GRANT privileges on child table which specific parent - sql

I am doing a condominium database under Postgres with these three tables (among others)
The tables are listed only with the PK and the FK involved in my problem to simplify the code
TableName: Administrator
PK: admin_id
TableName: Condo
PK: condo_id
FK: admin_id (Connects with Administrator of this condo)
TableName: Property
PK: property_id
FK: condo_id (Connects with parent condo)
Now, imagine there is a administrator with admin_id = 1 and I create a SQL user for him, for example:
CREATE ROLE "john_smith"
LOGIN PASSWORD '123456'
VALID UNTIL 'infinity';
So now I want him to only update the Properties related to a Condo that has him as administrator (admin_id = 1)
How could I do something like
GRANT SELECT, INSERT, UPDATE, DELETE
ON Property
WHERE "The Properties of a Condo with admin_id = 1"
TO "john_smith"
That's the question, thanks!

It is possible to do it on Postgress and this is called Row Security Policies
But you have not posted enough information about your DB to have a clear answer.
The idea is that you have to create specific ROLES that are GROUPS of USERS
In your example you created only a user role. You should add an Administrators usergroup and add your admin users to it.
Then you do something like
ALTER TABLE Property ENABLE ROW LEVEL SECURITY;
CREATE POLICY Property_Administrator ON property TO Administrators
USING (SELEcT true FROM condo WHERE condo.condo_id=property.condo_id AND condo.admin_id= current_user);
Just read the doc I linked and you'll achieve it pretty simply

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?

How to give access to columns to new user when current user does not see the tables?

Using SYSTEM user I create a new user. After that I try to give this user access to specific columns only in 1 table, but get the error that this table does not exist. Meaning that SYSTEM user does not have access to this table. Unfortunately, the user that has access to the normal production tables cannot manage user privileges and access. What are my options?
CREATE USER test1 IDENTIFIED BY 123456;
GRANT UPDATE (extinvno, invoiceno) ON invoice TO test1;
Edit: Solution
Created 3 views that I needed. GRANT-ed the new user SELECT and UPDATE on 2 of the views and SELET on the 3rd. For the new user I had to use the chema to refer to the views: chema.view
If SYSTEM doesn't own the table then you need to specify who does; for example if the table was in the HR schema you would do:
GRANT UPDATE (extinvno, invoiceno) ON HR.invoice TO test1;
... using the real owning schema name, of course.
It isn't that SYSTEM doesn't have access to the table; it's that by default it's looking for SYSTEM.invoice, which doesn't exist.
The table owner could also grant the update privilege to test1.

Why CREATE USER updates PG_ROLES table?

When I create a USER with "CREATE USER user1 WITH PASSWORD 'aaaaaaaa'
It is also creating a ROLE in PG_ROLES table with role name as same as 'user1'
Is it a trigger peforrming the this? Or is it default behavior?
Assuming you are not running a very old (<8.1) version of Postgresql this is explained by the documentation for CREATE USER:
CREATE USER is now an alias for CREATE ROLE. The only difference is
that when the command is spelled CREATE USER, LOGIN is assumed by
default, whereas NOLOGIN is assumed when the command is spelled CREATE
ROLE.
Further details are available in the Database Roles section of the documentation:
The concept of roles subsumes the concepts of “users” and “groups”. In
PostgreSQL versions before 8.1, users and groups were distinct kinds
of entities, but now there are only roles. Any role can act as a user,
a group, or both.
The system catalogs docs explain that:
The view pg_roles provides access to information about database roles.
So based upon this it is to be expected that running CREATE USER will have an impact on pg_roles.

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

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.

Delete register with a stored procedure with foreign key

Im new with SQL Server, i have programmed several stored procedures and i have the next problem. For example, i have 2 tables (Role and User), and when i try to delete a role, logically the procedure shows me the error (547) because there are a foreign key on "User Table". So, what i need is finding a way to delete that role. If it would be necessary delete all the user whose role is that i gonna delete or if its possible to reassigne a new role for that user who belongs to the role which i wanna delete.
I hope you understand what i want to do more or less. I search a simple example how to do that.
Thanks!
Deleting users with role 5:
Delete From Users Where RoleID = 5
Or updating:
Update Users Set RoleID = 6 Where RoleID = 5
Then deleting role itself:
Delete From Role Where ID = 5