-- Test login
set client_min_messages to warning;
create extension if not exists pgtap;
reset client_min_messages;

begin;

select plan(20);

set search_path to auth, numerus, public;

select has_function('numerus', 'login', array ['email', 'text', 'inet']);
select function_lang_is('numerus', 'login', array ['email', 'text', 'inet'], 'plpgsql');
select function_returns('numerus', 'login', array ['email', 'text', 'inet'], 'text');
select is_definer('numerus', 'login', array ['email', 'text', 'inet']);
select volatility_is('numerus', 'login', array ['email', 'text', 'inet'], 'volatile');
select function_privs_are('numerus', 'login', array ['email', 'text', 'inet'], 'guest', array ['EXECUTE']);
select function_privs_are('numerus', 'login', array ['email', 'text', 'inet'], 'invoicer', array []::text[]);
select function_privs_are('numerus', 'login', array ['email', 'text', 'inet'], 'admin', array []::text[]);
select function_privs_are('numerus', 'login', array ['email', 'text', 'inet'], 'authenticator', array []::text[]);

set client_min_messages to warning;
truncate auth."user" cascade;
truncate auth.login_attempt cascade;
reset client_min_messages;

insert into auth."user" (email, name, password, role)
values ('info@tandem.blog', 'Tandem', 'test', 'invoicer');

create temp table _login_test (result_num integer, cookie text not null);

select lives_ok (
	$$ insert into _login_test select 1, split_part(login('info@tandem.blog', 'test', '::1'::inet), '/', 1) $$,
	'Should login with a correct user and password'
);

select isnt_empty (
	$$ select cookie from _login_test join "user" using (cookie) where email = 'info@tandem.blog' $$,
	'Should have returned the cookie that wrote to the user relation.'
);

select results_eq (
	$$ select cookie_expires_at > current_timestamp from "user" where email = 'info@tandem.blog' $$,
	$$ values (true) $$,
	'Should have set an expiry date in the future.'
);

select isnt_empty (
	$$ select cookie from _login_test where cookie in (select split_part(login('info@tandem.blog', 'test', '192.168.0.1'::inet), '/', 1)) $$,
	'Should return the same cookie if not expired yet.'
);

update "user" set cookie_expires_at = current_timestamp - interval '1 hour' where email = 'info@tandem.blog';

select lives_ok (
	$$ insert into _login_test select 2, split_part(login('info@tandem.blog', 'test', '::1'::inet), '/', 1) $$,
	'Should login with a correct user and password even with an expired cookie'
);


select results_eq(
	$$ select count(distinct cookie)::integer from _login_test $$,
	$$ values (2) $$,
	'Should have returned a new cookie'
);

select isnt_empty (
	$$ select cookie from _login_test join "user" using (cookie) where email = 'info@tandem.blog' and result_num = 2 $$,
	'Should have updated the user’s cookie.'
);

select results_eq(
	$$ select cookie_expires_at > current_timestamp from "user" where email = 'info@tandem.blog' $$,
	$$ values(true) $$,
	'Should have set an expiry date in the future, again.'
);

select is(
	login('info@tandem.blog'::email, 'mah password', '127.0.0.1'::inet),
	''::text,
	'Should not find any role with an invalid password'
);

select is(
	login('nope@tandem.blog'::email, 'test'),
	''::text,
	'Should not find any role with an invalid email'
);

select results_eq(
	'select user_name, ip_address, success, attempted_at from login_attempt order by attempt_id',
	$$ values ('info@tandem.blog', '::1'::inet, true, current_timestamp)
	        , ('info@tandem.blog', '192.168.0.1'::inet, true, current_timestamp)
		, ('info@tandem.blog', '::1'::inet, true, current_timestamp)
		, ('info@tandem.blog', '127.0.0.1'::inet, false, current_timestamp)
		, ('nope@tandem.blog', null, false, current_timestamp)
	$$,
	'Should have recorded all login attempts.'
);


select *
from finish();

rollback;
