1+ CREATE
2+ OR REPLACE FUNCTION lock_project_rpc (
3+ _project_id uuid
4+ ) RETURNS BOOLEAN
5+ AS $body$
6+ DECLARE
7+ _project_read_only_group_id uuid;
8+ _project_group_ids uuid[];
9+ _project_admin_ids uuid[];
10+ _project_group_id uuid;
11+ _row_group_users public .group_users % rowtype;
12+ _read_only_layer_role uuid;
13+ _context_ids uuid[];
14+ _context_id uuid;
15+ _user_id uuid;
16+ BEGIN
17+ -- Must have Update privs on project
18+ IF NOT (check_action_policy_organization(auth .uid (), ' projects' , ' UPDATE' )
19+ OR check_action_policy_project(auth .uid (), ' projects' , ' UPDATE' , _project_id))
20+ THEN
21+ RETURN FALSE;
22+ END IF;
23+
24+ -- Select the read only project default group
25+ SELECT pg .id INTO _project_read_only_group_id
26+ FROM public .project_groups pg
27+ WHERE pg .project_id = _project_id
28+ AND pg .is_read_only IS TRUE;
29+
30+ -- Create an array of project_group ids
31+ _project_group_ids := ARRAY(
32+ SELECT pg .id
33+ FROM public .project_groups pg
34+ WHERE pg .project_id = _project_id
35+ AND pg .is_read_only IS NOT TRUE
36+ );
37+
38+ -- Create an array of user ids
39+ _project_admin_ids := ARRAY(
40+ SELECT gu .user_id
41+ FROM public .group_users gu
42+ WHERE gu .type_id = ANY(_project_group_ids)
43+ );
44+
45+ -- For each project group user, set them to read-only
46+ FOREACH _project_group_id IN ARRAY _project_group_ids
47+ LOOP
48+ UPDATE public .group_users
49+ SET type_id = _project_read_only_group_id
50+ WHERE type_id = _project_group_id
51+ AND group_type = ' project' ;
52+ END LOOP;
53+
54+ -- If we do not have a read-only layer default group then fail
55+ IF NOT EXISTS(SELECT 1 FROM public .default_groups dgx WHERE dgx .group_type = ' layer' AND dgx .is_read_only IS TRUE)
56+ THEN
57+ ROLLBACK ;
58+ RETURN FALSE;
59+ END IF;
60+
61+ -- Get the read only role from default groups
62+ SELECT dgx .role_id INTO _read_only_layer_role FROM public .default_groups dgx WHERE dgx .group_type = ' layer' AND dgx .is_read_only IS TRUE;
63+
64+ -- Get an array of context ids for this project
65+ _context_ids := ARRAY(
66+ SELECT c .id
67+ FROM public .contexts c
68+ WHERE c .project_id = _project_id
69+ );
70+
71+ -- Set all context users to read-only
72+ FOREACH _context_id IN ARRAY _context_ids
73+ LOOP
74+ UPDATE public .context_users
75+ SET role_id = _read_only_layer_role
76+ WHERE _context_id = _context_id;
77+ END LOOP;
78+
79+ -- Add the admins to each context as read-only
80+ FOREACH _context_id IN ARRAY _context_ids
81+ LOOP
82+ FOREACH _user_id IN ARRAY _project_admin_ids
83+ LOOP
84+ INSERT INTO public .context_users
85+ (role_id, user_id, context_id)
86+ VALUES (_read_only_layer_role, _user_id, _context_id)
87+ ON CONFLICT(user_id, context_id)
88+ DO NOTHING;
89+ END LOOP;
90+ END LOOP;
91+
92+ -- Set the admins to the read only project group
93+
94+ -- Update the project
95+ UPDATE public .projects
96+ SET is_locked = TRUE
97+ WHERE id = _project_id;
98+
99+ -- Success
100+ RETURN TRUE;
101+
102+ END
103+ $body$ LANGUAGE plpgsql SECURITY DEFINER;
0 commit comments