Human relations between users - mysql

I'm involve in a development of a tiny Social Network where users must be able to establish relations between them and also have permissions over contents. For a example: I add one user as my friend but this user doesn allow me to see all his/him contents so I only have access to those contents that user allow me (permissions). So I have a problem and need help designing the DER of this part. I think in have this tables:
- users (id, name)
- relations_type (id, name, active)
- users_relations (id, id_user_1, id_user_2)
- users_permissions (id, id_relation, id_module, id_user, view, edit, delete)
This cause the following:
Two rows for every relationship: User 1 > User 2 and User 2 > User 1 because when I search (SELECT) I need to know which are User 1 friends and also which are User2 friends. If I leave only one way relationship then I need a UNION and this migth slow my DB
Is that correct? How yours handle this when CRUD on this? I'm using MySQL by the way and MyISAM tables.

Don't use user1 and user2 as table names, you're going to forget which is which when the scope expands.
you can denormalize permissions on the users table, you don't need to divide tables for a few boolean bits.
never count on union, it will betray you in the least expected situations.

Related

best practice for designing system with multiple user type

We have a system with two main roles: service provider and customer. The provider side is users like doctors, nurses, and caregivers. The customer side is just the customer. all user types contain some common data and some uncommon data. in the current system, we have a table for each user type, and for common data, we have User table. currect system ERD is:
https://s4.uupload.ir/files/screenshot-20210710165449-1007x662_tpwd.png
in the current system, we have a lot of tables and we think about reducing them. our vision is to bring all user types in a single table called User and instead of a lot of tables, we have more columns. of course in some users, we have empty cells that do not belong to this user type.
I have 4 questions:
is it ok to bring customers and providers to a table like User?
what is the optimal number of columns in a table?
load a row with a lot of columns OR relation between different tables?
provider type should be a separate table or can be an enum?
It is best to put all users in single table. So when you check login there is less place to do mistake. When selecting user you dont need to use SELECT * FROM... You can use SELECT id, username, name FROM...
Dont put too many columns, if there is some data which you dont need when searching or displaying users, you can create helper table "user_meta" with dolumns user_id, meta_key, value where user_id and meta_key are primary key
Answered by first 2 answers
Provider type should be enum if there will not bee needs to expand with additional types.

Do I need more than my current 3 tables in order to create the relationships explained in my post?

I'm trying to create a clone of a very popular application called Discord which allows people to communicate over voice, video, and text.
Discord allows every user to create their own servers and invite people to them. In order to allow users to create servers, I first created 2 tables - users and servers
Users table:
id, username, password
And
Servers table:
id, name, image, userId
So the relationship between these 2 tables is that a user can create and have many servers and a server belongs to a user. So far, so good.
Once a server is created, users can join the server as members of that server. A user can join as many servers as he wants and a server can have many members. I achieved this by creating a server_users junction table and a many-to-many relationship between users and servers:
Server_Users table:
id, userId, serverId
This works fine, however, I'm not sure if the logic behind the many-to-many relationship between users and servers is sound. To me it seems like I'm applying 2 relationships between users and servers and I don't know if this is correct. Maybe I need more tables to make the relationships clear?
User has many servers and a server belongs to a user ( Because a user is the owner/creator of a server, and the server belongs to only 1 user - his creator )
Server has many users and users have many servers ( As in every server can have many members and every member can be a part of many servers )
I think it's good design, almost a textbook example. The goal is that the tables are in normal form, which is the case here.
An alternate design also with three tables, if you would like to "merge" the two relationships, is to also use Server_Users to store the user who owns the server, marked as such with a boolean column. However, I think it is more efficient how you did it with a foreign key (userId), as you will only need one join for the 1-to-N relationship.
I would also add that the design of the table is not only motivated by getting this right "theoretically", but also by your use case. Picking a design depends on the kinds of queries that you will run against the database. If you list all users on a server including the owner, but never the owner alone, then the alternate approach may be faster.
Another aspect is integrity constraints: do you require that the owner of the server is also a member of that server, or is it fully independent? This also influences the design.
An alternative in the context of large quantities of data that do not get updated often, is to denormalize everything, by nesting the users (replicated) inside the server tuples.
I think your approaches are good.
As discribed before it's depending on your use cases or future functions.
In my opinion you have this possibilities:
Possibility 1
user
id
username
password
server
id
name
image
userId
adminId (references user id of admin/owner/creator)
user_server
id
userId
serverId
Possibility 2
user
id
username
password
server
id
name
image
userId
user_server
id
userId
serverId
admin (null if not an admin and true if an admin/owner/creator)
Possibility 3
user
id
username
password
server
id
name
image
userId
roleId (1=normal user, 2=admin,3=moderator)
user_server
id
userId
serverId
role
id
rolename
With possibility 1 you are limited to one owner of a server.
With possibility 2 you could add a "admin flag" to each user wich is allowed to manage the server. (like in chat groups of a messanger where exists multiple group admins)
With possibility 3 you could add a system to manage the rights of the corresponding users.

MySQL M-N Relationship with extra attributes and permissions

I have a task in which I have to represent a M-N Relationship between a Users table and a Courses one. The goal is to allow only some Users (with a level of privilege) to see some Courses details(other tables related). The things get complicated because a user can have multiple privilege levels on different courses. For example - attending Course1 will give him privilege 1, watching Course2 will give him privilege 2 and so on. I am thinking to have a table users_courses which will store the relationship between a user and a course and also the privilege level (e.g. for columns: UserID | CourseID | Privilege).
The question is, can I create this join table including Privilege field ?
Is there another simpler approach ?
You can use RBAC pattern for that purpose. The picture below shows an example using users, permisions, and applicationes. In your case you would be using users, privileges and courses. You can also use roles for a better privileges handling.

Mysql Many to Many relationship

I am trying to implement a simple many to many relationship between two tables.
User and Groups.
User
---------
user_id
user_name
Group
----------
group_id
group_name
UserGroup
----------
user_id
group_id
Lets say both the user and group table each has 1000 entries.
I have to create one admin user that belongs to all groups.
Should I create 1000 entries in the UserGroup table for the "admin" user?
Can I create a boolean column say "Applicable_to_all_groups" in User table that should be checked first before selecting from UserGroup table?
Any suggestion on doing this the correct way will be appreciated.
Well, I would say there's no "true" solution for that kind of cases.
Let's look on some pros / cons
Solution 1, all in UserGroup table
Pros
Requests to get allowed groups is easier to write (no OR clause)
Cons
You will have to add an entry in this table every time you add an entry in the group table.
Doable, of course, but boring, and error-prone.
If you want a new User "which can also be related to all groups", you'll have to rewrite all your procedures / triggers / whatever you use to have "up-to-date" UserGroup table to add this new thing.
Solution2, flag (= boolean column)
Pros
Avoid unnecessary entries in your db (well, minor point)
Always "up-to-date", without any additional work.
Easy to add a new User with "all groups" rights (just put the flag to true)
Cons
You'll have to add OR clauses when requesting for allowed groups (based on flag or on GroupUser
table)
A personal point of view
I would go for the flag solution...

Granting permission to individual fields in MySQL

I have MySQL Database and have several tables in it. One, of course, is the users table for storing the username and passwords (which also has the rest of their information). For all the tables in the schema, I want to be able to grant users (or groups) permission to individual fields. Maybe an example will help:
There;'s a table called ACCOUNTS. In this table, the user fills out (and keeps up to date) all the data about their company (name, address, POC, etc). But I also want to have fields attached to this table that are read only for those users, such as LastPaymentDate (can't have them changing that!). Further, among those users, permissions differ. For example, the admin/superuser can change the name and address of the company, but standard users should not.
I'm thinking this might need to be done by making several Views for the table, one for each level of permission (group). I'm relatively new to MySQL, so I don't know if this is the best way. I can also see a lookup table that says which fields is allowed to view/edit.
My initial thought was to include in the comments (or the name of the field) a value from 0-5, and then the user would have a permission level (0-can't see; 1-Read only; 2-Read-write; 3-(not used); 4-(not used); 5-Edit/Delete the field itself.
Any suggestions? Views? Lookup table to determine which fields to display? Again, it'd not for the whole table, for each column within a table.
You can GRANT the rights to individual columns to a user, using this code:
GRANT SELECT (col1), INSERT (col1,col2) ON mydb.mytbl TO 'someuser'#'somehost';
Example taken from here:
http://dev.mysql.com/doc/refman/5.1/en/grant.html
Also there is no support for groups of users or SQL ROLES (which are groups of privileges) in MySQL.