diff --git a/src/app/api/config/[category]/route.ts b/src/app/api/config/[category]/route.ts deleted file mode 100644 index 607c60f..0000000 --- a/src/app/api/config/[category]/route.ts +++ /dev/null @@ -1,38 +0,0 @@ -/** - * Component: Configuration API Routes (by category) - * Documentation: documentation/backend/services/config.md - */ - -import { NextRequest, NextResponse } from 'next/server'; -import { getConfigService } from '@/lib/services/config.service'; -import { RMABLogger } from '@/lib/utils/logger'; - -const logger = RMABLogger.create('API.Config.Category'); - -// GET /api/config/:category - Get all config for a category -export async function GET( - request: NextRequest, - { params }: { params: Promise<{ category: string }> } -) { - try { - // TODO: Add authentication middleware - admin only - const { category } = await params; - const configService = getConfigService(); - - const config = await configService.getCategory(category); - - return NextResponse.json({ - category, - config, - }); - } catch (error) { - logger.error('Failed to get config for category', { error: error instanceof Error ? error.message : String(error) }); - return NextResponse.json( - { - error: 'Failed to get configuration', - message: error instanceof Error ? error.message : 'Unknown error', - }, - { status: 500 } - ); - } -} diff --git a/src/app/api/config/route.ts b/src/app/api/config/route.ts deleted file mode 100644 index f6d1e8c..0000000 --- a/src/app/api/config/route.ts +++ /dev/null @@ -1,84 +0,0 @@ -/** - * Component: Configuration API Routes - * Documentation: documentation/backend/services/config.md - */ - -import { NextRequest, NextResponse } from 'next/server'; -import { getConfigService, ConfigUpdate } from '@/lib/services/config.service'; -import { z } from 'zod'; -import { RMABLogger } from '@/lib/utils/logger'; - -const logger = RMABLogger.create('API.Config'); - -const ConfigUpdateSchema = z.object({ - updates: z.array( - z.object({ - key: z.string(), - value: z.string(), - encrypted: z.boolean().optional(), - category: z.string().optional(), - description: z.string().optional(), - }) - ), -}); - -// PUT /api/config - Update multiple configuration values -export async function PUT(request: NextRequest) { - try { - // TODO: Add authentication middleware - admin only - - const body = await request.json(); - const { updates } = ConfigUpdateSchema.parse(body); - - const configService = getConfigService(); - await configService.setMany(updates as ConfigUpdate[]); - - return NextResponse.json({ - success: true, - updated: updates.length, - }); - } catch (error) { - logger.error('Failed to update configuration', { error: error instanceof Error ? error.message : String(error) }); - - if (error instanceof z.ZodError) { - return NextResponse.json( - { - error: 'Validation error', - details: error.errors, - }, - { status: 400 } - ); - } - - return NextResponse.json( - { - error: 'Failed to update configuration', - message: error instanceof Error ? error.message : 'Unknown error', - }, - { status: 500 } - ); - } -} - -// GET /api/config - Get all configuration (masked sensitive values) -export async function GET() { - try { - // TODO: Add authentication middleware - admin only - - const configService = getConfigService(); - const allConfig = await configService.getAll(); - - return NextResponse.json({ - config: allConfig, - }); - } catch (error) { - logger.error('Failed to get all configuration', { error: error instanceof Error ? error.message : String(error) }); - return NextResponse.json( - { - error: 'Failed to get configuration', - message: error instanceof Error ? error.message : 'Unknown error', - }, - { status: 500 } - ); - } -} diff --git a/tests/api/config.routes.test.ts b/tests/api/config.routes.test.ts deleted file mode 100644 index 3777c8e..0000000 --- a/tests/api/config.routes.test.ts +++ /dev/null @@ -1,104 +0,0 @@ -/** - * Component: Config API Route Tests - * Documentation: documentation/testing.md - */ - -import { beforeEach, describe, expect, it, vi } from 'vitest'; - -const configServiceMock = vi.hoisted(() => ({ - setMany: vi.fn(), - getAll: vi.fn(), - getCategory: vi.fn(), -})); - -vi.mock('@/lib/services/config.service', () => ({ - getConfigService: () => configServiceMock, -})); - -describe('Config API routes', () => { - beforeEach(() => { - vi.clearAllMocks(); - }); - - it('returns full configuration', async () => { - configServiceMock.getAll.mockResolvedValue({ plex_url: 'http://plex' }); - const { GET } = await import('@/app/api/config/route'); - - const response = await GET(); - const payload = await response.json(); - - expect(payload.config.plex_url).toBe('http://plex'); - }); - - it('updates configuration values', async () => { - const { PUT } = await import('@/app/api/config/route'); - const response = await PUT({ - json: vi.fn().mockResolvedValue({ - updates: [{ key: 'plex_url', value: 'http://plex' }], - }), - } as any); - const payload = await response.json(); - - expect(response.status).toBe(200); - expect(payload.updated).toBe(1); - expect(configServiceMock.setMany).toHaveBeenCalled(); - }); - - it('returns 400 when configuration update payload is invalid', async () => { - const { PUT } = await import('@/app/api/config/route'); - const response = await PUT({ json: vi.fn().mockResolvedValue({}) } as any); - const payload = await response.json(); - - expect(response.status).toBe(400); - expect(payload.error).toMatch(/Validation error/); - }); - - it('returns 500 when configuration update fails', async () => { - configServiceMock.setMany.mockRejectedValueOnce(new Error('db down')); - const { PUT } = await import('@/app/api/config/route'); - const response = await PUT({ - json: vi.fn().mockResolvedValue({ - updates: [{ key: 'plex_url', value: 'http://plex' }], - }), - } as any); - const payload = await response.json(); - - expect(response.status).toBe(500); - expect(payload.error).toMatch(/Failed to update configuration/); - }); - - it('returns 500 when configuration lookup fails', async () => { - configServiceMock.getAll.mockRejectedValueOnce(new Error('db down')); - const { GET } = await import('@/app/api/config/route'); - - const response = await GET(); - const payload = await response.json(); - - expect(response.status).toBe(500); - expect(payload.error).toMatch(/Failed to get configuration/); - }); - - it('returns category configuration', async () => { - configServiceMock.getCategory.mockResolvedValue({ plex_url: 'http://plex' }); - const { GET } = await import('@/app/api/config/[category]/route'); - - const response = await GET({} as any, { params: Promise.resolve({ category: 'plex' }) }); - const payload = await response.json(); - - expect(payload.category).toBe('plex'); - expect(payload.config.plex_url).toBe('http://plex'); - }); - - it('returns 500 when category configuration lookup fails', async () => { - configServiceMock.getCategory.mockRejectedValueOnce(new Error('db down')); - const { GET } = await import('@/app/api/config/[category]/route'); - - const response = await GET({} as any, { params: Promise.resolve({ category: 'plex' }) }); - const payload = await response.json(); - - expect(response.status).toBe(500); - expect(payload.error).toMatch(/Failed to get configuration/); - }); -}); - -