[Jifty-commit] r2952 - in jifty/trunk: . lib/Jifty/Plugin/Authentication/Password/Action lib/Jifty/Plugin/LetMe lib/Jifty/Plugin/User/Model t/TestApp-Plugin-PasswordAuth/lib/TestApp/Plugin/PasswordAuth t/TestApp-Plugin-PasswordAuth/t

jifty-commit at lists.jifty.org jifty-commit at lists.jifty.org
Mon Mar 12 23:19:18 EDT 2007


Author: jesse
Date: Mon Mar 12 23:19:16 2007
New Revision: 2952

Added:
   jifty/trunk/lib/Jifty/Plugin/Authentication/Password/Action/Logout.pm   (contents, props changed)
   jifty/trunk/lib/Jifty/Plugin/Authentication/Password/Action/RecoverPassword.pm   (contents, props changed)
   jifty/trunk/lib/Jifty/Plugin/Authentication/Password/Action/ResendConfirmation.pm   (contents, props changed)
   jifty/trunk/lib/Jifty/Plugin/Authentication/Password/Action/ResetLostPassword.pm   (contents, props changed)
   jifty/trunk/lib/Jifty/Plugin/Authentication/Password/Action/SendAccountConfirmation.pm   (contents, props changed)
   jifty/trunk/lib/Jifty/Plugin/Authentication/Password/Action/SendPasswordReminder.pm   (contents, props changed)
   jifty/trunk/lib/Jifty/Plugin/Authentication/Password/Action/Signup.pm   (contents, props changed)
   jifty/trunk/lib/Jifty/Plugin/LetMe/
   jifty/trunk/lib/Jifty/Plugin/LetMe/Dispatcher.pm
Modified:
   jifty/trunk/   (props changed)
   jifty/trunk/lib/Jifty/ClassLoader.pm
   jifty/trunk/lib/Jifty/Config.pm
   jifty/trunk/lib/Jifty/Plugin/Authentication/Password/Action/GeneratePasswordToken.pm
   jifty/trunk/lib/Jifty/Plugin/Authentication/Password/Action/Login.pm
   jifty/trunk/lib/Jifty/Plugin/User/Model/User.pm
   jifty/trunk/t/TestApp-Plugin-PasswordAuth/lib/TestApp/Plugin/PasswordAuth/Bootstrap.pm
   jifty/trunk/t/TestApp-Plugin-PasswordAuth/t/00-model-User.t
   jifty/trunk/t/TestApp-Plugin-PasswordAuth/t/01-tokengen.t

Log:
 r53372 at pinglin:  jesse | 2007-03-12 23:17:27 -0400
  Next pass at a login/signup password auth plugin. Now supports login and logout. Next up is signup.


Modified: jifty/trunk/lib/Jifty/ClassLoader.pm
==============================================================================
--- jifty/trunk/lib/Jifty/ClassLoader.pm	(original)
+++ jifty/trunk/lib/Jifty/ClassLoader.pm	Mon Mar 12 23:19:16 2007
@@ -180,13 +180,14 @@
 
     # This is if, not elsif because we might have $base::Action::Deleteblah 
     # that matches that last elsif clause but loses on the eval.
-    if ( $module =~ /^(?:$base)::Action::(.*)$/x and not grep {$_ eq $base} map {ref} Jifty->plugins ) {
-        my $action = $1;
+    if ( $module =~ /^(?:$base)::(Action|Notification)::(.*)$/x and not grep {$_ eq $base} map {ref} Jifty->plugins ) {
+        my $type = $1; 
+        my $item = $2;
         # If we don't have the action in our own app, let's try the plugins
         # the app has loaded.
         foreach my $plugin (map {ref} Jifty->plugins) {
             next if ($plugin eq $base);
-            my $class = $plugin."::Action::".$action;
+            my $class = $plugin."::".$type."::".$item;
             if (Jifty::Util->try_to_require($class) ) {
         return $self->return_class(
                   "package $module;\n"

Modified: jifty/trunk/lib/Jifty/Config.pm
==============================================================================
--- jifty/trunk/lib/Jifty/Config.pm	(original)
+++ jifty/trunk/lib/Jifty/Config.pm	Mon Mar 12 23:19:16 2007
@@ -263,15 +263,15 @@
             L10N       => {
                 PoDir => "share/po",
             },
-            Plugins    => [
-            { REST => {},
-        },
-        {       Halo => {},},
-        {ErrorTemplates => {},},
-        {OnlineDocs => {},},
-        {        CompressedCSSandJS => {},},
-        {AdminUI => {},}
-            ],
+            Plugins => [
+                { LetMe               => {}, },
+                { REST               => {}, },
+                { Halo               => {}, },
+                { ErrorTemplates     => {}, },
+                { OnlineDocs         => {}, },
+                { CompressedCSSandJS => {}, },
+                { AdminUI            => {}, }
+                ],
             Web        => {
                 Port => '8888',
                 BaseURL => 'http://localhost',

Modified: jifty/trunk/lib/Jifty/Plugin/Authentication/Password/Action/GeneratePasswordToken.pm
==============================================================================
--- jifty/trunk/lib/Jifty/Plugin/Authentication/Password/Action/GeneratePasswordToken.pm	(original)
+++ jifty/trunk/lib/Jifty/Plugin/Authentication/Password/Action/GeneratePasswordToken.pm	Mon Mar 12 23:19:16 2007
@@ -12,13 +12,13 @@
 
 =head2 arguments
 
-We need the username of the user we're fetching a token for, so we can
+We need the email of the user we're fetching a token for, so we can
 return the salt.
 
 =cut
 
 sub arguments { 
-    return( { username => { mandatory => 1 } });
+    return( { email => { mandatory => 1 } });
 
 }
 
@@ -34,10 +34,10 @@
 sub take_action {
     my $self = shift;
 
-    my $username = $self->argument_value('username');
+    my $email = $self->argument_value('email');
     my $class = Jifty->app_class('Model','User');
     my $user = $class->new(current_user => Jifty::CurrentUser->superuser);
-    $user->load_by_cols(username => $username);
+    $user->load_by_cols(email => $email);
     unless($user->id) {
         $self->result->error('No such user');
     }

Modified: jifty/trunk/lib/Jifty/Plugin/Authentication/Password/Action/Login.pm
==============================================================================
--- jifty/trunk/lib/Jifty/Plugin/Authentication/Password/Action/Login.pm	(original)
+++ jifty/trunk/lib/Jifty/Plugin/Authentication/Password/Action/Login.pm	Mon Mar 12 23:19:16 2007
@@ -15,12 +15,12 @@
 
 =head2 arguments
 
-Return the username and password form fields
+Return the email and password form fields
 
 =cut
 
 sub arguments { 
-    return( { username => { label => 'Username',
+    return( { email => { label => 'Email',
                            mandatory => 1,
                            ajax_validates => 1,
                             }  ,
@@ -46,24 +46,24 @@
 
 }
 
-=head2 validate_username ADDRESS
+=head2 validate_email ADDRESS
 
-Makes sure that the username submitted is a legal username and that there's a user in the database with it.
+Makes sure that the email submitted is a legal email and that there's a user in the database with it.
 
 Overridden from Jifty::Action::Record.
 
 =cut
 
-sub validate_username {
+sub validate_email {
     my $self  = shift;
-    my $username = shift;
+    my $email = shift;
 
     my $u = Jifty->app_class('Model', 'User')->new(current_user => Jifty->app_class('CurrentUser')->superuser);
-    $u->load_by_cols( username => $username );
-    warn "Loaded $u with ".$username;
-    return $self->validation_error(username => 'We do not have an account that matches that username.') unless ($u->id);
+    $u->load_by_cols( email => $email );
+    warn "Loaded $u with ".$email;
+    return $self->validation_error(email => 'We do not have an account that matches that email.') unless ($u->id);
 
-    return $self->validation_ok('username');
+    return $self->validation_ok('email');
 }
 
 
@@ -134,7 +134,7 @@
     my $self = shift;
     warn "1";
     my $user = Jifty->app_class('Model', 'User')->new(current_user => Jifty->app_class('CurrentUser')->superuser);
-    $user->load_by_cols( username => $self->argument_value('username') );
+    $user->load_by_cols( email => $self->argument_value('email') );
 
 
     my $password = $self->argument_value('password');
@@ -145,16 +145,13 @@
     if ( $token ne '' ) {   # browser supports javascript, do password hashing
         unless ( $user->id && $user->hashed_password_is( $hashedpw, $token ) )
         {
-            $self->result->error(
-                'You may have mistyped your username or password. Give it another shot.'
-            );
+            $self->result->error( _('You may have mistyped your email or password. Give it another shot.'));
             return;
         }
         Jifty->web->session->set( login_token => '' );
     } else {                # no password hashing over the wire
         unless ( $user->id && $user->password_is($password) ) {
-            $self->result->error( 'You may have mistyped your username or password. Give it another shot.'
-            );
+            $self->result->error( _('You may have mistyped your email address or password. Give it another shot.'));
             return;
         }
     }

Added: jifty/trunk/lib/Jifty/Plugin/Authentication/Password/Action/Logout.pm
==============================================================================
--- (empty file)
+++ jifty/trunk/lib/Jifty/Plugin/Authentication/Password/Action/Logout.pm	Mon Mar 12 23:19:16 2007
@@ -0,0 +1,35 @@
+use warnings;
+use strict;
+
+=head1 NAME
+
+Jifty::Plugin::Authentication::Password::Action::Logout
+
+=cut
+
+package Jifty::Plugin::Authentication::Password::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/trunk/lib/Jifty/Plugin/Authentication/Password/Action/RecoverPassword.pm
==============================================================================
--- (empty file)
+++ jifty/trunk/lib/Jifty/Plugin/Authentication/Password/Action/RecoverPassword.pm	Mon Mar 12 23:19:16 2007
@@ -0,0 +1,8 @@
+
+use warnings;
+use strict;
+
+package Jifty::Plugin::Authentication::Password::Action::RecoverPassword;
+use base qw/Jifty::Action Jifty::Plugin::Authentication::Password/;
+
+1;

Added: jifty/trunk/lib/Jifty/Plugin/Authentication/Password/Action/ResendConfirmation.pm
==============================================================================
--- (empty file)
+++ jifty/trunk/lib/Jifty/Plugin/Authentication/Password/Action/ResendConfirmation.pm	Mon Mar 12 23:19:16 2007
@@ -0,0 +1,99 @@
+use warnings;
+use strict;
+
+=head1 NAME
+
+Jifty::Plugin::Authentication::Password::Action::ResendConfirmation
+
+=cut
+
+package Jifty::Plugin::Authentication::Password::Action::ResendConfirmation;
+use base qw/Jifty::Action/;
+
+__PACKAGE__->mk_accessors(qw(user_object));
+
+
+=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;
+    
+    # Make a blank user object
+    $self->user_object(Jifty->app_class('Model','User')->new(current_user => Jifty->app_class('CurrentUser')->superuser));
+}
+
+=head2 validate_address
+
+Make sure their email address is an unconfirmed user.
+
+=cut
+
+sub validate_address {
+    my $self  = shift;
+    my $email = shift;
+
+    unless ( $email =~ /\S\@\S/ ) {
+        return $self->validation_error(address => "Are you sure that's an email address?" );
+    }
+
+    $self->user_object(Jifty->app_class('Model','User')->new(current_user => Jifty->app_class('CurrentUser')->superuser));
+    $self->user_object->load_by_cols( email => $email );
+    unless ($self->user_object->id) {
+      return $self->validation_error(address => "It doesn't look like there's an account by that name.");
+    }
+
+    if ($self->user_object->email_confirmed) {
+      return $self->validation_error(address => "It looks like you're already 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;
+    my $user = $self->user_object();
+
+    Jifty->app_class('Notification','ConfirmAddress')->new( to => $user )->send;
+    
+    $self->result->message("We've re-sent your confirmation.");
+
+    return 1;
+}
+
+1;

Added: jifty/trunk/lib/Jifty/Plugin/Authentication/Password/Action/ResetLostPassword.pm
==============================================================================
--- (empty file)
+++ jifty/trunk/lib/Jifty/Plugin/Authentication/Password/Action/ResetLostPassword.pm	Mon Mar 12 23:19:16 2007
@@ -0,0 +1,91 @@
+use warnings;
+use strict;
+
+=head1 NAME
+
+Jifty::Plugin::Authentication::Password::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::Authentication::Password::Action::ResetLostPassword;
+use base qw/Jifty::Action/;
+
+=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, 
+                label  => _('Password') 
+            },
+            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::Authentication::Password::Model::User";
+        my $CurrentUser = "Jifty::Plugin::Authentication::Password::CurrentUser";
+
+
+    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/trunk/lib/Jifty/Plugin/Authentication/Password/Action/SendAccountConfirmation.pm
==============================================================================
--- (empty file)
+++ jifty/trunk/lib/Jifty/Plugin/Authentication/Password/Action/SendAccountConfirmation.pm	Mon Mar 12 23:19:16 2007
@@ -0,0 +1,100 @@
+use warnings;
+use strict;
+
+=head1 NAME
+
+Jifty::Plugin::Authentication::Password::Action::SendAccountConfirmation
+
+=cut
+
+package Jifty::Plugin::Authentication::Password::Action::SendAccountConfirmation;
+use base qw/Jifty::Action/;
+
+__PACKAGE__->mk_accessors(qw(user_object));
+
+=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;
+    my $LoginUser   = Jifty->app_class('Model', 'User');
+        my $CurrentUser   = Jifty->app_class('CurrentUser');
+
+
+
+    $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;
+
+    my $LoginUser   = "Jifty::Plugin::Authentication::Password::Model::User";
+        my $CurrentUser = "Jifty::Plugin::Authentication::Password::CurrentUser";
+
+
+    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::Authentication::Password::Notification::ConfirmAddress->new( to => $self->user_object )->send;
+    return $self->result->message(_("Confirmation resent."));
+}
+
+1;

Added: jifty/trunk/lib/Jifty/Plugin/Authentication/Password/Action/SendPasswordReminder.pm
==============================================================================
--- (empty file)
+++ jifty/trunk/lib/Jifty/Plugin/Authentication/Password/Action/SendPasswordReminder.pm	Mon Mar 12 23:19:16 2007
@@ -0,0 +1,99 @@
+use warnings;
+use strict;
+
+=head1 NAME
+
+Jifty::Plugin::Authentication::Password::Action::SendPasswordReminder
+
+=cut
+
+package Jifty::Plugin::Authentication::Password::Action::SendPasswordReminder;
+use base qw/Jifty::Action/;
+
+
+__PACKAGE__->mk_accessors(qw(user_object));
+
+=head2 arguments
+
+The field for C<SendLostPasswordReminder> is:
+
+=over 4
+
+=item address: the email address
+
+=back
+
+=cut
+
+sub arguments {
+    return (
+        {
+            address => {
+                label     => _('Email'),
+                mandatory => 1,
+            },
+        }
+    );
+
+}
+
+=head2 setup
+
+Create an empty user object to work with
+
+=cut
+
+sub setup {
+    my $self = shift;
+    my $LoginUser   = Jifty->app_class('Model','User');
+        my $CurrentUser = Jifty->app_class('CurrentUser');
+
+
+
+    # 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   = Jifty->app_class('Model','User');
+        my $CurrentUser = Jifty->app_class('CurrentUser');
+        
+
+    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 Reminder email giving a link to a password-reset form.
+
+=cut
+
+sub take_action {
+    my $self = shift;
+    Jifty->app_class('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/trunk/lib/Jifty/Plugin/Authentication/Password/Action/Signup.pm
==============================================================================
--- (empty file)
+++ jifty/trunk/lib/Jifty/Plugin/Authentication/Password/Action/Signup.pm	Mon Mar 12 23:19:16 2007
@@ -0,0 +1,115 @@
+use warnings;
+use strict;
+
+=head1 NAME
+
+Jifty::Plugin::Authentication::Password::Action::Signup
+
+=cut
+
+package Jifty::Plugin::Authentication::Password::Action::Signup;
+use Jifty::Plugin::Authentication::Password::Action::CreateUser;
+use base qw/Jifty::Plugin::Authentication::Password::Action::CreateUser/;
+
+=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->{'email'}{'mandatory'}        = 1;
+    $args->{'name'}{'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   = Jifty->app_class('Model', 'User');
+    my $CurrentUser   = Jifty->app_class('CurrentUser');
+
+
+    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">log 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   = Jifty->app_class('Model', 'User');
+    my $CurrentUser   = Jifty->app_class('CurrentUser');
+        
+    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 [_1], [_2].", Jifty->config->framework('ApplicationName'), $record->name)
+          . ' ' . _("We've sent a confirmation message to your email box.") );
+
+    return 1;
+}
+
+1;

Added: jifty/trunk/lib/Jifty/Plugin/LetMe/Dispatcher.pm
==============================================================================
--- (empty file)
+++ jifty/trunk/lib/Jifty/Plugin/LetMe/Dispatcher.pm	Mon Mar 12 23:19:16 2007
@@ -0,0 +1,25 @@
+use strict;
+use warnings;
+
+package Jifty::Plugin::LetMe::Dispatcher;
+use Jifty::Dispatcher -base;
+
+## 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;

Modified: jifty/trunk/lib/Jifty/Plugin/User/Model/User.pm
==============================================================================
--- jifty/trunk/lib/Jifty/Plugin/User/Model/User.pm	(original)
+++ jifty/trunk/lib/Jifty/Plugin/User/Model/User.pm	Mon Mar 12 23:19:16 2007
@@ -30,11 +30,72 @@
 use base 'Jifty::DBI::Record::Plugin';
 use Jifty::Plugin::User::Record schema {
     column name => type is 'text', label is 'How should I display your name?';
-    column username => type is 'text';
-};
+    column
+        email => type is 'text',
+        label is 'Email',
+        default is '', is immutable, is distinct;
+    column
+        email_confirmed => label is 'Email address confirmed?',
+        type is 'boolean', render_as 'Unrendered', is immutable;
 
+};
 
 # Your model-specific methods go here.
 
+
+
+=head2 set_email ADDRESS
+
+Whenever a user's email is set to a new value, we need to make 
+sure they reconfirm it.
+
+=cut
+
+{
+    no warnings 'redefine';
+
+sub set_email {
+    my $self  = shift;
+    my $new_address = shift;
+    my $email = $self->__value('email');
+
+    my @ret = $self->_set( column => 'email', value => $new_address);
+
+    unless ( $email eq $self->__value('email') ) {
+        $self->__set( column => 'email_confirmed', value => '0' );
+        Jifty->app_class('Notification','ConfirmAddress')->new( to => $self )->send;
+    }
+
+    return (@ret);
+}
+
+}
+
+=head2 validate_email
+
+Makes sure that the email address looks like an email address and is
+not taken.
+
+=cut
+
+sub validate_email {
+    my $self      = shift;
+    my $new_email = shift;
+    
+    return ( 0, "That $new_email doesn't look like an email address." )
+        if $new_email !~ /\S\@\S/;
+    
+    my $temp_user = Jifty->app_class('Model','User')->new( current_user => Jifty->app_class('CurrentUser')->superuser );
+    $temp_user->load_by_cols( 'email' => $new_email );
+    
+    # It's ok if *we* have the address we're looking for
+    return ( 0, q{It looks like somebody else is using that address. Is there a chance you have another account?} )
+        if $temp_user->id && ( !$self->id || $temp_user->id != $self->id );
+    
+    return 1;
+}
+
+
+
 1;
 

Modified: jifty/trunk/t/TestApp-Plugin-PasswordAuth/lib/TestApp/Plugin/PasswordAuth/Bootstrap.pm
==============================================================================
--- jifty/trunk/t/TestApp-Plugin-PasswordAuth/lib/TestApp/Plugin/PasswordAuth/Bootstrap.pm	(original)
+++ jifty/trunk/t/TestApp-Plugin-PasswordAuth/lib/TestApp/Plugin/PasswordAuth/Bootstrap.pm	Mon Mar 12 23:19:16 2007
@@ -11,7 +11,7 @@
     my $user = TestApp::Plugin::PasswordAuth::Model::User->new(
         current_user => $curuser );
     my ( $val, $msg ) = $user->create(
-        username     => 'gooduser at example.com',
+        email     => 'gooduser at example.com',
         color        => 'gray',
         swallow_type => 'african',
         password     => 'secret'

Modified: jifty/trunk/t/TestApp-Plugin-PasswordAuth/t/00-model-User.t
==============================================================================
--- jifty/trunk/t/TestApp-Plugin-PasswordAuth/t/00-model-User.t	(original)
+++ jifty/trunk/t/TestApp-Plugin-PasswordAuth/t/00-model-User.t	Mon Mar 12 23:19:16 2007
@@ -22,7 +22,7 @@
 # Try testing a create
 my $o = TestApp::Plugin::PasswordAuth::Model::User->new(current_user => $system_user);
 my ($id) = $o->create( name => 'jesse',
-                       username => 'jrv',
+                       email => 'jrv',
                        color => 'gray',
                        swallow_type => 'african',
                        password => 'secret');
@@ -42,7 +42,7 @@
 
 my $p = TestApp::Plugin::PasswordAuth::Model::User->new(current_user => $system_user);
  ($id) = $p->create( name => 'jesse2',
-                       username => 'jrv2',
+                       email => 'jrv2',
                        color => 'blue',
                        swallow_type => 'african',
                        password => 'secret');
@@ -50,7 +50,7 @@
 
 my $q = TestApp::Plugin::PasswordAuth::Model::User->new(current_user => $system_user);
 ($id) = $p->create( name => 'jesse2',
-                       username => 'jrv2',
+                       email => 'jrv2',
                        color => 'gray',
                        swallow_type => 'european',
                        password => 'secret');
@@ -58,7 +58,7 @@
 
 my $r = TestApp::Plugin::PasswordAuth::Model::User->new(current_user => $system_user);
  ($id) = $r->create( name => 'jesse2',
-                       username => 'jrv2',
+                       email => 'jrv2',
                        color => 'grey',
                        swallow_type => 'african',
                        password => 'secret');

Modified: jifty/trunk/t/TestApp-Plugin-PasswordAuth/t/01-tokengen.t
==============================================================================
--- jifty/trunk/t/TestApp-Plugin-PasswordAuth/t/01-tokengen.t	(original)
+++ jifty/trunk/t/TestApp-Plugin-PasswordAuth/t/01-tokengen.t	Mon Mar 12 23:19:16 2007
@@ -26,7 +26,7 @@
 
 # {{{ Get token for logging in with a JS-based md5-hashed password
 my $service='/__jifty/webservices/yaml';
-my $service_request ="$URL$service?J:A-moniker=GeneratePasswordToken&J:A:F-username-moniker=gooduser\@example.com"; 
+my $service_request ="$URL$service?J:A-moniker=GeneratePasswordToken&J:A:F-email-moniker=gooduser\@example.com"; 
 $mech->get_ok($service_request, "Token-generating webservice $service_request exists");
 
 # XXX needs to be more precise in checking for the token, but this works


More information about the Jifty-commit mailing list