Initial commit
This commit is contained in:
@@ -0,0 +1,152 @@
|
||||
/**
|
||||
* Bot API Key Management Routes
|
||||
*
|
||||
* POST /api/bots/[id]/api-key - Set/update LLM API key
|
||||
* DELETE /api/bots/[id]/api-key - Remove API key
|
||||
*
|
||||
* Requirements: 2.1, 2.2, 2.4
|
||||
*/
|
||||
|
||||
import { NextResponse } from 'next/server';
|
||||
import { requireAuth } from '@/lib/auth';
|
||||
import { z } from 'zod';
|
||||
import {
|
||||
getBotById,
|
||||
userOwnsBot,
|
||||
setApiKey,
|
||||
removeApiKey,
|
||||
BotNotFoundError,
|
||||
BotValidationError,
|
||||
} from '@/lib/bots/botManager';
|
||||
|
||||
type RouteContext = { params: Promise<{ id: string }> };
|
||||
|
||||
// Schema for setting API key
|
||||
const setApiKeySchema = z.object({
|
||||
apiKey: z.string().min(1, 'API key is required'),
|
||||
provider: z.enum(['openrouter', 'openai', 'anthropic']).optional(),
|
||||
});
|
||||
|
||||
/**
|
||||
* POST /api/bots/[id]/api-key - Set/update LLM API key
|
||||
*
|
||||
* Requires authentication.
|
||||
* Sets or updates the API key for the bot's LLM provider.
|
||||
* The API key is validated and encrypted before storage.
|
||||
*
|
||||
* Validates: Requirements 2.1, 2.2, 2.4
|
||||
*/
|
||||
export async function POST(request: Request, context: RouteContext) {
|
||||
try {
|
||||
const user = await requireAuth();
|
||||
const { id } = await context.params;
|
||||
const body = await request.json();
|
||||
const data = setApiKeySchema.parse(body);
|
||||
|
||||
// Check if user owns the bot
|
||||
const isOwner = await userOwnsBot(user.id, id);
|
||||
if (!isOwner) {
|
||||
// Check if bot exists at all
|
||||
const bot = await getBotById(id);
|
||||
if (!bot) {
|
||||
return NextResponse.json({ error: 'Bot not found' }, { status: 404 });
|
||||
}
|
||||
return NextResponse.json({ error: 'Not authorized' }, { status: 403 });
|
||||
}
|
||||
|
||||
// Set the API key (validates format and encrypts)
|
||||
await setApiKey(id, data.apiKey, data.provider);
|
||||
|
||||
return NextResponse.json({
|
||||
success: true,
|
||||
message: 'API key updated successfully',
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Set API key error:', error);
|
||||
|
||||
if (error instanceof z.ZodError) {
|
||||
return NextResponse.json(
|
||||
{ error: 'Invalid input', details: error.issues },
|
||||
{ status: 400 }
|
||||
);
|
||||
}
|
||||
|
||||
if (error instanceof Error && error.message === 'Authentication required') {
|
||||
return NextResponse.json({ error: 'Authentication required' }, { status: 401 });
|
||||
}
|
||||
|
||||
if (error instanceof BotNotFoundError) {
|
||||
return NextResponse.json(
|
||||
{ error: error.message, code: error.code },
|
||||
{ status: 404 }
|
||||
);
|
||||
}
|
||||
|
||||
if (error instanceof BotValidationError) {
|
||||
return NextResponse.json(
|
||||
{ error: error.message, code: error.code },
|
||||
{ status: 400 }
|
||||
);
|
||||
}
|
||||
|
||||
return NextResponse.json(
|
||||
{ error: 'Failed to set API key' },
|
||||
{ status: 500 }
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* DELETE /api/bots/[id]/api-key - Remove API key
|
||||
*
|
||||
* Requires authentication.
|
||||
* Removes the API key from the bot, disabling LLM functionality.
|
||||
*
|
||||
* Note: Since the llmApiKeyEncrypted field is NOT NULL in the schema,
|
||||
* this sets the key to an empty encrypted value, effectively disabling it.
|
||||
*
|
||||
* Validates: Requirements 2.4
|
||||
*/
|
||||
export async function DELETE(_request: Request, context: RouteContext) {
|
||||
try {
|
||||
const user = await requireAuth();
|
||||
const { id } = await context.params;
|
||||
|
||||
// Check if user owns the bot
|
||||
const isOwner = await userOwnsBot(user.id, id);
|
||||
if (!isOwner) {
|
||||
// Check if bot exists at all
|
||||
const bot = await getBotById(id);
|
||||
if (!bot) {
|
||||
return NextResponse.json({ error: 'Bot not found' }, { status: 404 });
|
||||
}
|
||||
return NextResponse.json({ error: 'Not authorized' }, { status: 403 });
|
||||
}
|
||||
|
||||
// Remove the API key
|
||||
await removeApiKey(id);
|
||||
|
||||
return NextResponse.json({
|
||||
success: true,
|
||||
message: 'API key removed successfully',
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Remove API key error:', error);
|
||||
|
||||
if (error instanceof Error && error.message === 'Authentication required') {
|
||||
return NextResponse.json({ error: 'Authentication required' }, { status: 401 });
|
||||
}
|
||||
|
||||
if (error instanceof BotNotFoundError) {
|
||||
return NextResponse.json(
|
||||
{ error: error.message, code: error.code },
|
||||
{ status: 404 }
|
||||
);
|
||||
}
|
||||
|
||||
return NextResponse.json(
|
||||
{ error: 'Failed to remove API key' },
|
||||
{ status: 500 }
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user