|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
create table if not exists basejump.invitations |
|
( |
|
|
|
id uuid unique not null default extensions.uuid_generate_v4(), |
|
|
|
account_role basejump.account_role not null, |
|
|
|
account_id uuid references basejump.accounts (id) on delete cascade not null, |
|
|
|
token text unique not null default basejump.generate_token(30), |
|
|
|
invited_by_user_id uuid references auth.users not null, |
|
|
|
account_name text, |
|
|
|
updated_at timestamp with time zone, |
|
|
|
created_at timestamp with time zone, |
|
|
|
invitation_type basejump.invitation_type not null, |
|
primary key (id) |
|
); |
|
|
|
|
|
GRANT SELECT, INSERT, UPDATE, DELETE ON TABLE basejump.invitations TO authenticated, service_role; |
|
|
|
|
|
CREATE TRIGGER basejump_set_invitations_timestamp |
|
BEFORE INSERT OR UPDATE |
|
ON basejump.invitations |
|
FOR EACH ROW |
|
EXECUTE FUNCTION basejump.trigger_set_timestamps(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
CREATE OR REPLACE FUNCTION basejump.trigger_set_invitation_details() |
|
RETURNS TRIGGER AS |
|
$$ |
|
BEGIN |
|
NEW.invited_by_user_id = auth.uid(); |
|
NEW.account_name = (select name from basejump.accounts where id = NEW.account_id); |
|
RETURN NEW; |
|
END |
|
$$ LANGUAGE plpgsql; |
|
|
|
CREATE TRIGGER basejump_trigger_set_invitation_details |
|
BEFORE INSERT |
|
ON basejump.invitations |
|
FOR EACH ROW |
|
EXECUTE FUNCTION basejump.trigger_set_invitation_details(); |
|
|
|
|
|
alter table basejump.invitations |
|
enable row level security; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
create policy "Invitations viewable by account owners" on basejump.invitations |
|
for select |
|
to authenticated |
|
using ( |
|
created_at > (now() - interval '24 hours') |
|
and |
|
basejump.has_role_on_account(account_id, 'owner') = true |
|
); |
|
|
|
|
|
create policy "Invitations can be created by account owners" on basejump.invitations |
|
for insert |
|
to authenticated |
|
with check ( |
|
|
|
basejump.is_set('enable_team_accounts') = true |
|
|
|
and (SELECT personal_account |
|
FROM basejump.accounts |
|
WHERE id = account_id) = false |
|
|
|
and |
|
(basejump.has_role_on_account(account_id, 'owner') = true) |
|
); |
|
|
|
create policy "Invitations can be deleted by account owners" on basejump.invitations |
|
for delete |
|
to authenticated |
|
using ( |
|
basejump.has_role_on_account(account_id, 'owner') = true |
|
); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
create or replace function public.get_account_invitations(account_id uuid, results_limit integer default 25, |
|
results_offset integer default 0) |
|
returns json |
|
language plpgsql |
|
as |
|
$$ |
|
BEGIN |
|
|
|
if (select public.current_user_account_role(get_account_invitations.account_id) ->> 'account_role' <> 'owner') then |
|
raise exception 'Only account owners can access this function'; |
|
end if; |
|
|
|
return (select json_agg( |
|
json_build_object( |
|
'account_role', i.account_role, |
|
'created_at', i.created_at, |
|
'invitation_type', i.invitation_type, |
|
'invitation_id', i.id |
|
) |
|
) |
|
from basejump.invitations i |
|
where i.account_id = get_account_invitations.account_id |
|
and i.created_at > now() - interval '24 hours' |
|
limit coalesce(get_account_invitations.results_limit, 25) offset coalesce(get_account_invitations.results_offset, 0)); |
|
END; |
|
$$; |
|
|
|
grant execute on function public.get_account_invitations(uuid, integer, integer) to authenticated; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
create or replace function public.accept_invitation(lookup_invitation_token text) |
|
returns jsonb |
|
language plpgsql |
|
security definer set search_path = public, basejump |
|
as |
|
$$ |
|
declare |
|
lookup_account_id uuid; |
|
declare new_member_role basejump.account_role; |
|
lookup_account_slug text; |
|
begin |
|
select i.account_id, i.account_role, a.slug |
|
into lookup_account_id, new_member_role, lookup_account_slug |
|
from basejump.invitations i |
|
join basejump.accounts a on a.id = i.account_id |
|
where i.token = lookup_invitation_token |
|
and i.created_at > now() - interval '24 hours'; |
|
|
|
if lookup_account_id IS NULL then |
|
raise exception 'Invitation not found'; |
|
end if; |
|
|
|
if lookup_account_id is not null then |
|
|
|
insert into basejump.account_user (account_id, user_id, account_role) |
|
values (lookup_account_id, auth.uid(), new_member_role); |
|
|
|
delete from basejump.invitations where token = lookup_invitation_token and invitation_type = 'one_time'; |
|
end if; |
|
return json_build_object('account_id', lookup_account_id, 'account_role', new_member_role, 'slug', |
|
lookup_account_slug); |
|
EXCEPTION |
|
WHEN unique_violation THEN |
|
raise exception 'You are already a member of this account'; |
|
end; |
|
$$; |
|
|
|
grant execute on function public.accept_invitation(text) to authenticated; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
create or replace function public.lookup_invitation(lookup_invitation_token text) |
|
returns json |
|
language plpgsql |
|
security definer set search_path = public, basejump |
|
as |
|
$$ |
|
declare |
|
name text; |
|
invitation_active boolean; |
|
begin |
|
select account_name, |
|
case when id IS NOT NULL then true else false end as active |
|
into name, invitation_active |
|
from basejump.invitations |
|
where token = lookup_invitation_token |
|
and created_at > now() - interval '24 hours' |
|
limit 1; |
|
return json_build_object('active', coalesce(invitation_active, false), 'account_name', name); |
|
end; |
|
$$; |
|
|
|
grant execute on function public.lookup_invitation(text) to authenticated; |
|
|
|
|
|
|
|
|
|
|
|
create or replace function public.create_invitation(account_id uuid, account_role basejump.account_role, |
|
invitation_type basejump.invitation_type) |
|
returns json |
|
language plpgsql |
|
as |
|
$$ |
|
declare |
|
new_invitation basejump.invitations; |
|
begin |
|
insert into basejump.invitations (account_id, account_role, invitation_type, invited_by_user_id) |
|
values (account_id, account_role, invitation_type, auth.uid()) |
|
returning * into new_invitation; |
|
|
|
return json_build_object('token', new_invitation.token); |
|
end |
|
$$; |
|
|
|
grant execute on function public.create_invitation(uuid, basejump.account_role, basejump.invitation_type) to authenticated; |
|
|
|
|
|
|
|
|
|
|
|
create or replace function public.delete_invitation(invitation_id uuid) |
|
returns void |
|
language plpgsql |
|
as |
|
$$ |
|
begin |
|
|
|
if basejump.has_role_on_account( |
|
(select account_id from basejump.invitations where id = delete_invitation.invitation_id), 'owner') <> |
|
true then |
|
raise exception 'Only account owners can delete invitations'; |
|
end if; |
|
|
|
delete from basejump.invitations where id = delete_invitation.invitation_id; |
|
end |
|
$$; |
|
|
|
grant execute on function public.delete_invitation(uuid) to authenticated; |