Refactor SQL tests, add function for single account per owner, enhance generator configuration
Enhanced the Supabase SQL tests by refining the code indentation. Added a new function that ensures users can only own a single account. Revised the interactive generator to use boolean checks rather than string inputs which simplifies the setup process and prevents potential user errors.
This commit is contained in:
@@ -22,10 +22,11 @@ select
|
|||||||
select
|
select
|
||||||
row_eq($$
|
row_eq($$
|
||||||
select
|
select
|
||||||
primary_owner_user_id, is_personal_account, slug, name from
|
primary_owner_user_id, is_personal_account, slug, name
|
||||||
makerkit.get_account_by_slug('test') $$, row
|
from makerkit.get_account_by_slug('test') $$,
|
||||||
(tests.get_supabase_uid('test1'), false, 'test'::text,
|
row (tests.get_supabase_uid('test1'), false,
|
||||||
'Test'::varchar), 'Users can create a team account');
|
'test'::text, 'Test'::varchar),
|
||||||
|
'Users can create a team account');
|
||||||
|
|
||||||
-- Should be the primary owner of the team account by default
|
-- Should be the primary owner of the team account by default
|
||||||
select
|
select
|
||||||
@@ -39,8 +40,9 @@ select
|
|||||||
from public.accounts
|
from public.accounts
|
||||||
where
|
where
|
||||||
slug = 'test')
|
slug = 'test')
|
||||||
and user_id = tests.get_supabase_uid('test1') $$, row
|
and user_id = tests.get_supabase_uid('test1')
|
||||||
('owner'::varchar), 'The primary owner should have the owner role for the team account');
|
$$, row ('owner'::varchar),
|
||||||
|
'The primary owner should have the owner role for the team account');
|
||||||
|
|
||||||
-- Should be able to see the team account
|
-- Should be able to see the team account
|
||||||
select
|
select
|
||||||
@@ -48,7 +50,9 @@ select
|
|||||||
select
|
select
|
||||||
* from public.accounts
|
* from public.accounts
|
||||||
where
|
where
|
||||||
primary_owner_user_id = tests.get_supabase_uid('test1') $$, 'The primary owner should be able to see the team account');
|
primary_owner_user_id =
|
||||||
|
tests.get_supabase_uid('test1') $$,
|
||||||
|
'The primary owner should be able to see the team account');
|
||||||
|
|
||||||
-- Others should not be able to see the team account
|
-- Others should not be able to see the team account
|
||||||
select
|
select
|
||||||
@@ -59,7 +63,9 @@ select
|
|||||||
select
|
select
|
||||||
* from public.accounts
|
* from public.accounts
|
||||||
where
|
where
|
||||||
primary_owner_user_id = tests.get_supabase_uid('test1') $$, 'Other users should not be able to see the team account');
|
primary_owner_user_id =
|
||||||
|
tests.get_supabase_uid('test1') $$,
|
||||||
|
'Other users should not be able to see the team account');
|
||||||
|
|
||||||
-- should not have any role for the team account
|
-- should not have any role for the team account
|
||||||
select
|
select
|
||||||
@@ -70,6 +76,48 @@ select
|
|||||||
false,
|
false,
|
||||||
'Foreign users should not have any role for the team account');
|
'Foreign users should not have any role for the team account');
|
||||||
|
|
||||||
|
-- enforcing a single team account per owner using a trigger when
|
||||||
|
-- inserting a team
|
||||||
|
set local role postgres;
|
||||||
|
|
||||||
|
create or replace function kit.single_account_per_owner()
|
||||||
|
returns trigger
|
||||||
|
as $$
|
||||||
|
declare
|
||||||
|
total_accounts int;
|
||||||
|
begin
|
||||||
|
select
|
||||||
|
count(id)
|
||||||
|
from
|
||||||
|
public.accounts
|
||||||
|
where
|
||||||
|
primary_owner_user_id = auth.uid() into total_accounts;
|
||||||
|
|
||||||
|
if total_accounts > 0 then
|
||||||
|
raise exception 'User can only own 1 account';
|
||||||
|
end if;
|
||||||
|
|
||||||
|
return NEW;
|
||||||
|
|
||||||
|
end
|
||||||
|
$$
|
||||||
|
language plpgsql
|
||||||
|
set search_path = '';
|
||||||
|
|
||||||
|
-- trigger to protect account fields
|
||||||
|
create trigger single_account_per_owner
|
||||||
|
before insert on public.accounts for each row
|
||||||
|
execute function kit.single_account_per_owner();
|
||||||
|
|
||||||
|
-- Create an team account
|
||||||
|
select
|
||||||
|
tests.authenticate_as('test1');
|
||||||
|
|
||||||
|
select
|
||||||
|
throws_ok(
|
||||||
|
$$ select
|
||||||
|
public.create_team_account('Test2') $$, 'User can only own 1 account');
|
||||||
|
|
||||||
select
|
select
|
||||||
*
|
*
|
||||||
from
|
from
|
||||||
|
|||||||
117
turbo/generators/templates/env/generator.ts
vendored
117
turbo/generators/templates/env/generator.ts
vendored
@@ -77,17 +77,16 @@ export function createEnvironmentVariablesGenerator(
|
|||||||
default: allVariables.NEXT_PUBLIC_DEFAULT_LOCALE ?? 'en',
|
default: allVariables.NEXT_PUBLIC_DEFAULT_LOCALE ?? 'en',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'input',
|
type: 'confirm',
|
||||||
name: 'values.NEXT_PUBLIC_AUTH_PASSWORD',
|
name: 'values.NEXT_PUBLIC_AUTH_PASSWORD',
|
||||||
message: 'Do you want to use email/password authentication?',
|
message: 'Do you want to use email/password authentication?',
|
||||||
default: allVariables.NEXT_PUBLIC_DEFAULT_LOCALE ?? 'true',
|
default: getBoolean(allVariables.NEXT_PUBLIC_AUTH_PASSWORD, true),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'input',
|
type: 'confirm',
|
||||||
name: 'values.NEXT_PUBLIC_AUTH_MAGIC_LINK',
|
name: 'values.NEXT_PUBLIC_AUTH_MAGIC_LINK',
|
||||||
message:
|
message: 'Do you want to use magic link authentication?',
|
||||||
'Do you want to use magic link authentication? (leave empty for false)',
|
default: getBoolean(allVariables.NEXT_PUBLIC_AUTH_MAGIC_LINK, false),
|
||||||
default: allVariables.NEXT_PUBLIC_AUTH_MAGIC_LINK ?? 'false',
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'input',
|
type: 'input',
|
||||||
@@ -96,63 +95,85 @@ export function createEnvironmentVariablesGenerator(
|
|||||||
default: allVariables.CONTACT_EMAIL,
|
default: allVariables.CONTACT_EMAIL,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'input',
|
type: 'confirm',
|
||||||
name: 'values.NEXT_PUBLIC_ENABLE_THEME_TOGGLE',
|
name: 'values.NEXT_PUBLIC_ENABLE_THEME_TOGGLE',
|
||||||
message: 'Do you want to enable the theme toggle?',
|
message: 'Do you want to enable the theme toggle?',
|
||||||
default: allVariables.NEXT_PUBLIC_ENABLE_THEME_TOGGLE ?? 'true',
|
default: getBoolean(allVariables.NEXT_PUBLIC_ENABLE_THEME_TOGGLE, true),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'input',
|
type: 'confirm',
|
||||||
name: 'values.NEXT_PUBLIC_ENABLE_PERSONAL_ACCOUNT_DELETION',
|
name: 'values.NEXT_PUBLIC_ENABLE_PERSONAL_ACCOUNT_DELETION',
|
||||||
message: 'Do you want to enable personal account deletion?',
|
message: 'Do you want to enable personal account deletion?',
|
||||||
default:
|
default: getBoolean(
|
||||||
allVariables.NEXT_PUBLIC_ENABLE_PERSONAL_ACCOUNT_DELETION ?? 'true',
|
allVariables.NEXT_PUBLIC_ENABLE_PERSONAL_ACCOUNT_DELETION,
|
||||||
|
true,
|
||||||
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'input',
|
type: 'confirm',
|
||||||
name: 'values.NEXT_PUBLIC_ENABLE_PERSONAL_ACCOUNT_BILLING',
|
name: 'values.NEXT_PUBLIC_ENABLE_PERSONAL_ACCOUNT_BILLING',
|
||||||
message: 'Do you want to enable personal account billing?',
|
message: 'Do you want to enable personal account billing?',
|
||||||
default:
|
default: getBoolean(
|
||||||
allVariables.NEXT_PUBLIC_ENABLE_PERSONAL_ACCOUNT_BILLING ?? 'true',
|
allVariables.NEXT_PUBLIC_ENABLE_PERSONAL_ACCOUNT_BILLING,
|
||||||
|
true,
|
||||||
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'input',
|
type: 'confirm',
|
||||||
name: 'values.NEXT_PUBLIC_ENABLE_TEAM_ACCOUNTS',
|
name: 'values.NEXT_PUBLIC_ENABLE_TEAM_ACCOUNTS',
|
||||||
message: 'Do you want to enable team accounts?',
|
message: 'Do you want to enable team accounts?',
|
||||||
default: allVariables.NEXT_PUBLIC_ENABLE_TEAM_ACCOUNTS ?? 'true',
|
default: getBoolean(
|
||||||
|
allVariables.NEXT_PUBLIC_ENABLE_TEAM_ACCOUNTS,
|
||||||
|
true,
|
||||||
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'input',
|
type: 'confirm',
|
||||||
name: 'values.NEXT_PUBLIC_ENABLE_TEAM_ACCOUNT_DELETION',
|
name: 'values.NEXT_PUBLIC_ENABLE_TEAM_ACCOUNT_DELETION',
|
||||||
message: 'Do you want to enable team account deletion?',
|
message: 'Do you want to enable team account deletion?',
|
||||||
default:
|
default: getBoolean(
|
||||||
allVariables.NEXT_PUBLIC_ENABLE_TEAM_ACCOUNT_DELETION ?? 'true',
|
allVariables.NEXT_PUBLIC_ENABLE_TEAM_ACCOUNT_DELETION,
|
||||||
|
true,
|
||||||
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'input',
|
type: 'confirm',
|
||||||
name: 'values.NEXT_PUBLIC_ENABLE_TEAM_ACCOUNTS_BILLING',
|
name: 'values.NEXT_PUBLIC_ENABLE_TEAM_ACCOUNTS_BILLING',
|
||||||
message: 'Do you want to enable team account billing?',
|
message: 'Do you want to enable team account billing?',
|
||||||
default:
|
default: getBoolean(
|
||||||
allVariables.NEXT_PUBLIC_ENABLE_TEAM_ACCOUNTS_BILLING ?? 'true',
|
allVariables.NEXT_PUBLIC_ENABLE_TEAM_ACCOUNTS_BILLING,
|
||||||
|
true,
|
||||||
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'input',
|
type: 'confirm',
|
||||||
name: 'values.NEXT_PUBLIC_ENABLE_TEAM_ACCOUNTS_CREATION',
|
name: 'values.NEXT_PUBLIC_ENABLE_TEAM_ACCOUNTS_CREATION',
|
||||||
message: 'Do you want to enable team account creation?',
|
message: 'Do you want to enable team account creation?',
|
||||||
default:
|
default: getBoolean(
|
||||||
allVariables.NEXT_PUBLIC_ENABLE_TEAM_ACCOUNTS_CREATION ?? 'true',
|
allVariables.NEXT_PUBLIC_ENABLE_TEAM_ACCOUNTS_CREATION,
|
||||||
|
true,
|
||||||
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'input',
|
type: 'confirm',
|
||||||
name: 'values.NEXT_PUBLIC_REALTIME_NOTIFICATIONS',
|
|
||||||
message: 'Do you want to enable realtime notifications?',
|
|
||||||
default: allVariables.NEXT_PUBLIC_REALTIME_NOTIFICATIONS ?? 'true',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'input',
|
|
||||||
name: 'values.NEXT_PUBLIC_ENABLE_NOTIFICATIONS',
|
name: 'values.NEXT_PUBLIC_ENABLE_NOTIFICATIONS',
|
||||||
message: 'Do you want to enable email notifications?',
|
message:
|
||||||
default: allVariables.NEXT_PUBLIC_ENABLE_NOTIFICATIONS ?? 'true',
|
'Do you want to enable notifications? If not - we will hide the notifications bell from the UI.',
|
||||||
|
default: getBoolean(
|
||||||
|
allVariables.NEXT_PUBLIC_ENABLE_NOTIFICATIONS,
|
||||||
|
true,
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
when: (answers) => answers.values.NEXT_PUBLIC_ENABLE_NOTIFICATIONS,
|
||||||
|
type: 'confirm',
|
||||||
|
name: 'values.NEXT_PUBLIC_REALTIME_NOTIFICATIONS',
|
||||||
|
message:
|
||||||
|
'Do you want to enable realtime notifications? If yes, we will enable the realtime notifications from Supabase. If not - updated will be fetched lazily.',
|
||||||
|
default: getBoolean(
|
||||||
|
allVariables.NEXT_PUBLIC_REALTIME_NOTIFICATIONS,
|
||||||
|
false,
|
||||||
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'input',
|
type: 'input',
|
||||||
@@ -279,11 +300,35 @@ export function createEnvironmentVariablesGenerator(
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
when: (answers) => answers.values.MAILER_PROVIDER === 'nodemailer',
|
when: (answers) => answers.values.MAILER_PROVIDER === 'nodemailer',
|
||||||
type: 'input',
|
type: 'confirm',
|
||||||
name: 'values.EMAIL_TLS',
|
name: 'values.EMAIL_TLS',
|
||||||
message: 'Do you want to enable TLS for your emails?',
|
message: 'Do you want to enable TLS for your emails?',
|
||||||
default: 'true',
|
default: getBoolean(allVariables.EMAIL_TLS, true),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'confirm',
|
||||||
|
name: 'captcha',
|
||||||
|
message:
|
||||||
|
'Do you want to enable Cloudflare Captcha protection for the Auth endpoints?',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
when: (answers) => answers.captcha,
|
||||||
|
type: 'input',
|
||||||
|
name: 'values.NEXT_PUBLIC_CAPTCHA_SITE_KEY',
|
||||||
|
message:
|
||||||
|
'What is the Cloudflare Captcha site key? NB: this is the PUBLIC key!',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
when: (answers) => answers.captcha,
|
||||||
|
type: 'input',
|
||||||
|
name: 'values.CAPTCHA_SECRET_TOKEN',
|
||||||
|
message:
|
||||||
|
'What is the Cloudflare Captcha secret key? NB: this is the PRIVATE key!',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getBoolean(value: string | undefined, defaultValue: boolean) {
|
||||||
|
return value === 'true' ? true : defaultValue;
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user