Reputation: 3573
I have altered my authController.php file to do a few things needed for my project. It works great, just need to make one more change. Right now the controller looks like this:
<?php
namespace App\Http\Controllers\Auth;
use App\User;
use App\Role;
use Mail;
use Validator;
use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\ThrottlesLogins;
use Illuminate\Foundation\Auth\AuthenticatesAndRegistersUsers;
use Illuminate\Http\Request;
use Illuminate\Foundation\Auth\ResetsPasswords;
class AuthController extends Controller
{
/*
|--------------------------------------------------------------------------
| Registration & Login Controller
|--------------------------------------------------------------------------
|
| This controller handles the registration of new users, as well as the
| authentication of existing users. By default, this controller uses
| a simple trait to add these behaviors. Why don't you explore it?
|
*/
use AuthenticatesAndRegistersUsers, ThrottlesLogins, ResetsPasswords;
/**
* Where to redirect users after login / registration.
*
* @var string
*/
protected $redirectTo = '/add';
/**
* Create a new authentication controller instance.
*
* @return void
*/
public function __construct()
{
$this->middleware($this->guestMiddleware(), ['except' => 'logout']);
}
/**
* Overwrite the Laravel 5.2 standard registration
* so user will not be logged in automatically.
*
* @param array $request
* @return Register
*/
public function register(Request $request)
{
$validator = $this->validator($request->all());
if ($validator->fails()) {
$this->throwValidationException(
$request, $validator
);
}
$this->create($request->all());
return redirect($this->redirectPath());
}
/**
* Extend password reset email to user for when registering
*/
public function sendResetLinkEmail(Request $request)
{
$this->validateSendResetLinkEmail($request);
$broker = $this->getBroker();
$this->subject = "First Time User Setup";
$broker->emailView = "auth.emails.password";
$response = Password::broker($broker)->sendFirstTimeSetup(
$this->getSendResetLinkEmailCredentials($request),
$this->resetEmailBuilder()
);
switch ($response) {
case Password::RESET_LINK_SENT:
return $this->getSendResetLinkEmailSuccessResponse($response);
case Password::FIRST_TIME_SETUP:
return $this->getSendFirstTimeSetupEmailSuccessResponse($response);
case Password::INVALID_USER:
default:
return $this->getSendResetLinkEmailFailureResponse($response);
}
}
public function getSendFirstTimeSetupEmailSuccessResponse($response)
{
return redirect()->back()->with('status', trans($response));
}
/**
* Get a validator for an incoming registration request.
*
* @param array $data
* @return \Illuminate\Contracts\Validation\Validator
*/
protected function validator(array $data)
{
return Validator::make($data, [
'first-name' => 'required|max:255',
'last-name' => 'required|max:255',
'phone' => 'required|max:255',
'form' => 'max:255',
'email' => 'required|email|max:255|unique:users',
'password' => 'required|min:6|confirmed',
]);
}
/**
* Create a new user instance after a valid registration.
*
* @param array $data
* @return User
*/
protected function create(Request $request, array $data )
{
//Create the user
$user = User::create([
'first_name' => $data['first-name'],
'last_name' => $data['last-name'],
'phone' => $data['phone'],
'email' => $data['email'],
'password' => bcrypt($data['password']),
]);
return $this->postEmail($request);
/*
Mail::send('auth.emails.registered', ['user' => $user], function ($m) use ($user)
{
$m->to($user->email, $user->first_name)->subject('You Have Been Added');
});*/
//Is it a User? Then give them that role
if ($data['user-role'] == 'user')
{
$role = Role::where('name', '=', 'user')->firstOrFail();
$user = User::find($user->id);
$user->roles()->attach($role->id);
}
//Is it an Admin? Then give them that role
if ($data['user-role'] == 'admin')
{
$role = Role::where('name', '=', 'owner')->firstOrFail();
$user = User::find($user->id);
$user->roles()->attach($role->id);
}
return $user;
}
}
It stops auto login on user creation, assigns a role to the user based on the form and sends a password reset email. The trouble is not I get the error Trait method guestMiddleware has not been applied, because there are collisions with other trait methods on App\Http\Controllers\Auth\AuthController
Upvotes: 1
Views: 3779
Reputation: 12559
You can fix your trait collision issue by changing the use
block to the following:
use ThrottlesLogins,
ResetsPasswords,
AuthenticatesAndRegistersUsers {
AuthenticatesAndRegistersUsers::guestMiddleware insteadof ResetsPasswords;
AuthenticatesAndRegistersUsers::getGuard insteadof ResetsPasswords;
AuthenticatesAndRegistersUsers::redirectPath insteadof ResetsPasswords;
}
It's ugly, but it will fix all related collisions, thus allowing you to just use the pre-built Illuminate methods if you so choose.
Upvotes: 0
Reputation: 50787
One of the tricks to this is understanding how the traits
inside of the Auth
factory work.
First, we'll need to use the use Illuminate\Foundation\Auth\ResetsPasswords;
Trait as well as the AuthenticatesAndRegistersUsers
and the ThrottlesLogins
trait.
use AuthenticatesAndRegistersUsers, ThrottlesLogins, ResetsPassword;
Next, we need to make sure that we have a $request
instance being passed to our create
method:
protected function create(Illuminate\Http\Request $request, array $data)
Sidenote - I would recommend moving away from passing in a $data
object as an argument and instead working with $request
. You can get your data like this: $request->get('first-name')
, etc.
Finally, we pass our $request
to the postEmail()
function:
return $this->postEmail($request);
This will pipe the $request to the ResetsPasswords\postEmail
function:
public function postEmail(Request $request)
{
return $this->sendResetLinkEmail($request);
}
Which will inturn pipe it to the ResetsPasswords\sendResetLinkEmail
function:
public function sendResetLinkEmail(Request $request)
{
$this->validateSendResetLinkEmail($request);
$broker = $this->getBroker();
$response = Password::broker($broker)->sendResetLink(
$this->getSendResetLinkEmailCredentials($request),
$this->resetEmailBuilder()
);
switch ($response) {
case Password::RESET_LINK_SENT:
return $this->getSendResetLinkEmailSuccessResponse($response);
case Password::INVALID_USER:
default:
return $this->getSendResetLinkEmailFailureResponse($response);
}
}
Which will ultimately send out an email.
The key to making this entire thing work is that the instance of Illuminate\Http\Request
always contains an email
field.
Note
The response
that will be returned from the sendResetLinkEmail
function may not be the same response that you sent out. Perhaps Users are confused by a Password Reset
request when they've just created their account. Instead, maybe you want to send a First Time Setup
. In order to do this, you will need to create your own Password Broker
and Password Facade
.
Next, lets make 2 new directories:
App\Brokers
App\Facades
Next, make a new file inside of App\Facades
and call it Password.php
. Namespace the file accordingly and extend the existing Password Facade. Also, we'll add another const
as an observable response type for our FIRST_TIME_SETUP
.
<?php
namespace App\Facades;
class Password extends \Illuminate\Support\Facades\Password {
/**
* Constant representing a successfully sent reminder.
*
* @var string
*/
const FIRST_TIME_SETUP = 'passwords.first_time_setup';
}
Now we have added another response type that we can switch
on which will help dictate how we send out our email.
Next, we need to make our Password Broker
and establish our sendFirstTimeSetup
functionality.
namespace App\Brokers;
class PasswordBroker extends Illuminate\Auth\Passwords\PasswordBroker {
public function sendFirstTimeSetup(array $credentials, Closure $callback = null)
{
// First we will check to see if we found a user at the given credentials and
// if we did not we will redirect back to this current URI with a piece of
// "flash" data in the session to indicate to the developers the errors.
$user = $this->getUser($credentials);
if (is_null($user)) {
return static::INVALID_USER;
}
// Once we have the reset token, we are ready to send the message out to this
// user with a link to reset their password. We will then redirect back to
// the current URI having nothing set in the session to indicate errors.
$token = $this->tokens->create($user);
$this->emailResetLink($user, $token, $callback);
return static::FIRST_TIME_SETUP;
}
}
Now we need to copy the sendResetLinkEmail
function that we saw earlier, and move it into our AuthController
. This will allow us to modify the Password
Facade that we use, and modify our switch
statement to support our First Time Setup
public function sendResetLinkEmail(Request $request)
{
$this->validateSendResetLinkEmail($request);
$broker = $this->getBroker();
$response = Password::broker($broker)->sendFirstTimeSetup(
$this->getSendResetLinkEmailCredentials($request),
$this->resetEmailBuilder()
);
switch ($response) {
case Password::RESET_LINK_SENT:
return $this->getSendResetLinkEmailSuccessResponse($response);
case Password::FIRST_TIME_SETUP:
return $this->getSendFirstTimeSetupEmailSuccessResponse($response);
case Password::INVALID_USER:
default:
return $this->getSendResetLinkEmailFailureResponse($response);
}
}
Then, also in the AuthController
, we'll make another function to return our response
:
public function getSendFirstTimeSetupEmailSuccessResponse($response)
{
return redirect()->back()->with('status', trans($response));
}
Finally, if you want to override the view
that is used by the function when being sent out, simply override the $broker->emailView
property before invoking the ->sendFirstTimeSetup()
function:
//...
$broker->emailView = "emails.user.first_time_setup";
$response = Password::broker($broker)->sendFirstTimeSetup(
$this->getSendResetLinkEmailCredentials($request),
$this->resetEmailBuilder()
);
//...
If you want to change the subject
of the email, override the ->subject()
property inside of your AuthController
prior to firing your ->sendFirstTimeSetup()
function:
//...
$this->subject = "First Time User Setup";
$broker->emailView = "emails.user.first_time_setup";
$response = Password::broker($broker)->sendFirstTimeSetup(
$this->getSendResetLinkEmailCredentials($request),
$this->resetEmailBuilder()
);
//...
I could go on and on, but I think this will get you going in the right direction. Hopefully it will help a few others as well.
Upvotes: 6