Update SQL tests and schema definitions for membership and invitation management

This commit includes updates to the SQL tests for the database layer handling memberships and invitations. Test cases are improved and expanded. It also introduces some changes to the underlying schema, including creation of new indices on the 'accounts' table and several adjustments to function definitions with regard to how user IDs are accessed. Also, some views related to user accounts are redefined for better data handling.
This commit is contained in:
giancarlo
2024-05-08 17:16:33 +07:00
parent 25abe83dfa
commit a501bb5444
3 changed files with 70 additions and 30 deletions

View File

@@ -357,6 +357,11 @@ add constraint accounts_slug_null_if_personal_account_true check (
) )
); );
-- Indexes
create index if not exists ix_accounts_primary_owner_user_id on public.accounts (primary_owner_user_id);
create index if not exists ix_accounts_is_personal_account on public.accounts (is_personal_account);
-- constraint to ensure that the primary_owner_user_id is unique for personal accounts -- constraint to ensure that the primary_owner_user_id is unique for personal accounts
create unique index unique_personal_account on public.accounts (primary_owner_user_id) create unique index unique_personal_account on public.accounts (primary_owner_user_id)
where where
@@ -701,7 +706,7 @@ set
from from
public.accounts_memberships membership public.accounts_memberships membership
where where
membership.user_id = auth.uid() membership.user_id = (select auth.uid())
and membership.account_id = has_role_on_account.account_id and membership.account_id = has_role_on_account.account_id
and((membership.account_role = has_role_on_account.account_role and((membership.account_role = has_role_on_account.account_role
or has_role_on_account.account_role is null))); or has_role_on_account.account_role is null)));
@@ -2375,13 +2380,20 @@ select
accounts.id as id, accounts.id as id,
accounts.name as name, accounts.name as name,
accounts.picture_url as picture_url, accounts.picture_url as picture_url,
accounts.public_data as public_data, (
subscriptions.status as subscription_status select
status
from
public.subscriptions
where
account_id = accounts.id
limit
1
) as subscription_status
from from
public.accounts public.accounts
left join public.subscriptions on accounts.id = subscriptions.account_id
where where
primary_owner_user_id = auth.uid () primary_owner_user_id = (select auth.uid ())
and accounts.is_personal_account = true and accounts.is_personal_account = true
limit limit
1; 1;
@@ -2396,21 +2408,29 @@ select
-- we create a view to load the user's accounts and memberships -- we create a view to load the user's accounts and memberships
-- useful to display the user's accounts in the app -- useful to display the user's accounts in the app
create or replace view create or replace view
public.user_accounts public.user_accounts (id, name, picture_url, slug, role)
with with
(security_invoker = true) as (security_invoker = true) as
select select
accounts.id as id, account.id,
accounts.name as name, account.name,
accounts.picture_url as picture_url, account.picture_url,
accounts.slug as slug, account.slug,
accounts_memberships.account_role as role membership.account_role
from from
public.accounts public.accounts account
join public.accounts_memberships on accounts.id = accounts_memberships.account_id join public.accounts_memberships membership on account.id = membership.account_id
where where
accounts_memberships.user_id = auth.uid () membership.user_id = (select auth.uid ())
and accounts.is_personal_account = false; and account.is_personal_account = false
and account.id in (
select
account_id
from
public.accounts_memberships
where
user_id = (select auth.uid ())
);
grant grant
select select
@@ -2420,8 +2440,8 @@ select
-- --
-- Function "public.team_account_workspace" -- Function "public.team_account_workspace"
-- Load all the data for a team account workspace -- Load all the data for a team account workspace
create create or replace function public.team_account_workspace(account_slug text)
or replace function public.team_account_workspace (account_slug text) returns table ( returns table (
id uuid, id uuid,
name varchar(255), name varchar(255),
picture_url varchar(1000), picture_url varchar(1000),
@@ -2431,9 +2451,7 @@ or replace function public.team_account_workspace (account_slug text) returns ta
primary_owner_user_id uuid, primary_owner_user_id uuid,
subscription_status public.subscription_status, subscription_status public.subscription_status,
permissions public.app_permissions[] permissions public.app_permissions[]
) ) as $$
set
search_path = '' as $$
begin begin
return QUERY return QUERY
select select
@@ -2448,23 +2466,19 @@ begin
array_agg(role_permissions.permission) array_agg(role_permissions.permission)
from from
public.accounts public.accounts
join public.accounts_memberships on accounts.id = join public.accounts_memberships on accounts.id = accounts_memberships.account_id
accounts_memberships.account_id
left join public.subscriptions on accounts.id = subscriptions.account_id left join public.subscriptions on accounts.id = subscriptions.account_id
left join public.role_permissions on join public.roles on accounts_memberships.account_role = roles.name
accounts_memberships.account_role = role_permissions.role left join public.role_permissions on accounts_memberships.account_role = role_permissions.role
left join public.roles on accounts_memberships.account_role = roles.name
where where
accounts.slug = account_slug accounts.slug = account_slug
and public.accounts_memberships.user_id = auth.uid() and public.accounts_memberships.user_id = (select auth.uid())
group by group by
accounts.id, accounts.id,
accounts_memberships.account_role, accounts_memberships.account_role,
subscriptions.status, subscriptions.status,
roles.hierarchy_level; roles.hierarchy_level;
end; end;
$$ language plpgsql; $$ language plpgsql;
grant grant

View File

@@ -58,6 +58,17 @@ select lives_ok(
'custom role should be able to create invitations' 'custom role should be able to create invitations'
); );
select lives_ok(
$$ SELECT public.add_invitations_to_account('makerkit', ARRAY[ROW('example@makerkit.dev', 'custom-role')::public.invitation]); $$,
'custom role should be able to create invitations using the function public.add_invitations_to_account'
);
select throws_ok(
$$ SELECT public.add_invitations_to_account('makerkit', ARRAY[ROW('example2@makerkit.dev', 'owner')::public.invitation]); $$,
'new row violates row-level security policy for table "invitations"',
'cannot invite members with higher roles'
);
-- Foreigners should not be able to create invitations -- Foreigners should not be able to create invitations
select tests.create_supabase_user('user'); select tests.create_supabase_user('user');
@@ -70,6 +81,11 @@ select throws_ok(
'new row violates row-level security policy for table "invitations"' 'new row violates row-level security policy for table "invitations"'
); );
select throws_ok(
$$ SELECT public.add_invitations_to_account('makerkit', ARRAY[ROW('example@example.com', 'member')::public.invitation]); $$,
'new row violates row-level security policy for table "invitations"'
);
select is_empty($$ select is_empty($$
select * from public.invitations where account_id = makerkit.get_account_id_by_slug('makerkit') $$, select * from public.invitations where account_id = makerkit.get_account_id_by_slug('makerkit') $$,
'no invitations should be listed' 'no invitations should be listed'

View File

@@ -45,6 +45,11 @@ select is(
'The member can check if they have a role on the account' 'The member can check if they have a role on the account'
); );
select isnt_empty(
$$ select * from public.get_account_members('makerkit') $$,
'The member can query the team account memberships using the get_account_members function'
);
select tests.authenticate_as('test'); select tests.authenticate_as('test');
-- Foreigners -- Foreigners
@@ -77,6 +82,11 @@ select is_empty(
'The foreigner cannot query the team account' 'The foreigner cannot query the team account'
); );
select is_empty(
$$ select * from public.get_account_members('makerkit') $$,
'The foreigner cannot query the team members'
);
select * from finish(); select * from finish();
rollback; rollback;