Skip to content

Commit 5fdb25b

Browse files
committed
Add public profile by column security
Now the row `lastactive` is only accessible by the admin. The public profile is accessed everywhere and in the admin view the whole profile is queried. For the me() function, we have to output a valid ctfnote.profile but we can't access the `lastactive` column, so we replace it with NULL by default. This fixes the problem we faced in the row wise security model.
1 parent faa2376 commit 5fdb25b

File tree

8 files changed

+146
-513
lines changed

8 files changed

+146
-513
lines changed
Lines changed: 24 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,9 @@
11
ALTER TABLE ctfnote.profile
22
ADD COLUMN "lastactive" timestamptz NOT NULL DEFAULT CURRENT_TIMESTAMP;
33

4-
--- Security
5-
DROP POLICY select_profile ON ctfnote.profile;
6-
CREATE POLICY select_profile_admin ON ctfnote.profile
7-
FOR SELECT TO user_admin
8-
USING (TRUE);
9-
10-
CREATE POLICY select_profile ON ctfnote.profile
11-
FOR SELECT TO user_guest
12-
USING (id = ctfnote_private.user_id ());
13-
14-
CREATE OR REPLACE VIEW ctfnote.public_profile AS
15-
SELECT
16-
"ctfnote"."profile"."id" as id,
17-
"ctfnote"."profile"."description",
18-
"ctfnote"."profile"."color",
19-
"ctfnote"."profile"."username",
20-
"ctfnote_private"."user"."role",
21-
CONCAT('profile-', "ctfnote"."profile"."id") as node_id
22-
FROM ctfnote.profile
23-
INNER JOIN "ctfnote_private"."user" ON "ctfnote_private"."user"."id" = "ctfnote"."profile"."id"
24-
ORDER BY id;
25-
26-
GRANT SELECT on ctfnote.public_profile TO user_guest;
27-
28-
CREATE OR REPLACE FUNCTION ctfnote_private.notify_profile_edit ()
29-
RETURNS TRIGGER
30-
AS $$
31-
BEGIN
32-
CASE TG_OP
33-
WHEN 'INSERT' THEN
34-
PERFORM
35-
ctfnote_private.notify ('created', 'profiles', NEW.id); RETURN NEW;
36-
WHEN 'UPDATE' THEN
37-
PERFORM
38-
ctfnote_private.notify ('update', 'public_profiles', NEW.id); RETURN NEW;
39-
WHEN 'DELETE' THEN
40-
PERFORM
41-
ctfnote_private.notify ('deleted', 'profiles', OLD.id); RETURN OLD;
42-
END CASE;
43-
END
44-
$$ VOLATILE
45-
LANGUAGE plpgsql;
4+
--- Security - Column wise
5+
GRANT SELECT (id, color, username, description) on ctfnote.profile TO user_guest;
6+
GRANT SELECT (id, color, username, description, lastactive) on ctfnote.profile TO user_admin;
467

478
/* UpdateLastActive */
489
CREATE FUNCTION ctfnote.update_last_active ()
@@ -56,15 +17,17 @@ CREATE FUNCTION ctfnote.update_last_active ()
5617
$$
5718
LANGUAGE plpgsql VOLATILE
5819
SECURITY DEFINER;
59-
GRANT EXECUTE ON FUNCTION ctfnote.update_last_active () TO user_guest;
6020

21+
GRANT EXECUTE ON FUNCTION ctfnote.update_last_active () TO user_guest;
6122

23+
--- Update me() function to not include lastactive but still return a ctfnote.profile
24+
DROP FUNCTION ctfnote.me();
6225
CREATE OR REPLACE FUNCTION ctfnote.me ()
6326
RETURNS ctfnote.profile
6427
AS $$
6528
SELECT ctfnote.update_last_active();
6629
SELECT
67-
*
30+
id, color, username, description, COALESCE(lastactive, NULL)
6831
FROM
6932
ctfnote.profile
7033
WHERE
@@ -74,3 +37,20 @@ CREATE OR REPLACE FUNCTION ctfnote.me ()
7437
$$
7538
LANGUAGE SQL
7639
STRICT STABLE;
40+
41+
GRANT EXECUTE ON FUNCTION ctfnote.me () TO user_anonymous;
42+
43+
--- Update triggers
44+
DROP TRIGGER _500_gql_update_profile ON ctfnote.profile;
45+
46+
CREATE TRIGGER _500_gql_update_profile
47+
AFTER INSERT OR DELETE ON ctfnote.profile
48+
FOR EACH ROW
49+
EXECUTE PROCEDURE ctfnote_private.notify_profile_edit ();
50+
51+
--- Exclude lastactive updates for update trigger
52+
CREATE TRIGGER _500_gql_update_profile_update
53+
AFTER UPDATE ON ctfnote.profile
54+
FOR EACH ROW
55+
WHEN (OLD.lastactive = NEW.lastactive)
56+
EXECUTE PROCEDURE ctfnote_private.notify_profile_edit ();

0 commit comments

Comments
 (0)