303 lines
10 KiB
PL/PgSQL
303 lines
10 KiB
PL/PgSQL
begin;
|
|
select plan(28); -- Total number of tests
|
|
|
|
-- ============================================================================
|
|
-- Trigger Function Existence Tests
|
|
-- ============================================================================
|
|
|
|
SELECT has_function('public', 'create_tablo_access_for_owner',
|
|
'Function create_tablo_access_for_owner should exist');
|
|
|
|
SELECT has_function('public', 'create_last_signed_in_on_profiles',
|
|
'Function create_last_signed_in_on_profiles should exist');
|
|
|
|
SELECT has_function('public', 'update_tablo_invites_on_login',
|
|
'Function update_tablo_invites_on_login should exist');
|
|
|
|
SELECT has_function('public', 'update_profile_subscription_status',
|
|
'Function update_profile_subscription_status should exist');
|
|
|
|
-- ============================================================================
|
|
-- Trigger Existence Tests
|
|
-- ============================================================================
|
|
|
|
SELECT has_trigger('public', 'tablos', 'trigger_create_tablo_access',
|
|
'Trigger trigger_create_tablo_access should exist on tablos table');
|
|
|
|
SELECT has_trigger('auth', 'users', 'trigger_on_last_signed_in',
|
|
'Trigger trigger_on_last_signed_in should exist on auth.users table');
|
|
|
|
SELECT has_trigger('auth', 'users', 'trigger_update_tablo_invites_on_login',
|
|
'Trigger trigger_update_tablo_invites_on_login should exist on auth.users table');
|
|
|
|
-- Stripe triggers
|
|
SELECT ok(
|
|
(SELECT COUNT(*) FROM information_schema.triggers
|
|
WHERE trigger_name = 'update_profile_on_subscription_change'
|
|
AND event_object_schema = 'stripe') > 0,
|
|
'Trigger update_profile_on_subscription_change should exist on stripe schema'
|
|
);
|
|
|
|
-- ============================================================================
|
|
-- Tablo Access Trigger Tests
|
|
-- ============================================================================
|
|
|
|
-- Create test user and tablo to trigger auto-creation of tablo_access
|
|
DO $$
|
|
DECLARE
|
|
trigger_user_id uuid := gen_random_uuid();
|
|
trigger_tablo_id integer;
|
|
BEGIN
|
|
-- Insert test user
|
|
INSERT INTO auth.users (id, instance_id, aud, role, email, encrypted_password, email_confirmed_at, created_at, updated_at)
|
|
VALUES
|
|
(trigger_user_id, '00000000-0000-0000-0000-000000000000', 'authenticated', 'authenticated', 'triggeruser@test.com', 'encrypted', now(), now(), now());
|
|
|
|
-- Insert test profile
|
|
INSERT INTO public.profiles (id, email, first_name, last_name)
|
|
VALUES
|
|
(trigger_user_id, 'triggeruser@test.com', 'Trigger', 'User');
|
|
|
|
-- Insert tablo (this should trigger auto-creation of tablo_access)
|
|
INSERT INTO public.tablos (owner_id, name, status, position)
|
|
VALUES
|
|
(trigger_user_id, 'Trigger Test Tablo', 'todo', 0)
|
|
RETURNING id INTO trigger_tablo_id;
|
|
|
|
-- Store test IDs
|
|
PERFORM set_config('test.trigger_user_id', trigger_user_id::text, true);
|
|
PERFORM set_config('test.trigger_tablo_id', trigger_tablo_id::text, true);
|
|
END $$;
|
|
|
|
-- Test: Verify tablo_access was auto-created
|
|
SELECT is(
|
|
(
|
|
SELECT count(*)::integer
|
|
FROM public.tablo_access
|
|
WHERE tablo_id = current_setting('test.trigger_tablo_id')::integer
|
|
AND user_id = current_setting('test.trigger_user_id')::uuid
|
|
),
|
|
1,
|
|
'Tablo access should be auto-created when tablo is created'
|
|
);
|
|
|
|
-- Test: Verify tablo_access has correct fields
|
|
SELECT is(
|
|
(
|
|
SELECT is_active
|
|
FROM public.tablo_access
|
|
WHERE tablo_id = current_setting('test.trigger_tablo_id')::integer
|
|
AND user_id = current_setting('test.trigger_user_id')::uuid
|
|
LIMIT 1
|
|
),
|
|
true,
|
|
'Auto-created tablo access should be active'
|
|
);
|
|
|
|
SELECT is(
|
|
(
|
|
SELECT is_admin
|
|
FROM public.tablo_access
|
|
WHERE tablo_id = current_setting('test.trigger_tablo_id')::integer
|
|
AND user_id = current_setting('test.trigger_user_id')::uuid
|
|
LIMIT 1
|
|
),
|
|
true,
|
|
'Auto-created tablo access should have admin privileges'
|
|
);
|
|
|
|
SELECT is(
|
|
(
|
|
SELECT granted_by
|
|
FROM public.tablo_access
|
|
WHERE tablo_id = current_setting('test.trigger_tablo_id')::integer
|
|
AND user_id = current_setting('test.trigger_user_id')::uuid
|
|
LIMIT 1
|
|
),
|
|
current_setting('test.trigger_user_id')::uuid,
|
|
'Auto-created tablo access should be granted by owner'
|
|
);
|
|
|
|
-- ============================================================================
|
|
-- Last Signed In Trigger Tests
|
|
-- ============================================================================
|
|
|
|
-- Create test user with last_sign_in_at
|
|
DO $$
|
|
DECLARE
|
|
signin_user_id uuid := gen_random_uuid();
|
|
test_signin_time timestamp with time zone := now();
|
|
BEGIN
|
|
-- Insert test user
|
|
INSERT INTO auth.users (id, instance_id, aud, role, email, encrypted_password, email_confirmed_at, last_sign_in_at, created_at, updated_at)
|
|
VALUES
|
|
(signin_user_id, '00000000-0000-0000-0000-000000000000', 'authenticated', 'authenticated', 'signinuser@test.com', 'encrypted', now(), test_signin_time, now(), now());
|
|
|
|
-- Insert test profile
|
|
INSERT INTO public.profiles (id, email, first_name, last_name)
|
|
VALUES
|
|
(signin_user_id, 'signinuser@test.com', 'SignIn', 'User');
|
|
|
|
-- Store test IDs
|
|
PERFORM set_config('test.signin_user_id', signin_user_id::text, true);
|
|
PERFORM set_config('test.signin_time', test_signin_time::text, true);
|
|
END $$;
|
|
|
|
-- Test: Update last_sign_in_at on auth.users (simulating a sign-in)
|
|
DO $$
|
|
DECLARE
|
|
new_signin_time timestamp with time zone := now() + interval '1 hour';
|
|
BEGIN
|
|
UPDATE auth.users
|
|
SET last_sign_in_at = new_signin_time,
|
|
updated_at = now()
|
|
WHERE id = current_setting('test.signin_user_id')::uuid;
|
|
|
|
PERFORM set_config('test.new_signin_time', new_signin_time::text, true);
|
|
END $$;
|
|
|
|
-- Test: Verify last_signed_in was updated in profiles
|
|
SELECT ok(
|
|
(
|
|
SELECT last_signed_in
|
|
FROM public.profiles
|
|
WHERE id = current_setting('test.signin_user_id')::uuid
|
|
) IS NOT NULL,
|
|
'Profile last_signed_in should be updated after auth.users sign in'
|
|
);
|
|
|
|
-- ============================================================================
|
|
-- Tablo Invites Trigger Tests
|
|
-- ============================================================================
|
|
|
|
-- Create test temporary user and invite
|
|
DO $$
|
|
DECLARE
|
|
temp_user_id uuid := gen_random_uuid();
|
|
temp_user_email text := 'tempuser@test.com';
|
|
invite_tablo_id integer;
|
|
BEGIN
|
|
-- Insert test user (will be marked as temporary)
|
|
INSERT INTO auth.users (id, instance_id, aud, role, email, encrypted_password, email_confirmed_at, created_at, updated_at)
|
|
VALUES
|
|
(temp_user_id, '00000000-0000-0000-0000-000000000000', 'authenticated', 'authenticated', temp_user_email, 'encrypted', now(), now(), now());
|
|
|
|
-- Insert test profile marked as temporary
|
|
INSERT INTO public.profiles (id, email, first_name, last_name, is_temporary)
|
|
VALUES
|
|
(temp_user_id, temp_user_email, 'Temp', 'User', true);
|
|
|
|
-- Create a tablo for invites
|
|
INSERT INTO public.tablos (owner_id, name, status, position)
|
|
VALUES
|
|
(temp_user_id, 'Invite Test Tablo', 'todo', 0)
|
|
RETURNING id INTO invite_tablo_id;
|
|
|
|
-- Create pending invite for this user's email
|
|
INSERT INTO public.tablo_invites (tablo_id, invited_email, invited_by, invite_token, is_pending)
|
|
VALUES
|
|
(invite_tablo_id, temp_user_email, temp_user_id, 'temp-user-token', true);
|
|
|
|
-- Store test IDs
|
|
PERFORM set_config('test.temp_user_id', temp_user_id::text, true);
|
|
PERFORM set_config('test.temp_user_email', temp_user_email, true);
|
|
END $$;
|
|
|
|
-- Test: Verify invite is initially pending
|
|
SELECT is(
|
|
(
|
|
SELECT is_pending
|
|
FROM public.tablo_invites
|
|
WHERE invited_email = current_setting('test.temp_user_email')
|
|
AND invite_token = 'temp-user-token'
|
|
LIMIT 1
|
|
),
|
|
true,
|
|
'Invite should be initially pending'
|
|
);
|
|
|
|
-- Test: Simulate sign-in to trigger invite update
|
|
DO $$
|
|
BEGIN
|
|
UPDATE auth.users
|
|
SET last_sign_in_at = now(),
|
|
updated_at = now()
|
|
WHERE id = current_setting('test.temp_user_id')::uuid;
|
|
END $$;
|
|
|
|
-- Test: Verify invite is_pending was set to false after sign-in
|
|
SELECT is(
|
|
(
|
|
SELECT is_pending
|
|
FROM public.tablo_invites
|
|
WHERE invited_email = current_setting('test.temp_user_email')
|
|
AND invite_token = 'temp-user-token'
|
|
LIMIT 1
|
|
),
|
|
false,
|
|
'Invite should be marked as not pending after temporary user signs in'
|
|
);
|
|
|
|
-- ============================================================================
|
|
-- Trigger Timing Tests
|
|
-- ============================================================================
|
|
|
|
-- Test that tablo access trigger fires AFTER INSERT
|
|
SELECT trigger_is(
|
|
'public', 'tablos', 'trigger_create_tablo_access',
|
|
'public', 'create_tablo_access_for_owner',
|
|
'Tablo access trigger should fire after insert'
|
|
);
|
|
|
|
-- ============================================================================
|
|
-- Security Tests
|
|
-- ============================================================================
|
|
|
|
-- Test that trigger functions are SECURITY DEFINER
|
|
SELECT is(
|
|
(
|
|
SELECT prosecdef
|
|
FROM pg_proc
|
|
WHERE proname = 'create_tablo_access_for_owner'
|
|
LIMIT 1
|
|
),
|
|
true,
|
|
'create_tablo_access_for_owner should be SECURITY DEFINER'
|
|
);
|
|
|
|
SELECT is(
|
|
(
|
|
SELECT prosecdef
|
|
FROM pg_proc
|
|
WHERE proname = 'create_last_signed_in_on_profiles'
|
|
LIMIT 1
|
|
),
|
|
true,
|
|
'create_last_signed_in_on_profiles should be SECURITY DEFINER'
|
|
);
|
|
|
|
SELECT is(
|
|
(
|
|
SELECT prosecdef
|
|
FROM pg_proc
|
|
WHERE proname = 'update_tablo_invites_on_login'
|
|
LIMIT 1
|
|
),
|
|
true,
|
|
'update_tablo_invites_on_login should be SECURITY DEFINER'
|
|
);
|
|
|
|
SELECT is(
|
|
(
|
|
SELECT prosecdef
|
|
FROM pg_proc
|
|
WHERE proname = 'update_profile_subscription_status'
|
|
LIMIT 1
|
|
),
|
|
true,
|
|
'update_profile_subscription_status should be SECURITY DEFINER'
|
|
);
|
|
|
|
select * from finish();
|
|
rollback;
|
|
|