SQL permissions based on record value (if column X = Y for user1 allow Inserts/Updates etc.) - sql

I need to run queries as a "user" which is a record in a table, with permissions based on a record value of that user.
I have a database with a tUsers Table, such as:
ID Username Email Role
1 Pieman mail.com Admin
2 Cakedude mail.co.uk Receptionist
3 Muffin gh.com Other
I need to have it so only "users"/records with "Role" of "Admin" can view and edit the table, and "Receptionist" view it etc.
I know of and use GRANT for permissions, but don't know how to run a query as a user based on a table record and to have the permission only GRANTED if that users' role is "Admin"
So if I have:
USE DB1;
GRANT SELECT ON OBJECT::tUsers TO Admins;
GO
SELECT * FROM tUsers
How do I make that run as say tUser with ID 1, and the GRANT if the users' role = "Admin"
I'm sure I've seen this done before.
I'm fairly new and still learning the correct terminology, so if this is a duplicate question, or is essentially just describing an sql Function sorry.

I don't think you can grant or revoke permissions to users in your own user table. However you can of course restrict queries based on your own user table.
One solution is to do it in your application. Verifier permissions before you do anything for him/her.
Another solution is to use stored procedures which take user id as parameter and do the checking for you in a central place.
The third one is to user parameterized views where you filter out entries one user can't access.
There are other solutions but the basic idea is you need somehow check permissions instead asking dBm server to do it for you.

Related

Registration process with a user_role table pattern

More of a sanity check question.
I'm using a DB relation similar to this, which seems a popular pattern:
Such schema makes a registration and login process quite sophisticated. Say I want to register a user and give them a 'USER' role by default.
For registration:
Create a user and insert to the users table
Get the ID of the USER role from the roles table
Insert newly created user's ID and the fetched ID of the USER role to the users_roles table
For login (I want to fetch the user with their roles):
Authenticate user and get the user ID from users table
Get Role IDs for that user from the user_roles table (user may have more than one)
Get role names from the roles table
I'm guessing that you could probably do some clever JOINs and nested SELECTs to avoid multiple statements (I'm using an SDK though, with no raw SQL option - and that means three separate DB calls) but is there a better way to do this while preserving such DB design?

Letting users "GRANT SELECT" without making them admins or giving them CONTROL permission

Background info:
I administrate a database in SSMS. I am the only administrator. I have users creating tables, and then they want to grant select permissions on those tables, to other users. But they are not allowed to do it because they are not administrators or have CONTROL permission on the schema.
Question:
How can I as an SSMS database administrator let users grant SELECT on tables they create to other users, without making them admins or giving them CONTROL permissions?
I would simply get users to create a table in their own schema along the lines of (SSMS syntax may be different, this is just meant to be illustrative):
create table select_access (
table_name varchar[50],
user_name varchar[50],
is_active varchar
)
Then have an admin job run periodically (every five or ten minutes, for example) and, for every applicable user, examine the entries in that table.
If there's an entry for a table not currently having the permission (with is_active set to Y), grant the permission. If there's an entry for a table currently having the permission (with is_active set to N), remove the permission.
That way, they have full control over select permissions on their tables without getting you involved.
To share a table, they just create it, add entries to select_access for each user they want to share it with, then wait for your job to run.
To disable, they just set the is_active field to N for the users they want to revoke access for and, again, wait for your job to run.
The use of is_active is just to make your life easier, as your only necessary source of information is just that table.
You could make it smarter by just letting them delete the row for the given user/table but then you'd have to process the table and all their tables that may have access granted but no longer have an entry in select_access.
Just make sure any table they grant permissions to is a table in their schema, not one of the system tables :-)

GRANT EXECUTE for "sp_delete_database_backuphistory" for group of users

I have a group login which has the Server Role "dbcreator". Users of this login has been granted execute on "sp_delete_database_backuphistory" so that they can delete each others databases. The problem now is that it is possible for these users to delete databases created by other logins. Is there a solution for this? Can permissionĀ“s be set, so that these users ONLY can delete databases created with this login?
You can't do this directly, but you can wrap the system sp_delete_database_backuphistory into your own usp_delete_database_backuphistory
that can call sp_delete_database_backuphistory or return immediately depending on a result of the check you want to perform.
I cannot ask you in a comment what do you mean saying 'databases created by other users', first of all only login (not user) can create a database but this information (db creator) you cannot extract from any system metadata, all you can get is the current database owner and this can differ from database creator.
I mean, when you create a database you can explicitly assign other login to own the database, or you can do this later for certain purposes

How can I allow Select permissions to a single record in a column?

The goal is to allow all the "Teachers" that have access to the Faculty table to have Select permissions to only their own social security number and not everybody elses. Do any of you know how I can perform something like this? I do have all my users setup as Windows Users and I have a windows group called Teachers, if that helps.
Not possible using the standard permissions in SQL server (that I am aware of)
You will need to implement this kind of constraint in your code.
You could in theory pass in the SS# and query based on this and raise an error if they do not match.
Social security numbers shoud be encrypted so they can't see each others numbers if they call up the record. You can use a decryption proc to allow them to decrypt that checks the userid against the profile id and will only decrypt if they match.
Implementing Row-level Permissions
Row-level permissions are used for applications that store information in a single table. Each row has a column that defines a differentiating parameter, such as a user name, label or other identifier. You then create parameterized stored procedures, passing in the appropriate value. Users can see only rows that match the supplied value.
The following steps describe how to configure row-level permissions based on a user or login name.
Create the table, adding an additional column to store the name.
Create a view that has a WHERE clause based on the user name column. This will restrict the rows returned to those with the specified value. Use one of the built-in functions to specify a database user or login name. This eliminates the need to create different views for different users.
' Returns the login identification name of the user.
WHERE UserName = SUSER_SNAME()
' USER_NAME or CURRENT_USER Return the database user name.
WHERE UserName = CURRENT_USER()
Create stored procedures to select, insert, update, and delete data based on the view, not the base tables. The view provides a filter that restricts the rows returned or modified.
For stored procedures that insert data, capture the user name using the same function specified in the WHERE clause of the view and insert that value into the UserName column.
Deny all permissions on the tables and views to the public role. Users will not be able to inherit permissions from other database roles, because the WHERE clause is based on user or login names, not on roles.
Grant EXECUTE on the stored procedures to database roles. Users can only access data through the stored procedures provided.

how to change db user name and db group name in Sybase Anywhere 11

all!
I have a db with tables User and Group, which represent entities in some application. But at the same time there are database users and database groups with the same names. I need to anonymize the database. It's easy to change db tables, e.g. update User set "Name" = "John",... where Id = 100500
But what to do with db users and db groups?
My first thought was to drop user and that create a new one:
drop user John;
create user njoh identified by 'pswd' login policy "root";
But belonging to groups is lost in the approach.
Is there any kind of rename method for db users in Sybase Anywhere 11?
Also I don't know how to change last log-in time and comments for a db user.
The same problem with groups. I didn't try to 'drop groups', 'cause I don't know if there is a possibility in Sybase Anywhere 11.
Could anyone tell me the truth - does the problem have a solution?
No, there is no way to rename an existing user. You can certainly drop it and create a new user but like you said, any group memberships are lost, as are permissions granted on objects like tables and procedures.
The only way to change the last login time for a user is by logging in. You can change the comment on a user by using comment on user is '<string>'.
There is no drop group statement - a group in SQL Anywhere (versions 12 and older) is simply a user with "group authority", so to drop a group you would use revoke connect from <group name>.
Disclaimer: I work for SAP in SQL Anywhere engineering.