diff options
Diffstat (limited to 'lib/Reaction/InterfaceModel/Action/User')
5 files changed, 288 insertions, 0 deletions
diff --git a/lib/Reaction/InterfaceModel/Action/User/ChangePassword.pm b/lib/Reaction/InterfaceModel/Action/User/ChangePassword.pm new file mode 100644 index 0000000..fc8ff88 --- /dev/null +++ b/lib/Reaction/InterfaceModel/Action/User/ChangePassword.pm @@ -0,0 +1,63 @@ +package Reaction::InterfaceModel::Action::User::ChangePassword; + +use Reaction::Class; + +class ChangePassword is 'Reaction::InterfaceModel::Action::User::SetPassword', which { + has old_password => (isa => 'Password', is => 'rw', lazy_fail => 1); + + around error_for_attribute => sub { + my $super = shift; + my ($self, $attr) = @_; + if ($attr->name eq 'old_password') { + return "Old password incorrect" + unless $self->verify_old_password; + } + #return $super->(@_); #commented out because the original didn't super() + }; + + around can_apply => sub { + my $super = shift; + my ($self) = @_; + return 0 unless $self->verify_old_password; + return $super->(@_); + }; + + implements verify_old_password => as { + my $self = shift; + return unless $self->has_old_password; + + my $user = $self->target_model; + return $user->can("check_password") ? + $user->check_password($self->old_password) : + $self->old_password eq $user->password; + }; + +}; + +1; + +=head1 NAME + +Reaction::InterfaceModel::Action::User::ChangePassword + +=head1 DESCRIPTION + +=head1 METHODS + +=head2 old_password + +=head2 verify_old_password + +=head1 SEE ALSO + +L<Reaction::InterfaceModel::Action::DBIC::User::ChangePassword> + +=head1 AUTHORS + +See L<Reaction::Class> for authors. + +=head1 LICENSE + +See L<Reaction::Class> for the license. + +=cut diff --git a/lib/Reaction/InterfaceModel/Action/User/Login.pm b/lib/Reaction/InterfaceModel/Action/User/Login.pm new file mode 100644 index 0000000..781ec0f --- /dev/null +++ b/lib/Reaction/InterfaceModel/Action/User/Login.pm @@ -0,0 +1,49 @@ +package Reaction::InterfaceModel::Action::User::Login; + +use Reaction::Class; +use aliased 'Reaction::InterfaceModel::Action'; + +class Login, is Action, which { + + has 'username' => (isa => 'SimpleStr', is => 'rw', lazy_fail => 1); + has 'password' => (isa => 'Password', is => 'rw', lazy_fail => 1); + + around error_for_attribute => sub { + my $super = shift; + my ($self, $attr) = @_; + my $result = $super->(@_); + my $predicate = $attr->predicate; + if (defined $result && $self->$predicate) { + return 'Invalid username or password'; + } + return; + }; + + implements do_apply => as { + my $self = shift; + my $target = $self->target_model; + return $target->login($self->username, $self->password); + }; +}; + +1; + +=head1 NAME + +Reaction::InterfaceModel::Action::User::Login + +=head1 DESCRIPTION + +=head2 username + +=head2 password + +=head1 AUTHORS + +See L<Reaction::Class> for authors. + +=head1 LICENSE + +See L<Reaction::Class> for the license. + +=cut diff --git a/lib/Reaction/InterfaceModel/Action/User/ResetPassword.pm b/lib/Reaction/InterfaceModel/Action/User/ResetPassword.pm new file mode 100644 index 0000000..3ef645d --- /dev/null +++ b/lib/Reaction/InterfaceModel/Action/User/ResetPassword.pm @@ -0,0 +1,63 @@ +package Reaction::InterfaceModel::Action::User::ResetPassword; + +use Reaction::Class; +use Digest::MD5; + +use aliased + 'Reaction::InterfaceModel::Action::User::Role::ConfirmationCodeSupport'; +use aliased 'Reaction::InterfaceModel::Action::User::SetPassword'; + +class ResetPassword is SetPassword, which { + + does ConfirmationCodeSupport; + + has confirmation_code => + (isa => 'NonEmptySimpleStr', is => 'rw', lazy_fail => 1); + + around error_for_attribute => sub { + my $super = shift; + my ($self, $attr) = @_; + if ($attr->name eq 'confirmation_code') { + return "Confirmation code incorrect" + unless $self->verify_confirmation_code; + } + #return $super->(@_); #commented out because the original didn't super() + }; + + implements verify_confirmation_code => as { + my $self = shift; + return $self->has_confirmation_code + && ($self->confirmation_code eq $self->generate_confirmation_code); + }; + +}; + +1; + +=head1 NAME + +Reaction::InterfaceModel::Action::User::ResetPassword + +=head1 DESCRIPTION + +=head2 error_for_attribute + +=head2 confirmation_code + +=head2 verify_confirmation_code + +=head1 SEE ALSO + +L<Reaction::InterfaceModel::Action::DBIC::User::ResetPassword> + +L<Reaction::InterfaceModel::Action::User::Role::ConfirmationCodeSupport> + +=head1 AUTHORS + +See L<Reaction::Class> for authors. + +=head1 LICENSE + +See L<Reaction::Class> for the license. + +=cut diff --git a/lib/Reaction/InterfaceModel/Action/User/Role/ConfirmationCodeSupport.pm b/lib/Reaction/InterfaceModel/Action/User/Role/ConfirmationCodeSupport.pm new file mode 100644 index 0000000..649f76a --- /dev/null +++ b/lib/Reaction/InterfaceModel/Action/User/Role/ConfirmationCodeSupport.pm @@ -0,0 +1,44 @@ +package Reaction::InterfaceModel::Action::User::Role::ConfirmationCodeSupport; + +use Reaction::Role; +use Digest::MD5; + +role ConfirmationCodeSupport, which{ + + #requires qw/target_model ctx/; + + implements generate_confirmation_code => as { + my $self = shift; + my $ident = $self->target_model->identity_string. + $self->target_model->password; + my $secret = $self->ctx->config->{confirmation_code_secret}; + die "Application config does not define confirmation_code_secret" + unless $secret; + return Digest::MD5::md5_hex($secret.$ident); + }; + +}; + +1; + +=head1 NAME + +Reaction::InterfaceModel::Action::User::Role::ConfirmationCodeSupport + +=head1 DESCRIPTION + +=head2 generate_confirmation_code + +=head2 meta + +Need to define confirmation_code_secret in application config. + +=head1 AUTHORS + +See L<Reaction::Class> for authors. + +=head1 LICENSE + +See L<Reaction::Class> for the license. + +=cut diff --git a/lib/Reaction/InterfaceModel/Action/User/SetPassword.pm b/lib/Reaction/InterfaceModel/Action/User/SetPassword.pm new file mode 100644 index 0000000..fcf922a --- /dev/null +++ b/lib/Reaction/InterfaceModel/Action/User/SetPassword.pm @@ -0,0 +1,69 @@ +package Reaction::InterfaceModel::Action::User::SetPassword; + +use Reaction::Class; +use Reaction::InterfaceModel::Action; + +class SetPassword is 'Reaction::InterfaceModel::Action', which { + + has new_password => (isa => 'Password', is => 'rw', lazy_fail => 1); + has confirm_new_password => + (isa => 'Password', is => 'rw', lazy_fail => 1); + + around error_for_attribute => sub { + my $super = shift; + my ($self, $attr) = @_; + if ($attr->name eq 'confirm_new_password') { + return "New password doesn't match" + unless $self->verify_confirm_new_password; + } + return $super->(@_); + }; + + around can_apply => sub { + my $super = shift; + my ($self) = @_; + return 0 unless $self->verify_confirm_new_password; + return $super->(@_); + }; + + implements verify_confirm_new_password => as { + my $self = shift; + return $self->has_new_password && $self->has_confirm_new_password + && ($self->new_password eq $self->confirm_new_password); + }; + +}; + +1; + +=head1 NAME + +Reaction::InterfaceModel::Action::User::SetPassword + +=head1 DESCRIPTION + +=head1 ATTRIBUTES + +=head2 new_password + +=head2 confirm_new_password + +=head1 METHODS + +=head2 verify_confirm_new_password + +Tests to make sure that C<new_password> and C<confirm_new_password> match. + +=head1 SEE ALSO + +L<Reaction::InterfaceModel::Action::DBIC::User::SetPassword> + +=head1 AUTHORS + +See L<Reaction::Class> for authors. + +=head1 LICENSE + +See L<Reaction::Class> for the license. + +=cut |