Move the user role down to company_user relation

I was starting to add the public page for campsite types, creating more
granular row-level security policies for select, insert, update, and
delete, because now the guest users needed to SELECT them and they have
no related company to filter the rows with.  Suddenly, i realized that
the role was wrong in the user relation: a user can be an admin to one
company, and employee to another, and guess to yet another company;
the role should be in the company_user relation instead.

That means that to know the role to set to, the user alone is not enough
and have to know the company as well.  Had to change all the
cookie-related function to accept also the company’s host name, as this
is the information that the Go application has.
This commit is contained in:
jordi fita mas 2023-08-08 02:22:16 +02:00
parent 477865477b
commit 866af09b50
43 changed files with 671 additions and 247 deletions

View File

@ -3,9 +3,9 @@ begin;
set search_path to camper, auth, public;
alter sequence user_user_id_seq restart with 42;
insert into auth."user" (email, name, password, role)
values ('demo@camper', 'Demo User', 'demo', 'employee')
, ('admin@camper', 'Demo Admin', 'admin', 'admin')
insert into auth."user" (email, name, password)
values ('demo@camper', 'Demo User', 'demo')
, ('admin@camper', 'Demo Admin', 'admin')
;
alter sequence company_company_id_seq restart with 52;
@ -17,9 +17,9 @@ values (52, 'localhost:8080')
, (52, 'camper.tandem.ws')
;
insert into company_user (company_id, user_id)
values (52, 42)
, (52, 43)
insert into company_user (company_id, user_id, role)
values (52, 42, 'employee')
, (52, 43, 'admin')
;
commit;

View File

@ -2,6 +2,7 @@
-- requires: roles
-- requires: schema_camper
-- requires: company
-- requires: user_profile
begin;
@ -16,6 +17,7 @@ create table campsite_type (
active boolean not null default true
);
grant select on table campsite_type to guest;
grant select on table campsite_type to employee;
grant select, insert, update, delete on table campsite_type to admin;
@ -23,16 +25,35 @@ grant usage on sequence campsite_type_campsite_type_id_seq to admin;
alter table campsite_type enable row level security;
create policy company_policy
create policy guest_ok
on campsite_type
for select
using (true)
;
create policy insert_to_company
on campsite_type
for insert
with check (
company_id in (select company_id from user_profile)
)
;
create policy update_company
on campsite_type
for update
using (
exists(
select 1
from company_user
join user_profile using (user_id)
where company_user.company_id = campsite_type.company_id
)
);
company_id in (select company_id from user_profile)
)
;
create policy delete_from_company
on campsite_type
for delete
using (
company_id in (select company_id from user_profile)
)
;
commit;

View File

@ -3,46 +3,53 @@
-- requires: schema_public
-- requires: schema_auth
-- requires: user
-- requires: company_host
-- requires: company_user
begin;
set search_path to public, auth;
create or replace function check_cookie(input_cookie text) returns name as
create or replace function check_cookie(input_cookie text, host text) returns name as
$$
declare
uid text;
user_email text;
user_role name;
cid text;
user_email text;
user_role name;
user_cookie text;
begin
select user_id::text, email::text, role, cookie
into uid, user_email, user_role, user_cookie
select company_id::text, email::text, role, cookie
into cid, user_email, user_role, user_cookie
from "user"
join company_user using (user_id)
join public.company_host using (company_id)
where email = split_part(input_cookie, '/', 2)
and cookie_expires_at > current_timestamp
and length(password) > 0
and cookie = split_part(input_cookie, '/', 1);
and cookie = split_part(input_cookie, '/', 1)
and company_host.host = check_cookie.host
;
if user_role is null then
uid := '0';
cid := '0';
user_email := '';
user_cookie := '';
user_role := 'guest'::name;
end if;
perform set_config('request.user.email', user_email, false);
perform set_config('request.user.cookie', user_cookie, false);
perform set_config('request.company.id', cid, false);
return user_role;
end;
$$
language plpgsql
security definer
stable
set search_path = auth, pg_temp;
set search_path = auth, camper, pg_temp;
comment on function check_cookie(text) is
comment on function check_cookie(text, text) is
'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;
revoke execute on function check_cookie(text, text) from public;
grant execute on function check_cookie(text, text) to authenticator;
commit;

View File

@ -36,7 +36,8 @@ create table company (
created_at timestamptz not null default current_timestamp
);
grant select, update on table company to employee;
grant select on table company to guest;
grant select on table company to employee;
grant select, update on table company to admin;
commit;

View File

@ -11,29 +11,16 @@ set search_path to camper, auth, public;
create table company_user (
company_id integer not null references company,
user_id integer not null references "user",
role name not null check (length(role) < 512),
primary key (company_id, user_id)
);
grant select on table company_user to employee;
grant select on table company_user to admin;
alter table company enable row level security;
create policy company_policy
on company
using (
exists(
select 1
from company_user
join user_profile using (user_id)
where company_user.company_id = company.company_id
)
);
-- TODO:
-- I think we can not do the same for company_user because it would be
-- an infinite loop, but in this case i think it is fine because we can
-- only see ids, nothing more.
-- I think we can enable row-level security for company_user because it would
-- be an infinite loop with user_profile, but in this case i think it is fine
-- because we can only see ids, nothing more.
commit;

View File

@ -0,0 +1,24 @@
-- Deploy camper:current_company_id to pg
-- requires: roles
-- requires: schema_camper
begin;
set search_path to camper;
create or replace function current_company_id() returns integer as
$$
select current_setting('request.company.id', true)::integer;
$$
language sql
stable;
comment on function current_company_id() is
'Returns the ID of the current company';
revoke execute on function current_company_id() from public;
grant execute on function current_company_id() to guest;
grant execute on function current_company_id() to employee;
grant execute on function current_company_id() to admin;
commit;

View File

@ -1,10 +1,11 @@
-- Deploy camper:ensure_role_exists to pg
-- requires: schema_auth
-- requires: user
-- requires: roles
-- requires: schema_camper
-- requires: company_user
begin;
set search_path to auth, public;
set search_path to camper, public;
create or replace function ensure_role_exists() returns trigger as
$$
@ -24,7 +25,7 @@ revoke execute on function ensure_role_exists() from public;
create trigger ensure_role_exists
after insert or update
on "user"
on company_user
for each row
execute procedure ensure_role_exists();

View File

@ -0,0 +1,25 @@
-- Deploy camper:policies_company to pg
-- requires: company
-- requires: user_profile
begin;
set search_path to camper, public;
alter table company enable row level security;
create policy guest_ok
on company
for select
using (true)
;
create policy update_company
on company
for update
using (
company_id in (select company_id from user_profile)
)
;
commit;

View File

@ -7,17 +7,17 @@ begin;
set search_path to public;
create or replace function set_cookie(input_cookie text) returns void as
create or replace function set_cookie(input_cookie text, host text) returns void as
$$
select set_config('role', check_cookie(input_cookie), false);
select set_config('role', check_cookie(input_cookie, host), false);
$$
language sql
stable;
comment on function set_cookie(text) is
comment on function set_cookie(text, text) is
'Sets the user information for the cookie and switches to its role';
revoke execute on function set_cookie(text) from public;
grant execute on function set_cookie(text) to authenticator;
revoke execute on function set_cookie(text, text) from public;
grant execute on function set_cookie(text, text) to authenticator;
commit;

View File

@ -13,7 +13,6 @@ create table "user" (
email email not null unique,
name text not null,
password text not null check (length(password) < 512),
role name not null check (length(role) < 512),
lang_tag text not null default 'und' references language,
cookie text not null default '',
cookie_expires_at timestamptz not null default '-infinity'::timestamp,

View File

@ -2,8 +2,10 @@
-- requires: roles
-- requires: schema_camper
-- requires: user
-- requires: company_user
-- requires: current_user_email
-- requires: current_user_cookie
-- requires: current_company_id
begin;
@ -11,18 +13,22 @@ set search_path to camper, public;
create or replace view user_profile with (security_barrier) as
select user_id
, company_id
, email
, name
, role
, lang_tag
, left(cookie, 10) as csrf_token
from auth."user"
join company_user using (user_id)
where email = current_user_email()
and cookie = current_user_cookie()
and cookie_expires_at > current_timestamp
and length(cookie) > 30
and company_id = current_company_id()
union all
select 0
, 0
, null::email
, ''
, 'guest'::name

View File

@ -26,7 +26,8 @@ import (
func (h *App) getUser(r *http.Request, conn *database.Conn) (*auth.User, error) {
cookie := auth.GetSessionCookie(r)
if _, err := conn.Exec(r.Context(), "select set_cookie($1)", cookie); err != nil {
host := httplib.Host(r)
if _, err := conn.Exec(r.Context(), "select set_cookie($1, $2)", cookie, host); err != nil {
return nil, err
}

View File

@ -2,6 +2,6 @@
begin;
drop function if exists public.check_cookie(text);
drop function if exists public.check_cookie(text, text);
commit;

View File

@ -2,7 +2,6 @@
begin;
drop policy if exists company_policy on camper.company;
drop table if exists camper.company_user;
commit;

View File

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

View File

@ -2,7 +2,9 @@
begin;
drop trigger if exists ensure_role_exists on auth."user";
drop function if exists auth.ensure_role_exists();
set search_path to camper;
drop trigger if exists ensure_role_exists on company_user;
drop function if exists ensure_role_exists();
commit;

View File

@ -0,0 +1,9 @@
-- Revert camper:policies_company from pg
begin;
set search_path to camper, public;
drop policy if exists guest_ok on company;
drop policy if exists update_company on company;
commit;

View File

@ -2,6 +2,6 @@
begin;
drop function if exists public.set_cookie(text);
drop function if exists public.set_cookie(text, text);
commit;

View File

@ -11,19 +11,14 @@ schema_camper [roles] 2023-07-21T22:08:39Z jordi fita mas <jordi@tandem.blog> #
email [schema_camper extension_citext] 2023-07-21T22:11:13Z jordi fita mas <jordi@tandem.blog> # Add email domain
schema_auth [roles] 2023-07-21T22:13:23Z jordi fita mas <jordi@tandem.blog> # Add authentication schema
user [roles schema_auth email language] 2023-07-21T22:37:20Z jordi fita mas <jordi@tandem.blog> # Add user relation
ensure_role_exists [schema_auth user] 2023-07-21T22:48:56Z jordi fita mas <jordi@tandem.blog> # Add trigger to ensure users role exists
extension_pgcrypto [schema_auth] 2023-07-21T22:53:25Z jordi fita mas <jordi@tandem.blog> # Add pgcrypto extension
encrypt_password [schema_auth user extension_pgcrypto] 2023-07-21T22:56:40Z jordi fita mas <jordi@tandem.blog> # Add function to encrypt users password
current_user_cookie [roles schema_camper] 2023-07-21T23:05:26Z jordi fita mas <jordi@tandem.blog> # Add function to get the cookie of the current user
current_user_email [roles schema_camper] 2023-07-21T23:09:34Z jordi fita mas <jordi@tandem.blog> # Add function to ge the email of the current user
current_user_email [roles schema_camper] 2023-07-21T23:09:34Z jordi fita mas <jordi@tandem.blog> # Add function to get the email of the current user
build_cookie [roles schema_camper current_user_email current_user_cookie] 2023-07-21T23:14:35Z jordi fita mas <jordi@tandem.blog> # Add function to build the cookie for the current user
login_attempt [schema_auth] 2023-07-21T23:22:17Z jordi fita mas <jordi@tandem.blog> # Add relation of log in attempts
login [roles schema_auth schema_camper extension_pgcrypto email user login_attempt build_cookie] 2023-07-21T23:29:18Z jordi fita mas <jordi@tandem.blog> # Add function to login
logout [roles schema_auth schema_camper current_user_email current_user_cookie user] 2023-07-21T23:36:12Z jordi fita mas <jordi@tandem.blog> # Add function to logout
check_cookie [roles schema_public schema_auth user] 2023-07-21T23:40:55Z jordi fita mas <jordi@tandem.blog> # Add function to check if a user cookie is valid
set_cookie [roles schema_public check_cookie] 2023-07-21T23:44:30Z jordi fita mas <jordi@tandem.blog> # Add function to set the role base don the cookie
user_profile [roles schema_camper user current_user_email current_user_cookie] 2023-07-21T23:47:36Z jordi fita mas <jordi@tandem.blog> # Add view for user profile
change_password [roles schema_auth schema_camper user] 2023-07-21T23:54:52Z jordi fita mas <jordi@tandem.blog> # Add function to change the current users password
extension_vat [schema_public] 2023-07-29T01:18:45Z jordi fita mas <jordi@tandem.blog> # Add vat extension
extension_pg_libphonenumber [schema_public] 2023-07-29T01:21:12Z jordi fita mas <jordi@tandem.blog> # Add phone numbers extension
extension_uri [schema_public] 2023-07-29T01:23:46Z jordi fita mas <jordi@tandem.blog> # Add URI extension
@ -36,6 +31,13 @@ country_i18n [roles schema_camper country_code language country] 2023-07-29T01:4
available_countries [schema_camper country country_i18n] 2023-07-29T01:48:40Z jordi fita mas <jordi@tandem.blog> # Add the list of available countries
company [roles schema_camper extension_vat email extension_pg_libphonenumber extension_uri currency_code currency country_code country language] 2023-07-29T01:56:41Z jordi fita mas <jordi@tandem.blog> # Add relation for company
company_user [roles schema_camper user company] 2023-07-29T02:08:07Z jordi fita mas <jordi@tandem.blog> # Add relation of company user
ensure_role_exists [roles schema_camper company_user] 2023-07-21T22:48:56Z jordi fita mas <jordi@tandem.blog> # Add trigger to ensure users role exists
company_host [roles schema_public] 2023-08-03T17:46:45Z jordi fita mas <jordi@tandem.blog> # Add relation of DNS domain and company
campsite_type [roles schema_camper company] 2023-07-31T11:20:29Z jordi fita mas <jordi@tandem.blog> # Add relation of campsite type
check_cookie [roles schema_public schema_auth user company_host company_user] 2023-07-21T23:40:55Z jordi fita mas <jordi@tandem.blog> # Add function to check if a user cookie is valid
set_cookie [roles schema_public check_cookie] 2023-07-21T23:44:30Z jordi fita mas <jordi@tandem.blog> # Add function to set the role base don the cookie
current_company_id [roles schema_camper] 2023-08-07T10:44:36Z jordi fita mas <jordi@tandem.blog> # Add function to get the ID of the current company
user_profile [roles schema_camper user company_user current_user_email current_user_cookie current_company_id] 2023-07-21T23:47:36Z jordi fita mas <jordi@tandem.blog> # Add view for user profile
policies_company [company user_profile] 2023-08-07T20:04:26Z jordi fita mas <jordi@tandem.blog> # Add row-level security profiles to company
change_password [roles schema_auth schema_camper user] 2023-07-21T23:54:52Z jordi fita mas <jordi@tandem.blog> # Add function to change the current users password
campsite_type [roles schema_camper company user_profile] 2023-07-31T11:20:29Z jordi fita mas <jordi@tandem.blog> # Add relation of campsite type
add_campsite_type [roles schema_camper campsite_type company] 2023-08-04T16:14:48Z jordi fita mas <jordi@tandem.blog> # Add function to create campsite types

View File

@ -20,14 +20,28 @@ select function_privs_are('camper', 'build_cookie', array ['email', 'text'], 'ad
select function_privs_are('camper', 'build_cookie', array ['email', 'text'], 'authenticator', array []::text[]);
set client_min_messages to warning;
truncate company_host cascade;
truncate company_user cascade;
truncate company cascade;
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', 'employee', '44facbb30d8a419dfd4bfbc44a4b5539d4970148dfc84bed0e',
current_timestamp + interval '1 month')
, (9, 'admin@tandem.blog', 'Demo', 'test', 'admin', '12af4c88b528c2ad4222e3740496ecbc58e76e26f087657524',
current_timestamp + interval '1 month')
insert into auth."user" (user_id, email, name, password, cookie, cookie_expires_at)
values (1, 'demo@tandem.blog', 'Demo', 'test', '44facbb30d8a419dfd4bfbc44a4b5539d4970148dfc84bed0e', current_timestamp + interval '1 month')
, (9, 'admin@tandem.blog', 'Demo', 'test', '12af4c88b528c2ad4222e3740496ecbc58e76e26f087657524', current_timestamp + interval '1 month')
;
insert into company (company_id, business_name, vatin, trade_name, phone, email, web, address, city, province, postal_code, country_code, currency_code, default_lang_tag)
values (2, 'Company 2', 'XX123', '', '555-555-555', 'a@a', '', '', '', '', '', 'ES', 'EUR', 'ca')
;
insert into company_user (company_id, user_id, role)
values (2, 1, 'employee')
, (2, 9, 'admin')
;
insert into company_host (company_id, host)
values (2, 'localhost')
;
select is(
@ -36,7 +50,7 @@ select is(
'Should build the cookie with the given user and cookie value'
);
select set_cookie('44facbb30d8a419dfd4bfbc44a4b5539d4970148dfc84bed0e/demo@tandem.blog');
select set_cookie('44facbb30d8a419dfd4bfbc44a4b5539d4970148dfc84bed0e/demo@tandem.blog', 'localhost');
reset role;
select is(
@ -46,7 +60,7 @@ select is(
);
select set_cookie('12af4c88b528c2ad4222e3740496ecbc58e76e26f087657524/admin@tandem.blog');
select set_cookie('12af4c88b528c2ad4222e3740496ecbc58e76e26f087657524/admin@tandem.blog', 'localhost');
reset role;
select is(
@ -56,7 +70,7 @@ select is(
);
select set_cookie('ashtasth');
select set_cookie('ashtasth', 'localhost');
reset role;
select is(

View File

@ -5,13 +5,13 @@ reset client_min_messages;
begin;
select plan(47);
select plan(55);
set search_path to camper, public;
select has_table('campsite_type');
select has_pk('campsite_type' );
select table_privs_are('campsite_type', 'guest', array[]::text[]);
select table_privs_are('campsite_type', 'guest', array['SELECT']::text[]);
select table_privs_are('campsite_type', 'employee', array['SELECT']);
select table_privs_are('campsite_type', 'admin', array['SELECT', 'INSERT', 'UPDATE', 'DELETE']);
select table_privs_are('campsite_type', 'authenticator', array[]::text[]);
@ -63,14 +63,15 @@ select col_default_is('campsite_type', 'active', 'true');
set client_min_messages to warning;
truncate campsite_type cascade;
truncate company_host cascade;
truncate company_user cascade;
truncate company cascade;
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', 'employee', '44facbb30d8a419dfd4bfbc44a4b5539d4970148dfc84bed0e', current_timestamp + interval '1 month')
, (5, 'admin@tandem.blog', 'Demo', 'test', 'admin', '12af4c88b528c2ad4222e3740496ecbc58e76e26f087657524', current_timestamp + interval '1 month')
insert into auth."user" (user_id, email, name, password, cookie, cookie_expires_at)
values (1, 'demo@tandem.blog', 'Demo', 'test', '44facbb30d8a419dfd4bfbc44a4b5539d4970148dfc84bed0e', current_timestamp + interval '1 month')
, (5, 'admin@tandem.blog', 'Demo', 'test', '12af4c88b528c2ad4222e3740496ecbc58e76e26f087657524', current_timestamp + interval '1 month')
;
insert into company (company_id, business_name, vatin, trade_name, phone, email, web, address, city, province, postal_code, country_code, currency_code, default_lang_tag)
@ -78,9 +79,14 @@ values (2, 'Company 2', 'XX123', '', '555-555-555', 'a@a', '', '', '', '', '', '
, (4, 'Company 4', 'XX234', '', '666-666-666', 'b@b', '', '', '', '', '', 'FR', 'USD', 'ca')
;
insert into company_user (company_id, user_id)
values (2, 1)
, (4, 5)
insert into company_user (company_id, user_id, role)
values (2, 1, 'admin')
, (4, 5, 'admin')
;
insert into company_host (company_id, host)
values (2, 'co2')
, (4, 'co4')
;
insert into campsite_type (company_id, name)
@ -93,44 +99,99 @@ select company_id, name
from campsite_type
order by company_id, name;
set role employee;
select is_empty('campsite_type_data', 'Should show no data when cookie is not set yet');
reset role;
select set_cookie('44facbb30d8a419dfd4bfbc44a4b5539d4970148dfc84bed0e/demo@tandem.blog');
set role guest;
select bag_eq(
'campsite_type_data',
$$ values (2, 'Wooden lodge')
, (4, 'Bungalow')
$$,
'Should only list campsite types of the companies where demo@tandem.blog is user of'
'Everyone should be able to list all campsite types across all companies'
);
reset role;
select set_cookie('12af4c88b528c2ad4222e3740496ecbc58e76e26f087657524/admin@tandem.blog');
select set_cookie('44facbb30d8a419dfd4bfbc44a4b5539d4970148dfc84bed0e/demo@tandem.blog', 'co2');
select lives_ok(
$$ insert into campsite_type(company_id, name) values (2, 'Another type' ) $$,
'Admin from company 2 should be able to insert a new campsite type to that company.'
);
select bag_eq(
'campsite_type_data',
$$ values (4, 'Bungalow')
$$ values (2, 'Wooden lodge')
, (2, 'Another type')
, (4, 'Bungalow')
$$,
'Should only list campsite type of the companies where admin@tandem.blog is user of'
'The new row should have been added'
);
reset role;
select set_cookie('not-a-cookie');
select throws_ok(
select lives_ok(
$$ update campsite_type set name = 'Another' where company_id = 2 and name = 'Another type' $$,
'Admin from company 2 should be able to update campsite type of that company.'
);
select bag_eq(
'campsite_type_data',
'42501', 'permission denied for table campsite_type',
'Should not allow select campsite types to guest users'
);
reset role;
select throws_ok( $$
insert into campsite_type (company_id, name)
values (2, ' ')
$$ values (2, 'Wooden lodge')
, (2, 'Another')
, (4, 'Bungalow')
$$,
'23514', 'new row for relation "campsite_type" violates check constraint "name_not_empty"',
'Should not allow campsite types with blank name'
'The row should have been updated.'
);
select lives_ok(
$$ delete from campsite_type where company_id = 2 and name = 'Another' $$,
'Admin from company 2 should be able to delete campsite type from that company.'
);
select bag_eq(
'campsite_type_data',
$$ values (2, 'Wooden lodge')
, (4, 'Bungalow')
$$,
'The row should have been deleted.'
);
select throws_ok(
$$ insert into campsite_type (company_id, name) values (4, 'Another type' ) $$,
'42501', 'new row violates row-level security policy for table "campsite_type"',
'Admin from company 2 should NOT be able to insert new campsite types to company 4.'
);
select lives_ok(
$$ update campsite_type set name = 'Nope' where company_id = 4 $$,
'Admin from company 2 should not be able to update new campsite types of company 4, but no error if company_id is not changed.'
);
select bag_eq(
'campsite_type_data',
$$ values (2, 'Wooden lodge')
, (4, 'Bungalow')
$$,
'No row should have been changed.'
);
select throws_ok(
$$ update campsite_type set company_id = 4 where company_id = 2 $$,
'42501', 'new row violates row-level security policy for table "campsite_type"',
'Admin from company 2 should NOT be able to move campsite types to company 4'
);
select lives_ok(
$$ delete from campsite_type where company_id = 4 $$,
'Admin from company 2 should NOT be able to delete campsite types from company 4, but not error is thrown'
);
select bag_eq(
'campsite_type_data',
$$ values (2, 'Wooden lodge')
, (4, 'Bungalow')
$$,
'No row should have been changed'
);
reset role;
select *
from finish();

View File

@ -20,12 +20,28 @@ select function_privs_are('camper', 'change_password', array ['text'], 'admin',
select function_privs_are('camper', 'change_password', array ['text'], 'authenticator', array []::text[]);
set client_min_messages to warning;
truncate company_host cascade;
truncate company_user cascade;
truncate company cascade;
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', 'employee', '44facbb30d8a419dfd4bfbc44a4b5539d4970148dfc84bed0e', current_timestamp + interval '1 month')
, (9, 'admin@tandem.blog', 'Demo', 'test', 'admin', '12af4c88b528c2ad4222e3740496ecbc58e76e26f087657524', current_timestamp + interval '1 month')
insert into auth."user" (user_id, email, name, password, cookie, cookie_expires_at)
values (1, 'demo@tandem.blog', 'Demo', 'test', '44facbb30d8a419dfd4bfbc44a4b5539d4970148dfc84bed0e', current_timestamp + interval '1 month')
, (9, 'admin@tandem.blog', 'Demo', 'test', '12af4c88b528c2ad4222e3740496ecbc58e76e26f087657524', current_timestamp + interval '1 month')
;
insert into company (company_id, business_name, vatin, trade_name, phone, email, web, address, city, province, postal_code, country_code, currency_code, default_lang_tag)
values (2, 'Company 2', 'XX123', '', '555-555-555', 'a@a', '', '', '', '', '', 'ES', 'EUR', 'ca')
;
insert into company_user (company_id, user_id, role)
values (2, 1, 'employee')
, (2, 9, 'admin')
;
insert into company_host (company_id, host)
values (2, 'localhost')
;
select lives_ok($$ select change_password('another') $$, 'Should run even without current user');
@ -35,7 +51,7 @@ select isnt_empty(
'Should not have changed any password'
);
select set_cookie('44facbb30d8a419dfd4bfbc44a4b5539d4970148dfc84bed0e/demo@tandem.blog');
select set_cookie('44facbb30d8a419dfd4bfbc44a4b5539d4970148dfc84bed0e/demo@tandem.blog', 'localhost');
select lives_ok($$ select change_password('another') $$, 'Should run with the correct user');

View File

@ -5,77 +5,107 @@ reset client_min_messages;
begin;
select plan(21);
select plan(23);
set search_path to auth, camper, public;
select has_function('public', 'check_cookie', array ['text']);
select function_lang_is('public', 'check_cookie', array ['text'], 'plpgsql');
select function_returns('public', 'check_cookie', array ['text'], 'name');
select is_definer('public', 'check_cookie', array ['text']);
select volatility_is('public', 'check_cookie', array ['text'], 'stable');
select function_privs_are('public', 'check_cookie', array ['text'], 'guest', array []::text[]);
select function_privs_are('public', 'check_cookie', array ['text'], 'employee', array []::text[]);
select function_privs_are('public', 'check_cookie', array ['text'], 'admin', array []::text[]);
select function_privs_are('public', 'check_cookie', array ['text'], 'authenticator', array ['EXECUTE']);
select has_function('public', 'check_cookie', array ['text', 'text']);
select function_lang_is('public', 'check_cookie', array ['text', 'text'], 'plpgsql');
select function_returns('public', 'check_cookie', array ['text', 'text'], 'name');
select is_definer('public', 'check_cookie', array ['text', 'text']);
select volatility_is('public', 'check_cookie', array ['text', 'text'], 'stable');
select function_privs_are('public', 'check_cookie', array ['text', 'text'], 'guest', array []::text[]);
select function_privs_are('public', 'check_cookie', array ['text', 'text'], 'employee', array []::text[]);
select function_privs_are('public', 'check_cookie', array ['text', 'text'], 'admin', array []::text[]);
select function_privs_are('public', 'check_cookie', array ['text', 'text'], 'authenticator', array ['EXECUTE']);
set client_min_messages to warning;
truncate company_host cascade;
truncate company_user cascade;
truncate company cascade;
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', 'employee', '44facbb30d8a419dfd4bfbc44a4b5539d4970148dfc84bed0e', current_timestamp + interval '1 month')
, (9, 'admin@tandem.blog', 'Demo', 'test', 'admin', '12af4c88b528c2ad4222e3740496ecbc58e76e26f087657524', current_timestamp + interval '1 month')
insert into auth."user" (user_id, email, name, password, cookie, cookie_expires_at)
values (1, 'demo@tandem.blog', 'Demo', 'test', '44facbb30d8a419dfd4bfbc44a4b5539d4970148dfc84bed0e', current_timestamp + interval '1 month')
, (9, 'admin@tandem.blog', 'Demo', 'test', '12af4c88b528c2ad4222e3740496ecbc58e76e26f087657524', current_timestamp + interval '1 month')
;
insert into company (company_id, business_name, vatin, trade_name, phone, email, web, address, city, province, postal_code, country_code, currency_code, default_lang_tag)
values (2, 'Company 2', 'XX123', '', '555-555-555', 'a@a', '', '', '', '', '', 'ES', 'EUR', 'ca')
, (4, 'Company 4', 'XX234', '', '666-666-666', 'b@b', '', '', '', '', '', 'FR', 'USD', 'es')
;
insert into company_user (company_id, user_id, role)
values (2, 1, 'employee')
, (4, 9, 'admin')
;
insert into company_host (company_id, host)
values (2, 'co2')
, (4, 'co4')
;
prepare user_info as
select current_user_email(), current_user_cookie();
select current_user_email(), current_user_cookie(), current_company_id();
select is(
check_cookie('44facbb30d8a419dfd4bfbc44a4b5539d4970148dfc84bed0e/demo@tandem.blog'),
check_cookie('44facbb30d8a419dfd4bfbc44a4b5539d4970148dfc84bed0e/demo@tandem.blog', 'co2'),
'employee'::name,
'Should validate the cookie for the first user'
);
select results_eq(
'user_info',
$$ values ('demo@tandem.blog', '44facbb30d8a419dfd4bfbc44a4b5539d4970148dfc84bed0e') $$,
$$ values ('demo@tandem.blog', '44facbb30d8a419dfd4bfbc44a4b5539d4970148dfc84bed0e', 2) $$,
'Should have updated the settings with the user info'
);
select is(
check_cookie('12af4c88b528c2ad4222e3740496ecbc58e76e26f087657524/admin@tandem.blog'),
check_cookie('12af4c88b528c2ad4222e3740496ecbc58e76e26f087657524/admin@tandem.blog', 'co4'),
'admin'::name,
'Should validate the cookie for the second user'
);
select results_eq(
'user_info',
$$ values ('admin@tandem.blog', '12af4c88b528c2ad4222e3740496ecbc58e76e26f087657524') $$,
$$ values ('admin@tandem.blog', '12af4c88b528c2ad4222e3740496ecbc58e76e26f087657524', 4) $$,
'Should have updated the settings with the other user info'
);
select is(
check_cookie('44facbb30d8a419dfd4bfbc44a4b5539d4970148dfc84bed0e/admin@tandem.blog'),
check_cookie('44facbb30d8a419dfd4bfbc44a4b5539d4970148dfc84bed0e/admin@tandem.blog', 'co2'),
'guest'::name,
'Should only match with the correct email'
);
select results_eq(
'user_info',
$$ values ('', '') $$,
$$ values ('', '', 0) $$,
'Should have updated the settings with a guest user'
);
select is(
check_cookie('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/admin@tandem.blog'),
check_cookie('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/admin@tandem.blog', 'co2'),
'guest'::name,
'Should only match with the correct cookie value'
);
select results_eq(
'user_info',
$$ values ('', '') $$,
$$ values ('', '', 0) $$,
'Should have left the settings with a guest user'
);
select is(
check_cookie('44facbb30d8a419dfd4bfbc44a4b5539d4970148dfc84bed0e/demo@tandem.blog', 'co4'),
'guest'::name,
'Should not allow cookies for a different company'
);
select results_eq(
'user_info',
$$ values ('', '', 0) $$,
'Should have left the settings with a guest user'
);
@ -83,26 +113,26 @@ update "user"
set cookie_expires_at = current_timestamp - interval '1 minute';
select is(
check_cookie('44facbb30d8a419dfd4bfbc44a4b5539d4970148dfc84bed0e/demo@tandem.blog'),
check_cookie('44facbb30d8a419dfd4bfbc44a4b5539d4970148dfc84bed0e/demo@tandem.blog', 'co2'),
'guest'::name,
'Should not allow expired cookies'
);
select results_eq(
'user_info',
$$ values ('', '') $$,
$$ values ('', '', 0) $$,
'Should have left the settings with a guest user'
);
select is(
check_cookie('12af4c88b528c2ad4222e3740496ecbc58e76e26f087657524/admin@tandem.blog'),
check_cookie('12af4c88b528c2ad4222e3740496ecbc58e76e26f087657524/admin@tandem.blog', 'co4'),
'guest'::name,
'Should not allow expired cookied for the other user as well'
);
select results_eq(
'user_info',
$$ values ('', '') $$,
$$ values ('', '', 0) $$,
'Should have left the settings with a guest user'
);

View File

@ -5,14 +5,14 @@ reset client_min_messages;
begin;
select plan(101);
select plan(102);
set search_path to camper, public;
select has_table('company');
select has_pk('company' );
select table_privs_are('company', 'guest', array []::text[]);
select table_privs_are('company', 'employee', array ['SELECT', 'UPDATE']);
select table_privs_are('company', 'guest', array ['SELECT']);
select table_privs_are('company', 'employee', array ['SELECT']);
select table_privs_are('company', 'admin', array ['SELECT', 'UPDATE']);
select table_privs_are('company', 'authenticator', array []::text[]);
@ -127,27 +127,30 @@ select col_default_is('company', 'created_at', 'CURRENT_TIMESTAMP');
set client_min_messages to warning;
truncate company_host cascade;
truncate company_user cascade;
truncate company cascade;
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', 'employee', '44facbb30d8a419dfd4bfbc44a4b5539d4970148dfc84bed0e', current_timestamp + interval '1 month')
, (5, 'admin@tandem.blog', 'Demo', 'test', 'admin', '12af4c88b528c2ad4222e3740496ecbc58e76e26f087657524', current_timestamp + interval '1 month')
insert into auth."user" (user_id, email, name, password, cookie, cookie_expires_at)
values (1, 'demo@tandem.blog', 'Demo', 'test', '44facbb30d8a419dfd4bfbc44a4b5539d4970148dfc84bed0e', current_timestamp + interval '1 month')
, (5, 'admin@tandem.blog', 'Demo', 'test', '12af4c88b528c2ad4222e3740496ecbc58e76e26f087657524', current_timestamp + interval '1 month')
;
insert into company (company_id, business_name, vatin, trade_name, phone, email, web, address, city, province, postal_code, country_code, currency_code, default_lang_tag)
values (2, 'Company 2', 'XX123', '', '555-555-555', 'a@a', '', '', '', '', '', 'ES', 'EUR', 'ca')
, (4, 'Company 4', 'XX234', '', '666-666-666', 'b@b', '', '', '', '', '', 'FR', 'USD', 'es')
, (6, 'Company 6', 'XX345', '', '777-777-777', 'c@c', '', '', '', '', '', 'DE', 'USD', 'ca')
;
insert into company_user (company_id, user_id)
values (2, 1)
, (2, 5)
, (4, 1)
, (6, 5)
insert into company_user (company_id, user_id, role)
values (2, 1, 'admin')
, (4, 5, 'admin')
;
insert into company_host (company_id, host)
values (2, 'co2')
, (4, 'co4')
;
prepare company_data as
@ -155,36 +158,44 @@ select company_id, business_name
from company
order by company_id;
set role employee;
select is_empty('company_data', 'Should show no data when cookie is not set yet');
reset role;
select set_cookie('44facbb30d8a419dfd4bfbc44a4b5539d4970148dfc84bed0e/demo@tandem.blog');
set role guest;
select results_eq(
'company_data',
$$ values ( 2, 'Company 2' )
, ( 4, 'Company 4' )
$$,
'Should only list companies where demo@tandem.blog is user of'
'Everyone should be able to list all companies'
);
reset role;
select set_cookie('12af4c88b528c2ad4222e3740496ecbc58e76e26f087657524/admin@tandem.blog');
select set_cookie('44facbb30d8a419dfd4bfbc44a4b5539d4970148dfc84bed0e/demo@tandem.blog', 'co2');
select lives_ok(
$$ update company set business_name = 'Another Company 2' where company_id = 2 $$,
'Admin from company 2 should be able to update that company.'
);
select results_eq(
'company_data',
$$ values ( 2, 'Company 2' )
, ( 6, 'Company 6' )
$$ values ( 2, 'Another Company 2' )
, ( 4, 'Company 4' )
$$,
'Should only list companies where admin@tandem.blog is user of'
'Should have updated the row.'
);
reset role;
select set_cookie('not-a-cookie');
select throws_ok(
'company_data',
'42501', 'permission denied for table company',
'Should not allow select to guest users'
select lives_ok(
$$ update company set business_name = 'Another Company 4' where company_id = 4 $$,
'Admin from company 2 should NOT be able to update that company, but no error is raised.'
);
select results_eq(
'company_data',
$$ values ( 2, 'Another Company 2' )
, ( 4, 'Company 4' )
$$,
'Should NOT have updated anything.'
);
reset role;
select throws_ok( $$

View File

@ -5,7 +5,7 @@ reset client_min_messages;
begin;
select plan(19);
select plan(23);
set search_path to camper, public;
@ -31,6 +31,12 @@ select col_type_is('company_user', 'user_id', 'integer');
select col_not_null('company_user', 'user_id');
select col_hasnt_default('company_user', 'user_id');
select has_column('company_user', 'role');
select col_type_is('company_user', 'role', 'name');
select col_not_null('company_user', 'role');
select col_hasnt_default('company_user', 'role');
select *
from finish();

View File

@ -0,0 +1,88 @@
-- Test current_company_id
set client_min_messages to warning;
create extension if not exists pgtap;
reset client_min_messages;
begin;
set search_path to camper, auth, public;
select plan(15);
select has_function('camper', 'current_company_id', array []::name[]);
select function_lang_is('camper', 'current_company_id', array []::name[], 'sql');
select function_returns('camper', 'current_company_id', array []::name[], 'integer');
select isnt_definer('camper', 'current_company_id', array []::name[]);
select volatility_is('camper', 'current_company_id', array []::name[], 'stable');
select function_privs_are('camper', 'current_company_id', array []::name[], 'guest', array ['EXECUTE']);
select function_privs_are('camper', 'current_company_id', array []::name[], 'employee', array ['EXECUTE']);
select function_privs_are('camper', 'current_company_id', array []::name[], 'admin', array ['EXECUTE']);
select function_privs_are('camper', 'current_company_id', array []::name[], 'authenticator', array []::text[]);
set client_min_messages to warning;
truncate company_host cascade;
truncate company_user cascade;
truncate company cascade;
truncate auth."user" cascade;
reset client_min_messages;
insert into auth."user" (user_id, email, name, password, cookie, cookie_expires_at)
values (1, 'demo@tandem.blog', 'Demo', 'test', '44facbb30d8a419dfd4bfbc44a4b5539d4970148dfc84bed0e', current_timestamp + interval '1 month')
, (5, 'admin@tandem.blog', 'Demo', 'test', '12af4c88b528c2ad4222e3740496ecbc58e76e26f087657524', current_timestamp + interval '1 month')
;
insert into company (company_id, business_name, vatin, trade_name, phone, email, web, address, city, province, postal_code, country_code, currency_code, default_lang_tag)
values (2, 'Company 2', 'XX123', '', '555-555-555', 'a@a', '', '', '', '', '', 'ES', 'EUR', 'ca')
, (4, 'Company 4', 'XX234', '', '666-666-666', 'b@b', '', '', '', '', '', 'FR', 'USD', 'es')
;
insert into company_user (company_id, user_id, role)
values (2, 1, 'employee')
, (4, 5, 'admin')
;
insert into company_host (company_id, host)
values (2, 'co2')
, (4, 'co4')
;
select lives_ok(
$$ select set_cookie('44facbb30d8a419dfd4bfbc44a4b5539d4970148dfc84bed0e/demo@tandem.blog', 'co2') $$,
'Should change ok for the first user'
);
select is(
current_company_id(),
2,
'Should return the company ID of the first user'
);
reset role;
select lives_ok(
$$ select set_cookie('12af4c88b528c2ad4222e3740496ecbc58e76e26f087657524/admin@tandem.blog', 'co4') $$,
'Should change ok for the second user'
);
select is(
current_company_id(),
4,
'Should return the cookie of the second user'
);
reset role;
select lives_ok(
$$ select set_cookie('', 'co2') $$,
'Should change ok for a guest user'
);
select is(current_company_id(), 0, 'Should return zero');
reset role;
select *
from finish();
rollback;

View File

@ -20,16 +20,34 @@ select function_privs_are('camper', 'current_user_cookie', array []::name[], 'ad
select function_privs_are('camper', 'current_user_cookie', array []::name[], 'authenticator', array []::text[]);
set client_min_messages to warning;
truncate company_host cascade;
truncate company_user cascade;
truncate company cascade;
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', 'employee', '44facbb30d8a419dfd4bfbc44a4b5539d4970148dfc84bed0e', current_timestamp + interval '1 month')
, (5, 'admin@tandem.blog', 'Demo', 'test', 'admin', '12af4c88b528c2ad4222e3740496ecbc58e76e26f087657524', current_timestamp + interval '1 month')
insert into auth."user" (user_id, email, name, password, cookie, cookie_expires_at)
values (1, 'demo@tandem.blog', 'Demo', 'test', '44facbb30d8a419dfd4bfbc44a4b5539d4970148dfc84bed0e', current_timestamp + interval '1 month')
, (5, 'admin@tandem.blog', 'Demo', 'test', '12af4c88b528c2ad4222e3740496ecbc58e76e26f087657524', current_timestamp + interval '1 month')
;
insert into company (company_id, business_name, vatin, trade_name, phone, email, web, address, city, province, postal_code, country_code, currency_code, default_lang_tag)
values (2, 'Company 2', 'XX123', '', '555-555-555', 'a@a', '', '', '', '', '', 'ES', 'EUR', 'ca')
, (4, 'Company 4', 'XX234', '', '666-666-666', 'b@b', '', '', '', '', '', 'FR', 'USD', 'es')
;
insert into company_user (company_id, user_id, role)
values (2, 1, 'employee')
, (4, 5, 'admin')
;
insert into company_host (company_id, host)
values (2, 'co2')
, (4, 'co4')
;
select lives_ok(
$$ select set_cookie('44facbb30d8a419dfd4bfbc44a4b5539d4970148dfc84bed0e/demo@tandem.blog') $$,
$$ select set_cookie('44facbb30d8a419dfd4bfbc44a4b5539d4970148dfc84bed0e/demo@tandem.blog', 'co2') $$,
'Should change ok for the first user'
);
@ -43,7 +61,7 @@ reset role;
select lives_ok(
$$ select set_cookie('12af4c88b528c2ad4222e3740496ecbc58e76e26f087657524/admin@tandem.blog') $$,
$$ select set_cookie('12af4c88b528c2ad4222e3740496ecbc58e76e26f087657524/admin@tandem.blog', 'co4') $$,
'Should change ok for the second user'
);
@ -56,7 +74,7 @@ select is(
reset role;
select lives_ok(
$$ select set_cookie('') $$,
$$ select set_cookie('', 'co2') $$,
'Should change ok for a guest user'
);

View File

@ -20,16 +20,34 @@ select function_privs_are('camper', 'current_user_email', array []::name[], 'adm
select function_privs_are('camper', 'current_user_email', array []::name[], 'authenticator', array []::text[]);
set client_min_messages to warning;
truncate company_host cascade;
truncate company_user cascade;
truncate company cascade;
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', 'employee', '44facbb30d8a419dfd4bfbc44a4b5539d4970148dfc84bed0e', current_timestamp + interval '1 month')
, (5, 'admin@tandem.blog', 'Demo', 'test', 'admin', '12af4c88b528c2ad4222e3740496ecbc58e76e26f087657524', current_timestamp + interval '1 month')
insert into auth."user" (user_id, email, name, password, cookie, cookie_expires_at)
values (1, 'demo@tandem.blog', 'Demo', 'test', '44facbb30d8a419dfd4bfbc44a4b5539d4970148dfc84bed0e', current_timestamp + interval '1 month')
, (5, 'admin@tandem.blog', 'Demo', 'test', '12af4c88b528c2ad4222e3740496ecbc58e76e26f087657524', current_timestamp + interval '1 month')
;
insert into company (company_id, business_name, vatin, trade_name, phone, email, web, address, city, province, postal_code, country_code, currency_code, default_lang_tag)
values (2, 'Company 2', 'XX123', '', '555-555-555', 'a@a', '', '', '', '', '', 'ES', 'EUR', 'ca')
, (4, 'Company 4', 'XX234', '', '666-666-666', 'b@b', '', '', '', '', '', 'FR', 'USD', 'es')
;
insert into company_user (company_id, user_id, role)
values (2, 1, 'employee')
, (4, 5, 'admin')
;
insert into company_host (company_id, host)
values (2, 'co2')
, (4, 'co4')
;
select lives_ok(
$$ select set_cookie('44facbb30d8a419dfd4bfbc44a4b5539d4970148dfc84bed0e/demo@tandem.blog') $$,
$$ select set_cookie('44facbb30d8a419dfd4bfbc44a4b5539d4970148dfc84bed0e/demo@tandem.blog', 'co2') $$,
'Should change ok for the first user'
);
@ -39,7 +57,7 @@ reset role;
select lives_ok(
$$ select set_cookie('12af4c88b528c2ad4222e3740496ecbc58e76e26f087657524/admin@tandem.blog') $$,
$$ select set_cookie('12af4c88b528c2ad4222e3740496ecbc58e76e26f087657524/admin@tandem.blog', 'co4') $$,
'Should change ok for the second user'
);
@ -48,7 +66,7 @@ select is(current_user_email(), 'admin@tandem.blog', 'Should return the email of
reset role;
select lives_ok(
$$ select set_cookie('') $$,
$$ select set_cookie('', '') $$,
'Should change ok for a guest user'
);

View File

@ -25,8 +25,8 @@ set client_min_messages to warning;
truncate "user" cascade;
reset client_min_messages;
insert into "user" (email, name, password, role)
values ('info@tandem.blog', 'Perita', 'test', 'guest');
insert into "user" (email, name, password)
values ('info@tandem.blog', 'Perita', 'test');
select row_eq(
$$ select email from "user" where password = crypt('test', password) $$,

View File

@ -7,41 +7,52 @@ begin;
select plan(14);
set search_path to auth, public;
set search_path to auth, camper, public;
select has_function('auth', 'ensure_role_exists', array []::name[]);
select function_lang_is('auth', 'ensure_role_exists', array []::name[], 'plpgsql');
select function_returns('auth', 'ensure_role_exists', array []::name[], 'trigger');
select isnt_definer('auth', 'ensure_role_exists', array []::name[]);
select volatility_is('auth', 'ensure_role_exists', array []::name[], 'volatile');
select function_privs_are('auth', 'ensure_role_exists', array []::name[], 'guest', array []::text[]);
select function_privs_are('auth', 'ensure_role_exists', array []::name[], 'employee', array []::text[]);
select function_privs_are('auth', 'ensure_role_exists', array []::name[], 'admin', array []::text[]);
select function_privs_are('auth', 'ensure_role_exists', array []::name[], 'authenticator', array []::text[]);
select has_function('camper', 'ensure_role_exists', array []::name[]);
select function_lang_is('camper', 'ensure_role_exists', array []::name[], 'plpgsql');
select function_returns('camper', 'ensure_role_exists', array []::name[], 'trigger');
select isnt_definer('camper', 'ensure_role_exists', array []::name[]);
select volatility_is('camper', 'ensure_role_exists', array []::name[], 'volatile');
select function_privs_are('camper', 'ensure_role_exists', array []::name[], 'guest', array []::text[]);
select function_privs_are('camper', 'ensure_role_exists', array []::name[], 'employee', array []::text[]);
select function_privs_are('camper', 'ensure_role_exists', array []::name[], 'admin', array []::text[]);
select function_privs_are('camper', 'ensure_role_exists', array []::name[], 'authenticator', array []::text[]);
select trigger_is('user', 'ensure_role_exists', 'ensure_role_exists');
select trigger_is('company_user', 'ensure_role_exists', 'ensure_role_exists');
set client_min_messages to warning;
truncate company_user cascade;
truncate company cascade;
truncate "user" cascade;
reset client_min_messages;
insert into auth."user" (user_id, email, name, password)
values (1, 'demo@tandem.blog', 'Demo', 'test')
, (9, 'admin@tandem.blog', 'Demo', 'test')
;
insert into company (company_id, business_name, vatin, trade_name, phone, email, web, address, city, province, postal_code, country_code, currency_code, default_lang_tag)
values (2, 'Company 2', 'XX123', '', '555-555-555', 'a@a', '', '', '', '', '', 'ES', 'EUR', 'ca')
;
select lives_ok(
$$ insert into "user" (email, name, password, role) values ('info@tandem.blog', 'Factura', 'test', 'guest') $$,
$$ insert into company_user (company_id, user_id, role) values (2, 1, 'guest') $$,
'Should be able to insert a user with a valid role'
);
select throws_ok(
$$ insert into "user" (email, name, password, role) values ('nope@tandem.blog', 'Factura', 'test', 'non-existing-role') $$,
$$ insert into company_user (companY_id, user_id, role) values (2, 9, 'non-existing-role') $$,
'23503',
'role not found: non-existing-role',
'Should not allow insert users with invalid roles'
);
select lives_ok($$ update "user" set role = 'employee' where email = 'info@tandem.blog' $$,
select lives_ok($$ update company_user set role = 'employee' where company_id = 2 and user_id = 1 $$,
'Should be able to change the role of a user to another valid role'
);
select throws_ok($$ update "user" set role = 'usurer' where email = 'info@tandem.blog' $$,
select throws_ok($$ update company_user set role = 'usurer' where company_id = 2 and user_id = 1 $$,
'23503',
'role not found: usurer',
'Should not allow update users to invalid roles'

View File

@ -24,8 +24,8 @@ 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', 'employee');
insert into auth."user" (email, name, password)
values ('info@tandem.blog', 'Tandem', 'test');
create temp table _login_test
(

View File

@ -23,9 +23,9 @@ 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, 'info@tandem.blog', 'Tandem', 'test', 'employee', '8c23d4a8d777775f8fc507676a0d99d3dfa54b03b1b257c838', current_timestamp + interval '1 day')
, (12, 'admin@tandem.blog', 'Admin', 'test', 'admin', '0169e5f668eec1e6749fd25388b057997358efa8dfd697961a', current_timestamp + interval '2 day')
insert into auth."user" (user_id, email, name, password, cookie, cookie_expires_at)
values (1, 'info@tandem.blog', 'Tandem', 'test', '8c23d4a8d777775f8fc507676a0d99d3dfa54b03b1b257c838', current_timestamp + interval '1 day')
, (12, 'admin@tandem.blog', 'Admin', 'test', '0169e5f668eec1e6749fd25388b057997358efa8dfd697961a', current_timestamp + interval '2 day')
;
prepare user_cookies as

View File

@ -5,66 +5,97 @@ reset client_min_messages;
begin;
select plan(15);
select plan(17);
set search_path to auth, camper, public;
select has_function('public', 'set_cookie', array ['text']);
select function_lang_is('public', 'set_cookie', array ['text'], 'sql');
select function_returns('public', 'set_cookie', array ['text'], 'void');
select isnt_definer('public', 'set_cookie', array ['text']);
select volatility_is('public', 'set_cookie', array ['text'], 'stable');
select function_privs_are('public', 'set_cookie', array ['text'], 'guest', array []::text[]);
select function_privs_are('public', 'set_cookie', array ['text'], 'employee', array []::text[]);
select function_privs_are('public', 'set_cookie', array ['text'], 'admin', array []::text[]);
select function_privs_are('public', 'set_cookie', array ['text'], 'authenticator', array ['EXECUTE']);
select has_function('public', 'set_cookie', array ['text', 'text']);
select function_lang_is('public', 'set_cookie', array ['text', 'text'], 'sql');
select function_returns('public', 'set_cookie', array ['text', 'text'], 'void');
select isnt_definer('public', 'set_cookie', array ['text', 'text']);
select volatility_is('public', 'set_cookie', array ['text', 'text'], 'stable');
select function_privs_are('public', 'set_cookie', array ['text', 'text'], 'guest', array []::text[]);
select function_privs_are('public', 'set_cookie', array ['text', 'text'], 'employee', array []::text[]);
select function_privs_are('public', 'set_cookie', array ['text', 'text'], 'admin', array []::text[]);
select function_privs_are('public', 'set_cookie', array ['text', 'text'], 'authenticator', array ['EXECUTE']);
set client_min_messages to warning;
truncate company_host cascade;
truncate company_user cascade;
truncate company cascade;
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', 'employee', '44facbb30d8a419dfd4bfbc44a4b5539d4970148dfc84bed0e', current_timestamp + interval '1 month')
, (5, 'admin@tandem.blog', 'Demo', 'test', 'admin', '12af4c88b528c2ad4222e3740496ecbc58e76e26f087657524', current_timestamp + interval '1 month')
insert into auth."user" (user_id, email, name, password, cookie, cookie_expires_at)
values (1, 'demo@tandem.blog', 'Demo', 'test', '44facbb30d8a419dfd4bfbc44a4b5539d4970148dfc84bed0e', current_timestamp + interval '1 month')
, (5, 'admin@tandem.blog', 'Demo', 'test', '12af4c88b528c2ad4222e3740496ecbc58e76e26f087657524', current_timestamp + interval '1 month')
;
insert into company (company_id, business_name, vatin, trade_name, phone, email, web, address, city, province, postal_code, country_code, currency_code, default_lang_tag)
values (2, 'Company 2', 'XX123', '', '555-555-555', 'a@a', '', '', '', '', '', 'ES', 'EUR', 'ca')
, (4, 'Company 4', 'XX234', '', '666-666-666', 'b@b', '', '', '', '', '', 'FR', 'USD', 'es')
;
insert into company_user (company_id, user_id, role)
values (2, 1, 'employee')
, (4, 5, 'admin')
;
insert into company_host (company_id, host)
values (2, 'co2')
, (4, 'co4')
;
prepare user_info as
select current_user_email(), current_user_cookie(), current_user;
select current_user_email(), current_user_cookie(), current_company_id(), current_user;
select lives_ok(
$$ select set_cookie('44facbb30d8a419dfd4bfbc44a4b5539d4970148dfc84bed0e/demo@tandem.blog') $$,
$$ select set_cookie('44facbb30d8a419dfd4bfbc44a4b5539d4970148dfc84bed0e/demo@tandem.blog', 'co2') $$,
'Should run ok for a valid cookie'
);
select results_eq(
'user_info',
$$ values ('demo@tandem.blog', '44facbb30d8a419dfd4bfbc44a4b5539d4970148dfc84bed0e', 'employee'::name) $$,
$$ values ('demo@tandem.blog', '44facbb30d8a419dfd4bfbc44a4b5539d4970148dfc84bed0e', 2, 'employee'::name) $$,
'Should have updated the info with the correct user'
);
reset role;
select lives_ok(
$$ select set_cookie('12af4c88b528c2ad4222e3740496ecbc58e76e26f087657524/admin@tandem.blog') $$,
$$ select set_cookie('44facbb30d8a419dfd4bfbc44a4b5539d4970148dfc84bed0e/demo@tandem.blog', 'co4') $$,
'Should run ok for a valid cookie, even for the wrong company'
);
select results_eq(
'user_info',
$$ values ('', '', 0, 'guest'::name) $$,
'Should have updated the info as a guest user for this company'
);
reset role;
select lives_ok(
$$ select set_cookie('12af4c88b528c2ad4222e3740496ecbc58e76e26f087657524/admin@tandem.blog', 'co4') $$,
'Should run ok for a different cookie'
);
select results_eq(
'user_info',
$$ values ('admin@tandem.blog', '12af4c88b528c2ad4222e3740496ecbc58e76e26f087657524', 'admin'::name) $$,
$$ values ('admin@tandem.blog', '12af4c88b528c2ad4222e3740496ecbc58e76e26f087657524', 4, 'admin'::name) $$,
'Should have updated the info with the other user'
);
reset role;
select lives_ok(
$$ select set_cookie('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/admin@tandem.blog') $$,
$$ select set_cookie('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/admin@tandem.blog', 'asth') $$,
'Should run ok even for an invalid cookie'
);
select results_eq(
'user_info',
$$ values ('', '', 'guest'::name) $$,
$$ values ('', '', 0, 'guest'::name) $$,
'Should have updated the info as a guest user'
);

View File

@ -5,7 +5,7 @@ reset client_min_messages;
begin;
select plan(56);
select plan(52);
set search_path to auth, public;
@ -45,11 +45,6 @@ select col_type_is('user', 'password', 'text');
select col_not_null('user', 'password');
select col_hasnt_default('user', 'password');
select has_column('user', 'role');
select col_type_is('user', 'role', 'name');
select col_not_null('user', 'role');
select col_hasnt_default('user', 'role');
select has_column('user', 'lang_tag');
select col_is_fk('user', 'lang_tag');
select fk_ok('user', 'lang_tag', 'language', 'lang_tag');

View File

@ -59,34 +59,51 @@ select column_privs_are('user_profile', 'csrf_token', 'authenticator', array []:
set client_min_messages to warning;
truncate company_host cascade;
truncate company_user cascade;
truncate company cascade;
truncate auth."user" cascade;
reset client_min_messages;
insert into auth."user" (user_id, email, name, password, role, cookie, cookie_expires_at, lang_tag)
values (1, 'demo@tandem.blog', 'Demo', 'test', 'employee', '44facbb30d8a419dfd4bfbc44a4b5539d4970148dfc84bed0e',
current_timestamp + interval '1 month', 'ca')
, (5, 'admin@tandem.blog', 'Admin', 'test', 'admin', '12af4c88b528c2ad4222e3740496ecbc58e76e26f087657524',
current_timestamp + interval '1 month', 'es')
, (7, 'another@tandem.blog', 'Another Admin', 'test', 'admin', default, default, default)
insert into auth."user" (user_id, email, name, password, cookie, cookie_expires_at, lang_tag)
values (1, 'demo@tandem.blog', 'Demo', 'test', '44facbb30d8a419dfd4bfbc44a4b5539d4970148dfc84bed0e', current_timestamp + interval '1 month', 'ca')
, (5, 'admin@tandem.blog', 'Admin', 'test', '12af4c88b528c2ad4222e3740496ecbc58e76e26f087657524', current_timestamp + interval '1 month', 'es')
, (7, 'another@tandem.blog', 'Another Admin', 'test', default, default, default)
;
insert into company (company_id, business_name, vatin, trade_name, phone, email, web, address, city, province, postal_code, country_code, currency_code, default_lang_tag)
values (2, 'Company 2', 'XX123', '', '555-555-555', 'a@a', '', '', '', '', '', 'ES', 'EUR', 'ca')
, (4, 'Company 4', 'XX234', '', '666-666-666', 'b@b', '', '', '', '', '', 'FR', 'USD', 'es')
;
insert into company_user (company_id, user_id, role)
values (2, 1, 'employee')
, (4, 5, 'admin')
, (4, 7, 'admin')
;
insert into company_host (company_id, host)
values (2, 'co2')
, (4, 'co4')
;
prepare profile as
select user_id, email, name, role, lang_tag, csrf_token
select user_id, company_id, email, name, role, lang_tag, csrf_token
from user_profile;
select set_config('request.user.cookie', '', false);
select results_eq(
'profile',
$$ values (0, null::email, '', 'guest'::name, 'und', '') $$,
$$ values (0, 0, null::email, '', 'guest'::name, 'und', '') $$,
'Should be set up with the guest user when no user logged in yet.'
);
select set_cookie('44facbb30d8a419dfd4bfbc44a4b5539d4970148dfc84bed0e/demo@tandem.blog');
select set_cookie('44facbb30d8a419dfd4bfbc44a4b5539d4970148dfc84bed0e/demo@tandem.blog', 'co2');
select results_eq(
'profile',
$$ values (1, 'demo@tandem.blog'::email, 'Demo', 'employee'::name, 'ca', '44facbb30d') $$,
$$ values (1, 2, 'demo@tandem.blog'::email, 'Demo', 'employee'::name, 'ca', '44facbb30d') $$,
'Should only see the profile of the first user'
);
@ -113,17 +130,17 @@ select throws_ok(
select results_eq(
'profile',
$$ values (1, 'demo+update@tandem.blog'::email, 'Demo Update', 'employee'::name, 'es', '44facbb30d') $$,
$$ values (1, 2, 'demo+update@tandem.blog'::email, 'Demo Update', 'employee'::name, 'es', '44facbb30d') $$,
'Should see the changed profile of the first user'
);
reset role;
select set_cookie('12af4c88b528c2ad4222e3740496ecbc58e76e26f087657524/admin@tandem.blog');
select set_cookie('12af4c88b528c2ad4222e3740496ecbc58e76e26f087657524/admin@tandem.blog', 'co4');
select results_eq(
'profile',
$$ values (5, 'admin@tandem.blog'::email, 'Admin', 'admin'::name, 'es', '12af4c88b5') $$,
$$ values (5, 4, 'admin@tandem.blog'::email, 'Admin', 'admin'::name, 'es', '12af4c88b5') $$,
'Should only see the profile of the second user'
);
@ -150,7 +167,7 @@ select throws_ok(
select results_eq(
'profile',
$$ values (5, 'admin+update@tandem.blog'::email, 'Admin Update', 'admin'::name, 'ca', '12af4c88b5') $$,
$$ values (5, 4, 'admin+update@tandem.blog'::email, 'Admin Update', 'admin'::name, 'ca', '12af4c88b5') $$,
'Should see the changed profile of the first user'
);

View File

@ -12,6 +12,9 @@ from camper.campsite_type
where false;
select 1 / count(*) from pg_class where oid = 'camper.campsite_type'::regclass and relrowsecurity;
select 1 / count(*) from pg_policy where polname = 'company_policy' and polrelid = 'camper.campsite_type'::regclass;
select 1 / count(*) from pg_policy where polname = 'guest_ok' and polrelid = 'camper.campsite_type'::regclass;
select 1 / count(*) from pg_policy where polname = 'insert_to_company' and polrelid = 'camper.campsite_type'::regclass;
select 1 / count(*) from pg_policy where polname = 'update_company' and polrelid = 'camper.campsite_type'::regclass;
select 1 / count(*) from pg_policy where polname = 'delete_from_company' and polrelid = 'camper.campsite_type'::regclass;
rollback;

View File

@ -2,6 +2,6 @@
begin;
select has_function_privilege('public.check_cookie(text)', 'execute');
select has_function_privilege('public.check_cookie(text, text)', 'execute');
rollback;

View File

@ -4,10 +4,8 @@ begin;
select company_id
, user_id
, role
from camper.company_user
where false;
select 1 / count(*) from pg_class where oid = 'camper.company'::regclass and relrowsecurity;
select 1 / count(*) from pg_policy where polname = 'company_policy' and polrelid = 'camper.company'::regclass;
rollback;

View File

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

View File

@ -2,13 +2,13 @@
begin;
select has_function_privilege('auth.ensure_role_exists()', 'execute');
select has_function_privilege('camper.ensure_role_exists()', 'execute');
select 1 / count(*)
from pg_trigger
where not tgisinternal
and tgname = 'ensure_role_exists'
and tgrelid = 'auth.user'::regclass
and tgrelid = 'camper.company_user'::regclass
and tgtype = b'00010101'::int;
-- │││││││
-- ││││││└─> row

View File

@ -0,0 +1,10 @@
-- Verify camper:policies_company on pg
begin;
set search_path to camper, public;
select 1 / count(*) from pg_class where oid = 'company'::regclass and relrowsecurity;
select 1 / count(*) from pg_policy where polname = 'guest_ok' and polrelid = 'company'::regclass;
select 1 / count(*) from pg_policy where polname = 'update_company' and polrelid = 'company'::regclass;
rollback;

View File

@ -2,6 +2,6 @@
begin;
select has_function_privilege('public.set_cookie(text)', 'execute');
select has_function_privilege('public.set_cookie(text, text)', 'execute');
rollback;

View File

@ -6,7 +6,6 @@ select user_id
, email
, name
, password
, role
, lang_tag
, cookie
, cookie_expires_at