diff --git a/rest-api/db/migrations/20240827090504_categories_and_publication.sql b/rest-api/db/migrations/20240827090504_categories_and_publication.sql new file mode 100644 index 0000000..688f420 --- /dev/null +++ b/rest-api/db/migrations/20240827090504_categories_and_publication.sql @@ -0,0 +1,116 @@ +-- migrate:up +CREATE TABLE internal.docs_category ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid (), + website_id UUID REFERENCES internal.website (id) ON DELETE CASCADE NOT NULL, + user_id UUID REFERENCES internal.user (id) ON DELETE SET NULL DEFAULT (CURRENT_SETTING('request.jwt.claims', TRUE)::JSON ->> 'user_id') ::UUID, + category_name VARCHAR(50) NOT NULL CHECK (TRIM(category_name) != ''), + category_weight INTEGER CHECK (category_weight >= 0) NOT NULL, + UNIQUE (website_id, category_name), + UNIQUE (website_id, category_weight) +); + +ALTER TABLE internal.website + ADD COLUMN is_published BOOLEAN NOT NULL DEFAULT FALSE; + +ALTER TABLE internal.article + ADD COLUMN category UUID REFERENCES internal.docs_category (id) ON DELETE SET NULL; + +ALTER TABLE internal.article + ALTER COLUMN user_id SET DEFAULT (CURRENT_SETTING('request.jwt.claims', TRUE)::JSON ->> 'user_id')::UUID; + +ALTER TABLE internal.docs_category ENABLE ROW LEVEL SECURITY; + +CREATE POLICY view_categories ON internal.docs_category + FOR SELECT + USING (internal.user_has_website_access (website_id, 10)); + +CREATE POLICY update_category ON internal.docs_category + FOR UPDATE + USING (internal.user_has_website_access (website_id, 20)); + +CREATE POLICY delete_category ON internal.docs_category + FOR DELETE + USING (internal.user_has_website_access (website_id, 20, article_user_id => user_id)); + +CREATE POLICY insert_category ON internal.docs_category + FOR INSERT + WITH CHECK (internal.user_has_website_access (website_id, 20)); + +CREATE VIEW api.docs_category WITH ( security_invoker = ON +) AS +SELECT + id, + website_id, + user_id, + category_name, + category_weight +FROM + internal.docs_category; + +CREATE OR REPLACE VIEW api.article WITH ( security_invoker = ON +) AS +SELECT + id, + website_id, + user_id, + title, + meta_description, + meta_author, + cover_image, + publication_date, + main_content, + created_at, + last_modified_at, + last_modified_by, + category -- New column +FROM + internal.article; + +GRANT SELECT, INSERT, UPDATE, DELETE ON internal.docs_category TO authenticated_user; + +GRANT SELECT, INSERT, UPDATE, DELETE ON api.docs_category TO authenticated_user; + +GRANT SELECT, INSERT, UPDATE, DELETE ON api.article TO authenticated_user; + +-- migrate:down +DROP POLICY view_categories ON internal.docs_category; + +DROP POLICY update_category ON internal.docs_category; + +DROP POLICY delete_category ON internal.docs_category; + +DROP POLICY insert_category ON internal.docs_category; + +DROP VIEW api.article; + +CREATE VIEW api.article WITH ( security_invoker = ON +) AS +SELECT + id, + website_id, + user_id, + title, + meta_description, + meta_author, + cover_image, + publication_date, + main_content, + created_at, + last_modified_at, + last_modified_by +FROM + internal.article; + +DROP VIEW api.docs_category; + +ALTER TABLE internal.article + DROP COLUMN category; + +DROP TABLE internal.docs_category; + +ALTER TABLE internal.website + DROP COLUMN is_published; + +ALTER TABLE internal.article + ALTER COLUMN user_id DROP DEFAULT; + diff --git a/web-app/src/lib/components/WebsiteEditor.svelte b/web-app/src/lib/components/WebsiteEditor.svelte index 47da211..9715784 100644 --- a/web-app/src/lib/components/WebsiteEditor.svelte +++ b/web-app/src/lib/components/WebsiteEditor.svelte @@ -5,6 +5,7 @@ const { id, + contentType, title, children, fullPreview = false, @@ -12,6 +13,7 @@ previewScrollTop = 0 }: { id: string; + contentType: string; title: string; children: Snippet; fullPreview?: boolean; @@ -41,6 +43,9 @@
  • Articles
  • + {#if contentType === "Docs"} + Categories + {/if}
  • Collaborators
  • diff --git a/web-app/src/lib/templates/blog/BlogArticle.svelte b/web-app/src/lib/templates/blog/BlogArticle.svelte index 9e076d1..262dc87 100644 --- a/web-app/src/lib/templates/blog/BlogArticle.svelte +++ b/web-app/src/lib/templates/blog/BlogArticle.svelte @@ -1,7 +1,7 @@ - + - +