Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion Backend/.env-example
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ GROQ_API_KEY=
SUPABASE_URL=
SUPABASE_KEY=
GEMINI_API_KEY=
YOUTUBE_API_KEY=
YOUTUBE_API_KEY=
SUPABASE_JWT_SECRET=
117 changes: 117 additions & 0 deletions Backend/schema.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
-- Enable UUID extension
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";

-- Create Enum Types
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 $$;

Comment on lines +5 to +28
Copy link
Contributor

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.

Suggested change
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.

-- Create Users Table
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'
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()
);

-- Create Audience Insights Table
CREATE TABLE IF NOT EXISTS public.audience_insights (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
user_id UUID NOT NULL REFERENCES public.users(id) ON DELETE CASCADE,
audience_age_group JSONB,
audience_location JSONB,
engagement_rate FLOAT,
average_views INTEGER,
time_of_attention INTEGER, -- in seconds
price_expectation DECIMAL(10, 2),
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);

-- Create Sponsorships Table
CREATE TABLE IF NOT EXISTS public.sponsorships (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
brand_id UUID NOT NULL REFERENCES public.users(id) ON DELETE CASCADE,
title TEXT NOT NULL,
description TEXT NOT NULL,
required_audience JSONB, -- {"age": ["18-24"], "location": ["USA", "UK"]}
budget DECIMAL(10, 2),
engagement_minimum FLOAT,
status deal_status DEFAULT 'open',
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);

-- Create User Posts Table
CREATE TABLE IF NOT EXISTS public.user_posts (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
user_id UUID NOT NULL REFERENCES public.users(id) ON DELETE CASCADE,
title TEXT NOT NULL,
content TEXT NOT NULL,
post_url TEXT,
category TEXT,
engagement_metrics JSONB, -- {"likes": 500, "comments": 100, "shares": 50}
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);

-- Create Sponsorship Applications Table
CREATE TABLE IF NOT EXISTS public.sponsorship_applications (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
creator_id UUID NOT NULL REFERENCES public.users(id) ON DELETE CASCADE,
sponsorship_id UUID NOT NULL REFERENCES public.sponsorships(id) ON DELETE CASCADE,
post_id UUID REFERENCES public.user_posts(id) ON DELETE SET NULL,
proposal TEXT NOT NULL,
status application_status DEFAULT 'pending',
applied_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);

-- 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()
);

-- 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()
);

-- 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;
Comment on lines +112 to +117
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

find . -name "schema.sql" -type f

Repository: AOSSIE-Org/InPactAI

Length of output: 83


🏁 Script executed:

wc -l ./Backend/schema.sql

Repository: AOSSIE-Org/InPactAI

Length of output: 87


🏁 Script executed:

cat -n ./Backend/schema.sql

Repository: AOSSIE-Org/InPactAI

Length of output: 5177


🏁 Script executed:

rg -i "supabase" --type md --type json --type yaml --type txt --type sql

Repository: AOSSIE-Org/InPactAI

Length of output: 3185


🏁 Script executed:

find ./Backend -name "*.sql" -o -name "*migration*" -type f

Repository: 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]
  • 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:

  1. 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.

  2. Without RLS policies, the current grants are unsafe in Supabase: anon can read all data and authenticated can 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.

3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,9 @@ To populate the database with initial data, follow these steps:
- In the left sidebar, click on **SQL Editor**.

3. **Run the SQL Script**
- Open the `schema.sql` file in your project.
- Copy the SQL queries from the file.
- Paste the queries into the SQL Editor and click **Run**.
- Open the `sql.txt` file in your project.
- Copy the SQL queries from the file.
- Paste the queries into the SQL Editor and click **Run**.
Expand Down