2
votes

When a user is logged on, I've added the ability for that user to create a new user (specifying an email address, without providing a password).

When that's done, I want the new user to get an email (like the Reset Password email with a link) that will send the user to a Set Password page (similar to the Reset Password view).

I figured out how to send the New user a regular email in the store function (UserController) :

public function store(UsersRequest $request)
{
    $user = User::create(Request::all());

    Mail::send('users.welcomemail', [], function ($message) { 
        $message->from('email@example.com', 'Email');
        $message->to('email@example.com', 'Email')->subject('Welcome!');
    });

    return redirect('business/');
}

I've create a new view for Setting a Password (copied from views/auth/reset.blade.php).

I'm just not sure what I should write (for Setting up a password) to my controller so it acts like the Reset a password function. Any ideas would help.

If possible, I would like to use what exists already in laravel.. default user table and controller, and password_resets table.

update - solution

I've managed to make it work.

UsersController

public function store(UsersRequest $request)
{
    $user = User::create(Request::all());

    $contactfirstname = $user->first_name;
    $contactemail = $user->email;

    $token = hash_hmac('sha256', str_random(40), config('app.key'));

    DB::table('password_resets')->insert(['email' => $user->email, 'token' => $token, 'created_at' =>  \Carbon\Carbon::now()->toDateTimeString()]);

    Mail::send('users.welcomemail', ['user' => $user, 'token' => $token], function ($message) use ($contactfirstname, $contactemail)
    { 
        $message->from('name@email.com', 'My name');
        $message->to($contactemail, $contactfirstname)->subject('Welcome!');
    });

    return redirect('business/');
}

users.welcomemail view

<h1>Hi! {{ $user->first_name }}</h1>

<p>We'd like to personally welcome you. Thank you for registering!</p>

<p>Please click the link below to set your account password and get access to your account :</p>

<p><a href="{{ URL::to('auth/passwordset/' .  $token) }}">{{ URL::to('auth/passwordset/' .  $token) }}</a></p>

route

('/auth/passwordset/{token}', 'PasswordSetupController@passwordset');

passwordSetupController

class PasswordsetController extends Controller {

    /*
    |--------------------------------------------------------------------------
    | Passwordset Controller
    |--------------------------------------------------------------------------
    |
    | This controller handles password setups for new users
    |
    */

    /**
     * Create a new controller instance.
     *
     * @return void
     */
    public function __construct()
    {

    }

    public function passwordset($token)
    {
        return view('users.passwordset')->with(['token' => $token]);
    }
}

passwordset/{token} view

@extends('app')

@section('content')
<div class="container-fluid">
    <div class="row">
        <div class="col-md-8 col-md-offset-2">
            <div class="panel panel-default">
                <div class="panel-heading">Set Password</div>
                <div class="panel-body">
                    @if (count($errors) > 0)
                        <div class="alert alert-danger">
                            <strong>Whoops!</strong> There were some problems with your input.<br><br>
                            <ul>
                                @foreach ($errors->all() as $error)
                                    <li>{{ $error }}</li>
                                @endforeach
                            </ul>
                        </div>
                    @endif

                    <form class="form-horizontal" role="form" method="POST" action="{{ url('/password/reset') }}">
                        <input type="hidden" name="_token" value="{{ csrf_token() }}">
                        <input type="hidden" name="token" value="{{ $token }}">

                        <div class="form-group">
                            <label class="col-md-4 control-label">E-Mail Address</label>
                            <div class="col-md-6">
                                <input type="email" class="form-control" name="email" value="{{ old('email') }}">
                            </div>
                        </div>

                        <div class="form-group">
                            <label class="col-md-4 control-label">Password</label>
                            <div class="col-md-6">
                                <input type="password" class="form-control" name="password">
                            </div>
                        </div>

                        <div class="form-group">
                            <label class="col-md-4 control-label">Confirm Password</label>
                            <div class="col-md-6">
                                <input type="password" class="form-control" name="password_confirmation">
                            </div>
                        </div>

                        <div class="form-group">
                            <div class="col-md-6 col-md-offset-4">
                                <button type="submit" class="btn btn-primary">
                                    Set Password
                                </button>
                            </div>
                        </div>
                    </form>
                </div>
            </div>
        </div>
    </div>
</div>
@endsection
1

1 Answers

5
votes

When you are creating the new account using the new email address, you also need to put a unique value in the database for that email, for example, you may create a record in the database using email and token fields so when creating the record and storing the email also store the token (unique). To get a unique token you may try this:

$token = hash_hmac('sha256', str_random(40), config('app.key'));

Now save the record in the database and send the email with a link and the link could be look something like this:

http://example.com/set/password/the-token-you-created-for-this-user

Now, just create a route for the link, for example:

get('/set/password/{token}', 'PasswordSetupController@getSetPassword');

Now, in the controller, declare the method, for example:

public function getSetPassword($token)
{
    // find the token from the database
    // if you can find a record, for example:
    $model = SomeModel::whereToken($token)->first();

    if($model) {
        // The matching $token is found. So show a view to set the password
        // with a form textbox and submit button, set form action, add route
        // for that action. Also, add a hidden field in the form for token,
        // so you can check it again on form submission
    }
}

Create a method for form processing, for example:

public function postSetPassword()
{
    if($token = Input::get('hidden_token_field')) {
        // Match it again and if matches then save the password and delete
        // the hashed record or update the hashed field, just figure it out.
    }
}

Route could be:

post('/set/password', 'PasswordSetupController@postSetPassword');

This is an abstract idea but you should be able to do the required work. I gave you the idea you asked for. Hope it'll help you. Make sure to set the form method POST according to the route above.