← back to Wine Finder Next

app/api/membership/samples/route.ts

65 lines

import { NextRequest, NextResponse } from 'next/server';
import { sampleUnitDb, sampleRightDb } from '@/lib/membershipDatabase';
import type { ApiResponse } from '@/src/types/membership';
import { checkRateLimit, getRateLimitConfig, getClientIdentifier } from '@/lib/rateLimit';
import { logAudit } from '@/lib/auth';
import { sanitizeString, validateBottleId } from '@/lib/inputValidation';

export async function GET(request: NextRequest) {
  try {
    // Rate limiting
    const identifier = getClientIdentifier(request);
    const rateLimit = checkRateLimit(identifier, getRateLimitConfig('/api/membership/samples'));

    if (!rateLimit.success) {
      return NextResponse.json({
        success: false,
        error: 'Rate limit exceeded. Please try again later.'
      } as ApiResponse<null>, { status: 429 });
    }

    const { searchParams } = new URL(request.url);
    const bottleId = searchParams.get('bottleId');
    const availableOnly = searchParams.get('available') === 'true';

    // Validate bottleId if provided
    if (bottleId) {
      const sanitizedBottleId = sanitizeString(bottleId, 100);
      if (!validateBottleId(sanitizedBottleId)) {
        return NextResponse.json({
          success: false,
          error: 'Invalid bottle ID format'
        } as ApiResponse<null>, { status: 400 });
      }
    }

    let samples;
    if (availableOnly) {
      samples = sampleUnitDb.getAvailable(bottleId ? sanitizeString(bottleId, 100) : undefined);
    } else if (bottleId) {
      samples = sampleUnitDb.getByBottleId(sanitizeString(bottleId, 100));
    } else {
      samples = sampleUnitDb.getAll();
    }

    logAudit({
      action: 'SAMPLES_LIST',
      resource: 'samples',
      ipAddress: identifier,
      userAgent: request.headers.get('user-agent') || 'unknown',
      success: true,
      metadata: { count: samples.length, bottleId, availableOnly }
    });

    return NextResponse.json({
      success: true,
      data: samples
    } as ApiResponse<typeof samples>);
  } catch (error) {
    return NextResponse.json({
      success: false,
      error: 'Failed to fetch samples'
    } as ApiResponse<null>, { status: 500 });
  }
}