Get each user role in PostgreSQL - postgresql

Suppose I have a DB and in this DB I have a users table and a groups table where each user is related to a specific group.
In the groups table we have a “data entry” group, a “reviewer” group, an “approver” group etc.
Now assume a user X. This user is added to the “data entry” group and also added to the “reviewer” group, that means the user X has both access rights: data entry and reviewer.
Y is another user who has the “data entry” access right, so when I want to generate a report to get the count for each user and group, the “data entry” user and the “data entry + reviewer” user must be counted separately.
The point here is that those users which belong to both groups must not be counted in the individual groups; for example the “data entry + reviewer” user must not be counted to the “data entry” group.

I'd aggregate twice - first, for each user get all the groups he or she belongs too, and then aggregate that result and count how many each combination appears:
-- Count how many times each combination occurs
SELECT group_combinataions, COUNT(*)
FROM (-- Get the groups for each user
SELECT STRING_AGG(group_name ORDER BY group_name) AS group_combinations
FROM groups
GROUP BY userid) t
GROUP BY group_combinations

Related

PostgreSQL: How to check if a list is contained in another list?

I'm working with PostgreSQL 13.
I have two tables like this:
permission_table
name
permission
Ann
Read Invoice
Ann
Write Invoice
Ann
Execute Payments
Bob
Read Staff data
Bob
Modify Staff data
Bob
Execute Payroll
Carl
Read Invoice
Carl
Write Invoice
risk_table
risk_id
permission
Risk1
Read Invoice
Risk1
Write Invoice
Risk1
Execute Payments
Risk2
Read Staff data
Risk2
Modify Staff data
Risk2
Execute Payroll
I'd like to create a new table containing the names of the employees of the first table whose permissions are pointed as risks in the second table. After the execution, the results should be like this:
name
risk_id
Ann
Risk1
Bob
Risk2
Since Carl only has two of the three permissions belonging to Risk2, he will not be included in the results.
My first brute force approach was to compare the list of permissions belonging to a risk to the permissions belonging to an employee. If the first list is included in the second one, then that combination of employee/risk will be added to the results table.
INSERT INTO results_table
SELECT a.employee, b.risk_id FROM permission_table a, risk_table b WHERE
((SELECT permission FROM risk_table c WHERE b.permission = c.permission ) EXCEPT
(SELECT permission FROM permission_table d WHERE a.employee=d.employee)
) IS NULL;
I'm not sure if the results could be correct using this approach, because if the tables are big, it takes a very long time even if I add a WHERE clause limiting the query to just one employee.
Could you please help?
One way of approaching this one is by
computing the amount of permissions for each "risk_id" value
joining the "permissions" and "risks" table with counts on matching "permission" values
making sure that the distinct count of permissions for each triplet "<permissions.name, risks.risk_id, risks.cnt>" corresponds to the full amount of permissions.
WITH risks_with_counts AS (
SELECT *, COUNT(permission) OVER(PARTITION BY risk_id) AS cnt
FROM risks
)
SELECT p.name, r.risk_id
FROM permissions p
INNER JOIN risks_with_counts r
ON p.permission = r.permission
GROUP BY p.name, r.risk_id, r.cnt
HAVING COUNT(DISTINCT r.permission) = r.cnt
Carl won't be included in the output as he doesn't have all permissions from "risk_id = 'Risk 1'"
Check the demo here.

_eq permission value against ID in different table?

I'm setting up some permissions in hasura, I have an 'assigned' table which maps an assigned item to a user, I require the user to be able to only access items they have been assigned. I figured the best way to do this was with the _exists operator where I have:
{"_exists":{"_table":{"name":"assigned_item","schema":"public"},"_where":{"_and":[{"userid":{"_eq":"X-Hasura-User-Id"}},{"feed_item_id":{"_eq":"XXX"}}]}}
My issue comes into play with the last _eq: XXX - I need for it to equal the value from the item table.
The permission is being created against the assigned item.
Assuming your assigned_item table has userid and feed_item_id .. your permissions should be:
on the assigned_item table, just add the permission: userid _eq X-Hasura-User-Id as in "A user can see all their assigned items".
on the feed_items? table, use the relationship to reach the user_id through the assigned_item table. Assuming the relationship on feed_items is called say "assigned_users", then the permission is: feed_items > assigned_users > user_id _eq X-Hasura-User-Id

is it possible with optimistic concurrency ensure this case?

I have a table that has a long column that is a GroupCode. I can have groups of products, so to get all the product of a group I just get all the products which GroupCode is the same.
I can change a product from one group to another, and if I change a product from a group, I want that all the products of the group change to the new group.
If I use optimistic concurrency, it could happen this:
One user wants to change a product from a group, so he gets all the products with the same groupCode. Set the new new groupCode to all this products.
A second user add a new product to the group. But the first user doesn't have this product because he got all the products before the second user add the new product.
So at the end, a new product has a wrong GroupCode, because the code is not correct because all the products of the group was change to the new group. So I would have a group with only one product, and it wouldn't be correct.
With pessimistic concurrency, the first use get all the products of the group, block all the products.
The second user try to add a new product to the group, to do that, first try to get one of the products of the group as reference product, but how it is blocked by the first user, the second user has to wait.
The first user changes all the products to the new group and unblock all the products.
The second user get the reference product, that has the new groupCode, so the new product is added to the correct group.
In summary, I want that when I change a product from one group to another, I want to change all the products of the group, and avoid that a new product belongs to the old group.
Is it possible to solve this case with optimistic concurrency? Or I have to use pessimistic concurrency?
I honestly don't see the issue here. If you want to implement it as OCC, you should just follow the OCC phases.
User A gets all records which belong to group ABC
User B gets a reference to Record1, which belongs to ABC at the moment
User A moves Record1 to group XYZ
User B wants to add a new record to the group to which Record1 belongs. So just before inserting the record, get the group of Record, which is now XYZ
This is assuming that you go with the 'referential record' approach. If your screen (or whatever) just lists the currently available groups, and meanwhile one of those groups becomes empty (because you have moved all records to another group), there is no way of telling if that's a concurrency issue or it is working as expected. In such case, you should normalize your database and split the categories into a separate table, so that at least the user gets an error that the group no longer exists.

How to get group info of a user

I get a user's JID,i want to get the group info that the user has joined by user JID.
Can someone help me ?Please.
Depending on which storage type you are using in there (CoreData/Memory) - the 'groups' field on the user (XMPPUserCoreDataStorageObject) is a 1:m relation to the groups (XMPPGroupCoreDataStorageObject) of that user, and each group also has a 1:m relation to users (group.users).
So you should be able to get the user object via the jid of that user ([xmppRosterStorage userForJID:jid ...]), and from there, get the groups (user.groups).

How to restrict other user group members to view the Documents

I have created an Organization which has four user groups. I want to restrict the user group to view the file uploaded by the other user group.
i.e
Organization 1
User Group 1
A
B
User Group 2
C
D
User Group 3
E
F
User Group 4
G
H
I am using CustomLanding hook to land on the organization page.
From above, If A uploads a document, it can be viewed only by B in user group 1.
Like the same I want to restrict the viewable condition to other groups also.
Please guide me to achieve this.
Regards,
Dinesh.
you can create different roles for the user and apply permission for role.
Instead of taking as user group with in organization we have teams. you can try with teams.