Initial miaojingAI project with image resolution guard
This commit is contained in:
142
src/app/api/admin/system-apis/route.ts
Normal file
142
src/app/api/admin/system-apis/route.ts
Normal file
@@ -0,0 +1,142 @@
|
||||
import { NextRequest, NextResponse } from 'next/server';
|
||||
import { requireAdmin } from '@/lib/admin-auth';
|
||||
import { getDbClient } from '@/storage/database/local-db';
|
||||
import {
|
||||
encryptApiKeyForStorage,
|
||||
ensureSystemApiSchema,
|
||||
isUuid,
|
||||
listSystemApis,
|
||||
toSafeSystemApi,
|
||||
} from '@/lib/server-api-config';
|
||||
|
||||
async function readBody(request: NextRequest) {
|
||||
return request.json().catch(() => ({}));
|
||||
}
|
||||
|
||||
function normalizeType(value: unknown): 'image' | 'video' | 'text' {
|
||||
return value === 'video' || value === 'text' ? value : 'image';
|
||||
}
|
||||
|
||||
export async function GET(request: NextRequest) {
|
||||
const authError = await requireAdmin(request);
|
||||
if (authError) return authError;
|
||||
const includeInactive = request.nextUrl.searchParams.get('includeInactive') !== 'false';
|
||||
return NextResponse.json({ apis: await listSystemApis(includeInactive) });
|
||||
}
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
const authError = await requireAdmin(request);
|
||||
if (authError) return authError;
|
||||
|
||||
const body = await readBody(request);
|
||||
if (!body.name?.trim() || !body.modelName?.trim()) {
|
||||
return NextResponse.json({ error: '请填写显示名称和模型名称' }, { status: 400 });
|
||||
}
|
||||
|
||||
const secret = encryptApiKeyForStorage(String(body.apiKey || ''));
|
||||
const client = await getDbClient();
|
||||
try {
|
||||
await ensureSystemApiSchema(client);
|
||||
const result = await client.query(
|
||||
`INSERT INTO system_api_configs (
|
||||
provider, name, api_url, model_name, note, api_key_encrypted,
|
||||
api_key_preview, type, credits_per_use, is_active, sort_order
|
||||
)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10,
|
||||
COALESCE((SELECT MAX(sort_order) + 1 FROM system_api_configs), 0))
|
||||
RETURNING id, provider, name, api_url, model_name, note, api_key_preview,
|
||||
type, credits_per_use, is_active, sort_order, created_at, updated_at`,
|
||||
[
|
||||
String(body.provider || '').trim(),
|
||||
String(body.name).trim(),
|
||||
String(body.apiUrl || '').trim(),
|
||||
String(body.modelName).trim(),
|
||||
String(body.note || '').trim(),
|
||||
secret.encrypted,
|
||||
secret.preview,
|
||||
normalizeType(body.type),
|
||||
Number(body.creditsPerUse || 10),
|
||||
body.isActive !== false,
|
||||
],
|
||||
);
|
||||
return NextResponse.json({ api: toSafeSystemApi(result.rows[0]) });
|
||||
} finally {
|
||||
client.release();
|
||||
}
|
||||
}
|
||||
|
||||
export async function PUT(request: NextRequest) {
|
||||
const authError = await requireAdmin(request);
|
||||
if (authError) return authError;
|
||||
|
||||
const body = await readBody(request);
|
||||
if (!isUuid(body.id) || !body.name?.trim() || !body.modelName?.trim()) {
|
||||
return NextResponse.json({ error: '缺少 API ID、显示名称或模型名称' }, { status: 400 });
|
||||
}
|
||||
|
||||
const updates: string[] = [];
|
||||
const params: unknown[] = [];
|
||||
let idx = 1;
|
||||
const add = (column: string, value: unknown) => {
|
||||
updates.push(`${column} = $${idx++}`);
|
||||
params.push(value);
|
||||
};
|
||||
|
||||
add('provider', String(body.provider || '').trim());
|
||||
add('name', String(body.name).trim());
|
||||
add('api_url', String(body.apiUrl || '').trim());
|
||||
add('model_name', String(body.modelName).trim());
|
||||
add('note', String(body.note || '').trim());
|
||||
add('type', normalizeType(body.type));
|
||||
add('credits_per_use', Number(body.creditsPerUse || 10));
|
||||
add('is_active', body.isActive !== false);
|
||||
if (body.sortOrder !== undefined) add('sort_order', Number(body.sortOrder || 0));
|
||||
|
||||
if (typeof body.apiKey === 'string' && body.apiKey.trim() && body.apiKey !== '********') {
|
||||
const secret = encryptApiKeyForStorage(body.apiKey);
|
||||
add('api_key_encrypted', secret.encrypted);
|
||||
add('api_key_preview', secret.preview);
|
||||
}
|
||||
if (body.clearApiKey === true) {
|
||||
add('api_key_encrypted', '');
|
||||
add('api_key_preview', '');
|
||||
}
|
||||
updates.push('updated_at = NOW()');
|
||||
params.push(body.id);
|
||||
|
||||
const client = await getDbClient();
|
||||
try {
|
||||
await ensureSystemApiSchema(client);
|
||||
const result = await client.query(
|
||||
`UPDATE system_api_configs
|
||||
SET ${updates.join(', ')}
|
||||
WHERE id = $${idx}
|
||||
RETURNING id, provider, name, api_url, model_name, note, api_key_preview,
|
||||
type, credits_per_use, is_active, sort_order, created_at, updated_at`,
|
||||
params,
|
||||
);
|
||||
if (result.rows.length === 0) {
|
||||
return NextResponse.json({ error: '系统 API 不存在' }, { status: 404 });
|
||||
}
|
||||
return NextResponse.json({ api: toSafeSystemApi(result.rows[0]) });
|
||||
} finally {
|
||||
client.release();
|
||||
}
|
||||
}
|
||||
|
||||
export async function DELETE(request: NextRequest) {
|
||||
const authError = await requireAdmin(request);
|
||||
if (authError) return authError;
|
||||
const body = await readBody(request);
|
||||
const id = body.id || request.nextUrl.searchParams.get('id');
|
||||
if (!isUuid(id)) return NextResponse.json({ error: '缺少 API ID' }, { status: 400 });
|
||||
|
||||
const client = await getDbClient();
|
||||
try {
|
||||
await ensureSystemApiSchema(client);
|
||||
await client.query('DELETE FROM system_api_configs WHERE id = $1', [id]);
|
||||
return NextResponse.json({ success: true });
|
||||
} finally {
|
||||
client.release();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user