Initial commit

This commit is contained in:
root
2026-01-26 08:34:48 +01:00
commit 387314581f
216 changed files with 81204 additions and 0 deletions
+152
View File
@@ -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 }
);
}
}