I'm working a site for invoicing and inventory, and I need two different kinds of Authentication, one for clients and other one for users (sellers, administrator). I know it would be easier to have a single table Users with a field like user_type, instead of having Users and Clients but I need this two tables individually because they interact each other and also have differents behaviors. What do you think I should do for an efficient authentication?
I think what you want is permission groups. This way you can add a group called clients and one as administrators or sales. I would look # Sentry by Cartalyst. I use this to manage 13 groups. This also has the ability manage permissions and write conditional statements on permissions.
No idea what your software does but it looks like you need to do some reading on pivot tables.
My guess is that you have "clients", "Users", and "Invoices"? and need each invoice to have a client and a user? Maybe several of either?
All of you members, client or user, in the same table. Make sure to give them all a 'user id' of some sort.
'Invoice' table, same as the last two.
Pivot table would be member_to_invoice. This would be a many to many pivot (i think) and would simply have (invoice_id, client_id, user_id).
This would give each invoice a member and a user. The drawback of this would be that a member type is only set by the invoice. So there wouldn't be a way to have a client log in that was different then a users. Though that might not be a drawback depending on what the system does.
You could set it up the other way as well with another table 'member_type' and pivot that off the member table. This would give you separation in the member types. Then you wouldn't really need the member_to_invoice pivot unless you needed multiple users or clients attached to a single invoice.
Related
I am a novice in SQL organization! I essentially have an inventory app written in php with an sql database. If I want to allow multiple users to create inventories independent of one another using my web app, would I just use foreign keys linked to a user table or should I be creating new tables for each user, or another option that I have not considered?
thank you!
I have said before that it's a code smell if you hear the word "per" in the context of of database design.
I'm going to create a table per user.
That could result in a lot of tables. How many users will you have? Hundreds? Thousands? Millions? Can your database handle millions of tables? How can you test this? Does that mean your application must create new tables on the fly as new users register?
In your application code, would you create a separate PHP class for each user? Probably not -- you'd create one class that can be reused for many users. One of the class data members would distinguish the user, so each object instance of that class is for one user. But it's the same class.
Likewise, it's almost always better to create one table, and make sure the table includes a column to identify the user. It's simpler to add new users by INSERTing new rows into the table, instead of requiring new tables to be created.
There are exceptions to every rule, of course. You might have so many users that you must split the database over multiple database servers. Or you might have a very strict privacy requirement and separating the data into multiple tables is a good way to enforce it. But if you're just starting out with a small project, those exception cases probably don't affect you yet.
The application I have to design is the following:
A group has several functionalities that each user can access and
work with. It is not a chatting group. It it like having data that
each user can add/edit based on his privileges.
Each user can create or join as many groups as he/she likes.
My question is what is the best way to design a database for such task.
Examples similar to what I want to achieve exist on live sites such as:
Deviantart's groups, Trello, Facebook's groups, LinkedIn company pages etc
I have two ways that sound good but I may miss something important:
I was thinking that one database is the best way, and create
associations with the groups and the users. This way though makes me
think about performance. What will happen if/when there will be
thousands or even million of users and maybe more groups available.
Will a mysql database handle all the requests and respond quickly ?
An other suggestion was made to me that I could split each group
into different tables. So when a user connects the requests that
will happen will be only based on the groups he/she has joined. Only to
those tables. With that approach I see a database full of tables
that will not be able to manage later on, as more groups get
created.
Am I overthinking that I will have performance issues ?
Is there a technology that I am missing that could help with my situation ?
This application will be developed in laravel 5 with mysql database and angular 2.
Thank you in advance!
John,
Have a nice and creative day!
A user signs up, they can create a group and follow other groups and add items to groups.
User table design example:
id|email|username|password
Groups table design example:
id|user_id|title|description
user_id = person that created group.
Items table design example:
id|user_id|title|content
user_id = person that added item.
GroupUsers table design example:
id|group_id|user_id|role
role = admin or moderator or follower or whatever you want that user to be able to do for that group. You can have the same user_id assigned to many group_id.
GroupItems table design example:
id|group_id|item_id
I wrote this out quickly and may not be perfect by any means, this should give you an idea of one technique. If you do not understand relational databases. Please go learn.
Let's say I have three tables: users, books, and users_books.
In one of my views, I want to display a list of all the books the current user has access to. A user has access to a book if a row matching a user and a book exists in users_books.
There are (at least) two ways I can accomplish this:
In my fetchAll() method in the books model, execute a join of some sort on the users_books table.
In an Acl plugin, first create a resource out of every book. Then, create a role out of every user. Next, allow or deny users access to each resource based on the users_books table. Finally, in the fetchAll() method of the books model, call isAllowed() on each book we find, using the current user as the role.
I see the last option as the best, because then I could use the Acl in other places in my application. That would remove the need to perform duplicate access checks.
What would you suggest?
I'd push it all down into the database:
Doing it in the database through JOINs will be a lot faster than filtering things in your PHP.
Doing it in the database will let you paginate things properly without having to jump through hoops like fetching more data than you need (and then fetching even more if you end up throwing too much out).
I can think of two broad strategies you could employ for managing the ACLs.
You could set up explicit ACLs in the database with a single table sort of like this:
id: The id of the thing (book, picture, ...) in question.
id_type: The type or table that id comes from.
user: The user that can look at the thing.
The (id, id_type) pair give you a pseudo-FK that you can use for sanity checking your database and the id_type can be used to select a class to provide the necessary glue to interact the the type-specific parts of the ACLs and add SQL snippets to queries to properly join the ACL table.
Alternatively, you could use a naming convention to attach an ACL sidecar table to each table than needs an ACL. For table t, you could have a table t_acl with columns like:
id: The id of the thing in t (with a real foreign key for integrity).
user: The user the can look at the thing.
Then, you could have a single ACL class that could adjust your SQL given the base table name.
The main advantage of the first approach is that you have a single ACL store for everything so it is easy to answer questions like "what can user X look at?". The main advantage of the second approach is that you can have real referential integrity and less code (through naming conventions) for gluing it all together.
Hopefully the above will help your thinking.
I would separate out your database access code from your models by creating a finder method in a repository class with an add method like getBooksByUser(User $user) to return a collection of book objects.
Not entirely sure you need ACLs from what you describe. I maybe wrong.
That's kinda vague so here's the meaty stuff:
I have seen authentication systems that do one of the following
have a separate role table for each roles, and a separate permissions table, all users in one table
have a separate table for administrators
there's a lot that I have missed, I know. But what I'm trying to really ask is:
How should I design my database in a website that I have a lot of kinds of users and each with different access?
How will I make it so that my script is flexible enough if I decide to add another type of user with another type of permissions?
I currently have a User class and am planning to make my Administrator class which extends that User class. Or is that a bit of an overkill when I can have them all in a single class and just assign necessary permissions?
you can have tables -
user (user_id, name ...)
permission (perm_id, name, desc)
role (role_id, title)
user_role (user_id, role_id)
user_permission (user_id, perm_id)
role_permission (role_id, perm_id)
This way you can have as many roles in the system as you require, and you have both role level permissions, user level permissions.
you can add an additional level of abstraction. basically you add a table in your database to manage user groups, and assign group permissions to those groups. different users can have multiple groups.
this way you can quickly change permissions to a predefined set of rules, without needing to change every user separately. you can also change the permissions for a group of users at once
I think you need to think about several concepts here. The first would be an access control list (ACL) and then second would be authentication.
In an ACL, you define resources, which are objects that you want to restrict access to and roles, which are objects that may request access to a resource.
The way I implement my ACL, is using Zend_Acl. I have a table called user_roles
user_roles('user_role_id', 'name', 'permissions', 'parent_role_id')`
I also have a table called user_role_maps that maps a user's ID to a user role ID. (You could just have this as a column on the user table, but that just depends on how you feel about normalisation ;-) .) I can then construct my Zend_Acl object from this table and then, when a user is authenticated, I can determine which resources they have permission to and what actions they can perform on a resource. (A resource implements Zend_Acl_Resource_Interface so it is identifiable by Zend_Acl as a resource.
As for authentication, this is a simpler concept (in my opinion), you've probably already figured out some form of token matching authentication system yourself. The crucial aspect is using the authenticated user's ID to determine their role. The Zend Framework also provides a package for this in Zend_Auth.
I've used a lot of Zend Framework recommendations here, the reason for this is that their packages have very few dependencies on other packages, making it quite simple to plug components in. I'm sure other frameworks provide ACL packages that you could use, or roll out your own if you have the time and understanding.
Good Luck.
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.