kandimat/backend/sql/04_setup_authentication.sql
Christoph Lienhard 4a2ba8406d
#20 Return person on change role mutation
Return the whole person object on calling the changeRole mutation.
This enables the apollo cache in the frontend to automatically
update the role of the given user.

Furthermore, made all create function statements idempotent by
deleting them first if existing.
2021-05-28 23:41:30 +02:00

114 lines
3.3 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 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 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;