./migrations/202de79_to_5f9c3c7.sql

This commit is contained in:
Orion Kindel 2023-07-17 14:24:14 -04:00
parent 7fde5ae5a3
commit 1a95cd0462
Signed by untrusted user who does not match committer: orion
GPG Key ID: 6D4165AE4C928719

442
202de79_to_5f9c3c7.sql Normal file
View File

@ -0,0 +1,442 @@
alter table "public"."usr_session" drop column "expired";
alter table "public"."usr_session" add column "remembered" boolean not null default false;
set check_function_bodies = off;
CREATE OR REPLACE FUNCTION public.usr_session_touch(session usr_session_key)
RETURNS usr
LANGUAGE plpgsql
AS $function$
declare
session public.usr_session;
session_usr public.usr;
new_exp timestamp;
begin
select s
from public.usr_session s
where s.key = session
into session;
if session is null then
raise exception 'usr_session_invalid';
end if;
if session.expires_at <= now() then
raise exception 'usr_session_expired';
end if;
if session.remembered then
new_exp := now() + interval '1 week';
else
new_exp := now() + interval '1 hour';
end if;
update public.usr_session s
set s.expires_at = new_exp
where s.id = session.id;
select u.*
from public.usr u
where u.id = session.usr
into session_usr;
return session_usr;
end;
$function$
;
CREATE OR REPLACE FUNCTION public.do_check_usr_tag()
RETURNS trigger
LANGUAGE plpgsql
STABLE
AS $function$
begin
if new.tag = usr_tag_of_string('root') then
raise exception 'tag_invalid';
else
return new;
end if;
end;
$function$
;
CREATE OR REPLACE FUNCTION public.do_community_immutable_columns()
RETURNS trigger
LANGUAGE plpgsql
AS $function$
begin
if OLD.id <> NEW.id then
raise exception 'immutable_field'
using detail = 'public.community.id is immutable',
errcode = 'restrict_violation';
elsif OLD.uid <> NEW.uid then
raise exception 'immutable_field'
using detail = 'public.community.uid is immutable',
errcode = 'restrict_violation';
end if;
return NEW;
end;
$function$
;
CREATE OR REPLACE FUNCTION public.do_grp_immutable_columns()
RETURNS trigger
LANGUAGE plpgsql
AS $function$
begin
if OLD.id <> NEW.id then
raise exception 'immutable_field'
using detail = 'public.grp.id is immutable',
errcode = 'restrict_violation';
elsif OLD.uid <> NEW.uid then
raise exception 'immutable_field'
using detail = 'public.grp.uid is immutable',
errcode = 'restrict_violation';
elsif OLD.tag <> NEW.tag then
raise exception 'immutable_field'
using detail = 'public.grp.tag is immutable',
errcode = 'restrict_violation';
end if;
return NEW;
end;
$function$
;
CREATE OR REPLACE FUNCTION public.do_perm_immutable_columns()
RETURNS trigger
LANGUAGE plpgsql
AS $function$
begin
if OLD.id <> NEW.id then
raise exception 'immutable_field'
using detail = 'public.perm.id is immutable',
errcode = 'restrict_violation';
elsif OLD.uid <> NEW.uid then
raise exception 'immutable_field'
using detail = 'public.perm.uid is immutable',
errcode = 'restrict_violation';
elsif OLD.path <> NEW.path then
raise exception 'immutable_field'
using detail = 'public.perm.path is immutable',
errcode = 'restrict_violation';
end if;
return NEW;
end;
$function$
;
CREATE OR REPLACE FUNCTION public.do_thread_attachment_emoji_immutable_columns()
RETURNS trigger
LANGUAGE plpgsql
AS $function$
begin
if OLD.id <> NEW.id then
raise exception 'immutable_field'
using detail = 'public.thread_attachment_emoji.id is immutable',
errcode = 'restrict_violation';
elsif OLD.uid <> NEW.uid then
raise exception 'immutable_field'
using detail = 'public.thread_attachment_emoji.uid is immutable',
errcode = 'restrict_violation';
elsif OLD.thread_attachment <> NEW.thread_attachment then
raise exception 'immutable_field'
using detail = 'public.thread_attachment_emoji.thread_attachment is immutable',
errcode = 'restrict_violation';
elsif OLD.emoji <> NEW.emoji then
raise exception 'immutable_field'
using detail = 'public.thread_attachment_emoji.emoji is immutable',
errcode = 'restrict_violation';
end if;
return NEW;
end;
$function$
;
CREATE OR REPLACE FUNCTION public.do_thread_attachment_immutable_columns()
RETURNS trigger
LANGUAGE plpgsql
AS $function$
begin
if OLD.id <> NEW.id then
raise exception 'immutable_field'
using detail = 'public.thread_attachment.id is immutable',
errcode = 'restrict_violation';
elsif OLD.uid <> NEW.uid then
raise exception 'immutable_field'
using detail = 'public.thread_attachment.uid is immutable',
errcode = 'restrict_violation';
elsif OLD.thread <> NEW.thread then
raise exception 'immutable_field'
using detail = 'public.thread_attachment.thread is immutable',
errcode = 'restrict_violation';
elsif OLD.kind <> NEW.kind then
raise exception 'immutable_field'
using detail = 'public.thread_attachment.kind is immutable',
errcode = 'restrict_violation';
end if;
return NEW;
end;
$function$
;
CREATE OR REPLACE FUNCTION public.do_thread_attachment_vote_immutable_columns()
RETURNS trigger
LANGUAGE plpgsql
AS $function$
begin
if OLD.id <> NEW.id then
raise exception 'immutable_field'
using detail = 'public.thread_attachment_vote.id is immutable',
errcode = 'restrict_violation';
elsif OLD.uid <> NEW.uid then
raise exception 'immutable_field'
using detail = 'public.thread_attachment_vote.uid is immutable',
errcode = 'restrict_violation';
elsif OLD.thread_attachment <> NEW.thread_attachment then
raise exception 'immutable_field'
using detail = 'public.thread_attachment_vote.thread_attachment is immutable',
errcode = 'restrict_violation';
elsif OLD.direction <> NEW.direction then
raise exception 'immutable_field'
using detail = 'public.thread_attachment_vote.direction is immutable',
errcode = 'restrict_violation';
end if;
return NEW;
end;
$function$
;
CREATE OR REPLACE FUNCTION public.do_thread_feed_immutable_columns()
RETURNS trigger
LANGUAGE plpgsql
AS $function$
begin
if OLD.id <> NEW.id then
raise exception 'immutable_field'
using detail = 'public.thread_feed.id is immutable',
errcode = 'restrict_violation';
elsif OLD.uid <> NEW.uid then
raise exception 'immutable_field'
using detail = 'public.thread_feed.uid is immutable',
errcode = 'restrict_violation';
elsif OLD.thread <> NEW.thread then
raise exception 'immutable_field'
using detail = 'public.thread_feed.thread is immutable',
errcode = 'restrict_violation';
elsif OLD.community <> NEW.community then
raise exception 'immutable_field'
using detail = 'public.thread_feed.community is immutable',
errcode = 'restrict_violation';
end if;
return NEW;
end;
$function$
;
CREATE OR REPLACE FUNCTION public.do_thread_immutable_columns()
RETURNS trigger
LANGUAGE plpgsql
AS $function$
begin
if OLD.id <> NEW.id then
raise exception 'immutable_field'
using detail = 'public.thread.id is immutable',
errcode = 'restrict_violation';
elsif OLD.uid <> NEW.uid then
raise exception 'immutable_field'
using detail = 'public.thread.uid is immutable',
errcode = 'restrict_violation';
elsif OLD.kind <> NEW.kind then
raise exception 'immutable_field'
using detail = 'public.thread.kind is immutable',
errcode = 'restrict_violation';
end if;
return NEW;
end;
$function$
;
CREATE OR REPLACE FUNCTION public.do_usr_immutable_columns()
RETURNS trigger
LANGUAGE plpgsql
AS $function$
begin
if OLD.id <> NEW.id then
raise exception 'immutable_field'
using detail = 'public.usr.id is immutable',
errcode = 'restrict_violation';
elsif OLD.uid <> NEW.uid then
raise exception 'immutable_field'
using detail = 'public.usr.uid is immutable',
errcode = 'restrict_violation';
end if;
return NEW;
end;
$function$
;
CREATE OR REPLACE FUNCTION public.do_usr_session_immutable_columns()
RETURNS trigger
LANGUAGE plpgsql
AS $function$
begin
if OLD.id <> NEW.id then
raise exception 'immutable_field'
using detail = 'public.usr_session.id is immutable',
errcode = 'restrict_violation';
elsif OLD.key <> NEW.key then
raise exception 'immutable_field'
using detail = 'public.usr_session.key is immutable',
errcode = 'restrict_violation';
elsif OLD.expires_at <> NEW.expires_at then
raise exception 'immutable_field'
using detail = 'public.usr_session.expires_at is immutable',
errcode = 'restrict_violation';
elsif OLD.usr <> NEW.usr then
raise exception 'immutable_field'
using detail = 'public.usr_session.usr is immutable',
errcode = 'restrict_violation';
elsif OLD.location <> NEW.location then
raise exception 'immutable_field'
using detail = 'public.usr_session.location is immutable',
errcode = 'restrict_violation';
elsif OLD.device <> NEW.device then
raise exception 'immutable_field'
using detail = 'public.usr_session.device is immutable',
errcode = 'restrict_violation';
elsif OLD.ip <> NEW.ip then
raise exception 'immutable_field'
using detail = 'public.usr_session.ip is immutable',
errcode = 'restrict_violation';
end if;
return NEW;
end;
$function$
;
CREATE OR REPLACE FUNCTION public.immutable(schema text, table_ text, columns text[])
RETURNS void
LANGUAGE plpgsql
AS $function$
declare
col text;
qualified_name text := concat(schema, '.', table_);
do_table_immutable_columns text := concat('do_', table_, '_immutable_columns');
trigger_table_immutable_columns text := concat('trigger_', table_, '_immutable_columns');
create_do_table_immutable_columns text;
create_trigger_table_immutable_columns text;
begin
create_do_table_immutable_columns := concat( create_do_table_immutable_columns
, 'create function ', schema, '.', do_table_immutable_columns, E'() returns trigger language plpgsql as \$\$\n'
, E'begin\n'
, ' if OLD.', columns[1], ' <> NEW.', columns[1], E' then\n'
, E' raise exception \'immutable_field\'\n'
, E' using detail = \'', qualified_name, '.', columns[1], E' is immutable\',\n'
, E' errcode = \'restrict_violation\';\n'
);
foreach col in array columns[2:] loop
create_do_table_immutable_columns := concat( create_do_table_immutable_columns
, E' elsif OLD.', col, ' <> NEW.', col, E' then\n'
, E' raise exception \'immutable_field\'\n'
, E' using detail = \'', qualified_name, '.', col, E' is immutable\',\n'
, E' errcode = \'restrict_violation\';\n'
);
end loop;
create_do_table_immutable_columns := concat( create_do_table_immutable_columns
, E' end if;\n'
, E'\n'
, E' return NEW;\n'
, E'end;\n'
, E'\$\$;\n'
);
create_trigger_table_immutable_columns := concat( create_trigger_table_immutable_columns
, 'create trigger ', trigger_table_immutable_columns, E'\n'
, 'before update on ', qualified_name, E'\n'
, 'for each row execute function ', do_table_immutable_columns, '();'
);
execute create_do_table_immutable_columns;
execute create_trigger_table_immutable_columns;
end;
$function$
;
CREATE OR REPLACE FUNCTION public.usr_session_login(tag_or_email usr_tag_or_email, password text, remember boolean DEFAULT false, location text DEFAULT NULL::text, device usr_session_device DEFAULT NULL::usr_session_device, ip inet DEFAULT NULL::inet)
RETURNS usr_session_key
LANGUAGE plpgsql
AS $function$
declare
usr public.usr;
key public.usr_session_key := usr_session_key_gen();
expires_at timestamp;
begin
usr := public.usr_session_login_validate(tag_or_email, password);
if remember then
expires_at := now() + interval '1 week';
else
expires_at := now() + interval '1 hour';
end if;
insert into public.usr_session
(key, expires_at, usr, remembered, location, device, ip)
values
(key, expires_at, usr.id, remember, location, device, ip);
return key;
end;
$function$
;
CREATE OR REPLACE FUNCTION public.usr_session_login_validate(tag_or_email usr_tag_or_email, password text)
RETURNS usr
LANGUAGE plpgsql
STABLE
AS $function$
declare
usr_email public.email := public.usr_tag_or_email_to_email(tag_or_email);
usr_tag public.usr_tag := public.usr_tag_or_email_to_tag(tag_or_email);
usr public.usr;
begin
select *
from public.usr as u
where u.email = usr_email
or u.tag = usr_tag
into usr;
if usr.id = 1 or usr.tag = usr_tag_of_string('root') then
raise notice 'root user may not be logged into';
raise exception 'incorrect_password';
end if;
if usr is null then
-- prevent email guess bruteforces by raising the same exception
-- for invalid password and user not found
raise notice 'user % not found', usr_tag_or_email_to_string(tag_or_email);
raise exception 'incorrect_password';
end if;
if not hashed_text_matches(password, usr.password) then
raise notice 'password does not match for user %', usr_tag_or_email_to_string(tag_or_email);
raise exception 'incorrect_password';
end if;
return usr;
end;
$function$
;