From 2451582dc6d17758f9e845fd2ea71aef440d5ef5 Mon Sep 17 00:00:00 2001 From: Matt Date: Mon, 26 Jan 2026 15:44:25 +0100 Subject: [PATCH] Complete database grants and update README init.sql changes: - Add INSERT grant for members table (for /join signup) - Add INSERT grant for dues_payments (for board recording payments) - Add full CRUD grants for events, documents, document_folders - Add UPDATE grant for email_templates (admin management) - Add anon role grants for public event viewing and RSVP creation README changes: - Add "Important Notes" section explaining dynamic env vars - Add first-time setup and database initialization docs - Add troubleshooting for 403 errors with grant fix commands - Add troubleshooting for "account not configured" errors Co-Authored-By: Claude Opus 4.5 --- deploy/README.md | 52 ++++++++++++++++++++++++++++++++++++++++++++++++ deploy/init.sql | 35 +++++++++++++++++++++----------- 2 files changed, 75 insertions(+), 12 deletions(-) diff --git a/deploy/README.md b/deploy/README.md index d7f95fa..3fbcfc5 100644 --- a/deploy/README.md +++ b/deploy/README.md @@ -271,6 +271,37 @@ docker run --rm -v monacousa_storage-data:/data -v $(pwd):/backup alpine \ docker compose up -d ``` +## Important Notes + +### Environment Variables + +The portal uses **dynamic environment variables** which are read at runtime. This means: +- You can change `.env` values and restart containers without rebuilding +- The pre-built Docker image works with any configuration +- JWT tokens and API keys must be generated using `./setup.sh` + +### First-Time Setup + +On first access to the portal, you'll be redirected to `/setup` where you create the initial admin account. This only happens when the `members` table is empty. + +### Database Initialization + +The `init.sql` file: +- Creates all database schemas, tables, views, and functions +- Sets up Row Level Security (RLS) policies +- Grants appropriate permissions to database roles +- Runs automatically on first container start + +If you need to reset the database: +```bash +docker compose down -v # WARNING: Deletes all data! +docker compose up -d +``` + +### Rebuilding the Portal (If Needed) + +If you're building from source instead of using the pre-built image, ensure environment variables are passed during build for static features. For most deployments, the pre-built image with runtime env vars is recommended. + ## Troubleshooting ### Containers not starting @@ -305,6 +336,27 @@ This usually means the API keys don't match. Run setup again: docker compose restart kong ``` +### API 403 Forbidden errors + +This means the database permissions (GRANTs) are missing. This is fixed in the init.sql, but if you see this on an existing deployment, run: + +```bash +docker compose exec db psql -U postgres -c " +GRANT SELECT, INSERT, UPDATE ON public.members TO authenticated; +GRANT SELECT ON public.membership_statuses TO authenticated; +GRANT SELECT ON public.membership_types TO authenticated; +GRANT SELECT ON public.members_with_dues TO authenticated; +GRANT SELECT, INSERT ON public.dues_payments TO authenticated; +GRANT SELECT, INSERT, UPDATE, DELETE ON public.events TO authenticated; +GRANT SELECT, INSERT, UPDATE, DELETE ON public.event_rsvps TO authenticated; +GRANT SELECT ON public.events_with_counts TO authenticated; +" +``` + +### "Your account is not properly configured" error + +This occurs when a user can authenticate but can't query their member profile. Usually a database permission issue - see the 403 fix above. + ### Portal not loading ```bash diff --git a/deploy/init.sql b/deploy/init.sql index 6842131..b53d9a6 100644 --- a/deploy/init.sql +++ b/deploy/init.sql @@ -243,11 +243,10 @@ GRANT ALL ON public.membership_statuses TO service_role; GRANT ALL ON public.membership_types TO service_role; GRANT ALL ON public.members TO service_role; --- Grant authenticated role read access to core tables (required for RLS to work) +-- Grant authenticated role access to core tables (required for RLS to work) GRANT SELECT ON public.membership_statuses TO authenticated; GRANT SELECT ON public.membership_types TO authenticated; -GRANT SELECT ON public.members TO authenticated; -GRANT UPDATE ON public.members TO authenticated; +GRANT SELECT, INSERT, UPDATE ON public.members TO authenticated; -- DUES PAYMENTS CREATE TABLE public.dues_payments ( @@ -629,6 +628,17 @@ LEFT JOIN LATERAL ( -- Grant view access to authenticated users GRANT SELECT ON public.events_with_counts TO authenticated; +-- ============================================ +-- TABLE GRANTS FOR ANON ROLE (public access) +-- ============================================ +-- These grants allow unauthenticated users to access public content. +-- RLS policies control what specific data can be accessed. + +GRANT SELECT ON public.events TO anon; +GRANT SELECT ON public.event_types TO anon; +GRANT SELECT, INSERT ON public.event_rsvps_public TO anon; +GRANT SELECT ON public.events_with_counts TO anon; + -- ============================================ -- TABLE GRANTS FOR AUTHENTICATED ROLE -- ============================================ @@ -636,24 +646,25 @@ GRANT SELECT ON public.events_with_counts TO authenticated; -- RLS policies control WHAT rows can be accessed, -- but GRANT controls WHETHER the table can be accessed at all. --- Core tables -GRANT SELECT ON public.dues_payments TO authenticated; +-- Dues payments (board/admin can insert via RLS policy) +GRANT SELECT, INSERT ON public.dues_payments TO authenticated; --- Events -GRANT SELECT ON public.events TO authenticated; +-- Events (board/admin can manage via RLS) +GRANT SELECT, INSERT, UPDATE, DELETE ON public.events TO authenticated; GRANT SELECT ON public.event_types TO authenticated; GRANT SELECT, INSERT, UPDATE, DELETE ON public.event_rsvps TO authenticated; -GRANT SELECT, INSERT ON public.event_rsvps_public TO authenticated; +GRANT SELECT, INSERT, UPDATE, DELETE ON public.event_rsvps_public TO authenticated; --- Documents -GRANT SELECT ON public.documents TO authenticated; +-- Documents (board/admin can manage via RLS) +GRANT SELECT, INSERT, UPDATE, DELETE ON public.documents TO authenticated; GRANT SELECT ON public.document_categories TO authenticated; -GRANT SELECT ON public.document_folders TO authenticated; +GRANT SELECT, INSERT, UPDATE, DELETE ON public.document_folders TO authenticated; -- Settings (public settings viewable) GRANT SELECT ON public.app_settings TO authenticated; --- Email logs (own logs viewable) +-- Email (admin can manage templates, users can view own logs) +GRANT SELECT, UPDATE ON public.email_templates TO authenticated; GRANT SELECT ON public.email_logs TO authenticated; -- Notification preferences