Implement login cookie, its verification, and logout
At first i thought that i would need to implement sessions, the ones
that keep small files onto the disk, to know which user is talking to
the server, but then i realized that, for now at least, i only need a
very large number, plus the email address, to be used as a lookup, and
that can be stored in the user table, in a separate schema.
Had to change login to avoid raising exceptions when login failed
because i now keep a record of login attemps, and functions are always
run in a single transaction, thus the exception would prevent me to
insert into login_attempt. Even if i use a separate procedure, i could
not keep the records.
I did not want to add a parameter to the logout function because i was
afraid that it could be called from separate users. I do not know
whether it is possible with the current approach, since the settings
variable is also set by the same applications; time will tell.
2023-01-17 19:48:50 +00:00
|
|
|
-- Test logout
|
|
|
|
set client_min_messages to warning;
|
|
|
|
create extension if not exists pgtap;
|
|
|
|
reset client_min_messages;
|
|
|
|
|
|
|
|
begin;
|
|
|
|
|
|
|
|
select plan(15);
|
|
|
|
|
|
|
|
set search_path to auth, numerus, public;
|
|
|
|
|
2023-01-18 13:13:58 +00:00
|
|
|
select has_function('numerus', 'logout', array []::name[]);
|
|
|
|
select function_lang_is('numerus', 'logout', array []::name[], 'sql');
|
|
|
|
select function_returns('numerus', 'logout', array []::name[], 'void');
|
|
|
|
select is_definer('numerus', 'logout', array []::name[]);
|
|
|
|
select volatility_is('numerus', 'logout', array []::name[], 'volatile');
|
|
|
|
select function_privs_are('numerus', 'logout', array []::name[], 'guest', array []::text[]);
|
|
|
|
select function_privs_are('numerus', 'logout', array []::name[], 'invoicer', array ['EXECUTE']);
|
|
|
|
select function_privs_are('numerus', 'logout', array []::name[], 'admin', array ['EXECUTE']);
|
|
|
|
select function_privs_are('numerus', 'logout', array []::name[], 'authenticator', array []::text[]);
|
Implement login cookie, its verification, and logout
At first i thought that i would need to implement sessions, the ones
that keep small files onto the disk, to know which user is talking to
the server, but then i realized that, for now at least, i only need a
very large number, plus the email address, to be used as a lookup, and
that can be stored in the user table, in a separate schema.
Had to change login to avoid raising exceptions when login failed
because i now keep a record of login attemps, and functions are always
run in a single transaction, thus the exception would prevent me to
insert into login_attempt. Even if i use a separate procedure, i could
not keep the records.
I did not want to add a parameter to the logout function because i was
afraid that it could be called from separate users. I do not know
whether it is possible with the current approach, since the settings
variable is also set by the same applications; time will tell.
2023-01-17 19:48:50 +00:00
|
|
|
|
|
|
|
set client_min_messages to warning;
|
|
|
|
truncate auth."user" cascade;
|
|
|
|
reset client_min_messages;
|
|
|
|
|
Add a function to set request settings and the role
I did not like the idea that it was the Go server who should set values
such as request.user or set the role, because this is mostly something
that only the database wants for itself, such as when calling logout. I
am also planning to use these setings for row security with the user’s
id, that the Go application has no need for, but with the current
approach i would need to return it from check_cookie so that it can
return it back to the database when acquiring the connection.
I would have used the same function to set the settings and the role,
but security definer functions—obviously in retrospect—can not set the
role, because then could switch to any role of the user that defined the
function, not the roles they are member of. Thus, a new function.
I did not want to do that every time i needed the database connection
within the same request, because it would perform the same operations
each time—it is the same cookie, afterall—, so new connections are
request scoped and passed along in the context.
2023-01-19 12:07:32 +00:00
|
|
|
insert into auth."user" (user_id, email, name, password, role, cookie, cookie_expires_at)
|
|
|
|
values (1, 'info@tandem.blog', 'Tandem', 'test', 'invoicer', '8c23d4a8d777775f8fc507676a0d99d3dfa54b03b1b257c838', current_timestamp + interval '1 day')
|
|
|
|
, (12, 'admin@tandem.blog', 'Admin', 'test', 'admin', '0169e5f668eec1e6749fd25388b057997358efa8dfd697961a', current_timestamp + interval '2 day')
|
Implement login cookie, its verification, and logout
At first i thought that i would need to implement sessions, the ones
that keep small files onto the disk, to know which user is talking to
the server, but then i realized that, for now at least, i only need a
very large number, plus the email address, to be used as a lookup, and
that can be stored in the user table, in a separate schema.
Had to change login to avoid raising exceptions when login failed
because i now keep a record of login attemps, and functions are always
run in a single transaction, thus the exception would prevent me to
insert into login_attempt. Even if i use a separate procedure, i could
not keep the records.
I did not want to add a parameter to the logout function because i was
afraid that it could be called from separate users. I do not know
whether it is possible with the current approach, since the settings
variable is also set by the same applications; time will tell.
2023-01-17 19:48:50 +00:00
|
|
|
;
|
|
|
|
|
|
|
|
prepare user_cookies as
|
|
|
|
select cookie, cookie_expires_at from "user" order by user_id
|
|
|
|
;
|
|
|
|
|
2023-01-23 00:18:05 +00:00
|
|
|
select set_config('request.user.cookie', '', false);
|
Implement login cookie, its verification, and logout
At first i thought that i would need to implement sessions, the ones
that keep small files onto the disk, to know which user is talking to
the server, but then i realized that, for now at least, i only need a
very large number, plus the email address, to be used as a lookup, and
that can be stored in the user table, in a separate schema.
Had to change login to avoid raising exceptions when login failed
because i now keep a record of login attemps, and functions are always
run in a single transaction, thus the exception would prevent me to
insert into login_attempt. Even if i use a separate procedure, i could
not keep the records.
I did not want to add a parameter to the logout function because i was
afraid that it could be called from separate users. I do not know
whether it is possible with the current approach, since the settings
variable is also set by the same applications; time will tell.
2023-01-17 19:48:50 +00:00
|
|
|
select lives_ok( $$ select * from logout() $$, 'Can logout “nobody”' );
|
|
|
|
|
|
|
|
select results_eq(
|
|
|
|
'user_cookies',
|
|
|
|
$$ values ('8c23d4a8d777775f8fc507676a0d99d3dfa54b03b1b257c838', current_timestamp + interval '1 day')
|
|
|
|
, ('0169e5f668eec1e6749fd25388b057997358efa8dfd697961a', current_timestamp + interval '2 day')
|
|
|
|
$$,
|
|
|
|
'Nothing changed'
|
|
|
|
);
|
|
|
|
|
2023-01-23 00:18:05 +00:00
|
|
|
select set_config('request.user.cookie', '8c23d4a8d777775f8fc507676a0d99d3dfa54b03b1b257c838', false);
|
Implement login cookie, its verification, and logout
At first i thought that i would need to implement sessions, the ones
that keep small files onto the disk, to know which user is talking to
the server, but then i realized that, for now at least, i only need a
very large number, plus the email address, to be used as a lookup, and
that can be stored in the user table, in a separate schema.
Had to change login to avoid raising exceptions when login failed
because i now keep a record of login attemps, and functions are always
run in a single transaction, thus the exception would prevent me to
insert into login_attempt. Even if i use a separate procedure, i could
not keep the records.
I did not want to add a parameter to the logout function because i was
afraid that it could be called from separate users. I do not know
whether it is possible with the current approach, since the settings
variable is also set by the same applications; time will tell.
2023-01-17 19:48:50 +00:00
|
|
|
select lives_ok( $$ select * from logout() $$, 'Can logout the first user' );
|
|
|
|
|
|
|
|
select results_eq(
|
|
|
|
'user_cookies',
|
|
|
|
$$ values ('', '-infinity'::timestamptz)
|
|
|
|
, ('0169e5f668eec1e6749fd25388b057997358efa8dfd697961a'::text, current_timestamp + interval '2 day')
|
|
|
|
$$,
|
|
|
|
'The first user logged out'
|
|
|
|
);
|
|
|
|
|
2023-01-23 00:18:05 +00:00
|
|
|
select set_config('request.user.cookie', '0169e5f668eec1e6749fd25388b057997358efa8dfd697961a', false);
|
Implement login cookie, its verification, and logout
At first i thought that i would need to implement sessions, the ones
that keep small files onto the disk, to know which user is talking to
the server, but then i realized that, for now at least, i only need a
very large number, plus the email address, to be used as a lookup, and
that can be stored in the user table, in a separate schema.
Had to change login to avoid raising exceptions when login failed
because i now keep a record of login attemps, and functions are always
run in a single transaction, thus the exception would prevent me to
insert into login_attempt. Even if i use a separate procedure, i could
not keep the records.
I did not want to add a parameter to the logout function because i was
afraid that it could be called from separate users. I do not know
whether it is possible with the current approach, since the settings
variable is also set by the same applications; time will tell.
2023-01-17 19:48:50 +00:00
|
|
|
select lives_ok( $$ select * from logout() $$, 'Can logout the second user' );
|
|
|
|
|
|
|
|
select results_eq(
|
|
|
|
'user_cookies',
|
|
|
|
$$ values ('', '-infinity'::timestamptz)
|
|
|
|
, ('', '-infinity'::timestamptz)
|
|
|
|
$$,
|
|
|
|
'The second user logged out'
|
|
|
|
);
|
|
|
|
|
|
|
|
select *
|
|
|
|
from finish();
|
|
|
|
|
|
|
|
rollback;
|