Move in progress apps temporarily
This commit is contained in:
parent
ba04aa108c
commit
6eaaf8e9be
360 changed files with 6171 additions and 55 deletions
|
|
@ -1,650 +0,0 @@
|
|||
--! Previous: -
|
||||
--! Hash: sha1:b13a5217288f5d349d8d9e3afbd7bb30c0dbad21
|
||||
|
||||
-- region Bootstrap
|
||||
drop schema if exists app_public cascade;
|
||||
alter default privileges revoke all on sequences from public;
|
||||
alter default privileges revoke all on functions from public;
|
||||
|
||||
-- By default the public schema is owned by `postgres`; we need superuser privileges to change this :(
|
||||
-- alter schema public owner to waterbear;
|
||||
revoke all on schema public from public;
|
||||
grant all on schema public to :DATABASE_OWNER;
|
||||
|
||||
|
||||
create schema app_public;
|
||||
grant usage on schema
|
||||
public,
|
||||
app_public
|
||||
to
|
||||
:DATABASE_VISITOR,
|
||||
app_admin,
|
||||
app_anonymous,
|
||||
app_user;
|
||||
|
||||
/**********/
|
||||
|
||||
drop schema if exists app_hidden cascade;
|
||||
create schema app_hidden;
|
||||
grant usage on schema app_hidden to :DATABASE_VISITOR;
|
||||
|
||||
alter default privileges in schema app_hidden grant usage, select on sequences to :DATABASE_VISITOR;
|
||||
|
||||
/**********/
|
||||
|
||||
alter default privileges in schema public, app_public, app_hidden grant usage, select on sequences to :DATABASE_VISITOR;
|
||||
alter default privileges in schema public, app_public, app_hidden
|
||||
grant execute on functions to
|
||||
:DATABASE_VISITOR,
|
||||
app_admin,
|
||||
app_user;
|
||||
|
||||
/**********/
|
||||
|
||||
drop schema if exists app_private cascade;
|
||||
create schema app_private;
|
||||
|
||||
|
||||
-- endregion
|
||||
-- region UtilFunctions
|
||||
create function app_private.tg__add_job() returns trigger as
|
||||
$$
|
||||
begin
|
||||
perform graphile_worker.add_job(tg_argv[0], json_build_object('id', NEW.id),
|
||||
coalesce(tg_argv[1], public.gen_random_uuid()::text));
|
||||
return NEW;
|
||||
end;
|
||||
$$ language plpgsql volatile
|
||||
security definer
|
||||
set search_path to pg_catalog, public, pg_temp;
|
||||
comment on function app_private.tg__add_job() is
|
||||
E'Useful shortcut to create a job on insert/update. Pass the task name as the first trigger argument, and optionally the queue name as the second argument. The record id will automatically be available on the JSON payload.';
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
|
||||
create function app_private.tg__timestamps() returns trigger as
|
||||
$$
|
||||
begin
|
||||
NEW.created_at = (case when TG_OP = 'INSERT' then NOW() else OLD.created_at end);
|
||||
NEW.updated_at = (case
|
||||
when TG_OP = 'UPDATE' and OLD.updated_at >= NOW()
|
||||
then OLD.updated_at + interval '1 millisecond'
|
||||
else NOW() end);
|
||||
return NEW;
|
||||
end;
|
||||
$$ language plpgsql volatile
|
||||
set search_path to pg_catalog, public, pg_temp;
|
||||
comment on function app_private.tg__timestamps() is
|
||||
E'This trigger should be called on all tables with created_at, updated_at - it ensures that they cannot be manipulated and that updated_at will always be larger than the previous updated_at.';
|
||||
|
||||
-- endregion
|
||||
|
||||
-- region Users, Sessions, and Accounts
|
||||
/* ------------------------------------------------------------------ */
|
||||
create table app_private.sessions
|
||||
(
|
||||
id uuid not null default gen_random_uuid() primary key,
|
||||
user_id uuid not null,
|
||||
expires timestamptz not null,
|
||||
session_token text not null,
|
||||
access_token text not null,
|
||||
created_at timestamptz not null default now(),
|
||||
updated_at timestamptz not null default now(),
|
||||
last_active_at timestamptz not null default now()
|
||||
);
|
||||
|
||||
create unique index session_token on app_private.sessions(session_token);
|
||||
create unique index access_token on app_private.sessions(access_token);
|
||||
|
||||
alter table app_private.sessions
|
||||
enable row level security;
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
|
||||
create function app_public.current_session_id() returns uuid as
|
||||
$$
|
||||
-- note the jwt.claims.session_id doesn't mean you have to use jwt, it is just where this function will always look for the session id.
|
||||
select nullif(pg_catalog.current_setting('jwt.claims.session_id', true), '')::uuid;
|
||||
$$ language sql stable;
|
||||
comment on function app_public.current_session_id() is
|
||||
E'Handy method to get the current session ID.';
|
||||
|
||||
/*
|
||||
* A less secure but more performant version of this function would be just:
|
||||
*
|
||||
* select nullif(pg_catalog.current_setting('jwt.claims.user_id', true), '')::int;
|
||||
*
|
||||
* The increased security of this implementation is because even if someone gets
|
||||
* the ability to run SQL within this transaction they cannot impersonate
|
||||
* another user without knowing their session_id (which should be closely
|
||||
* guarded).
|
||||
*/
|
||||
create function app_public.current_user_id() returns uuid as
|
||||
$$
|
||||
select user_id
|
||||
from app_private.sessions
|
||||
where id = app_public.current_session_id();
|
||||
$$ language sql stable
|
||||
security definer
|
||||
set search_path to pg_catalog, public, pg_temp;
|
||||
comment on function app_public.current_user_id() is
|
||||
E'Handy method to get the current user ID for use in RLS policies, etc; in GraphQL, use `currentUser{id}` instead.';
|
||||
-- We've put this in public, but omitted it, because it's often useful for debugging auth issues.
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
|
||||
-- These are the user roles for our application
|
||||
create type app_public.role_type as
|
||||
ENUM ('none','admin', 'user');
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
|
||||
create table app_public.users
|
||||
(
|
||||
id uuid not null default uuid_generate_v1mc() primary key,
|
||||
email citext not null,
|
||||
email_verified timestamptz,
|
||||
name text not null,
|
||||
avatar text,
|
||||
user_role app_public.role_type not null default 'none',
|
||||
is_active boolean not null default false,
|
||||
created_at timestamptz not null default now(),
|
||||
updated_at timestamptz not null default now(),
|
||||
created_by text not null,
|
||||
constraint users_email_validity check (email ~* '^[A-Za-z0-9._%-]+@[A-Za-z0-9.-]+[.][A-Za-z]+$'),
|
||||
constraint users_avatar_validity check (avatar ~ '^https?://[^/]+'),
|
||||
constraint users_email_unique unique (email)
|
||||
);
|
||||
comment on table app_public.users is
|
||||
E'A user who can log in to the application.';
|
||||
comment on column app_public.users.id is
|
||||
E'Unique identifier for the user.';
|
||||
comment on column app_public.users.email is
|
||||
E'The email address of the user.';
|
||||
comment on column app_public.users.email_verified is
|
||||
E'The time at which the email address was verified';
|
||||
comment on column app_public.users.name is
|
||||
E'Public-facing name (or pseudonym) of the user.';
|
||||
comment on column app_public.users.avatar is
|
||||
E'Optional avatar URL.';
|
||||
comment on column app_public.users.user_role is
|
||||
E'The role that defines the user''s privileges.';
|
||||
comment on column app_public.users.is_active is
|
||||
E'If false, the user is not allowed to login or access the application';
|
||||
|
||||
alter table app_public.users
|
||||
enable row level security;
|
||||
|
||||
alter table app_private.sessions
|
||||
add constraint sessions_user_id_fkey foreign key ("user_id") references app_public.users on delete cascade;
|
||||
|
||||
create index on app_private.sessions (user_id);
|
||||
|
||||
-- app_public perms default
|
||||
create policy access_self on app_public.users to app_anonymous using (id = app_public.current_user_id());
|
||||
|
||||
--create policy update_self on app_public.users for update using (id = app_public.current_user_id());
|
||||
grant select on app_public.users to app_anonymous;
|
||||
grant update (name, avatar) on app_public.users to :DATABASE_VISITOR, app_user;
|
||||
|
||||
-- app_public perms for app_admin
|
||||
create policy access_all on app_public.users to app_admin using (true);
|
||||
grant update (email, name, avatar, is_active, user_role) on app_public.users to app_admin;
|
||||
grant select on app_public.users to app_admin;
|
||||
grant insert (email, name, avatar, user_role, is_active, created_by) on app_public.users to app_admin;
|
||||
grant update (email, name, avatar, user_role, is_active, created_by) on app_public.users to app_admin;
|
||||
|
||||
create trigger _100_timestamps
|
||||
before insert or update
|
||||
on app_public.users
|
||||
for each row
|
||||
execute procedure app_private.tg__timestamps();
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
|
||||
create function app_public.current_user() returns app_public.users as
|
||||
$$
|
||||
select users.*
|
||||
from app_public.users
|
||||
where id = app_public.current_user_id();
|
||||
$$ language sql stable;
|
||||
comment on function app_public.current_user() is
|
||||
E'The currently logged in user (or null if not logged in).';
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
|
||||
create function app_public.logout() returns void as
|
||||
$$
|
||||
begin
|
||||
-- Delete the session
|
||||
delete from app_private.sessions where id = app_public.current_session_id();
|
||||
-- Clear the identifier from the transaction
|
||||
perform set_config('jwt.claims.session_id', '', true);
|
||||
end;
|
||||
$$ language plpgsql security definer
|
||||
volatile
|
||||
set search_path to pg_catalog, public, pg_temp;
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
|
||||
create table app_public.accounts
|
||||
(
|
||||
id uuid not null default uuid_generate_v1mc() primary key,
|
||||
compound_id text not null,
|
||||
user_id uuid not null,
|
||||
provider_type text not null,
|
||||
provider_id text not null,
|
||||
provider_account_id text not null,
|
||||
refresh_token text,
|
||||
access_token text,
|
||||
access_token_expires timestamptz,
|
||||
created_at timestamptz not null default now(),
|
||||
updated_at timestamptz not null default now()
|
||||
);
|
||||
|
||||
alter table app_public.accounts
|
||||
enable row level security;
|
||||
|
||||
alter table app_public.accounts
|
||||
add constraint accounts_user_id_fkey foreign key ("user_id") references app_public.users on delete cascade;
|
||||
|
||||
create unique index accounts_compound_id on app_public.accounts(compound_id);
|
||||
create index accounts_provider_account_id on app_public.accounts(provider_account_id);
|
||||
create index accounts_provider_id on app_public.accounts(provider_id);
|
||||
create index accounts_user_id on app_public.accounts (user_id);
|
||||
|
||||
create policy access_self on app_public.accounts to app_anonymous using (user_id = app_public.current_user_id());
|
||||
|
||||
grant select on app_public.accounts to app_anonymous;
|
||||
grant update (compound_id, provider_type, provider_id, provider_account_id, refresh_token, access_token, access_token_expires) on app_public.accounts to app_user;
|
||||
|
||||
create policy access_all on app_public.accounts to app_admin using (true);
|
||||
grant update (compound_id, provider_type, provider_id, provider_account_id, refresh_token, access_token, access_token_expires) on app_public.accounts to app_admin;
|
||||
grant select on app_public.accounts to app_admin;
|
||||
grant insert (user_id, compound_id, provider_type, provider_id, provider_account_id, refresh_token, access_token, access_token_expires) on app_public.accounts to app_admin;
|
||||
grant update (compound_id, provider_type, provider_id, provider_account_id, refresh_token, access_token, access_token_expires) on app_public.accounts to app_admin;
|
||||
|
||||
create trigger _100_timestamps
|
||||
before insert or update
|
||||
on app_public.accounts
|
||||
for each row
|
||||
execute procedure app_private.tg__timestamps();
|
||||
|
||||
-- endregion
|
||||
|
||||
-- region Create first user function
|
||||
|
||||
create or replace function app_public.create_first_user (user_email text, user_name text)
|
||||
returns setof app_public.users
|
||||
as
|
||||
$$
|
||||
declare
|
||||
user_count int;
|
||||
begin
|
||||
|
||||
user_count := (select count(id) from app_public.users);
|
||||
|
||||
if (user_count != 0) then
|
||||
raise exception 'Admin user already created';
|
||||
end if;
|
||||
|
||||
return query insert into app_public.users (email, email_verified, name, user_role, is_active, created_by)
|
||||
values (user_email, now(), user_name, 'admin', true, 'first user hook') returning *;
|
||||
end ;
|
||||
$$ LANGUAGE plpgsql VOLATILE
|
||||
SECURITY DEFINER;
|
||||
|
||||
|
||||
comment on function app_public.create_first_user(user_email text, user_name text) is
|
||||
E'Creates the first user with an admin role. Only possible when there are no other users in the database.';
|
||||
|
||||
grant execute on function app_public.create_first_user(user_email text, user_name text) to app_anonymous;
|
||||
|
||||
create function app_private.tg__first_user() returns trigger as
|
||||
$$
|
||||
declare
|
||||
user_count int;
|
||||
begin
|
||||
user_count := (select count(id) from app_public.users);
|
||||
|
||||
if (user_count = 0) then
|
||||
NEW.user_role = 'admin';
|
||||
end if;
|
||||
return NEW;
|
||||
end;
|
||||
$$ language plpgsql volatile
|
||||
set search_path to pg_catalog, public, pg_temp;
|
||||
comment on function app_private.tg__first_user() is
|
||||
E'This trigger is called to ensure the first user created is an admin';
|
||||
|
||||
|
||||
create trigger _101_first_user
|
||||
before insert
|
||||
on app_public.users
|
||||
for each row
|
||||
execute procedure app_private.tg__first_user();
|
||||
-- endregion
|
||||
|
||||
-- region Settings
|
||||
|
||||
create table app_public.settings
|
||||
(
|
||||
id uuid not null default uuid_generate_v1mc() primary key,
|
||||
name text not null,
|
||||
value jsonb,
|
||||
created_at timestamptz not null default now(),
|
||||
updated_at timestamptz not null default now()
|
||||
|
||||
);
|
||||
|
||||
create unique index setting_name on app_public.settings(name);
|
||||
|
||||
alter table app_public.settings
|
||||
enable row level security;
|
||||
|
||||
create policy access_all on app_public.settings to app_admin using (true);
|
||||
grant update (name, value) on app_public.settings to app_admin;
|
||||
grant select on app_public.settings to app_admin;
|
||||
grant insert (name, value) on app_public.settings to app_admin;
|
||||
|
||||
create trigger _100_timestamps
|
||||
before insert or update
|
||||
on app_public.settings
|
||||
for each row
|
||||
execute procedure app_private.tg__timestamps();
|
||||
|
||||
-- endregion
|
||||
|
||||
-- region Provider
|
||||
|
||||
create table app_public.voice_providers
|
||||
(
|
||||
id uuid not null default uuid_generate_v1mc() primary key,
|
||||
kind text not null,
|
||||
name text not null,
|
||||
credentials jsonb not null,
|
||||
created_at timestamptz not null default now(),
|
||||
updated_at timestamptz not null default now()
|
||||
);
|
||||
|
||||
create unique index voice_providers_number on app_public.voice_providers(name);
|
||||
|
||||
alter table app_public.voice_providers
|
||||
enable row level security;
|
||||
|
||||
create policy access_all on app_public.voice_providers to app_admin using (true);
|
||||
grant update (name, credentials) on app_public.voice_providers to app_admin;
|
||||
grant select on app_public.voice_providers to app_admin;
|
||||
grant insert (kind, name, credentials) on app_public.voice_providers to app_admin;
|
||||
grant delete on app_public.voice_providers to app_admin;
|
||||
|
||||
create trigger _100_timestamps
|
||||
before insert or update
|
||||
on app_public.voice_providers
|
||||
for each row
|
||||
execute procedure app_private.tg__timestamps();
|
||||
-- endregion
|
||||
|
||||
-- region Voice Line
|
||||
|
||||
create table app_public.voice_lines
|
||||
(
|
||||
id uuid not null default uuid_generate_v1mc() primary key,
|
||||
provider_id uuid not null,
|
||||
provider_line_sid text not null,
|
||||
number text not null,
|
||||
language text not null,
|
||||
voice text not null,
|
||||
prompt_text text,
|
||||
prompt_audio jsonb,
|
||||
audio_prompt_enabled boolean not null default false,
|
||||
audio_converted_at timestamptz,
|
||||
created_at timestamptz not null default now(),
|
||||
updated_at timestamptz not null default now()
|
||||
);
|
||||
|
||||
alter table app_public.voice_lines
|
||||
add constraint voice_lines_provider_id_fkey foreign key ("provider_id") references app_public.voice_providers on delete cascade;
|
||||
|
||||
create index on app_public.voice_lines (provider_id);
|
||||
create index on app_public.voice_lines (provider_line_sid);
|
||||
create unique index voice_lines_number on app_public.voice_lines(number);
|
||||
|
||||
alter table app_public.voice_lines
|
||||
enable row level security;
|
||||
|
||||
create policy access_all on app_public.voice_lines to app_admin using (true);
|
||||
grant update (prompt_text, prompt_audio, audio_prompt_enabled, language, voice) on app_public.voice_lines to app_admin;
|
||||
grant select on app_public.voice_lines to app_admin;
|
||||
grant insert (provider_id, provider_line_sid, number, prompt_text, prompt_audio, audio_prompt_enabled, language, voice) on app_public.voice_lines to app_admin;
|
||||
grant delete on app_public.voice_lines to app_admin;
|
||||
|
||||
create trigger _100_timestamps
|
||||
before insert or update
|
||||
on app_public.voice_lines
|
||||
for each row
|
||||
execute procedure app_private.tg__timestamps();
|
||||
|
||||
|
||||
create function app_private.tg__voice_line_provider_update() returns trigger as $$
|
||||
begin
|
||||
if (TG_OP = 'DELETE') then
|
||||
perform graphile_worker.add_job('voice-line-delete', json_build_object('voiceLineId', OLD.id, 'providerId', OLD.provider_id, 'providerLineSid', OLD.provider_line_sid));
|
||||
else
|
||||
perform graphile_worker.add_job('voice-line-provider-update', json_build_object('voiceLineId', NEW.id));
|
||||
end if;
|
||||
|
||||
return null;
|
||||
end;
|
||||
$$ language plpgsql volatile security definer set search_path to pg_catalog, public, pg_temp;
|
||||
|
||||
comment on function app_private.tg__voice_line_provider_update() is
|
||||
E'This trigger is called to ensure a voice line is connected to twilio properly';
|
||||
|
||||
|
||||
create trigger _101_voice_line_provider_update
|
||||
after insert or update of provider_line_sid or delete
|
||||
on app_public.voice_lines
|
||||
for each row
|
||||
execute procedure app_private.tg__voice_line_provider_update();
|
||||
|
||||
create function app_private.tg__voice_line_prompt_audio_update() returns trigger as $$
|
||||
begin
|
||||
perform graphile_worker.add_job('voice-line-audio-update', json_build_object('voiceLineId', NEW.id));
|
||||
return null;
|
||||
end;
|
||||
$$ language plpgsql volatile security definer set search_path to pg_catalog, public, pg_temp;
|
||||
|
||||
comment on function app_private.tg__voice_line_prompt_audio_update() is
|
||||
E'This trigger is called to ensure a voice line is connected to twilio properly';
|
||||
|
||||
|
||||
create trigger _101_voice_line_prompt_audio_update
|
||||
after insert or update of prompt_audio
|
||||
on app_public.voice_lines
|
||||
for each row
|
||||
execute procedure app_private.tg__voice_line_prompt_audio_update();
|
||||
-- endregion
|
||||
|
||||
-- region Webhooks
|
||||
create table app_public.webhooks
|
||||
(
|
||||
id uuid not null default uuid_generate_v1mc() primary key,
|
||||
backend_type text not null,
|
||||
backend_id uuid not null,
|
||||
name text not null,
|
||||
endpoint_url text not null,
|
||||
http_method text not null default 'post',
|
||||
headers jsonb,
|
||||
created_at timestamptz not null default now(),
|
||||
updated_at timestamptz not null default now(),
|
||||
constraint webhook_http_method_validity check (http_method in ('post', 'put')),
|
||||
constraint webhook_endpoint_url_validity check (endpoint_url ~ '^https?://[^/]+')
|
||||
);
|
||||
|
||||
create index on app_public.webhooks (backend_type, backend_id);
|
||||
|
||||
alter table app_public.webhooks
|
||||
enable row level security;
|
||||
|
||||
create policy access_all on app_public.webhooks to app_admin using (true);
|
||||
grant update (name, endpoint_url, http_method, headers) on app_public.webhooks to app_admin;
|
||||
grant select on app_public.webhooks to app_admin;
|
||||
grant insert (backend_type, backend_id, name, endpoint_url, http_method, headers) on app_public.webhooks to app_admin;
|
||||
grant delete on app_public.webhooks to app_admin;
|
||||
|
||||
create trigger _100_timestamps
|
||||
before insert or update
|
||||
on app_public.webhooks
|
||||
for each row
|
||||
execute procedure app_private.tg__timestamps();
|
||||
-- endregion
|
||||
|
||||
-- region WhatsappBots
|
||||
set transform_null_equals to true;
|
||||
create table app_public.whatsapp_bots
|
||||
(
|
||||
id uuid not null default uuid_generate_v1mc() primary key,
|
||||
phone_number text not null,
|
||||
token uuid not null default uuid_generate_v1mc(),
|
||||
user_id uuid not null,
|
||||
description text,
|
||||
auth_info text,
|
||||
qr_code text,
|
||||
is_verified boolean not null default false,
|
||||
created_at timestamptz not null default now(),
|
||||
updated_at timestamptz not null default now()
|
||||
|
||||
);
|
||||
|
||||
create unique index whatsapp_bot_token on app_public.whatsapp_bots(token);
|
||||
|
||||
alter table app_public.whatsapp_bots
|
||||
add constraint whatsapp_bots_user_id_fkey foreign key ("user_id") references app_public.users on delete cascade;
|
||||
|
||||
alter table app_public.whatsapp_bots
|
||||
enable row level security;
|
||||
|
||||
create policy access_all on app_public.whatsapp_bots to app_admin using (true);
|
||||
grant update (phone_number, token, user_id, description, auth_info, qr_code, is_verified) on app_public.whatsapp_bots to app_admin;
|
||||
grant select on app_public.whatsapp_bots to app_admin;
|
||||
grant insert (phone_number, token, user_id, description, auth_info, qr_code, is_verified) on app_public.whatsapp_bots to app_admin;
|
||||
|
||||
create trigger _100_timestamps
|
||||
before insert or update
|
||||
on app_public.whatsapp_bots
|
||||
for each row
|
||||
execute procedure app_private.tg__timestamps();
|
||||
|
||||
-- endregion
|
||||
-- region WhatsappMessages
|
||||
|
||||
create table app_public.whatsapp_messages
|
||||
(
|
||||
id uuid not null default uuid_generate_v1mc() primary key,
|
||||
whatsapp_bot_id uuid not null,
|
||||
wa_message_id text,
|
||||
wa_message text,
|
||||
wa_timestamp timestamptz,
|
||||
created_at timestamptz not null default now(),
|
||||
updated_at timestamptz not null default now()
|
||||
|
||||
);
|
||||
|
||||
create unique index whatsapp_message_whatsapp_bot_id on app_public.whatsapp_messages(whatsapp_bot_id);
|
||||
|
||||
alter table app_public.whatsapp_messages
|
||||
add constraint whatsapp_messages_whatsapp_bot_id_fkey foreign key ("whatsapp_bot_id") references app_public.whatsapp_bots on delete cascade;
|
||||
|
||||
alter table app_public.whatsapp_messages
|
||||
enable row level security;
|
||||
|
||||
create policy access_all on app_public.whatsapp_messages to app_admin using (true);
|
||||
grant update (whatsapp_bot_id, wa_message_id, wa_message, wa_timestamp) on app_public.whatsapp_messages to app_admin;
|
||||
grant select on app_public.whatsapp_messages to app_admin;
|
||||
grant insert (whatsapp_bot_id, wa_message_id, wa_message, wa_timestamp) on app_public.whatsapp_messages to app_admin;
|
||||
|
||||
create trigger _100_timestamps
|
||||
before insert or update
|
||||
on app_public.whatsapp_messages
|
||||
for each row
|
||||
execute procedure app_private.tg__timestamps();
|
||||
|
||||
-- endregion
|
||||
-- region WhatsappAttachments
|
||||
|
||||
create table app_public.whatsapp_attachments
|
||||
(
|
||||
id uuid not null default uuid_generate_v1mc() primary key,
|
||||
whatsapp_bot_id uuid not null,
|
||||
whatsapp_message_id uuid,
|
||||
attachment bytea,
|
||||
created_at timestamptz not null default now(),
|
||||
updated_at timestamptz not null default now()
|
||||
|
||||
);
|
||||
|
||||
create unique index whatsapp_attachment_whatsapp_bot_id on app_public.whatsapp_attachments(whatsapp_bot_id);
|
||||
create unique index whatsapp_attachment_whatsapp_message_id on app_public.whatsapp_attachments(whatsapp_message_id);
|
||||
|
||||
alter table app_public.whatsapp_attachments
|
||||
add constraint whatsapp_attachments_whatsapp_bot_id_fkey foreign key ("whatsapp_bot_id") references app_public.whatsapp_bots on delete cascade;
|
||||
alter table app_public.whatsapp_attachments
|
||||
add constraint whatsapp_attachments_whatsapp_message_id_fkey foreign key ("whatsapp_message_id") references app_public.whatsapp_messages on delete cascade;
|
||||
|
||||
alter table app_public.whatsapp_attachments
|
||||
enable row level security;
|
||||
|
||||
create policy access_all on app_public.whatsapp_attachments to app_admin using (true);
|
||||
grant update (whatsapp_bot_id, whatsapp_message_id, attachment) on app_public.whatsapp_attachments to app_admin;
|
||||
grant select on app_public.whatsapp_attachments to app_admin;
|
||||
grant insert (whatsapp_bot_id, whatsapp_message_id, attachment) on app_public.whatsapp_attachments to app_admin;
|
||||
|
||||
create trigger _100_timestamps
|
||||
before insert or update
|
||||
on app_public.whatsapp_attachments
|
||||
for each row
|
||||
execute procedure app_private.tg__timestamps();
|
||||
|
||||
-- endregion
|
||||
|
||||
-- region SignalBots
|
||||
set transform_null_equals to true;
|
||||
create table app_public.signal_bots
|
||||
(
|
||||
id uuid not null default uuid_generate_v1mc() primary key,
|
||||
phone_number text not null,
|
||||
token uuid not null default uuid_generate_v1mc(),
|
||||
user_id uuid not null,
|
||||
description text,
|
||||
auth_info text,
|
||||
is_verified boolean not null default false,
|
||||
created_at timestamptz not null default now(),
|
||||
updated_at timestamptz not null default now()
|
||||
|
||||
);
|
||||
|
||||
create unique index signal_bot_token on app_public.signal_bots(token);
|
||||
|
||||
alter table app_public.signal_bots
|
||||
add constraint signal_bots_user_id_fkey foreign key ("user_id") references app_public.users on delete cascade;
|
||||
|
||||
alter table app_public.signal_bots
|
||||
enable row level security;
|
||||
|
||||
create policy access_all on app_public.signal_bots to app_admin using (true);
|
||||
grant update (phone_number, token, user_id, description, auth_info, is_verified) on app_public.signal_bots to app_admin;
|
||||
grant select on app_public.signal_bots to app_admin;
|
||||
grant insert (phone_number, token, user_id, description, auth_info, is_verified) on app_public.signal_bots to app_admin;
|
||||
|
||||
create trigger _100_timestamps
|
||||
before insert or update
|
||||
on app_public.signal_bots
|
||||
for each row
|
||||
execute procedure app_private.tg__timestamps();
|
||||
|
||||
|
||||
-- endregion
|
||||
Loading…
Add table
Add a link
Reference in a new issue