Manage collaborators via RLS

This commit is contained in:
thiloho
2024-08-07 19:13:39 +02:00
parent 75aac7b1bc
commit fbadbb18a4
4 changed files with 105 additions and 193 deletions

View File

@@ -9,244 +9,157 @@ ALTER TABLE internal.article ENABLE ROW LEVEL SECURITY;
ALTER TABLE internal.footer ENABLE ROW LEVEL SECURITY;
ALTER TABLE internal.collab ENABLE ROW LEVEL SECURITY;
CREATE FUNCTION internal.user_has_website_access(website_id UUID, required_permission INTEGER DEFAULT 10)
RETURNS BOOLEAN AS $$
DECLARE
_user_id UUID;
_has_access BOOLEAN;
BEGIN
_user_id := (current_setting('request.jwt.claims', true)::json->>'user_id')::UUID;
SELECT EXISTS (
SELECT 1
FROM internal.website
WHERE id = website_id AND owner_id = _user_id
) INTO _has_access;
IF _has_access THEN
RETURN _has_access;
END IF;
SELECT EXISTS (
SELECT 1
FROM internal.collab c
WHERE c.website_id = user_has_website_access.website_id
AND c.user_id = (current_setting('request.jwt.claims', true)::json->>'user_id')::UUID
AND c.permission_level >= user_has_website_access.required_permission
) INTO _has_access;
RETURN _has_access;
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;
CREATE POLICY view_user ON internal.user
FOR SELECT
USING (true);
CREATE POLICY view_own_websites ON internal.website
CREATE POLICY view_websites ON internal.website
FOR SELECT
USING (owner_id = (current_setting('request.jwt.claims', true)::json->>'user_id')::UUID);
USING (internal.user_has_website_access(id, 10));
CREATE POLICY update_own_website ON internal.website
CREATE POLICY update_website ON internal.website
FOR UPDATE
USING (owner_id = (current_setting('request.jwt.claims', true)::json->>'user_id')::UUID);
USING (internal.user_has_website_access(id, 20));
CREATE POLICY delete_own_website ON internal.website
CREATE POLICY delete_website ON internal.website
FOR DELETE
USING (owner_id = (current_setting('request.jwt.claims', true)::json->>'user_id')::UUID);
USING (internal.user_has_website_access(id, 40));
CREATE POLICY view_own_media ON internal.media
CREATE POLICY view_media ON internal.media
FOR SELECT
USING (user_id = (current_setting('request.jwt.claims', true)::json->>'user_id')::UUID);
USING (internal.user_has_website_access(website_id, 10));
CREATE POLICY insert_own_media ON internal.media
CREATE POLICY insert_media ON internal.media
FOR INSERT
WITH CHECK (
EXISTS (
SELECT 1
FROM internal.website
WHERE internal.website.id = internal.media.website_id
AND internal.website.owner_id = (current_setting('request.jwt.claims', true)::json->>'user_id')::UUID
)
);
WITH CHECK (internal.user_has_website_access(website_id, 20));
CREATE POLICY view_own_settings ON internal.settings
CREATE POLICY view_settings ON internal.settings
FOR SELECT
USING (
EXISTS (
SELECT 1
FROM internal.website
WHERE internal.website.id = internal.settings.website_id
AND internal.website.owner_id = (current_setting('request.jwt.claims', true)::json->>'user_id')::UUID
)
);
USING (internal.user_has_website_access(website_id, 10));
CREATE POLICY update_own_settings ON internal.settings
CREATE POLICY update_settings ON internal.settings
FOR UPDATE
USING (
EXISTS (
SELECT 1
FROM internal.website
WHERE internal.website.id = internal.settings.website_id
AND internal.website.owner_id = (current_setting('request.jwt.claims', true)::json->>'user_id')::UUID
)
);
USING (internal.user_has_website_access(website_id, 20));
CREATE POLICY view_own_header ON internal.header
CREATE POLICY view_header ON internal.header
FOR SELECT
USING (
EXISTS (
SELECT 1
FROM internal.website
WHERE internal.website.id = internal.header.website_id
AND internal.website.owner_id = (current_setting('request.jwt.claims', true)::json->>'user_id')::UUID
)
);
USING (internal.user_has_website_access(website_id, 10));
CREATE POLICY update_own_header ON internal.header
CREATE POLICY update_header ON internal.header
FOR UPDATE
USING (
EXISTS (
SELECT 1
FROM internal.website
WHERE internal.website.id = internal.header.website_id
AND internal.website.owner_id = (current_setting('request.jwt.claims', true)::json->>'user_id')::UUID
)
);
USING (internal.user_has_website_access(website_id, 20));
CREATE POLICY view_own_home ON internal.home
CREATE POLICY view_home ON internal.home
FOR SELECT
USING (
EXISTS (
SELECT 1
FROM internal.website
WHERE internal.website.id = internal.home.website_id
AND internal.website.owner_id = (current_setting('request.jwt.claims', true)::json->>'user_id')::UUID
)
);
USING (internal.user_has_website_access(website_id, 10));
CREATE POLICY update_own_home ON internal.home
CREATE POLICY update_home ON internal.home
FOR UPDATE
USING (
EXISTS (
SELECT 1
FROM internal.website
WHERE internal.website.id = internal.home.website_id
AND internal.website.owner_id = (current_setting('request.jwt.claims', true)::json->>'user_id')::UUID
)
);
USING (internal.user_has_website_access(website_id, 20));
CREATE POLICY view_own_articles ON internal.article
CREATE POLICY view_articles ON internal.article
FOR SELECT
USING (
EXISTS (
SELECT 1
FROM internal.website
WHERE internal.website.id = internal.article.website_id
AND internal.website.owner_id = (current_setting('request.jwt.claims', true)::json->>'user_id')::UUID
)
);
USING (internal.user_has_website_access(website_id, 10));
CREATE POLICY update_own_article ON internal.article
CREATE POLICY update_article ON internal.article
FOR UPDATE
USING (
EXISTS (
SELECT 1
FROM internal.website
WHERE internal.website.id = internal.article.website_id
AND internal.website.owner_id = (current_setting('request.jwt.claims', true)::json->>'user_id')::UUID
)
);
USING (internal.user_has_website_access(website_id, 20));
CREATE POLICY delete_own_article ON internal.article
CREATE POLICY delete_article ON internal.article
FOR DELETE
USING (
EXISTS (
SELECT 1
FROM internal.website
WHERE internal.website.id = internal.article.website_id
AND internal.website.owner_id = (current_setting('request.jwt.claims', true)::json->>'user_id')::UUID
)
);
USING (internal.user_has_website_access(website_id, 30));
CREATE POLICY insert_own_article ON internal.article
CREATE POLICY insert_article ON internal.article
FOR INSERT
WITH CHECK (
EXISTS (
SELECT 1
FROM internal.website
WHERE internal.website.id = internal.article.website_id
AND internal.website.owner_id = (current_setting('request.jwt.claims', true)::json->>'user_id')::UUID
)
);
WITH CHECK (internal.user_has_website_access(website_id, 20));
CREATE POLICY view_own_footer ON internal.footer
CREATE POLICY view_footer ON internal.footer
FOR SELECT
USING (
EXISTS (
SELECT 1
FROM internal.website
WHERE internal.website.id = internal.footer.website_id
AND internal.website.owner_id = (current_setting('request.jwt.claims', true)::json->>'user_id')::UUID
)
);
USING (internal.user_has_website_access(website_id, 10));
CREATE POLICY update_own_footer ON internal.footer
CREATE POLICY update_footer ON internal.footer
FOR UPDATE
USING (
EXISTS (
SELECT 1
FROM internal.website
WHERE internal.website.id = internal.footer.website_id
AND internal.website.owner_id = (current_setting('request.jwt.claims', true)::json->>'user_id')::UUID
)
);
USING (internal.user_has_website_access(website_id, 20));
CREATE POLICY view_collaborations ON internal.collab
FOR SELECT
USING (
EXISTS (
SELECT 1
FROM internal.website
WHERE internal.website.id = internal.collab.website_id
AND internal.website.owner_id = (current_setting('request.jwt.claims', true)::json->>'user_id')::UUID
)
);
USING (internal.user_has_website_access(website_id, 10));
CREATE POLICY insert_collaborations ON internal.collab
FOR INSERT
WITH CHECK (
EXISTS (
SELECT 1
FROM internal.website
WHERE internal.website.id = internal.collab.website_id
AND internal.website.owner_id = (current_setting('request.jwt.claims', true)::json->>'user_id')::UUID
)
);
WITH CHECK (internal.user_has_website_access(website_id, 30));
CREATE POLICY update_collaborations ON internal.collab
FOR UPDATE
USING (
EXISTS (
SELECT 1
FROM internal.website
WHERE internal.website.id = internal.collab.website_id
AND internal.website.owner_id = (current_setting('request.jwt.claims', true)::json->>'user_id')::UUID
)
);
USING (internal.user_has_website_access(website_id, 30));
CREATE POLICY delete_collaborations ON internal.collab
FOR DELETE
USING (
EXISTS (
SELECT 1
FROM internal.website
WHERE internal.website.id = internal.collab.website_id
AND internal.website.owner_id = (current_setting('request.jwt.claims', true)::json->>'user_id')::UUID
)
);
USING (internal.user_has_website_access(website_id, 30));
-- migrate:down
DROP POLICY view_user ON internal.user;
DROP POLICY view_own_websites ON internal.website;
DROP POLICY delete_own_website ON internal.website;
DROP POLICY update_own_website ON internal.website;
DROP POLICY view_own_media ON internal.media;
DROP POLICY insert_own_media ON internal.media;
DROP POLICY view_own_settings ON internal.settings;
DROP POLICY update_own_settings ON internal.settings;
DROP POLICY view_own_header ON internal.header;
DROP POLICY update_own_header ON internal.header;
DROP POLICY view_own_home ON internal.home;
DROP POLICY update_own_home ON internal.home;
DROP POLICY view_own_articles ON internal.article;
DROP POLICY update_own_article ON internal.article;
DROP POLICY delete_own_article ON internal.article;
DROP POLICY insert_own_article ON internal.article;
DROP POLICY view_own_footer ON internal.footer;
DROP POLICY update_own_footer ON internal.footer;
DROP POLICY view_websites ON internal.website;
DROP POLICY delete_website ON internal.website;
DROP POLICY update_website ON internal.website;
DROP POLICY view_media ON internal.media;
DROP POLICY insert_media ON internal.media;
DROP POLICY view_settings ON internal.settings;
DROP POLICY update_settings ON internal.settings;
DROP POLICY view_header ON internal.header;
DROP POLICY update_header ON internal.header;
DROP POLICY view_home ON internal.home;
DROP POLICY update_home ON internal.home;
DROP POLICY view_articles ON internal.article;
DROP POLICY update_article ON internal.article;
DROP POLICY delete_article ON internal.article;
DROP POLICY insert_article ON internal.article;
DROP POLICY view_footer ON internal.footer;
DROP POLICY update_footer ON internal.footer;
DROP POLICY view_collaborations ON internal.collab;
DROP POLICY insert_collaborations ON internal.collab;
DROP POLICY update_collaborations ON internal.collab;
DROP POLICY delete_collaborations ON internal.collab;
DROP FUNCTION internal.user_has_website_access(UUID, INTEGER);
ALTER TABLE internal.user DISABLE ROW LEVEL SECURITY;
ALTER TABLE internal.website DISABLE ROW LEVEL SECURITY;