diff --git a/src/app/api/auth/register/route.ts b/src/app/api/auth/register/route.ts index 208effe..9ac66fe 100644 --- a/src/app/api/auth/register/route.ts +++ b/src/app/api/auth/register/route.ts @@ -122,9 +122,19 @@ export async function POST(request: NextRequest) { }) .returning(); - // 创建默认用户设置 + // 创建默认用户设置(API Key 为空,需要用户自行配置) await db.insert(userSettings).values({ userId, + cchUrl: process.env.CCH_DEFAULT_URL || 'https://claude.leocoder.cn/', + cchApiKey: null, + cchApiKeyConfigured: false, + defaultModel: 'claude-sonnet-4-20250514', + defaultTools: ['web_search', 'code_execution', 'web_fetch'], + theme: 'light', + language: 'zh-CN', + fontSize: 15, + enableThinking: false, + saveChatHistory: true, }); // 生成 JWT Token diff --git a/src/app/api/settings/route.ts b/src/app/api/settings/route.ts index 100520b..6fa0000 100644 --- a/src/app/api/settings/route.ts +++ b/src/app/api/settings/route.ts @@ -2,45 +2,81 @@ import { NextResponse } from 'next/server'; import { db } from '@/drizzle/db'; import { userSettings } from '@/drizzle/schema'; import { eq } from 'drizzle-orm'; +import { getCurrentUser } from '@/lib/auth'; +import { encryptApiKey } from '@/lib/crypto'; -// GET /api/settings - 获取用户设置 +// 默认设置值 +const DEFAULT_SETTINGS = { + cchUrl: process.env.CCH_DEFAULT_URL || 'https://claude.leocoder.cn/', + cchApiKeyConfigured: false, + defaultModel: 'claude-sonnet-4-20250514', + defaultTools: ['web_search', 'code_execution', 'web_fetch'], + systemPrompt: '', + temperature: '0.7', + theme: 'light', + language: 'zh-CN', + fontSize: 15, + enableThinking: false, + saveChatHistory: true, +}; + +// 格式化设置响应(不返回 API Key 本身) +function formatSettingsResponse(settings: typeof userSettings.$inferSelect | null) { + if (!settings) { + return DEFAULT_SETTINGS; + } + + return { + cchUrl: settings.cchUrl || DEFAULT_SETTINGS.cchUrl, + cchApiKeyConfigured: settings.cchApiKeyConfigured || false, + defaultModel: settings.defaultModel || DEFAULT_SETTINGS.defaultModel, + defaultTools: settings.defaultTools || DEFAULT_SETTINGS.defaultTools, + systemPrompt: settings.systemPrompt || '', + temperature: settings.temperature || '0.7', + theme: settings.theme || DEFAULT_SETTINGS.theme, + language: settings.language || DEFAULT_SETTINGS.language, + fontSize: settings.fontSize || 15, + enableThinking: settings.enableThinking || false, + saveChatHistory: settings.saveChatHistory ?? true, + }; +} + +// GET /api/settings - 获取当前用户的设置 export async function GET() { try { - const settings = await db.query.userSettings.findFirst({ - where: eq(userSettings.id, 1), - }); - - if (!settings) { - // 如果没有设置,返回默认值 - return NextResponse.json({ - cchUrl: process.env.CCH_DEFAULT_URL || 'http://localhost:13500', - cchApiKeyConfigured: false, - defaultModel: 'claude-sonnet-4-20250514', - defaultTools: ['web_search', 'code_execution', 'web_fetch'], - systemPrompt: '', - temperature: '0.7', - theme: 'light', - language: 'zh-CN', - fontSize: 15, - enableThinking: false, - saveChatHistory: true, - }); + // 1. 获取当前登录用户 + const user = await getCurrentUser(); + if (!user) { + // 未登录用户返回默认设置(允许查看但无法保存) + return NextResponse.json(DEFAULT_SETTINGS); } - // 不返回 API Key 本身,只返回是否已配置 - return NextResponse.json({ - cchUrl: settings.cchUrl, - cchApiKeyConfigured: settings.cchApiKeyConfigured, - defaultModel: settings.defaultModel, - defaultTools: settings.defaultTools, - systemPrompt: settings.systemPrompt || '', - temperature: settings.temperature || '0.7', - theme: settings.theme, - language: settings.language, - fontSize: settings.fontSize || 15, - enableThinking: settings.enableThinking, - saveChatHistory: settings.saveChatHistory, + // 2. 查询该用户的设置 + const settings = await db.query.userSettings.findFirst({ + where: eq(userSettings.userId, user.userId), }); + + // 3. 如果没有设置记录,创建默认设置 + if (!settings) { + const newSettings = await db + .insert(userSettings) + .values({ + userId: user.userId, + cchUrl: DEFAULT_SETTINGS.cchUrl, + defaultModel: DEFAULT_SETTINGS.defaultModel, + defaultTools: DEFAULT_SETTINGS.defaultTools, + theme: DEFAULT_SETTINGS.theme, + language: DEFAULT_SETTINGS.language, + fontSize: DEFAULT_SETTINGS.fontSize, + enableThinking: DEFAULT_SETTINGS.enableThinking, + saveChatHistory: DEFAULT_SETTINGS.saveChatHistory, + }) + .returning(); + + return NextResponse.json(formatSettingsResponse(newSettings[0])); + } + + return NextResponse.json(formatSettingsResponse(settings)); } catch (error) { console.error('Failed to get settings:', error); return NextResponse.json( @@ -50,9 +86,18 @@ export async function GET() { } } -// PUT /api/settings - 更新用户设置 +// PUT /api/settings - 更新当前用户的设置 export async function PUT(request: Request) { try { + // 1. 获取当前登录用户 + const user = await getCurrentUser(); + if (!user) { + return NextResponse.json( + { error: '请先登录后再修改设置' }, + { status: 401 } + ); + } + const body = await request.json(); const { cchUrl, @@ -68,7 +113,7 @@ export async function PUT(request: Request) { saveChatHistory, } = body; - // 构建更新对象 + // 2. 构建更新对象 const updateData: Record = { updatedAt: new Date(), }; @@ -77,14 +122,15 @@ export async function PUT(request: Request) { updateData.cchUrl = cchUrl; } - // 如果提供了 API Key,更新它 + // 如果提供了 API Key,加密后存储 if (cchApiKey !== undefined) { if (cchApiKey === '') { // 清除 API Key updateData.cchApiKey = null; updateData.cchApiKeyConfigured = false; } else { - updateData.cchApiKey = cchApiKey; + // 加密存储 API Key + updateData.cchApiKey = encryptApiKey(cchApiKey); updateData.cchApiKeyConfigured = true; } } @@ -126,15 +172,23 @@ export async function PUT(request: Request) { updateData.saveChatHistory = saveChatHistory; } - // 检查是否存在设置记录 + // 3. 检查是否存在该用户的设置记录 const existing = await db.query.userSettings.findFirst({ - where: eq(userSettings.id, 1), + where: eq(userSettings.userId, user.userId), }); if (!existing) { // 创建新的设置记录 await db.insert(userSettings).values({ - id: 1, + userId: user.userId, + cchUrl: DEFAULT_SETTINGS.cchUrl, + defaultModel: DEFAULT_SETTINGS.defaultModel, + defaultTools: DEFAULT_SETTINGS.defaultTools, + theme: DEFAULT_SETTINGS.theme, + language: DEFAULT_SETTINGS.language, + fontSize: DEFAULT_SETTINGS.fontSize, + enableThinking: DEFAULT_SETTINGS.enableThinking, + saveChatHistory: DEFAULT_SETTINGS.saveChatHistory, ...updateData, }); } else { @@ -142,27 +196,15 @@ export async function PUT(request: Request) { await db .update(userSettings) .set(updateData) - .where(eq(userSettings.id, 1)); + .where(eq(userSettings.userId, user.userId)); } - // 返回更新后的设置(不包含 API Key) + // 4. 返回更新后的设置(不包含 API Key) const updatedSettings = await db.query.userSettings.findFirst({ - where: eq(userSettings.id, 1), + where: eq(userSettings.userId, user.userId), }); - return NextResponse.json({ - cchUrl: updatedSettings?.cchUrl, - cchApiKeyConfigured: updatedSettings?.cchApiKeyConfigured, - defaultModel: updatedSettings?.defaultModel, - defaultTools: updatedSettings?.defaultTools, - systemPrompt: updatedSettings?.systemPrompt || '', - temperature: updatedSettings?.temperature || '0.7', - theme: updatedSettings?.theme, - language: updatedSettings?.language, - fontSize: updatedSettings?.fontSize || 15, - enableThinking: updatedSettings?.enableThinking, - saveChatHistory: updatedSettings?.saveChatHistory, - }); + return NextResponse.json(formatSettingsResponse(updatedSettings ?? null)); } catch (error) { console.error('Failed to update settings:', error); return NextResponse.json(