-
Notifications
You must be signed in to change notification settings - Fork 140
feat(api): refactor backend, add collaborations/creators routes, security, and config updates #150
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
Conversation
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the You can disable this status message by setting the WalkthroughThis 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
Sequence DiagramssequenceDiagram
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
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)
Estimated code review effort🎯 4 (Complex) | ⏱️ ~65 minutes
Possibly related PRs
Poem
Pre-merge checks and finishing touches✅ Passed checks (3 passed)
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 |
|
@CodeRabbit review |
✅ Actions performedReview triggered.
|
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: 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
HTTPExceptionjust 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 inverify_token.
verify_tokencurrently swallows every exception and quietly returnsFalse, 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 theexceptto 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
📒 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_typebeing 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_campaignsendpoint properly uses the brand dependency and extracts the brand ID consistently with the create endpoint.
232-244: Consistent brand-based authentication implementation.The
get_campaignendpoint properly uses the brand dependency and verifies ownership through the database query.
264-278: Consistent brand-based authentication implementation.The
update_campaignendpoint properly uses the brand dependency and verifies ownership before allowing updates.
325-337: Consistent brand-based authentication implementation.The
delete_campaignendpoint 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
idis a PRIMARY KEY UUID field with a default value, guaranteed to be present in every record. Theget_current_brandfunction validates that a brand profile exists before returningresponse.data, so accessingbrand['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_userfunction 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_creatorfunction 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.routerdefines routes with the/collaborationsprefix (e.g.,@router.get("/collaborations", ...)), andcreators.routersimilarly defines routes with the/collaborationsprefix (e.g.,@router.get("/creators", ...)). This is a standard FastAPI pattern—routes can be organized through explicit path prefixes in decorators rather than theprefixparameter ininclude_router(). There are no route conflicts, and the API organization is clear. No changes are needed.Likely an incorrect or invalid review comment.
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>
📝 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
Summary by CodeRabbit
Release Notes