@@ -169,9 +169,9 @@ GRANT ALL ON TABLE public.group_membership TO authenticated;
169169GRANT ALL ON TABLE public .group_membership TO service_role;
170170
171171CREATE OR REPLACE VIEW public .my_groups AS
172- SELECT id, split_part(email,' @' ,1 ) AS name FROM auth .users
173- JOIN public .group_membership ON (group_id= id)
174- WHERE member_id = auth .uid ();
172+ SELECT id, split_part(email, ' @' , 1 ) AS name FROM auth .users
173+ JOIN public .group_membership ON (group_id = id)
174+ WHERE member_id = auth .uid ();
175175
176176CREATE TYPE public .account_local_input AS (
177177 -- PlatformAccount columns
@@ -180,92 +180,10 @@ CREATE TYPE public.account_local_input AS (
180180 -- local values
181181 email VARCHAR ,
182182 email_trusted BOOLEAN ,
183- space_editor BOOLEAN
183+ space_editor BOOLEAN ,
184+ permissions public." SpaceAccessPermissions"
184185);
185186
186- CREATE OR REPLACE FUNCTION public .upsert_account_in_space(
187- space_id_ BIGINT ,
188- local_account public .account_local_input
189- ) RETURNS BIGINT
190- SECURITY DEFINER
191- SET search_path = ' '
192- LANGUAGE plpgsql
193- AS $$
194- DECLARE
195- platform_ public." Platform" ;
196- account_id_ BIGINT ;
197- user_uid UUID;
198- BEGIN
199- SELECT platform INTO STRICT platform_ FROM public." Space" WHERE id = space_id_;
200- INSERT INTO public." PlatformAccount" AS pa (
201- account_local_id, name, platform
202- ) VALUES (
203- local_account .account_local_id , local_account .name , platform_
204- ) ON CONFLICT (account_local_id, platform) DO UPDATE SET
205- name = COALESCE(NULLIF(TRIM (EXCLUDED .name ), ' ' ), pa .name )
206- RETURNING id, dg_account INTO STRICT account_id_, user_uid;
207- IF user_uid IS NOT NULL THEN
208- INSERT INTO public." SpaceAccess" as sa (space_id, account_uid, permissions)
209- VALUES (space_id_, user_uid,
210- CASE WHEN COALESCE(local_account .space_editor , true) THEN ' editor'
211- ELSE ' reader' END)
212- ON CONFLICT (space_id, account_uid)
213- DO UPDATE SET permissions = CASE
214- WHEN COALESCE(local_account .space_editor , sa .editor , true) THEN ' editor'
215- ELSE ' reader' END;
216- END IF;
217- INSERT INTO public." LocalAccess" (space_id, account_id) values (space_id_, account_id_)
218- ON CONFLICT (space_id, account_id)
219- DO NOTHING;
220- IF local_account .email IS NOT NULL THEN
221- -- TODO: how to distinguish basic untrusted from platform placeholder email?
222- INSERT INTO public." AgentIdentifier" as ai (account_id, value, identifier_type, trusted) VALUES (account_id_, local_account .email , ' email' , COALESCE(local_account .email_trusted , false))
223- ON CONFLICT (value, identifier_type, account_id)
224- DO UPDATE SET trusted = COALESCE(local_account .email_trusted , ai .trusted , false);
225- END IF;
226- RETURN account_id_;
227- END;
228- $$;
229-
230- CREATE OR REPLACE FUNCTION public .upsert_accounts_in_space(
231- space_id_ BIGINT ,
232- accounts JSONB
233- ) RETURNS SETOF BIGINT
234- SECURITY DEFINER
235- SET search_path = ' '
236- LANGUAGE plpgsql
237- AS $$
238- DECLARE
239- platform_ public." Platform" ;
240- account_id_ BIGINT ;
241- account_row JSONB;
242- local_account public .account_local_input ;
243- BEGIN
244- SELECT platform INTO STRICT platform_ FROM public." Space" WHERE id = space_id_;
245- FOR account_row IN SELECT * FROM jsonb_array_elements(accounts)
246- LOOP
247- local_account := jsonb_populate_record(NULL ::public .account_local_input , account_row);
248- RETURN NEXT public .upsert_account_in_space (space_id_, local_account);
249- END LOOP;
250- END;
251- $$;
252-
253- -- legacy
254- CREATE OR REPLACE FUNCTION public .create_account_in_space(
255- space_id_ BIGINT ,
256- account_local_id_ varchar ,
257- name_ varchar ,
258- email_ varchar = null ,
259- email_trusted boolean = true,
260- editor_ boolean = true
261- ) RETURNS BIGINT
262- SECURITY DEFINER
263- SET search_path = ' '
264- LANGUAGE sql
265- AS $$
266- SELECT public .upsert_account_in_space (space_id_, ROW(name_, account_local_id_ ,email_, email_trusted, editor_)::public .account_local_input );
267- $$;
268-
269187
270188CREATE OR REPLACE FUNCTION public .is_my_account(account_id BIGINT ) RETURNS boolean
271189STABLE SECURITY DEFINER
307225
308226COMMENT ON FUNCTION public.my_user_accounts IS ' security utility: The uids which give me access, either as myself or as a group member.' ;
309227
228+ CREATE OR REPLACE FUNCTION public .my_permissions_in_space(
229+ space_id_ BIGINT
230+ ) RETURNS public." SpaceAccessPermissions"
231+ SET search_path = ' '
232+ LANGUAGE sql
233+ AS $$
234+ SELECT max (permissions) FROM public." SpaceAccess"
235+ JOIN public .my_user_accounts () ON (account_uid = my_user_accounts)
236+ WHERE space_id= space_id_;
237+ $$;
238+
310239CREATE OR REPLACE FUNCTION public .in_group(group_id_ UUID) RETURNS BOOLEAN
311240STABLE SECURITY DEFINER
312241SET search_path = ' '
391320
392321COMMENT ON FUNCTION public.unowned_account_in_shared_space IS ' security utility: does current user share a space with this unowned account?' ;
393322
323+
324+ CREATE OR REPLACE FUNCTION public .upsert_account_in_space(
325+ space_id_ BIGINT ,
326+ local_account public .account_local_input
327+ ) RETURNS BIGINT
328+ SECURITY DEFINER
329+ SET search_path = ' '
330+ LANGUAGE plpgsql
331+ AS $$
332+ DECLARE
333+ platform_ public." Platform" ;
334+ account_id_ BIGINT ;
335+ user_uid UUID;
336+ permissions_ public." SpaceAccessPermissions" ;
337+ BEGIN
338+ SELECT platform INTO STRICT platform_ FROM public." Space" WHERE id = space_id_;
339+ INSERT INTO public." PlatformAccount" AS pa (
340+ account_local_id, name, platform
341+ ) VALUES (
342+ local_account .account_local_id , local_account .name , platform_
343+ ) ON CONFLICT (account_local_id, platform) DO UPDATE SET
344+ name = COALESCE(NULLIF(TRIM (EXCLUDED .name ), ' ' ), pa .name )
345+ RETURNING id, dg_account INTO STRICT account_id_, user_uid;
346+ IF user_uid IS NOT NULL THEN
347+ -- is any permission specified in the input?
348+ permissions_ := COALESCE(
349+ local_account .permissions ,
350+ CASE WHEN local_account .space_editor IS true THEN ' editor' -- legacy
351+ WHEN local_account .space_editor IS false THEN ' reader' END);
352+ INSERT INTO public." SpaceAccess" as sa (space_id, account_uid, permissions)
353+ VALUES (space_id_, user_uid, least(my_permissions_in_space(space_id_), COALESCE(permissions_, ' editor' )))
354+ ON CONFLICT (space_id, account_uid)
355+ DO UPDATE SET permissions = CASE
356+ WHEN permissions_ IS NULL THEN permissions
357+ ELSE least(my_permissions_in_space(space_id_), permissions_)
358+ END;
359+ END IF;
360+ INSERT INTO public." LocalAccess" (space_id, account_id) values (space_id_, account_id_)
361+ ON CONFLICT (space_id, account_id)
362+ DO NOTHING;
363+ IF local_account .email IS NOT NULL THEN
364+ -- TODO: how to distinguish basic untrusted from platform placeholder email?
365+ INSERT INTO public." AgentIdentifier" as ai (account_id, value, identifier_type, trusted) VALUES (account_id_, local_account .email , ' email' , COALESCE(local_account .email_trusted , false))
366+ ON CONFLICT (value, identifier_type, account_id)
367+ DO UPDATE SET trusted = COALESCE(local_account .email_trusted , ai .trusted , false);
368+ END IF;
369+ RETURN account_id_;
370+ END;
371+ $$;
372+
373+ CREATE OR REPLACE FUNCTION public .upsert_accounts_in_space(
374+ space_id_ BIGINT ,
375+ accounts JSONB
376+ ) RETURNS SETOF BIGINT
377+ SECURITY DEFINER
378+ SET search_path = ' '
379+ LANGUAGE plpgsql
380+ AS $$
381+ DECLARE
382+ platform_ public." Platform" ;
383+ account_id_ BIGINT ;
384+ account_row JSONB;
385+ local_account public .account_local_input ;
386+ BEGIN
387+ SELECT platform INTO STRICT platform_ FROM public." Space" WHERE id = space_id_;
388+ FOR account_row IN SELECT * FROM jsonb_array_elements(accounts)
389+ LOOP
390+ local_account := jsonb_populate_record(NULL ::public .account_local_input , account_row);
391+ RETURN NEXT public .upsert_account_in_space (space_id_, local_account);
392+ END LOOP;
393+ END;
394+ $$;
395+
396+ -- legacy
397+ CREATE OR REPLACE FUNCTION public .create_account_in_space(
398+ space_id_ BIGINT ,
399+ account_local_id_ varchar ,
400+ name_ varchar ,
401+ email_ varchar = null ,
402+ email_trusted boolean = true,
403+ permissions_ public." SpaceAccessPermissions" = ' editor'
404+ ) RETURNS BIGINT
405+ SECURITY DEFINER
406+ SET search_path = ' '
407+ LANGUAGE sql
408+ AS $$
409+ SELECT public .upsert_account_in_space (space_id_, ROW(name_, account_local_id_ ,email_, email_trusted, null , permissions_)::public .account_local_input );
410+ $$;
411+
394412-- Space: Allow anyone to insert, but only users who are members of the space can update or select
395413
396414ALTER TABLE public." Space" ENABLE ROW LEVEL SECURITY;
0 commit comments