kandimat/backend/db/sql/04_setup_authentication.sql
Christoph Lienhard d2eaf3bd98
#17 unfinished
2021-06-23 17:49:49 +02:00

152 lines
4.5 KiB
PL/PgSQL

create extension if not exists "pgcrypto";
-- Define JWT claim structure
drop type if exists candymat_data.jwt_token cascade;
create type candymat_data.jwt_token as
(
role text,
person_row_id integer,
exp bigint
);
-- Function to get the currently logged-in person
drop function if exists candymat_data.current_person;
create function candymat_data.current_person(
) returns candymat_data.person as
$$
select *
from candymat_data.person
where row_id = nullif(current_setting('jwt.claims.person_row_id', true), '')::integer
$$ language sql stable;
grant execute on function candymat_data.current_person() to candymat_person;
-- Function to register a new user
drop function if exists candymat_data.register_person;
create function candymat_data.register_person(
first_name text,
last_name text,
email text,
password text
) returns candymat_data.person as
$$
declare
person candymat_data.person;
begin
if (trim(register_person.first_name) <> '') is not true then
raise 'Invalid first name: ''%''', register_person.first_name;
end if;
if (trim(register_person.last_name) <> '') is not true then
raise 'Invalid last name: ''%''', register_person.last_name;
end if;
if (trim(register_person.password) <> '') is not true then
raise 'Invalid password.';
end if;
insert into candymat_data.person (first_name, last_name)
values ($1, $2)
returning * into person;
insert into candymat_data_privat.person_account (person_row_id, email, password_hash)
values (person.row_id, $3, crypt($4, gen_salt('bf')));
return person;
end ;
$$ language plpgsql strict
security definer;
grant execute on function candymat_data.register_person(text, text, text, text) to candymat_anonymous;
-- Authenticate: Login for user
drop function if exists candymat_data.authenticate;
create function candymat_data.authenticate(
email text,
password text
) returns candymat_data.jwt_token as
$$
declare
account candymat_data_privat.person_account;
declare person candymat_data.person;
begin
select a.*
into account
from candymat_data_privat.person_account as a
where a.email = $1;
select p.*
into person
from candymat_data.person as p
where p.row_id = account.person_row_id;
if account.password_hash = crypt(password, account.password_hash) then
return (person.role, account.person_row_id,
extract(epoch from (now() + interval '2 days')))::candymat_data.jwt_token;
else
return null;
end if;
end;
$$ language plpgsql strict
security definer;
grant execute on function candymat_data.authenticate(text, text) to candymat_anonymous, candymat_person;
-- Change password
drop function if exists candymat_data.change_password;
create function candymat_data.change_password(
email text,
old_password text,
new_password text
) returns candymat_data.jwt_token as
$$
declare
account candymat_data_privat.person_account;
declare person candymat_data.person;
begin
select a.*
into account
from candymat_data_privat.person_account as a
where a.email = $1;
select p.*
into person
from candymat_data.person as p
where p.row_id = account.person_row_id;
if account.password_hash = crypt(old_password, account.password_hash) then
select *
from candymat_data.person
where row_id = nullif(current_setting('jwt.claims.person_row_id', true), '')::integer
return (person.role, account.person_row_id,
extract(epoch from (now() + interval '2 days')))::candymat_data.jwt_token;
else
return null;
end if;
end;
$$ language plpgsql strict
security definer;
grant execute on function candymat_data.change_role(integer, candymat_data.role) to candymat_editor;
-- Change role: Changes role for a given user. Only editors are allowed to use it.
drop function if exists candymat_data.change_role;
create function candymat_data.change_role(
person_row_id integer,
new_role candymat_data.role
)
returns candymat_data.person as
$$
declare
person candymat_data.person;
begin
update candymat_data.person
set role = new_role
where candymat_data.person.row_id = $1
returning * into person;
return person;
end;
$$ language plpgsql strict
security definer;
grant execute on function candymat_data.change_role(integer, candymat_data.role) to candymat_editor;