Files
thrilltrack-explorer/PHASE_2_COMPLETE_SUPABASE_REMOVAL_PLAN.md

12 KiB

Phase 2: Complete Supabase Removal Plan

Current Status

Completed - Reports Integration

All three components now use Django API for reports operations:

  • ReportButton.tsx - Uses reportsService.submitReport()
  • useModerationStats.ts - Uses reportsService.getStatistics() for report stats
  • ReportsQueue.tsx - Uses reportsService.listReports() and reportsService.updateReportStatus()

⚠️ Remaining Supabase Dependencies

ReportsQueue.tsx

  1. Line ~195-210: Reporter Profile Fetching

    await supabase.rpc('get_users_with_emails')
    // OR
    await supabase.from('profiles').select(...)
    

    Django Endpoint Exists: GET /api/v1/users/ (batch fetch)

  2. Lines ~219-258: Related Content Fetching

    • Reviews: supabase.from('reviews').select(...).in('id', reviewIds)
    • Profiles: supabase.rpc('get_users_with_emails')
    • Submissions: supabase.from('content_submissions').select(...).in('id', submissionIds)

    Django Endpoints Exist:

    • GET /api/v1/reviews/ (batch fetch with filters)
    • GET /api/v1/users/ (batch fetch)
    • GET /api/v1/moderation/submissions (batch fetch)
  3. Lines ~385-401: Audit Logging

    await supabase.rpc('log_admin_action', {...})
    

    Django Endpoint: MISSING - needs to be created

useModerationStats.ts

  1. Lines ~81-84: Content Submissions Stats

    await supabase.from('content_submissions')
      .select('id', { count: 'exact', head: true })
      .eq('status', 'pending')
    

    Django Endpoint: ⚠️ EXISTS but needs stats endpoint

  2. Lines ~86-89: Flagged Reviews Stats

    await supabase.from('reviews')
      .select('id', { count: 'exact', head: true })
      .eq('moderation_status', 'flagged')
    

    Django Endpoint: ⚠️ EXISTS but needs count/stats endpoint

  3. Lines ~143-181: Realtime Subscriptions

    • Supabase realtime for submissions
    • Supabase realtime for reviews Solution: Convert to polling (already have polling code)

Django API Audit

Endpoints That Exist

Users/Auth (/api/v1/auth/)

  • GET /api/v1/users/ - List users with filters (supports batch via search)
  • GET /api/v1/users/{id} - Get single user
  • GET /api/v1/me - Get current user profile

Reviews (/api/v1/reviews/)

  • GET /api/v1/reviews/ - List reviews with filters
  • GET /api/v1/reviews/{id} - Get single review
  • Supports filtering by entity_id, user_id, rating, etc.

Content Submissions (/api/v1/moderation/)

  • GET /api/v1/moderation/submissions - List submissions with pagination
  • GET /api/v1/moderation/submissions/{id} - Get single submission
  • Supports filtering by status

Missing Django Endpoints

1. Batch User Fetch by IDs

Current: GET /api/v1/users/?search={query} (not ideal for batch by IDs) Needed: GET /api/v1/users/batch?ids=id1,id2,id3 Alternative: Use search with IDs or fetch individually (less efficient)

2. Batch Reviews Fetch by IDs

Current: GET /api/v1/reviews/?entity_id={id} (filters by entity) Needed: GET /api/v1/reviews/batch?ids=id1,id2,id3 Alternative: Fetch individually or filter by entity_id if all same entity

3. Batch Submissions Fetch by IDs

Current: GET /api/v1/moderation/submissions (no ID filter) Needed: GET /api/v1/moderation/submissions/batch?ids=id1,id2,id3 Alternative: Fetch individually

4. Moderation Statistics Endpoint

Needed: GET /api/v1/moderation/stats Response:

{
  "pending_submissions": 5,
  "reviewing_submissions": 2,
  "flagged_reviews": 3
}

5. Audit Logging Endpoint

Needed: POST /api/v1/audit/log Request:

{
  "action": "report_resolved",
  "target_user_id": "uuid",
  "details": {}
}

Implementation Plan

Phase 2A: Add Missing Django Endpoints (~2-3 hours)

1. Add Batch Fetch Endpoints

File: django/api/v1/endpoints/auth.py

@router.get("/users/batch", response={200: List[UserProfileOut]})
def batch_get_users(request, ids: str = Query(..., description="Comma-separated user IDs")):
    """Batch fetch users by IDs"""
    user_ids = [id.strip() for id in ids.split(',')]
    users = User.objects.filter(id__in=user_ids)
    return list(users)

File: django/api/v1/endpoints/reviews.py

@router.get("/batch", response={200: List[ReviewOut]})
def batch_get_reviews(request, ids: str = Query(..., description="Comma-separated review IDs")):
    """Batch fetch reviews by IDs"""
    review_ids = [id.strip() for id in ids.split(',')]
    reviews = Review.objects.filter(id__in=review_ids).select_related('user')
    return [_serialize_review(review) for review in reviews]

File: django/api/v1/endpoints/moderation.py

@router.get('/submissions/batch', response={200: List[ContentSubmissionOut]})
def batch_get_submissions(request, ids: str = Query(..., description="Comma-separated submission IDs")):
    """Batch fetch submissions by IDs"""
    submission_ids = [id.strip() for id in ids.split(',')]
    submissions = ContentSubmission.objects.filter(id__in=submission_ids)
    return [_submission_to_dict(sub) for sub in submissions]

2. Add Moderation Statistics Endpoint

File: django/api/v1/endpoints/moderation.py

@router.get('/stats', response={200: ModerationStatsOut})
def get_moderation_stats(request):
    """Get moderation queue statistics"""
    from django.db.models import Count, Q
    from apps.reviews.models import Review
    
    pending_submissions = ContentSubmission.objects.filter(
        status='pending'
    ).count()
    
    reviewing_submissions = ContentSubmission.objects.filter(
        status='reviewing'
    ).count()
    
    flagged_reviews = Review.objects.filter(
        moderation_status='flagged'
    ).count()
    
    return {
        'pending_submissions': pending_submissions,
        'reviewing_submissions': reviewing_submissions,
        'flagged_reviews': flagged_reviews
    }

3. Add Audit Logging Endpoint

File: django/api/v1/endpoints/audit.py (NEW)

from ninja import Router
from apps.users.permissions import jwt_auth, require_auth

router = Router(tags=['Audit'])

@router.post("/log", auth=jwt_auth, response={201: MessageSchema})
@require_auth
def log_admin_action(request, data: AdminActionLog):
    """Log an admin action for audit trail"""
    # TODO: Implement audit logging
    # Could use django-auditlog or custom model
    return 201, {"message": "Action logged", "success": True}

Phase 2B: Create Frontend Service Layers (~3-4 hours)

1. Users Service (src/services/users/)

Structure:

src/services/users/
├── types.ts           # User interfaces
├── mappers.ts         # Data transformation
├── usersService.ts    # API client
└── index.ts           # Exports

Key Methods:

  • getUserProfile(userId: string)
  • getUserProfiles(userIds: string[]) - batch fetch
  • getCurrentUser()

2. Reviews Service (src/services/reviews/)

Structure:

src/services/reviews/
├── types.ts
├── mappers.ts
├── reviewsService.ts
└── index.ts

Key Methods:

  • getReview(reviewId: string)
  • getReviews(reviewIds: string[]) - batch fetch
  • getReviewsByEntity(entityType, entityId)

3. Submissions Service (src/services/submissions/)

Structure:

src/services/submissions/
├── types.ts
├── mappers.ts
├── submissionsService.ts
└── index.ts

Key Methods:

  • getSubmission(submissionId: string)
  • getSubmissions(submissionIds: string[]) - batch fetch
  • getSubmissionStats()

4. Audit Service (src/services/audit/)

Structure:

src/services/audit/
├── types.ts
├── auditService.ts
└── index.ts

Key Methods:

  • logAdminAction(action, targetUserId, details)

Phase 2C: Update Components (~2-3 hours)

Update ReportsQueue.tsx

Changes:

  1. Replace reporter profile fetching:
// BEFORE
const { data: allProfiles } = await supabase.rpc('get_users_with_emails');

// AFTER
import { usersService } from '@/services/users';
const result = await usersService.getUserProfiles(reporterIds);
const profiles = result.success ? result.data : [];
  1. Replace related content fetching:
// BEFORE
const { data: reviewsData } = await supabase.from('reviews')
  .select('id, title, content, rating')
  .in('id', reviewIds);

// AFTER
import { reviewsService } from '@/services/reviews';
const result = await reviewsService.getReviews(reviewIds);
const reviewsData = result.success ? result.data : [];
  1. Replace audit logging:
// BEFORE
await supabase.rpc('log_admin_action', {...});

// AFTER
import { auditService } from '@/services/audit';
await auditService.logAdminAction(action, targetUserId, details);
  1. Remove Supabase import

Update useModerationStats.ts

Changes:

  1. Replace submission stats:
// BEFORE
const { count } = await supabase.from('content_submissions')
  .select('*', { count: 'exact', head: true })
  .eq('status', 'pending');

// AFTER
import { submissionsService } from '@/services/submissions';
const result = await submissionsService.getStats();
const pendingSubmissions = result.success ? result.data.pending_submissions : 0;
  1. Replace flagged reviews stats:
// BEFORE
const { count } = await supabase.from('reviews')
  .select('*', { count: 'exact', head: true })
  .eq('moderation_status', 'flagged');

// AFTER
// Use moderation stats endpoint from submissions service
const flaggedContent = result.success ? result.data.flagged_reviews : 0;
  1. Remove realtime subscriptions, rely on polling only

  2. Remove Supabase import

Phase 2D: Testing (~2 hours)

  1. Unit Tests

    • Test each service layer method
    • Test data mappers
    • Test error handling
  2. Integration Tests

    • Test component integration
    • Test data flow
    • Test error scenarios
  3. E2E Tests

    • Test complete report flow
    • Test stats updates
    • Test audit logging

Estimated Timeline

Phase Task Time Dependencies
2A Add Django endpoints 2-3 hrs None
2B Create service layers 3-4 hrs Phase 2A
2C Update components 2-3 hrs Phase 2B
2D Testing 2 hrs Phase 2C
Total 9-12 hrs

Alternative: Simplified Approach

If full batch endpoints are too much work, we can:

  1. Keep individual fetches - Less efficient but simpler
  2. Use existing filter parameters - e.g., filter by entity_id instead of batch IDs
  3. Skip audit logging - Remove audit log calls entirely for now

This would reduce Phase 2A to just adding the moderation stats endpoint (~30 min).

Recommendation

Option 1: Full Implementation (9-12 hours)

  • Complete Supabase removal
  • Optimal performance with batch endpoints
  • Full feature parity

Option 2: Simplified (4-6 hours)

  • Skip batch endpoints, fetch individually
  • Add only stats endpoint
  • Remove audit logging calls
  • Still removes all Supabase dependencies

Option 3: Phased Approach

  • Phase 2A: Stats endpoint only (30 min)
  • Phase 2B: Service layers with individual fetches (2-3 hrs)
  • Phase 2C: Update components (2-3 hrs)
  • Phase 2D: Testing (2 hrs)
  • Total: 6.5-8.5 hours
  • Later: Add batch endpoints for optimization

Decision Point

Which approach would you like to proceed with?

  1. Full implementation with batch endpoints
  2. Simplified without batch endpoints
  3. Phased approach (recommended for incremental progress)