kandimat/backend/sql/04_setup_authentication.sql
Christoph Lienhard f7a56a0bed Rename candymat -> kandimat everywhere
Furthermore, submodule link to new public repo
2022-02-02 15:06:13 +01:00

114 lines
3.3 KiB
PL/PgSQL

create extension if not exists "pgcrypto";
-- Define JWT claim structure
drop type if exists kandimat_data.jwt_token cascade;
create type kandimat_data.jwt_token as
(
role text,
person_row_id integer,
exp bigint
);
-- Function to get the currently logged-in person
drop function if exists kandimat_data.current_person;
create function kandimat_data.current_person(
) returns kandimat_data.person as
$$
select *
from kandimat_data.person
where row_id = nullif(current_setting('jwt.claims.person_row_id', true), '')::integer
$$ language sql stable;
grant execute on function kandimat_data.current_person() to kandimat_person;
-- Function to register a new user
drop function if exists kandimat_data.register_person;
create function kandimat_data.register_person(
first_name text,
last_name text,
email text,
password text
) returns kandimat_data.person as
$$
declare
person kandimat_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 kandimat_data.person (first_name, last_name)
values ($1, $2)
returning * into person;
insert into kandimat_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 kandimat_data.register_person(text, text, text, text) to kandimat_anonymous;
-- Authenticate: Login for user
drop function if exists kandimat_data.authenticate;
create function kandimat_data.authenticate(
email text,
password text
) returns kandimat_data.jwt_token as
$$
declare
account kandimat_data_privat.person_account;
declare person kandimat_data.person;
begin
select a.*
into account
from kandimat_data_privat.person_account as a
where a.email = $1;
select p.*
into person
from kandimat_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')))::kandimat_data.jwt_token;
else
return null;
end if;
end;
$$ language plpgsql strict
security definer;
grant execute on function kandimat_data.authenticate(text, text) to kandimat_anonymous, kandimat_person;
-- Change role: Changes role for a given user. Only editors are allowed to use it.
drop function if exists kandimat_data.change_role;
create function kandimat_data.change_role(
person_row_id integer,
new_role kandimat_data.role
)
returns kandimat_data.person as
$$
declare
person kandimat_data.person;
begin
update kandimat_data.person
set role = new_role
where kandimat_data.person.row_id = $1
returning * into person;
return person;
end;
$$ language plpgsql strict security definer;
grant execute on function kandimat_data.change_role(integer, kandimat_data.role) to kandimat_editor;