I am currently developing a website using Laravel.
A user belongs to 1 and only 1 group.
How do I restrict the route
Route::('/view/profile/{id}', 'ProfileController#showProfile');
to be only accessible by other users belonging to the same group. I would also like to allow the admin to access this route. However the admin does not belong to any group.
I know there are two ways to solve your problem.
You can create a custom middleware and bind it to your route.
Or you can do a simple check in your controller method.
I will give an example of the second method since it is the easiest.
Example:
// YourController.php
public function yourMethod()
{
// Get the user from authentication
$user = Auth::user();
// Check user and redirect to login when NULL
// This also can be done with auth middleware (check link in method 1)
if (!$user) return Response::redirect('yourLoginRoute');
// Check if has not group throw forbidden
if ($user->group->id != theGroupId) return App::abort(403);
}
Edit after comment #PaulLucero
So if I understand correctly only users of the same group can visit eachothers profile page (view/profile/{id}). Also you want to use a middleware to solve this problem but are unable to retrieve the route parameter {id}.
You can retrieve a parameter in Laravel 4 outside a route by using Route::input('yourParameter'). Check this and scroll down to Accessing A Route Parameter Value.
Example:
class YourMiddleware
{
public function handle($request, Closure $next)
{
// Get id from route and get user model
$user_id = Route::input('id');
$user = User::find($user_id);
// Do some checks
....
// Get user from auth
$auth_user = Auth::user();
// Do some checks
....
// If groups don't match throw 403
if ($user->group_id != $auth_user->group_id) return App::abort(403);
return $next($request);
}
}
I think this should do the trick.
create a custom middleware try like this
public function yourMethod()
{
$user = Auth::user();
if ($user->group_id == 1) {
return Response::redirect('yourRouteToGroupID-1');
else if(if ($user->group_id == 2) {)
return Response::redirect('yourRouteToGroupID-2');
else{
return App::abort(403);
}
}
Related
Please forgive me if my question is too generic but I am at my wits end.
I have a users table with a level field as shown given below:
$table->unsignedSmallInteger('level')->after('password');
I want to redirect the user to different dashboards based on the value of the level field. For example for level 0 user
\admin\dashboard
for level 1 user
\user\dashboard
I am using Laravel 8.4 and laravel/breeze for authentication.
Thank You
Ok, found a solution.
On routes\web.php I have commented out the default dashboard route and created a new route for /dashboard and pointed it to App\Http\Controllers\DashboardsController#index
// Route::get('/dashboard', function () {
// return view('dashboard');
// })->middleware(['auth'])->name('dashboard');
require __DIR__.'/auth.php';
Route::get('/dashboard','App\Http\Controllers\DashboardsController#index')->middleware(['auth'])->name('dashboard');
index function of DashboardsController
public function index() {
$data['authenticated_user'] = Auth::user();
if($data['authenticated_user']->level == 0) {
echo "Admin";
} elseif($data['authenticated_user']->level == 1) {
echo "Employee";
} else {
echo "Security";
}
}
Basically this will accomplish what I want to achieve.
Thanks
I created a Laravel policy called "UserPolicy" which is supposed to filter out users that do not have the permission to edit, delete, and update other users. The problem is that I am trying to pass an external user's information to the policy. But instead, it just returns the authenticated users information.
My Policy:
public function edit(?User $user)
{
if(auth()->check()) {
dd($user);
$userpower = auth()->user()->roles()->min('power');
if($userpower <= $user->power) {
return true;
} else {
return false;
}
} else {
return false;
}
}
My Controller:
public function edit(User $user)
{
$this->authorize('edit', $user);
$roles = Role::all();
$user = User::where('steamid', $user->steamid)->with('roles')->first();
return view('manage.includes.users.edit')->with(compact('user', 'roles'));
}
For example, I am the user Bob. I am trying to edit the user, John. As a test, I included the dd() function to dump the $user information that is passing into the Policy. After seeing the results, instead of John's information being passed, it is Bob's. How can I make it where it is John's information and not Bob's.
Thank you for your help, if you need more information please let me know.
The first parameter is the authenticated user. The second parameter is the resource. Try defining your policy as:
/**
* Can a guest user, or an authenticated user (let's call this first user Bob)
* edit another user (let's call that second user John) ?
*/
public function edit(?User $bob, User $john)
{
//
}
I need some advice, basically I have an application where users can register as normal customers, and inside the dashboard there is a option to register as an author for a list of categories. A customer can be many authors.
So basically after registering/subscribing as an author in the custom dashboard appears a box of his author(s) that he created and after clicking it goes to a specific dashboard with different menu, etc.
My only issue is when I start to create the permissions, for example I created a Middle-ware with the name of "author", so when someone try to access these pages it must be an author.
Middleware code:
public function handle($request, Closure $next)
{
if(isset($request->id) && auth()->check() && count(auth()->user()->authorsProfile) > 0){
return $next($request);
}
return redirect('/dashboard')->with("error","Only Authors Allowed");
}
example:
Route::group(['middleware' => ['auth','author']], function() {
//Dashboard
Route::get('authorsarea/{id}','AuthorController#dashboard')->name('author-dashboard');
});
So the second validation i need to make is inside the controllers, I need to check based on the ID if this an author id belongs to the customer/user.
example:
public function dashboard($id)
{
$user = Auth::user();
$user_author = Author::find($id);
if($user_author->user_id != Auth::user()->id){
return back()->with("error","This Author is not you");
}
//Go to dashboard
return view('frontend.author.dashboard');
}
I feel that pasting alwasy this code and checking if this author belongs to the user doesnt feel quite clean, is there a better way than pasting always this code in each page controller where I try to access a private area for authors?
Or even if you guys feel that there is a completely different way of doing all of this I'm open to it.
You can make another middleware and have the check there, similar to the author middleware you have created. Something like this:
public function handle($request, Closure $next)
{
$authorID = $request->route()->parameter('id');
$user_author = Author::find($authorID);
if($user_author->user_id != auth()->user()->id){
return back()->with('error', 'This Author is not you');
}
return $next($request);
}
I wanted to do custom redirect logic upon logging in to my site. So I wrote this code
public function login()
{
$user = //what do I put here?
$this->guard()->login($user);
$id = Auth::id();
//dd($id);
$rfid = DB::table('users')->where('id', $id)->value('reference_id');
if ($rfid == null){
dd($id);
return redirect()->action('RedirectController#client');
}
else {
//dd($rfid);
return redirect()->action('RedirectController#employee');
}
}
However my problem is that all it does is redirect. Which makes sense. The code I have there only manages the redirect, there is nothing there to actually log anyone in. So I did some researching and found
$this->guard()->login($user);
As a way to log the user in. However I don't know what to define the variable $user as. I know this should work because I use it in a different place on my site, but it the $user variable that I use there wouldn't work here. So under the scenario of simply login in the user, what do put there in order to authorize the user as in our database, and then log them in?
If you look at Laravel 5.3 AuthenticatesUsers traits , you will understand how login works behind the scene.
you need to change your login method to use attempt instead of login as follows to work it accordingly.
public function login(Request $request)
{
$user = //what do I put here?
$this->guard()->attempt($this->credentials($request), $request->has('remember'));
$id = Auth::id();
//dd($id);
$rfid = DB::table('users')->where('id', $id)->value('reference_id');
if ($rfid == null){
dd($id);
return redirect()->action('RedirectController#client');
}
else {
//dd($rfid);
return redirect()->action('RedirectController#employee');
}}
I recommend you to use it as I mentioned. If you still want to get $user value you can try out
$user = $this->guard()->user();
Though I haven't used it like that.
I am trying to authorize a delete request on a resource if the resource belongs to a user for which I have created a Delete Request in Laravel 5.
For another resource I could do something like:
public function authorize()
{
if(Pivot::findOrFail($this->route('pivots'))->user_id != Auth::user()->id){
return false;
}
return true;
}
So basically $this->route('pivots') would return the id of the pivot that the user is trying to delete and I would check if it belongs to the current user.
But now I am trying for another resource similar to this one:
public function authorize()
{
if(CropSection::findOrFail($this->route('crop-sections'))->pivot->user_id != Auth::user()->id){
return false;
}
return true;
}
I tried to die and dump $this->route('crop-sections') and it comes out to be null but the request was http://localhost:8000/crop-sections/10 which has the id as 10.
What am I doing wrong?
You have to change 'crop-sections' to 'crop_sections'.
Route parameters cannot contain the - character. Use an underscore (_) instead.
You can find more info here.