Proper way to design an inventory system - php

I am a pretty good programmer but I am not great when it comes to designing system architectures. I have a pretty simple inventory system I am making however I would like to know a good way to structure it.
I have around 20 pieces of equipment that users can [View All | Update | Delete | Add] each of them. However I have different access levels for different equipment (which needs to be dynamic, change who can view or delete what).
For example, one piece of equipment would have?
addPart1.php
removePart1.php
updatePart1.php
index.php (view all parts)
addPart2.php
removePart2.php
updatePart2.php
index.php (view all parts)
For all parts? Im confused on trying to design a good, scalable and efficient structure.

An access control list (ACL) is a list of permissions attached to an object. An ACL specifies which users or system processes are granted access to objects, as well as what operations are allowed to be performed on given objects. In a typical ACL, each entry in the list specifies a subject and an operation (e.g. the entry (Alice, delete) on the ACL for file WXY gives Alice permission to access file WXY).
Source: WIKI
Please take a look at:
http://dev.juokaz.com/php/acl-made-easy-part-1 (tutorial on ACL)
http://sourceforge.net/projects/tackle/

You could categorize your products table, so each kind of equipment has its own "category" or "group". You can do that by assigning a "group_id" to each product (on a new column on your table). If you have 300 products, some of them will be on group 1, others on group 2, etc.
Then, on your users table (the one that contains usernames/password for each admin), you need to add an additional field called "group_permissions". On that field you have to store a list of "group ids" each user can view. You can store those permissions separated by comma.
$permissions = '1,2,5,9';
Each time a user access one of your PHP files, you get its permissions and do a simple check like this:
SELECT * FROM products WHERE group_id IN($permissions)
That will only return the products that user has permissions to edit or view. This will vary depending of your interface.

Related

How to properly extend a database model with PHP

I know that the title of this question is not intuitive, but let's go to the question.
I've designed a "core system" for all my backend web apps (control panels, systems to manage clientes, balances, etc). This "core" is the start point for developing new modules according to the new system specific needs, but I always keep the "core modules":
Users (to manage user roles)
User type (in distinct systems there are distinct kinds of users, so it's nice to manage them dinamicly)
Modules (to create new modules and add permissions to them)
Dashboard
My main question is for the User module. Since it has the default columns
UserId; Name; Login; e-Mail; Password; isRoot; isPowerUser; UserTypeId
I want to create new control panels and apps, but dont want to change this table to keep the "core" updatable with an easy process in the future. My ideia of design is to create table named User_Extra which will contai all the extra columns for this specific user.
Is this a good approach? I'll also will create a new class named UserExtra.class.php.
If u want to take a look at the project to get the ideia: https://bitbucket.org/alexandrekop/akop-core
Imagine looking at your database schema, and seeing a table named "user_extra" with a bunch of fields that aren't related to each other in any way and each field is related to a different module, does it feel 'right'?
My suggestion is to split the extra fields into relevant tables, possibly per module, or per logical group.
For example, if one module was related to addresses, you would have a table "user_addresses", with things only specific to the address of the user.

Best Practices: Creating a simple CRUD web application with users/roles

After searching online a good amount, I couldn't find anything that was exactly what I was looking for or that outlined how to create a web application with users. The closest thing I could find was this stackoverflow post, which outlined how to create a web application with users/roles on a SQL server.
I also found a couple alternatives from this post.
Create a simple relational database
make a 'meta-table'
I'm creating a web application on CodeIgniter that is a wine management tool, similar to CellarTracker. Each user has their own 'cellar', or collection of wines that they can perform the CRUD operations on. What would be a conventional way to make this. How should I structure the database? Are there any CI Libraries that would make User-management, roles, permissions, etc. easier?
(I have already found that TankAuth seems like its the best authentication library).
Here's how I would structure (part of) the database:
**users_table**
id
email
password
**wines_table**
id
user_id
My plan is to have each bottle of wine have a user's id associated with it. I doubt that this is the most secure or efficient way to handle a CRUD web application with many users though.
I have experience with the CRUD operations, but am not sure how I can connect them with a user-management system.
consider having a completely separate table just for wines that is not associated with users.
this table has wine parents and children. the parent contains fields for the winery, the name of the wine, location, etc. the children would be the specific years of the vintage.
so a user enters a wine name in his tracker. the system looks it up - if its not found then the user creates the record. system creates a parent record and a separate child record with the year.
if the wine is found - then the user can update the parent record, and either chose a year, or enter a new one.
system would then add a record to a separate table - users_wines - with the id of the parent (the wine) and the id of the child (the specific year)
this opens up many different possibilities including having wine lists that are shared by groups of users.
you also can easily change the relationship of the user and his wine bottle - because they are separate. the user can change status on users_wines - wine in cellar, drinking the wine, empty wine bottle - and this does not affect the record for the wine itself.
====
Edit - yeah mentioning the wine.com api would have been good info. that gets into much larger questions. suggest that you first define what your users are able to do. My first question is - what if a user does not like the name coming back from wine.com? and what if there is an actual mistake in the api? are you going to customer service a wrong wine name coming back from the api?
Or - Can a user rename a wine in their list? if they can then the data relationship with wine.com is going to be very different.
personally i would think it would be annoying to try and create a wine list, but you cant edit the names. it seems like thats removing too much control from the user.
however if this is an app for restaurants that need accountability - then having the wine name be unchangeable could be considered a feature.
so spend some time with your user roles and user stories. then let that inform the data relationships.

Complex Righty System: ACL, RBAC and more what?

We are currently developing a project management software. And we are having trouble deciding on the correct approach to implement security. We have looked at both ACL and RBAC and are already pretty certain that we need at least a combination of both for specific reasons. But there are a couple of problems that do not have a nice solution in either world. Let me explain:
Let's say you have the following entities:
Users, with different roles, i.e.
Project Lead
Worker
Admin
Projects
Assigned Users
Tasks in Project
Now the following rule should be expressed:
A User with the Role Worker is only allowed to view Tasks, which are related to a project he is assigned to.
This results in that a User is only allowed to view some Tasks in the whole list.
We would use RBAC to give Roles the permission to actually read Tasks. But the condition is not applied as there are specific entities involved. ACL could be used, but we fear the nightmare of keeping the ACL entries consitent with the requirements (Users can change, Roles can change, new Tasks can be introduced an would have to get the correct entries, which is just as complex).
Of course there could be specific queries when viewing a specific project (WHERE project_id = 123), but this does not help for a "View of all my current Tasks", where basically every task can be considered for display, but the ACL would have to be checked for every single entriy.
And how do I ensure things like "Get the first 25 Tasks the current User is allowed to see" without loading all the tasks from the DB and then filtering based on the ACL, i.e. handling pagination.
You need to look beyond ACL and RBAC and consider attribute-based access control (ABAC - see NIST's guide here). Gartner calls this space "externalized authorization management".
With ABAC, you can easily express any rules that take into account not just who the user is but also what the user wants to do, where, when, why, and how. Using attributes to define authorization, you can use XACML to implement policies. XACML is an OASIS standard (just like SAML).
With XACML, you get an API where you can ask questions e.g.: can Alice view this record? But in your case, it's not enough because you want to filter out records from the database. And, as you describe, you want the query to be the right from the start rather than going back and forth to the database until you have the right number of authorized records. This is where XACML becomes particularly interesting because it's technology-neutral. You can apply XACML to Java, C#, and other languages e.g. Python but also apply XACML to different layers (presentation, APIs, and... databases). XACML can be queried in a reverse query way to produce a SQL statement which you could then use to query your backend database for the relevant records:
Which records can Alice view?
Alice can view records in California which yields "SELECT * FROM records WHERE location='CA'"
HTH
Well, I use Yii framework with its nice RBAC layer. I'm not too familiar with ACLs, nor did I need to be, lately.
In Yii RBAC terms, your key to the solution is using 'business rules'.
Bizrules are small snippets of code that are attached to a 'permission' or a 'role' (an 'auth item' in Yii's terms). This code is run dynamically when the need to determine access to a certain 'permission' (lets say, but it could also be attached to a 'role'), and it recieves the 'item in question' (task in your example) and determine actual access to the specific task or not.
Here's a more detailed example:
say you need to have the following permissions:
Edit task (which should be allowed to anyone with the role 'tasks administrator')
Edit own tasks (which should be allowed to the person who submitted this task).
Now, in the 'task edit' code section, you would first check for 'edit task' permission. if ok - allow.
if wasn't allowed, also check for 'edit own task' (using else-if construct). Now on the last mentioned permission there should be attached a bizrule (=php code) that accepts a 'task' object and compares its 'creator id' to the 'currently checked user id'. If equal, it returns true, meaning access should be granted.
That's in a nutshell. If you're interested in more, see this section of the official guide. There are also a bunch of other resources, should you need.

How to implement a permissions system that varies according to the values a user is attempting to save?

The context is a educational administration system built on the Zend Framework. We are implementing a RESTful MVC to handle pretty much all data interactions with clients. Relationships between resources are mapped in the database with foreign keys etc.
Example case: a teacher creating a report on a specific student.
We currently have a role-based permissions system that can be tailored to the level of the individual role (using, eg, teacher_5 as the role name). Therefore we can easily restrict access to an already existing report (by generating permissions in the report model that allows edit/put permissions on the report only to the tutor role who created it, say). The problem comes on creation. In order to add a report a user can post to /reports, say, the following data:
{ achievement: "4", performance: "5", student_id: "10" }
The problem is that tutors are only allowed to create new reports on a certain subset of student_ids - those students that they are teaching.
One approach would be to treat this as a validation issue on that field. The issue with this is that we want to protect ourselves from making mistakes, and that is not easy to do with validation (the code would have to know in advance that special validation is expected on certain fields).
The other would be to somehow extend our permissions system to a completely granular one (i.e., there would be a permission for every field in every model), and then extend our current permissions system to responding to paramaterised permissions checks. So if we wanted to know if the current user has permissions to add student_id 10 to a report on creation, we would end up with something like
if ($acl->isAllowed($resource, $role, $action, $field, $value))
where $resource would be a report model, $role would be the teacher teacher_5, $action would be "post", $field would be student_id, and $value would be 10. The acl class would essentially handle a call to the $resource itself.
We are not sure which direction to take, but presumably this is a fairly common issue, so we are wondering what approach other people have taken.
What about having another table containing the student_id's that each teacher tutors. Then you can easily check if the teacher is allowed to do the insertion. Another benefit from that solution would be the ability to extract statistics about the whole class, like average grades, attendance etc

Access control for multiple users in a web application

I'am working on a PHP + MySQL Social Networking application, now i need to setup different access control (read,create,edit,delete) for global (all items) and/or self items (item which created by themselves) for each module to group or specific user.
Does anyone has suggestions in doing this (table structures, etc)?
okay here i provide more detail, currently i have a tbl_module, tbl_user, and tbl_user_role. Each user and role can have different access to specific module.
read
update
create
delete
and devided by global access or self only (own account or records created by themselves).
and my current approach: i create another table to hold the access detail:
acl_uid
mod_id (fk module uid)
target_id (fk user uid or role uid)
acl_type (user/role to identify the target id reference)
acl_read
acl_update
acl_create
acl_delete
acl_read, acl_update, acl_create, acl_delete value ranges:
0 deny
1 allow
2 refer to lower priority check (if user has value 2 then refer to role)
3 self only
i believe that theres more efficient way to solve this, or may an improvement to my current approach.
thanks for your responses.
That's a pretty broad question, so you're likely to only get very broad answers.
Most CMS systems have a table that lists the types of content that can be produced on the system.
Another table describes how each type of content is displayed (on the front page, on individual blog pages, etc).
Another table gives each user one or more "user types" or "groups" such as admin, unregistered, moderator, etc.
A last table is an access table of sorts - it shows what each group has power to do, including the types of content it can create, edit, publish, etc.
I recommend you spend a little time studying the database schemas of other CMS software, such as Slashcode, Drupal, or one of the other millions of CMS systems.
-Adam
It is in fact a very broad question. Assuming you have a clear separation of application tiers (eg, using MVC), then this is the sort of stuff going in the business layer.
Taking your direct requirements, it could be fairly simple. In your users table, have a hasEdit, hasView, etc. For each item, attach a userid to it representing the creator. In the business layer, the rule is they have edit permission if they are the creator, or they have hasEdit = true.
Taking it up a notch, if you have different types, and the hasEdit permission is per-type, you need another entity for that.
userPermission
userPermissionId
userId (FK)
typeId (FK)
hasEdit (boolean)
hasView
etc..
To find out if they have permission to edit, you check if either they're the owner, or look up that items type and the current user in the userPermission table, and check hasEdit. You could make additional rules, like putting a global hasEdit in the user table. Or representing global hasEdit by an entry in userPermissionId with a NULL typeId.
This can get way more complex, using roles and variable numbers of permissions.. it all comes down to your requirements. You need to carefully spec out your business requirements (come up with a bunch of use cases), and then you can design from there. As is, there's really not enough information to come up with anymore than I've outlined here (and even this is probably not exactly what you need).
I like to use a kind of firewall rules approach or similarly a mysql tables rules approach: you can grant users or groups of users certain rights on certain objects or groups of objects. Make each rule be a row in your rules table. When you need to do an action like edit, you can inner join on your rules table for the current user, current user's group, the boolean edit column and the object id or object group. If you get any rows back then the permission is granted.
There are quite a few ways of designing security, and I've liked quite a few for different situations. There's UNIX-style user-group-other. I happen to like PmWiki's security model.
I developed a website which used user-role-permissions structure similar to Apache. With that website, I used a template system that used a header include file and a footer include file to wrap the page contents with the "standard stuff". A page with restricted content could set a variable to the required permission, that the header script looks for, and if set, calls an auth function that checks the user belongs to a role that permission.
The nice thing about using the user-role-permissions model is if most of your users fall into neat categories of authorization, setting the authorization for a user is a simple matter of adding the right role to that user. The permissions are linked to roles, not users directly, so you can adjust the permissions of entire classes of users easily.

Categories