Use user’ß email for auth funcs and return cookie on email change
This is for security, just in case two users have the same cookie, althought it is unlikely, but nevertheless less guessable. I also need to refresh the cookie when the user changes their email address, because it is liked toghether. It does mean that it will logout from everywhere else, but i can not do anything about that.
This commit is contained in:
parent
f9e22c0789
commit
5eeaab2013
|
@ -0,0 +1,25 @@
|
|||
-- Deploy numerus:build_cookie to pg
|
||||
-- requires: schema_numerus
|
||||
-- requires: current_user_email
|
||||
-- requires: current_user_cookie
|
||||
|
||||
begin;
|
||||
|
||||
set search_path to numerus, public;
|
||||
|
||||
create or replace function build_cookie(user_email email default null, user_cookie text default null) returns text as
|
||||
$$
|
||||
select coalesce(user_cookie, current_user_cookie()) || '/' || coalesce(user_email, current_user_email());
|
||||
$$
|
||||
language sql
|
||||
stable;
|
||||
|
||||
revoke execute on function build_cookie(email, text) from public;
|
||||
grant execute on function build_cookie(email, text) to guest;
|
||||
grant execute on function build_cookie(email, text) to invoicer;
|
||||
grant execute on function build_cookie(email, text) to admin;
|
||||
|
||||
comment on function build_cookie(email, text) is
|
||||
'Build the cookie to send to the user’s browser, either for the given values or for the current user.';
|
||||
|
||||
commit;
|
|
@ -28,7 +28,6 @@ begin
|
|||
user_cookie := '';
|
||||
user_role := 'guest'::name;
|
||||
end if;
|
||||
perform set_config('request.user.id', uid, false);
|
||||
perform set_config('request.user.email', user_email, false);
|
||||
perform set_config('request.user.cookie', user_cookie, false);
|
||||
return user_role;
|
||||
|
@ -40,7 +39,7 @@ stable
|
|||
set search_path = auth, numerus, pg_temp;
|
||||
|
||||
comment on function check_cookie(text) is
|
||||
'Checks whether a given cookie is for a valid users, returning its email and role';
|
||||
'Checks whether a given cookie is for a valid users, returning their role, and setting current_user_email and current_user_cookie';
|
||||
|
||||
revoke execute on function check_cookie(text) from public;
|
||||
grant execute on function check_cookie(text) to authenticator;
|
||||
|
|
|
@ -1,23 +0,0 @@
|
|||
-- Deploy numerus:current_app_user to pg
|
||||
-- requires: schema_numerus
|
||||
|
||||
begin;
|
||||
|
||||
set search_path to numerus;
|
||||
|
||||
create or replace function current_app_user() returns text as
|
||||
$$
|
||||
select current_setting('request.user.cookie', true);
|
||||
$$
|
||||
language sql
|
||||
stable;
|
||||
|
||||
comment on function current_app_user() is
|
||||
'Returns the ID of the current Numerus user';
|
||||
|
||||
revoke execute on function current_app_user() from public;
|
||||
grant execute on function current_app_user() to guest;
|
||||
grant execute on function current_app_user() to invoicer;
|
||||
grant execute on function current_app_user() to admin;
|
||||
|
||||
commit;
|
|
@ -0,0 +1,23 @@
|
|||
-- Deploy numerus:current_user_cookie to pg
|
||||
-- requires: schema_numerus
|
||||
|
||||
begin;
|
||||
|
||||
set search_path to numerus;
|
||||
|
||||
create or replace function current_user_cookie() returns text as
|
||||
$$
|
||||
select current_setting('request.user.cookie', true);
|
||||
$$
|
||||
language sql
|
||||
stable;
|
||||
|
||||
comment on function current_user_cookie() is
|
||||
'Returns the cookie of the current Numerus user';
|
||||
|
||||
revoke execute on function current_user_cookie() from public;
|
||||
grant execute on function current_user_cookie() to guest;
|
||||
grant execute on function current_user_cookie() to invoicer;
|
||||
grant execute on function current_user_cookie() to admin;
|
||||
|
||||
commit;
|
|
@ -0,0 +1,23 @@
|
|||
-- Deploy numerus:current_user_email to pg
|
||||
-- requires: schema_numerus
|
||||
|
||||
begin;
|
||||
|
||||
set search_path to numerus;
|
||||
|
||||
create or replace function current_user_email() returns text as
|
||||
$$
|
||||
select current_setting('request.user.email', true);
|
||||
$$
|
||||
language sql
|
||||
stable;
|
||||
|
||||
comment on function current_user_email() is
|
||||
'Returns the email of the current Numerus user';
|
||||
|
||||
revoke execute on function current_user_email() from public;
|
||||
grant execute on function current_user_email() to guest;
|
||||
grant execute on function current_user_email() to invoicer;
|
||||
grant execute on function current_user_email() to admin;
|
||||
|
||||
commit;
|
|
@ -6,6 +6,7 @@
|
|||
-- requires: email
|
||||
-- requires: user
|
||||
-- requires: login_attempt
|
||||
-- requires: build_cookie
|
||||
|
||||
begin;
|
||||
|
||||
|
@ -48,7 +49,7 @@ begin
|
|||
(user_name, ip_address, success)
|
||||
values (login.email, login.ip_address, true);
|
||||
|
||||
return user_cookie || '/' || email;
|
||||
return build_cookie(email, user_cookie);
|
||||
end;
|
||||
$$
|
||||
language plpgsql
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
-- Deploy numerus:logout to pg
|
||||
-- requires: schema_auth
|
||||
-- requires: user
|
||||
-- requires: current_app_user
|
||||
-- requires: current_user_cookie
|
||||
-- requires: current_user_email
|
||||
|
||||
begin;
|
||||
|
||||
|
@ -12,7 +13,8 @@ $$
|
|||
update "user"
|
||||
set cookie = default
|
||||
, cookie_expires_at = default
|
||||
where cookie = current_app_user()
|
||||
where email = current_user_email()
|
||||
and cookie = current_user_cookie()
|
||||
and cookie_expires_at > current_timestamp
|
||||
and length(cookie) > 30
|
||||
$$
|
||||
|
@ -21,7 +23,7 @@ security definer
|
|||
set search_path to auth, numerus, pg_temp;
|
||||
|
||||
comment on function logout() is
|
||||
'Removes the cookie and its expiry data from the current user, set as request.user setting';
|
||||
'Removes the cookie and its expiry data from the current user, as returned by current_user_email and current_user_cookie';
|
||||
|
||||
revoke execute on function logout() from public;
|
||||
grant execute on function logout() to invoicer;
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
-- Deploy numerus:user_profile to pg
|
||||
-- requires: schema_numerus
|
||||
-- requires: user
|
||||
-- requires: current_app_user
|
||||
-- requires: current_user_cookie
|
||||
-- requires: current_user_email
|
||||
|
||||
begin;
|
||||
|
||||
|
@ -16,7 +17,8 @@ select user_id
|
|||
, role
|
||||
, lang_tag
|
||||
from auth."user"
|
||||
where cookie = current_app_user()
|
||||
where email = current_user_email()
|
||||
and cookie = current_user_cookie()
|
||||
and cookie_expires_at > current_timestamp
|
||||
and length(cookie) > 30
|
||||
union all
|
||||
|
@ -28,23 +30,40 @@ select 0
|
|||
where not exists (
|
||||
select 1
|
||||
from auth."user"
|
||||
where cookie = current_app_user()
|
||||
where email = current_user_email()
|
||||
and cookie = current_user_cookie()
|
||||
and cookie_expires_at > current_timestamp
|
||||
and length(cookie) > 30
|
||||
);
|
||||
|
||||
create rule update_user_profile as on update to user_profile
|
||||
do instead update auth."user"
|
||||
set email = new.email
|
||||
, name = new.name
|
||||
, lang_tag = new.lang_tag
|
||||
where cookie = current_app_user()
|
||||
and cookie_expires_at > current_timestamp
|
||||
and length(cookie) > 30
|
||||
;
|
||||
|
||||
grant select on table user_profile to guest;
|
||||
grant select, update(email, name, lang_tag) on table user_profile to invoicer;
|
||||
grant select, update(email, name, lang_tag) on table user_profile to admin;
|
||||
|
||||
create or replace function update_user_profile() returns trigger as
|
||||
$$
|
||||
begin
|
||||
update auth."user"
|
||||
set email = new.email
|
||||
, name = new.name
|
||||
, lang_tag = new.lang_tag
|
||||
where email = current_user_email()
|
||||
and cookie = current_user_cookie()
|
||||
and cookie_expires_at > current_timestamp
|
||||
and length(cookie) > 30
|
||||
;
|
||||
|
||||
perform set_config('request.user.email', new.email, false);
|
||||
|
||||
return new;
|
||||
end;
|
||||
$$
|
||||
language plpgsql
|
||||
security definer
|
||||
set search_path to auth, numerus, pg_temp;
|
||||
|
||||
create trigger update_user_profile
|
||||
instead of update on user_profile
|
||||
for each row execute procedure update_user_profile();
|
||||
|
||||
commit;
|
||||
|
|
|
@ -46,7 +46,7 @@ func LoginHandler() http.Handler {
|
|||
conn := getConn(r)
|
||||
cookie := conn.MustGetText(r.Context(), "", "select login($1, $2, $3)", page.Email, page.Password, remoteAddr(r))
|
||||
if cookie != "" {
|
||||
http.SetCookie(w, createSessionCookie(cookie, 8766*24*time.Hour))
|
||||
setSessionCookie(w, cookie)
|
||||
http.Redirect(w, r, "/", http.StatusSeeOther)
|
||||
return
|
||||
}
|
||||
|
@ -79,6 +79,10 @@ func remoteAddr(r *http.Request) string {
|
|||
return address
|
||||
}
|
||||
|
||||
func setSessionCookie(w http.ResponseWriter, cookie string) {
|
||||
http.SetCookie(w, createSessionCookie(cookie, 8766*24*time.Hour))
|
||||
}
|
||||
|
||||
func createSessionCookie(value string, duration time.Duration) *http.Cookie {
|
||||
return &http.Cookie{
|
||||
Name: sessionCookie,
|
||||
|
|
|
@ -32,7 +32,7 @@ func ProfileHandler() http.Handler {
|
|||
page := ProfilePage{
|
||||
Title: pgettext("title", "User Settings", locale),
|
||||
Email: user.Email,
|
||||
Languages: mustGetLanguageOptions(r.Context(), conn),
|
||||
Language: user.Language.String(),
|
||||
}
|
||||
if r.Method == "POST" {
|
||||
r.ParseForm()
|
||||
|
@ -41,11 +41,13 @@ func ProfileHandler() http.Handler {
|
|||
page.Password = r.FormValue("password")
|
||||
page.PasswordConfirm = r.FormValue("password_confirm")
|
||||
page.Language = r.FormValue("language")
|
||||
conn.MustExec(r.Context(), "update user_profile set name = $1, email = $2, lang_tag = $3", page.Name, page.Email, page.Language)
|
||||
http.Redirect(w, r, "/profile", http.StatusSeeOther);
|
||||
return;
|
||||
cookie := conn.MustGetText(r.Context(), "", "update user_profile set name = $1, email = $2, lang_tag = $3 returning build_cookie()", page.Name, page.Email, page.Language)
|
||||
setSessionCookie(w, cookie)
|
||||
http.Redirect(w, r, "/profile", http.StatusSeeOther)
|
||||
return
|
||||
} else {
|
||||
if err := conn.QueryRow(r.Context(), "select name, lang_tag from user_profile").Scan(&page.Name, &page.Language); err != nil {
|
||||
page.Languages = mustGetLanguageOptions(r.Context(), conn)
|
||||
if err := conn.QueryRow(r.Context(), "select name from user_profile").Scan(&page.Name); err != nil {
|
||||
panic(nil)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
-- Revert numerus:build_cookie from pg
|
||||
|
||||
begin;
|
||||
|
||||
drop function if exists numerus.build_cookie(numerus.email, text);
|
||||
|
||||
commit;
|
|
@ -1,7 +0,0 @@
|
|||
-- Revert numerus:current_app_user from pg
|
||||
|
||||
begin;
|
||||
|
||||
drop function if exists numerus.current_app_user();
|
||||
|
||||
commit;
|
|
@ -0,0 +1,7 @@
|
|||
-- Revert numerus:current_user_cookie from pg
|
||||
|
||||
begin;
|
||||
|
||||
drop function if exists numerus.current_user_cookie();
|
||||
|
||||
commit;
|
|
@ -0,0 +1,7 @@
|
|||
-- Revert numerus:current_user_email from pg
|
||||
|
||||
begin;
|
||||
|
||||
drop function if exists numerus.current_user_email();
|
||||
|
||||
commit;
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
begin;
|
||||
|
||||
drop trigger if exists update_user_profile on numerus.user_profile;
|
||||
drop function if exists numerus.update_user_profile();
|
||||
drop view if exists numerus.user_profile;
|
||||
|
||||
commit;
|
||||
|
|
10
sqitch.plan
10
sqitch.plan
|
@ -15,9 +15,11 @@ extension_pgcrypto [schema_auth] 2023-01-13T00:11:50Z jordi fita mas <jordi@tand
|
|||
encrypt_password [schema_auth user extension_pgcrypto] 2023-01-13T00:14:30Z jordi fita mas <jordi@tandem.blog> # Add trigger to encrypt user’s password
|
||||
login_attempt [schema_auth] 2023-01-17T14:05:49Z jordi fita mas <jordi@tandem.blog> # Add table to log login attempts
|
||||
login [roles schema_numerus schema_auth extension_pgcrypto email user login_attempt] 2023-01-13T00:32:32Z jordi fita mas <jordi@tandem.blog> # Add function to login
|
||||
check_cookie [schema_public user] 2023-01-17T17:48:49Z jordi fita mas <jordi@tandem.blog> # Add function to check if a user cookie is valid
|
||||
current_app_user [schema_numerus] 2023-01-21T20:16:28Z jordi fita mas <jordi@tandem.blog> # Add function to get the ID of the current Numerus’ user
|
||||
logout [schema_auth current_app_user user] 2023-01-17T19:10:21Z jordi fita mas <jordi@tandem.blog> # Add function to logout
|
||||
current_user_cookie [schema_numerus] 2023-01-21T20:16:28Z jordi fita mas <jordi@tandem.blog> # Add function to get the cookie of the current Numerus’ user
|
||||
current_user_email [schema_numerus] 2023-01-23T19:11:53Z jordi fita mas <jordi@tandem.blog> # Add function to get the email of the current Numerus’ user
|
||||
build_cookie [schema_numerus current_user_email current_user_cookie] 2023-01-23T19:46:13Z jordi fita mas <jordi@tandem.blog> # Add function to build the cookie for the current user
|
||||
check_cookie [schema_public user build_cookie] 2023-01-17T17:48:49Z jordi fita mas <jordi@tandem.blog> # Add function to check if a user cookie is valid
|
||||
logout [schema_auth current_user_email current_user_cookie user] 2023-01-17T19:10:21Z jordi fita mas <jordi@tandem.blog> # Add function to logout
|
||||
set_cookie [schema_public check_cookie] 2023-01-19T11:00:22Z jordi fita mas <jordi@tandem.blog> # Add function to set the role based on the cookie
|
||||
available_languages [schema_numerus language] 2023-01-21T21:11:08Z jordi fita mas <jordi@tandem.blog> # Add the initial available languages
|
||||
user_profile [schema_numerus user current_app_user] 2023-01-21T23:18:20Z jordi fita mas <jordi@tandem.blog> # Add view for user profile
|
||||
user_profile [schema_numerus user current_user_email current_user_cookie] 2023-01-21T23:18:20Z jordi fita mas <jordi@tandem.blog> # Add view for user profile
|
||||
|
|
|
@ -0,0 +1,70 @@
|
|||
-- Test build_cookie
|
||||
set client_min_messages to warning;
|
||||
create extension if not exists pgtap;
|
||||
reset client_min_messages;
|
||||
|
||||
begin;
|
||||
|
||||
select plan(13);
|
||||
|
||||
set search_path to numerus, auth, public;
|
||||
|
||||
select has_function('numerus', 'build_cookie', array ['email', 'text']);
|
||||
select function_lang_is('numerus', 'build_cookie', array ['email', 'text'], 'sql');
|
||||
select function_returns('numerus', 'build_cookie', array ['email', 'text'], 'text');
|
||||
select isnt_definer('numerus', 'build_cookie', array ['email', 'text']);
|
||||
select volatility_is('numerus', 'build_cookie', array ['email', 'text'], 'stable');
|
||||
select function_privs_are('numerus', 'build_cookie', array ['email', 'text'], 'guest', array ['EXECUTE']);
|
||||
select function_privs_are('numerus', 'build_cookie', array ['email', 'text'], 'invoicer', array ['EXECUTE']);
|
||||
select function_privs_are('numerus', 'build_cookie', array ['email', 'text'], 'admin', array ['EXECUTE']);
|
||||
select function_privs_are('numerus', 'build_cookie', array ['email', 'text'], 'authenticator', array []::text[]);
|
||||
|
||||
set client_min_messages to warning;
|
||||
truncate auth."user" cascade;
|
||||
reset client_min_messages;
|
||||
|
||||
insert into auth."user" (user_id, email, name, password, role, cookie, cookie_expires_at)
|
||||
values (1, 'demo@tandem.blog', 'Demo', 'test', 'invoicer', '44facbb30d8a419dfd4bfbc44a4b5539d4970148dfc84bed0e', current_timestamp + interval '1 month')
|
||||
, (9, 'admin@tandem.blog', 'Demo', 'test', 'admin', '12af4c88b528c2ad4222e3740496ecbc58e76e26f087657524', current_timestamp + interval '1 month')
|
||||
;
|
||||
|
||||
select is(
|
||||
build_cookie('test@example.com'::email, '123abc'),
|
||||
'123abc/test@example.com',
|
||||
'Should build the cookie with the given user and cookie value'
|
||||
);
|
||||
|
||||
select set_cookie('44facbb30d8a419dfd4bfbc44a4b5539d4970148dfc84bed0e/demo@tandem.blog');
|
||||
|
||||
select is(
|
||||
build_cookie(),
|
||||
'44facbb30d8a419dfd4bfbc44a4b5539d4970148dfc84bed0e/demo@tandem.blog',
|
||||
'Should build the cookie for the logged in user'
|
||||
);
|
||||
|
||||
reset role;
|
||||
|
||||
select set_cookie('12af4c88b528c2ad4222e3740496ecbc58e76e26f087657524/admin@tandem.blog');
|
||||
|
||||
select is(
|
||||
build_cookie(),
|
||||
'12af4c88b528c2ad4222e3740496ecbc58e76e26f087657524/admin@tandem.blog',
|
||||
'Should build the cookie for the other logged in user'
|
||||
);
|
||||
|
||||
reset role;
|
||||
|
||||
select set_cookie('ashtasth');
|
||||
|
||||
select is(
|
||||
build_cookie(),
|
||||
'/',
|
||||
'Should build the cookie for the guest user'
|
||||
);
|
||||
|
||||
reset role;
|
||||
|
||||
select *
|
||||
from finish();
|
||||
|
||||
rollback;
|
|
@ -29,10 +29,7 @@ values (1, 'demo@tandem.blog', 'Demo', 'test', 'invoicer', '44facbb30d8a419dfd4b
|
|||
;
|
||||
|
||||
prepare user_info as
|
||||
select current_setting('request.user.id', true)::integer
|
||||
, current_setting('request.user.email', true)
|
||||
, current_setting('request.user.cookie', true)
|
||||
;
|
||||
select current_user_email(), current_user_cookie();
|
||||
|
||||
select is (
|
||||
check_cookie('44facbb30d8a419dfd4bfbc44a4b5539d4970148dfc84bed0e/demo@tandem.blog'),
|
||||
|
@ -42,7 +39,7 @@ select is (
|
|||
|
||||
select results_eq (
|
||||
'user_info',
|
||||
$$ values (1, 'demo@tandem.blog', '44facbb30d8a419dfd4bfbc44a4b5539d4970148dfc84bed0e') $$,
|
||||
$$ values ('demo@tandem.blog', '44facbb30d8a419dfd4bfbc44a4b5539d4970148dfc84bed0e') $$,
|
||||
'Should have updated the settings with the user info'
|
||||
);
|
||||
|
||||
|
@ -54,7 +51,7 @@ select is (
|
|||
|
||||
select results_eq (
|
||||
'user_info',
|
||||
$$ values (9, 'admin@tandem.blog', '12af4c88b528c2ad4222e3740496ecbc58e76e26f087657524') $$,
|
||||
$$ values ('admin@tandem.blog', '12af4c88b528c2ad4222e3740496ecbc58e76e26f087657524') $$,
|
||||
'Should have updated the settings with the other user info'
|
||||
);
|
||||
|
||||
|
@ -66,7 +63,7 @@ select is (
|
|||
|
||||
select results_eq (
|
||||
'user_info',
|
||||
$$ values (0, '', '') $$,
|
||||
$$ values ('', '') $$,
|
||||
'Should have updated the settings with a guest user'
|
||||
);
|
||||
|
||||
|
@ -78,7 +75,7 @@ select is (
|
|||
|
||||
select results_eq (
|
||||
'user_info',
|
||||
$$ values (0, '', '') $$,
|
||||
$$ values ('', '') $$,
|
||||
'Should have left the settings with a guest user'
|
||||
);
|
||||
|
||||
|
@ -92,7 +89,7 @@ select is (
|
|||
|
||||
select results_eq (
|
||||
'user_info',
|
||||
$$ values (0, '', '') $$,
|
||||
$$ values ('', '') $$,
|
||||
'Should have left the settings with a guest user'
|
||||
);
|
||||
|
||||
|
@ -104,7 +101,7 @@ select is (
|
|||
|
||||
select results_eq (
|
||||
'user_info',
|
||||
$$ values (0, '', '') $$,
|
||||
$$ values ('', '') $$,
|
||||
'Should have left the settings with a guest user'
|
||||
);
|
||||
|
||||
|
|
|
@ -1,62 +0,0 @@
|
|||
-- Test current_app_user
|
||||
set client_min_messages to warning;
|
||||
create extension if not exists pgtap;
|
||||
reset client_min_messages;
|
||||
|
||||
begin;
|
||||
|
||||
set search_path to numerus, auth, public;
|
||||
|
||||
select plan(15);
|
||||
|
||||
select has_function('numerus', 'current_app_user', array []::name[]);
|
||||
select function_lang_is('numerus', 'current_app_user', array []::name[], 'sql');
|
||||
select function_returns('numerus', 'current_app_user', array []::name[], 'text');
|
||||
select isnt_definer('numerus', 'current_app_user', array []::name[]);
|
||||
select volatility_is('numerus', 'current_app_user', array []::name[], 'stable');
|
||||
select function_privs_are('numerus', 'current_app_user', array []::name[], 'guest', array ['EXECUTE']);
|
||||
select function_privs_are('numerus', 'current_app_user', array []::name[], 'invoicer', array ['EXECUTE']);
|
||||
select function_privs_are('numerus', 'current_app_user', array []::name[], 'admin', array ['EXECUTE']);
|
||||
select function_privs_are('numerus', 'current_app_user', array []::name[], 'authenticator', array []::text []);
|
||||
|
||||
set client_min_messages to warning;
|
||||
truncate auth."user" cascade;
|
||||
reset client_min_messages;
|
||||
|
||||
insert into auth."user" (user_id, email, name, password, role, cookie, cookie_expires_at)
|
||||
values (1, 'demo@tandem.blog', 'Demo', 'test', 'invoicer', '44facbb30d8a419dfd4bfbc44a4b5539d4970148dfc84bed0e', current_timestamp + interval '1 month')
|
||||
, (5, 'admin@tandem.blog', 'Demo', 'test', 'admin', '12af4c88b528c2ad4222e3740496ecbc58e76e26f087657524', current_timestamp + interval '1 month')
|
||||
;
|
||||
|
||||
select lives_ok(
|
||||
$$ select set_cookie('44facbb30d8a419dfd4bfbc44a4b5539d4970148dfc84bed0e/demo@tandem.blog') $$,
|
||||
'Should change ok for the first user'
|
||||
);
|
||||
|
||||
select is(current_app_user(), '44facbb30d8a419dfd4bfbc44a4b5539d4970148dfc84bed0e', 'Should be running as the first user');
|
||||
|
||||
reset role;
|
||||
|
||||
|
||||
select lives_ok(
|
||||
$$ select set_cookie('12af4c88b528c2ad4222e3740496ecbc58e76e26f087657524/admin@tandem.blog') $$,
|
||||
'Should change ok for the second user'
|
||||
);
|
||||
|
||||
select is(current_app_user(), '12af4c88b528c2ad4222e3740496ecbc58e76e26f087657524', 'Should be running as the second user');
|
||||
|
||||
reset role;
|
||||
|
||||
select lives_ok(
|
||||
$$ select set_cookie('') $$,
|
||||
'Should change ok for a guest user'
|
||||
);
|
||||
|
||||
select is(current_app_user(), '', 'Should be running as the first user');
|
||||
|
||||
reset role;
|
||||
|
||||
select *
|
||||
from finish();
|
||||
|
||||
rollback;
|
|
@ -0,0 +1,62 @@
|
|||
-- Test current_user_cookie
|
||||
set client_min_messages to warning;
|
||||
create extension if not exists pgtap;
|
||||
reset client_min_messages;
|
||||
|
||||
begin;
|
||||
|
||||
set search_path to numerus, auth, public;
|
||||
|
||||
select plan(15);
|
||||
|
||||
select has_function('numerus', 'current_user_cookie', array []::name[]);
|
||||
select function_lang_is('numerus', 'current_user_cookie', array []::name[], 'sql');
|
||||
select function_returns('numerus', 'current_user_cookie', array []::name[], 'text');
|
||||
select isnt_definer('numerus', 'current_user_cookie', array []::name[]);
|
||||
select volatility_is('numerus', 'current_user_cookie', array []::name[], 'stable');
|
||||
select function_privs_are('numerus', 'current_user_cookie', array []::name[], 'guest', array ['EXECUTE']);
|
||||
select function_privs_are('numerus', 'current_user_cookie', array []::name[], 'invoicer', array ['EXECUTE']);
|
||||
select function_privs_are('numerus', 'current_user_cookie', array []::name[], 'admin', array ['EXECUTE']);
|
||||
select function_privs_are('numerus', 'current_user_cookie', array []::name[], 'authenticator', array []::text []);
|
||||
|
||||
set client_min_messages to warning;
|
||||
truncate auth."user" cascade;
|
||||
reset client_min_messages;
|
||||
|
||||
insert into auth."user" (user_id, email, name, password, role, cookie, cookie_expires_at)
|
||||
values (1, 'demo@tandem.blog', 'Demo', 'test', 'invoicer', '44facbb30d8a419dfd4bfbc44a4b5539d4970148dfc84bed0e', current_timestamp + interval '1 month')
|
||||
, (5, 'admin@tandem.blog', 'Demo', 'test', 'admin', '12af4c88b528c2ad4222e3740496ecbc58e76e26f087657524', current_timestamp + interval '1 month')
|
||||
;
|
||||
|
||||
select lives_ok(
|
||||
$$ select set_cookie('44facbb30d8a419dfd4bfbc44a4b5539d4970148dfc84bed0e/demo@tandem.blog') $$,
|
||||
'Should change ok for the first user'
|
||||
);
|
||||
|
||||
select is(current_user_cookie(), '44facbb30d8a419dfd4bfbc44a4b5539d4970148dfc84bed0e', 'Should return the cookie of the first user');
|
||||
|
||||
reset role;
|
||||
|
||||
|
||||
select lives_ok(
|
||||
$$ select set_cookie('12af4c88b528c2ad4222e3740496ecbc58e76e26f087657524/admin@tandem.blog') $$,
|
||||
'Should change ok for the second user'
|
||||
);
|
||||
|
||||
select is(current_user_cookie(), '12af4c88b528c2ad4222e3740496ecbc58e76e26f087657524', 'Should return the cookie of the second user');
|
||||
|
||||
reset role;
|
||||
|
||||
select lives_ok(
|
||||
$$ select set_cookie('') $$,
|
||||
'Should change ok for a guest user'
|
||||
);
|
||||
|
||||
select is(current_user_cookie(), '', 'Should return an empty string');
|
||||
|
||||
reset role;
|
||||
|
||||
select *
|
||||
from finish();
|
||||
|
||||
rollback;
|
|
@ -0,0 +1,63 @@
|
|||
-- Test current_user_email
|
||||
set client_min_messages to warning;
|
||||
create extension if not exists pgtap;
|
||||
reset client_min_messages;
|
||||
|
||||
begin;
|
||||
|
||||
set search_path to numerus, auth, public;
|
||||
|
||||
select plan(15);
|
||||
|
||||
select has_function('numerus', 'current_user_email', array []::name[]);
|
||||
select function_lang_is('numerus', 'current_user_email', array []::name[], 'sql');
|
||||
select function_returns('numerus', 'current_user_email', array []::name[], 'text');
|
||||
select isnt_definer('numerus', 'current_user_email', array []::name[]);
|
||||
select volatility_is('numerus', 'current_user_email', array []::name[], 'stable');
|
||||
select function_privs_are('numerus', 'current_user_email', array []::name[], 'guest', array ['EXECUTE']);
|
||||
select function_privs_are('numerus', 'current_user_email', array []::name[], 'invoicer', array ['EXECUTE']);
|
||||
select function_privs_are('numerus', 'current_user_email', array []::name[], 'admin', array ['EXECUTE']);
|
||||
select function_privs_are('numerus', 'current_user_email', array []::name[], 'authenticator', array []::text []);
|
||||
|
||||
set client_min_messages to warning;
|
||||
truncate auth."user" cascade;
|
||||
reset client_min_messages;
|
||||
|
||||
insert into auth."user" (user_id, email, name, password, role, cookie, cookie_expires_at)
|
||||
values (1, 'demo@tandem.blog', 'Demo', 'test', 'invoicer', '44facbb30d8a419dfd4bfbc44a4b5539d4970148dfc84bed0e', current_timestamp + interval '1 month')
|
||||
, (5, 'admin@tandem.blog', 'Demo', 'test', 'admin', '12af4c88b528c2ad4222e3740496ecbc58e76e26f087657524', current_timestamp + interval '1 month')
|
||||
;
|
||||
|
||||
select lives_ok(
|
||||
$$ select set_cookie('44facbb30d8a419dfd4bfbc44a4b5539d4970148dfc84bed0e/demo@tandem.blog') $$,
|
||||
'Should change ok for the first user'
|
||||
);
|
||||
|
||||
select is(current_user_email(), 'demo@tandem.blog', 'Should return the email of the first user');
|
||||
|
||||
reset role;
|
||||
|
||||
|
||||
select lives_ok(
|
||||
$$ select set_cookie('12af4c88b528c2ad4222e3740496ecbc58e76e26f087657524/admin@tandem.blog') $$,
|
||||
'Should change ok for the second user'
|
||||
);
|
||||
|
||||
select is(current_user_email(), 'admin@tandem.blog', 'Should return the email of the second user');
|
||||
|
||||
reset role;
|
||||
|
||||
select lives_ok(
|
||||
$$ select set_cookie('') $$,
|
||||
'Should change ok for a guest user'
|
||||
);
|
||||
|
||||
select is(current_user_email(), '', 'Should return an empty string');
|
||||
|
||||
reset role;
|
||||
|
||||
|
||||
select *
|
||||
from finish();
|
||||
|
||||
rollback;
|
|
@ -5,7 +5,7 @@ reset client_min_messages;
|
|||
|
||||
begin;
|
||||
|
||||
select plan(15);
|
||||
select plan(17);
|
||||
|
||||
set search_path to auth, numerus, public;
|
||||
|
||||
|
@ -33,6 +33,7 @@ select cookie, cookie_expires_at from "user" order by user_id
|
|||
;
|
||||
|
||||
select set_config('request.user.cookie', '', false);
|
||||
select set_config('request.user.email', '', false);
|
||||
select lives_ok( $$ select * from logout() $$, 'Can logout “nobody”' );
|
||||
|
||||
select results_eq(
|
||||
|
@ -40,10 +41,23 @@ select results_eq(
|
|||
$$ values ('8c23d4a8d777775f8fc507676a0d99d3dfa54b03b1b257c838', current_timestamp + interval '1 day')
|
||||
, ('0169e5f668eec1e6749fd25388b057997358efa8dfd697961a', current_timestamp + interval '2 day')
|
||||
$$,
|
||||
'Nothing changed'
|
||||
'Should have changed nothing'
|
||||
);
|
||||
|
||||
select set_config('request.user.cookie', '0169e5f668eec1e6749fd25388b057997358efa8dfd697961a', false);
|
||||
select set_config('request.user.email', 'info@tandem.blog', false);
|
||||
select lives_ok( $$ select * from logout() $$, 'Can logout even if the email and cookie does not match' );
|
||||
|
||||
select results_eq(
|
||||
'user_cookies',
|
||||
$$ values ('8c23d4a8d777775f8fc507676a0d99d3dfa54b03b1b257c838', current_timestamp + interval '1 day')
|
||||
, ('0169e5f668eec1e6749fd25388b057997358efa8dfd697961a', current_timestamp + interval '2 day')
|
||||
$$,
|
||||
'Should have changed nothing'
|
||||
);
|
||||
|
||||
select set_config('request.user.cookie', '8c23d4a8d777775f8fc507676a0d99d3dfa54b03b1b257c838', false);
|
||||
select set_config('request.user.email', 'info@tandem.blog', false);
|
||||
select lives_ok( $$ select * from logout() $$, 'Can logout the first user' );
|
||||
|
||||
select results_eq(
|
||||
|
@ -55,6 +69,7 @@ select results_eq(
|
|||
);
|
||||
|
||||
select set_config('request.user.cookie', '0169e5f668eec1e6749fd25388b057997358efa8dfd697961a', false);
|
||||
select set_config('request.user.email', 'admin@tandem.blog', false);
|
||||
select lives_ok( $$ select * from logout() $$, 'Can logout the second user' );
|
||||
|
||||
select results_eq(
|
||||
|
|
|
@ -29,7 +29,7 @@ values (1, 'demo@tandem.blog', 'Demo', 'test', 'invoicer', '44facbb30d8a419dfd4b
|
|||
;
|
||||
|
||||
prepare user_info as
|
||||
select current_setting('request.user.id', true)::integer, current_setting('request.user.email', true), current_user;
|
||||
select current_user_email(), current_user_cookie(), current_user;
|
||||
|
||||
select lives_ok(
|
||||
$$ select set_cookie('44facbb30d8a419dfd4bfbc44a4b5539d4970148dfc84bed0e/demo@tandem.blog') $$,
|
||||
|
@ -38,7 +38,7 @@ select lives_ok(
|
|||
|
||||
select results_eq(
|
||||
'user_info',
|
||||
$$ values (1, 'demo@tandem.blog', 'invoicer'::name) $$,
|
||||
$$ values ('demo@tandem.blog', '44facbb30d8a419dfd4bfbc44a4b5539d4970148dfc84bed0e', 'invoicer'::name) $$,
|
||||
'Should have updated the info with the correct user'
|
||||
);
|
||||
|
||||
|
@ -51,7 +51,7 @@ select lives_ok(
|
|||
|
||||
select results_eq(
|
||||
'user_info',
|
||||
$$ values (5, 'admin@tandem.blog', 'admin'::name) $$,
|
||||
$$ values ('admin@tandem.blog', '12af4c88b528c2ad4222e3740496ecbc58e76e26f087657524', 'admin'::name) $$,
|
||||
'Should have updated the info with the other user'
|
||||
);
|
||||
|
||||
|
@ -64,7 +64,7 @@ select lives_ok(
|
|||
|
||||
select results_eq(
|
||||
'user_info',
|
||||
$$ values (0, '', 'guest'::name) $$,
|
||||
$$ values ('', '', 'guest'::name) $$,
|
||||
'Should have updated the info as a guest user'
|
||||
);
|
||||
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
-- Verify numerus:build_cookie on pg
|
||||
|
||||
begin;
|
||||
|
||||
select has_function_privilege('numerus.build_cookie(numerus.email, text)', 'execute');
|
||||
|
||||
rollback;
|
|
@ -1,7 +0,0 @@
|
|||
-- Verify numerus:current_app_user on pg
|
||||
|
||||
begin;
|
||||
|
||||
select has_function_privilege('numerus.current_app_user()', 'execute');
|
||||
|
||||
rollback;
|
|
@ -0,0 +1,7 @@
|
|||
-- Verify numerus:current_user_cookie on pg
|
||||
|
||||
begin;
|
||||
|
||||
select has_function_privilege('numerus.current_user_cookie()', 'execute');
|
||||
|
||||
rollback;
|
|
@ -0,0 +1,7 @@
|
|||
-- Verify numerus:current_user_email on pg
|
||||
|
||||
begin;
|
||||
|
||||
select has_function_privilege('numerus.current_user_email()', 'execute');
|
||||
|
||||
rollback;
|
|
@ -11,4 +11,35 @@ select
|
|||
from numerus.user_profile
|
||||
where false;
|
||||
|
||||
select has_function_privilege('numerus.update_user_profile()', 'execute');
|
||||
|
||||
select 1/count(*)
|
||||
from pg_trigger
|
||||
where not tgisinternal
|
||||
and tgname = 'update_user_profile'
|
||||
and tgrelid = 'numerus.user_profile'::regclass
|
||||
and tgtype = b'01010001'::int;
|
||||
-- │││││││
|
||||
-- ││││││└─> row
|
||||
-- │││││└──> before
|
||||
-- ││││└───> insert
|
||||
-- │││└────> delete
|
||||
-- ││└─────> update
|
||||
-- │└──────> truncate
|
||||
-- └───────> instead
|
||||
select 1/count(*)
|
||||
from pg_trigger
|
||||
where not tgisinternal
|
||||
and tgname = 'encrypt_password'
|
||||
and tgrelid = 'auth.user'::regclass
|
||||
and tgtype = b'00010111'::int;
|
||||
-- │││││││
|
||||
-- ││││││└─> row
|
||||
-- │││││└──> before
|
||||
-- ││││└───> insert
|
||||
-- │││└────> delete
|
||||
-- ││└─────> update
|
||||
-- │└──────> truncate
|
||||
-- └───────> instead
|
||||
|
||||
rollback;
|
||||
|
|
Loading…
Reference in New Issue