All checks were successful
Deploy MineGeo to Dokploy / deploy (push) Successful in 3m27s
50 lines
3.2 KiB
PL/PgSQL
50 lines
3.2 KiB
PL/PgSQL
alter table public.profiles add column username text;
|
|
alter table public.profiles add constraint profiles_username_format check (username is null or username ~ '^[a-z0-9_]{3,32}$');
|
|
create unique index profiles_username_unique on public.profiles (username) where username is not null;
|
|
|
|
create table public.moderator_applications (
|
|
id uuid primary key default gen_random_uuid(),
|
|
platform text not null check (platform in ('telegram', 'discord')),
|
|
platform_user_id text not null,
|
|
platform_username text,
|
|
requested_username text not null,
|
|
profile_id uuid references public.profiles(id) on delete set null,
|
|
confirmation_hash text not null unique,
|
|
status text not null default 'confirming' check (status in ('confirming', 'pending', 'approved', 'declined')),
|
|
expires_at timestamptz not null default (now() + interval '30 minutes'),
|
|
created_at timestamptz not null default now(),
|
|
reviewed_at timestamptz,
|
|
reviewer_discord_id text,
|
|
admin_notified_at timestamptz,
|
|
applicant_notified_at timestamptz
|
|
);
|
|
create index moderator_applications_queue on public.moderator_applications (created_at) where status = 'pending';
|
|
create unique index moderator_applications_one_open on public.moderator_applications (platform, platform_user_id) where status = 'pending';
|
|
alter table public.moderator_applications enable row level security;
|
|
revoke all on public.moderator_applications from public, anon, authenticated;
|
|
grant all on public.moderator_applications to service_role;
|
|
|
|
create table public.moderator_bot_admin (id boolean primary key default true check (id), discord_user_id text not null);
|
|
alter table public.moderator_bot_admin enable row level security;
|
|
revoke all on public.moderator_bot_admin from public, anon, authenticated;
|
|
grant all on public.moderator_bot_admin to service_role;
|
|
|
|
create function public.review_moderator_application(p_application uuid, p_decision text, p_reviewer text)
|
|
returns text language plpgsql security invoker set search_path = '' as $$
|
|
declare application public.moderator_applications; current_role text; current_status text;
|
|
begin
|
|
if not exists (select 1 from public.moderator_bot_admin where discord_user_id = p_reviewer) then raise exception 'Admin permission required'; end if;
|
|
if p_decision not in ('approved', 'declined') then raise exception 'Invalid decision'; end if;
|
|
select * into application from public.moderator_applications where id = p_application for update;
|
|
if not found or application.status <> 'pending' then raise exception 'Application is no longer pending'; end if;
|
|
if p_decision = 'approved' then
|
|
select role, account_status into current_role, current_status from public.profiles where id = application.profile_id for update;
|
|
if not found or current_status <> 'active' or current_role <> 'contributor' then raise exception 'Account cannot be promoted'; end if;
|
|
update public.profiles set role = 'moderator' where id = application.profile_id;
|
|
end if;
|
|
update public.moderator_applications set status = p_decision, reviewed_at = now(), reviewer_discord_id = p_reviewer where id = p_application;
|
|
return p_decision;
|
|
end; $$;
|
|
revoke all on function public.review_moderator_application(uuid,text,text) from public, anon, authenticated;
|
|
grant execute on function public.review_moderator_application(uuid,text,text) to service_role;
|