webgui/lib/WebGUI/Auth/WebGUI.pm
Colin Kuskie 21c4fcb75f This patch adds user invitations, a way for existing users on a site
to send an email to their friends and invite them to create an account
on the site.  The feature is enabled or disabled in the site Settings.
(Operation/Settings.pm)

It is implemented as a new operation, Invite (Operation/Invite.pm,
Help/Invite.pm, i18n/English/Invite.pm), and the option is displayed
as an option on the user's account screen. (Operation/Shared.pm).
The form is templated, and lives in the Invite namespace.  Once
the invitation is submitted, if the user's email address is not
already in WebGUI, an email is sent and a record is stored in
the userInvitations table.

When the friend gets the invitation, they are taken to the account
creation screen, which conveniently has their email address already
filled in.  This required changes in the Auth modules (Auth.pm, Auth/*.pm),
and ProfileField.pm.  The latter was so that profile fields can have
their values manually set.  The former changes handle inserting the
email address, bypassing the anonymous registration check, and
updating the record in ther userInvitations table.

I refactored some code out of the AdminConsole for finding the url
back to the site and added it to Session/Url.pm.  The method is
called getBackToSiteUrl.
2007-06-10 16:38:43 +00:00

845 lines
34 KiB
Perl

package WebGUI::Auth::WebGUI;
#-------------------------------------------------------------------
# WebGUI is Copyright 2001-2006 Plain Black Corporation.
#-------------------------------------------------------------------
# Please read the legal notices (docs/legal.txt) and the license
# (docs/license.txt) that came with this distribution before using
# this software.
#-------------------------------------------------------------------
# http://www.plainblack.com info@plainblack.com
#-------------------------------------------------------------------
use Digest::MD5;
use strict;
use URI;
use WebGUI::Asset::Template;
use WebGUI::Auth;
use WebGUI::HTMLForm;
use WebGUI::Macro;
use WebGUI::Mail::Send;
use WebGUI::Storage::Image;
use WebGUI::User;
use WebGUI::Utility;
our @ISA = qw(WebGUI::Auth);
#-------------------------------------------------------------------
sub _hasNonWordCharacters {
my $self = shift;
my $password = shift;
my $numberRequired = shift;
return ($password =~ tr/A-Za-z0-9_//c) >= $numberRequired;
}
#-------------------------------------------------------------------
sub _hasNumberCharacters {
my $self = shift;
my $password = shift;
my $numberRequired = shift;
return ($password =~ tr/0-9//) >= $numberRequired;
}
#-------------------------------------------------------------------
sub _hasMixedCaseCharacters {
my $self = shift;
my $password = shift;
my $numberRequired = shift;
return $password =~ tr/a-z// && ($password =~ tr/A-Z//) >= $numberRequired;
}
#-------------------------------------------------------------------
=head2 _isValidPassword ( )
Validates the password.
=cut
sub _isValidPassword {
my $self = shift;
my $password = shift;
WebGUI::Macro::negate(\$password);
my $confirm = shift;
WebGUI::Macro::negate(\$confirm);
my $error = "";
my $i18n = WebGUI::International->new($self->session,'AuthWebGUI');
if ($password ne $confirm) {
$error .= '<li>'.$i18n->get(3).'</li>';
}
if ($password eq "") {
$error .= '<li>'.$i18n->get(4).'</li>';
}
if ($self->getSetting("passwordLength") && length($password) < $self->getSetting("passwordLength")){
$error .= '<li>'.$i18n->get(7)." ".$self->getSetting("passwordLength").'</li>';
}
if ($self->getSetting("requiredDigits") && !$self->_hasNumberCharacters($password, $self->getSetting("requiredDigits"))) {
$error .= '<li>'.sprintf($i18n->echo("Password must conatain at least %s numeric characters."), $self->getSetting("requiredDigits")).'</li>';
}
if ($self->getSetting("nonWordCharacters") && !$self->_hasNonWordCharacters($password, $self->getSetting("nonWordCharacters"))) {
$error .= '<li>'.sprintf($i18n->echo("Password must contain at least %s non-word characters such as , ! @ etc."), $self->getSetting("nonWordCharacters")).'</li>';
}
if ($self->getSetting("requiredMixedCase") && !$self->_hasMixedCaseCharacters($password, $self->getSetting("requiredMixedCase"))) {
$error .= '<li>'.sprintf($i18n->echo("Password must contain at least %s upper case characters and at least one lowercase character (mixed case)."), $self->getSetting("requiredMixedCase")).'</li>';
}
$self->error($error);
return $error eq "";
}
#-------------------------------------------------------------------
=head2 _logSecurityMessage ( )
Logs the successful password change message.
=cut
sub _logSecurityMessage {
my $self = shift;
$self->session->errorHandler->security("change password. Password changed successfully");
}
#-------------------------------------------------------------------
sub authenticate {
my $self = shift;
my ($identifier, $userData, $auth);
$auth = $self->SUPER::authenticate($_[0]);
return 0 if !$auth;
$identifier = $_[1];
$userData = $self->getParams;
if ((Digest::MD5::md5_base64($identifier) eq $$userData{identifier}) && ($identifier ne "")) {
return 1;
}
$self->user(WebGUI::User->new($self->session,1));
my $i18n = WebGUI::International->new($self->session);
$self->error($i18n->get(68));
return 0;
}
#-------------------------------------------------------------------
sub createAccount {
my $self = shift;
my $message = shift;
my $confirm = shift || $self->session->form->process("confirm");
my $vars = shift || {};
$self->session->errorHandler->warn('WebGUI::Auth::createAccount called');
if ($self->session->user->userId ne "1") {
return $self->displayAccount;
}
elsif (!$self->session->setting->get("anonymousRegistration") && !$self->session->setting->get('userInvitationsEnabled')) {
return $self->displayLogin;
}
my $i18n = WebGUI::International->new($self->session);
$vars->{'create.message'} = $message if ($message);
$vars->{useCaptcha} = $self->session->setting->get("webguiUseCaptcha");
if ($vars->{useCaptcha}) {
use WebGUI::Form::Captcha;
my $captcha = WebGUI::Form::Captcha->new($self->session,{"name"=>"authWebGUI.captcha"});
$vars->{'create.form.captcha'} = $captcha->toHtml.'<span class="formSubtext">'.$captcha->get('subtext').'</span>';
$vars->{'create.form.captcha.label'} = $i18n->get("captcha label","AuthWebGUI");
}
$vars->{'create.form.username'} = WebGUI::Form::text($self->session,{"name"=>"authWebGUI.username","value"=>$self->session->form->process("authWebGUI.username")});
$vars->{'create.form.username.label'} = $i18n->get(50);
$vars->{'create.form.password'} = WebGUI::Form::password($self->session,{"name"=>"authWebGUI.identifier"});
$vars->{'create.form.password.label'} = $i18n->get(51);
$vars->{'create.form.passwordConfirm'} = WebGUI::Form::password($self->session,{"name"=>"authWebGUI.identifierConfirm"});
$vars->{'create.form.passwordConfirm.label'} = $i18n->get(2,'AuthWebGUI');
$vars->{'create.form.hidden'} = WebGUI::Form::hidden($self->session,{"name"=>"confirm","value"=>$confirm});
$vars->{'recoverPassword.isAllowed'} = $self->getSetting("passwordRecovery");
$vars->{'recoverPassword.url'} = $self->session->url->page('op=auth;method=recoverPassword');
$vars->{'recoverPassword.label'} = $i18n->get(59);
return $self->SUPER::createAccount("createAccountSave",$vars);
}
#-------------------------------------------------------------------
sub createAccountSave {
my $self = shift;
my $i18n = WebGUI::International->new($self->session);
return $self->displayAccount if ($self->session->user->userId ne "1");
#Make sure anonymous registration is enabled
unless ($self->session->setting->get("anonymousRegistration") || $self->session->setting->get("userInvitationsEnabled")) {
$self->session->errorHandler->security($i18n->get("no registration hack", "AuthWebGUI"));
return $self->displayLogin;
}
my $username = $self->session->form->process('authWebGUI.username');
my $password = $self->session->form->process('authWebGUI.identifier');
my $passConfirm = $self->session->form->process('authWebGUI.identifierConfirm');
my $error;
$error = $self->error unless($self->validUsername($username));
if ($self->session->setting->get("webguiUseCaptcha")) {
unless ($self->session->form->process('authWebGUI.captcha', "Captcha")) {
$error .= $i18n->get("captcha failure","AuthWebGUI");
}
}
$error .= $self->error unless($self->_isValidPassword($password,$passConfirm));
my ($profile, $temp, $warning) = WebGUI::Operation::Profile::validateProfileData($self->session);
$error .= $temp;
return $self->createAccount($error) unless ($error eq "");
# If Email address is not unique, a warning is displayed
if ($warning ne "" && !$self->session->form->process("confirm")) {
return $self->createAccount('<li>'.$i18n->get(1078).'</li>', 1);
}
my $properties;
$properties->{changeUsername} = $self->session->setting->get("webguiChangeUsername");
$properties->{changePassword} = $self->session->setting->get("webguiChangePassword");
$properties->{identifier} = Digest::MD5::md5_base64($password);
$properties->{passwordLastUpdated} =$self->session->datetime->time();
$properties->{passwordTimeout} = $self->session->setting->get("webguiPasswordTimeout");
$properties->{status} = 'Deactivated' if ($self->session->setting->get("webguiValidateEmail"));
$self->SUPER::createAccountSave($username,$properties,$password,$profile);
if ($self->session->setting->get("webguiValidateEmail")) {
my $key = $self->session->id->generate();
$self->saveParams($self->userId,"WebGUI",{emailValidationKey=>$key});
my $mail = WebGUI::Mail::Send->create($self->session,{
to=>$profile->{email},
subject=>$i18n->get('email address validation email subject','AuthWebGUI')
});
$mail->addText($i18n->get('email address validation email body','AuthWebGUI')."\n\n".$self->session->url->getSiteURL().$self->session->url->page("op=auth;method=validateEmail;key=".$key));
$mail->addFooter;
$mail->send;
$self->user->status("Deactivated");
$self->session->var->end($self->session->var->get("sessionId"));
$self->session->var->start(1,$self->session->getId);
my $u = WebGUI::User->new($self->session,1);
$self->{user} = $u;
$self->logout;
return $self->displayLogin($i18n->get('check email for validation','AuthWebGUI'));
}
return undef;
}
#-------------------------------------------------------------------
sub deactivateAccount {
my $self = shift;
return $self->displayLogin if($self->userId eq '1');
return $self->SUPER::deactivateAccount("deactivateAccountConfirm");
}
#-------------------------------------------------------------------
sub deactivateAccountConfirm {
my $self = shift;
return $self->displayLogin unless ($self->session->setting->get("selfDeactivation"));
return $self->SUPER::deactivateAccountConfirm;
}
#-------------------------------------------------------------------
sub displayAccount {
my $self = shift;
my $vars;
return $self->displayLogin($_[0]) if ($self->userId eq '1');
my $i18n = WebGUI::International->new($self->session);
my $userData = $self->getParams;
$vars->{'account.message'} = $_[0] if ($_[0]);
$vars->{'account.noform'} = 1;
if($userData->{changeUsername} || (!defined $userData->{changeUsername} && $self->session->setting->get("webguiChangeUsername"))){
$vars->{'account.form.username'} = WebGUI::Form::text($self->session,{"name"=>"authWebGUI.username","value"=>$self->username});
$vars->{'account.form.username.label'} = $i18n->get(50);
$vars->{'account.noform'} = 0;
}
if($userData->{changePassword} || (!defined $userData->{changePassword} && $self->session->setting->get("webguiChangePassword"))){
$vars->{'account.form.password'} = WebGUI::Form::password($self->session,{"name"=>"authWebGUI.identifier","value"=>"password"});
$vars->{'account.form.password.label'} = $i18n->get(51);
$vars->{'account.form.passwordConfirm'} = WebGUI::Form::password($self->session,{"name"=>"authWebGUI.identifierConfirm","value"=>"password"});
$vars->{'account.form.passwordConfirm.label'} = $i18n->get(2,'AuthWebGUI');
$vars->{'account.noform'} = 0;
}
$vars->{'account.nofields'} = $i18n->get(22,'AuthWebGUI');
return $self->SUPER::displayAccount("updateAccount",$vars);
}
#-------------------------------------------------------------------
=head2 displayLogin ( )
The initial login screen an unauthenticated user sees
=cut
sub displayLogin {
my $self = shift;
my $vars;
return $self->displayAccount($_[0]) if ($self->userId ne "1");
my $i18n = WebGUI::International->new($self->session);
$vars->{'login.message'} = $_[0] if ($_[0]);
$vars->{'recoverPassword.isAllowed'} = $self->getSetting("passwordRecovery");
$vars->{'recoverPassword.url'} = $self->session->url->page('op=auth;method=recoverPassword');
$vars->{'recoverPassword.label'} = $i18n->get(59);
return $self->SUPER::displayLogin("login",$vars);
}
#-------------------------------------------------------------------
=head2 editUserForm ( )
Creates user form elements specific to this Auth Method.
=cut
sub editUserForm {
my $self = shift;
my $userData = $self->getParams;
my $f = WebGUI::HTMLForm->new($self->session);
my $i18n = WebGUI::International->new($self->session);
$f->password(
name=>"authWebGUI.identifier",
label=>$i18n->get(51),
value=>"password"
);
$f->interval(
-name=>"authWebGUI.passwordTimeout",
-label=>$i18n->get(16,'AuthWebGUI'),
-value=>$userData->{passwordTimeout},
-defaultValue=>$self->session->setting->get("webguiPasswordTimeout")
);
my $userChange = $self->session->setting->get("webguiChangeUsername");
if($userChange || $userChange eq "0"){
$userChange = $userData->{changeUsername};
}
$f->yesNo(
-name=>"authWebGUI.changeUsername",
-value=>$userChange,
-label=>$i18n->get(21,'AuthWebGUI')
);
my $passwordChange = $self->session->setting->get("webguiChangePassword");
if($passwordChange || $passwordChange eq "0"){
$passwordChange = $userData->{changePassword};
}
$f->yesNo(
-name=>"authWebGUI.changePassword",
-value=>$passwordChange,
-label=>$i18n->get(20,'AuthWebGUI')
);
return $f->printRowsOnly;
}
#-------------------------------------------------------------------
=head2 editUserFormSave ( )
Saves user elements unique to this authentication method
=cut
sub editUserFormSave {
my $self = shift;
my $userId = $self->session->form->get("uid");
my $properties;
my $userData = $self->getParams($userId);
my $identifier = $self->session->form->process('authWebGUI.identifier');
unless (!$identifier || $identifier eq "password") {
$properties->{identifier} = Digest::MD5::md5_base64($self->session->form->process('authWebGUI.identifier'));
if($userData->{identifier} ne $properties->{identifier}){
$properties->{passwordLastUpdated} =$self->session->datetime->time();
}
}
$properties->{passwordTimeout} = $self->session->form->interval('authWebGUI.passwordTimeout');
$properties->{changeUsername} = $self->session->form->process('authWebGUI.changeUsername');
$properties->{changePassword} = $self->session->form->process('authWebGUI.changePassword');
if($userId eq "new") {
$properties->{passwordLastUpdated} =$self->session->datetime->time();
if ($self->session->setting->get("webguiExpirePasswordOnCreation")){
$properties->{passwordLastUpdated} =$self->session->datetime->time() - $properties->{passwordTimeout};
}
}
$self->SUPER::editUserFormSave($properties);
}
#-------------------------------------------------------------------
=head2 editUserSettingsForm ( )
Creates form elements for user settings page custom to this auth module
=cut
sub editUserSettingsForm {
my $self = shift;
my $i18n = WebGUI::International->new($self->session,'AuthWebGUI');
my $f = WebGUI::HTMLForm->new($self->session);
$f->integer(
-name=>"webguiPasswordLength",
-value=>$self->session->setting->get("webguiPasswordLength"),
-label=>$i18n->get(15),
);
$f->integer(
-name => "webguiRequiredDigits",
-label => $i18n->echo("Number of digits required in password"),
-value => $self->session->setting->get("webguiRequiredDigits")
);
$f->integer(
-name => "webguiNonWordCharacters",
-label => $i18n->echo("Number of non-word characters required in password"),
-value => $self->session->setting->get("webguiNonWordCharacters")
);
$f->integer(
-name => "webguiRequiredMixedCase",
-label => $i18n->echo("Number of upper case case characters required in password"),
-value => $self->session->setting->get("webguiRequiredMixedCase")
);
$f->interval(
-name=>"webguiPasswordTimeout",
-label=>$i18n->get(16),
-value=>$self->session->setting->get("webguiPasswordTimeout")
);
$f->yesNo(
-name=>"webguiExpirePasswordOnCreation",
-value=>$self->session->setting->get("webguiExpirePasswordOnCreation"),
-label=>$i18n->get(9)
);
$f->yesNo(
-name=>"webguiSendWelcomeMessage",
-value=>$self->session->setting->get("webguiSendWelcomeMessage"),
-label=>$i18n->get(868,'WebGUI')
);
$f->textarea(
-name=>"webguiWelcomeMessage",
-value=>$self->session->setting->get("webguiWelcomeMessage"),
-label=>$i18n->get(869,'WebGUI')
);
$f->yesNo(
-name=>"webguiChangeUsername",
-value=>$self->session->setting->get("webguiChangeUsername"),
-label=>$i18n->get(19)
);
$f->yesNo(
-name=>"webguiChangePassword",
-value=>$self->session->setting->get("webguiChangePassword"),
-label=>$i18n->get(18)
);
$f->yesNo(
-name => "webguiPasswordRecovery",
-value => $self->session->setting->get("webguiPasswordRecovery"),
-label => $i18n->get(6),
-hoverHelp => $i18n->get('webguiPasswordRecovery hoverHelp')
);
$f->yesNo(
-name => "webguiPasswordRecoveryRequireUsername",
-value => $self->session->setting->get("webguiPasswordRecoveryRequireUsername"),
-label => $i18n->get('require username for password recovery'),
-hoverHelp => $i18n->get('webguiPasswordRecoveryRequireUsername hoverHelp')
);
$f->yesNo(
-name=>"webguiValidateEmail",
-value=>$self->session->setting->get("webguiValidateEmail"),
-label=>$i18n->get('validate email')
);
$f->yesNo(
-name=>"webguiUseCaptcha",
-value=>$self->session->setting->get("webguiUseCaptcha"),
-label=>$i18n->get('use captcha')
);
$f->template(
-name=>"webguiAccountTemplate",
-value=>$self->session->setting->get("webguiAccountTemplate"),
-namespace=>"Auth/WebGUI/Account",
-label=>$i18n->get("account template")
);
$f->template(
-name=>"webguiCreateAccountTemplate",
-value=>$self->session->setting->get("webguiCreateAccountTemplate"),
-namespace=>"Auth/WebGUI/Create",
-label=>$i18n->get("create account template")
);
$f->template(
-name=>"webguiExpiredPasswordTemplate",
-value=>$self->session->setting->get("webguiExpiredPasswordTemplate"),
-namespace=>"Auth/WebGUI/Expired",
-label=>$i18n->get("expired password template")
);
$f->template(
-name=>"webguiLoginTemplate",
-value=>$self->session->setting->get("webguiLoginTemplate"),
-namespace=>"Auth/WebGUI/Login",
-label=>$i18n->get("login template")
);
$f->template(
-name=>"webguiPasswordRecoveryTemplate",
-value=>$self->session->setting->get("webguiPasswordRecoveryTemplate"),
-namespace=>"Auth/WebGUI/Recovery2",
-label=>$i18n->get("password recovery template")
);
return $f->printRowsOnly;
}
#-------------------------------------------------------------------
sub editUserSettingsFormSave {
my $self = shift;
my $f = $self->session->form;
my $s = $self->session->setting;
$s->set("webguiPasswordLength", $f->process("webguiPasswordLength","integer"));
$s->set("webguiRequiredDigits", $f->process("webguiRequiredDigits","integer"));
$s->set("webguiNonWordCharacters", $f->process("webguiNonWordCharacters","integer"));
$s->set("webguiRequiredMixedCase", $f->process("webguiRequiredMixedCase","integer"));
$s->set("webguiPasswordTimeout", $f->process("webguiPasswordTimeout","interval"));
$s->set("webguiExpirePasswordOnCreation", $f->process("webguiExpirePasswordOnCreation","yesNo"));
$s->set("webguiSendWelcomeMessage", $f->process("webguiSendWelcomeMessage","yesNo"));
$s->set("webguiWelcomeMessage", $f->process("webguiWelcomeMessage","textarea"));
$s->set("webguiChangeUsername", $f->process("webguiChangeUsername","yesNo"));
$s->set("webguiChangePassword", $f->process("webguiChangePassword","yesNo"));
# Special case to make sure we have at least one field enabled before allowing
# password recovery to be turned on.
$s->set("webguiPasswordRecovery", $f->process("webguiPasswordRecovery","yesNo") && ($self->session->db->quickArray("SELECT COUNT(*) FROM userProfileField WHERE requiredForPasswordRecovery = 1"))[0] > 0);
$s->set("webguiPasswordRecoveryRequireUsername", $f->process("webguiPasswordRecoveryRequireUsername","yesNo"));
$s->set("webguiValidateEmail", $f->process("webguiValidateEmail","yesNo"));
$s->set("webguiUseCaptcha", $f->process("webguiUseCaptcha","yesNo"));
$s->set("webguiAccountTemplate", $f->process("webguiAccountTemplate","template"));
$s->set("webguiCreateAccountTemplate", $f->process("webguiCreateAccountTemplate","template"));
$s->set("webguiExpiredPasswordTemplate", $f->process("webguiExpiredPasswordTemplate","template"));
$s->set("webguiLoginTemplate", $f->process("webguiLoginTemplate","template"));
$s->set("webguiPasswordRecoveryTemplate", $f->process("webguiPasswordRecoveryTemplate","template"));
}
#-------------------------------------------------------------------
sub getAccountTemplateId {
my $self = shift;
return $self->session->setting->get("webguiAccountTemplate") || "PBtmpl0000000000000010";
}
#-------------------------------------------------------------------
sub getCreateAccountTemplateId {
my $self = shift;
return $self->session->setting->get("webguiCreateAccountTemplate") || "PBtmpl0000000000000011";
}
#-------------------------------------------------------------------
sub getExpiredPasswordTemplateId {
my $self = shift;
return $self->session->setting->get("webguiExpiredPasswordTemplate") || "PBtmpl0000000000000012";
}
#-------------------------------------------------------------------
sub getLoginTemplateId {
my $self = shift;
return $self->session->setting->get("webguiLoginTemplate") || "PBtmpl0000000000000013";
}
#-------------------------------------------------------------------
sub getPasswordRecoveryTemplateId {
my $self = shift;
return $self->session->setting->get("webguiPasswordRecoveryTemplate") || "PBtmpl0000000000000014";
}
#-------------------------------------------------------------------
sub login {
my $self = shift;
if(!$self->authenticate($self->session->form->process("username"),$self->session->form->process("identifier"))){
$self->session->http->setStatus("401","Incorrect Credentials");
$self->session->errorHandler->security("login to account ".$self->session->form->process("username")." with invalid information.");
my $i18n = WebGUI::International->new($self->session);
return $self->displayLogin("<h1>".$i18n->get(70)."</h1>".$self->error);
}
my $userData = $self->getParams;
if($self->getSetting("passwordTimeout") && $userData->{passwordTimeout}){
my $expireTime = $userData->{passwordLastUpdated} + $userData->{passwordTimeout};
if ($self->session->datetime->time() >= $expireTime){
my $userId = $self->userId;
$self->logout;
return $self->resetExpiredPassword($userId);
}
}
return $self->SUPER::login();
}
#-------------------------------------------------------------------
sub new {
my $class = shift;
my $session = shift;
my $authMethod = $_[0];
my $userId = $_[1];
my @callable = ('validateEmail','createAccount','deactivateAccount','displayAccount','displayLogin','login','logout','recoverPassword','resetExpiredPassword','recoverPasswordFinish','createAccountSave','deactivateAccountConfirm','resetExpiredPasswordSave','updateAccount');
my $self = WebGUI::Auth->new($session,$authMethod,$userId,\@callable);
bless $self, $class;
}
#-------------------------------------------------------------------
sub recoverPassword {
my $self = shift;
return $self->displayLogin unless $self->session->setting->get('webguiPasswordRecovery') and $self->userId eq '1';
my @fields = @{WebGUI::ProfileField->getPasswordRecoveryFields($self->session)};
return $self->displayLogin unless @fields;
my $vars = {};
my $i18n = WebGUI::International->new($self->session);
$vars->{title} = $i18n->get(71);
$vars->{'recoverFormHeader'} = "\n\n".WebGUI::Form::formHeader($self->session,{});
$vars->{'recoverFormHidden'} = WebGUI::Form::hidden($self->session,{"name"=>"op","value"=>"auth"});
$vars->{'recoverFormHidden'} .= WebGUI::Form::hidden($self->session,{"name"=>"method","value"=>"recoverPasswordFinish"});
$vars->{'recoverFormSubmit'} = WebGUI::Form::submit($self->session,{});
$vars->{'recoverFormFooter'} = WebGUI::Form::formFooter($self->session,);
$vars->{'loginUrl'} = $self->session->url->page('op=auth;method=init');
$vars->{'loginLabel'} = $i18n->get(58);
$vars->{'anonymousRegistrationIsAllowed'} = ($self->session->setting->get("anonymousRegistration"));
$vars->{'createAccountUrl'} = $self->session->url->page('op=auth;method=createAccount');
$vars->{'createAccountLabel'} = $i18n->get(67);
$vars->{'recoverMessage'} = $_[0] if ($_[0]);
# Semi-duplication with WebGUI::Auth::createAccount. -.-
$vars->{'recoverFormProfile'} = [];
foreach my $field (@fields) {
my ($id, $formField, $label) = ($field->getId, $field->formField, $field->getLabel);
push @{$vars->{'recoverFormProfile'}},
+{ 'id' => $id, 'formElement' => $formField, 'label' => $label };
my $prefix = 'recoverFormProfileField' . ucfirst($id);
$vars->{$prefix.'FormElement'} = $formField;
$vars->{$prefix.'Label'} = $label;
}
if ($self->getSetting('passwordRecoveryRequireUsername')) {
$vars->{'recoverFormUsername'} = WebGUI::Form::text($self->session, {name => 'authWebGUI.username'});
$vars->{'recoverFormUsernameLabel'} = $i18n->get(50);
}
return WebGUI::Asset::Template->new($self->session,$self->getPasswordRecoveryTemplateId)->process($vars);
}
#-------------------------------------------------------------------
sub recoverPasswordFinish {
my $self = shift;
my $i18n = WebGUI::International->new($self->session);
my $i18n2 = WebGUI::International->new($self->session, 'AuthWebGUI');
return $self->displayLogin unless $self->session->setting->get('webguiPasswordRecovery') and $self->userId eq '1';
my $username;
if ($self->getSetting('passwordRecoveryRequireUsername')) {
$username = $self->session->form->process('authWebGUI.username');
return $self->recoverPassword($i18n2->get('password recovery no username')) unless defined $username;
}
my @fields = @{WebGUI::ProfileField->getPasswordRecoveryFields($self->session)};
return $self->displayLogin unless @fields;
my %fieldValues;
my @failedRequiredFields;
foreach my $field (@fields) {
my $value = $field->formProcess;
$fieldValues{$field->getId} = $value;
push @failedRequiredFields, $field unless defined $value;
}
if (@failedRequiredFields) {
my $errorMessage = '<ul>' . join("\n", map {
'<li>' . $_->getLabel . ' ' . $i18n->get(451) . '</li>'
} @failedRequiredFields) . '</ul>';
return $self->recoverPassword($errorMessage);
}
my @fieldNames = keys %fieldValues;
my @fieldValues = values %fieldValues;
my $wheres = join(' ', map{"AND upd.$fieldNames[$_] = ?"} (0..$#fieldNames));
$wheres .= ' AND u.username = ?' if defined $username;
my $sql = "SELECT u.userId FROM users AS u JOIN userProfileData AS upd ON u.userId=upd.userId WHERE u.authMethod = 'WebGUI' $wheres";
my @userIds = $self->session->db->buildArray($sql, [@fieldValues, (defined($username)? ($username) : ())]);
if (@userIds == 0) {
return $self->recoverPassword($i18n2->get('password recovery no results'));
} elsif (@userIds > 1) {
return $self->recoverPassword($i18n2->get('password recovery multiple results'));
}
# Exactly one result.
my $userId = $userIds[0];
my ($password, $passwordConfirm) = ($self->session->form->process('authWebGUI.identifier'), $self->session->form->process('authWebGUI.identifierConfirm'));
unless (defined $password and defined $passwordConfirm) {
my $vars = {};
$vars->{title} = $i18n->get(71);
$vars->{'recoverFormHeader'} = "\n\n" . WebGUI::Form::formHeader($self->session, {});
$vars->{'recoverFormHidden'} =
(WebGUI::Form::hidden($self->session, {name => 'op', value => 'auth'})
. WebGUI::Form::hidden($self->session, {name => 'method', value => 'recoverPasswordFinish'})
. (defined($username)?
WebGUI::Form::hidden($self->session, {name => 'authWebGUI.username',
value => $username}) : '')
. join('', map{WebGUI::Form::hidden($self->session, {name => $_, value => $fieldValues{$_}})}
keys %fieldValues));
$vars->{'recoverFormSubmit'} = WebGUI::Form::submit($self->session, {});
$vars->{'recoverFormFooter'} = WebGUI::Form::formFooter($self->session);
# Duplication with above in recoverPassword.
$vars->{'loginUrl'} = $self->session->url->page('op=auth;method=init');
$vars->{'loginLabel'} = $i18n->get(58);
$vars->{'anonymousRegistrationIsAllowed'} = ($self->session->setting->get("anonymousRegistration"));
$vars->{'createAccountUrl'} = $self->session->url->page('op=auth;method=createAccount');
$vars->{'createAccountLabel'} = $i18n->get(67);
# End duplication.
$vars->{'recoverFormPassword'} = WebGUI::Form::password($self->session, {name => 'authWebGUI.identifier'});
$vars->{'recoverFormPasswordConfirm'} = WebGUI::Form::password($self->session, {name => 'authWebGUI.identifierConfirm'});
$vars->{'recoverFormPasswordLabel'} = $i18n->get(51);
$vars->{'recoverFormPasswordConfirmLabel'} = $i18n2->get(2);
# Mrgh. z.z
$vars->{'doingRecovery'} = 1;
return WebGUI::Asset::Template->new($self->session, $self->getPasswordRecoveryTemplateId)->process($vars);
}
if ($self->_isValidPassword($password, $passwordConfirm)) {
$self->user(WebGUI::User->new($self->session, $userId));
$self->saveParams($userId, $self->authMethod,
{ identifier => Digest::MD5::md5_base64($password),
passwordLastUpdated => $self->session->datetime->time });
$self->_logSecurityMessage;
return $self->SUPER::login;
} else {
return $self->recoverPassword('<ul><li>'.$self->error.'</li></ul>');
}
}
#-------------------------------------------------------------------
sub resetExpiredPassword {
my $self = shift;
my $uid = shift || $self->session->form->process("uid");
my $vars;
my $i18n = WebGUI::International->new($self->session);
$vars->{displayTitle} = '<h3>'.$i18n->get(8,'AuthWebGUI').'</h3>';
$vars->{'expired.message'} = $_[0] if($_[0]);
$vars->{'expired.form.header'} = "\n\n".WebGUI::Form::formHeader($self->session,{});
$vars->{'expired.form.hidden'} = WebGUI::Form::hidden($self->session,{"name"=>"op","value"=>"auth"});
$vars->{'expired.form.hidden'} .= WebGUI::Form::hidden($self->session,{"name"=>"method","value"=>"resetExpiredPasswordSave"});
$vars->{'expired.form.hidden'} .= WebGUI::Form::hidden($self->session,{"name"=>"uid","value"=>$uid});
$vars->{'expired.form.oldPassword'} = WebGUI::Form::password($self->session,{"name"=>"oldPassword"});
$vars->{'expired.form.oldPassword.label'} = $i18n->get(10,'AuthWebGUI');
$vars->{'expired.form.password'} = WebGUI::Form::password($self->session,{"name"=>"identifier"});
$vars->{'expired.form.password.label'} = $i18n->get(11,'AuthWebGUI');
$vars->{'expired.form.passwordConfirm'} = WebGUI::Form::password($self->session,{"name"=>"identifierConfirm"});
$vars->{'expired.form.passwordConfirm.label'} = $i18n->get(2,'AuthWebGUI');
$vars->{'expired.form.submit'} = WebGUI::Form::submit($self->session,{});
$vars->{'expired.form.footer'} = WebGUI::Form::formFooter($self->session,);
return WebGUI::Asset::Template->new($self->session,$self->getExpiredPasswordTemplateId)->process($vars);
}
#-------------------------------------------------------------------
sub resetExpiredPasswordSave {
my $self = shift;
my ($error,$u,$properties,$msg);
$u = WebGUI::User->new($self->session,$self->session->form->process("uid"));
my $i18n = WebGUI::International->new($self->session);
$error .= $self->error if(!$self->authenticate($u->username,$self->session->form->process("oldPassword")));
$error .= '<li>'.$i18n->get(5,'AuthWebGUI').'</li>' if($self->session->form->process("identifier") eq "password");
$error .= '<li>'.$i18n->get(12,'AuthWebGUI').'</li>' if ($self->session->form->process("oldPassword") eq $self->session->form->process("identifier"));
$error .= $self->error if(!$self->_isValidPassword($self->session->form->process("identifier"),$self->session->form->process("identifierConfirm")));
return $self->resetExpiredPassword($u->userId, "<h1>".$i18n->get(70)."</h1>".$error) if($error ne "");
$properties->{identifier} = Digest::MD5::md5_base64($self->session->form->process("identifier"));
$properties->{passwordLastUpdated} =$self->session->datetime->time();
$self->saveParams($u->userId,$self->authMethod,$properties);
$self->_logSecurityMessage();
return $self->SUPER::login();
}
#-------------------------------------------------------------------
sub validateEmail {
my $self = shift;
my ($userId) = $self->session->db->quickArray("select userId from authentication where fieldData=? and fieldName='emailValidationKey' and authMethod='WebGUI'", [$self->session->form->process("key")]);
if (defined $userId) {
my $u = WebGUI::User->new($self->session,$userId);
$u->status("Active");
$self->session->db->write("DELETE FROM authentication WHERE userId = ? AND fieldName = 'emailValidationKey'");
}
return $self->displayLogin;
}
#-------------------------------------------------------------------
=head2 updateAccount ( )
Sets properties to update and passes them to the superclass
=cut
sub updateAccount {
my $self = shift;
my $i18n = WebGUI::International->new($self->session);
my $username = $self->session->form->process('authWebGUI.username');
my $password = $self->session->form->process('authWebGUI.identifier');
my $passConfirm = $self->session->form->process('authWebGUI.identifierConfirm');
my $display = '<li>'.$i18n->get(81).'</li>';
my $error = "";
if($self->userId eq '1'){
return $self->displayLogin;
}
if($username){
if($self->_isDuplicateUsername($username)){
$error .= $self->error;
}
if(!$self->_isValidUsername($username)){
$error .= $self->error;
}
}
if($password){
if(!$self->_isValidPassword($password,$passConfirm)){
$error .= $self->error;
}
}
if($error){
$display = $error;
}
my $properties;
my $u = $self->user;
if(!$error){
if($username){
$u->username($username);
}
if($password){
my $userData = $self->getParams;
unless ($password eq "password") {
$properties->{identifier} = Digest::MD5::md5_base64($password);
$self->_logSecurityMessage();
if($userData->{identifier} ne $properties->{identifier}){
$properties->{passwordLastUpdated} =$self->session->datetime->time();
}
}
}
}
$self->saveParams($u->userId,$self->authMethod,$properties);
$self->session->user(undef,undef,$u);
return $self->displayAccount($display);
}
1;