Redirect authenticated users according to their role - laravel

I need to redirect users based on ther role in application. In MySQL, I've added "isAdmin" column in Users table to check whether user is admin or not. Only solution I've come up with is to render html on the same blade according to user's type.
For example.
#if(Auth::user()->isAdmin == 1)
<p>Hello, Admin</p>
//other html for admin
#else
//other html for users
Is there a better way to do this in terms of more beautiful and efficient code because this looks messy?
I'm using this package (https://github.com/acacha/adminlte-laravel) which uses Laravel's default authentication system.
I want to redirect users during their login process to two different blades, lets say homeUsers.blade.php and admin.blade.php.

Logic is here: The best way is to create two tables one users and another roles, and put role_id in users table as foreign key.Then create a relation that a role belongsTo a user.
However in your case if you have two views and you want to show one for admin and other for other users follow the below method.
Create two views which you want to use in your case 1) admin 2) homeUsers
#if(Auth::user()->isAdmin == 1)
#include('admin') //admin.blade.php
#else
#include('homeUsers') //homeUsers.blade.php

I'm not sure what version of Laravel you're using, but this seems like it should be in your Middleware.
Check out RedirectIfAuthenticated.php in Middleware. Then, you could do the following.
public function handle($request, Closure $next, $guard = null)
{
if (Auth::guard($guard)->check()) {
if (Auth::user()->role == 'Admin')
{
return redirect('/admin');
}
else
{
return redirect('/home')
}
}
return $next($request);
}

Related

How to restrict users to use application

I am using laravel framework to develop api’s ,it’s an existing application .there is a requirement if more than 5users registered from 6th user onwards i have to restrict them to use application until they approved by manager or they paid for registration fee then only the user will allow to use the application.
Can anyone give me the idea how to acheive this scenario or suggest me any package in laravel
Solution:
You can add 'status' field in your table. Now when your api is registering a user, you can check the No. of users in the database. If more than or equals to 5, you can set the status to 0. Now show the manager list of user with status 0 and when the status changes you can use the application.
Make sure to add condition where status = 1 when user is getting logged in.
I hope it helps!
Well, you can just put a isApproved column to indicate if the user is already approved or just like the email_verified_at that accepts timestamp as a value then create a middleware where you can check if the user is approved or not. then add a method to the user model to check if the user is approve :
User model
class User extends Authenticatable
{
public function isApproved()
{
// check if the account_approved_at column is not null.
return ! is_null($this->account_approved_at);
}
}
Middleware
class EnsureUserIsApproved
{
public function handle(Request $request, Closure $next)
{
if(! $request->user()->isApproved()) {
// can also use abort(403) instead of redirect
return redirect('route-where-you-want-the-user-to-redirect')
}
return $next($request);
}
}
You can check this for more information about middleware

Laravel check if user belongs to certain company before login

I'm developing an application to help companies manage its products.
First, the company should register itself to the app with an active admin user. The new registered company is not active by default.
I want to check if the user company active before logging in.
For example:
I want to register Nike to the app . the registered user is admin#nike.com
if I want to login with "admin#nike.com", it should not be possible till Nike company become active.
Database structure is like this:
Company:
com_id
com_name
com_isActive
User:
user_id
user_name
email
password
user_isAdmin
user_com_id
Any suggestions how to fix it?
Probably you have relation in your User model. Something like
public function company()
{
return $this->belongsTo(Company::class);
}
In your LoginController (if you want it only there) or in some middleware you can check request()->user()->company()->is_active and do whatever you need. RedirectIfAuthenticated middleware is a variant if you don't want to make new middleware
1.First add column to the company table called isActive and adminEmail
2.Make a new Validation Rule called CheckCompanyStatus by this command
php artisan make:rule CheckCompanyStatus
3.Inside this rule put the following logic inside passes()
$data = \Company::where('adminEmail',$value)->first();
if($data->isActive == true) {
return true;
} else {
return false;
}
Go to LoginController and override the function validateLogin() and put this logic
protected function validateLogin(Request $request)
{
$this->validate(['email'=>new \CheckCompany, 'password'=>
'required]);
}
Make sure to add adminEmail and isActive in your company registration form as well
and use all the classes at the top
Let me know if u have any errors

How to give access to views to specific user in laravel?

I have a Category Controller which checks if user is logged in
class CategoryController extends Controller
{
public function __construct() {
$this->middleware('auth');
}
...
My category routes are :
//Category Controller
Route::get('admin/category/{category}/edit', ['uses'=>'categoryController#edit','as'=>'admin.category.edit']);
Route::put('admin/category/{category}', ['uses'=>'categoryController#update','as'=>'admin.category.update']);
Route::get('admin/category/{category}', ['uses'=>'categoryController#show','as'=>'admin.category.show']);
Route::delete('admin/category/{category}', ['uses'=>'categoryController#destroy','as'=>'admin.category.destroy']);
Route::get('admin/category/create', ['uses'=>'categoryController#create','as'=>'admin.category.create']);
Route::get('admin/category', ['uses'=>'categoryController#index','as'=>'admin.category.index']);
Route::post('admin/category', ['uses'=>'categoryController#store','as'=>'admin.category.store']);
Is there a way to give access to these views to only specific user?
For example if user email is admin123#gmail.com then he is allowed to go to those view.
I know I can check like this
if(Auth::user()->email == 'admin123#gmail.com')
{
dd('admin Logged in');
}
But this is possible if i go to individual view and put all my content in the if statement.
Is there way to handle this in controller.
Thanks.
You can use the middlewares for these kinds of work.
From the docs
Middleware provide a convenient mechanism for filtering HTTP requests entering your application. For example, Laravel includes a middleware that verifies the user of your application is authenticated. If the user is not authenticated, the middleware will redirect the user to the login screen. However, if the user is authenticated, the middleware will allow the request to proceed further into the application.
You should restrict users by route groups. Use middleware for that.
However, if you have complicated logic, sometimes you may want to check if user is admin in controller, model and other classes. In this case you can create global helper isAdmin() and use it for simple checks. Examples:
if (isAdmin()) {
// Do something
}
{{ isAdmin() ? 'active' : '' }}
A better way to define user role is like 0 for admin, 1 for user, 2 for member.
Then you can check the user role like:
if(Auth::check())
{
if(Auth::User()->user_type == 0)
{
return view('admin_dashboard');
}
else if(Auth::User()->user_type == 1)
{
return view('user_dashboard');
}
else if(Auth::User()->user_type == 2)
{
return view('member_dashboard');
}
}

two users auth in a single table in laravel 5.2

I'm trying to build an online shop website using laravel framework
I have a table with these column : id, username, password, division_id
where division_id refers to a table called division with: id, division_type
and I have two division type : Admin and Customers
I'm trying to divide permission to access a certain number of pages based on their division_id such as admin can access Admin panel but not Customer, and customer can access Customer panel such as product-order page but not admin.
Both types can do almost everything in their accessible pages, and my main pages will have an Admin Panel, a customer Panel, and main website.
How can I do that in my project using only a single table and middle-ware group?
P.S. I'm new to this forum
For this Middleware, you just need to check if the division required to view the site is the same as the division that the user belongs to. In the handle function, you can pass a 3rd argument that represents a division name, such as customer
When you add the Middleware to your routes, you can pass the name of the division as an argument to the handle function like so:
'middleware' => ['division:customer']
Implementing this in an Route Group may look something like this:
Route::group(['prefix' => 'customer', 'middleware' => ['division:customer']], funtion(){
//route definitions for all these routes will require a "division" type of "customer"
});
Or you could apply it to route resources for RESTful routing:
Route::resource('customer', 'CustomerController')->middleware(['divison:customer']);
Or you could just apply it to a specific route:
Route::get('customer/{id}', 'CustomerController#show')->middleware(['division:customer']);
In your handle function you can access that value as the 3rd argument:
public function handle($request, Closure $next, Division $division)
To make the process of automagically resolving a dependency by something other than the primary key easy, we'll go ahead and pop open our App\Providers\RouteServiceProvider and add some magic inside of the boot function.
public function boot(Router $router)
{
parent::boot($router);
$router->bind('division', function($value) {
return Division::where(function($query) use($value){
if (is_int($value)) {
return $query->where('id', $value)->first();
} else {
return $query->where('type', ucfirst($value))->first();
}
return null;
});
});
Now, back to the Middleware, we can easily make a comparison against the $division in our handle function, and our authorized user.
if(app()->user()->division->type == $division->type) {
return $next($request);
}
abort(403, 'You are not authorized to view this page!');

Symfony2 shared users across multiple apps

I have multiple symfony2 applications which share common entities, but use different database settings. Each of these databases has tables user, user_role and role.
Here's the catch: I would like that user to be able to login to app1 by visiting www.myproject.com/app1/login and after changing URL to /app2/ to use existing token ONLY if identical user exists in app2's database (same username, password and salt). Currently it checks only for same username which is, you must agree, quite inconvenient...
I can't really see when refreshUser() is being called... :-/
All apps use same User and Role entities and UserRepository.
Any help would be much appreciated!
UserRepository:
class UserRepository extends EntityRepository implements \Symfony\Component\Security\Core\User\UserProviderInterface{
/** #var User */
private $user;
public function loadUserByUsername($username) {
/** #var $Q \Doctrine\ORM\Query */
$Q = $this->getEntityManager()
->createQuery('SELECT u FROM CommonsBundle:User u WHERE u.username = :username')
->setParameters(array(
'username' => $username
));
$user = $Q->getOneOrNullResult();
if ( $user == null ){
throw new UsernameNotFoundException("");
}
return $this->user = $user;
}
public function refreshUser(UserInterface $user) {
return $this->loadUserByUsername($user->getUsername());
}
public function supportsClass($class) {
return $class === 'CommonsBundle\Entity\User';
}
public function findById($id){
return $this->getEntityManager()
->createQuery('SELECT u FROM CommonsBundle:User u WHERE u.id = :id')
->setParameters(array(
'id' => $id
))
->getOneOrNullResult();
}
}
User#equals(UserInterface):
I know there is a prettier way to write this method but I will rewrite it after see this working :)
public function equals(UserInterface $user)
{
if (!$user instanceof User) {
return false;
}
if ($this->password !== $user->getPassword()) {
return false;
}
if ($this->getSalt() !== $user->getSalt()) {
return false;
}
if ($this->username !== $user->getUsername()) {
return false;
}
return true;
}
Your question made me think. When using symfony2 security, you got one problem: Either a session is valid, meaning the user is authenticated as either anonymous or real user, or the session is invalid.
So, with this in mind, I don't see your approach working as you would like it, because let's say user1 logs in and is using app1. Now he switches to app2 and is not in the database, meaning he should not have access. What to do now? Invalidate the session? This would mean he has to log in again in app1.
If you would use subdomains, you could tie your session to that subdomain, but this would mean the user has to log in again for each application.
There is another problem: It seems like symfony2 stores the id of the user into the session, so without access to the app1 database, you cannot know what the password and the roles of the user in the app1 database are and cannot check for it.
I guess the security of symfony2 was simply not made for such behaviour. It expects the session to relate to the same user within your whole application.
I don't think that symfony2 is the big problem here but the overall handling with php. Let's think for one moment what I would suggest without symfony2:
When a user logs in, store user and roles into a specific array in the session, like:
user.app1 = array('username','password',array('role1','role2'))
Now, on each request to app1 I would check if user.app1 is in the session and read the roles from there. If not, I would check for user.app2, user.app3 and so on. If I find none, redirect to login. If I find one, I would query the database to find the user with the same username and compare the other values. If match, store everything into the database. If not, check next user from session.
I looked up the symfony security reference, and you got some extension points, so maybe you can work from there on. The form_login got a success_handler, so adding the array to the session as suggested above should be done there. The firewall itself has some parameters like request_matcher and entry_point which could be used to add additional checks like the ones I mentioned above. All are defined as services, so injecting the entity manager and the security context should be no problem.
I personally think the design itself is not optimal here and you might be better of refactoring your code to either use one user for all apps and different roles (remember that you can define many entity managers and use different databases) or even consolidating all databases and storing everything into one database, using acl to prevent users from viewing the "wrong" content.

Resources