Skip to content

Conversation

@Saahi30
Copy link
Collaborator

@Saahi30 Saahi30 commented Nov 10, 2025

📝 Description

This pull request refactors and extends the backend API to support new collaboration and creator features, improves security, and updates configuration and environment files. The changes enhance modularity, maintainability, and security of the backend codebase.

🔧 Changes Made

Added new API routes for collaborations and creators.
Introduced a token model for authentication and authorization.
Added core dependencies and security utilities, including JWT helpers.
Refactored campaigns and auth routes for improved structure and error handling.
Updated configuration files, main entry point, requirements, and environment example.

✅ Checklist

  • I have read the contributing guidelines.
  • I have added tests that prove my fix is effective or that my feature works.
  • I have added necessary documentation (if applicable).
  • Any dependent changes have been merged and published in downstream modules.

Summary by CodeRabbit

Release Notes

  • New Features
    • AI-powered creator recommendations using intelligent matching algorithms based on niche compatibility, audience size, engagement metrics, and content alignment.
    • Automated collaboration idea generation with AI-generated suggestions tailored to creator profiles and interests.
    • Full collaboration management system including proposal tracking, status filtering, messaging, performance metrics, and completion analytics.
    • Enhanced creator discovery with advanced filtering, search functionality, and comprehensive profile browsing by niche.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 10, 2025

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Walkthrough

This PR introduces a complete JWT-based authentication and authorization layer with dependency injection, plus two new feature modules. Changes include security infrastructure for token validation and role-based access control, configuration updates for JWT secrets and new dependencies (Groq AI, PyJWT), refactored campaign routes to use brand-based authentication, and new API endpoints for creator discovery and collaboration management with AI-assisted recommendation and idea-generation capabilities.

Changes

Cohort / File(s) Summary
Authentication & Security Infrastructure
backend/app/core/security.py, backend/app/core/dependencies.py, backend/app/models/token.py
Introduced JWTHandler class for token validation and payload extraction; added FastAPI dependency functions for authenticated user, creator, and brand contexts with role-based access control; created Pydantic models for token responses and decoded token data.
Configuration & Environment
backend/app/core/config.py, backend/env_example, backend/requirements.txt
Added SUPABASE_JWT_SECRET configuration field; updated environment example with new variable; added groq and pyjwt[crypto] dependencies.
Campaign Routes
backend/app/api/routes/campaigns.py
Replaced manual user_id Query parameter with brand-based dependency injection; refactored all CRUD endpoints (create, read, update, delete, list) to use get_current_brand dependency; removed legacy get_brand_id_from_user helper.
Creator Discovery & Recommendations
backend/app/api/routes/creators.py
New module with endpoints for listing creators, fetching recommendations via multi-factor scoring system, retrieving creator details, and listing active niches; supports optional Groq AI reranking for recommendations with graceful fallback.
Collaboration Management
backend/app/api/routes/collaborations.py
New module with endpoints for listing creator collaborations, fetching single collaboration, aggregating collaboration stats, generating collaboration ideas via Groq AI, and recommending creators for ideas; includes robust validation, access checks, and pagination.
App Initialization
backend/app/main.py
Registered new collaborations and creators routers in FastAPI application.
Testing
backend/test_jwt.py
New test script for validating JWT authentication flow against Supabase-backed API; verifies token generation, protected endpoint access, and invalid token rejection.

Sequence Diagrams

sequenceDiagram
    participant Client
    participant FastAPI as FastAPI Route
    participant JWTHandler
    participant Supabase
    participant Groq as Groq AI (optional)

    Client->>FastAPI: GET /creators/recommendations
    FastAPI->>JWTHandler: decode JWT token
    JWTHandler-->>FastAPI: decoded payload {user_id, role}
    FastAPI->>Supabase: fetch current creator profile
    Supabase-->>FastAPI: creator data
    FastAPI->>Supabase: fetch all active candidate creators
    Supabase-->>FastAPI: candidates list
    
    Note over FastAPI: Compute multi-factor scores<br/>(niche, content, openness,<br/>audience, engagement, etc.)
    
    alt AI reranking enabled
        FastAPI->>Groq: POST prompt with ranked candidates
        Groq-->>FastAPI: reranked JSON response
        FastAPI->>FastAPI: parse & map to CreatorRecommendation
    else AI unavailable/disabled
        FastAPI->>FastAPI: use rule-based ranking
    end
    
    FastAPI-->>Client: List[CreatorRecommendation] with match_scores
Loading
sequenceDiagram
    participant Client
    participant FastAPI as FastAPI Route
    participant Supabase
    participant Groq as Groq AI
    participant JWTHandler

    Client->>FastAPI: POST /collaborations/generate-ideas
    FastAPI->>JWTHandler: validate & extract creator context
    JWTHandler-->>FastAPI: authenticated creator dict
    FastAPI->>Supabase: fetch current creator profile
    Supabase-->>FastAPI: current creator data
    FastAPI->>Supabase: fetch target creator profile
    Supabase-->>FastAPI: target creator data
    
    Note over FastAPI: Build detailed prompt:<br/>current profile, target profile,<br/>niches, content types, audience
    
    FastAPI->>Groq: POST prompt for collaboration ideas
    Groq-->>FastAPI: JSON response with 5 ideas
    FastAPI->>FastAPI: parse JSON & validate structure
    FastAPI->>FastAPI: map to CollaborationIdea models
    FastAPI-->>Client: CollaborationIdeasResponse (up to 5 ideas)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~65 minutes

  • JWT token validation and role-based access control (security.py, dependencies.py): Verify proper token decoding, error handling for expired/invalid tokens, and role extraction from Supabase claims.
  • Creator recommendation scoring logic (creators.py): Review multi-factor scoring algorithm (niche similarity, audience, engagement, recency, etc.), diversity constraints, and Groq AI reranking fallback behavior.
  • AI prompt engineering and JSON parsing (collaborations.py): Inspect Groq prompts for idea generation and creator recommendations; validate JSON parsing robustness and error recovery.
  • Database query patterns and pagination (collaborations.py, creators.py): Confirm Supabase queries handle filtering, pagination, and de-duplication correctly.
  • Access control and validation (collaborations.py, creators.py): Verify self-collaboration prevention, profile active checks, candidate validation, and 403/404 responses for unauthorized access.

Possibly related PRs

Poem

🐰 A hop through tokens, a leap through trust,
JWT secrets guarded (a must!),
Creators find collaborators, AI suggests the match,
Dependencies injected, roles attached—
One brand, one creator, one unified catch! 🤝✨

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main changes: backend refactoring with new collaborations/creators routes, security, and config updates. It is specific, clear, and directly reflects the comprehensive scope of the changeset.
Docstring Coverage ✅ Passed Docstring coverage is 80.00% which is sufficient. The required threshold is 80.00%.

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@Saahi30
Copy link
Collaborator Author

Saahi30 commented Nov 10, 2025

@CodeRabbit review

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 10, 2025

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 6

🧹 Nitpick comments (4)
backend/test_jwt.py (2)

18-19: Document that test credentials must be updated for actual testing.

The hardcoded credentials are clearly marked as test values, but consider adding a comment emphasizing that users must create a test account and update these values before running the script.

Add a more prominent comment:

 # Test user credentials (update with your test account)
+# IMPORTANT: Create a test account in your Supabase project and update these values
 TEST_EMAIL = "[email protected]"
 TEST_PASSWORD = "Test123!@#"

89-89: Consider redacting token in output to prevent accidental exposure.

Printing even a partial token in logs could be a security concern in some environments. Consider shortening the displayed portion or using asterisks.

Apply this diff:

-    print(f"✅ Got JWT token: {token[:50]}...\n")
+    print(f"✅ Got JWT token: {token[:20]}...***\n")
backend/app/core/dependencies.py (1)

48-52: Remove redundant exception handler.

Catching HTTPException just to immediately re-raise it adds no value and makes the code unnecessarily verbose.

Apply this diff:

     # Decode and validate token
-    try:
-        payload = jwt_handler.decode_token(token)
-    except HTTPException as e:
-        raise e
+    payload = jwt_handler.decode_token(token)
backend/app/core/security.py (1)

85-98: Tighten the exception handling in verify_token.

verify_token currently swallows every exception and quietly returns False, even when it’s a configuration or coding bug (e.g., wrong secret type, decoding logic errors). That makes diagnosing broken deployments painful and can silently mask new regressions. Narrow the except to the JWT error family and let unexpected exceptions surface.

-        try:
-            jwt.decode(
-                token,
-                self.secret_key,
-                algorithms=[self.algorithm],
-                options={
-                    "verify_signature": True,
-                    "verify_exp": True,
-                    "verify_aud": False  # Disable audience verification
-                }
-            )
-            return True
-        except:
-            return False
+        try:
+            jwt.decode(
+                token,
+                self.secret_key,
+                algorithms=[self.algorithm],
+                options={
+                    "verify_signature": True,
+                    "verify_exp": True,
+                    "verify_aud": False,  # Disable audience verification
+                },
+            )
+            return True
+        except jwt.PyJWTError:
+            return False
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between bb74b9a and df2327d.

📒 Files selected for processing (11)
  • backend/app/api/routes/campaigns.py (7 hunks)
  • backend/app/api/routes/collaborations.py (1 hunks)
  • backend/app/api/routes/creators.py (1 hunks)
  • backend/app/core/config.py (1 hunks)
  • backend/app/core/dependencies.py (1 hunks)
  • backend/app/core/security.py (1 hunks)
  • backend/app/main.py (2 hunks)
  • backend/app/models/token.py (1 hunks)
  • backend/env_example (1 hunks)
  • backend/requirements.txt (1 hunks)
  • backend/test_jwt.py (1 hunks)
🧰 Additional context used
🪛 Ruff (0.14.3)
backend/app/api/routes/campaigns.py

78-78: Do not perform function call Depends in argument defaults; instead, perform the call within the function, or read the default from a module-level singleton variable

(B008)


155-155: Do not perform function call Depends in argument defaults; instead, perform the call within the function, or read the default from a module-level singleton variable

(B008)


234-234: Do not perform function call Depends in argument defaults; instead, perform the call within the function, or read the default from a module-level singleton variable

(B008)


267-267: Do not perform function call Depends in argument defaults; instead, perform the call within the function, or read the default from a module-level singleton variable

(B008)


327-327: Do not perform function call Depends in argument defaults; instead, perform the call within the function, or read the default from a module-level singleton variable

(B008)

backend/app/core/dependencies.py

28-28: Do not perform function call Depends in argument defaults; instead, perform the call within the function, or read the default from a module-level singleton variable

(B008)


51-52: Remove exception handler; error is immediately re-raised

(TRY203)


52-52: Use raise without specifying exception name

Remove exception name

(TRY201)


72-75: Abstract raise to an inner function

(TRY301)


83-83: Consider moving this statement to an else block

(TRY300)


85-85: Do not catch blind exception: Exception

(BLE001)


86-89: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)


88-88: Use explicit conversion flag

Replace with conversion flag

(RUF010)


93-93: Do not perform function call Depends in argument defaults; instead, perform the call within the function, or read the default from a module-level singleton variable

(B008)


125-128: Abstract raise to an inner function

(TRY301)


130-130: Consider moving this statement to an else block

(TRY300)


134-137: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)


143-143: Do not perform function call Depends in argument defaults; instead, perform the call within the function, or read the default from a module-level singleton variable

(B008)


183-183: Do not perform function call Depends in argument defaults; instead, perform the call within the function, or read the default from a module-level singleton variable

(B008)


204-204: Do not use bare except

(E722)

backend/app/api/routes/creators.py

102-102: Do not perform function call Depends in argument defaults; instead, perform the call within the function, or read the default from a module-level singleton variable

(B008)


154-154: Consider moving this statement to an else block

(TRY300)


161-161: Use explicit conversion flag

Replace with conversion flag

(RUF010)


179-179: Do not perform function call Depends in argument defaults; instead, perform the call within the function, or read the default from a module-level singleton variable

(B008)


198-198: Abstract raise to an inner function

(TRY301)


240-240: Do not catch blind exception: Exception

(BLE001)


385-385: Undefined name json

(F821)


386-386: Do not catch blind exception: Exception

(BLE001)


401-403: try-except-pass detected, consider logging the exception

(S110)


401-401: Do not catch blind exception: Exception

(BLE001)


410-410: Multiple statements on one line (colon)

(E701)


411-411: Multiple statements on one line (colon)

(E701)


412-412: Multiple statements on one line (colon)

(E701)


413-413: Multiple statements on one line (colon)

(E701)


425-425: Consider moving this statement to an else block

(TRY300)


432-432: Use explicit conversion flag

Replace with conversion flag

(RUF010)


439-439: Unused function argument: creator

(ARG001)


439-439: Do not perform function call Depends in argument defaults; instead, perform the call within the function, or read the default from a module-level singleton variable

(B008)


458-461: Abstract raise to an inner function

(TRY301)


463-463: Consider moving this statement to an else block

(TRY300)


475-475: Use explicit conversion flag

Replace with conversion flag

(RUF010)


481-481: Unused function argument: creator

(ARG001)


481-481: Do not perform function call Depends in argument defaults; instead, perform the call within the function, or read the default from a module-level singleton variable

(B008)


500-500: Consider moving this statement to an else block

(TRY300)


505-505: Use explicit conversion flag

Replace with conversion flag

(RUF010)

backend/app/models/token.py

12-12: Possible hardcoded password assigned to: "token_type"

(S105)

backend/app/core/security.py

20-20: Abstract raise to an inner function

(TRY301)


20-20: Avoid specifying long messages outside the exception class

(TRY003)


21-21: Do not catch blind exception: Exception

(BLE001)


22-22: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)


22-22: Avoid specifying long messages outside the exception class

(TRY003)


22-22: Use explicit conversion flag

Replace with conversion flag

(RUF010)


61-61: Consider moving this statement to an else block

(TRY300)


64-67: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)


70-73: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)


72-72: Use explicit conversion flag

Replace with conversion flag

(RUF010)


96-96: Consider moving this statement to an else block

(TRY300)


97-97: Do not use bare except

(E722)


161-161: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)


161-161: Avoid specifying long messages outside the exception class

(TRY003)


171-171: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)


171-171: Avoid specifying long messages outside the exception class

(TRY003)

backend/app/api/routes/collaborations.py

50-50: Do not perform function call Depends in argument defaults; instead, perform the call within the function, or read the default from a module-level singleton variable

(B008)


100-100: Consider moving this statement to an else block

(TRY300)


107-107: Use explicit conversion flag

Replace with conversion flag

(RUF010)


114-114: Do not perform function call Depends in argument defaults; instead, perform the call within the function, or read the default from a module-level singleton variable

(B008)


135-138: Abstract raise to an inner function

(TRY301)


144-147: Abstract raise to an inner function

(TRY301)


149-149: Consider moving this statement to an else block

(TRY300)


161-161: Use explicit conversion flag

Replace with conversion flag

(RUF010)


167-167: Do not perform function call Depends in argument defaults; instead, perform the call within the function, or read the default from a module-level singleton variable

(B008)


210-210: Consider moving this statement to an else block

(TRY300)


215-215: Use explicit conversion flag

Replace with conversion flag

(RUF010)


240-240: Do not perform function call Depends in argument defaults; instead, perform the call within the function, or read the default from a module-level singleton variable

(B008)


275-275: Abstract raise to an inner function

(TRY301)


277-277: Abstract raise to an inner function

(TRY301)


329-329: Abstract raise to an inner function

(TRY301)


374-377: Abstract raise to an inner function

(TRY301)


382-385: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)


384-384: Use explicit conversion flag

Replace with conversion flag

(RUF010)


386-386: Do not catch blind exception: Exception

(BLE001)


387-390: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)


389-389: Use explicit conversion flag

Replace with conversion flag

(RUF010)


397-397: Use explicit conversion flag

Replace with conversion flag

(RUF010)


426-426: Do not perform function call Depends in argument defaults; instead, perform the call within the function, or read the default from a module-level singleton variable

(B008)


453-453: Abstract raise to an inner function

(TRY301)


472-475: Abstract raise to an inner function

(TRY301)


539-539: Abstract raise to an inner function

(TRY301)


575-578: Abstract raise to an inner function

(TRY301)


598-601: Abstract raise to an inner function

(TRY301)


613-616: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)


615-615: Use explicit conversion flag

Replace with conversion flag

(RUF010)


617-617: Do not catch blind exception: Exception

(BLE001)


618-621: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)


620-620: Use explicit conversion flag

Replace with conversion flag

(RUF010)


628-628: Use explicit conversion flag

Replace with conversion flag

(RUF010)

backend/test_jwt.py

19-19: Possible hardcoded password assigned to: "TEST_PASSWORD"

(S105)


26-26: Probable use of requests call without timeout

(S113)


49-49: Probable use of requests call without timeout

(S113)


65-65: Probable use of requests call without timeout

(S113)

🔇 Additional comments (13)
backend/app/core/config.py (1)

29-30: LGTM! Required JWT secret is properly configured.

The JWT secret is correctly defined as a required field with helpful documentation. Making it required (no default) ensures the application won't start without proper JWT configuration, which is good security practice.

backend/app/models/token.py (1)

9-25: LGTM! Token models are well-defined.

The Pydantic models for JWT authentication are properly structured with clear field types and helpful docstrings. The static analysis warning about token_type being a hardcoded password is a false positive—it's the standard OAuth2 bearer token type.

backend/env_example (1)

30-34: LGTM! Clear documentation for JWT secret configuration.

The environment variable documentation is excellent, particularly the explicit warning to use the JWT Secret rather than the anon key. This helps prevent a common configuration mistake.

backend/app/api/routes/campaigns.py (5)

155-182: Consistent brand-based authentication implementation.

The get_campaigns endpoint properly uses the brand dependency and extracts the brand ID consistently with the create endpoint.


232-244: Consistent brand-based authentication implementation.

The get_campaign endpoint properly uses the brand dependency and verifies ownership through the database query.


264-278: Consistent brand-based authentication implementation.

The update_campaign endpoint properly uses the brand dependency and verifies ownership before allowing updates.


325-337: Consistent brand-based authentication implementation.

The delete_campaign endpoint properly uses the brand dependency and verifies ownership before allowing deletion.


78-87: No validation issues found — code is safe.

The brands table schema confirms that id is a PRIMARY KEY UUID field with a default value, guaranteed to be present in every record. The get_current_brand function validates that a brand profile exists before returning response.data, so accessing brand['id'] is completely safe and will never raise a KeyError.

backend/app/core/dependencies.py (3)

27-83: Well-structured user authentication dependency.

The get_current_user function properly validates JWT tokens, fetches user profiles, and handles error cases. The email enrichment from the token payload is a nice touch for cases where the profile might not have it stored.


92-130: Good role-based access control for creators.

The get_current_creator function properly checks the user role and fetches the creator profile with appropriate error handling for onboarding scenarios.


14-24: Clear security scheme configuration for Swagger documentation.

Both required and optional security schemes are well-configured with helpful descriptions for API documentation.

backend/requirements.txt (1)

26-28: Update dependency versions to more recent releases.

The latest available versions are groq 0.33.0 and pyjwt 2.10.1, while the requirements currently pin groq 0.11.0 and pyjwt 2.8.0. While pyjwt 2.8.0 is not affected by current published CVEs, both dependencies are outdated and should be upgraded to benefit from bug fixes, performance improvements, and compatibility updates. Consider updating to groq 0.33.0 and pyjwt 2.10.1.

backend/app/main.py (1)

10-11: ****

The routes in both modules are properly namespaced through their path decorators. The collaborations.router defines routes with the /collaborations prefix (e.g., @router.get("/collaborations", ...)), and creators.router similarly defines routes with the /collaborations prefix (e.g., @router.get("/creators", ...)). This is a standard FastAPI pattern—routes can be organized through explicit path prefixes in decorators rather than the prefix parameter in include_router(). There are no route conflicts, and the API organization is clear. No changes are needed.

Likely an incorrect or invalid review comment.

Saahi30 and others added 6 commits November 10, 2025 21:30
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
@Saahi30 Saahi30 merged commit 6930a57 into dev Nov 10, 2025
1 check passed
@Saahi30 Saahi30 deleted the feat/backend-api-refactor branch November 10, 2025 17:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants