Skip to content

Commit

Permalink
Merge pull request #44 from maevsi/fix/uuid-null
Browse files Browse the repository at this point in the history
fix: account for empty account id
  • Loading branch information
dargmuesli authored Nov 3, 2023
2 parents 1347c53 + cd846a2 commit a340922
Show file tree
Hide file tree
Showing 17 changed files with 190 additions and 62 deletions.
102 changes: 68 additions & 34 deletions schema/schema.definition.sql

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion src/deploy/function_account_delete.sql
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ CREATE FUNCTION maevsi.account_delete(
DECLARE
_current_account_id UUID;
BEGIN
_current_account_id := current_setting('jwt.claims.account_id', true)::UUID;
_current_account_id := current_setting('jwt.claims.account_id')::UUID;

IF (EXISTS (SELECT 1 FROM maevsi_private.account WHERE account.id = _current_account_id AND account.password_hash = maevsi.crypt($1, account.password_hash))) THEN
IF (EXISTS (SELECT 1 FROM maevsi.event WHERE event.author_account_id = _current_account_id)) THEN
Expand Down
2 changes: 1 addition & 1 deletion src/deploy/function_account_password_change.sql
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ BEGIN
RAISE 'New password too short!' USING ERRCODE = 'invalid_parameter_value';
END IF;

_current_account_id := current_setting('jwt.claims.account_id', true)::UUID;
_current_account_id := current_setting('jwt.claims.account_id')::UUID;

IF (EXISTS (SELECT 1 FROM maevsi_private.account WHERE account.id = _current_account_id AND account.password_hash = maevsi.crypt($1, account.password_hash))) THEN
UPDATE maevsi_private.account SET password_hash = maevsi.crypt($2, maevsi.gen_salt('bf')) WHERE account.id = _current_account_id;
Expand Down
2 changes: 1 addition & 1 deletion src/deploy/function_account_upload_quota_bytes.sql
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ BEGIN;

CREATE FUNCTION maevsi.account_upload_quota_bytes() RETURNS BIGINT AS $$
BEGIN
RETURN (SELECT upload_quota_bytes FROM maevsi_private.account WHERE account.id = current_setting('jwt.claims.account_id', true)::UUID);
RETURN (SELECT upload_quota_bytes FROM maevsi_private.account WHERE account.id = current_setting('jwt.claims.account_id')::UUID);
END;
$$ LANGUAGE PLPGSQL STRICT STABLE SECURITY DEFINER;

Expand Down
2 changes: 1 addition & 1 deletion src/deploy/function_event_delete.sql
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ DECLARE
_current_account_id UUID;
_event_deleted maevsi.event;
BEGIN
_current_account_id := current_setting('jwt.claims.account_id', true)::UUID;
_current_account_id := current_setting('jwt.claims.account_id')::UUID;

IF (EXISTS (SELECT 1 FROM maevsi_private.account WHERE account.id = _current_account_id AND account.password_hash = maevsi.crypt($2, account.password_hash))) THEN
DELETE
Expand Down
6 changes: 5 additions & 1 deletion src/deploy/function_event_invitee_count_maximum.sql
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,11 @@ BEGIN
"event".invitee_count_maximum > (maevsi.invitee_count(id)) -- Using the function here is required as there would otherwise be infinite recursion.
)
)
OR "event".author_account_id = current_setting('jwt.claims.account_id', true)::UUID
OR (
NULLIF(current_setting('jwt.claims.account_id', true), '')::UUID IS NOT NULL
AND
"event".author_account_id = NULLIF(current_setting('jwt.claims.account_id', true), '')::UUID
)
OR "event".id IN (SELECT maevsi_private.events_invited())
)
);
Expand Down
13 changes: 8 additions & 5 deletions src/deploy/function_event_unlock.sql
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ BEGIN
_jwt_id := current_setting('jwt.claims.id', true)::UUID;
_jwt := (
_jwt_id,
current_setting('jwt.claims.account_id', true)::UUID,
NULLIF(current_setting('jwt.claims.account_id', true), '')::UUID, -- prevent empty string cast to UUID
current_setting('jwt.claims.account_username', true)::TEXT,
current_setting('jwt.claims.exp', true)::BIGINT,
(SELECT ARRAY(SELECT DISTINCT UNNEST(maevsi.invitation_claim_array() || $1) ORDER BY 1)),
Expand All @@ -43,17 +43,20 @@ BEGIN
RAISE 'No invitation for this invitation id found!' USING ERRCODE = 'no_data_found';
END IF;

_event := (
SELECT author_account_id, slug
SELECT *
FROM maevsi.event
WHERE id = _event_id
);
INTO _event;

IF (_event IS NULL) THEN
RAISE 'No event for this invitation id found!' USING ERRCODE = 'no_data_found';
END IF;

_event_author_account_username := maevsi.account_username_by_id(_event.author_account_id);
_event_author_account_username := (
SELECT username
FROM maevsi.account
WHERE id = _event.author_account_id
);

IF (_event_author_account_username IS NULL) THEN
RAISE 'No event author username for this invitation id found!' USING ERRCODE = 'no_data_found';
Expand Down
13 changes: 12 additions & 1 deletion src/deploy/function_events_invited.sql
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,22 @@ BEGIN;

CREATE FUNCTION maevsi_private.events_invited()
RETURNS TABLE (event_id UUID) AS $$
DECLARE
jwt_account_id UUID;
BEGIN
jwt_account_id := NULLIF(current_setting('jwt.claims.account_id', true), '')::UUID;

RETURN QUERY
SELECT invitation.event_id FROM maevsi.invitation
WHERE
invitation.contact_id IN (SELECT id FROM maevsi.contact WHERE contact.account_id = current_setting('jwt.claims.account_id', true)::UUID) -- The contact selection does not return rows where account_id "IS" null due to the equality comparison.
invitation.contact_id IN (
SELECT id
FROM maevsi.contact
WHERE
jwt_account_id IS NOT NULL
AND
contact.account_id = jwt_account_id
) -- The contact selection does not return rows where account_id "IS" null due to the equality comparison.
OR invitation.id = ANY (maevsi.invitation_claim_array());
END
$$ LANGUAGE PLPGSQL STRICT STABLE SECURITY DEFINER;
Expand Down
9 changes: 8 additions & 1 deletion src/deploy/function_events_organized.sql
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,17 @@ BEGIN;

CREATE FUNCTION maevsi.events_organized()
RETURNS TABLE (event_id UUID) AS $$
DECLARE
account_id UUID;
BEGIN
account_id := NULLIF(current_setting('jwt.claims.account_id', true), '')::UUID;

RETURN QUERY
SELECT id FROM maevsi.event
WHERE "event".author_account_id = current_setting('jwt.claims.account_id', true)::UUID;
WHERE
account_id IS NOT NULL
AND
"event".author_account_id = account_id;
END
$$ LANGUAGE PLPGSQL STRICT STABLE SECURITY DEFINER;

Expand Down
2 changes: 1 addition & 1 deletion src/deploy/function_profile_picture_set.sql
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ CREATE FUNCTION maevsi.profile_picture_set(
BEGIN
INSERT INTO maevsi.profile_picture(account_id, upload_id)
VALUES (
current_setting('jwt.claims.account_id', true)::UUID,
current_setting('jwt.claims.account_id')::UUID,
$1
)
ON CONFLICT (account_id)
Expand Down
6 changes: 3 additions & 3 deletions src/deploy/function_upload_create.sql
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,14 @@ BEGIN
IF (COALESCE((
SELECT SUM(upload.size_byte)
FROM maevsi.upload
WHERE upload.account_id = current_setting('jwt.claims.account_id', true)::UUID
WHERE upload.account_id = current_setting('jwt.claims.account_id')::UUID
), 0) + $1 <= (
SELECT upload_quota_bytes
FROM maevsi_private.account
WHERE account.id = current_setting('jwt.claims.account_id', true)::UUID
WHERE account.id = current_setting('jwt.claims.account_id')::UUID
)) THEN
INSERT INTO maevsi.upload(account_id, size_byte)
VALUES (current_setting('jwt.claims.account_id', true)::UUID, $1)
VALUES (current_setting('jwt.claims.account_id')::UUID, $1)
RETURNING upload.id INTO _upload;

RETURN _upload;
Expand Down
17 changes: 15 additions & 2 deletions src/deploy/table_contact_policy.sql
Original file line number Diff line number Diff line change
Expand Up @@ -16,23 +16,36 @@ ALTER TABLE maevsi.contact ENABLE ROW LEVEL SECURITY;
-- Only display contacts authored by the invoker's account.
-- Only display contacts for which an accessible invitation exists.
CREATE POLICY contact_select ON maevsi.contact FOR SELECT USING (
(
NULLIF(current_setting('jwt.claims.account_id', true), '')::UUID IS NOT NULL
AND (
account_id = current_setting('jwt.claims.account_id', true)::UUID
OR author_account_id = current_setting('jwt.claims.account_id', true)::UUID
OR id IN (SELECT maevsi.invitation_contact_ids())
OR
author_account_id = current_setting('jwt.claims.account_id', true)::UUID
)
)
OR
id IN (SELECT maevsi.invitation_contact_ids())
);

-- Only allow inserts for contacts authored by the invoker's account.
CREATE POLICY contact_insert ON maevsi.contact FOR INSERT WITH CHECK (
NULLIF(current_setting('jwt.claims.account_id', true), '')::UUID IS NOT NULL
AND
author_account_id = current_setting('jwt.claims.account_id', true)::UUID
);

-- Only allow updates for contacts authored by the invoker's account.
CREATE POLICY contact_update ON maevsi.contact FOR UPDATE USING (
NULLIF(current_setting('jwt.claims.account_id', true), '')::UUID IS NOT NULL
AND
author_account_id = current_setting('jwt.claims.account_id', true)::UUID
);

-- Only allow deletes for contacts authored by the invoker's account except for the own account's contact.
CREATE POLICY contact_delete ON maevsi.contact FOR DELETE USING (
NULLIF(current_setting('jwt.claims.account_id', true), '')::UUID IS NOT NULL
AND
author_account_id = current_setting('jwt.claims.account_id', true)::UUID
AND
account_id IS DISTINCT FROM current_setting('jwt.claims.account_id', true)::UUID
Expand Down
10 changes: 9 additions & 1 deletion src/deploy/table_event_policy.sql
Original file line number Diff line number Diff line change
Expand Up @@ -27,17 +27,25 @@ CREATE POLICY event_select ON maevsi.event FOR SELECT USING (
invitee_count_maximum > (maevsi.invitee_count(id)) -- Using the function here is required as there would otherwise be infinite recursion.
)
)
OR author_account_id = current_setting('jwt.claims.account_id', true)::UUID
OR (
NULLIF(current_setting('jwt.claims.account_id', true), '')::UUID IS NOT NULL
AND
author_account_id = current_setting('jwt.claims.account_id', true)::UUID
)
OR id IN (SELECT maevsi_private.events_invited())
);

-- Only allow inserts for events authored by the current user.
CREATE POLICY event_insert ON maevsi.event FOR INSERT WITH CHECK (
NULLIF(current_setting('jwt.claims.account_id', true), '')::UUID IS NOT NULL
AND
author_account_id = current_setting('jwt.claims.account_id', true)::UUID
);

-- Only allow updates for events authored by the current user.
CREATE POLICY event_update ON maevsi.event FOR UPDATE USING (
NULLIF(current_setting('jwt.claims.account_id', true), '')::UUID IS NOT NULL
AND
author_account_id = current_setting('jwt.claims.account_id', true)::UUID
);

Expand Down
44 changes: 40 additions & 4 deletions src/deploy/table_invitation_policy.sql
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,16 @@ ALTER TABLE maevsi.invitation ENABLE ROW LEVEL SECURITY;
-- Only display invitations to events organized by oneself.
CREATE POLICY invitation_select ON maevsi.invitation FOR SELECT USING (
id = ANY (maevsi.invitation_claim_array())
OR contact_id IN (SELECT id FROM maevsi.contact WHERE contact.account_id = current_setting('jwt.claims.account_id', true)::UUID)
OR
(
NULLIF(current_setting('jwt.claims.account_id', true), '')::UUID IS NOT NULL
AND
contact_id IN (
SELECT id
FROM maevsi.contact
WHERE contact.account_id = current_setting('jwt.claims.account_id', true)::UUID
)
)
OR event_id IN (SELECT maevsi.events_organized())
);

Expand All @@ -33,15 +42,33 @@ CREATE POLICY invitation_insert ON maevsi.invitation FOR INSERT WITH CHECK (
OR
maevsi.event_invitee_count_maximum(event_id) > maevsi.invitee_count(event_id)
)
AND contact_id IN (SELECT id FROM maevsi.contact WHERE contact.author_account_id = current_setting('jwt.claims.account_id', true)::UUID)
AND
(
NULLIF(current_setting('jwt.claims.account_id', true), '')::UUID IS NOT NULL
AND
contact_id IN (
SELECT id
FROM maevsi.contact
WHERE contact.author_account_id = current_setting('jwt.claims.account_id', true)::UUID
)
)
);

-- Only allow updates to invitations issued to oneself through invitation claims.
-- Only allow updates to invitations issued to oneself through the account.
-- Only allow updates to invitations to events organized by oneself.
CREATE POLICY invitation_update ON maevsi.invitation FOR UPDATE USING (
id = ANY (maevsi.invitation_claim_array())
OR contact_id IN (SELECT id FROM maevsi.contact WHERE contact.account_id = current_setting('jwt.claims.account_id', true)::UUID)
OR
(
NULLIF(current_setting('jwt.claims.account_id', true), '')::UUID IS NOT NULL
AND
contact_id IN (
SELECT id
FROM maevsi.contact
WHERE contact.account_id = current_setting('jwt.claims.account_id', true)::UUID
)
)
OR event_id IN (SELECT maevsi.events_organized())
);

Expand All @@ -58,7 +85,16 @@ BEGIN
TG_OP = 'UPDATE'
AND ( -- Invited.
OLD.id = ANY (maevsi.invitation_claim_array())
OR OLD.contact_id IN (SELECT id FROM maevsi.contact WHERE contact.account_id = current_setting('jwt.claims.account_id', true)::UUID)
OR
(
NULLIF(current_setting('jwt.claims.account_id', true), '')::UUID IS NOT NULL
AND
OLD.contact_id IN (
SELECT id
FROM maevsi.contact
WHERE contact.account_id = current_setting('jwt.claims.account_id', true)::UUID
)
)
)
AND
EXISTS (
Expand Down
10 changes: 9 additions & 1 deletion src/deploy/table_profile_picture.sql
Original file line number Diff line number Diff line change
Expand Up @@ -32,19 +32,27 @@ CREATE POLICY profile_picture_select ON maevsi.profile_picture FOR SELECT USING

-- Only allow inserts with a account id that matches the invoker's account id.
CREATE POLICY profile_picture_insert ON maevsi.profile_picture FOR INSERT WITH CHECK (
NULLIF(current_setting('jwt.claims.account_id', true), '')::UUID IS NOT NULL
AND
account_id = current_setting('jwt.claims.account_id', true)::UUID
);

-- Only allow updates to the item with the account id that matches the invoker's account id.
CREATE POLICY profile_picture_update ON maevsi.profile_picture FOR UPDATE USING (
NULLIF(current_setting('jwt.claims.account_id', true), '')::UUID IS NOT NULL
AND
account_id = current_setting('jwt.claims.account_id', true)::UUID
);

-- Only allow deletes for the item with the account id that matches the invoker's account id.
CREATE POLICY profile_picture_delete ON maevsi.profile_picture FOR DELETE USING (
(SELECT current_user) = 'maevsi_tusd'
OR
account_id = current_setting('jwt.claims.account_id', true)::UUID
(
NULLIF(current_setting('jwt.claims.account_id', true), '')::UUID IS NOT NULL
AND
account_id = current_setting('jwt.claims.account_id', true)::UUID
)
);

COMMIT;
6 changes: 5 additions & 1 deletion src/deploy/table_upload_policy.sql
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,11 @@ ALTER TABLE maevsi.upload ENABLE ROW LEVEL SECURITY;
CREATE POLICY upload_select_using ON maevsi.upload FOR SELECT USING (
(SELECT current_user) = 'maevsi_tusd'
OR
account_id = current_setting('jwt.claims.account_id', true)::UUID
(
NULLIF(current_setting('jwt.claims.account_id', true), '')::UUID IS NOT NULL
AND
account_id = current_setting('jwt.claims.account_id', true)::UUID
)
OR
id IN (SELECT upload_id FROM maevsi.profile_picture)
);
Expand Down
6 changes: 3 additions & 3 deletions src/revert/table_upload_policy.sql
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

BEGIN;

DROP POLICY upload_delete ON maevsi.event;
DROP POLICY upload_select ON maevsi.event;
DROP POLICY upload_update ON maevsi.event;
DROP POLICY upload_delete_using ON maevsi.upload;
DROP POLICY upload_select_using ON maevsi.upload;
DROP POLICY upload_update_using ON maevsi.upload;

COMMIT;

0 comments on commit a340922

Please sign in to comment.