User talk:Caveman

From AOLserver Wiki
Jump to navigation Jump to search

Hi, and welcome to the wiki! If you don't mind me asking, what's your full name (or do you want to remain anonymous)? Are you also subscribed to the AOLSERVER mailing list? Some of us also hang out on IRC and chat (you can also access the chat via AIM, but most folks use IRC).

If you have any questions or concerns, don't hesitate to contact me. Thanks! -- Dossy 07:13, 3 December 2005 (EST)


Why does it seem like you're avoiding Tcl? Your recent wiki edits have been focused around other languages in AOLserver other than Tcl, like Lua, PHP and Ruby. Why? You will really never get the kind of performance out of Perl, PHP or Ruby as you will Tcl, because Tcl is suitable for embedding in a multi-threaded application where Perl, PHP and Ruby aren't. (I don't know enough about Lua to say one way or the other.) So, if you still want to use those other languages, then you probably don't care about performance at the high end, in which case, you probably don't need to use AOLserver, either. In the small, any web server will be more than adequate on modern hardware to serve a few hundred pages here and there. It's when you start getting into the few hundred per second arena where AOLserver has the opportunity to shine. -- Dossy 07:46, 10 December 2005 (EST)

  • Not at all -- I'm looking at other languages simply from the point of view of seeing how AOLServer modules are built at all. It has been a while since I did any heavy lifting with C, and I felt that tinkering with the module code would be a good refresher. Just scratching an itch. I use TCL heavily every day at work, and have no real knowledge of Lua either, it just seemed an opportune target to use when examining the general AOLServer module layer. --Caveman 12:23, 12 December 2005 (EST)
    • Okay, cool. FYI, "AOLserver" is capitalized just like that, not "AOLServer" -- I'm picking nits, but the consistency is important to me. Thanks. :-) -- Dossy 12:41, 12 December 2005 (EST)
      • Ack. I've been doing that on a ton of pages -- my mistake, I will try to use the correct capitalisation. --Caveman 12:43, 12 December 2005 (EST)

towards a data and authentication layer

It is possible that similar exists elsewhere (non-OpenACS) but I enjoy framework construction anyway. Services provided:

  1. authentication (password check)
  2. sequences
  3. data layer

Authentication/Authorization config (nsz):

# config: "/security/password/expression"
# {ns_sha1 [ns_md5 [lindex $args 0]] [lindex $args 1]}
# config: "/security/password/query"
# {select password, salt from users where name='[ns_dbquoteval [lindex $args 0]]'}
# config: "/security/salt/length" "8"
# config: "/security/salt/dictionary" "0123456789abcdefghijkl..."

Basically the "expression" is used in a function, nsz_password to format a given clear-text password (varargs "args" to allow additional arguments to the function). The first argument is always the password.

The "query" is executed as part of password-based authentication. The form handler reaches nsz_auth "myname" "mypassword" and the query is executed using the input list "myname". All row data beyond the first column, which must always be the password, is appended to the input password "mypassword" to produce the hash/salted/hash input "xpassword". This input "xpassword" is compared with the result of the returned value for the first column from the database query. If there is a match, password authentication succeeds for the user.

Examples:

nsz_auth "sam" "correctpassword"
# Query returns "sadf8vcx8vxasd7f7...","asduf7z6dfa..."
# Expression eval for input passes "correctpassword","asduf7z6dfa..." and returns "sadf8vcx8vxasd7f7..."
# Return value matches query
# nsz_auth returns "sam"

nsz_auth "sam" "badpassword"
# Query returns "sadf8vcx8vxasd7f7...","asduf7z6dfa..."
# Expression eval for input passes "badpassword","asduf7z6dfa..." and returns "yyzkfosd232cx7c..."
# Return value does not match query
# nsz_auth raises error "bad password"

Different configurations could use simple clear-text passwords, no salt, etc, simply by changing their configuration:

# config: "nsz/security/password/expression"
# {lindex $args 0}
# config: "nsz/security/password/query"
# {select password from users where name='[ns_dbquoteval [lindex $args 0]]'}

The above would be the default configuration. For salt, the default would be size of 8 and dictionary of alphanumerics.

Function nsz_salt can take 0, 1, or 2 arguments and returns the generated salt. The first argument is the length of the salt, defaults to config value. The second argument is the dictionary for the salt, default to config value.

Question: How to make "users" table configurable? What about configuring which database pool to use? What about multiple authentication realms?


Sequences configuration should be as simple as specifying the database pool to use (default by default), the name of the sequence table, the size of the sequence chunk to claim when the local cache runs out of sequence numbers, and the number of retries before error during chunk claim. It could however be more complex, to specify the column names for the "name" and "value" of the sequence.

Config:

# config: "nso/sequence/default/poolname" (default by default)
# config: "nso/sequence/default/size" "100"
# config: "nso/sequence/default/retry" "5"
# config: "nso/sequence/default/table" "sequences_table"
# config: "nso/sequence/default/name" "name_field"
# config: "nso/sequence/default/value" "value_field"

Sequence defaults could be over-written per-sequence in similar fashion.

Example usage:

set nextId [nso_sequence next "my_seq_name"]
# returns 53 or error if fail

The function nso_sequence would thread-safe return the next sequence number it had available in its local nsv data, or if not available, claim the next chunk of 100 sequences numbers from the database:

# select value_field from sequences_table where name_field='my_seq_name'
# result is 125, attempt to claim 100 values
# update cave_sequences set value=225 where name_field='my_seq_name' and value_field=125

This would be retried up to 5 times.


Data layer notes:

Config would map names like "users" to database pools and table names. Default would be default database pool and identity table name.

Example usage:

# set nssValues [ns_set create]
# ns_set update $nssValues "name" "sam"
# ns_set update $nssValues "password" "mypassword"
# ns_set put $nssValues "mail" "sam@caveman.org"
# set nssUserKey [nso_row create "users" $nssValues]
# set nssNewValues [ns_set create]
# ns_set put $nssNewValues "mail" "samuelmb@gmail.com"
# nso_row update "users" $nssUserKey $nssNewValues

Using ns_set instead of a model type-checking "nso_set" at least for now for simplicity and it would be the simple case.

Additional config allows for data transforms:

# multi stage of filters and expressions:
#
# stage 0: accept-data-filter
#   e.g. "require a password is not null"
#   e.g. "require this integer be above zero"
#   e.g. "require id not be set"
#
# stage 1: transform-data-filter
# config: expressions to apply to row:
#   e.g. "generate a salt"
#     ns_set update $nssData "salt" [nsz_salt]
#   e.g. "transform the password"
#     ns_set update $nssData "password" [nsz_password [ns_set get $nssData "password"] [ns_set get $nssData "salt"]]
#   e.g. "generate the next id from sequence"
#     ns_set update $nssData "id" [nso_sequence next "my_seq_name"]
#
# stage 2: veto-data-filter?
#
# allow multiple "inheritance" of data rules? or just defining rules that
# can be referenced by multiple tables?

very draft state

useful links

philip.greenspun.com/doc/ philip.greenspun.com/doc/data-pipeline