Add function to change the current user’s password

This function does not ask for the confirmation because this is an
user-facing issue, not for the database.

Still missing: validation and proper error messages.
This commit is contained in:
jordi fita mas 2023-01-23 21:41:14 +01:00
parent 56d149e211
commit d9c93b8797
6 changed files with 103 additions and 0 deletions

View File

@ -0,0 +1,28 @@
-- Deploy numerus:change_password to pg
-- requires: schema_numerus
-- requires: user
begin;
set search_path to numerus, auth, public;
create or replace function change_password(new_password text) returns void as
$$
update "user"
set password = new_password
where email = current_user_email()
and cookie = current_user_cookie()
and cookie_expires_at > current_timestamp
and length(cookie) > 30
$$ language sql
security definer
set search_path to auth, numerus, pg_temp;
revoke execute on function change_password(text) from public;
grant execute on function change_password(text) to invoicer;
grant execute on function change_password(text) to admin;
comment on function change_password(text) is
'Changes the password for the current app user';
commit;

View File

@ -43,6 +43,9 @@ func ProfileHandler() http.Handler {
page.Language = r.FormValue("language")
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)
if page.Password != "" && page.Password == page.PasswordConfirm {
conn.MustExec(r.Context(), "select change_password($1)", page.Password)
}
http.Redirect(w, r, "/profile", http.StatusSeeOther)
return
} else {

View File

@ -0,0 +1,7 @@
-- Revert numerus:change_password from pg
begin;
drop function if exists numerus.change_password(text);
commit;

View File

@ -23,3 +23,4 @@ logout [schema_auth current_user_email current_user_cookie user] 2023-01-17T19:1
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_user_email current_user_cookie] 2023-01-21T23:18:20Z jordi fita mas <jordi@tandem.blog> # Add view for user profile
change_password [schema_numerus user] 2023-01-23T20:22:45Z jordi fita mas <jordi@tandem.blog> # Add function to change the current users password

57
test/change_password.sql Normal file
View File

@ -0,0 +1,57 @@
-- Test change_password
set client_min_messages to warning;
create extension if not exists pgtap;
reset client_min_messages;
begin;
select plan(14);
set search_path to numerus, auth, public;
select has_function('numerus', 'change_password', array ['text']);
select function_lang_is('numerus', 'change_password', array ['text'], 'sql');
select function_returns('numerus', 'change_password', array ['text'], 'void');
select is_definer('numerus', 'change_password', array ['text']);
select volatility_is('numerus', 'change_password', array ['text'], 'volatile');
select function_privs_are('numerus', 'change_password', array ['text'], 'guest', array []::text[]);
select function_privs_are('numerus', 'change_password', array ['text'], 'invoicer', array ['EXECUTE']);
select function_privs_are('numerus', 'change_password', array ['text'], 'admin', array ['EXECUTE']);
select function_privs_are('numerus', 'change_password', array ['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 lives_ok( $$ select change_password('another') $$, 'Should run even without current user' );
select isnt_empty (
$$ select * from auth."user" where password = crypt('test', password) $$,
'Should not have changed any password'
);
select set_cookie('44facbb30d8a419dfd4bfbc44a4b5539d4970148dfc84bed0e/demo@tandem.blog');
select lives_ok( $$ select change_password('another') $$, 'Should run with the correct user' );
reset role;
select isnt_empty (
$$ select * from auth."user" where email = 'demo@tandem.blog' and password = crypt('another', password) $$,
'Should have changed the password of the current user'
);
select isnt_empty (
$$ select * from auth."user" where email = 'admin@tandem.blog' and password = crypt('test', password) $$,
'Should not have changed any other password'
);
select *
from finish();
rollback;

View File

@ -0,0 +1,7 @@
-- Verify numerus:change_password on pg
begin;
select has_function_privilege('numerus.change_password(text)', 'execute');
rollback;