在使用忘记密码发送密码重置电子邮件之前检查用户是否已激活

Checking if User is activated before sending Password Reset email using Forgot Password

我正在使用 Laravel 5.3 创建一个小应用程序。我已经在 Laravel 的默认 Auth 上应用了用户激活(通过电子邮件确认)。但是如果 account/user 未通过验证电子邮件地址激活,我找不到停止发送密码重置 link 的方法。目前,如果用户创建了一个帐户但未验证电子邮件地址 he/she 可以使用密码重置 link.

登录

这是我在用户中的内容 table

public function up()
{
    Schema::create('users', function (Blueprint $table) {
        $table->increments('id');
        $table->string('name')->nullable();;
        $table->string('username')->unique();
        $table->string('email')->unique();
        $table->string('company')->nullable();;
        $table->string('password');
        $table->boolean('activated')->default(false);
        $table->rememberToken();
        $table->timestamps();
    });

    Schema::create('user_activations', function (Blueprint $table) {
        $table->integer('user_id')->unsigned();
        $table->string('token')->index();
        $table->timestamp('created_at');
    });
}

更新 我试图通过更新以下功能来做到这一点。但它不起作用

public function reset(Request $request)
{
    if (!$request->activated) {
        return redirect('/');
    } else {
        $this->validate($request, $this->rules(), $this->validationErrorMessages());

        $response = $this->broker()->reset(
            $this->credentials($request), function ($user, $password) {
                $this->resetPassword($user, $password);
            }
        );

        return $response == Password::PASSWORD_RESET
                    ? $this->sendResetResponse($response)
                    : $this->sendResetFailedResponse($request, $response);
    }
}

我找到了解决方案。以防万一有人在寻找相同的解决方案。这是我重写的函数

public function sendResetLinkEmail(Request $request)
{
    $this->validate($request, ['email' => 'required|email']);
    $user_check = User::where('email', $request->email)->first();

    if (!$user_check->activated) {
        return back()->with('status', 'Your account is not activated. Please activate it first.');
    } else {
        $response = $this->broker()->sendResetLink(
            $request->only('email')
        );

        if ($response === Password::RESET_LINK_SENT) {
            return back()->with('status', trans($response));
        }

        return back()->withErrors(
            ['email' => trans($response)]
        );
    }
} 

另一种直接的方法是创建一个新的验证规则来检查用户帐户是否被激活,然后将规则添加到ForgotPasswordController 内的validateEmail 方法中。只需确保每次停用用户时都删除密码令牌。

<?php

namespace App\Rules;

use Illuminate\Contracts\Validation\Rule;
use App\User;

class ActiveUser implements Rule
{
    /**
     * Create a new rule instance.
     *
     * @return void
     */
    public function __construct()
    {
        //
    }

    /**
     * Determine if the validation rule passes.
     *
     * @param  string  $attribute
     * @param  mixed  $value
     * @return bool
     */
    public function passes($attribute, $value)
    {
        $user = User::whereEmail($value)->first();
        if($user) {
            if($user->active) {
                return true;
            }
            return false;
        }
        return true;
    }

    /**
     * Get the validation error message.
     *
     * @return string
     */
    public function message()
    {
        return 'Your account is deactivated.';
    }
}

并且在 ForgotPasswordController

/**
 * Validate the email for the given request.
 *
 * @param  \Illuminate\Http\Request  $request
 * @return void
 */
protected function validateEmail(Request $request)
{
    $this->validate($request, ['email' => [ 'required', 'email', new ActiveUser ]]);
}

这是在任何用户停用时删除令牌的方法。

$user = \App\user::find(1);
\Illuminate\Support\Facades\Password::broker()->deleteToken($user);

另一种解决方案是覆盖用户模型中的 sendPasswordResetNotification

/**
 * OVERWRITE ORIGINAL
 * @param string $token
 */
public function sendPasswordResetNotification($token) {
  if(!$this->active){
    session()->flash('error', 'Your account is disabled.');
    return back();
  }

  $this->notify(new \Illuminate\Auth\Notifications\ResetPassword($token));
}

如果用户未激活,他将不会收到另一封电子邮件。相反,他将返回到登录页面,并在会话中显示一条错误消息。要显示它,您需要在 blade 文件中添加类似这样的内容:

@if ($errors->any())
@foreach ($errors->all() as $message)
  <div class="alert alert-danger-plain">
    <i class="icon-exclamation"></i> {{ $message }}
  </div>
@endforeach
@endif