I have been working on a project using php with laravel for a week now, I just want to make sure I am following the best practices.
I really like the idea of Resource controllers and CRUD, they make sense and I chose to follow this approach. However, should I be using them on a model where different users have different access rights on it?
suppose I have different types of users (user, admin, agent) that have different access rights on the same models. Which of the following approaches is more appropriate for this case?
Create a normal controller for each user type along with its middleware that authorizes the access to this controller. Then add a route to that controller with that middleware.
Create a resource controller for each resource (model), create a route group for each user type containing all routes for this user type from the defined controllers along with a middleware for this route group.
In other words, where both of the following are possible, should controllers definition be based on user type or resources themselves?
Personally I name my controllers based on the resources and then handle the roles/user types via middlewares
Related
I've Blog website where all user can post Blog.I have learned about Gates,Policy and Middleware .Please come to know that i am using Auth() Default Authentication Process in Laravel. I want to protect user (A) blog from other users.
Now I have many things to handle this.
Using Auth if(Auth()->user->id==$blog->user_id)
Using Gate if(Gate::Allow('blog_protection',$blog))
Using Policy if(Auth::user()->cant('blog_protection',$post))
Using Middleware $this->middleware('blog_access')
Please tell if i am wrong Meaning of that functions then what is best method to handle this request for more reusable . Many Thanks In Advance.
I would consider writing a policy class for blog model resource. Multiple reasons :
You can list all access methods related to blog in one file to easy to track
You can do just $this->authorize('access_method_name', Blog::class) in controller
You can pass extra arguments to the method to filter it conditionally
If you have a method outside controller and you need to add filter(ideally the controller authorize() would filter it out) but still you can use
$user->can() or $user->cant()..
which will internally use the same policy.
Also to mention you can use this in blade directives #can()...# endcan #cannot...#endcannot
Middleware is something which would intervene in every request specified in the route group or all requests if its registered as global middleware group. If you want an access filter applicable globally in all routes then middleware is a better option. But for specific resource, I would prefer policies.
In short middleware for request filtering and handling whereas Policy for managing granular level access controls.
I have a system where Admin can manage doctors and doctor has ability to manage itself. For this, I am using Laravel Authorization using policies. I registered a policy for admins that it can access doctors like:
Route::resource('doctors', 'DoctorsController')->middleware('can:access-doctors, App\Doctor');
But what I need is a separate policy for just one route out of resource group i.e. doctors.edit so a doctor can edit own profile like: can:edit-doctor, $doctor something.
Is there a possibility to do this in a proper way or I have to make manual routes and assign policies rather than using resource routes???
If I'm not wrong, you'll need a different endpoint to specify specific middlewares for each route.
You could do:
Route::get('doctors/{doctor}/edit', 'DoctorsController#edit')
->middleware('can:edit-doctor', 'App\Doctor'));
Route::put('doctors/{doctor}', 'DoctorsController#update')
->middleware('can:edit-doctor', 'App\Doctor'));
Route::resource('doctors', 'DoctorsController')
->except(['edit', 'update'])
->middleware('can:access-doctors, App\Doctor'));
I am new to Laravel and need to know how can i structure my project in Laravel.
1) We have almost 21 different modules in the project all the modules are connecting with same database but each module should be register under different namespace.
for example - if i have admin and inventory, the admin should access from /admin and inventory should access from /inventory. Also it will be fine if i can write the routing for each namespace from the corresponding app folder.
2) Another thing we have a different level of user and the different URL will be accessible to those who have permission. So i am planning to write a middle ware for checking the permission before the user request is reaching each controller. So i need a top level middle ware also to check the permission of the login user for all the module.
What structure will be good to implement this type of application. I only need to connect only one database throughout the application.
Here are a few suggestions :
1) You must have a different controller for each module. Place the controllers further in subdirectories if needed.
For example, I keep my Admin-related controllers in the Admin directory under the App\Controllers directory, API-related in App\Controllers\API directory and similarly, App\Controllers\Web for web-only controllers.
2) Have a separate route-file (web.php) for each controller.
Name the route-file to something that matches with the name of the module you are dealing with. for example, 'inventory.php' for dealing with inventory-controller routes only. You need to register the routes as well, just like web.php,api.php, etc routes have been pre-registered out of the box.
3) Follow design patterns to keep your code clean. I would suggest taking a look at Service-Repository pattern.
The code flow then becomes as follows :
Routes pass on the request to a Controller. The controller does not handle the business logic and passes task specific requests to the Service Class where all the business logic will be handled. If any Database specific tasks (CRUD) are needed, the Service class then calls the methods defined in the Repository class.
Have a separate Service and Repository class for all your modules. For example, InventoryController -> InventoryService -> InventoryRepository.
This is just a practice that I follow and may not be the best
solution.
I am using Phalcon as my framework of choice. I have hit a bit of a road block when it comes to structuring my website. I would like to use ACL to manage permissions to my website. But it seems ACL does not allow my to set permission values for 'parameters'.
Say I am creating a website that has user created 'groups' which only users with the correct permissions (set in the ACL) can view.
It might work something like this: website.com/groups/view/MyGroup
Group being the controller, view being the action and "MyGroup" being the parameter for the action defining which group to view.
I can only set the access permission for the groups controller or view action. Not the parameter.
Ideally, I'd use the database adapter for ACL and I would create a new user group for every group created in my app. I could have hundreds of groups, each with own set of users. I can reuse the 'groups' controller code for every group, because we always use the same controller/actions, except we point to different groups by changing the parameter.
How could I achieve this using Phalcons ACL library ? Maybe I need to structure things differently?
Phalcons ACL is based on 'Resources', in which a Resource can technically be anything you desire, you're not limited to controllers only.
http://docs.phalconphp.com/en/latest/api/Phalcon_Acl.html
Let's begin by saying that my model classes are User and Entries.
I've read the following tutorial: http://book.cakephp.org/2.0/en/tutorials-and-examples/simple-acl-controlled-application/simple-acl-controlled-application.html and I see they use an extra model called Group in order assign a role to users.
What is different in using a Group model, instead of a role attribute in User (User.role = 'admin')
What is the difference in adding Group to the ARO instead of adding User to the ARO, and then using an alias.
If I implement ACL, does that means I no longer need admin routing?
PD: I am new to ACL list, I have always authorized actions using a something like if($user['role'] == 'admin').
These are two different ways of handling authentication. If you only have a few controllers and one or two admins, you'll probably be fine with using the User.role method you have now. If you have multiple controllers and various users who should have access to different sections of your site, you should use ACL.
You don't need to create Groups to use ACL, but it makes life a lot easier. Instead of assigning permissions for dozens of different users, you can create two or three groups, set the permissions for those groups, and then assign each user to one of the groups. Then, if you ever need to add a new controller -- or even a new view -- you only have to do that at the group level, instead of for each user. (Take a look at this demo. Now imagine that you have another 10 controllers/50 actions and you have to set those permissions for 20 or 30 users instead of for 4 groups.) Of course, even if you are setting permissions at the Group level, you could always override them at the User level if you need to.
Admin routing is separate from ACL. Routing just controls the URLs you can use to get to pages. (See Cake PHP - Prefix Routing. You can use ACL control without admin routing, and you can use admin routing without ACL control.