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

你。 提交于 2020-01-02 05:12:05

问题


I'm creating a small app using Laravel 5.3. I've applied user activation (via email confirmation) on Laravel's default Auth. But i couldn't find a way to stop sending password reset link if account/user not activated by verifying email address. Currently if a user creates an account and doesn't verify the email address he/she can login using Password Reset link.

this what i've in user 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');
    });
}

UPDATE I tried to do it by updating the below function. but it's not working

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);
    }
}

回答1:


I found the solution. Just in case if someone looking for the same solution. Here is the function i overridden

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)]
        );
    }
} 



回答2:


Another straightforward way is to create a new validation rule to check if the user account is activated, And then add the rule to the validateEmail method inside the ForgotPasswordController. Just make sure that you delete the password token everytime you deactivate a user.

<?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.';
    }
}

And in the 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 ]]);
}

And this is how to delete the token at any user deactivation.

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



回答3:


Another solution is to overwrite the sendPasswordResetNotification in your User Model:

/**
 * 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));
}

If the user is not activated, he won't get another email. Instead, he will be returned back to the login page with an error message in the session. To show it you need something like this in your blade file:

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


来源:https://stackoverflow.com/questions/41269684/checking-if-user-is-activated-before-sending-password-reset-email-using-forgot-p

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!