[Jifty-commit] r956 - in jifty/trunk: . lib lib/Jifty
lib/Jifty/Test/WWW lib/Jifty/Web
jifty-commit at lists.jifty.org
jifty-commit at lists.jifty.org
Fri Apr 28 15:50:00 EDT 2006
Author: alexmv
Date: Fri Apr 28 15:49:59 2006
New Revision: 956
Modified:
jifty/trunk/ (props changed)
jifty/trunk/lib/Jifty.pm
jifty/trunk/lib/Jifty/Everything.pm
jifty/trunk/lib/Jifty/Model/Session.pm
jifty/trunk/lib/Jifty/Test/WWW/Mechanize.pm
jifty/trunk/lib/Jifty/Web/Session.pm
Log:
r12683 at zoq-fot-pik: chmrr | 2006-04-28 15:49:31 -0400
* Sessions stored in the database
Modified: jifty/trunk/lib/Jifty.pm
==============================================================================
--- jifty/trunk/lib/Jifty.pm (original)
+++ jifty/trunk/lib/Jifty.pm Fri Apr 28 15:49:59 2006
@@ -5,7 +5,7 @@
use encoding 'utf8';
# Work around the fact that Time::Local caches thing on first require
BEGIN { local $ENV{'TZ'} = "GMT"; require Time::Local;}
-our $VERSION = '0.60427';
+our $VERSION = '0.60428';
=head1 NAME
Modified: jifty/trunk/lib/Jifty/Everything.pm
==============================================================================
--- jifty/trunk/lib/Jifty/Everything.pm (original)
+++ jifty/trunk/lib/Jifty/Everything.pm Fri Apr 28 15:49:59 2006
@@ -38,6 +38,7 @@
use Jifty::View::Mason::Handler ();
use Jifty::Model::Metadata ();
+use Jifty::Model::Session ();
use Jifty::Request ();
Modified: jifty/trunk/lib/Jifty/Model/Session.pm
==============================================================================
--- jifty/trunk/lib/Jifty/Model/Session.pm (original)
+++ jifty/trunk/lib/Jifty/Model/Session.pm Fri Apr 28 15:49:59 2006
@@ -1,2 +1,91 @@
-package Jifty::Model::Session;
-"TRUE, THIS IS A STUB FILE. SORRY";
+use warnings;
+use strict;
+
+=head1 NAME
+
+Jifty::Model::Session - Jifty session tracking
+
+=head1 DESCRIPTION
+
+Every Jifty application automatically inherits this table, which
+tracks session information for the application. Individual keys in
+the session structure are stored as rows, making session updates take
+constant time, and also reducing the need for locking.
+
+=cut
+
+package Jifty::Model::Session::Schema;
+use Jifty::DBI::Schema;
+
+column session_id => type is 'varchar(32)';
+column key => type is 'text';
+column value => type is 'blob',
+ filters are 'Jifty::DBI::Filter::Storable';
+column created => type is 'timestamp',
+ filters are 'Jifty::DBI::Filter::DateTime';
+column updated => type is 'timestamp',
+ filters are 'Jifty::DBI::Filter::DateTime';
+column key_type => type is 'varchar(32)';
+
+package Jifty::Model::Session;
+
+use base qw( Jifty::Record );
+use DateTime;
+
+=head2 table
+
+Sessions are stored in the table C<_jifty_sessions>.
+
+=cut
+
+sub table {'_jifty_sessions'}
+sub since { '0.60428' }
+sub current_user { return Jifty::CurrentUser->superuser }
+
+=head2 new_session_id
+
+Returns a random new session id. This is a 32-character hex string.
+
+=cut
+
+sub new_session_id {
+ return Digest::MD5::md5_hex(
+ Digest::MD5::md5_hex( time() . {} . rand() . $$ ) );
+}
+
+=head2 create
+
+Defaults the created and updated times to now.
+
+=cut
+
+sub create {
+ my $self = shift;
+ my %args = (
+ session_id => $self->new_session_id,
+ key_type => "key",
+ created => DateTime->now,
+ updated => DateTime->now,
+ @_,
+ );
+
+ return $self->SUPER::create(%args);
+}
+
+=head2 set_value [VALUE]
+
+Updates the C<updated> column, in addition to setting the value.
+
+=cut
+
+sub set_value {
+ my $self = shift;
+ my $value = shift;
+
+ return undef unless $self->id;
+
+ $self->set_updated( DateTime->now );
+ $self->_set( column => 'value', value => $value );
+}
+
+1;
Modified: jifty/trunk/lib/Jifty/Test/WWW/Mechanize.pm
==============================================================================
--- jifty/trunk/lib/Jifty/Test/WWW/Mechanize.pm (original)
+++ jifty/trunk/lib/Jifty/Test/WWW/Mechanize.pm Fri Apr 28 15:49:59 2006
@@ -13,13 +13,15 @@
=head1 NAME
-Jifty::Test::WWW::Mechanize - Subclass of L<Test::WWW::Mechanize> with extra Jifty features
+Jifty::Test::WWW::Mechanize - Subclass of L<Test::WWW::Mechanize> with
+extra Jifty features
=head1 METHODS
=head2 new
-Overrides L<Test::WWW::Mechanize>'s C<new> to automatically give the bot a cookie jar.
+Overrides L<Test::WWW::Mechanize>'s C<new> to automatically give the
+bot a cookie jar.
=cut
@@ -32,8 +34,8 @@
=head2 moniker_for ACTION, FIELD1 => VALUE1, FIELD2 => VALUE2
-Finds the moniker of the first action of type I<ACTION> whose "constructor"
-field I<FIELD1> is I<VALUE1>, and so on.
+Finds the moniker of the first action of type I<ACTION> whose
+"constructor" field I<FIELD1> is I<VALUE1>, and so on.
=cut
@@ -63,9 +65,10 @@
=head2 fill_in_action MONIKER, FIELD1 => VALUE1, FIELD2 => VALUE2, ...
-Finds the fields on the current page with the names FIELD1, FIELD2, etc in the MONIKER
-action, and fills them in. Returns the L<HTML::Form> object of the form
-that the action is in, or undef if it can't find all the fields.
+Finds the fields on the current page with the names FIELD1, FIELD2,
+etc in the MONIKER action, and fills them in. Returns the
+L<HTML::Form> object of the form that the action is in, or undef if it
+can't find all the fields.
=cut
@@ -90,11 +93,13 @@
=head2 fill_in_action_ok MONIKER, FIELD1 => VALUE1, FIELD2 => VALUE2, ...
-Finds the fields on the current page with the names FIELD1, FIELD2, etc in the MONIKER
-action, and fills them in. Returns the L<HTML::Form> object of the form
-that the action is in, or undef if it can't find all the fields.
+Finds the fields on the current page with the names FIELD1, FIELD2,
+etc in the MONIKER action, and fills them in. Returns the
+L<HTML::Form> object of the form that the action is in, or undef if it
+can't find all the fields.
-Also, passes if it finds all of the fields and fails if any of the fields are missing.
+Also, passes if it finds all of the fields and fails if any of the
+fields are missing.
=cut
@@ -135,8 +140,8 @@
=head2 action_field_value MONIKER, FIELD
-Finds the fields on the current page with the names FIELD in the action
-MONIKER, and returns its value, or undef if it can't be found.
+Finds the fields on the current page with the names FIELD in the
+action MONIKER, and returns its value, or undef if it can't be found.
=cut
@@ -153,14 +158,6 @@
return $input->value;
}
-=head2 field_error_text MONIKER, FIELD
-
-Finds the error span on the current page for the name FIELD in the action
-MONIKER, and returns the text (tags stripped) from it. (If the field can't be
-found.
-
-=cut
-
# When it sees something like
# http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd as a DOCTYPE, this will make
# it open static/dtd/xhtml1-strict.dtd instead -- great for offline hacking!
@@ -180,6 +177,14 @@
$_[-1] = 1; # just return please
};
+=head2 field_error_text MONIKER, FIELD
+
+Finds the error span on the current page for the name FIELD in the
+action MONIKER, and returns the text (tags stripped) from it. (If the
+field can't be found.
+
+=cut
+
sub field_error_text {
my $self = shift;
my $moniker = shift;
@@ -199,8 +204,9 @@
=head2 uri
-L<WWW::Mechanize> has a bug where it returns the wrong value for C<uri> after
-redirect. This fixes that. See http://rt.cpan.org/NoAuth/Bug.html?id=9059
+L<WWW::Mechanize> has a bug where it returns the wrong value for
+C<uri> after redirect. This fixes that. See
+http://rt.cpan.org/NoAuth/Bug.html?id=9059
=cut
@@ -208,7 +214,8 @@
=head2 get_html_ok URL
-Calls C<get> URL, followed by testing the HTML using L<Test::HTML::Lint>.
+Calls C<get> URL, followed by testing the HTML using
+L<Test::HTML::Lint>.
=cut
@@ -222,7 +229,8 @@
=head2 submit_html_ok
-Calls C<submit>, followed by testing the HTML using L<Test::HTML::Lint>.
+Calls C<submit>, followed by testing the HTML using
+L<Test::HTML::Lint>.
=cut
@@ -269,7 +277,6 @@
my $session = Jifty::Web::Session->new;
$session->load($1);
- $session->_session->release_all_locks();
return $session;
}
Modified: jifty/trunk/lib/Jifty/Web/Session.pm
==============================================================================
--- jifty/trunk/lib/Jifty/Web/Session.pm (original)
+++ jifty/trunk/lib/Jifty/Web/Session.pm Fri Apr 28 15:49:59 2006
@@ -2,231 +2,239 @@
use strict;
package Jifty::Web::Session;
-use base qw/Jifty::Object Class::Accessor::Fast/;
+use base qw/Jifty::Object/;
use CGI::Cookie;
-
-# We don't use Class::Accessor::Fast as we want to do our own 'set' and 'get' here
-#__PACKAGE__->mk_accessors(qw(_session));
+use DateTime;
=head1 NAME
Jifty::Web::Session - A Jifty session handler
-=head1 DESCRIPTION
-
-* Jifty sessions
-
-* User gets a per-app session cookie in their first response from the server
-* User gets an updated cookie on any request where:
- 1) if the cookie parameters have changed
- 2) if the user's current sessionid doesn't match the cookie's session id
+=cut
-* The session cookie is handed out after all processing, but before any page
- content is displayed
+=head1 new
-* The user gets a cookie even if we're doing a redirect.
+Returns a new, empty session.
-* In the future, we might want to not give the user a cookie.
+=cut
+sub new {
+ my $class = shift;
+ return bless {}, $class;
+}
+=head2 id
-* Debugging
+Returns the session's id if it has been loaded, or C<undef> otherwise.
-** Should log:
- * User presented a session cookie
- * Loaded session from disk
- * Failed to load session from disk (expired)
- * Created a new session
- * Sent a session cookie to the user.
+=cut
+sub id {
+ my $self = shift;
+ return $self->loaded ? $self->_session->session_id : undef;
+}
-=head2 load
+=head2 load [ID]
-Load up the current session from a cookie
+Load up the current session from the given C<ID>, or the appropriate
+cookie (see L</cookie_name>) otherwise. If both of those fail,
+creates a session in the database.
=cut
-
sub load {
- my $self = shift;
+ my $self = shift;
my $session_id = shift;
- require Apache::Session::File;
-
unless ($session_id) {
my %cookies = CGI::Cookie->fetch();
my $cookiename = $self->cookie_name;
- $session_id = $cookies{$cookiename} ? $cookies{$cookiename}->value() : undef;
+ $session_id
+ = $cookies{$cookiename} ? $cookies{$cookiename}->value() : undef;
}
- $Storable::Deparse = 1;
- $Storable::Eval = 1;
- my %session;
-
- my $session_dir = Jifty::Util->absolute_path( Jifty->config->framework('Web')->{'SessionDir'} );
-
- eval {
- tie %session, 'Apache::Session::File', ( $session_id ? $session_id : undef ),
- {
- Directory => $session_dir,
- LockDirectory => $session_dir,
- };
-
- };
- if ($@) {
- tie %session, 'Apache::Session::File', undef,
- {
- Directory => $session_dir,
- LockDirectory => $session_dir,
- };
- }
+ my $session = Jifty::Model::Session->new;
+ $session->load_by_cols(
+ session_id => $session_id,
+ key_type => "session"
+ )
+ if $session_id;
- $self->_session( tied(%session) );
- $session{_session_id} = $session{_session_id} || $session_id;
+ $session->create( key_type => "session" ) unless $session->id;
+ $self->_session($session);
}
=head2 unload
-Flush the session to disk and quit.
+Flush the session, and leaves the session object blank.
=cut
sub unload {
my $self = shift;
- return unless($self->_session);
- $self->_session->save();
- $self->_session->{object_store}->close;
- $self->_session->release_all_locks();
+ return unless $self->loaded;
$self->_session(undef);
}
=head2 loaded
-Returns true if the session has already been loaded
+Returns true if the session has already been loaded.
=cut
sub loaded {
my $self = shift;
- return $self->_session && $self->get('_session_id');
+ return $self->_session;
}
sub _session {
my $self = shift;
$self->{'_session'} = shift if (@_);
- return ($self->{'_session'});
+ return ( $self->{'_session'} );
}
-=head2 get KEY
+=head2 get KEY [TYPE]
-Returns the value for C<KEY> for the current user's session
+Returns the value for C<KEY> for the current user's session. C<TYPE>,
+which defaults to "key", allows accessing of other namespaces in the
+session, including "metadata" and "continuation".
=cut
sub get {
- my $self = shift;
- my $key = shift;
- return($self->_session ? $self->_session->FETCH($key) : undef);
-
+ my $self = shift;
+ my $key = shift;
+ my $key_type = shift || "key";
+
+ return undef unless $self->loaded;
+
+ my $setting = Jifty::Model::Session->new;
+ $setting->load_by_cols(
+ session_id => $self->id,
+ key_type => $key_type,
+ key => $key
+ );
+ return $setting->value;
}
+=head2 set KEY => VALUE, [TYPE]
-=head2 set KEY => VALUE
-
-Sets the value C<VALUE> for C<KEY> for the current user's session
+Sets the value C<VALUE> for C<KEY> for the session. C<TYPE>, which
+defaults to "key", allows values to be set in other namespaces,
+including "metadata" and "continuation".
=cut
sub set {
- my $self = shift;
- my $key = shift;
- my $value = shift;
-
- ($self->_session ? $self->_session->STORE($key => $value) : undef);
-
+ my $self = shift;
+ my $key = shift;
+ my $value = shift;
+ my $key_type = shift || "key";
+
+ return undef unless $self->loaded;
+ $self->_session->set_updated( DateTime->now );
+
+ my $setting = Jifty::Model::Session->new;
+ $setting->load_by_cols(
+ session_id => $self->id,
+ key_type => $key_type,
+ key => $key
+ );
+ if ( $setting->id ) {
+ $setting->set_value($value);
+ } else {
+ $setting->create(
+ session_id => $self->id,
+ key_type => $key_type,
+ key => $key,
+ value => $value
+ );
+ }
}
+=head2 remove KEY, [TYPE]
-=head2 remove KEY
-
-Remove key C<KEY> from the cache.
+Remove key C<KEY> from the cache. C<TYPE> defaults to "key".
=cut
sub remove {
- my $self = shift;
- my $key = shift;
- $self->set($key => undef);
+ my $self = shift;
+ my $key = shift;
+ my $key_type = shift || "key";
+
+ return undef unless $self->loaded;
+ $self->_session->set_updated( DateTime->now );
+
+ my $setting = Jifty::Model::Session->new;
+ $setting->load_by_cols(
+ session_id => $self->id,
+ key_type => $key_type,
+ key => $key
+ );
+ $setting->delete if $setting->id;
}
+=head2 set_continuation ID CONT
-=head2 set_continuation KEY VALUE
-
-Stores a continuation in the session
+Stores a continuation in the session.
=cut
-
sub set_continuation {
my $self = shift;
- my $key = shift;
- my $val = shift;
-
- $self->set( '_continuation_'.$key => $val);
-
+ $self->set( @_, "continuation" );
}
+=head2 get_continuation ID
-
-=head2 get_continuation KEY
-
-Pulls a continuation from the current session. Expects a continuation id
+Pulls a continuation from the current session. Expects a continuation
+C<ID>.
=cut
-sub get_continuation {
+sub get_continuation {
my $self = shift;
- my $key = shift;
- $self->get('_continuation_'.$key);
+ $self->get( @_, "continuation" );
}
-=head2 remove_continuation CONTINUATION_ID
+=head2 remove_continuation ID
-Removes a continuation with id CONTINUATION id from the store.
+Removes a continuation with id C<ID> from the store.
=cut
sub remove_continuation {
my $self = shift;
- my $key = shift;
- $self->remove('_continuation_'.$key);
+ $self->remove( @_, "continuation" );
}
-
=head2 continuations
-Return a hash of all the continuations in this session. Keyed by continuation_C<id>.
+Return a hash of all the continuations in this session, keyed by the
+continuations' C<id>.
=cut
-
sub continuations {
my $self = shift;
- my %continuations;
- # XXX TODO: we're deeply abusing the API. that's uncool. We want to replace Apache::Session
- map { $continuations{$_} = $self->get($_) } grep { /^_continuation_/ } keys %{$self->_session->{'data'}};
- return %continuations;
-}
-
+ return () unless $self->loaded;
+ my $conts = Jifty::Model::SessionCollection->new;
+ $conts->limit( column => "key_type", value => "continuation" );
+ $conts->limit( column => "session_id", value => $self->id );
+ my %continuations;
+ $continuations{ $_->key } = $_->value while $_ = $conts->next;
+ return %continuations;
+}
=head2 set_cookie
-Sets the session cookie
+Sets the session cookie.
=cut
@@ -239,22 +247,23 @@
= $cookies{$cookie_name} ? $cookies{$cookie_name}->value() : undef;
my $cookie = new CGI::Cookie(
-name => $cookie_name,
- -value => $self->get('_session_id'),
- -expires => $self->get('_expires'),
+ -value => $self->id,
+ -expires => $self->expires,
);
# XXX TODO might need to change under mod_perl
if ( not $cookies{$cookie_name}
or ( $cookies{$cookie_name} ne $cookie->as_string ) )
{
- Jifty->web->response->add_header( 'Set-Cookie' => $cookie->as_string );
+ Jifty->web->response->add_header(
+ 'Set-Cookie' => $cookie->as_string );
}
}
-
=head2 cookie_name
-Returns the current session's cookie_name. (It's a generic thing for all users
+Returns the current session's cookie_name -- it is the same for all
+users, but various accorting to the port the server is running on.
=cut
@@ -262,25 +271,19 @@
my $self = shift;
my $cookiename = "JIFTY_SID_" . ( $ENV{'SERVER_PORT'} || 'NOPORT' );
return ($cookiename);
-
}
-=head2 expires
+=head2 expires [VALUE]
-Return this cache entry's expirey date, in the format expected by Cache::Cache;
+Get or set the session's expiration date, in a format expected by
+Cache::Cache.
=cut
-
sub expires {
- my $self = shift;
- if(@_) {
- my $expiry = shift;
- $self->set('_expires' => $expiry);
- }
- return ($self->get('_expires'));
+ my $self = shift;
+ $self->set( 'expires' => shift, "metadata" ) if @_;
+ return ( $self->get( 'expires', "metadata" ) );
}
-
-
1;
More information about the Jifty-commit
mailing list