public function actionReset($id, $code) {
    if (!$this->module->enablePasswordRecovery) {
      throw new NotFoundHttpException();
    }

    /** @var Token $token */
    $token = Token::find()->where(['userId' => $id, 'code' => $code, 'type' => Token::TYPE_RECOVERY])->one();
    $event = $this->getResetPasswordEvent($token);

    $this->trigger(self::EVENT_BEFORE_TOKEN_VALIDATE, $event);

    if ($token === null || $token->isExpired || $token->user === null) {
      $this->trigger(self::EVENT_AFTER_TOKEN_VALIDATE, $event);
      Yii::$app->session->setFlash('danger', Yii::t('users', 'Recovery link is invalid or expired. Please try requesting a new one.'));
      return $this->render('/message', [
        'title' => Yii::t('users', 'Invalid or expired link'),
        'module' => $this->module,
      ]);
    }

    /** @var RecoveryForm $model */
    $model = Yii::createObject([
      'class' => RecoveryForm::className(),
      'scenario' => 'reset',
    ]);
    $event->setForm($model);

    $this->performAjaxValidation($model);
    $this->trigger(self::EVENT_BEFORE_RESET, $event);

    if ($model->load(Yii::$app->getRequest()->post()) && $model->resetPassword($token)) {
      $this->trigger(self::EVENT_AFTER_RESET, $event);
      return $this->render('/message', [
        'title' => Yii::t('users', 'Password has been changed'),
        'module' => $this->module,
      ]);
    }

    return $this->render('reset', [
      'model' => $model,
    ]);
  }