From: John Graham-C. <jgr...@us...> - 2005-04-07 19:55:36
|
Update of /cvsroot/popfile/engine/Classifier In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv21537/Classifier Modified Files: Bayes.pm popfile.sql Log Message: More work on v0.23.0 (Multi-user Support) Add account association and allow different users to log in. Users can be associated with specific accounts when POPFile is in multi-user mode. Currently every user has a blank password. Also cloning of per-bucket parameters is not working. Would love to have volunteers to do the following: 1. Test out the new functionality for account association 2. Write code to do per-bucket parameter cloning (see Bayes.pm TODO) 3. Write code to set/reset user passwords. --- Classifer/Bayes.pm: Add functions for handling account creation and deletion and mapping of accounts to users. Add new message called CREAT used to pass a child generated session to the parent. Proxy/Proxy.pm Proxy/POP3.pm: Add code for handling users associated with accounts and use it in the POP3 module to lookup users dynamically when they are logged in. UI/HTML.pm: Update UI to be able to handle different users using the cookie and changes to the History API. Add code to the users_page to handle account association on a per user basis. UI/HTTP.pm: Add url_decode_ and decode form parameters. POPFile/MQ.pm: Comment the CREAT message. POPFile/History.pm: Make history mechanism aware of different users so that different users get a different view of the history. skins/default/user_page.thtml: Add code for handling account association. languages/English.msg: Additional strings needed for the account handling. --- Once this is all working we can start to fix the test suite and nail down the v0.23.0 release. Index: Bayes.pm =================================================================== RCS file: /cvsroot/popfile/engine/Classifier/Bayes.pm,v retrieving revision 1.343 retrieving revision 1.344 diff -C2 -d -r1.343 -r1.344 *** Bayes.pm 24 Feb 2005 01:39:15 -0000 1.343 --- Bayes.pm 7 Apr 2005 19:54:41 -0000 1.344 *************** *** 9,13 **** # Bayes.pm --- Naive Bayes text classifier # ! # Copyright (c) 2001-2004 John Graham-Cumming # # This file is part of POPFile --- 9,13 ---- # Bayes.pm --- Naive Bayes text classifier # ! # Copyright (c) 2001-2005 John Graham-Cumming # # This file is part of POPFile *************** *** 104,107 **** --- 104,108 ---- $self->{db_delete_zero_words__} = 0; $self->{db_get_user_list__} = 0; + $self->{db_get_user_from_account__} = 0; # Caches the name of each bucket and relates it to both the bucket *************** *** 225,228 **** --- 226,230 ---- $self->mq_register_( 'COMIT', $self ); $self->mq_register_( 'RELSE', $self ); + $self->mq_register_( 'CREAT', $self ); $self->mq_register_( 'TICKD', $self ); *************** *** 253,256 **** --- 255,265 ---- } + if ( $type eq 'CREAT' ) { + my ( $session, $user ) = ( $message[0], $message[1] ); + $self->{api_sessions__}{$session} = $user; + $self->db_update_cache__( $session ); + $self->log_( 1, "CREAT message on $session for $user" ); + } + if ( $type eq 'TICKD' ) { $self->cleanup_orphan_words__(); *************** *** 702,705 **** --- 711,717 ---- 'select id, name from users order by name;' ); + $self->{db_get_user_from_account__} = $self->db_()->prepare( + 'select userid from accounts where account = ?' ); + # Get the mapping from parameter names to ids into a local hash *************** *** 752,755 **** --- 764,768 ---- $self->{db_delete_zero_words__}->finish; $self->{db_get_user_list__}->finish; + $self->{db_get_user_from_account__}->finish; } *************** *** 895,899 **** # assuming that the user name is admin with password '' ! my $session = $self->get_session_key( 'admin', '' ); if ( !defined( $session ) ) { --- 908,912 ---- # assuming that the user name is admin with password '' ! my $session = $self->get_administrator_session_key(); if ( !defined( $session ) ) { *************** *** 1446,1450 **** my $random = Crypt::Random::makerandom_octet( Length => 128, Strength => 1 ); my $now = time; ! return sha256_hex( "$random$now" ); } --- 1459,1463 ---- my $random = Crypt::Random::makerandom_octet( Length => 128, Strength => 1 ); my $now = time; ! return sha256_hex( "$$" . "$random$now" ); } *************** *** 1570,1574 **** #---------------------------------------------------------------------------- # ! # release_sessionss_key # # $session A session key previously returned by get_session_key --- 1583,1603 ---- #---------------------------------------------------------------------------- # ! # get_user_id_from_session ! # ! # $session A session key previously returned by get_session_key ! # ! # Returns the user ID associated with a session ! # ! #---------------------------------------------------------------------------- ! sub get_user_id_from_session ! { ! my ( $self, $session ) = @_; ! ! return $self->valid_session_key__( $session ); ! } ! ! #---------------------------------------------------------------------------- ! # ! # release_sessions_key # # $session A session key previously returned by get_session_key *************** *** 1586,1589 **** --- 1615,1701 ---- } + #---------------------------------------------------------------------------- + # + # get_administrator_session_key + # + # Returns a string based session key for the administrator. WARNING + # this is not for external use. This function bypasses all + # authentication checks and gives admin access. Should only be called + # in the top-level POPFile process. + # + #---------------------------------------------------------------------------- + sub get_administrator_session_key + { + my ( $self ) = @_; + + my $session = $self->generate_unique_session_key__(); + $self->{api_sessions__}{$session} = 1; + $self->db_update_cache__( $session ); + $self->log_( 1, "get_administrator_session_key returning key $session" ); + return $session; + } + + #---------------------------------------------------------------------------- + # + # get_session_key_from_token + # + # Gets a session key from a account token + # + # $session Valid administrator session + # $module Name of the module that is passing the token + # $token The token (usually an account name) + # + # Returns undef on failure or a session key + # + #---------------------------------------------------------------------------- + + sub get_session_key_from_token + { + my ( $self, $session, $module, $token ) = @_; + + # Verify that the user has an administrator session set up + + if ( $self->get_user_parameter( $session, 'GLOBAL_can_admin' ) != 1 ) { + return undef; + } + + # If we are in single user mode then simply return the + # administrator session for compatibility with old versions of + # POPFile. + + if ( $self->global_config_( 'single_user' ) == 1 ) { + return $session; + } + + # If the this is not the pop3 module then return the administrator + # session since there is currently no token matching for non-POP3 + # accounts. + + if ( $module ne 'pop3' ) { + return $session; + } + + # Check the token against the associations in the database and + # figure out which user is being talked about + + my $result = $self->{db_get_user_from_account__}->execute( "$module:$token" ); + if ( !defined( $result ) ) { + $self->log_( 1, "Unknown account $module:$token" ); + return undef; + } + my $user = $self->{db_get_user_from_account__}->fetchrow_arrayref->[0]; + + my $user_session = $self->generate_unique_session_key__(); + $self->{api_sessions__}{$user_session} = $user; + $self->db_update_cache__( $user_session ); + $self->log_( 1, "get_session_key_from_token returning key $user_session for user $self->{api_sessions__}{$user_session}" ); + + # Send the session to the parent so that it is recorded and can + # be correctly shutdown + + $self->mq_post_( 'CREAT', $user_session, $user ); + + return $user_session; + } #---------------------------------------------------------------------------- *************** *** 2592,2595 **** --- 2704,2813 ---- #---------------------------------------------------------------------------- # + # get_accounts (ADMIN ONLY) + # + # Returns a list of accounts associatd with the passed in user ID. This + # function is ADMIN ONLY. + # + # $session A valid session key returned by a call to get_session_key + # $id A user id + # + #---------------------------------------------------------------------------- + sub get_accounts + { + my ( $self, $session, $id ) = @_; + + # Check that this user is an administrator + + my $can_admin = $self->get_user_parameter( $session, 'GLOBAL_can_admin' ); + + if ( $can_admin != 1 ) { + return undef; + } + + # If user is an admin then grab the accounts for the user requested + + my $h = $self->db_()->prepare( "select account from accounts where userid = $id;" ); + $h->execute; + my @accounts; + while ( my $row = $h->fetchrow_arrayref ) { + push ( @accounts, $row->[0] ); + } + $h->finish; + + return @accounts; + } + + #---------------------------------------------------------------------------- + # + # add_account (ADMIN ONLY) + # + # Add an account associated with a user + # + # $session A valid session key returned by a call to get_session_key + # $id A user id + # $module The module adding the account + # $account The account to add + # + #---------------------------------------------------------------------------- + sub add_account + { + my ( $self, $session, $id, $module, $account ) = @_; + + # Check that this user is an administrator + + my $can_admin = $self->get_user_parameter( $session, 'GLOBAL_can_admin' ); + + if ( $can_admin != 1 ) { + return 0; + } + + # User is admin so try to insert the new account after checking to see + # if someone already has this account + + my $result = $self->{db_get_user_from_account__}->execute( "$module:$account" ); + if ( !defined( $result ) ) { + return 0; + } + if ( defined( $self->{db_get_user_from_account__}->fetchrow_arrayref ) ) { + return -1; + } + + $account = $self->db_()->quote( "$module:$account" ); + my $h = $self->db_()->prepare( "insert into accounts ( userid, account ) values ( $id, $account );" ); + if ( !defined( $h->execute ) ) { + return 0; + } + + return 1; + } + + #---------------------------------------------------------------------------- + # + # remove_account (ADMIN ONLY) + # + # Remove an account associated with a user + # + # $session A valid session key returned by a call to get_session_key + # $module The module removing the account + # $account The account to remove + # + #---------------------------------------------------------------------------- + sub remove_account + { + my ( $self, $session, $module, $account ) = @_; + + # Check that this user is an administrator + + my $can_admin = $self->get_user_parameter( $session, 'GLOBAL_can_admin' ); + + if ( $can_admin != 1 ) { + return 0; + } + + return $self->db_()->do( "delete from accounts where account = '$module:$account';" ); + } + + #---------------------------------------------------------------------------- + # # get_buckets # *************** *** 3064,3068 **** } ! $self->db_()->do( "insert into users ( name ) values ( '$new_user' );" ); my $id = $self->get_user_id( $session, $new_user ); --- 3282,3288 ---- } ! my $password = md5_hex( $new_user . '__popfile__' ); ! ! $self->db_()->do( "insert into users ( name, password ) values ( '$new_user', '$password' );" ); my $id = $self->get_user_id( $session, $new_user ); *************** *** 3090,3093 **** --- 3310,3331 ---- $self->db_()->do( "insert into user_params ( userid, utid, val ) values ( $id, $utid, '$add{$utid}' );" ); } + + # Clone buckets + + $h = $self->db_()->prepare( "select name, pseudo from buckets where userid = $clid;" ); + $h->execute; + my %buckets; + while ( my $row = $h->fetchrow_arrayref ) { + $buckets{$row->[0]} = $row->[1]; + } + $h->finish; + foreach my $name (keys %buckets) { + $self->db_()->do( "insert into buckets ( userid, name, pseudo ) values ( $id, '$name', $buckets{$name} );" ); + } + + # TODO clone bucket parameters + + # TODO assign a password + } Index: popfile.sql =================================================================== RCS file: /cvsroot/popfile/engine/Classifier/popfile.sql,v retrieving revision 1.24 retrieving revision 1.25 diff -C2 -d -r1.24 -r1.25 *** popfile.sql 26 Jan 2005 11:50:56 -0000 1.24 --- popfile.sql 7 Apr 2005 19:54:44 -0000 1.25 *************** *** 1,3 **** ! -- POPFILE SCHEMA 6 -- --------------------------------------------------------------------------- -- --- 1,3 ---- ! -- POPFILE SCHEMA 7 -- --------------------------------------------------------------------------- -- *************** *** 27,54 **** -- from there) -- ! -- +---------------+ +-----------------+ ! -- | user_template | | bucket_template | ! -- +---------------+ +-----------------+ ! -- | id |-----+ | id |---+ ! -- | name | | | name | | ! -- | def | | | def | | ! -- | form | | +-----------------+ | ! -- +---------------+ | | ! -- | | ! -- +---------------+ | +---------------+ | ! -- | user_params | | | bucket_params | | ! -- +---------------+ | +---------------+ | ! -- | id | | | id | | ! -- +---| userid | | +---| bucketid | | ! -- | | utid |-----+ | | btid |---+ ! -- | | val | | | val | ! -- | +---------------+ | +---------------+ ! -- | | +----------+ ! -- | | | matrix | +-------+ ! -- | | +---------+ +----------+ | words | ! -- | +----------+ | | buckets | | id | +-------+ ! -- | | users | | +---------+ | wordid |---| id | ! -- | +----------+ /--+---| id |=====---| bucketid | | word | ! -- +----==| id |-----(-------| userid | \ | times | +-------+ -- / | name | | | name | | | lastseen | -- | | password | | | pseudo | | +----------+ --- 27,55 ---- -- from there) -- ! -- +---------------+ +-----------------+ ! -- | user_template | | bucket_template | ! -- +---------------+ +-----------------+ ! -- | id |-----\ | id |---\ ! -- | name | | | name | | ! -- | def | | | def | | ! -- | form | | +----------+ +-----------------+ | ! -- +---------------+ | | accounts | | ! -- | +----------+ | ! -- +---------------+ | | id | +---------------+ | ! -- | user_params | | | userid |-\ | bucket_params | | ! -- +---------------+ | | account | | +---------------+ | ! -- | id | | +----------+ | | id | | ! -- /---| userid | | | /---| bucketid | | ! -- | | utid |-----/ | | | btid |-----/ ! -- | | val | | | | val | ! -- | +---------------+ /-------------------/ | +---------------+ ! -- | | | ! -- | | /-----------------/ +----------+ ! -- | | | | matrix | +-------+ ! -- | | | +---------+ +----------+ | words | ! -- | +----------+ | | | buckets | | id | +-------+ ! -- | | users | | | +---------+ | wordid |---| id | ! -- | +----------+ | /--+---| id |=====---| bucketid | | word | ! -- \----==| id |---+-(-------| userid | \ | times | +-------+ -- / | name | | | name | | | lastseen | -- | | password | | | pseudo | | +----------+ *************** *** 58,65 **** -- | | | magnets | | -- | +------------+ | +-----------+ | +--------------+ ! -- | | history | | +--| id | | | magnet_types | ! -- | +------------+ | | | bucketid |--+ +--------------+ -- | | id | | | | mtid |--------| id | ! -- +---| userid | | | | val | | mtype | -- | hdr_from | | | | seq | | header | -- | hdr_to | | | +-----------+ +--------------+ --- 59,66 ---- -- | | | magnets | | -- | +------------+ | +-----------+ | +--------------+ ! -- | | history | | /--| id | | | magnet_types | ! -- | +------------+ | | | bucketid |--/ +--------------+ -- | | id | | | | mtid |--------| id | ! -- \---| userid | | | | val | | mtype | -- | hdr_from | | | | seq | | header | -- | hdr_to | | | +-----------+ +--------------+ *************** *** 68,72 **** -- | bucketid |--+ | -- | usedtobe |--/ | ! -- | magnetid |--------+ -- | hdr_date | -- | inserted | --- 69,73 ---- -- | bucketid |--+ | -- | usedtobe |--/ | ! -- | magnetid |--------/ -- | hdr_date | -- | inserted | *************** *** 159,163 **** lastseen date, -- last time the record was read -- or written ! unique (wordid, bucketid) -- each word appears once in a bucket ); --- 160,165 ---- lastseen date, -- last time the record was read -- or written ! unique (wordid, bucketid) -- each word appears once in a ! -- bucket ); *************** *** 223,226 **** --- 225,244 ---- -- --------------------------------------------------------------------------- -- + -- accounts - the table of accounts (e.g. pop3:host:user) associated with + -- each user that is used by POPFile's multi-user mode + -- + -- --------------------------------------------------------------------------- + + create table accounts( id integer primary key, -- unique ID for this + -- entry + userid integer, -- User associated with + -- this account + account varchar(255), -- Account token + unique (account) -- Each account appears + -- once + ); + + -- --------------------------------------------------------------------------- + -- -- bucket_params - the table that relates buckets with bucket parameters -- (as defined in bucket_template) and specific values. *************** *** 549,554 **** insert into user_template ( name, def, form ) values ( 'html_show_configbars', 1, '%d' ); - - -- The adminisrator (user 1) can_admin --- 567,570 ---- |