CakePHP 3 resetowanie hasła

Funkcje password() i reset() komponentu Auth służą do umożliwienia użytkownikowi resetowania hasła.

Gdy użytkownik zapomni hasła, potrzebujemy metody, aby je zresetować. Możemy zweryfikować użytkownika poprzez e-mail, wysłać e-mail z linkiem do resetowania hasła na ten zweryfikowany adres. Użytkownik po wejściu na ten link może zmienić swoje hasło.
Na górze w pliku UsersController.php dodaj.
use Cake\Routing\Router;
use Cake\Mailer\Email;
Potem dodaj następujące funkcje. Funkcja password() sprawdza czy użytkownik o podanym emailu istnieje. Jeśli tak wysyła emaila na podany adres z linkiem do strony (sendResetEmail()), na której może on zmienić hasło. W urlu przesyłamy ponadto unikalny passkey, którego występowanie będziemy sprawdzać w funkcji reset().
public function password()
{
	if ($this->request->is('post')) {
		$query = $this->Users->findByEmail($this->request->data['email']);
		$user = $query->first();
		if (is_null($user)) {
			$this->Flash->error('Email address does not exist. Please try again');
		} else {
			$passkey = uniqid();
			$url = Router::Url(['controller' => 'users', 'action' => 'reset'], true) . '/' . $passkey;
			$timeout = time() + DAY;
			 if ($this->Users->updateAll(['passkey' => $passkey, 'timeout' => $timeout], ['id' => $user->id])){
				$this->sendResetEmail($url, $user);
				$this->redirect(['action' => 'login']);
			} else {
				$this->Flash->error('Error saving reset passkey/timeout');
			}
		}
	}
}

private function sendResetEmail($url, $user) {
	$email = new Email();
	$email->template('resetpass');
	$email->emailFormat('both');
	$email->from('[email protected]');
	$email->to($user->email, $user->full_name);
	$email->subject('Reset your password');
	$email->viewVars(['url' => $url, 'username' => $user->username]);
	if ($email->send()) {
		$this->Flash->success(__('Check your email for your reset password link'));
	} else {
		$this->Flash->error(__('Error sending email: ') . $email->smtpError);
	}
}

public function reset($passkey = null) {
	if ($passkey) {
		$query = $this->Users->find('all', ['conditions' => ['passkey' => $passkey, 'timeout >' => time()]]);
		$user = $query->first();
		if ($user) {
			if (!empty($this->request->data)) {
				// Clear passkey and timeout
				$this->request->data['passkey'] = null;
				$this->request->data['timeout'] = null;
				$user = $this->Users->patchEntity($user, $this->request->data);
				if ($this->Users->save($user)) {
					$this->Flash->set(__('Your password has been updated.'));
					return $this->redirect(array('action' => 'login'));
				} else {
					$this->Flash->error(__('The password could not be updated. Please, try again.'));
				}
			}
		} else {
			$this->Flash->error('Invalid or expired passkey. Please check your email or try again');
			$this->redirect(['action' => 'password']);
		}
		unset($user->password);
		$this->set(compact('user'));
	} else {
		$this->redirect('/');
	}
}
Pozostało nam stworzyć pliki widoków oraz template emaila. Poniżej formularz, w którym użytkownik wprowadzi swój email.
Plik src/Template/Users/password.ctp:
<?php $this->assign('title', 'Request Password Reset'); ?><div class="users content">
	<h3><?php echo __('Forgot Password'); ?></h3>
	<?php
    	echo $this->Form->create();
        echo $this->Form->input('email', ['autofocus' => true, 'label' => 'Email address', 'required' => true]);
		echo $this->Form->button('Request reset email');
    	echo $this->Form->end();
	?>
</div>
Plik src/Template/Users/reset.ctp:
<?php $this->assign('title', 'Reset Password'); ?>
<div class="users form large-9 medium-8 columns content">
    <?php echo $this->Form->create($user) ?>
    <fieldset>
        <legend><?php echo __('Reset Password') ?>
    <?php
        echo $this->Form->input('password', ['required' => true, 'autofocus' => true]); ?>
        <p class="helper">Passwords must be at least 8 characters and contain at least 1 number, 1 uppercase, 1 lowercase and 1 special character</p>
    <?php 
        echo $this->Form->input('confirm_password', ['type' => 'password', 'required' => true]);
    ?>
    </fieldset>
 	<?php echo $this->Form->button(__('Submit')); ?>
    <?php echo $this->Form->end(); ?>
</div>
Wyświetla on prosty formularz, w którym użytkownik może wprowadzić nowe hasło. W przypadku funkcji sendResetEmail() musimy utworzyć szablony wiadomości e-mail wyświetlające dwie zmienne, a ponieważ wysyłamy zarówno zwykły tekst, jak i format html, musimy utworzyć szablon dla każdego z nich.
Template emaila, który jest wysyłany do użytkownika.
Plik src/Template/Email/html/resetpass.ctp
<p>Your username is <?php echo $username; ?></p>

<p>Click on the link below to Reset Your Password.</p>

<p><a href="<?php echo $url; ?>">Click here to Reset Your Password</a></p>

<pre>or Visit this Link</pre><br/>
<p><a href=""><?php echo $url; ?></a></p>

Plik src/Template/Email/text/resetpass.ctp - szablon dla zwykłego tekstu.
Your username is <?php echo $username; ?>

Click on the link below or copy and paste it into your web browser to reset your password:

<?php echo $url; ?>