In Laravel 5.4, they hard-coded the user authentication system, So when you use artisan command 'make:auth' everything will be created for you under the hood, but the thing is that i want when my user get registered successfully i want to create a new instance of 'Profile Class' and make the table columns empty until the user fills his profile, So where can I place the code for creating user profile?
In the RegisterController you can override the registered function.
This function is called directly after a user has successfully registered.
/**
* The user has been registered.
*
* #param \Illuminate\Http\Request $request
* #param mixed $user
* #return mixed
*/
protected function registered(Request $request, $user)
{
// Create a profile here
}
Alternatively, you could also do this with model events directly on the user model
class User extends Authenticatable
{
protected static function boot()
{
parent::boot();
static::creating(function($user) {
// Create profile here
});
}
}
In your app\Http\Controllers\Auth\RegisterController.php on the create() method right after you create a new user you can do this:
use App\Profile; // <-- Import this at the top
protected function create(array $data)
{
$user = User::create([ // <-- change this as you see fit
'name' => $data['name'],
'email' => $data['email'],
'password' => bcrypt($data['password']),
]);
Profile::create(['user_id' => $user->id]);
return $user;
}
Related
I am currently working on a system where people can submit a registration request. The admin will need to accept the request in order for the user to be able to sign in. In my database, I have a field called is_request and with every registration this field is set by default to 1 (is set by default to 1 in the database) , meaning yes. When a user with this field set to 1, tries to log in, they will need to be notified that their account has not yet been activated. How can I accomplish this?
When the user tries to register the following happens:
protected function create(array $data)
{
$users = User::where('role_id', 1)->get();
$user = User::create([
'firstname' => $data['firstname'],
'lastname' => $data['lastname'],
'email' => $data['email'],
'role_id' => 3,
'activated' => 0,
'user_token' => Str::random(32),
'password' => Hash::make($data['password']),
]);
foreach($users as $admin) {
$admin->notify(new registerRequest($user));
}
Mail::to($user->email)->send(new RegisterRequestSend($user));
return $user;
}
And when the admin in the backend "accepts" the request the field is_request will be set to 0 and the user needs to be able to sign into the app.
The login controller looks like this
class LoginController extends Controller
{
/*
|--------------------------------------------------------------------------
| Login Controller
|--------------------------------------------------------------------------
|
| This controller handles authenticating users for the application and
| redirecting them to your home screen. The controller uses a trait
| to conveniently provide its functionality to your applications.
|
*/
use AuthenticatesUsers;
/**
* Where to redirect users after login.
*
* #var string
*/
protected $redirectTo = RouteServiceProvider::HOME;
/**
* Create a new controller instance.
*
* #return void
*/
public function __construct()
{
$this->middleware('guest')->except('logout');
}
}
Update:: DB Table
You could create an global middleware that checks if the user is accepted or not:
namespace App\Http\Middleware;
use Closure;
class CheckIfAccepted
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
if (auth()->check() && !auth()->user()->isAccepted) {
auth()->logout();
return redirect('not-accepted');
}
return $next($request);
}
}
This middleware will log out any authed user that aren't accepted and redirect them to a route of your choice.
Change auth()->user()->isAccepted to an attribute or method that contains information about the accepted-status.
If you want the middleware to run at every request, you can add it as a global middleware by adding it the the $middleware-array in app/Http/Kernel.php.
You can read more about middleware and how to create them in the docs:
https://laravel.com/docs/master/middleware
First you have to make the admin to update the attributes of the user when they are notified
User::where('id' , $user_id)->update(['is_request' => 0]);
then add this in your login controller
public function credentials(Request $request)
{
$credentials = $request->only($this->username(), 'password');
$credentials = array_add($credentials, 'is_request', 0);
return $credentials;
}
I have this on my controller but the redirection does not work it says Type error: Argument 1 passed to Illuminate\Auth\SessionGuard::login(), I have tried this so far but nothing
<?php
namespace App\Http\Controllers\Auth;
use App\Events\NewUserWasRegistered;
use App\Http\Controllers\Controller;
use App\Models\User;
use Illuminate\Foundation\Auth\RegistersUsers;
use Validator;
use Auth;
class RegisterController extends Controller
{
/*
|--------------------------------------------------------------------------
| Register Controller
|--------------------------------------------------------------------------
|
| This controller handles the registration of new users as well as their
| validation and creation. By default this controller uses a trait to
| provide this functionality without requiring any additional code.
|
*/
use RegistersUsers;
/**
* Where to redirect users after login / registration.
*
* #var string
*/
protected $redirectTo = '/home';
/**
* Create a new controller instance.
*
* #return void
*/
public function __construct()
{
$this->middleware('guest');
}
/**
* Get a validator for an incoming registration request.
*
* #param array $data
*
* #return \Illuminate\Contracts\Validation\Validator
*/
protected function validator(array $data)
{
$rules = [
'email' => 'required|email|max:255|unique:users',
'password' => 'required|confirmed|min:6',
'g-recaptcha-response' => 'required|captcha',
'allow_register' => 'required|accepted',
];
if (app()->environment('local') || app()->environment('testing')) {
unset($rules['g-recaptcha-response']);
}
$data['allow_register'] = config('root.app.allow_register', true);
$messages = [
'allow_register.accepted' => trans('app.allow_register'),
];
return Validator::make($data, $rules, $messages);
}
/**
* Create a new user instance after a valid registration.
*
* #param array $data
*
* #return User
*/
protected function create(array $data)
{
$user = User::create([
'username' => md5("{$data['name']}/{$data['email']}"),
'name' => $data['name'],
'email' => $data['email'],
'password' => bcrypt($data['password']),
'role_id' => $data['role'],
]);
event(new NewUserWasRegistered($user));
if($user){
if ($user->role_id == 0) {
Auth::login($user);
return redirect('user/businesses');
}else if($user->role_id == 1){
Auth::login($user);
return 'Working on..';
}
}
// return $user;
}
}
Can someone please help me I am stuck, I have tried so many things but I am new on coding so maybe you will understand If it is that I am asking too much
App\Models\User must implement the interface/contract Illuminate\Contracts\Auth\Authenticatable.
"If you need to log an existing user instance into your application, you may call the login method with the user instance. The given object must be an implementation of the Illuminate\Contracts\Auth\Authenticatable contract. Of course, the App\User model included with Laravel already implements this interface ..."
Laravel 5.7 Docs - Authentication - Manually Authenticating Users - Other Authentication Methods
Side Note:
The create method of that controller is only for taking an array of data and creating a new User and returning that User instance. Nothing else. The registration flow out of the box calls that method, only to create the user. It then does the login and everything else.
In my application I made use of the php artisan make:auth command to provide some early on user login & registration scaffolding.
It has come to my attention that everytime I create a new user whilst being logged in as i.e. UserX, my user changes after submitting the registration to the newly created user.
Example below:
BEFORE REGISTRATION
Logged in as UserX
AFTER REGISTRATION
Logged in as UserZ (newly registered user)
=======
I am wondering how I can make it so that when I create a new user through registration, the system retains the user that was logged in instead of taking on the newly registered user.
Below is the register controller:
=======
<?php
namespace App\Http\Controllers\Auth;
use App\User;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Validator;
use Illuminate\Foundation\Auth\RegistersUsers;
class RegisterController extends Controller
{
/*
|--------------------------------------------------------------------------
| Register Controller
|--------------------------------------------------------------------------
|
| This controller handles the registration of new users as well as their
| validation and creation. By default this controller uses a trait to
| provide this functionality without requiring any additional code.
|
*/
use RegistersUsers;
/**
* Where to redirect users after registration.
*
* #var string
*/
protected $redirectTo = '/home';
/**
* Create a new controller instance.
*
* #return void
*/
public function __construct()
{
$this->middleware('auth');
}
/**
* 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, [
'name' => 'required|string|max:255',
'email' => 'required|string|email|max:255|unique:users',
'password' => 'required|string|min:6|confirmed',
]);
}
/**
* Create a new user instance after a valid registration.
*
* #param array $data
* #return \App\User
*/
protected function create(array $data)
{
return User::create([
'name' => $data['name'],
'email' => $data['email'],
'password' => Hash::make($data['password']),
]);
}
}
If you need to provide users the ability to add new users you should do so through a UsersController.
Now your new controller won't take on the behaviour of registration. This would also make logic in your application clearer since you are not registering a user, you are creating a new one.
To expand a little, the RegisterController executes the following code when you register a user (through use Auth\RegisteredUsers register method).
$this->guard()->login($user);
return $this->registered($request, $user)
?: redirect($this->redirectPath());
So in essence you must follow the approach I mention above unless you remove "use RegisteredUsers;" from the RegisterController which would not generally be recommended. Using your separate controller / behaviour allows you to create additional logic such as checking for user type (e.g. Admin User) before allowing to create a user etc. etc.
Right now redirectTo is set to /home.
I want to know how I can redirect to the previous page.
I tried using
protected $redirectTo = URL::previous();
but I get parse error, expecting ','' or ';''
What would be the best solution to approach this problem? I assume I'd need to over-ride the $redirectTo variable somehow with URL::previous() and that would be sufficient.
This is my register controller:
namespace App\Http\Controllers\Auth;
use App\User;
use URL;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Validator;
use Illuminate\Foundation\Auth\RegistersUsers;
class RegisterController extends Controller
{
use RegistersUsers;
/**
* Where to redirect users after registration.
*
* #var string
*/
protected $redirectTo = '/home';
/**
* Create a new controller instance.
*
* #return void
*/
public function __construct()
{
$this->middleware('guest');
}
/**
* 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, [
// 'name' => 'required|max:255',
'username' => 'required|max:255|unique:users',
'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(array $data)
{
return User::create([
// 'name' => $data['name'],
'username' => $data['username'],
'email' => $data['email'],
'password' => bcrypt($data['password']),
]);
}
}
The RegisterController uses the RegistersUsers trait. When you submit the form, the register() method of this trait is called. It validates the input, creates and authenticates the user and then redirects to the path specified by the redirectPath() method. This method is actually set in the RedirectsUsers trait, which is used by the RegistersUsers trait.
The redirectPath() method will look for a redirectTo() method on the controller. If it does find this method, it will use whatever is returned from it. If doesn't find this method, it will redirect to the url specified in the redirectTo property instead.
So, if you need to set the redirect path dynamically, put this in your RegisterController:
protected function redirectTo()
{
return url()->previous();
}
Read more here.
add this to RegisterController:
protected function redirectTo(){
return url()->previous();
}
Note: if present the field $redirectTo , remove it
This is much better if the user is coming from the login page to the register page and we need to redirect him after registration to the previous link:
add this to RegisterController:
protected function registered(Request $request, $user)
{
return redirect()->intended($this->redirectPath());
}
In case you want to stay on the same page when no authentication is required and also go on the next one for which is required, it is possible to overwrite the code by adding the following code to the RegisterController.
The first part write the last page that was accessed before displaying the register blade, and the second part redirects to written page upon successful registration.
public function showRegistrationForm()
{
if(!session()->has('url.intended'))
{
session(['url.intended' => url()->previous()]);
}
return view('auth.register');
}
protected function registered(Request $request, $user)
{
return redirect()->intended($this->redirectPath());
}
I want my AuthController to check for few conditions and redirect to the respected routes accordingly. I want to check the if the logged in user's DB has particular columns are not empty. If its not empty i am redirecting to home page else I am redirecting to another route. I have used postLogin method. the issue here is its not checking the condition at all and directly redirecting to home even if the condtion fails. I tried to log in with new users whose details in DB are not filled , then also it redirected me to the home page and same happened with user who has his personal details filled in DB
here is the code of my AuthController
<?php
namespace App\Http\Controllers\Auth;
use App\User;
use Validator;
use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\ThrottlesLogins;
use Illuminate\Foundation\Auth\AuthenticatesAndRegistersUsers;
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;
/**
* Where to redirect users after login / registration.
*
* #var string
*/
//protected $redirectTo = '/user-prof';
public function postLogin(Request $request)
{
$email = $request->email;
$user = \Auth::user();
if(($user->username && $user->phone && $user->bio && $user->dobday && $user->dobmonth && $user->dobyear && $user->firstname
&& $user->lastname && $user->topics && $user->nationality)!= NULL)
{
redirect('home');
}
else
{
redirect('/user-prof');
}
return $this->login($request);
}
/**
* Create a new authentication controller instance.
*
* #return void
*/
public function __construct()
{
$this->middleware($this->guestMiddleware(), ['except' => 'logout']);
}
/**
* 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, [
'name' => 'required|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(array $data)
{
return User::create([
'name' => $data['name'],
'email' => $data['email'],
'password' => bcrypt($data['password']),
]);
}
}
I also want to know if i am checking the DB column data in the right way in IF condition inside the postLogin() method.
You probably mean to do those checks after the user has been 'authenticated' and logged in. You can define a authenticated method on your AuthController that will be called by handleUserWasAuthenticated after the user has been authenticated.
Something like this perhaps. (Get the user's attributes, only get the ones we want to check, use array_filter to remove the nulls, see if all the required fields are there).
protected function authenticated($request, $user)
{
$required = [
'username', 'phone', 'bio', 'dobday', 'dobmonth', 'dobyear',
'firstname', 'lastname', 'topics', 'nationality'
];
$userAtts = array_filter(array_only($user->toArray(), $required));
if (count($userAtts) != count($required)) {
return redirect('/user-prof');
}
return redirect('home');
}
This doesn't change any methods the AuthController already has via the traits, it just adds a method that handleUserWasAuthenticated will check to see if exists, and if so will call it.
Illuminate\Foundation\Auth\AuthenticatesUsers#login -> #handleUserWasAuthenticated
If you intend on 'caging' the user until these fields are filled in, then I would go with a middleware option similar to what #Ravi's answer is saying, but would have to be applied to a lot of routes.
Do not override the method in Authcontroller. Use an after-middleware on postLogin route to check the conditions and route accordingly.
https://laravel.com/docs/5.2/middleware
There is one other way to do it; however, I wouldn't suggest you do it. You may modify the RedirectsUsers trait. It is a Laravel file and will be defaulted back to original at every composer update. Although you can have a look at it to understand the redirection
https://github.com/laravel/framework/blob/5.1/src/Illuminate/Foundation/Auth/RedirectsUsers.php