-- Deploy camper:login to pg
-- requires: roles
-- requires: schema_auth
-- requires: schema_camper
-- requires: extension_pgcrypto
-- requires: email
-- requires: user
-- requires: login_attempt
-- requires: build_cookie

begin;

set search_path to camper, auth;

create or replace function login(email email, password text, ip_address inet default null) returns text as
$$
declare
	user_cookie text;
begin
	if not exists (select *
		       from "user"
		       where "user".email = login.email
		         and "user".password = crypt(login.password, "user".password)) then
		insert into login_attempt (user_name, ip_address, success)
		values (login.email, login.ip_address, false);
		return '';
	end if;

	select cookie
	into user_cookie
	from "user"
	where "user".email = login.email
	  and cookie_expires_at > current_timestamp
	  and length(cookie) > 30;

	if user_cookie is null then
		select encode(gen_random_bytes(25), 'hex') into user_cookie;
	end if;

	update "user"
	set cookie = user_cookie
	  , cookie_expires_at = current_timestamp + interval '1 year'
	where "user".email = login.email;

	insert into login_attempt (user_name, ip_address, success)
	values (login.email, login.ip_address, true);

	return build_cookie(email, user_cookie);
end;
$$
language plpgsql
security definer
set search_path = auth, camper, pg_temp;

comment on function login(email, text, inet) is
'Tries to logs a user in, recording the attempt, and returns the cookie to send back to the user if the authentication was successfull.';

revoke execute on function login(email, text, inet) from public;
grant execute on function login(email, text, inet) to guest;

commit;
