Snapey
Snapey
3 months ago (865,465 XP)

Not sure using notifications.

    protected function registered(Request $request, $user, $reset_token) {
        $user->notify(new UserRegisteredNotification($user, $reset_token));  // no need to pass user to the notification
    }

Notification

public $reset_token;

public function __construct($reset_token)
{
    $this->reset_token = $reset_token;
}
public function toMail($notifiable) {
        $pw_reset = DB::table('password_resets')->where('email', $this->user->email)->first();
        return (new MailMessage)
            ...
            ->action('Reset Password', url(config('app.url').route('password.reset', $this->reset_token, false)))  // get the token from this object
            ...
    }
Snapey
Snapey
3 months ago (865,465 XP)

I know you are getting close to cracking it, but TBH I don't like this as an option.

Password reset links are meant to have a very limited life but you are sending it in response to a new user being created. Does the user know they are being created or is someone else doing it for them (like an invite). If so, the token may well have expired before they deal with it

I would probably rather send them to the password reset page so they request a new token.

BezhanSalleh

i would show the reset password for the new registered user after he/she is authenticated (or verified their email if verification is involved) for the first time and after that business as usual.

Snapey
Snapey
3 months ago (865,465 XP)

This does both. If they get the reset token then they have verified their email

BezhanSalleh

yeah, but if you are verifying the email then you send the user to the reset page and after reset to the login page. and you probably have a change password option for the authenticated user. for a first time user seems lots of hoop to jump over.

My way Verify->Authenticate->Reset by leveraging the change password option if exist->boom!

larel_b

@Snapey There is only 1 admin - the site owner - this person can create accounts without passwords - the new user will get an email link to set/reset the password.

BezhanSalleh

in this case on creation send an email with their username and system generated password and when a user is authenticated using their system generated password that's the first time show the reset password form. Et Voila!

larel_b

@BezhanSalleh Initially, I was going to do it that way, but I didn't want to send a plain text password through email. Do you think you can help me accomplish this in the way I intend?

Everything works, but I'm getting this password reset token is invalid when submitting the reset form.

larel_b

@Snapey Thanks I voted your answer as the correct one. I did it like this before, but I wasn't hashing the token correctly.

I used this in the RegisterController:

public $reset_token;

    $this->reset_token = hash_hmac('sha256', Str::random(40), $key);
    DB::table('password_resets')->insert([
       'email' => $request->email,
        'token' => Hash::make($this->reset_token),
        'created_at' => Carbon::now(),
    ]);

Then I passed the token to my notification class like so:

protected function registered(Request $request, $user) { $user->notify(new UserRegisteredNotification($user, $this->reset_token)); }

In the Notification class:

public $token;

public function __construct($user, $reset_token) {
    $this->user = $user;
    $this->token = $reset_token;
}

From there, I send the e-mail to the user with a link to

url(config('app.url').route('password.reset', $this->token, false))

It all works now!

Snapey
Snapey
3 months ago (865,465 XP)

Good job

Just one thing I tried to call out in the code.

if you do $user->notify(notificationClass) then its the user that is being notified and is the $notifiable in the notification. You don't need to send the user again as a parameter to the class.

At least thats how I think it works.

larel_b

@Snapey My UserRegisteredNotification is called as a class like this:

$user->notify(new UserRegisteredNotification($user, $this->reset_token));

Notice that the reference to the user is inside the calling class and if you don't pass it in, then you have to get the reference some other way. This appears to be how it's done in the Laravel docs too. In my notification class, I'm actually using the user object to print details in the e-mail. I just didn't post the code because it wasn't relevant to the problem.

Thanks again for the help.

Snapey
Snapey
3 months ago (865,465 XP)

But when you do user-notify() you are using the notifiable trait added to the User model

In your toMail class you accept a variable $notifiable. ...this is the user

In any case. In your notification class you pass the user into the constructor but you don't save it

Please sign in or create an account to participate in this conversation.