Restricting users to proper read/write/update permission in MySQL - mysql

Let's assume there is a website called as mysite.com -
Now, mysite has users who have registered for the website.
Say Jane and John are two registered users on the website.
mysite.com uses MySQL to store its data.
Say there are tables such as Users which stores username, address, contact, etc,.
My question is how do i make it possible such that Jane -
can only read her rows from the Users table.
can only modify her rows from the Users table.
Also, while modification she cannot update the value in for username cell.
Also, what general roles are given to Jane and John with respect to the database? They cannot obviously cannot connect to MySQL as root/admin users. How to handle this situation?

You would not try to control this at the level of database users. Really, your database users are strictly for different pieces of code that interact directly with your database. Within your back-end code you would want to check which user of your software is logged in, and then restrict them to only reading or writing certain rows or data.
There is no way to set a MySQL user to be able to read/write some rows of a table and not others.
To expand on this... You may have a piece of software that lets Jane read some information but not write anything. That piece of software should connect to your database as a MySQL user with the minimum permission necessary to accomplish it's task. E.g. it can select but not update or insert. Another piece of software may allow users to edit rows, so you set up a MySQL user for that software which does have the update permission.

I've done this in my mini project once, my project was based on HTML, CSS, JS, PHP, and MySQL where I had created one website to store employee database, and employee can log in to there account and make some changes like to address or phone number, but I didn't give permission to changes Name, Government ID, or something which is permanent.
All this I did in front-end and not in back-end.
You can do this to, say Jane and John account where they can change there own information.
There is disabled attribute that is used in HTML where you can restrict the user from inputting any value
This is what I believe your answer would be based on how you explained your problem. If it worked, your welcome!

Related

Designing a SaaS on a single database, multi-tenant (SQL)

I'm working on a SaaS product and trying to figure out the best way to design the database for my scenario, which I think is pretty standard.
I should not that I don't have an experience designing such a database.
I tired researched online, but there isn't really any info I could find about implementation. There are quite a few comparing the different multi-tenant architectures.
For the multi-tenant approach, I decided go with a single database - seemed to be the most fitting.
Here's the basic list of what should be supported:
Multiple clients, all separated, no sharing of data between them.
Each client has it's own user base (staff/employees).
The client's staff members have different access levels to the system (exposure to different areas, ability to perform certain actions)
Each client have it's own customers.
I can wrap my head around the basic concept of having the tenant_id on any table belongs to that tenant. I guess my issue is more with how to combine it with different access levels per client's staff member.
How would you go about it?
Any reference some implementation of such a DB?
Thanks
Update
After #dmfy answer, I gave it some thought and came up with this solution:
account
-id
-name
user
-id
-account_id
-username
-password
role
-id
-account_id
-name
user_role
-user_id
-role_id
access
-id
-role_id
-name
role_access
-role_id
-access_id
session
-account_id
-user_id
-token
I'll explain-
The role table is essentially a "group" of users associated with a list of permissions/access levels.
The access table represents a single permission. An area of the platform, an action that can (or cannot) be performed.
A row in the session table is created after a successful login. Each time there's a call to the server, if the user has been verified against the token, I will lookup the roles for that user (using the session.user_id on the user_roles and collect it's access list using role.id on role_access.role_id).
Once I have the access list I can check against the request and see if the user is permitted to perform the action.
Notes
role can be customized for each tenant/account (e.g one can have "Management" and "Employees" and another can have "Management", "Support", and "Sales" ), hence the association with account.
access on the other hand, is platform-wide. The platform have the same set of areas and actions across all tenants. So there is not need to associate it with a specific account.
An improvement to the access lookup could be to store the access list on the session on login, to eliminate the double join (get all the user's roles, get all the roles' access lists).
Questions
Firstly, what is your overall opinion on the design. Do you see any flaws?
Is saving the account_id on the session really needed/a good idea?
Is having the server check whether the user has access to a certain resource is the standard way of doing this? Is there a way to do this as part of the itself query (e.g get an error from the DB itself)?
You might get a better answer by describing the requirements before you outline the solution.
Your design seems to describe an authorisation scheme. It looks fairly credible - I'd summarize it in natural language as:
A tenant is an account.
An account has many users.
A user can have
many roles.
Roles grant access to many permissions.
The system
maintains a list of sessions, mapping requests to users; this in turn
allows the system to check whether the user has permissions for a
given action.
Without knowing your requirements, that seems fairly reasonable. You may want to include a link from "account" to something your application recognizes as "tenant".
The big question is how you will use this data in your application. Checking permissions - especially fine-grained permissions - for each request could be expensive.
The specific solution here depends heavily on your application framework - many have built-in authentication/authorization models, and it's usually a good idea to use those built-in features.
For ideas on how to implement this, you could look at CanCanCan, an authorization framework for Ruby on Rails, or Authority for Laravel.
It's also not clear how the actual data in your system will be linked to an account - if your system tracks widgets, does the "widgets" table have an "account_id" column? If so, how does your application track who is and is not allowed to access that row?
It sounds like you're conflating database users with application users. In a SaaS product with a shared-schema model, individual users won't have direct acess to the database; instead, your application connects as a single user with appropriate rights on all objects it needs. What you're worried about is what areas of the application users can access and what actions they can take. This means you need to build your authorization model into your schema.
The simplest possible model has two levels of access: regular users and administrators. This can be represented with a users table having a tenant_id to associate individual logins with the correct client, and an is_admin flag. Your application then ensures that only users with the flag set can access administrative functionality. If your authorization model is more complex, design your schema appropriately (users may have a many:many relationship with roles, for example).
Note also that a tenant_id column is only strictly required for tables directly related to tenants; if you have a profiles table with a user_id, you can trace the relationship back to the tenant through users. In some cases it may make sense to add the tenant_id to avoid long join chains.

Convert local database to cloud hosted mysql database

I have an application which is currently tied to the desktop application which will specific to each of my users.
The Existing application has about 300 table
The current database design is specific to a single user. For example , for a given clinic as user , we have following tables
• Patient
• Patient_address
• Patient_Images
• Employees
• Clinic_details
• Devices
What I want is to host this database on web. I want to use this database for multiple users and need to be able to store and retrieve data on a user unique key(Let’s say user ID)
The database will be local as well as cloud based i.e. I would like user to continue work even if they do not have internet, and be able to sync it on demand when connection is back, I may also choose to run a nightly sync process on user desktop.
What is the best strategy to do this? Currently I’m using MySQL, would it help if I switch to SQL?
Any help in this is appreciated.
Thanks
Bhim
P.S. - If this is not the right forum, please suggest the right forum for this question.
MySQL is SQL. You cannot switch from MySQL to SQL. It is like saying that you want to switch from Espresso to Coffee.
If you want the ability to work offline and sync when the connection is back, be prepared to be working on that little feature for the next couple of years or so. I would say, do not even try.
For storing all of your "users" in one database, the term you are looking for is multi-tenancy, and it is a big subject, not suitable for a stackoverflow question and answer. So, multi-tenancy is the term you want to google for in order to find information on how to achieve this.

User Restrictions based on Field Content in MS Access

I need to set up user permissions within the same table, based on the value of a field. I know that this is not directly possible in Access but a post on Allenbrown.com points to a way of doing this see here. I'm not proficient in coding so I'm hoping that I can get some directions from you. Here are the details:
I have two tables in the database, a parent one populated via a form and a children one populated via a subform. The parent contains companies and the child contain subsidiaries of those companies. In the child table, I have a field called "Domicile" and I want to discriminate user access based on that. Because the database will be used by a variety of people worldwide, my plan is to create user groups based on location and allow users to edit (or add) information based on a match between their location (as specified in the group) and the domicile of the subsidiary. For example, a person in Europe will only be allowed to edit data for subsidiaries that are in Europe, even though companies from other domiciles may be stored in the same table.
I'm looking for some guidance here as well as suggestions as to how you think may be done most effectively. I'm not partial to this method, that's just something I came up with to put some logic behind what I'm doing.
Thank you so much!
The important thing to note in Allen's description is (emphasis mine):
Assuming all updates are performed through forms, the Current event of the form then locks the fields based on this property.
There would be no practical, bulletproof way to prevent users from viewing and altering any data in the table(s) if they open the back-end database file directly.
Since you are asking for advice on how "[row- or column-level restrictions] may be done most effectively" the first issue you need to address is how "effective" those restrictions really need to be:
If you can accept that these will be "soft restrictions" (really a matter of convenience to the user so they don't accidentally alter certain records or fields while using the forms), then Allen's approach might be sufficient. (If so, then follow Allen's instructions as best you can and ask new question if you need help with a specific aspect of that implementation.)
On the other hand, if you need "hard restrictions" (serious protection against mischievous or malevolent user activity) then you'll have to employ a different database back-end -- something like Microsoft SQL Server -- with a richer set of security tools for you to use.

Sharing databases between web applications design pattern

I have several different web applications with their own separate databases. All of these different web applications also use a common database for authentication which contains the list of all of my users and the user's name. To keep things simple, let just say my application databases are like a forum and they track user posts; in the tables they will store a userID and some post text.
Now the problem I am having is that some of my team members feel that what we are doing is messy and frictional because it kind of a pain how to get my applications to display a users name next to their posts which is a very common task. First I have to go to the application database and do something like SELECT userID, postText FROM tblPosts then I have to take that userID and go to the user database and get the actual name with SELECT name FROM tblUsers WHERE userID = X. And then merge data from those two queries together to get it out on the page.
I personally don't mind the way we are doing it as I think it's important to just use a single separate user database for data constancy, but some of my team members want to copy over all of the user names into the local application databases and store the user name next to the userID when recording posts so its super simple to get that information back out. In the event a user wants to change their name (a very infrequent event and we only have about 100 users) we should just run an update in the common database as well as all of the application databases.
This seems like a common issue people might have. Can someone please weigh in on the common approaches to dealing with the problem and what we might want to do.
You have a system with a working single-signon scheme (centralized user identity and authentication). That's a huge competitive advantage.
You've built it simply and cleanly. That's even more huge. This kind of thing is very hard to get right, and you have done that.
(If you were to try to build this with some system like LDAP or Active Directory, you'd have a lot of complex code to maintain.)
Don't let your fellow developers sacrifice that advantage for their personal convenience. If you have to synchronize changes to the user database, you will have problems when things get out of sync. It's a when question, not an if question.
By the way, if your user database and website specific databases are on the same MySQL server, you can do stuff like this to integrate the use of the two different databases. That may meet the needs of your developers.
SELECT u.username, d.opname
FROM userdatabase.users u
JOIN website.transaction d ON u.userid = d.userid
But if you do this, you'll make it hard to migrate your various website databases to other server machines in the future.

connect database table with the local username id password of the system

how to connect database table with the local username id and password of the system?. When user logs into the machine. opens up the software, he gets only the assets alloted to him. asset information is contained in the database table..anyone has any idea on how to implement this.I'm using mySQLdb with pyqt4.(creating an asset manager, user gets only the assets alloted to him )
As has been stated in the comments, the tables should not be any different between users. Also, there is no way to get the users password without them entering it again. And once you do have them enter it, you would have to use some method to authenticate them, such as checking it against an LDAP server.
Otherwise, if you simply want to base the delivery of database information of the current logged user and assume that them being logged in is enough of an authentication, you could simple get the login name with os.getlogin()
Most likely what you would just be doing is selecting on your table, data that has that username as matching criteria of some column. You wouldn't be using any sort of database-level authentication to filter the data. The authentication comes from some other earlier layer.
In pseudo-code: select * from assets where user is <result of os.login()>
With regards to the reason you are getting downvotes... People would like to see more context about your problem to understand the solution you are after. What is the structure of your database tables? Are you associating asset records with users? Is there a specific need for security or simply automatically identifying a user that is running the software? People on SO that take a little more time to outline their problem, the context, and what they have tried, tend to get better responses and upvotes.