[Jifty-commit] r1471 - in jifty/branches/plugin_rewrite: . lib/Jifty plugins/Login plugins/Login/lib plugins/Login/lib/Jifty plugins/Login/lib/Jifty/Plugin plugins/Login/lib/Jifty/Plugin/Login plugins/Login/lib/Jifty/Plugin/Login/Action plugins/Login/lib/Jifty/Plugin/Login/Model plugins/Login/lib/Jifty/Plugin/Login/Notification plugins/Login/share plugins/Login/share/web plugins/Login/share/web/templates/let share/web/static/js

jifty-commit at lists.jifty.org jifty-commit at lists.jifty.org
Tue Jul 4 10:11:51 EDT 2006


Author: jpeacock
Date: Tue Jul  4 10:11:38 2006
New Revision: 1471

Added:
   jifty/branches/plugin_rewrite/plugins/Login/
   jifty/branches/plugin_rewrite/plugins/Login/MANIFEST
   jifty/branches/plugin_rewrite/plugins/Login/Makefile.PL
   jifty/branches/plugin_rewrite/plugins/Login/lib/
   jifty/branches/plugin_rewrite/plugins/Login/lib/Jifty/
   jifty/branches/plugin_rewrite/plugins/Login/lib/Jifty/Plugin/
   jifty/branches/plugin_rewrite/plugins/Login/lib/Jifty/Plugin/Login/
   jifty/branches/plugin_rewrite/plugins/Login/lib/Jifty/Plugin/Login.pm
   jifty/branches/plugin_rewrite/plugins/Login/lib/Jifty/Plugin/Login/Action/
   jifty/branches/plugin_rewrite/plugins/Login/lib/Jifty/Plugin/Login/Action/ConfirmEmail.pm
   jifty/branches/plugin_rewrite/plugins/Login/lib/Jifty/Plugin/Login/Action/Login.pm
   jifty/branches/plugin_rewrite/plugins/Login/lib/Jifty/Plugin/Login/Action/Logout.pm
   jifty/branches/plugin_rewrite/plugins/Login/lib/Jifty/Plugin/Login/Action/RecoverPassword.pm
   jifty/branches/plugin_rewrite/plugins/Login/lib/Jifty/Plugin/Login/Action/ResetLostPassword.pm
   jifty/branches/plugin_rewrite/plugins/Login/lib/Jifty/Plugin/Login/Action/SendAccountConfirmation.pm
   jifty/branches/plugin_rewrite/plugins/Login/lib/Jifty/Plugin/Login/Action/SendPasswordReminder.pm
   jifty/branches/plugin_rewrite/plugins/Login/lib/Jifty/Plugin/Login/Action/Signup.pm
   jifty/branches/plugin_rewrite/plugins/Login/lib/Jifty/Plugin/Login/CurrentUser.pm
   jifty/branches/plugin_rewrite/plugins/Login/lib/Jifty/Plugin/Login/Dispatcher.pm
   jifty/branches/plugin_rewrite/plugins/Login/lib/Jifty/Plugin/Login/Model/
   jifty/branches/plugin_rewrite/plugins/Login/lib/Jifty/Plugin/Login/Model/User.pm
   jifty/branches/plugin_rewrite/plugins/Login/lib/Jifty/Plugin/Login/Notification/
   jifty/branches/plugin_rewrite/plugins/Login/lib/Jifty/Plugin/Login/Notification/ConfirmAddress.pm   (contents, props changed)
   jifty/branches/plugin_rewrite/plugins/Login/share/
   jifty/branches/plugin_rewrite/plugins/Login/share/web/
   jifty/branches/plugin_rewrite/plugins/Login/share/web/templates/
   jifty/branches/plugin_rewrite/plugins/Login/share/web/templates/let/
   jifty/branches/plugin_rewrite/plugins/Login/share/web/templates/let/confirm_email
   jifty/branches/plugin_rewrite/plugins/Login/share/web/templates/login
   jifty/branches/plugin_rewrite/plugins/Login/share/web/templates/logout
   jifty/branches/plugin_rewrite/plugins/Login/share/web/templates/signup
Modified:
   jifty/branches/plugin_rewrite/   (props changed)
   jifty/branches/plugin_rewrite/lib/Jifty/Action.pm
   jifty/branches/plugin_rewrite/lib/Jifty/Record.pm
   jifty/branches/plugin_rewrite/lib/Jifty/Web.pm
   jifty/branches/plugin_rewrite/share/web/static/js/calendar.js

Log:
Sync with trunk (to get the plugins/Login files)

Modified: jifty/branches/plugin_rewrite/lib/Jifty/Action.pm
==============================================================================
--- jifty/branches/plugin_rewrite/lib/Jifty/Action.pm	(original)
+++ jifty/branches/plugin_rewrite/lib/Jifty/Action.pm	Tue Jul  4 10:11:38 2006
@@ -737,7 +737,7 @@
     my $val = shift;
     return undef unless defined $val and $val =~ /\S/;
     return undef unless my $obj = Jifty::DateTime->new_from_string($val);
-    return $obj->ymd eq $val ? undef : $obj->ymd;
+    return $obj->ymd;
 }
 
 =head2 _validate_arguments

Modified: jifty/branches/plugin_rewrite/lib/Jifty/Record.pm
==============================================================================
--- jifty/branches/plugin_rewrite/lib/Jifty/Record.pm	(original)
+++ jifty/branches/plugin_rewrite/lib/Jifty/Record.pm	Tue Jul  4 10:11:38 2006
@@ -62,9 +62,10 @@
     }
 
     foreach my $key ( keys %attribs ) {
+        my $attr = $attribs{$key};
         my $method = "validate_$key";
-        next unless $self->can($method);
-        my ( $val, $msg ) = $self->$method( $attribs{$key} );
+        my $func = $self->can($method) or next;
+        my ( $val, $msg ) = $func->($self, $attr);
         unless ($val) {
             $self->log->error("There was a validation error for $key");
             return ( $val, $msg );
@@ -72,7 +73,7 @@
 
         # remove blank values. We'd rather have nulls
         if ( exists $attribs{$key}
-            and ( not defined $attribs{$key} or (not ref $attribs{$key} and $attribs{$key} eq "" )) )
+            and ( not defined $attr or (not ref $attr and $attr eq "" )) )
         {
             delete $attribs{$key};
         }

Modified: jifty/branches/plugin_rewrite/lib/Jifty/Web.pm
==============================================================================
--- jifty/branches/plugin_rewrite/lib/Jifty/Web.pm	(original)
+++ jifty/branches/plugin_rewrite/lib/Jifty/Web.pm	Tue Jul  4 10:11:38 2006
@@ -923,6 +923,31 @@
 
 Returns a C<< <script> >> tag for the compressed Javascript.
 
+Your application specific javascript goes in
+F<share/web/static/js/app.js>.  This will be automagically included if
+it exists.
+
+If you want to add javascript behaviour to your page using CSS
+selectors then put your behaviour rules in
+F<share/web/static/js/app_behaviour.js> which will also be
+automagically included if it exists.  The C<behaviour.js> library is
+included by Jifty.  For more information on C<behaviour.js> see
+L<http://bennolan.com/behaviour/>.
+
+However if you want to include other javascript libraries you need to
+add them to the javascript_libs array of your application.  Do this in
+the C<start> sub of your main application class.  For example if your application is Foo then in L<lib/Foo.pm>
+
+ sub start {
+   Jifty->web->javascript_libs([
+ 			       @{ Jifty->web->javascript_libs },
+ 			       "yourJavascriptLib.js",
+ 			      ]);
+ }
+
+Jifty will look for javascript libraries under share/web/static/js/ by
+default.
+
 =cut
 
 sub include_javascript {

Added: jifty/branches/plugin_rewrite/plugins/Login/MANIFEST
==============================================================================
--- (empty file)
+++ jifty/branches/plugin_rewrite/plugins/Login/MANIFEST	Tue Jul  4 10:11:38 2006
@@ -0,0 +1,29 @@
+inc/Module/Install.pm
+inc/Module/Install/Base.pm
+inc/Module/Install/Can.pm
+inc/Module/Install/Fetch.pm
+inc/Module/Install/Makefile.pm
+inc/Module/Install/Metadata.pm
+inc/Module/Install/Share.pm
+inc/Module/Install/Win32.pm
+inc/Module/Install/WriteAll.pm
+lib/Jifty/Plugin/Login.pm
+lib/Jifty/Plugin/Login/Action/ConfirmEmail.pm
+lib/Jifty/Plugin/Login/Action/Login.pm
+lib/Jifty/Plugin/Login/Action/Logout.pm
+lib/Jifty/Plugin/Login/Action/RecoverPassword.pm
+lib/Jifty/Plugin/Login/Action/ResetLostPassword.pm
+lib/Jifty/Plugin/Login/Action/SendAccountConfirmation.pm
+lib/Jifty/Plugin/Login/Action/SendPasswordReminder.pm
+lib/Jifty/Plugin/Login/Action/Signup.pm
+lib/Jifty/Plugin/Login/CurrentUser.pm
+lib/Jifty/Plugin/Login/Dispatcher.pm
+lib/Jifty/Plugin/Login/Model/User.pm
+lib/Jifty/Plugin/Login/Notification/ConfirmAddress.pm
+Makefile.PL
+MANIFEST			This list of files
+META.yml
+share/web/templates/let/confirm_email
+share/web/templates/login
+share/web/templates/logout
+share/web/templates/signup

Added: jifty/branches/plugin_rewrite/plugins/Login/Makefile.PL
==============================================================================
--- (empty file)
+++ jifty/branches/plugin_rewrite/plugins/Login/Makefile.PL	Tue Jul  4 10:11:38 2006
@@ -0,0 +1,8 @@
+use inc::Module::Install;
+name('Jifty-Plugin-Login');
+version('0.01');
+requires('Jifty' => '0.60507');
+
+install_share;
+
+WriteAll;

Added: jifty/branches/plugin_rewrite/plugins/Login/lib/Jifty/Plugin/Login.pm
==============================================================================
--- (empty file)
+++ jifty/branches/plugin_rewrite/plugins/Login/lib/Jifty/Plugin/Login.pm	Tue Jul  4 10:11:38 2006
@@ -0,0 +1,31 @@
+use strict;
+use warnings;
+
+package Jifty::Plugin::Login;
+use base qw/Jifty::Plugin/;
+
+# Your plugin goes here.  If takes any configuration or arguments, you
+# probably want to override L<Jifty::Plugin/init>.
+{
+    my ($CurrentUserClass, $LoginUserClass);
+
+    sub init {
+	my $self = shift;
+	my %args = @_;
+	my $appname = Jifty->config->framework('ApplicationName');
+	$CurrentUserClass = $args{CurrentUserClass}
+	    || "${appname}::CurrentUser";
+	$LoginUserClass = $args{LoginUserClass}
+	    || "${appname}::Model::User";
+    }
+
+    sub CurrentUserClass {
+	return $CurrentUserClass;
+    }
+
+    sub LoginUserClass {
+	return $LoginUserClass;
+    }
+}
+
+1;

Added: jifty/branches/plugin_rewrite/plugins/Login/lib/Jifty/Plugin/Login/Action/ConfirmEmail.pm
==============================================================================
--- (empty file)
+++ jifty/branches/plugin_rewrite/plugins/Login/lib/Jifty/Plugin/Login/Action/ConfirmEmail.pm	Tue Jul  4 10:11:38 2006
@@ -0,0 +1,59 @@
+use warnings;
+use strict;
+
+=head1 NAME
+
+Jifty::Plugin::Login::Action::ConfirmEmail - Confirm a user's email address
+
+=head1 DESCRIPTION
+
+This is the link in a user's email to confirm that their email
+email is really theirs.  It is not really meant to be rendered on any
+web page, but is used by the confirmation notification.
+
+=cut
+
+package Jifty::Plugin::Login::Action::ConfirmEmail;
+use base qw/Jifty::Action Jifty::Plugin::Login/;
+
+=head2 actions
+
+A null sub, because the superclass wants to make sure we fill in actions
+
+=cut
+
+sub actions { }
+
+=head2 take_action
+
+Set their confirmed status.
+
+=cut
+
+sub take_action {
+    my $self        = shift;
+    my $LoginUser   = $self->LoginUserClass();
+    my $CurrentUser = $self->CurrentUserClass();
+    my $u = $LoginUser->new( current_user => $CurrentUser->superuser );
+    $u->load_by_cols( email => Jifty->web->current_user->user_object->email );
+
+    if ( $u->email_confirmed ) {
+        $self->result->error(
+            email => "You have already confirmed your account." );
+        $self->result->success(1);    # but the action is still a success
+    }
+
+    $u->set_email_confirmed('1');
+
+    # Set up our login message
+    $self->result->message( "Welcome to "
+          . Jifty->config->framework('ApplicationName') . ", "
+          . $u->name
+          . ". Your email address has now been confirmed." );
+
+    # Actually do the login thing.
+    Jifty->web->current_user( $CurrentUser->new( id => $u->id ) );
+    return 1;
+}
+
+1;

Added: jifty/branches/plugin_rewrite/plugins/Login/lib/Jifty/Plugin/Login/Action/Login.pm
==============================================================================
--- (empty file)
+++ jifty/branches/plugin_rewrite/plugins/Login/lib/Jifty/Plugin/Login/Action/Login.pm	Tue Jul  4 10:11:38 2006
@@ -0,0 +1,112 @@
+use warnings;
+use strict;
+
+=head1 NAME
+
+Jifty::Plugin::Login::Action::Login
+
+=cut
+
+package Jifty::Plugin::Login::Action::Login;
+use base qw/Jifty::Action Jifty::Plugin::Login/;
+
+=head2 arguments
+
+Return the email and password form fields
+
+=cut
+
+sub arguments {
+    return (
+        {
+            email => {
+                label          => 'Email address',
+                mandatory      => 1,
+                ajax_validates => 1,
+            },
+
+            password => {
+                type      => 'password',
+                label     => 'Password',
+                mandatory => 1
+            },
+            remember => {
+                type  => 'checkbox',
+                label => 'Remember me?',
+                hints =>
+                  'If you want, your browser can remember your login for you',
+                default => 0,
+            }
+        }
+    );
+
+}
+
+=head2 validate_email ADDRESS
+
+Makes sure that the email submitted is a legal email address and that there's a user in the database with it.
+
+
+=cut
+
+sub validate_email {
+    my $self  = shift;
+    my $email = shift;
+    my $LoginUser = $self->LoginUserClass();
+    my $CurrentUser = $self->CurrentUserClass();
+
+    unless ( $email =~ /\S\@\S/ ) {
+        return $self->validation_error(
+            email => "That doesn't look like an email address." );
+    }
+
+    my $u = $LoginUser->new( current_user => $CurrentUser->superuser );
+    $u->load_by_cols( email => $email );
+    return $self->validation_error(
+        email => 'No account has that email address.' )
+      unless ( $u->id );
+
+    return $self->validation_ok('email');
+}
+
+=head2 take_action
+
+Actually check the user's password. If it's right, log them in.
+Otherwise, throw an error.
+
+
+=cut
+
+sub take_action {
+    my $self = shift;
+    my $CurrentUser = $self->CurrentUserClass();
+
+    my $user = $CurrentUser->new( email => $self->argument_value('email') );
+
+    unless ( $user->id
+        && $user->password_is( $self->argument_value('password') ) )
+    {
+        $self->result->error(
+ q{You may have mistyped your email address or password. Give it another shot?}
+        );
+        return;
+    }
+
+    unless ( $user->user_object->email_confirmed ) {
+        $self->result->error(q{You haven't confirmed your account yet.});
+        return;
+    }
+
+    # Set up our login message
+    $self->result->message( "Welcome back, " . $user->user_object->name . "." );
+
+    # Actually do the signin thing.
+    Jifty->web->current_user($user);
+    Jifty->web->session->expires(
+        $self->argument_value('remember') ? '+1y' : undef );
+    Jifty->web->session->set_cookie;
+
+    return 1;
+}
+
+1;

Added: jifty/branches/plugin_rewrite/plugins/Login/lib/Jifty/Plugin/Login/Action/Logout.pm
==============================================================================
--- (empty file)
+++ jifty/branches/plugin_rewrite/plugins/Login/lib/Jifty/Plugin/Login/Action/Logout.pm	Tue Jul  4 10:11:38 2006
@@ -0,0 +1,35 @@
+use warnings;
+use strict;
+
+=head1 NAME
+
+Jifty::Plugin::Login::Action::Logout
+
+=cut
+
+package Jifty::Plugin::Login::Action::Logout;
+use base qw/Jifty::Action/;
+
+=head2 arguments
+
+Return the email and password form fields
+
+=cut
+
+sub arguments {
+    return ( {} );
+}
+
+=head2 take_action
+
+Nuke the current user object
+
+=cut
+
+sub take_action {
+    my $self = shift;
+    Jifty->web->current_user(undef);
+    return 1;
+}
+
+1;

Added: jifty/branches/plugin_rewrite/plugins/Login/lib/Jifty/Plugin/Login/Action/RecoverPassword.pm
==============================================================================
--- (empty file)
+++ jifty/branches/plugin_rewrite/plugins/Login/lib/Jifty/Plugin/Login/Action/RecoverPassword.pm	Tue Jul  4 10:11:38 2006
@@ -0,0 +1,7 @@
+
+use warnings;
+use strict;
+
+package Jifty::Plugin::Login::Action::RecoverPassword;
+
+1;

Added: jifty/branches/plugin_rewrite/plugins/Login/lib/Jifty/Plugin/Login/Action/ResetLostPassword.pm
==============================================================================
--- (empty file)
+++ jifty/branches/plugin_rewrite/plugins/Login/lib/Jifty/Plugin/Login/Action/ResetLostPassword.pm	Tue Jul  4 10:11:38 2006
@@ -0,0 +1,87 @@
+use warnings;
+use strict;
+
+=head1 NAME
+
+Jifty::Plugin::Login::Action::ResetPassword - Confirm and reset a lost password
+
+=head1 DESCRIPTION
+
+This is the action run by the link in a user's email to confirm that their email
+address is really theirs, when claiming that they lost their password.  
+
+
+=cut
+
+package Jifty::Plugin::Login::Action::ResetPassword;
+use base qw/Jifty::Action/;
+
+use Jifty::Plugin::Login::Model::User;
+
+=head2 arguments
+
+ConfirmEmail has the following fields: address, code, password, and password_confirm.
+Note that it can get the first two from the confirm dhandler.
+
+=cut
+
+sub arguments {
+    return (
+        {
+            password         => { type => 'password', sticky => 0 },
+            password_confirm => {
+                type   => 'password',
+                sticky => 0,
+                label  => 'type your password again'
+            },
+        }
+    );
+}
+
+=head2 take_action
+
+Resets the password.
+
+=cut
+
+sub take_action {
+    my $self        = shift;
+    my $LoginUser   = $Jifty::Plugin::Login::LoginUserClass;
+    my $CurrentUser = $Jifty::Plugin::Login::CurrentUserClass;
+    my $u = $LoginUser->new( current_user => $CurrentUser->superuser );
+    $u->load_by_cols( email => Jifty->web->current_user->user_object->email );
+
+    unless ($u) {
+        $self->result->error(
+"You don't exist. I'm not sure how this happened. Really, really sorry. Please email us!"
+        );
+    }
+
+    my $pass   = $self->argument_value('password');
+    my $pass_c = $self->argument_value('password_confirm');
+
+    # Trying to set a password (ie, submitted the form)
+    unless (defined $pass
+        and defined $pass_c
+        and length $pass
+        and $pass eq $pass_c )
+    {
+        $self->result->error(
+"It looks like you didn't enter the same password into both boxes. Give it another shot?"
+        );
+        return;
+    }
+
+    unless ( $u->set_password($pass) ) {
+        $self->result->error("There was an error setting your password.");
+        return;
+    }
+
+    # Log in!
+    $self->result->message("Your password has been reset.  Welcome back.");
+    Jifty->web->current_user( $CurrentUser->new( id => $u->id ) );
+    return 1;
+
+}
+
+1;

Added: jifty/branches/plugin_rewrite/plugins/Login/lib/Jifty/Plugin/Login/Action/SendAccountConfirmation.pm
==============================================================================
--- (empty file)
+++ jifty/branches/plugin_rewrite/plugins/Login/lib/Jifty/Plugin/Login/Action/SendAccountConfirmation.pm	Tue Jul  4 10:11:38 2006
@@ -0,0 +1,97 @@
+use warnings;
+use strict;
+
+=head1 NAME
+
+Jifty::Plugin::Login::Action::ResendConfirmation
+
+=cut
+
+package Jifty::Plugin::Login::Action::ResendConfirmation;
+use base qw/Jifty::Action/;
+my $LoginUser   = $Jifty::Plugin::Login::LoginUserClass;
+my $CurrentUser = $Jifty::Plugin::Login::CurrentUserClass;
+
+__PACKAGE__->mk_accessors(qw(user_object));
+
+use Jifty::Plugin::Login::Model::User;
+
+=head2 arguments
+
+The field for C<ResendConfirmation> is:
+
+=over 4
+
+=item address: the email address
+
+=back
+
+=cut
+
+sub arguments {
+    return (
+        {
+            address => {
+                label         => 'email address',
+                mandatory     => 1,
+                default_value => "",
+            },
+        }
+    );
+}
+
+=head2 setup
+
+Create an empty user object to work with
+
+=cut
+
+sub setup {
+    my $self = shift;
+
+    $self->user_object(
+        $LoginUser->new( current_user => $CurrentUser->superuser ) );
+}
+
+=head2 validate_address
+
+Make sure their email address is an unconfirmed user.
+
+=cut
+
+sub validate_address {
+    my $self  = shift;
+    my $email = shift;
+
+    return $self->validation_error(
+        address => "That doesn't look like an email address." )
+      unless ( $email =~ /\S\@\S/ );
+
+    $self->user_object(
+        $LoginUser->new( current_user => $CurrentUser->superuser ) );
+    $self->user_object->load_by_cols( email => $email );
+    return $self->validation_error(
+        address => "It doesn't look like there's an account by that name." )
+      unless ( $self->user_object->id );
+
+    return $self->validation_error(
+        address => "It looks like you're already confirmed." )
+      if ( $self->user_object->email_confirmed );
+
+    return $self->validation_ok('address');
+}
+
+=head2 take_action
+
+Create a new unconfirmed user and send out a confirmation email.
+
+=cut
+
+sub take_action {
+    my $self = shift;
+    Jifty::Plugin::Login::Notification::ConfirmAddress->new(
+        to => $self->user_object )->send;
+    return $self->result->message("Confirmation resent.");
+}
+
+1;

Added: jifty/branches/plugin_rewrite/plugins/Login/lib/Jifty/Plugin/Login/Action/SendPasswordReminder.pm
==============================================================================
--- (empty file)
+++ jifty/branches/plugin_rewrite/plugins/Login/lib/Jifty/Plugin/Login/Action/SendPasswordReminder.pm	Tue Jul  4 10:11:38 2006
@@ -0,0 +1,97 @@
+use warnings;
+use strict;
+
+=head1 NAME
+
+Jifty::Plugin::Login::Action::SendLostPasswordConfirmation
+
+=cut
+
+package Jifty::Plugin::Login::Action::SendLostPasswordConfirmation;
+use base qw/Jifty::Plugin::Login::Action Jifty::Action Jifty::Plugin::Login/;
+
+__PACKAGE__->mk_accessors(qw(user_object));
+
+use Jifty::Plugin::Login::Model::User;
+
+=head2 arguments
+
+The field for C<SendLostPasswordConfirmation> is:
+
+=over 4
+
+=item address: the email address
+
+=back
+
+=cut
+
+sub arguments {
+    return (
+        {
+            address => {
+                label     => 'email address',
+                mandatory => 1,
+            },
+        }
+    );
+
+}
+
+=head2 setup
+
+Create an empty user object to work with
+
+=cut
+
+sub setup {
+    my $self = shift;
+    my $LoginUser = $self->LoginUserClass();
+    my $CurrentUser = $self->CurrentUserClass();
+
+    # Make a blank user object
+    $self->user_object(
+        $LoginUser->new( current_user => $CurrentUser->superuser ) );
+}
+
+=head2 validate_address
+
+Make sure there's actually an account by that name.
+
+=cut
+
+sub validate_address {
+    my $self  = shift;
+    my $email = shift;
+    my $LoginUser = $self->LoginUserClass();
+    my $CurrentUser = $self->CurrentUserClass();
+
+    return $self->validation_error(
+        address => "That doesn't look like an email address." )
+      unless ( $email =~ /\S\@\S/ );
+
+    $self->user_object(
+        $LoginUser->new( current_user => $CurrentUser->superuser ) );
+    $self->user_object->load_by_cols( email => $email );
+    return $self->validation_error(
+        address => "It doesn't look like there's an account by that name." )
+      unless ( $self->user_object->id );
+
+    return $self->validation_ok('address');
+}
+
+=head2 take_action
+
+Send out a confirmation email giving a link to a password-reset form.
+
+=cut
+
+sub take_action {
+    my $self = shift;
+    Jifty::Plugin::Login::Notification::ConfirmLostPassword->new(
+        to => $self->user_object )->send;
+    return $self->result->message(
+        "A link to reset your password has been sent to your email account.");
+}
+
+1;

Added: jifty/branches/plugin_rewrite/plugins/Login/lib/Jifty/Plugin/Login/Action/Signup.pm
==============================================================================
--- (empty file)
+++ jifty/branches/plugin_rewrite/plugins/Login/lib/Jifty/Plugin/Login/Action/Signup.pm	Tue Jul  4 10:11:38 2006
@@ -0,0 +1,114 @@
+use warnings;
+use strict;
+
+=head1 NAME
+
+Jifty::Plugin::Login::Action::Signup
+
+=cut
+
+package Jifty::Plugin::Login::Action::Signup;
+use Jifty::Plugin::Login::Action::CreateUser;
+use base qw/Jifty::Plugin::Login::Action::CreateUser Jifty::Plugin::Login/;
+
+=head2 arguments
+
+
+The fields for C<Signup> are:
+
+=over 4
+
+=item email: the email address
+
+=item password and password_confirm: the requested password
+
+=item name: your full name
+
+=back
+
+=cut
+
+sub arguments {
+    my $self = shift;
+    my $args = $self->SUPER::arguments;
+
+    my %fields = (
+        name             => 1,
+        email            => 1,
+        password         => 1,
+        password_confirm => 1,
+    );
+
+    for ( keys %$args ) { delete $args->{$_} unless ( $fields{$_} ); }
+    $args->{'email'}{'ajax_validates'}   = 1;
+    $args->{'password_confirm'}{'label'} = "Type that again?";
+    return $args;
+}
+
+=head2 validate_email
+
+Make sure their email address looks sane
+
+=cut
+
+sub validate_email {
+    my $self  = shift;
+    my $email = shift;
+    my $LoginUser = $self->LoginUserClass();
+    my $CurrentUser = $self->CurrentUserClass();
+
+    return $self->validation_error(
+        email => "That doesn't look like an email address." )
+      unless ( $email =~ /\S\@\S/ );
+
+    my $u = $LoginUser->new( current_user => $CurrentUser->superuser );
+    $u->load_by_cols( email => $email );
+    if ( $u->id ) {
+        return $self->validation_error( email =>
+'It looks like you already have an account. Perhaps you want to <a href="/login">sign in</a> instead?'
+        );
+    }
+
+    return $self->validation_ok('email');
+}
+
+=head2 take_action
+
+Overrides the virtual C<take_action> method on L<Jifty::Action> to call
+the appropriate C<Jifty::Record>'s C<create> method when the action is
+run, thus creating a new object in the database.
+
+Makes sure that the user only specifies things we want them to.
+
+=cut
+
+sub take_action {
+    my $self   = shift;
+    my $LoginUser = $self->LoginUserClass();
+    my $CurrentUser = $self->CurrentUserClass();
+    my $record = $LoginUser->new( current_user => $CurrentUser->superuser );
+
+    my %values;
+    $values{$_} = $self->argument_value($_) for grep {
+        defined $self->record->column($_) and defined $self->argument_value($_)
+    } $self->argument_names;
+
+    my ($id) = $record->create(%values);
+
+    # Handle errors?
+    unless ( $record->id ) {
+        $self->result->error(
+"Something bad happened and we couldn't create your account.  Try again later. We're really, really sorry."
+        );
+        return;
+    }
+
+    $self->result->message( "Welcome to "
+          . Jifty->config->framework('ApplicationName') . ", "
+          . $record->name
+          . ". We've sent a confirmation message to your email box." );
+
+    return 1;
+}
+
+1;

Added: jifty/branches/plugin_rewrite/plugins/Login/lib/Jifty/Plugin/Login/CurrentUser.pm
==============================================================================
--- (empty file)
+++ jifty/branches/plugin_rewrite/plugins/Login/lib/Jifty/Plugin/Login/CurrentUser.pm	Tue Jul  4 10:11:38 2006
@@ -0,0 +1,39 @@
+use warnings;
+use strict;
+
+
+package Jifty::Plugin::Login::CurrentUser;
+
+use base qw/Jifty::CurrentUser Jifty::Plugin::Login/;
+
+=head2 new PARAMHASH
+
+Instantiate a new current user object, loading the user by paramhash:
+
+   my $item = Jifty::Plugin::Login::Model::Item->new( Jifty::Plugin::Login::CurrentUser->new(email => 'user at site'));
+
+if you give the param 
+    _bootstrap => 1
+
+your object will be marked as a bootstrap user. You can use that to do an endrun around acls.
+
+=cut
+
+
+
+sub _init {
+    my $self = shift;
+    my %args = (@_);
+    my $LoginUserClass = $self->LoginUserClass;
+
+    if (delete $args{'_bootstrap'} ) {
+        $self->is_bootstrap_user(1);
+    } elsif (keys %args) {
+        $self->user_object($LoginUserClass->new(current_user => $self));
+        $self->user_object->load_by_cols(%args);
+    }
+    $self->SUPER::_init(%args);
+}
+
+
+1;

Added: jifty/branches/plugin_rewrite/plugins/Login/lib/Jifty/Plugin/Login/Dispatcher.pm
==============================================================================
--- (empty file)
+++ jifty/branches/plugin_rewrite/plugins/Login/lib/Jifty/Plugin/Login/Dispatcher.pm	Tue Jul  4 10:11:38 2006
@@ -0,0 +1,62 @@
+use strict;
+use warnings;
+
+package Jifty::Plugin::Login::Dispatcher;
+use Jifty::Dispatcher -base;
+
+# Put any plugin-specific dispatcher rules here.
+
+# Sign up for an account
+on 'signup' => run {
+    redirect('/') if ( Jifty->web->current_user->id );
+    set 'action' =>
+        Jifty->web->new_action(
+	    class => 'Signup',
+	    moniker => 'signupbox'
+	);
+
+    set 'next' => Jifty->web->request->continuation
+        || Jifty::Continuation->new(
+        request => Jifty::Request->new( path => "/" ) );
+
+};
+
+# Login
+on 'login' => run {
+    set 'action' =>
+        Jifty->web->new_action(
+	    class => 'Login',
+	    moniker => 'loginbox'
+	);
+    set 'next' => Jifty->web->request->continuation
+        || Jifty::Continuation->new(
+        request => Jifty::Request->new( path => "/" ) );
+};
+
+# Log out
+before 'logout' => run {
+    Jifty->web->request->add_action(
+        class   => 'Logout',
+        moniker => 'logout',
+    );
+};
+
+## LetMes
+before qr'^/let/(.*)' => run {
+    my $let_me = Jifty::LetMe->new();
+    $let_me->from_token($1);
+    redirect '/error/let_me/invalid_token' unless $let_me->validate;
+
+    Jifty->web->temporary_current_user($let_me->validated_current_user);
+
+    my %args = %{$let_me->args};
+    set $_ => $args{$_} for keys %args;
+    set let_me => $let_me;
+};
+
+on qr'^/let/' => run {
+    my $let_me = get 'let_me';
+    show '/let/' . $let_me->path;
+};
+
+1;

Added: jifty/branches/plugin_rewrite/plugins/Login/lib/Jifty/Plugin/Login/Model/User.pm
==============================================================================
--- (empty file)
+++ jifty/branches/plugin_rewrite/plugins/Login/lib/Jifty/Plugin/Login/Model/User.pm	Tue Jul  4 10:11:38 2006
@@ -0,0 +1,127 @@
+package Jifty::Plugin::Login::Model::User::Schema;
+use Jifty::DBI::Schema;
+
+column
+  name => type is 'text',
+  label is 'Name',
+  is mandatory,
+  is distinct;
+
+column
+  email => type is 'text',
+  label is 'Email address',
+  is mandatory,
+  is distinct;
+
+column
+  password =>,
+  type is 'text',
+  label is 'Password',
+  render_as 'password';
+
+column
+  email_confirmed => label is 'Email address confirmed?',
+  type is 'boolean';
+
+column
+  auth_token => type is 'text',
+  render_as 'Password';
+
+package Jifty::Plugin::Login::Model::User;
+use base qw/Jifty::Record/;
+use Jifty::Plugin::Login::Notification::ConfirmAddress;
+
+sub create {
+    my $self  = shift;
+    my %args  = (@_);
+    my (@ret) = $self->SUPER::create(%args);
+
+    if ( $self->id and not $self->email_confirmed ) {
+        Jifty::Plugin::Login::Notification::ConfirmAddress->new( to => $self )
+          ->send;
+    }
+    return (@ret);
+}
+
+=head2 password_is STRING
+
+Returns true if and only if the current user's password matches STRING
+
+=cut
+
+sub password_is {
+    my $self   = shift;
+    my $string = shift;
+    return 1 if ( $self->_value('password') eq $string );
+    return 0;
+}
+
+=head2 password
+
+Never display a password
+
+=cut
+
+sub password {
+    return undef;
+
+}
+
+=head2 current_user_can
+
+Allows the current user to see all their own attributes and
+everyone else to see their username.
+
+Allows the current user to update any of their own attributes
+except whether or not their email has been confirmed.
+
+Passes everything else off to the superclass.
+
+=cut
+
+sub current_user_can {
+    my $self  = shift;
+    my $right = shift;
+    my %args  = (@_);
+    Carp::confess if ( $right eq 'read' and not $args{'column'} );
+    if (    $right eq 'read'
+        and $self->id == $self->current_user->id )
+    {
+        return 1;
+    }
+    elsif ( $right eq 'read' and $args{'column'} eq 'name' ) {
+        return (1);
+
+    }
+    elsif ( $right eq 'update'
+        and $self->id == $self->current_user->id
+        and $args{'column'} ne 'email_confirmed' )
+    {
+        return (1);
+    }
+
+    return $self->SUPER::current_user_can( $right, %args );
+}
+
+=head2 auth_token
+
+Returns the user's unique authentication token. If the user 
+doesn't have one, sets one and returns it.
+
+=cut
+
+sub auth_token {
+    my $self = shift;
+    return undef
+      unless ( $self->current_user_can( read => column => 'auth_token' ) );
+    my $value = $self->_value('auth_token');
+    unless ($value) {
+        my $digest = Digest::MD5->new();
+        $digest->add( rand(100) );
+        $self->__set( column => 'auth_token', value => $digest->b64digest );
+    }
+    return $self->_value('auth_token');
+
+}
+
+1;

Added: jifty/branches/plugin_rewrite/plugins/Login/lib/Jifty/Plugin/Login/Notification/ConfirmAddress.pm
==============================================================================
--- (empty file)
+++ jifty/branches/plugin_rewrite/plugins/Login/lib/Jifty/Plugin/Login/Notification/ConfirmAddress.pm	Tue Jul  4 10:11:38 2006
@@ -0,0 +1,55 @@
+use warnings;
+use strict;
+
+package Jifty::Plugin::Login::Notification::ConfirmAddress;
+use base qw/Jifty::Notification Jifty::Plugin::Login/;
+
+=head1 NAME
+
+Hiveminder::Notification::ConfirmAddress
+
+=head1 ARGUMENTS
+
+C<to>, a L<Jifty::Plugin::Login::Model::User> whose address we are confirming.
+
+=cut
+
+=head2 setup
+
+Sets up the fields of the message.
+
+=cut
+
+sub setup {
+    my $self = shift;
+    my $LoginUser = $self->LoginUserClass;
+
+    unless ( UNIVERSAL::isa($self->to, $LoginUser) ){
+	$self->log->error((ref $self) . " called with invalid user argument");
+	return;
+    } 
+   
+
+    my $letme = Jifty::LetMe->new();
+    $letme->email($self->to->email);
+    $letme->path('confirm_email'); 
+    my $confirm_url = $letme->as_url;
+    my $appname = Jifty->config->framework('ApplicationName');
+
+    $self->subject( "Welcome to $appname!" );
+    $self->from( Jifty->config->framework('AdminEmail') );
+
+    $self->body(<<"END_BODY");
+
+You're getting this message because you (or somebody claiming to be you)
+signed up for $appname.
+
+Before you can use $appname, we need to make sure that we got your email
+address right.  Click on the link below to get started:
+
+$confirm_url
+
+END_BODY
+}
+
+1;

Added: jifty/branches/plugin_rewrite/plugins/Login/share/web/templates/let/confirm_email
==============================================================================
--- (empty file)
+++ jifty/branches/plugin_rewrite/plugins/Login/share/web/templates/let/confirm_email	Tue Jul  4 10:11:38 2006
@@ -0,0 +1,7 @@
+<%init>
+Jifty->web->new_action(
+    moniker => 'confirm_email',
+    class   => 'ConfirmEmail',
+)->run;
+Jifty->web->redirect("/");
+</%init>

Added: jifty/branches/plugin_rewrite/plugins/Login/share/web/templates/login
==============================================================================
--- (empty file)
+++ jifty/branches/plugin_rewrite/plugins/Login/share/web/templates/login	Tue Jul  4 10:11:38 2006
@@ -0,0 +1,20 @@
+<%args>
+$action => undef
+$next => undef
+</%args>
+<&|/_elements/wrapper, title => 'Login' &>
+
+% if (not Jifty->web->current_user->id) {
+<h2>Login</h2>
+<% Jifty->web->form->start(call => $next, name => "loginbox") %>
+<% $action->form_field('email') %>
+<% $action->form_field('password') %>
+<% $action->form_field('remember') %>
+<% Jifty->web->form->submit(label => 'Login', submit => $action) %>
+<% Jifty->web->form->end %>
+<% Jifty->web->tangent( label => q{Don't have an account?}, url => '/signup' )%>
+% }
+% else {
+You're already logged in.
+% }
+</&>

Added: jifty/branches/plugin_rewrite/plugins/Login/share/web/templates/logout
==============================================================================
--- (empty file)
+++ jifty/branches/plugin_rewrite/plugins/Login/share/web/templates/logout	Tue Jul  4 10:11:38 2006
@@ -0,0 +1,3 @@
+<&| /_elements/wrapper, title => "Logged out" &>
+<p>Ok, you're now logged out. Have a good day.</p>
+</&>

Added: jifty/branches/plugin_rewrite/plugins/Login/share/web/templates/signup
==============================================================================
--- (empty file)
+++ jifty/branches/plugin_rewrite/plugins/Login/share/web/templates/signup	Tue Jul  4 10:11:38 2006
@@ -0,0 +1,14 @@
+<%args>
+$action
+$next
+</%args>
+<&|/_elements/wrapper, title => 'Signup' &>
+<h2>Signup</h2>
+<% Jifty->web->form->start(call => $next, name => "signupbox") %>
+<% $action->form_field('email') %>
+<% $action->form_field('name') %>
+<% $action->form_field('password') %>
+<% $action->form_field('password_confirm') %>
+<% Jifty->web->form->submit(label => 'Signup', submit => $action) %>
+<% Jifty->web->form->end %>
+</&>

Modified: jifty/branches/plugin_rewrite/share/web/static/js/calendar.js
==============================================================================
--- jifty/branches/plugin_rewrite/share/web/static/js/calendar.js	(original)
+++ jifty/branches/plugin_rewrite/share/web/static/js/calendar.js	Tue Jul  4 10:11:38 2006
@@ -25,6 +25,11 @@
 
         Jifty.Calendar.hideOpenCalendar();
         
+        /* We need to delay Jifty's canonicalization until after we've
+           selected a value via the calendar */
+        input["_onblur"] = input.onblur;
+        input.onblur     = null;
+        
         if ( wrap ) {
             wrap.style.display = "block";
             Jifty.Calendar.openCalendar = wrapId;
@@ -69,6 +74,18 @@
     hideOpenCalendar: function() {
         if ( Jifty.Calendar.openCalendar ) {
             $( Jifty.Calendar.openCalendar ).style.display = "none";
+
+            /* Get the input's ID */
+            var inputId = Jifty.Calendar.openCalendar;
+                inputId = inputId.replace(/^cal_/, '');
+                inputId = inputId.replace(/_wrap$/, '');
+
+            var input = $( inputId );
+
+            /* Restore the original onblur */
+            input.onblur     = input["_onblur"];
+            input["_onblur"] = null;
+            
             Jifty.Calendar.openCalendar = "";
         }
     }


More information about the Jifty-commit mailing list