I am new to php and I an currently creating a e-commerce site. I have created a CMS backend for the admin to add/edit/delete products, manage orders, manage shop configuration and add/edit/delete users.
I am having trouble finding out how to set user permissions/access rights so that:
- General staff only have access to managing orders and
- management staff have access to everything
So basically giving users a role which will give them restrictions or full access to everything.
Is there any tutorials or anyone with previous experience of adding this feature who can point me in the right direction?
Any help will be greatly appreciated. Thanks
An alternative design to what #Johnathan suggests would be a user HAS_MANY roles and each role HAS_MANY permissions.
Users:
+ id
+ name
Roles:
+ id
+ name
Permissions:
+ id
+ name
Then you link users to each of their roles, (and roles to each of their permissions), like this:
RolesUsers:
+ id
+ role_id /* Associate a Role to a User */
+ user_id /* Associate a User to a Role */
RolePermissions:
+ id
+ role_id /* Associate a Role to a Permission */
+ permission_id /* Associate a Permission to a Role */
Rather than cascading roles, or only allowing a user to be in a single role - users having multiple roles provides the most amount of flexibility.
Permissions are associated with Roles, and Users are associated with Roles. While there are, undoubtedly, many ways to implement this type of system, what follows is a quick concept from which you could begin thinking:
Users:
+ userid
+ roleid /* Associate a Role to a User */
Roles:
+ roleid
+ rolename
Permissions:
+ permissionid
+ permissionname
RolePermissions:
+ roleid
+ permissionid /* Associate a Permission to a Role */
Note in the first table how the role is associated directly from within the user table. You could break this out and put it in its own table if you wanted to assign multiple roles to a user.
Once this is all in place, or something similar to it, you can track the user's role via a session variable, and determine whether or not the user is permitted to perform any given action by looking up the id/name of that action, and the id/name of their role, in the RolePermissions table.
if ( $user->allowed( 'deleteUser' ) ) {
$users->remove( $uid );
}
Of course the database side is only the first part of the work. Next you would need to implement the connections between the database, and your code.
There are several ways of doing this that depends on how your app is going to grow. If you're pretty sure you'll only have these two profiles, then just add a "profile" field in your "user" table.
I suppose you have already implemented the login management, then you probably keep the logged user id in session. Just keep the profile type also and every time you display some component that should be accessible to the managers only, wrap it in
<?php if ($_SESSION['logged_user_profile'] == 'manager'): ?>
<!-- display your thing here -->
<?php endif; ?>
Note that this would only hide the elements. You would have to perform this check everywhere in your code also to prevent the corresponding actions from being executed...
A (much) better way if you use an MVC framework like CodeIgniter for instance would be to hook all requests through your access controller and redirect the user to a "access forbidden" page if he tries to access something he's not allowed to. This way, your access is controlled in one spot only.
Well, this is a complex subject that heavily depends on the architecture of your project so sorry if this doesn't answer your question correctly.
Extending from Jonathan's structure, I made a few modifications :
Users:
+ userid
+ roleid /* Associate a Role to a User */
Roles:
+ roleid
+ rolename
+ roleinherit /* Added this field */
Permissions:
+ permissionid
+ permissionname
RolePermissions:
+ roleid
+ permissionid /* Associate a Permission to a Role */
Being able to inherit from other roles can really help simplifying access control. For example, you could say that the "moderator" role inherits the "user" role which inherits the "guest" role. That way, you never have a guest that can do things even a moderator can't do.
Of course, this structure might be harder to implement as you can no longer create a simple query to check. A good way to handle these would be to create a recursive function that pulls data for the user's role, then merges it with the results of this function for the inherited role.
function getPermissions($roleID) {
// get info about this role and store it in $permissions. Assume we also set $inheritFrom
if ($inheritFrom == 0) return $permissions;
else return array_merge($permissions, getPermissions($inheritFrom));
}
Make sure to cache the results of this function, because it might become heavy.
Related
I have to create an application in which there are 5 types of accounts
Super admin
Inventory admin
Shop owner
Shop manager
User
So How can I create these multiple accounts with Laravel, should I use different middleware group for each. also, i have to create privileges with all.
Currently, I am using it with different middleware and session for each and separate tables in DB for each, but I don't think so that's a good way to do it.
What is the way to create these multiple accounts with Laravel.
#Thanks
In addition to providing authentication services, Laravel also provides a simple way to authorize user actions against a given resource. Laravel's approach to authorization is simple, and there are two primary ways of authorizing actions: gates and policies. Please refer the Laravel documentation for more details.
Authorization in Laravel 5.5
As #Fawzan has said, if you only working with Roles (or a Group) then just create a groups table and then link each user to the appropriate group. You then have a single user table with a groupID for each user.
Then you could create a blade directive to help you in your app to check if a user has a specific role. (Place this inside your AppServiceProvider)
Blade::directive('hasRole', function ($role) {
return auth()->user()->role->name = $role;
});
// Or a little more performant if you call the directive many times.
$roles = Role::all()->pluck('id', 'name')->toArray();
Blade::directive('hasRole', function ($role) use ($roles) {
return auth()->user()->roleID == $roles[$role];
});
You can add a column to users table called user_type and
insert the decimal value for each user for example
Super admin = 1;
Inventory admin = 2;
Shop owner = 3;
Shop manager = 4;
User = 5;
and based on the user_type you can do all your operation.
I have the table structure below
Here are the tables.
Users:
+ userid
+ roleid /* Associate a Role to a User */
Roles:
+ roleid
+ rolename
Permissions:
+ permissionid
+ permissionname
RolePermissions:
+ roleid
+ permissionid /* Associate a Permission to a Role */
Hoping the structure makes sense.
I need users with the change_password permission to be able to change a user's password. Which is simple just assign the permission to their role.
The complication is that certain roles can only change certain types of users' passwords. e.g A Janitor can change a Junior Janitors Password But not a Teacher's Password. So can't just do a $user->can('edit_password') check. Also don't want a bunch of if_this_role_is_editing_this_role checks. Is there a really nice way you guys would approach this? Thanks.
You can add a "power" col to your user table. That way, you can block an action if the user is doing an action on a user that has a power bigger or equal to his own power privileges.
Current project I am working on is a web application, that has to be delivered to multiple customers on their own servers. The website needs a permission control system, that will manage areas and features users can or can not use.
As for know, I'm designing a database-driven permissions system, with permissions stored in database. Every user has a role. The role defines the list permissions available. The schema looks like this:
users table
1. user_id
2. name
3. role_id
roles table
1. role_id
2. name
permissions table
1. permission_id
2. name
roles_permissions table:
1. role_id
2. permission_id
In the code I would fetch logged users role and permissions, and check if the user is able to perform action or see area like so:
if($user->hasPermission('Edit HR')) {
// let user see the editing HR section
}
The hasPermission would check if user has a permission with a name 'Edit HR' and will return the needed result. The problem I see is the database table has to have the permission record with a name being exactly 'Edit HR', not 'Edit_hr' or 'HR Editing'. So I have to make sure the data for the permissions system is the same for every database the applications are using. Which kind of makes me think this is a flawed design and needs to be re-designed. Creating new sections and features would also require to update all the databases, which also makes me a sad panda.
So, basically, the question is: what is the best way to design the database driven permission system and keep the database integrity on multiple databases?
The scheme you've come up with looks fine. The only thing I would add to that is on the permissions table I would add a field called tag or similar.
The permission tag would be something like EDIT_HR, and you would use this as the reference in your code instead of its name. Use the name just for display purposes for example HR Editing. This way the name can vary as required, and it won't affect your code.
The solution I'm using is to have a global $current_user object that reads the permissions table on creation and stores all permission actions that are valid for it. This array is then searched whenever you need to check an action. It saves on DB queries, although if there are security implications for storing this kind of data in a global object, I haven't found it.
There's only 1 db table required (sample):
user_id | user_role | user_action
---------------------------------
0 | 10 | view_dashboard
0 | 1 | view_users
User role corresponds to the minimum user type (Admin, editor, visitor, etc.) so all actions with a user_role >= $current_user role are available. The user_id column allows you to override certain levels for a specific user.
With this kind of setup, it's also easy to have a page that lists all permissions and allows a user to modify the value with a simple dropdown (but make sure not every user can do that).
I'm using Codeigniter with Ion Auth for user management. I'd like to create two different user roles - one for volunteers and one for organizations. I know that I can use Ion Auth's groups for things like access control, but what would be a good way to add fields to the different user types (for instance - the volunteer user will have a 'languages spoken' field while the organization will have a 'mission' field)? Should I extend the Ion Auth class for each new user type and handle CRUD seperately for each type, or use the 'groups' field and the user id to reference the fields in another table? Any insight as to an approach to this common problem?
I would recommend just adding all the fields you need into the meta table and only updating the ones you need per user group. If you need multiple groups per user check out Ion Auth v2.
I had the same problem before, what I ended up doing was building relation tables to handle different groups with different fields. Then I modified the profile() code a bit, to join the additional relation table according to the user's group settings.
I would start off building a relational database.
example:
**volunteers table**
id
user_id
languages
**organizations table**
id
user_id
mission
Then depending on user group, join the table in profile() function.
Hope this helps!
We want to add 4 types(or groups) of users to our website, they should access only associated pages what we allow while creating those groups. So should we set an array of permission and check at top of page if user has permission to view this page or any other way like creating db tables or writing class. Please help.
Normally I'm not a big fan of using Zend outside of a fully Zend application, except with Zend_Lucene, but I would recommend using Zend_Acl in your application, which handles this task transparently to your application. It's quite easy to use, here you have a sample code from the Zend dev:
$acl = new Zend_Acl();
$acl->addRole(new Zend_Acl_Role('guest'))
->addRole(new Zend_Acl_Role('member'))
->addRole(new Zend_Acl_Role('admin'));
$parents = array('guest', 'member', 'admin');
$acl->addRole(new Zend_Acl_Role('someUser'), $parents);
$acl->add(new Zend_Acl_Resource('someResource'));
$acl->deny('guest', 'someResource');
$acl->allow('member', 'someResource');
echo $acl->isAllowed('someUser', 'someResource') ? 'allowed' : 'denied';
Hope I can help,
David
I created 2 tables:
1) Users (ID, Name, Password, GroupID)
2) UserGroups (ID, Name)
Then build a function which checks if the user is in a group. On the top of the page you check this and show the page (or not).
If you want to extend this you can create a table actions and a crosstable, which links an action (access a page or edit something) to a set of usergroups. This way you can have multiple groups on one action. These are those tables:
3) Actions (ID, Name)
4) Group_actions (GroupID, ActionID)
What I have to solve this issue is this:
I have created one table with user levels.
Every time the user logs in, I retrieve this level from the database and save it in session variables.
In every page, I check if the value of the session variable that correspond to the user is allowed to see this page.
EDIT: tO check, I used this function:
function checkPermission($allowedLevel)
{
if(isset($_SESSION['level']) AND ($_SESSION['level'] == "$allowedLevel")){
return TRUE;
}
else{
return FALSE;
}
}
And in the top of every script I have:
if(checkPermission($someLevel)){
// Run the script
}
else{
// Manage unauthorized access...
}
EDIT 2: My tables are like this:
I have a table for levels: user_type(id_level, level) and in the table where I store the user information I have a foreign key to the id_level for each user.
Every time they log in, I get the user information by making a join between the table user and user_type (Since id_level is a foreign key in my user table)