User permissions with accessing some data, from a MySQL database, with PHP? - php

I have this simple MySQL table, which I called data_table:
/--------------+------------------+-------------------\
+ data_id + data_content + addition_content |
+--------------+------------------+-------------------+
+ data_1 + data_content_1 + comment_for_1 |
+ data_2 + data_content_2 + comment_for_2 |
+ data_3 + data_content_3 + comment_for_3 |
+ + + |
+ ... + ... + ... |
+ + + |
+ data_n + data_content_n + comment_for_n |
\--------+-----+------------------+-------------------/
To help users can submit their data to my database, I have created a simple HTML form (with PHP core) for easier data submission.
For getting data from this table (data_table), I have used this query (from my_query.php):
// ...
$var_get = $_GET['url'];
$query_1 = mysql_query("SELECT * FROM `MyDB` WHERE `data_id` = '{$var_get}'");
while ($query_2 = mysql_fetch_array($query_1))
{
echo $query_2['x_2'];
}
// ...
Anyone can see any result (from echo $query_2['x_2'];) when they access my_query.php page with a $_GET[]; value.
Now, I don't want to allow all people can access any data from my website. So, I decide to allow the access-permission to certain users only; and, I have an idea:
I will create a new MySQL table (user_table):
/--------------+------------------+-------------------\
+ user_id + user_name + user_password |
+--------------+------------------+-------------------+
+ user_1 + user_name_1 + password_1 |
+ user_2 + user_name_2 + password_2 |
+ user_3 + user_name_3 + password_3 |
+ + + |
+ ... + ... + ... |
+ + + |
+ user_n + user_name_n + password_n |
\--------+-----+------------------+-------------------/
Then, I will add a new data column (data_owner) to existed table (data_table). Every record (data line) will be have a owner; this owner is the existed user (in user_table) who submitted their data to my website.
Finally, I will add a new data column (allowed_user) to existed table (data_table). Every record (data line) will be have some allowed users; these allowed users are existed users (in user_table) who are allowed to see result (from echo $query_2['x_2'];). If someone is not an allowed user (from certain record), they won't see the real data.
My idea is not bad?
Sorry, programming is not my job; so, there are some limitations in my programming skills. Can you give me an example, please?

What you are describing is a basic login/auth system for users.
https://www.phpro.org/tutorials/Basic-Login-Authentication-with-PHP-and-MySQL.html
With this in place, users should only be allowed to update their own records.
If you would like admin users, or moderators, you could set up a simple Access Control List.
eg:
CREATE TABLE levels(
id int not null primary key auto_increment'
name varchar(20) not null
);
INSERT INTO levels(id, name) values (1,'admin');
INSERT INTO levels(id, name) values (2, 'moderator');
INSERT INTO levels(id, name) values (3, 'guest');
When a user logs in, you can check if they have moderator, or admin privileges to look at other user data.
There are also ACL implementations ready to go if you wish to use an existing solution.
Kev

You need to create one more field called role
for example: user_id,user_name,user_password,user_role
while register you need to pass role type as (admin,superadmin(optional),publisher,guest) you can add whatever you need in the role.
based on role you will need to give permission.

No, I don't think so! Your idea is not the best fix for the problem.
What you really need is an Access Control List just like Kevin Waterson said
I wouldnt advice you to implement your own ACL though. You could check out this ACL Library on GitHub, it's one of the best ACL Libraries for PHP out there, it doesnt have too much learning curve (if at all it has any) and it just works.
If you were to use the Samshal\Acl Library which I linked to above, the following snippet will help you protect your resources:
$permissionManager = new \Samshal\Acl(); #<-- Instantiate the ACL Class
#When you create a new data, add it to your ACL by doing
$permissionManager->addResource('data_1'); #<- data_1 is the id of your newly created data
#You need to also register users to the ACL
$permissionManager->addRole('user_n'); #<- user_n is the id (probably the username) of your just created user
#Then grant permissions by doing:
$permissionManager->user_n->can->view('data_1');
#Or deny permissions by doing
$permissionManager->user_n->cannot->view('data_1');
Save a serialized$permissionManager in a database or file and voila! You have successfully just protected every resource.
The library has other cool features too like allowing you to grant edit, create, delete or even allow you to create and attach an entirely custom permission like approveDataContent permissions on your resources.
You can visit https://github.com/Samshal/Acl/blob/master/README.md to learn more about the ACL library

Related

Laravel - php Identifying multiple check in / check out in attendance

We are developing a simple attendance system based on Laravel Framework. We are new to Laravel framework.
We use the basic auth system of Laravel. The user can check in / check out using the system. While doing,the user is supposed to take a photo of their own and we also get the location details from browser.
For attendance, we have the following schema:
id (primary Key) (int)
userid (int) (foreign key to id of the user table)
status (boolean) ( 0 - out / 1 - in)
attendancedatetime (datetime)
gpslat (float)
gpslon (float)
photourl (varchar)
Now we wish to avoid check-in/check-out by an user within few minutes (say for example within 10 minutes).
Also, we wish to avoid multiple check-in or multiple check-out by the same user at a time.
Is it possible to do this in Laravel Controller?
Will this provide any solution to our problem?
Firstly Find out last checked details by
select max(time(attendancedatetime)) as last_checked_time
From<TableName>
WHERE userid=<USERID> and DATE(attendancedatetime)=<Current Date>
after that in Laravel, compare this returned last_checked_time with current time. If it is less then 30 minutes return false else run your insert statement!

Role Hierarchy...Kinda

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.

User Access Levels on PHP

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.

User permissions fine-grain control PHP MySQL

I am building a web app which users use to assign tasks to each other.
The users are all on a LAN.
There is a basic permissions system already, where user roles are either Admin or normal user.
What I have to implement is something really fine-grained...and I cant think of a good way to do this
Heres a list of things I need to have control over:
If a user can change other users info
If the user can access the LAN network via VPN(this is another challenge all together, i think)
Users can assign tasks to only a set of other users(maybe all, maybe few)
If user has the ability to change/delete an already assigned task from another user
If the user can delete other users
If a user can change other users permissions
What I want is an example of something similar so that I dont have to re-invent the wheel. Or maybe an idea on how to implement this with as little headache as possible :P. Also I dont know how I would structure a MySQL table/s to store all these permissions.
I thought of assigning users roles but I need more flexibility than just those roles.
Any ideas?
One simple approach is to only have one extra column in the user table, called Access, Permission or something like that. Then for each of the permissions you want you define a constant with a integer value that's dividable by 2, or the number 1, e.g:
class PermissionChecker {
const CAN_CHANGE_OTHER_USERS_INFO = 1; // in bit form: 000001
const CAN_ACCESS_LAN_VIA_VPN = 2; // 000010
const CAN_ASSIGN_TASKS = 4; // 000100
const CAN_CHANGE_OTHER_USERS_TASKS = 8;// 001000
const CAN_DELETE_USERS = 16; // 010000
const CAN_CHANGE_USER_PERMISSIONS = 32;// 100000
public static function hasAccess($userAccess, $accessFlag) {
return $userAccess & $accessFlag; // The bitwise operation is the key....
}
}
$userAccess = 33; // read from database, in bit form: 100001
// check permissions like:
if (PermissionChecker::hasAccess($userAccess, PermissionChecker::CAN_CHANGE_OTHER_USERS_INFO)) {
// this will be true, because 100001 & 000001 returns 1
}
if (PermissionChecker::hasAccess($userAccess, PermissionChecker::CAN_CHANGE_USER_PERMISSIONS)) {
// this will be true as well, because 100001 & 100000 returns 1
}
if (PermissionChecker::hasAccess($userAccess, PermissionChecker::CAN_CHANGE_OTHER_USERS_TASKS)) {
// this will not happen... because 100001 & 001000 returns 0
}
Then when another permission level is needed you only have to add another number that's dividable by 2, e.g. 64, 128, etc. Maybe not the prettiest solution, but a simple one.
And when you want to store permissions for a user you use the bitwise-or operator, like:
$userAccess = PermissionChecker::CAN_CHANGE_OTHER_USERS_TASKS |
PermissionChecker::CAN_CHANGE_OTHER_USERS_INFO; // will give $userAccess = 9;
// then store $userAccess in the database for current user...
One option is to use a database table to store the permissions where a row is a single permission. If a permission is not present in the table for a given user_id then that user does not have the permission.
user_id | permission
-----------------------------
1 | CHANGE_USER_INFO
1 | DELETE_USERS
1 | CHANGE_USER_PERMISSIONS
2 | VPN_ACCESS
As you can see, user 1 would be able to change info, delete and change permissions. User 2 can only access the VPN. This would be easy to add and remove permissions, you'd just need to insert or delete. It would also be easy to create new permission types in future.
To address your point number 3. That one would be more complicated. For that you could have another table with columns user_id and target_user_id where you would insert the user_id of which users can assign tasks to. Alternatively you could add another column to the table above like a generic ID, then insert ASSIGN_TASK and populate the ID column with the target user.
Allow the administrator to define roles, as well as define which powers to give each role. That can be done with a bitwise comparison (good), or with a many-to-many relationship database tables (better).
This system gives you most flexibility, as it easily allows you to add new abilities without reconfiguring the whole system of roles.

Saving a visible user log

For an application, I need to save user logs that come in different formats, like account changes among application specific changes. The over goal is to have a twitter like news feed about their account and global sent messages.
The problem is I'm not sure how to save this information. For an example, say the user has submitted a support ticket. I would want a message on their feed to display: "Ticket "I need help" has been submitted to the Help Desk" Where the title would be a link to the their ticket.
Would it be wise to save the entire link in the message? I personally don't want to, because the title of the ticket could change or the location could be changed as well. I have thought about saving the ticket id along with the message in its own column, but then what about other message that don't use ticket id and instead another id? Would I create a new column that way?
Let me know if more information is needed. Thanks for all the help!
just do a templating approach
+--------------+
+ event +
+--------------+
+ id +
+ user_id +
+ type +
+ custom_id +
+--------------+
id is your key autoincrement
user_id: your user key
type is a type for example send_message, created_ticket whatever your application need to log
custom_id is just a number if type is send_message maybe the message id, if created_ticket the ticket id, what ever id you need to identify the ressource
you can use the custom_id and type to fetch the link title.

Categories