-
Notifications
You must be signed in to change notification settings - Fork 122
fix(backend): Correct SQL schema, fix enums, and update local setup #229
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
…e `schema.sql` while including `SUPABASE_JWT_SECRET` in `.env-example`.
….sql` setup instructions in `README.md`.
…stead of `sql.txt`.
WalkthroughAdds a PostgreSQL schema with ENUMs and seven tables (users, audience_insights, sponsorships, user_posts, sponsorship_applications, collaborations, sponsorship_payments) with UUIDs, timestamps, JSONB fields, and FK cascades/SET NULL; grants roles permissions; updates README SQL-run steps; restores Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes
Poem
Pre-merge checks and finishing touches✅ Passed checks (3 passed)
✨ Finishing touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🧹 Nitpick comments (2)
Backend/schema.sql (2)
73-80: Self-collaboration is permissible in the schema.The
collaborationstable allowscreator_1_idandcreator_2_idto reference the same user (self-collaboration). If this is not intended, add a CHECK constraint to enforcecreator_1_id != creator_2_id. If intentional, consider a comment clarifying the design.If self-collaboration should be prevented, apply this optional diff:
-- Create Collaborations Table CREATE TABLE IF NOT EXISTS public.collaborations ( id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), creator_1_id UUID NOT NULL REFERENCES public.users(id) ON DELETE CASCADE, creator_2_id UUID NOT NULL REFERENCES public.users(id) ON DELETE CASCADE, collaboration_details TEXT NOT NULL, status invite_status DEFAULT 'pending', created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() + CHECK (creator_1_id != creator_2_id) );
83-91: Sponsorship payments allow multiple records per sponsorship.There is no UNIQUE constraint preventing duplicate payment records for the same
creator_id,brand_id, andsponsorship_idcombination. This permits multiple payments per sponsorship, which may be intentional (e.g., milestone-based or installment payments) but should be clarified. If only one payment per sponsorship is expected, consider adding a UNIQUE constraint.If each sponsorship should have only one payment record, apply this optional diff:
-- Create Sponsorship Payments Table CREATE TABLE IF NOT EXISTS public.sponsorship_payments ( id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), creator_id UUID NOT NULL REFERENCES public.users(id) ON DELETE CASCADE, brand_id UUID NOT NULL REFERENCES public.users(id) ON DELETE CASCADE, sponsorship_id UUID NOT NULL REFERENCES public.sponsorships(id) ON DELETE CASCADE, amount DECIMAL(10, 2) NOT NULL, status payment_status DEFAULT 'pending', transaction_date TIMESTAMP WITH TIME ZONE DEFAULT NOW() + UNIQUE (sponsorship_id) );If multiple payments per sponsorship are intentional, no change is needed.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
Backend/.env-example(1 hunks)Backend/schema.sql(1 hunks)README.md(1 hunks)
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: Saahi30
Repo: AOSSIE-Org/InPactAI PR: 145
File: backend/SQL:98-112
Timestamp: 2025-11-08T12:24:11.598Z
Learning: In the InPactAI repository, the backend/SQL file is a documentation reference that points to schema-reference.md and is not meant to be executed directly. Table ordering and FK constraint issues should not be flagged for this file.
📚 Learning: 2025-11-08T12:24:11.598Z
Learnt from: Saahi30
Repo: AOSSIE-Org/InPactAI PR: 145
File: backend/SQL:98-112
Timestamp: 2025-11-08T12:24:11.598Z
Learning: In the InPactAI repository, the backend/SQL file is a documentation reference that points to schema-reference.md and is not meant to be executed directly. Table ordering and FK constraint issues should not be flagged for this file.
Applied to files:
README.mdBackend/schema.sql
🔇 Additional comments (3)
Backend/.env-example (1)
10-11: Environment variables properly aligned with backend setup.The re-addition of
YOUTUBE_API_KEYand introduction ofSUPABASE_JWT_SECRETsupport the existing integrations and new JWT authentication infrastructure in the schema.Backend/schema.sql (1)
1-98: Schema structure, table ordering, and FK dependencies are well-designed.All tables are created in dependency order (users first, then all referencing tables), and all ENUMs are defined before use. FK relationships correctly use ON DELETE CASCADE or ON DELETE SET NULL as appropriate. Role-based GRANT statements provide reasonable Supabase access control.
README.md (1)
195-200: Data population instructions correctly sequenced and updated for new schema.sql.The instructions now reference both
schema.sql(schema bootstrap) andsql.txt(data population) in the correct order. Users will initialize the schema first, then populate data—matching the intended setup flow.Consider adding a brief clarification that
schema.sqlis a one-time initialization step and should not be re-executed if the schema already exists (due to ENUM creation conflicts—though this is a minor polish and not essential for the current review).
Added checks to prevent duplicate enum type creation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🧹 Nitpick comments (2)
Backend/schema.sql (2)
1-2: Preferpgcrypto/gen_random_uuid()overuuid-osspfor portability in Supabase/local dev
uuid_generate_v4()hard-depends onuuid-ossp; many Supabase setups standardize onpgcrypto+gen_random_uuid()instead.--- Enable UUID extension -CREATE EXTENSION IF NOT EXISTS "uuid-ossp"; +CREATE EXTENSION IF NOT EXISTS "pgcrypto"; CREATE TABLE IF NOT EXISTS public.users ( - id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), ... );(Apply the default swap to other
idcolumns too.)Also applies to: 31-39, 44-45, 57-58, 70-71, 82-85, 93-96, 103-107
30-40: Constrainpublic.users.role(enum/check) instead of free-form TEXT
As-is, any string can be inserted (including typos), and downstream logic will drift.CREATE TABLE IF NOT EXISTS public.users ( id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), username TEXT UNIQUE NOT NULL, email TEXT UNIQUE NOT NULL, - role TEXT NOT NULL, -- 'creator' or 'brand' + role TEXT NOT NULL CHECK (role IN ('creator', 'brand')), profile_image TEXT, bio TEXT, created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), is_online BOOLEAN DEFAULT FALSE, last_seen TIMESTAMP WITH TIME ZONE DEFAULT NOW() );
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
Backend/schema.sql(1 hunks)
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: Saahi30
Repo: AOSSIE-Org/InPactAI PR: 145
File: backend/SQL:98-112
Timestamp: 2025-11-08T12:24:11.598Z
Learning: In the InPactAI repository, the backend/SQL file is a documentation reference that points to schema-reference.md and is not meant to be executed directly. Table ordering and FK constraint issues should not be flagged for this file.
📚 Learning: 2025-11-08T12:24:11.598Z
Learnt from: Saahi30
Repo: AOSSIE-Org/InPactAI PR: 145
File: backend/SQL:98-112
Timestamp: 2025-11-08T12:24:11.598Z
Learning: In the InPactAI repository, the backend/SQL file is a documentation reference that points to schema-reference.md and is not meant to be executed directly. Table ordering and FK constraint issues should not be flagged for this file.
Applied to files:
Backend/schema.sql
| DO $$ BEGIN | ||
| CREATE TYPE application_status AS ENUM ('pending', 'accepted', 'rejected'); | ||
| EXCEPTION | ||
| WHEN duplicate_object THEN null; | ||
| END $$; | ||
|
|
||
| DO $$ BEGIN | ||
| CREATE TYPE invite_status AS ENUM ('pending', 'accepted', 'declined'); | ||
| EXCEPTION | ||
| WHEN duplicate_object THEN null; | ||
| END $$; | ||
|
|
||
| DO $$ BEGIN | ||
| CREATE TYPE payment_status AS ENUM ('pending', 'completed', 'failed'); | ||
| EXCEPTION | ||
| WHEN duplicate_object THEN null; | ||
| END $$; | ||
|
|
||
| DO $$ BEGIN | ||
| CREATE TYPE deal_status AS ENUM ('open', 'closed', 'in_progress'); | ||
| EXCEPTION | ||
| WHEN duplicate_object THEN null; | ||
| END $$; | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion | 🟠 Major
Schema-qualify ENUM types + avoid silently masking incompatible existing types
Right now CREATE TYPE application_status ... etc will create in whatever search_path resolves first, and duplicate_object hides cases where the type exists but doesn’t match expected labels (you’ll only find out later at insert/cast time). Consider pinning to public and/or asserting shape.
-DO $$ BEGIN
- CREATE TYPE application_status AS ENUM ('pending', 'accepted', 'rejected');
-EXCEPTION
- WHEN duplicate_object THEN null;
-END $$;
+DO $$
+BEGIN
+ CREATE TYPE public.application_status AS ENUM ('pending', 'accepted', 'rejected');
+EXCEPTION
+ WHEN duplicate_object THEN
+ NULL;
+END
+$$;(Repeat for invite_status, payment_status, deal_status.)
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| DO $$ BEGIN | |
| CREATE TYPE application_status AS ENUM ('pending', 'accepted', 'rejected'); | |
| EXCEPTION | |
| WHEN duplicate_object THEN null; | |
| END $$; | |
| DO $$ BEGIN | |
| CREATE TYPE invite_status AS ENUM ('pending', 'accepted', 'declined'); | |
| EXCEPTION | |
| WHEN duplicate_object THEN null; | |
| END $$; | |
| DO $$ BEGIN | |
| CREATE TYPE payment_status AS ENUM ('pending', 'completed', 'failed'); | |
| EXCEPTION | |
| WHEN duplicate_object THEN null; | |
| END $$; | |
| DO $$ BEGIN | |
| CREATE TYPE deal_status AS ENUM ('open', 'closed', 'in_progress'); | |
| EXCEPTION | |
| WHEN duplicate_object THEN null; | |
| END $$; | |
| DO $$ | |
| BEGIN | |
| CREATE TYPE public.application_status AS ENUM ('pending', 'accepted', 'rejected'); | |
| EXCEPTION | |
| WHEN duplicate_object THEN | |
| NULL; | |
| END | |
| $$; | |
| DO $$ | |
| BEGIN | |
| CREATE TYPE public.invite_status AS ENUM ('pending', 'accepted', 'declined'); | |
| EXCEPTION | |
| WHEN duplicate_object THEN | |
| NULL; | |
| END | |
| $$; | |
| DO $$ | |
| BEGIN | |
| CREATE TYPE public.payment_status AS ENUM ('pending', 'completed', 'failed'); | |
| EXCEPTION | |
| WHEN duplicate_object THEN | |
| NULL; | |
| END | |
| $$; | |
| DO $$ | |
| BEGIN | |
| CREATE TYPE public.deal_status AS ENUM ('open', 'closed', 'in_progress'); | |
| EXCEPTION | |
| WHEN duplicate_object THEN | |
| NULL; | |
| END | |
| $$; |
🤖 Prompt for AI Agents
In Backend/schema.sql around lines 5 to 28, the CREATE TYPEs run unqualified and
silently swallow duplicate_object even when an existing type has a different
set/order of labels; change each block to schema-qualify the type name (e.g.
public.application_status) and replace the blanket EXCEPTION handler with a
check that inspects pg_type/unnest(enum_range(NULL::public.application_status))
(or use EXISTS + array comparison of enum labels) and RAISE EXCEPTION if the
existing labels differ from the expected list; if the type does not exist then
CREATE it in public. Repeat the same schema-qualification and shape assertion
for invite_status, payment_status, and deal_status.
| -- Grant Permissions | ||
| GRANT USAGE ON SCHEMA public TO anon, authenticated, service_role; | ||
| GRANT ALL ON ALL TABLES IN SCHEMA public TO service_role; | ||
| GRANT ALL ON ALL SEQUENCES IN SCHEMA public TO service_role; | ||
| GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO authenticated; | ||
| GRANT SELECT ON ALL TABLES IN SCHEMA public TO anon; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
find . -name "schema.sql" -type fRepository: AOSSIE-Org/InPactAI
Length of output: 83
🏁 Script executed:
wc -l ./Backend/schema.sqlRepository: AOSSIE-Org/InPactAI
Length of output: 87
🏁 Script executed:
cat -n ./Backend/schema.sqlRepository: AOSSIE-Org/InPactAI
Length of output: 5177
🏁 Script executed:
rg -i "supabase" --type md --type json --type yaml --type txt --type sqlRepository: AOSSIE-Org/InPactAI
Length of output: 3185
🏁 Script executed:
find ./Backend -name "*.sql" -o -name "*migration*" -type fRepository: AOSSIE-Org/InPactAI
Length of output: 83
🌐 Web query:
PostgreSQL ALTER DEFAULT PRIVILEGES syntax future tables sequences
💡 Result:
Short summary — ALTER DEFAULT PRIVILEGES (PostgreSQL)
-
Purpose: set privileges that will be applied to objects created in the future (does not change existing objects). [1][3]
-
Basic form:
ALTER DEFAULT PRIVILEGES [ FOR { ROLE | USER } target_role [, ...] ]
[ IN SCHEMA schema_name [, ...] ]
GRANT|REVOKE ...;
The GRANT/REVOKE part uses object-type-specific clauses (ON TABLES, ON SEQUENCES, ON FUNCTIONS, etc.). [1] -
Examples:
- Future tables (and views/foreign tables) in a schema:
ALTER DEFAULT PRIVILEGES IN SCHEMA myschema
GRANT SELECT ON TABLES TO read_role; - Future sequences in a schema:
ALTER DEFAULT PRIVILEGES IN SCHEMA myschema
GRANT USAGE, SELECT ON SEQUENCES TO app_role; - For objects created by another role:
ALTER DEFAULT PRIVILEGES FOR ROLE owner_role IN SCHEMA myschema
GRANT INSERT ON TABLES TO app_role;
(Syntax variants and full privilege lists are documented in the reference.) [1]
- Future tables (and views/foreign tables) in a schema:
-
Important notes:
- Default-privileges apply only to objects created by the specified target role (or the current role if FOR ROLE omitted). They are not inherited from roles you are a member of. [1]
- Per-schema default privileges are additive to global defaults — you cannot use IN SCHEMA to revoke a privilege that was granted globally. [1]
- Supported object classes include tables (incl. views/foreign tables), sequences, functions/routines, types, schemas, and large objects (exact support may vary by PostgreSQL version). [1][2]
- Use \ddp in psql to inspect default-privilege assignments. [1]
References:
[1] PostgreSQL ALTER DEFAULT PRIVILEGES documentation.
[2] PostgreSQL older-version docs / compatibility notes.
[3] Practical explanation and examples (Cybertec).
🌐 Web query:
Supabase Row Level Security RLS anon authenticated roles security best practices
💡 Result:
Below are concise Supabase Row-Level Security (RLS) best practices for anon/authenticated roles and general security — with links to authoritative docs and guidance.
High-level rules
- Always enable RLS for any table/view/function in the public schema (default for Dashboard-created tables). [1][4]
- Never expose the service_role key on the frontend — treat it as a backend secret (env var) because it bypasses RLS. Use the anon/publishable key on clients. [1][2]
Policy design and role usage
- Explicitly target roles in policies (TO authenticated, anon) rather than relying only on auth.uid() checks. Prefer adding authenticated to TO when you want signed-in users only. [5][3]
- For auth-based rules, require auth.uid() IS NOT NULL when you expect authenticated users (avoid implicit null = comparisons). Example: USING (auth.uid() IS NOT NULL AND auth.uid() = user_id). [3]
- Create separate policies per operation (SELECT / INSERT / UPDATE / DELETE) and use WITH CHECK for validating new/updated rows. [6][3]
- Use auth.jwt() and JWT claims (e.g., custom claims like org_id, is_anonymous) for richer authorization where needed. [6][8]
Performance & complexity
- Avoid expensive joins inside policy expressions. Prefer comparing native columns to a precomputed set or using security-definer functions to encapsulate complex logic. Index columns used in policy predicates. [5]
- Test and profile RLS policies on realistic data sizes; very large IN-lists or unindexed predicates can be slow. [5]
Role hardening & key management
- Keep anon/publishable keys removable/rotatable; rotate keys and monitor usage. Use Security Advisor checks in Supabase and review any flagged built-in-role changes. [1][2]
- Create custom Postgres roles for administrative tasks instead of granting bypass privileges to anon/authenticated. Limit bypassrls or superuser privileges to service accounts only. [2][5]
Operational & auditing
- Limit client-surface to anon/authenticated keys; perform sensitive operations on server-side using service_role or vault-backed secrets. [1][3]
- Log and audit accesses and failed policy checks where possible; use application logs + database logs to detect misuse.
- Regularly review RLS policies, and include policy checks in your security reviews and CI/CD deployments.
Examples & helpers
- Use small helper security functions (SECURITY DEFINER when safe) to centralize permission logic, and keep policy SQL short and index-friendly. [5][3]
Primary references
- Supabase: Securing your data / API keys / RLS docs. [1][2][3][4]
- Supabase discussion & performance tips (RLS performance, use of TO roles, join advice). [5]
If you want, I can:
- Audit a specific table’s policies you paste here and suggest exact SQL policy fixes, or
- Provide sample policy templates (select/insert/update/delete + WITH CHECK) for a typical multi-tenant app.
🌐 Web query:
PostgreSQL GRANT SELECT INSERT UPDATE DELETE ON TABLES syntax Supabase anon authenticated
💡 Result:
Syntax (Postgres):
GRANT { SELECT | INSERT | UPDATE | DELETE [, ...] }
ON [ TABLE ] schema.table
TO role_name [, ...] [ WITH GRANT OPTION ]. [1]
Examples (Supabase default roles):
- Grant read-only to public (anon):
GRANT SELECT ON public.my_table TO anon; - Grant full CUD+read to authenticated users:
GRANT SELECT, INSERT, UPDATE, DELETE ON public.my_table TO authenticated; - Grant to both:
GRANT SELECT ON public.my_table TO authenticated, anon;
Notes for Supabase:
- Supabase exposes Postgres roles anon (unauthenticated) and authenticated (logged-in). Use GRANT to give role-level privileges, but enforce row-level access via RLS policies (create policy ... FOR TO authenticated, anon USING (...)). RLS is the recommended way to control per-row access in Supabase. [2][3]
References:
[1] PostgreSQL GRANT docs.
[2] Supabase — default Postgres roles (anon, authenticated).
[3] Supabase — Row Level Security and example policies.
Add ALTER DEFAULT PRIVILEGES to ensure future tables inherit permissions, and enable RLS with policies for Supabase safety
Two legitimate concerns with the current grant setup:
-
GRANT ... ON ALL TABLES applies only to existing tables—future tables won't inherit these permissions unless you also set
ALTER DEFAULT PRIVILEGES. This creates a maintenance risk where new tables accidentally lack proper access controls. -
Without RLS policies, the current grants are unsafe in Supabase:
anoncan read all data andauthenticatedcan insert, update, and delete everything. This is wide-open and unsuitable for production.
Recommended additions (at minimum):
GRANT USAGE ON SCHEMA public TO anon, authenticated, service_role;
GRANT ALL ON ALL TABLES IN SCHEMA public TO service_role;
GRANT ALL ON ALL SEQUENCES IN SCHEMA public TO service_role;
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO authenticated;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO anon;
+
+-- Ensure future tables/sequences get consistent privileges
+ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO anon;
+ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO authenticated;
+ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON TABLES TO service_role;
+ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON SEQUENCES TO service_role;Additionally, add ENABLE ROW LEVEL SECURITY on each table and define baseline policies per table (e.g., users table allows authenticated users to see/edit only their own row). If this schema is not yet ready for production, add a comment documenting that.
🤖 Prompt for AI Agents
In Backend/schema.sql around lines 112 to 117, the GRANT statements only affect
existing objects and leave future tables/sequences without proper permissions
and also leave tables wide-open in Supabase; update the schema to call ALTER
DEFAULT PRIVILEGES FOR ROLE service_role IN SCHEMA public GRANT ... to ensure
newly created tables and sequences inherit the same grants for anon,
authenticated, and service_role, and for each existing and future table enable
row level security (ALTER TABLE ... ENABLE ROW LEVEL SECURITY) and add per-table
RLS policies (e.g., for users: allow authenticated users to SELECT/UPDATE/DELETE
only their own row, and restrict anon to minimal read access) or insert a clear
comment that the DB is not production-ready until RLS policies are defined.
Closes #BUG: Fix SQL schema issues (USER-DEFINED, FK order, duplicate blocks, triggers) + missing SUPABASE_JWT_SECRET in .env.example #191
Description
This PR fixes several critical issues preventing the project from being set up locally. Specifically, it addresses SQL migration failures caused by invalid enum types, incorrect table creation order, and missing permissions. It also adds a missing required environment variable to the example configuration.
Changes Made
USER-DEFINEDplaceholders with proper PostgreSQLENUMtypes (application_status,invite_status,payment_status,deal_status).usersexists before it is referenced).GRANTpermissions foranon,authenticated, andservice_roleto fix "permission denied" errors.SUPABASE_JWT_SECRETto Backend/.env-example as it is required for the app to run.Screenshots or Visual Changes (if applicable)
N/A - Backend/Schema changes only.
Checklist
Summary by CodeRabbit
✏️ Tip: You can customize this high-level summary in your review settings.