Handling roles by dividing users in multiple tables/models - orm

My application has several kinds of users with different sets of properties, for example: customers and employees. One user may be belong to more than one of these roles.
So I decided to have this (simplified example) structure of my database:
users (contains the fields applicable to all different kinds of users)
id
username
email
customers (contains fields applicable to customer role)
id
user_id
shipping_address
employees (contains fields applicable to employee role)
id
user_id
salary
Question 1: Is this a good way of handling user roles with many different properties?
In reality I have six roles with sets of 7-20 properties. Some of the roles are not even conventionar roles, but bore like extra properties. If a user decides to login with a Facebook acoount, then the Facebook_account table is applicable.
Question 2: When using an ORM, in my case Eloquent, would it make sense to have the role model (customers) extend the user model?
When I fetch a customer object I really want all user och customer properties together, without having to merge them manually.

Related

Database design for individual and group sign up

I need to create a system that allows both individual users and groups (e.g., a company) to sign up for a subscription service.
The procedure for signing up for a group membership will involve a user paying for as many users as they require (e.g., 5) at sign up. Once they have paid they will be able to create these other users (i.e., have admin functions) that will be associated with this group (e.g., other members of their company). (They will be able to pay for more users for their group at a later date if they wish.) A user cannot be in more than one group. The original person that signed up on behalf of a group can assign admin roles to these newly created members.
For login purposes, I would like to have both individual users and group users in the same table of the database. For example, it could be called and have columns (to keep things simple):
user table:
user_id
username
I then thought that there must be a second table that shows the links between users (i.e., which belong to which group). Let's say that this is:
groups table:
group_id
user_id
I am guessing that this is a one-to-many relationship as many users can be in one group, but each user can be in only one group.
In order to assign the proper roles to the user that signed up on behalf of a group there would be another table called:
roles table:
role_id
user_id
This would allow some users to have permissions of admin rather than just user. I would then just have to lookup the user_id's of the admin role (a specific admin user_id) when they logged in and this would give them access to the correct people in their group.
Before I go ahead designing this database I was wondering if this is an appropriate database design to go about creating these individual and group users or if there is a better setup?
FURTHER INFO: There are two sign up forms: an individual sign up form and a groups sign up form.
For an individual, we will record their "username", their user_type (individual) and assign them a role of "user". They do not need to be assigned a group id and we will not need to convert their membership to a group membership later on.
For the user who signed up as a group using the group sign up form, we will record their "username", their user_type (group), no. of memberships purchased (e.g., 5), a group id (e.g., a unique integer) and assign them a role of "admin". Because they have purchased multiple memberships, they will be able to create/add new users to their group upto the number purchased. They can assign each new user a role of either "user" or "admin". A role of "user" in both individal and group membership has the same permissions, so there are only two types of role.
As such, I had planned a createUser() function that creates:
For an individual: username, user_type(individual), role(user)
For a group: username, user_type(group), group_id, no_purchased, role(admin)
For a new member of a group (created by admin): username, user_type(group), group_id(the same as the admin), role(admin or user)
I had then planned to create a checkUser() function that:
Gets their id, username, etc...
Checks if they are an admin or user.
If admin, then gets the users/admins that are in the same group as them.
Most calls to the database will be to login (i.e., username/password). I was looking to see what the simplest database structure would be for this situation.
I feel like you might make your life simpler if you consider individual users as groups users with only one member. This will also give you flexibility in the future if an individual user would like to expand into a group?
On the other hand you can keep it as you have it but I wouldn't bother specifying the user type. That can be derived based on if they belong to a group or not.
Many ways to tackle this problem...

1 to 1 database design

I have a database and normally users are the central object.
In database I have a tables roles and users in roles so I can give users different permissions on site.
But now I have one doubt.
I saw before one database with structure like this (User is in 1:1 relation to other tables):
User{UserId, Username, Email etc.}
Admin{UserId, some specific columns}
Child{UserId, some specific columns}
Admin{Parent, some specific columns}
and other tables are connected to user not through User table but through Admin, Child and admin.
Because now I design my database I have Users and user can be Admin, CompanyManager and Professor.
I wonder should I design table like I show above or just relied on roles?
What is advantage of the first approach?
And also in my business model User doesn't have to be CompanyManager or Professor so this is actually 1 to 0 or 1 design.
What is a good way to design database with scenario like this?
The advantage of having specific tables for certain types of users is to store information that is only relevant to that class of user.
In your example,
perhaps all users would have a manager - so the manager ID would go in the users column.
managers would have permissions to view certain information, so this would be handled via a role.
only professors would have a Subject, or the "HasTenure" property. So this information would go in a professors table. Using this approach, you avoid the need to have a "Subject" column in the users table, when it is only applicable to a certain subset of users. As such you avoid a functional dependency in the users table, and a violation of 3rd Normal Form.
I prefer this approach:
In this way, you can easily group Roles into categories and assign them to users.

Database design relations in User and Profile

I'm designing a web application for a school. So far, I'm stuck with the database which has these tables:
users
id
username
password
profile
user_id (FK)
name
last_name
sex
group_id (FK)
(other basic information)
... And other tables irrelevant now, like events, comitees, groups and so on.
So, the users table stores basic information about the login, and the profiles table stores all the personal data about the user.
Now, the *group_id* column in the profile table has a foreign key that references the ID column of the group in which the user is currently enrolled, in the groups table. A user can only be enrolled in one group at once, so there's no need for any additional tables.
The thing is that it doesn't make much sense to me declaring a relation like group HAS MANY profiles. Instead, the relation should be group HAS MANY users, but then, I would have to put a *group_id* column on the users table, which doesn't really fit in, since the users table only stores auth information.
On the other side, I would like to list all the users enrolled in a group using an ORM and getting the a users collection and not profiles. The way I see it, is that the users table is like the 'parent' and the profiles table extends the users table.
The same problem would occur when setting attendances for events. Should I reference the profile as a foreign key in the events_attendance table? Or should I reference the user ID?
Of course both solutions could be implemented and work, but which of them is the best choice?
I have dug a little and found that both solutions would comply with 3NF, so in theory, would be correct, but I'm having a hard time designing the right way my database.
This is a question of your own conventions. You need to decide what is the main entity, right after that you can easiy find a proper solution. Both ways are good, but if you think of User as of the main entity while Profile is a property then you should put GroupId into User, otherwise, if you mean User and Profile as a single entity, you can leave GroupId in Profile, and by this you're not saying group HAS MANY profiles but group HAS MANY users.
By setting a proper one-to-one relation (User-Profile) you can force your data integrity good enough.

use of views for validation of an incorrect login-id or an unidentified user

I read this on msdn:
Views let different users to see data in different ways, even when they are using the same
data at the same time. This is especially useful when users who have many different interests and skill levels share the same database.
For example, a view can be created that retrieves only the data for the customers with whom an account manager deals. The view can determine which data to retrieve based on the login ID of the account manager who uses the view.
My question:
For the above example , i would have to have a column named Userid/LoginId on my table on which the view is created so that i can apply a check option in the view for this column. and then if a user with a name not in that column tries to enter data , then he/she is blocked.
Yes, you are right. You should
add a column with the user's login or database user name (say you call it username),
each row should have username populated with the login or database name of the person who is allowed to see that row
you can then build a view where you use the builtin functions SUSER_SNAME() (for logins) or USER_NAME (for database names) in your WHERE clause to filter only the rows the user is allowed to see
See Granting Row-Level Permissions in SQL Server (ADO.NET).
You don't have to add a column to the table: it could be more appropriate to instead add a new table to model the relationship.
There's a deisgn rule of thumb that states a table should model an entity or a relationship but not both. Let's say the table in question models the companies a customer owns (i.e. an entity table) and the business rule states the the account manager can only see companies relating to customers he looks after.
Is account manager an attribute of a company? No, so account_manager should not be a column (attribute) in the Companies table.
Is there a direct relationship between account_manager and a company? No, so a relationship table between is not due here (because the relationship is indirect).
Rather, the direct relationships are between account manager and customer, and between customer and company respectively. There should be two tables whose sole purpose is to model these relationships.

Is it better to have roles as a column on my users table, or do it through join tables (Roles & Assignments)? - Rails 3

You can see my models here:
https://gist.github.com/768947
Just to explain what is happening, I have a few models. At the core of my app, there are: projects, stages, uploads, comments, users. Then there are roles & assignments to manage user authorization.
I am doing this with the plugin declarative_authorization & devise for login.
So the first question is, is it better to just add a column of 'Roles' to my user model/table and store the roles for each user there? If I have a user that has multiple roles, then I can just store all the roles as an array and cycle through them as needed.
Or is it better to do it like I have it setup now, where I use two separate tables and a bunch of joins to setup the assignments? I only have 4 roles: designer, client, admin, superuser.
Better in the sense that it is 'less expensive' from a computing resources standpoint to do each query with the column, than with the joins or is the difference not that significant?
I guess, the root of my question is...right now if I want to get a project assigned to the current_user I simply do current_user.projects.each do |project| and cycle through them that way. This is after I have done: #projects = current_user.projects in the projects controller. The same applies for all my other models - except Users & Roles.
However, if I wanted to find a user with role "client", it becomes convoluted very quickly. Or am I overcomplicating it?
Any help would be appreciated.
I think it's better to have user and role tables that are separate. It's a many-to-many relationship, because a user can have many roles and many users can have the same role. You'll need a JOIN table (e.g. user_role) to do that. I'd recommend three tables. Of course you'll have primary keys for both user and role; the user_role table will have two columns, one for each primary key, and foreign key relationships to their respective tables.
So now if you want all users with the role "client", it's an easy JOIN between user and user_role. If you want a particular user's roles, you'll need to JOIN the three tables.
I would not recommend an array of roles in user. It goes against first normal form.