I just want to assign a role to newly registered user. How I can achieve this in Laravel 5 with Entrust? I am using Entrust for roles and permissions.
Last time I tried to fire event after user registration in a file in vendor folder. Is there any way to fire an event for role assignment without modifying anything inside vendor folder?
If yes then where should I fire event? I don't want to modify anything inside my vendor folder like firing event in postRegister() in AuthenticatesAndRegistersUsers.php because new updates will overwrite my code.
Code on this link looks good but I don't know entrust has registration event or not.
http://laravel.io/forum/07-02-2014-entrust-assign-role-on-user-signup
Here is my code in routes.php:
// this event is firing on user login and i am getting user object
Event::listen('auth.login', function($user) {
var_dump($user);
die(__LINE__);
});
// this event is not firing on user registration
Event::listen('auth.register', function($user) {
var_dump($user);
die(__LINE__);
// $donor_role = DB::table('app_roles')->where('name', '=', 'donor')->pluck('id');
// $user->roles()->attach($donor_role);
// return false;
});
Please help me out.
App\Service\Registrar.php
This is my way:
public function create(array $data)
{
$create = User::create([
'username' => $data['username'],
'email' => $data['email'],
'password' => $data['password'],
]);
$user = User::find($create->id);
$role = Role::where('name', '=', 'user')->firstOrFail();
$user->roles()->attach($role->id);
return $create;
}
I figured it out all by myself. Here is how I achieved:
I copied postRegister() function from /vendor/laravel/framework/src/Illuminate/Foundation/Auth/AuthenticatesAndRegistersUsers.php and overridden in /app/Http/Controllers/Auth/AuthController.php with some modification.
Here is the modified function in AuthController.php:
public function postRegister(Request $request) {
$validator = $this->registrar->validator($request->all());
if ($validator->fails()) {
$this->throwValidationException(
$request, $validator
);
}
$this->auth->login($this->registrar->create($request->all()));
// little modification :-)
\Event::fire('auth.assign_default_role', $this->auth->user());
return redirect($this->redirectPath());
}
And here is the event listener in routes.php:
Event::listen('auth.assign_default_role', function($user) {
$donor_role = DB::table('app_roles')->where('name', '=', 'donor')- >pluck('id');
$user->roles()->attach($donor_role);
return false;
});
You can fire the register event from your controller where the actual signup is being handled.
Event::fire('auth.register', array($user));
In Laravel 5.7+ you can go to the RegisterController and modify the create function:
protected function create(array $data) {
$user = User::create([
'name' => $data['name'],
'email' => $data['email'],
'password' => Hash::make($data['password']),
]);
$default_role = Role::where('name', 'DEFAULT_ROLE_NAME')->first();
$user->attachRole($default_role);
return $user;
}
Don't forget to use App\Models\Role; in the beginning.
Related
In my Register controller - I have the following method to check if a record exists in another table before creating a user:
public function getCompanyDetails($id)
{
$details = Company::where('company_id', $id)->first();
return $details;
}
protected function create(array $data)
{
$company_id = $data['com_id'];
$company_details = $this->getCompanyDetails($company_id);
if ($company_details == null) {
return redirect()
->back()
->with('warning', 'We could not find the company');
} else {
return User::create([
'name' => $data['name'],
'email' => $data['email'],
'password' => Hash::make($data['password']),
]);
}
}
However when the company record is not found. I'm getting the following error message:
Cannot use object of type Illuminate\Http\RedirectResponse as an array
I believe it's expecting a return of type user. But how can I redirect back to the registration page if the company is not found?
Thanks in Advance
Try the method withErrors():
Redirect::back()->withErrors(['warning', 'We could not find the company']);
I however recommend you to use the validation rule Exists instead of having more queries and manually return a message. You can do it like so:
$request->validate([
'company_id' => 'required|integer|exists:App\Company,id',
]);
Then you won't need the extra logic and the other method.
Source: https://laravel.com/docs/7.x/validation#rule-exists
I have one form in frontend where I have there is some city details , rooms details and user registration in one form like I have city name , room name , address etc email addresss and password in same form and I have done 2 logics in one controller for creating cities and registering user
It is saving the both data in correct table in the database
but I want that first user should register and if user is vcerified only the room details should be saved in database
I am in confusion wheather to apply if again or what
public function checkLogin(Request $request)
{
$user = User::create([
'name'=>$request->name,
'email'=>$request->email,
'password'=>$request->password,
'role_id' => config('quickadmin.default_role_id'),
]);
if ($user) {
if (Auth::check()) {
$city = TotalCity::create([
'name'=>$request->name,
'created_by'=>$request->created_by_id,
]);
}
return redirect()->to('/admin/home');
}
}
Let me show you how I'd probably write this logic:
public function checkLogin(Request $request)
{
$user = User::firstOrCreate([
'email'=> $request->email,
],
[
'name'=> $request->name,
'password'=> bcrypt($request->password),
'role_id' => config('quickadmin.default_role_id'),
]);
if (Auth::check()) {
// it's not clear if you utilize `email_verified_at`, if so
// if (Auth::check() && Auth::user()->email_verified_at) {
$city = TotalCity::create([
'name'=>$request->name,
'created_by'=> Auth::user()->id, // or $user->id depending on your preference
]);
}
return redirect('/admin/home');
}
The firstOrCreate() checks if an entry with that email exists, it gets it, otherwise creates it.
Furthermore, if I want to check for Authentication, I'd use 'auth' middleware in my route.
Route::get('example', 'ExampleController#checkLogin')->middleware('auth');
That removes the need of entire check:
if (Auth::check()) { ... }
I am new to Laravel and have been fairly successful in implementing user authentication. Now to move on to the next step I must allow only users whose status in active to login. For that I have added a
status TINYINT
column in my mysql users table.
I found this in the Laravel Documentation:
Specifying Additional Conditions
If you wish, you may also add extra conditions to the authentication
query in addition to the user's e-mail and password. For example, we
may verify that user is marked as "active":
if (Auth::attempt(['email' => $email, 'password' => $password, 'active' => 1])) {
// The user is active, not suspended, and exists.
}
Can someone please point out where I need to put this chunk. Am thoroughly confused and need some pointers.
Thanks
Have this on your LoginController:
protected function credentials(Request $request)
{
return ['username' => $request->{$this->username()}, 'password' => $request->password, 'status' => 1];
}
You just take user status and check user status is true or false. You can take status using Auth::User()->status from auth session. Try this.
if(Auth::attempt(['email'=>$request->email,'password'=>$request->password])){
$userStatus = Auth::User()->status;
if($userStatus=='1') {
return redirect()->intended(url('/dashboard'));
}else{
Auth::logout();
Session::flush();
return redirect(url('login'))->withInput()->with('errorMsg','You are temporary blocked. please contact to admin');
}
}
else {
return redirect(url('login'))->withInput()->with('errorMsg','Incorrect username or password. Please try again.');
}
Just simply put this code in your App\Auth\LoginController or elsewhere where you have your LoginController located.
public function authenticate(Request $request)
{
$credentials = $request->only('email', 'password');
if (Auth::attempt(['email' => $email, 'password' => $password, 'active' => 1])) {
// Authentication passed...
return redirect()->intended('dashboard');
}
}
with this code you are overriding default authenticate function
Add this to your LoginController:
protected function credentials(Request $request)
{
return [$this->username() => $request->{$this->username()}, 'password' => $request->password, 'active' => 1];
}
Add below method in
app\Http\Controllers\Auth\LoginController.php
and it would extend
AuthenticatesUsers trait
validateLogin method. So basically, it would check for your active clause as well.
protected function validateLogin(Request $request)
{
$this->validate($request, [
$this->username() => [
'required',
Rule::exists('users')->where(function ($query) {
$query->where('active', 1);
}),
],
'password' => 'required'
]);
}
OR
Place your required code in app\Http\Controllers\Auth\LoginController.php
public function authenticate(Request $request)
{
if (Auth::attempt(['email' => $request->email, 'password' => $request->password, 'active' => 1])) {
// The user is active, not suspended, and exists.
}
}
You can override authenticated() method in your App\Http\Controllers\Auth\LoginController.php like so:
protected function authenticated(Request $request, $user)
{
if(!$user->active) {
Auth::logout();
abort(403);
};
}
Do note it's quick but not very "Laravely" solution. Sloppy.
I have two tables the first one is the user table which have these property id, username, email,remember_token, createdat, updateat another table is called received_pay having id, email, token my task is to check if the email, and token entered by the user must match the ones in received_pay otherwise new user is not created, thanks for your time in advanced,
I'm trying to create new user on a condition that if there is data in another table then new user is created otherwise not I have put my code inside if else statement and is throwing errors.
my function for creating new user is listed below:
protected function create(array $data)
{
/*$exists = \DB::table('received_pay')->where('email', $data['email'])->first(); */
$exists=\DB::table('received_pay')->where('email', '=', $data['email'])->where('token', $data['token'])->exists();
if ($exists === null)
{
// user doesn't exist
return User::create([
'username' => $data['username'],
'email' => $data['email'],
'password' => bcrypt($data['password']),
'token' => $data['token'],
]);
}
else
{
return null;
}
}
I think that the best approach in Laravel is create a middleware to protect this url. If you already have this create user feature working is better don't modify it.
So the first step would be create a middleware (https://laravel.com/docs/5.5/middleware) to add your safeguard, something like this:
<?php
namespace App\Http\Middleware;
use Closure;
class CheckPayment
{
public function handle($request, Closure $next)
{
$payment = \DB::table('received_pay')->where('email', $request->email)->where('token', $request->token]);
if (!$payment->count()) {
return redirect('no-payment');
}
return $next($request);
}
}
Then you would need to create a route to handle this invalid creation users (this no-payment url).
And finally you can protect your create-user url in route, by adding your middleware in your kernel.php file...
protected $routeMiddleware = [
...
'payment' => \App\Http\Middleware\CheckPayment::class,
];
and in your web.php route file:
Route::post('user', 'UserController#create')->middleware('payment');
In this way your code will look cleaner, tidier, and closer to the way Laravel works.
I hope it would work fine for you.
If you wish to do it with if statement then do it like below
protected function create(array $data)
{
/*$exists = \DB::table('received_pay')->where('email', $data['email'])->first(); */
$exists=\DB::table('received_pay')->where('email', '=', $data['email'])->where('token', $data['token']);
if (!$exists->count())
{
// user doesn't exist
return User::create([
'username' => $data['username'],
'email' => $data['email'],
'password' => bcrypt($data['password']),
'token' => $data['token'],
]);
}
else
{
return null;
}
}
the count() in the if is to make the statement evaluate true if the data exists and false otherwise and create the new user.
I think that solves your problem.
How can I redirect to specific path after registration in Laravel?. I want to redirect page on id after registration. please help me.
Thank You, in advanced..
If you want to run custom logic after user registers, you'll need to implement registered() method in the controller that registers users:
protected function registered(Request $request, $user)
{
$path = ...; //determine path to redirect to
return redirect($path);
}
I found the answers, Just add $this->redirectTo = ' / ' in Auth/RegisterController.php
Auth/RegisterController.php
Like This:
protected function create(array $data)
{
$user = User::create([
'name' => $data['name'],
'email' => $data['email'],
'password' => bcrypt($data['password']),
]);
$this->redirectTo = '/';
return $user;
}