---
--- Name: search_permission_graph(character varying, integer, character varying, character varying, integer); Type: FUNCTION; Schema: public; Owner: -
---
-
-CREATE FUNCTION public.search_permission_graph(starting_uuid character varying, starting_perm integer, override_edge_tail character varying DEFAULT NULL::character varying, override_edge_head character varying DEFAULT NULL::character varying, override_edge_perm integer DEFAULT NULL::integer) RETURNS TABLE(target_uuid character varying, val integer, traverse_owned boolean)
- LANGUAGE sql STABLE
- AS $$
-/*
- From starting_uuid, perform a recursive self-join on the edges
- to follow chains of permissions. This is a breadth-first search
- of the permission graph. Permission is propagated across edges,
- which may narrow the permission for subsequent links (eg I start
- at can_manage but when traversing a can_read link everything
- touched through that link will only be can_read).
-
- When revoking a permission, we follow the chain of permissions but
- with a permissions level of 0. The update on the permissions table
- has to happen _before_ the permission is actually removed, because
- we need to be able to traverse the edge before it goes away. When
- we do that, we also need to traverse it at the _new_ permission
- level - this is what override_edge_tail/head/perm are for.
-
- Yields the set of objects that are potentially affected, and
- their permission levels granted by having starting_perm on
- starting_uuid.
-
- If starting_uuid is a user, this computes the entire set of
- permissions for that user (because it returns everything that is
- reachable by that user).
-
- Used by the compute_permission_subgraph function.
-*/
-WITH RECURSIVE
- traverse_graph(target_uuid, val, traverse_owned) as (
- values (starting_uuid, starting_perm,
- should_traverse_owned(starting_uuid, starting_perm))
- union
- (select edges.head_uuid,
- least(edges.val,
- traverse_graph.val,
- case traverse_graph.traverse_owned
- when true then null
- else 0
- end,
- case (edges.tail_uuid = override_edge_tail AND
- edges.head_uuid = override_edge_head)
- when true then override_edge_perm
- else null
- end),
- should_traverse_owned(edges.head_uuid, edges.val)
- from permission_graph_edges as edges, traverse_graph
- where traverse_graph.target_uuid = edges.tail_uuid))
- select target_uuid, max(val), bool_or(traverse_owned) from traverse_graph
- group by (target_uuid);
-$$;
-
-