diff options
-rw-r--r-- | app/frontend/controls/RegistrationForm.php | 26 | ||||
-rw-r--r-- | app/frontend/controls/RegistrationForm.tpl | 185 | ||||
-rw-r--r-- | app/frontend/events/RegistrationEvents.php | 16 | ||||
-rw-r--r-- | app/frontend/facades/UserFacade.php | 47 | ||||
-rw-r--r-- | app/frontend/url/config.xml | 5 |
5 files changed, 209 insertions, 70 deletions
diff --git a/app/frontend/controls/RegistrationForm.php b/app/frontend/controls/RegistrationForm.php index 46494e3..0e6f740 100644 --- a/app/frontend/controls/RegistrationForm.php +++ b/app/frontend/controls/RegistrationForm.php @@ -6,8 +6,25 @@ Prado::using('Application.facades.UserFacade'); class RegistrationForm extends FacadeTemplateControl { + public function onLoad($param) { + parent::onLoad($param); + if ($this->Request['success'] === 'success') { + $this->MV->setActiveView($this->SuccessPanel); + } else { + $this->MV->setActiveView($this->FormPanel); + } + } + public function checkUsername($sender, $param) { - $param->IsValid = $this->getFacade()->checkForUsername($this->Login->SafeText); + $param->IsValid = $this->getFacade()->checkForUsername( + $this->Login->SafeText + ); + } + + public function checkEMail($sender, $param) { + $param->IsValid = $this->getFacade()->checkForEMail( + $this->EMail->SafeText + ); } public function registerUser($sender, $param) { @@ -15,10 +32,13 @@ class RegistrationForm extends FacadeTemplateControl { $this->getFacade()->registerUser( $this->Login->SafeText, $this->Password->Text, - $this->Admin->Checked + $this->EMail->Text ); $this->Response->redirect( - $this->Service->constructUrl(NULL) + $this->Service->constructUrl( + $this->Request->ServiceParameter, + ['success' => 'success'] + ) ); } } diff --git a/app/frontend/controls/RegistrationForm.tpl b/app/frontend/controls/RegistrationForm.tpl index 9defe54..0c7e146 100644 --- a/app/frontend/controls/RegistrationForm.tpl +++ b/app/frontend/controls/RegistrationForm.tpl @@ -1,66 +1,119 @@ -<%[ Username: ]%> -<com:TTextBox ID="Login" - ValidationGroup="SignupGroup" /> -<com:TRequiredFieldValidator - ControlToValidate="Login" - Display="Dynamic" - ValidationGroup="SignupGroup"> - <prop:ErrorMessage><%[ Username cannot be empty ]%></prop:ErrorMessage> -</com:TRequiredFieldValidator> -<com:TRegularExpressionValidator - ControlToValidate="Login" - RegularExpression="[a-zA-Z0-9_]{6,255}" - Display="Dynamic" - ValidationGroup="SignupGroup"> - <prop:ErrorMessage><%[ Username must contain 6-255 characters, all Latin alphanumeric or underscore ]%></prop:ErrorMessage> -</com:TRegularExpressionValidator> -<com:TCustomValidator - ControlToValidate="Login" - OnServerValidate="checkUsername" - Display="Dynamic" - ValidationGroup="SignupGroup"> - <prop:ErrorMessage><%[ Username already exists ]%></prop:ErrorMessage> -</com:TCustomValidator> -<br /> -<%[ Password: ]%> -<com:TTextBox ID="Password" - TextMode="Password" - ValidationGroup="SignupGroup" /> -<com:TRequiredFieldValidator - ControlToValidate="Password" - Display="Dynamic" - ValidationGroup="SignupGroup"> - <prop:ErrorMessage><%[ Password cannot be empty ]%></prop:ErrorMessage> -</com:TRequiredFieldValidator> -<br /> -<%[ Repeat password: ]%> -<com:TTextBox ID="RePassword" - TextMode="Password" - ValidationGroup="SignupGroup" /> -<com:TRequiredFieldValidator - ControlToValidate="RePassword" - Display="Dynamic" - ValidationGroup="SignupGroup"> - <prop:ErrorMessage><%[ Password cannot be empty ]%></prop:ErrorMessage> -</com:TRequiredFieldValidator> -<com:TCompareValidator - ControlToValidate="RePassword" - ControlToCompare="Password" - DataType="String" - Operator="Equal" - Display="Dynamic" - ValidationGroup="SignupGroup"> - <prop:ErrorMessage><%[ Passwords don't match ]%></prop:ErrorMessage> -</com:TCompareValidator> -<br /> -<%[ Admin: ]%> -<com:TCheckBox ID="Admin" - ValidationGroup="SignupGroup" /> -<br /> -<com:TButton - OnCommand="registerUser" - ValidationGroup="SignupGroup"> - <prop:Text><%[ Create ]%></prop:Text> -</com:TButton> -<com:TValidationSummary - ValidationGroup="SignupGroup" /> +<com:TMultiView ID="MV"> + <com:TView ID="FormPanel"> + <%[ Username: ]%> + <com:TTextBox ID="Login" + ValidationGroup="SignupGroup" /> + <com:TRequiredFieldValidator + ControlToValidate="Login" + Display="Dynamic" + ValidationGroup="SignupGroup"> + <prop:ErrorMessage><%[ Username cannot be empty ]%></prop:ErrorMessage> + </com:TRequiredFieldValidator> + <com:TRegularExpressionValidator + ControlToValidate="Login" + RegularExpression="[a-zA-Z0-9_]{6,255}" + Display="Dynamic" + ValidationGroup="SignupGroup"> + <prop:ErrorMessage><%[ Username must contain 6-255 characters, all Latin alphanumeric or underscore ]%></prop:ErrorMessage> + </com:TRegularExpressionValidator> + <com:TCustomValidator + ControlToValidate="Login" + OnServerValidate="checkUsername" + Display="Dynamic" + ValidationGroup="SignupGroup"> + <prop:ErrorMessage><%[ Username already exists ]%></prop:ErrorMessage> + </com:TCustomValidator> + <br /> + <%[ Password: ]%> + <com:TTextBox ID="Password" + TextMode="Password" + ValidationGroup="SignupGroup" /> + <com:TRequiredFieldValidator + ControlToValidate="Password" + Display="Dynamic" + ValidationGroup="SignupGroup"> + <prop:ErrorMessage><%[ Password cannot be empty ]%></prop:ErrorMessage> + </com:TRequiredFieldValidator> + <br /> + <%[ Repeat password: ]%> + <com:TTextBox ID="RePassword" + TextMode="Password" + ValidationGroup="SignupGroup" /> + <com:TRequiredFieldValidator + ControlToValidate="RePassword" + Display="Dynamic" + ValidationGroup="SignupGroup"> + <prop:ErrorMessage><%[ Password cannot be empty ]%></prop:ErrorMessage> + </com:TRequiredFieldValidator> + <com:TCompareValidator + ControlToValidate="RePassword" + ControlToCompare="Password" + DataType="String" + Operator="Equal" + Display="Dynamic" + ValidationGroup="SignupGroup"> + <prop:ErrorMessage><%[ Passwords don't match ]%></prop:ErrorMessage> + </com:TCompareValidator> + <br /> + <%[ E-mail: ]%> + <com:TTextBox ID="EMail" + ValidationGroup="SignupGroup" /> + <com:TRequiredFieldValidator + ControlToValidate="EMail" + Display="Dynamic" + ValidationGroup="SignupGroup"> + <prop:ErrorMessage><%[ E-mail address cannot be empty ]%></prop:ErrorMessage> + </com:TRequiredFieldValidator> + <com:TEmailAddressValidator + ControlToValidate="EMail" + Display="Dynamic" + ValidationGroup="SignupGroup" + CheckMXRecord="false"> + <prop:ErrorMessage><%[ E-mail address is invalid ]%></prop:ErrorMessage> + </com:TEmailAddressValidator> + <com:TCustomValidator + ControlToValidate="EMail" + OnServerValidate="checkEMail" + Display="Dynamic" + ValidationGroup="SignupGroup"> + <prop:ErrorMessage><%[ E-mail already registered ]%></prop:ErrorMessage> + </com:TCustomValidator> + <br /> + <%[ Repeat e-mail: ]%> + <com:TTextBox ID="ReEMail" + ValidationGroup="SignupGroup" /> + <com:TRequiredFieldValidator + ControlToValidate="ReEMail" + Display="Dynamic" + ValidationGroup="SignupGroup"> + <prop:ErrorMessage><%[ E-mail address cannot be empty ]%></prop:ErrorMessage> + </com:TRequiredFieldValidator> + <com:TEmailAddressValidator + ControlToValidate="ReEMail" + Display="Dynamic" + ValidationGroup="SignupGroup" + CheckMXRecord="false"> + <prop:ErrorMessage><%[ E-mail address is invalid ]%></prop:ErrorMessage> + </com:TEmailAddressValidator> + <com:TCompareValidator + ControlToValidate="ReEMail" + ControlToCompare="EMail" + DataType="String" + Operator="Equal" + Display="Dynamic" + ValidationGroup="SignupGroup"> + <prop:ErrorMessage><%[ E-mails don't match ]%></prop:ErrorMessage> + </com:TCompareValidator> + <br /> + <com:TButton + OnCommand="registerUser" + ValidationGroup="SignupGroup"> + <prop:Text><%[ Create ]%></prop:Text> + </com:TButton> + <com:TValidationSummary + ValidationGroup="SignupGroup" /> + </com:TView> + <com:TView ID="SuccessPanel"> + <%[ Registration finished without problems. Please activate your account with the link we've sent you. ]%> + </com:TView> +</com:TMultiView> diff --git a/app/frontend/events/RegistrationEvents.php b/app/frontend/events/RegistrationEvents.php new file mode 100644 index 0000000..21bcff3 --- /dev/null +++ b/app/frontend/events/RegistrationEvents.php @@ -0,0 +1,16 @@ +<?php + +Prado::using('Application.events.EventModule'); +Prado::using('Application.model.User'); +Prado::using('Application.facades.UserFacade'); + +class RegistrationEvents extends EventModule { + + public function onUserRegistered(User $user) { + $facade = UserFacade::getInstance(); + $facade->requestActivation($user); + } + +} + +?> diff --git a/app/frontend/facades/UserFacade.php b/app/frontend/facades/UserFacade.php index 9c1d5d8..96f4923 100644 --- a/app/frontend/facades/UserFacade.php +++ b/app/frontend/facades/UserFacade.php @@ -14,16 +14,29 @@ class UserFacade extends Facade { return User::finder()->findByLogin($login); } + public function findByEMail(string $email) { + return User::finder()->findByEMail($email); + } + public function checkForUsername(string $login) { return !User::finder()->count('login = ?', $login); } - public function registerUser(string $login, string $password, bool $admin) { + public function checkForEMail(string $email) { + return !User::finder()->count('e_mail = ?', $email); + } + + public function registerUser( + string $login, + string $password, + string $email, + bool $admin=FALSE) { $transaction = $this->beginTransaction(); try { $newUser = new User(); $newUser->Login = $login; $newUser->Password = $this->generatePassword($password); + $newUser->EMail = $email; $newUser->IsAdmin = $admin; $newUser->save(); $this->raiseEvent('UserRegistered', $newUser); @@ -55,6 +68,38 @@ class UserFacade extends Facade { return password_verify($password, $dbPassword); } + public function requestActivation(User $user) { + $user->IsActive = FALSE; + $user->ActivationHash = md5(mt_rand()); + $user->save(); + $this->_sendActivationMail($user); + } + + protected function _generateActivationLink($email, $hash) { + $application = Prado::getApplication(); + return $application->Request->getBaseUrl() + . $application->Service->constructUrl( + 'Activate', + ['email' => base64_encode($email), + 'hash' => $hash] + ); + } + + protected function _sendActivationMail(User $user) { + $mailModule = Prado::getApplication()->getModule('mail'); + $mailer = $mailModule->getMailer(); + $template = $mailModule->getTemplate('activation-link'); + $template->link = $this->_generateActivationLink( + $user->EMail, $user->ActivationHash + ); + $mailer->sendTemplate( + $template, + Prado::localize('rcal - account activation'), + $user->EMail, + $user->Login + ); + } + public function activateUser(string $email, string $hash) { $user = $this->findByEMail( base64_decode($email) diff --git a/app/frontend/url/config.xml b/app/frontend/url/config.xml index 71a65f3..1400a1c 100644 --- a/app/frontend/url/config.xml +++ b/app/frontend/url/config.xml @@ -31,6 +31,11 @@ parameters.email="(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?" parameters.hash="[a-f0-9]{32}" /> + <url ServiceParameter="Signup" + UrlFormat="HiddenPath" + pattern="signup/{success}/" + parameters.success="success" /> + <url ServiceParameter="*" UrlFormat="HiddenPath" EnableCustomUrl="false" |