61517879e1
- Create Kong declarative configuration for routing and authentication. - Implement initialization script to set up the database. - Add SQL migration for initializing roles, schemas, and seeding vehicle data. - Create leads and customers tables with appropriate policies and functions for CRM. - Seed admin user and configure storage bucket with RLS policies.
82 lines
3.5 KiB
SQL
82 lines
3.5 KiB
SQL
-- Runs AFTER GoTrue and Storage auto-migrate their schemas.
|
|
-- Seeds the admin user (from psql vars :admin_email / :admin_password),
|
|
-- the vehicle-photos storage bucket, and storage RLS policies. Idempotent.
|
|
--
|
|
-- IMPORTANT: the seeded password is a BOOTSTRAP value only. The admin UI
|
|
-- enforces a password rotation on first login via
|
|
-- auth.users.raw_user_meta_data.must_change_password=true, so the real
|
|
-- operational password is NEVER equal to the .env seed.
|
|
|
|
-- Publish psql vars as GUCs so the DO block can read them reliably.
|
|
select set_config('mccars.admin_email', :'admin_email', false);
|
|
select set_config('mccars.admin_password', :'admin_password', false);
|
|
|
|
do $$
|
|
declare
|
|
v_user_id uuid;
|
|
v_email text := coalesce(nullif(current_setting('mccars.admin_email', true), ''), 'admin@mccars.local');
|
|
v_pass text := coalesce(nullif(current_setting('mccars.admin_password', true), ''), 'mc-cars-admin');
|
|
begin
|
|
if not exists (select 1 from auth.users where email = v_email) then
|
|
v_user_id := gen_random_uuid();
|
|
insert into auth.users (
|
|
id, instance_id, aud, role, email, encrypted_password,
|
|
email_confirmed_at, raw_app_meta_data, raw_user_meta_data,
|
|
created_at, updated_at, is_super_admin,
|
|
confirmation_token, email_change, email_change_token_new, recovery_token
|
|
) values (
|
|
v_user_id,
|
|
'00000000-0000-0000-0000-000000000000',
|
|
'authenticated', 'authenticated',
|
|
v_email,
|
|
crypt(v_pass, gen_salt('bf')),
|
|
now(),
|
|
jsonb_build_object('provider','email','providers',jsonb_build_array('email')),
|
|
jsonb_build_object('must_change_password', true),
|
|
now(), now(), false, '', '', '', ''
|
|
);
|
|
|
|
insert into auth.identities (
|
|
id, user_id, identity_data, provider, provider_id,
|
|
last_sign_in_at, created_at, updated_at
|
|
) values (
|
|
gen_random_uuid(), v_user_id,
|
|
jsonb_build_object('sub', v_user_id::text, 'email', v_email),
|
|
'email', v_email,
|
|
now(), now(), now()
|
|
);
|
|
end if;
|
|
end
|
|
$$;
|
|
|
|
-- -----------------------------------------------------------------------------
|
|
-- Storage bucket + RLS
|
|
-- -----------------------------------------------------------------------------
|
|
insert into storage.buckets (id, name, public, file_size_limit, allowed_mime_types)
|
|
values ('vehicle-photos','vehicle-photos', true, 52428800,
|
|
array['image/jpeg','image/png','image/webp','image/avif'])
|
|
on conflict (id) do update
|
|
set public = excluded.public,
|
|
file_size_limit = excluded.file_size_limit,
|
|
allowed_mime_types = excluded.allowed_mime_types;
|
|
|
|
drop policy if exists "vehicle_photos_public_read" on storage.objects;
|
|
drop policy if exists "vehicle_photos_admin_insert" on storage.objects;
|
|
drop policy if exists "vehicle_photos_admin_update" on storage.objects;
|
|
drop policy if exists "vehicle_photos_admin_delete" on storage.objects;
|
|
|
|
create policy "vehicle_photos_public_read"
|
|
on storage.objects for select using (bucket_id = 'vehicle-photos');
|
|
|
|
create policy "vehicle_photos_admin_insert"
|
|
on storage.objects for insert to authenticated
|
|
with check (bucket_id = 'vehicle-photos');
|
|
|
|
create policy "vehicle_photos_admin_update"
|
|
on storage.objects for update to authenticated
|
|
using (bucket_id = 'vehicle-photos') with check (bucket_id = 'vehicle-photos');
|
|
|
|
create policy "vehicle_photos_admin_delete"
|
|
on storage.objects for delete to authenticated
|
|
using (bucket_id = 'vehicle-photos');
|