114 lines
3.3 KiB
PL/PgSQL
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;
|