1 -- Copyright (C) The Arvados Authors. All rights reserved.
3 -- SPDX-License-Identifier: AGPL-3.0
5 -- constructing perm_edges
6 -- 1. get the list of all permission links,
7 -- 2. any can_manage link or permission link to a group means permission should "follow through"
8 -- (as a special case, can_manage links to a user grant access to everything owned by the user,
9 -- unlike can_read or can_write which only grant access to the user record)
10 -- 3. add all owner->owned relationships between groups as can_manage edges
12 -- constructing permissions
13 -- 1. base case: start with set of all users as the working set
15 -- join with edges where the tail is in the working set and "follow" is true
16 -- produce a new working set with the head (target) of each edge
17 -- set permission to the least permission encountered on the path
18 -- propagate trashed flag down
20 CREATE TEMPORARY VIEW permission_view AS
22 perm_value (name, val) AS (
24 ('can_read', 1::smallint),
29 perm_edges (tail_uuid, head_uuid, val, follow, trashed) AS (
30 SELECT links.tail_uuid,
33 (pv.val = 3 OR groups.uuid IS NOT NULL) AS follow,
34 0::smallint AS trashed
36 LEFT JOIN perm_value pv ON pv.name = links.name
37 LEFT JOIN groups ON pv.val<3 AND groups.uuid = links.head_uuid
38 WHERE links.link_class = 'permission'
40 SELECT owner_uuid, uuid, 3, true, CASE is_trashed WHEN true THEN 1 ELSE 0 END FROM groups
42 perm (val, follow, user_uuid, target_uuid, trashed, startnode) AS (
43 SELECT 3::smallint AS val,
45 users.uuid::varchar(32) AS user_uuid,
46 users.uuid::varchar(32) AS target_uuid,
47 0::smallint AS trashed,
51 SELECT LEAST(perm.val, edges.val)::smallint AS val,
52 edges.follow AS follow,
53 perm.user_uuid::varchar(32) AS user_uuid,
54 edges.head_uuid::varchar(32) AS target_uuid,
55 GREATEST(perm.trashed, edges.trashed)::smallint AS trashed,
58 INNER JOIN perm_edges edges
59 ON (perm.startnode or perm.follow) AND edges.tail_uuid = perm.target_uuid
63 MAX(val) AS perm_level,
64 CASE follow WHEN true THEN target_uuid ELSE NULL END AS target_owner_uuid,
65 MAX(trashed) AS trashed
67 GROUP BY user_uuid, target_uuid, target_owner_uuid;