Laravel advanced middlewares - laravel

I'm using this line in some controller's __construct
$this->middleware('auth');
This results, that every not logged user will be redirected to login page. It's of course, ok, but there is a problem.
I have two groups of users. In database I have a column called "role", which is boolean. 0 means basic users and 1 means admins. How can I treat, that entrance to some of controllers will be allowed only for admins? I really don't know how to do that in pretty way.

You can pass things to the middleware, like
$this->middleware('auth:1');
Now in the middleware you can check to see if the authenticated user has a role that you passed (in the example, 1). If they don't have the role that you require, then you can redirect them to the login screen or however you want to handle it.

you can use the following code to get the authenticated user and then write custom logic.
if(Auth::user()->role==0)
{
//you are basic user
}
esle if(Auth->user()->role==1)
{
//you are admin
}
you can also Gates and Policies for this type of work.

Related

MiddleWare vs CustomRequest for check user rights

Let's say there some users who have several posts. Every user has many posts, and every post belongs to one user.
To change post frontend uses URL like users/1/posts/3. The goal is to check, that post number 3 belongs to user number 1.
There are several ways to do it:
Check inside controller method or service(bad method IMHO)
Check inside custom request (authorize function)
Check inside middleware
I choose between the last 2, but have some doubts. The custom request should contain validation rules and do not be linked with authorization(SOLID), and I don't know if it's good to do it inside middleware.
I assume you want to check if user can modify the post.
For authorizing access https://laravel.com/docs/7.x/authorization#creating-policies is a way to go.
After defining policy you can reuse it in blade files, in controller and etc..
The policy defines rules for standard actions like create, read, update, delete.
For blades then you can:
#can('update', $post)
For methods in controllers:
$this->authorize('update', $post)
For anywhere else:
$user->can('update', $post)
You can use Policies in conjunction with custom Form Requests

Laravel middleware is "bypassed" when i submit the invalid token, but when it is a valid token, the middleware is executed

all my fellow friends, i have a question.
Route::group([
'middleware' => ['ensure.role:store', 'auth:api']
]
For simplification,
i have two roles : ADMIN and STORE
I have created a middleware that will validate user role, and if the user role is correct, then will allow the user to access the route.
It works fine.
I tried using ADMIN Jwt Token to access STORE routes, and rightfully i am kicked out, and vice versa.
But now, if i modify the token, lets say i add a string to any part of the token, and try to access any route, actually i am allowed to.
I tried var_dump and print something on the related middleware, and here are my observation.
1. If the token is VALID as one of the user role, then
the var_dump is executed, (means the middleware is executed)
2. if the token is INVALID as in i add / modify the original
token, then the var_dump is not executed, and so are the
others route middleware.
I am wondering what causes this behavior, and what could be the fix for this issue, as i need to throw 401 unauthenticated in any token invalid case.
Thank you
I figured it out.
After series of testing and reading, i found out that after laravel 5.3 and above, constructor is called before middleware. And because in my constructor i am using an user object before i am authenticated by the middleware, i encountered constructor error, because user is null.
Of course it is a bad practice to use user object in the construct, however due to the convenience of usage, i still decided to use it.
It sounds complex to use closure based middleware as alternative solution
So i use a workaround to do it.
I create a helper function that return me true if there is an user object or return abort(401); if there is no user object, then add this one line to all the constructors.
$this->checkAccess = EnsureRoleUtil::check('admin');
After that, i just do my next constructor as normally
public function __construct() {
$this->checkAccess = EnsureRoleUtil::check('admin');
$this->user = Auth::user();
$this->categoryM = new CategoryManager($this->user);
}
However, to be noted, it is not a good practice, it is just a hack / workaround.

Laravel "conditional routing"?

I have an interesting problem I need to solve and looking for best way to approach it.
Have a laravel 5.4 app that is fronted by a few public static pages. App is a golf performance tracking app. User enters data and the app does some analysis and shows graphs etc.
Problem is that if a new user signs up they have no data and they need to enter a score for the app to "work"
User signs up, verifies email, etc. so they now have authorized access to the app.
What I want to do is check if the user has any scores in the db (fine I can do that easily) then if they have at least one score entered send them to the app. Fine.
If they have no scores I want to send them to a view that explains that they need to have to enter a score and present the form to do so.
Question is:
where is the best place to check if the user has no scores and then send them to the view to enter the score and not allow them to access any of the app views.
Looking for the best way to do this? Is it create the condition and check the db in the routes/web.php? Is there a better way to accomplish it? and if so what do I do with the routes that sit in:
Route::group(['middleware' => ['web','auth']], function () {
Create a custom middleware and check if the user has score and redirect to any route or display any view you want. Something like this.
public function handle($request, Closure $next)
{
$user = $request->user();
if ($user && ($user->score == 0)) {
return redirect()->route('instruction');
}
return $next($request);
}
Apply this new middleware to all the routes which shouldn't be accessed by users with no scores. Also make sure you use this middleware after auth and not before.

Laravel 5 user role check before

I have some trouble figuring out how to do this properly.
I have Users that can create Articles which can be viewed, edited and deleted. I want to restrict the edit and delete actions if the currently logged in user is not the creator of the Article.
I have already done this using Policies and use Gate within a Form Request, but if i understand correctly FormRequest is only for POST requests. And I currently pass the FormRequest as a parameter to the getEdit() action. That seems wrong.
So how can I make sure the user can neither access nor edit the Article?
If you already defined a Policy you can directly access it using the Gate facade within your controller action like this:
public function getEdit($id)
{
$reference = Reference::findOrFail($id);
if (Gate::denies('owns-reference', $reference))
abort(403);
return view('reference.edit')
->with('reference', $reference);
}
Just make sure to include the Gate on top of your file like this:
use Gate;

codeigniter permissible user actions

hi typically a codeigniter mvc controller accepts an id as a parameter for a controller function. For example:
/photo/edit/1
A user would edit image id 1 from the photo controller. What is the best practice to prevent a user from editing someone else’s image..for example editing id 2? Restriction has to include more than just verifying a logged in user, because a logged in user will still be able to edit image 2.
I was thinking that i would write a library that implements a permission function, that is called on all controller functions. I would pass the user id and the url to the library function which would contain logic to verify if a user could execute that function or in this case edit an image.
The problem i see is..it will be tedious to write the logic code for all functions of my site, as each is different logic. Is there a better generally practiced way?
You generally handle the checking in the controller itself, so if, for instance you have the currently logged in user, and the photo object from the db, just store the photo's owner in the db record and compare them.
It really is not all that tedious, you are simply verifying ownership of the object before processing actions on it.
example...
if ($the_user->id == $the_photo->owner_id) {
//allow their actions
}
else {
redirect('/'); //if not, kick em out
}

Resources