/** * Sets a user's password once they've verified they have access to their email. * * @throws HttpException|Exception * @return null */ public function actionSetPassword() { if (craft()->userSession->isLoggedIn()) { craft()->userSession->logout(); } $code = craft()->request->getRequiredParam('code'); $id = craft()->request->getRequiredParam('id'); $user = craft()->users->getUserByUid($id); if ($user) { $isCodeValid = craft()->users->isVerificationCodeValidForUser($user, $code); } if (!$user || !$isCodeValid) { throw new HttpException('200', Craft::t('Invalid verification code.')); } $url = craft()->config->getSetPasswordPath($code, $id, $user); if (craft()->request->isPostRequest()) { $newPassword = craft()->request->getRequiredPost('newPassword'); $passwordModel = new PasswordModel(); $passwordModel->password = $newPassword; if ($passwordModel->validate()) { $user->newPassword = $newPassword; if (craft()->users->changePassword($user)) { // Do we need to auto-login? if (craft()->config->get('autoLoginAfterAccountActivation') === true) { craft()->userSession->impersonate($user->id); } // If the user can't access the CP, then send them to the front-end setPasswordSuccessPath. if (!$user->can('accessCp')) { $setPasswordSuccessPath = craft()->config->getLocalized('setPasswordSuccessPath'); $url = UrlHelper::getSiteUrl($setPasswordSuccessPath); } else { $postCpLoginRedirect = craft()->config->get('postCpLoginRedirect'); $url = UrlHelper::getCpUrl($postCpLoginRedirect); } $this->redirect($url); } } craft()->userSession->setNotice(Craft::t('Couldn’t update password.')); $this->_processSetPasswordPath($user); $errors = array(); $errors = array_merge($errors, $user->getErrors('newPassword')); $errors = array_merge($errors, $passwordModel->getErrors('password')); $this->renderTemplate($url, array('errors' => $errors, 'code' => $code, 'id' => $id, 'newUser' => $user->password ? false : true)); } else { $this->_processSetPasswordPath($user); $this->renderTemplate($url, array('code' => $code, 'id' => $id, 'newUser' => $user->password ? false : true)); } }
/** * Sets a user record up for a new password without saving it. * * @param UserModel $user The user who is getting a new password. * @param UserRecord $userRecord The user’s record. * @param bool $updatePasswordResetRequired Whether the user’s * {@link UserModel::passwordResetRequired passwordResetRequired} * attribute should be set `false`. Default is `true`. * @param bool $forceDifferentPassword Whether to force a new password to be different from any existing * password. * * @return bool */ private function _setPasswordOnUserRecord(UserModel $user, UserRecord $userRecord, $updatePasswordResetRequired = true, $forceDifferentPassword = false) { // Validate the password first $passwordModel = new PasswordModel(); $passwordModel->password = $user->newPassword; $validates = false; // If it's a new user AND we allow public registration, set it on the 'password' field and not 'newpassword'. if (!$user->id && craft()->systemSettings->getSetting('users', 'allowPublicRegistration')) { $passwordErrorField = 'password'; } else { $passwordErrorField = 'newPassword'; } if ($passwordModel->validate()) { if ($forceDifferentPassword) { // See if the passwords are the same. if (craft()->security->checkPassword($user->newPassword, $userRecord->password)) { $user->addErrors(array($passwordErrorField => Craft::t('That password is the same as your old password. Please choose a new one.'))); } else { $validates = true; } } else { $validates = true; } if ($validates) { // Fire an 'onBeforeSetPassword' event $event = new Event($this, array('password' => $user->newPassword, 'user' => $user)); $this->onBeforeSetPassword($event); // Is the event is giving us the go-ahead? $validates = $event->performAction; } } if ($validates) { $hash = craft()->security->hashPassword($user->newPassword); $userRecord->password = $user->password = $hash; $userRecord->invalidLoginWindowStart = null; $userRecord->invalidLoginCount = $user->invalidLoginCount = null; $userRecord->verificationCode = null; $userRecord->verificationCodeIssuedDate = null; // If it's an existing user, reset the passwordResetRequired bit. if ($updatePasswordResetRequired && $user->id) { $userRecord->passwordResetRequired = $user->passwordResetRequired = false; } $userRecord->lastPasswordChangeDate = $user->lastPasswordChangeDate = DateTimeHelper::currentUTCDateTime(); $user->newPassword = null; $success = true; } else { $user->addErrors(array($passwordErrorField => $passwordModel->getErrors('password'))); $success = false; } if ($success) { // Fire an 'onSetPassword' event $this->onSetPassword(new Event($this, array('user' => $user))); } return $success; }
/** * Sets a user record up for a new password without saving it. * * @access private * @param UserModel $user * @param UserRecord $userRecord * @return bool */ private function _setPasswordOnUserRecord(UserModel $user, UserRecord $userRecord) { // Validate the password first $passwordModel = new PasswordModel(); $passwordModel->password = $user->newPassword; if ($passwordModel->validate()) { $hashAndType = craft()->security->hashString($user->newPassword); $userRecord->password = $user->password = $hashAndType['hash']; $userRecord->encType = $user->encType = $hashAndType['encType']; $userRecord->status = $user->status = UserStatus::Active; $userRecord->invalidLoginWindowStart = null; $userRecord->invalidLoginCount = $user->invalidLoginCount = null; $userRecord->verificationCode = null; $userRecord->verificationCodeIssuedDate = null; // If it's an existing user, reset the passwordResetRequired bit. if ($user->id) { $userRecord->passwordResetRequired = $user->passwordResetRequired = false; } $userRecord->lastPasswordChangeDate = $user->lastPasswordChangeDate = DateTimeHelper::currentUTCDateTime(); $user->newPassword = null; return true; } else { // If it's a new user AND we allow public registration, set it on the 'password' field and not 'newpassword'. if (!$user->id && craft()->systemSettings->getSetting('users', 'allowPublicRegistration', false)) { $user->addErrors(array('password' => $passwordModel->getErrors('password'))); } else { $user->addErrors(array('newPassword' => $passwordModel->getErrors('password'))); } return false; } }