/** * After validation generate new pwd, recovery token and send email * @throws SyntaxException * @throws \Ffcms\Core\Exception\NativeException */ public function make() { $user = App::$User->getIdentityViaEmail($this->email); if ($user === null) { throw new SyntaxException('Email not found'); } if ($user->approve_token !== '0' && Str::length($user->approve_token) > 0) { throw new SyntaxException('You must approve your account'); } $rows = UserRecovery::where('user_id', '=', $user->getId())->orderBy('id', 'DESC')->first(); if ($rows !== null && $rows !== false) { // prevent spam of recovery messages if (Date::convertToTimestamp($rows->created_at) > time() - self::DELAY) { return; } } // generate pwd, token and pwdCrypt $newPwd = Str::randomLatinNumeric(mt_rand(8, 16)); $pwdCrypt = App::$Security->password_hash($newPwd); $token = Str::randomLatinNumeric(mt_rand(64, 128)); // write new data to recovery table $rObject = new UserRecovery(); $rObject->user_id = $user->id; $rObject->password = $pwdCrypt; $rObject->token = $token; $rObject->save(); // write logs data $log = new UserLog(); $log->user_id = $user->id; $log->type = 'RECOVERY'; $log->message = __('Password recovery is initialized from: %ip%', ['ip' => App::$Request->getClientIp()]); $log->save(); // generate mail template $mailTemplate = App::$View->render('user/mail/recovery', ['login' => $user->login, 'email' => $this->email, 'password' => $newPwd, 'token' => $token, 'id' => $rObject->id]); $sender = App::$Properties->get('adminEmail'); // format SWIFTMailer format $mailMessage = \Swift_Message::newInstance(App::$Translate->get('Profile', 'Account recovery on %site%', ['site' => App::$Request->getHost()]))->setFrom([$sender])->setTo([$this->email])->setBody($mailTemplate, 'text/html'); // send message App::$Mailer->send($mailMessage); }
/** * Recovery form and recovery submit action * @param int|null $id * @param string|null $token * @return string * @throws \Ffcms\Core\Exception\NativeException * @throws ForbiddenException * @throws NotFoundException * @throws \Ffcms\Core\Exception\SyntaxException */ public function actionRecovery($id = null, $token = null) { if (App::$User->isAuth()) { // always auth? prevent any actions throw new ForbiddenException(); } // is recovery submit? if (Obj::isLikeInt($id) && Str::length($token) >= 64) { $rObject = UserRecovery::where('id', '=', $id)->where('token', '=', $token)->where('archive', '=', false); // check if recovery row exist if ($rObject->count() !== 1) { throw new NotFoundException('This recovery data is not found'); } $rData = $rObject->first(); // check if user with this "user_id" in recovery row exist $rUser = App::$User->identity($rData->user_id); if ($rUser === null) { throw new NotFoundException('User is not found'); } // all is ok, lets set new pwd $rUser->password = $rData->password; $rUser->save(); $rData->archive = true; $rData->save(); // add notification App::$Session->getFlashBag()->add('success', __('Your account are successful recovered. We recommend you change password')); // lets open user session with recovered data $loginModel = new FormLogin(); $loginModel->openSession($rUser); $this->response->redirect('/'); // session is opened, refresh page } // lets work with recovery form data $model = new FormRecovery(true); if ($model->send()) { if ($model->validate()) { $model->make(); App::$Session->getFlashBag()->add('success', __('We send to you email with instruction to recovery your account')); } else { App::$Session->getFlashBag()->add('error', __('Form validation is failed')); } } // render visual form content return $this->view->render('recovery', ['model' => $model]); }