How to create users database table for different user access levels - mysql

I have an issue about creating database table for user to login in different level access of the system.
I have 3 user roles "ENUM(master_admin, admin_country, admin_city )".
If the master_admin logged in will have access to the whole system,
but if admin_city logged in will have access to his country only with countryID,
and if admin_city logged in will have access to his city data only with cityID
The problem is on creating users table that will save info of different
administrators so they can have access to their related part of the system.
So later when other admin created to cover other parts of the system it will be easily to set them using the same users table.
I tried this:
users table
+--------+-----------+-------------+
| userID | countryID | user_role| |
+--------+-----------+-------------+
| 1 | 23 | master |
+--------+-----------+-------------+
countries table
+-----------+-------------+
| countryID | countryName |
+-----------+-------------+
| 23 | US |
+-----------+-------------+
coutrries table
+-----------+-------------+-------------+
| cityID | countryID | cityName |
+-----------+-------------+-------------+
| 2 | 23 | New York |
+-----------+-------------+-------------+
How can I set my users table for this problem.

Split the users table
users table
+--------+-----------+-----------------+
| userID | username | email |
+--------+-----------+-----------------+
| 1 | adm | master#master |
+--------+-----------+-----------------+
users_Role table
+--------+-----------+------------+-------------+
| userID | countryID | cityID | roleID |
+--------+-----------+------------+-------------+
| 1 | 23 | NULL | 1 |
+--------+-----------+------------+-------------+
| 1 | 22 | NULL | 2 |
+--------+-----------+------------+-------------+
| 1 | NULL | 2 | 3 |
+--------+-----------+------------+-------------+
role table
+-----------+-----------------+
| roleID | roleName |
+-----------+-----------------+
| 1 | Master |
+-----------+-----------------+
| 2 | COUNTRYMASTER |
+-----------+-----------------+
| 3 | CityMaster |
+-----------+-----------------+
OF course you could make a City/Countryid column, as the role defines what type of id is saved.
So can give or remove for every user individual rigst, per country and/or city.
User_role has redundant indormation so another rolentable is necessary for nomalization

You didn't really try all that much, which means your question is reasonable vague. Whenever you design a system with varying levels of access you need to make very sure that access can't be accidentally granted. Even a bug shouldn't make this possible.
A bad way to do this would be to create a cityId in the users table. If there's a number there, say 2, the user has only access to data of New York, if it is 3 only Washington, etc. If the value is zero the user has access to all cities. Choosing zero seems to make sense here, but it is dangerous, because a bug in setting the cityId could set it to zero and give access that shouldn't be granted.
The normal way to do this is to make a separate table which very explicitly grants access. You could call this table permission. Each user can have multiple permissions. You could define a level in it: 'master', 'country' and 'city'. This tells you what kind of access someone has. Other fields could specify exactly which country or city.
Whenever the user accesses a resource you have to check it against the permissions an user has. access is only granted when the answer is positive. You have to write your software in such a way, that forgetting to check the permission, would break the functionality of the software.
I would also log every access, and every change made to the permission table. It might surprise you how often you will have to play detective and find out exactly who did what when.
No matter what you do, this will never be as secure as it can be. There's always a change an user can access something they shouldn't. It could be due to a bug, or a mistake by an administrator. The only way to have real security is to actually put cities and countries in different databases, and let users only exist in the database to which they are allowed to have access. Security and practicality often are enemies.

Related

How to create a table for a user in a Database

I am creating an mobile application. In this app, I have created a Login and Register activity. I have also created a online Database using AWS(Amazon Web Service) to store all the login information of the user upon registering.
In my database, i have a table called 'users'. This table holds the following fields "fname","lname","username","password". This part works and successfully stores data from my phone to the database.
for example,
| fname | lname | username | password |
| ------ | ------ | -------- | -------- |
| john | doe | jhon123 | 1234 |
Inside the app, I have an option where the user may click on "Start Log", which will record a start and end values on a seekBar.
How can i create a table under a user who is logged in.
(Essentially, i want to be able to create multiple tables under a user.)
for example,
This table should be under the user "john123":
| servo | Start | End |
| ------ | ------ | --- |
| 1 | 21 | 30 |
| 2 | 30 | 11 |
| 3 | 50 | 41 |
| 4 | 0 | 15 |
I know its a confusing question, but
i am essentially just trying to have multiple tables linked to a user.
As to:
How to create a table for a user in a Database
Here are some GUI tools you might find useful:
MySQL - MySQL Workbench
PostgreSQL - PG Admin
As for creating a separate table for each user, refer to #Polymath's answer. There is no benefit in creating separate tables for each user (you might as well use a json file).
What you should do is create a logs table that has a user_id attribute referencing the id in the users table.
-------------------------------------------------------
| id | fname | lname | username | password |
| -- | ------ | ------ | -------- | ------------------- |
| 1 | john | doe | jhon123 | encrypted(password) |
-------------------------------------------------------
|______
|
V
---------------------------------------
| id | user_id | servo_id | start | end |
| -- | ------- | -------- | ----- | --- |
| 1 | 1 | 1 | 21 | 30 |
| 2 | 1 | 2 | 30 | 11 |
---------------------------------------
You should also look into database normalization as your "john123" table is not in 3NF. The servo should be decomposed out of logs table if it will be logged by multiple users or multiple times (which I'm guessing is the case for you).
In reading this I wonder if your design is right. It sounds like you are trying to create a table for each user. I also wonder how scalable it is to have a unique table per user. if you scale to millions of users you will have millions of tables to manage and will probably need a separate index table to find the right table for the user. Why a table for each? Why not a single table with the UserID as a use key value. You can extract the data just by filtering on the UserID.
Select * FROM UsersData ORDER BY DateTime WHERE User == UserID
However I will leave that for you to ponder.
You mentioned that this is a Mobile App. I think what you need to do is look at AWS Federated access and Cognito which will allow you to Identify a user using federate Identities. Pass the User unique Id , plus a temporary (one use) credentials linked to an access Role. Combined this way, you can scale to millions of users with full authentication without managing millions of accounts.
RL

SQL Table Relationships - Trying to Avoid Cyclical Relationships

I'm trying to manage table relationships in my database, but every option I mock up ends up creating cyclical relationships, which seem to be a big no-no. Here is my setup:
I have the Group table:
+----+--------+
| id | name |
+----+--------+
| 1 | group1 |
| 2 | group2 |
+----+--------+
I also have a UserToGroup table giving users access (with varying permission level) to groups, with FKs pointing to my Group (many-to-one) and to my User table (many-to-one):
+----+----------+---------+---------------+
| id | group_id | user_id | permission_id |
+----+----------+---------+---------------+
| 1 | 1 | 1 | 2 |
| 2 | 1 | 2 | 3 |
| 3 | 2 | 1 | 2 |
+----+----------+---------+---------------+
Where I get stuck is that I want to add an owner flag on each instance of the Group table, where creating a FK constraint would block SQL from removing the UserToGroup instance of a group's owner (ultimately the owner of a group cannot lose permission access to its group.
Functionally, owner permission is completely independent from the permissions granted to users (as the owner would have access to certain management pages, while permission access grants various levels of read/write), and I want to always maintain a required UserToGroup instance in the database for the group's owner, stopping the database (through FK constraints) from the possibility of removing the owner from the UserToGroup table, where he manages all users for a given group.
Initially I had Group.owner_id pointing to the given User, but that only create a FK constraint for when the user is deleted.
I have also tried creating the following variations to my database, but they create cyclical relationships:
Where I created a FK in my Group table pointing to a UserToGroup instance labelling it as the owner's instance:
+----+--------+---------------------+
| id | name | owner_user_to_group |
+----+--------+---------------------+
| 1 | group1 | 2 |
| 2 | group2 | 3 |
+----+--------+---------------------+
Inversly, where I created an owner table that would manage the owner check between the Group and UserToGroup tables:
+----+----------+------------------+
| id | group_id | user_to_group_id |
+----+----------+------------------+
| 1 | 1 | 2 |
| 2 | 2 | 3 |
+----+----------+------------------+
But in both cases it creates a cyclical relationship with the Group table, where both cannot be created without each other.
Is there a way I can manage both owner and permissions separately for Group instances, but also create a logical relationship between both in my database so that I can use the FK constraints to avoid SQL from deleting the UserToGroup instance of the Group's owner?
I might have misunderstood but are you looking for this?
If not, try to explain more simply what you need exactly and I'll try again.

One to many table with 3M records

I have a table in MySQL that contains almsot 3 million records.
The table saves friend information in a user system. So it has many users and even more friends (There is a (soft)max of 2000 per user). I had added some extra fields name, url, dob, image, registered which are varchar(255) and dates.
My basic data is 2 int's and 1 varchar(6).
When using PHPMyAdmin it all gets really slow. I have an index on the user ID and the varchar(6) and that's how I query all the friends of a user (which goes well). However, any other operation (or the ones to come) aren't going to be fast.
My options:
Remove the double data (Normalizing)
Change the datatype for the friend IDs and save it like a JSON blob
So questions;
When my table is only 2 ints and a tiny varchar, will it still be
slow with 3M records?
Should I change my datatype?
Should I be
using a different pattern for this friendlist problem?
Edit: To clarify a bit more.
The Users are not my actual users, but they are user objects nonetheless. All the Friends are a User object, but I may or may not already have the User object. So I'm using the extra data in Friends to show data about it in the list on the Users page.
In the ideal world things wouldn't take so long, in the next optimal world I would only have 2 fields in Friends which are user_id and friend_id. But I can not rely on linking friend_id to a User object, I may not have it..
Users (has more fields, but for brevity)
+-------+---------+-------+------------+
| shard | user_id | name | dob |
+-------+---------+-------+------------+
| nl | 1 | Bob | 2014-03-26 |
| nl | 2 | Erik | 2014-03-26 |
| de | 1 | Johan | 2014-02-01 |
+-------+---------+-------+------------+
Friends (has more fields, see description above)
+-------+---------+-----------+--------+
| shard | user_id | friend_id | name |
+-------+---------+-----------+--------+
| nl | 1 | 2 | Erik |
| nl | 1 | 3 | Alice |
| de | 1 | 2 | Rasmus |
+-------+---------+-----------+--------+
nl-Bob is friends with nl-Erik (Is a user)
nl-Bob is friends with nl-Alice (Is not a user)
de-Johan is friends with de-Rasmus (Is not a user)

Structuring a MySQL database for user information

I am quite new to MySQL, I know most of the basic functions and how to send queries etc. However, I am trying to learn about structuring it for optimal searches for user information and wanted to get some ideas.
Right now I just have one table (for functionality purposes and testing) called user_info which holds the users information and another table that stores photos linked to the user. Ideally id like most of this information to be as quickly as accessible as possible
In creating a database which is primarily used to store and retrieve user information (name, age, phone, messages, etc.) would it be a good idea to create a NEW TABLE for each new user that stores all the information so the one table user_info does not become bogged down by multiple queries, locking, etc. So for example user john smith would have his very own table in the database holding all his information including photos, messages etc.
OR
is it better to have just a few tables such as user_info, user_photos, user_messages,etc. and accessing data in this manner.
I am not concerned about redundancy in the tables such as the users email address being repeated multiple times.
The latter is the best way. You declare one table for users, and several columns with the data you want.
Now if you want users to have photos, you'd require a new table with photos and a Foreign Key attribute that links to the user table's Primary Key.
You should definitely NOT create a new table for each user. Create one table for user_info, one for photos if each user can have many photos. A messages table would probably contain two user_id columns (user_to, user_from) and a message column. Try to normalize the data as much as possible.
Users
====
id
email
etc
Photos
====
id
user_id
meta_data
etc
Messages
====
id
user_id_to
user_id_from
message
timestamp
etc
I agree with both the answers supplied here, but one thing they haven't mentioned yet is lookup tables.
Going with the general examples here consider this: you have a users table, and a photos table. Now you want to introduce a featre on your site that allows users to "Favorite" photos from other users.
Rather than making a new table called "Favorites" and adding in all your data about the image (fiel location, metadata, score/whatever) all over again, have a table that effectively sits BETWEEN the other two.
+-----------------------+ +-------------------------------------+
| ++ users | | ++ photos |
| userID | email | name | | photoID | ownerID | fileLo | etc... |
+--------+-------+------| +---------+---------+--------+--------+
| 1 | .... | Tom | | 35 | 1 | ..... | .......|
| 2 | .... | Rob | | 36 | 2 | ..... | .......|
| 3 | .... | Dan | | 37 | 1 | ..... | .......|
+--------+-------+------+ | 43 | 3 | ..... | .......|
| 48 | 2 | ..... | .......|
| 49 | 3 | ..... | .......|
| 53 | 2 | ..... | .......|
+---------+---------+--------+--------+
+------------------+
| ++ Favs |
| userID | photoID |
+--------+---------+
| 1 | 37 |
| 1 | 48 |
| 2 | 37 |
+--------+---------+
With this approach, you link the data you have cleanly, efficiently and without too much data replication.

Set up Table to store variable number of fields per record?

How should I set up my database / table, if I do not know the number of fields I would populate per record?
For example, if I have a web form that allows a user to enter all the cars he owns, and I don't want to limit him to a certain number, how would I store this in the database end?
The above problem extends to similar situations such as storing a user's order (variable number of items per order) etc.
In Relational Database Management Systems (RDBMS) instead you create child records in a dependent table that relate child entities (cars) with parent entities (users). There is a concept known as database normalization, and the objective is that each table contains data for a single type of entity.
So you have a user table with the user information:
user_id | user_name | email | ...
1234 | User1 | user1#example.com | ...
2356 | User2 | user2#example.com | ...
Then another table for storing the information of each car of a user:
user_car_id | user_id | car_label | make | model | ...
1 | 1234 | MyCar | Ford | 2011 | ...
2 | 2356 | A Car | Chevrolet | 2010 | ...
3 | 1234 | MyOtherCar| BMW | 2000 | ...
So instead of storing the info of the cars in the user table, you have a table for storing car (user_car) information related to each user by way of the user_id column. This is an example of a one-to-many relationship, in which one user can have many related cars.
this is an entire topic: database normalization.
the short answer is you make more than one table.
in your example you would have person table, a car table, and a third that linked person to the car