Compare commits
No commits in common. "ada95e4e7fe37459344a921422ee1fa376810d70" and "629924c342315d294faf133baecb28e9233a5bc3" have entirely different histories.
ada95e4e7f
...
629924c342
|
|
@ -3,7 +3,7 @@ import { cookies } from 'next/headers'
|
||||||
import { getDb } from '@/lib/db'
|
import { getDb } from '@/lib/db'
|
||||||
import { verifyToken } from '@/lib/auth'
|
import { verifyToken } from '@/lib/auth'
|
||||||
import { checkPermission } from '@/lib/permissions'
|
import { checkPermission } from '@/lib/permissions'
|
||||||
import { writeAuditLog, getClientIP, diffObjects } from '@/lib/audit'
|
import { writeAuditLog, getClientIP } from '@/lib/audit'
|
||||||
|
|
||||||
async function getSession() {
|
async function getSession() {
|
||||||
const cookieStore = await cookies()
|
const cookieStore = await cookies()
|
||||||
|
|
@ -20,8 +20,7 @@ export async function PUT(request: Request, { params }: { params: Promise<{ id:
|
||||||
}
|
}
|
||||||
|
|
||||||
const { id } = await params
|
const { id } = await params
|
||||||
type ApiKeyRow = { id: number; name: string; permissions: string; expires_at: string | null; is_active: number }
|
const existing = getDb().prepare('SELECT id FROM api_keys WHERE id = ?').get(id)
|
||||||
const existing = getDb().prepare<[string | number], ApiKeyRow>('SELECT id, name, permissions, expires_at, is_active FROM api_keys WHERE id = ?').get(id)
|
|
||||||
if (!existing) return NextResponse.json({ error: 'API Key 不存在' }, { status: 404 })
|
if (!existing) return NextResponse.json({ error: 'API Key 不存在' }, { status: 404 })
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
@ -36,20 +35,6 @@ export async function PUT(request: Request, { params }: { params: Promise<{ id:
|
||||||
is_active !== undefined ? (is_active ? 1 : 0) : 1,
|
is_active !== undefined ? (is_active ? 1 : 0) : 1,
|
||||||
id
|
id
|
||||||
)
|
)
|
||||||
|
|
||||||
// 审计日志
|
|
||||||
const changes = diffObjects(existing as unknown as Record<string, unknown>, body)
|
|
||||||
if (Object.keys(changes).length > 0) {
|
|
||||||
writeAuditLog({
|
|
||||||
userId: session.id,
|
|
||||||
action: 'update',
|
|
||||||
entityType: 'api_key',
|
|
||||||
entityId: Number(id),
|
|
||||||
details: { changes },
|
|
||||||
ipAddress: getClientIP(request),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
return NextResponse.json({ success: true })
|
return NextResponse.json({ success: true })
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
const msg = e instanceof Error ? e.message : '更新失败'
|
const msg = e instanceof Error ? e.message : '更新失败'
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
// GET + POST /api/auth/logout — 退出登录(清除 cookie + 302 跳转 /login)
|
// GET + POST /api/auth/logout — 退出登录(清除 cookie + 302 跳转 /login)
|
||||||
import { NextRequest, NextResponse } from 'next/server'
|
import { NextResponse } from 'next/server'
|
||||||
import { writeAuditLog, getClientIP } from '@/lib/audit'
|
|
||||||
|
|
||||||
const cookieDomain = process.env.COOKIE_DOMAIN || '.tlyq.ai'
|
const cookieDomain = process.env.COOKIE_DOMAIN || '.tlyq.ai'
|
||||||
|
|
||||||
|
|
@ -23,28 +22,4 @@ function logoutResponse(): NextResponse {
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function GET() { return logoutResponse() }
|
export async function GET() { return logoutResponse() }
|
||||||
|
export async function POST() { return logoutResponse() }
|
||||||
export async function POST(request: NextRequest) {
|
|
||||||
// 从 session cookie 提取用户名用于审计
|
|
||||||
let username = 'anonymous'
|
|
||||||
try {
|
|
||||||
const token =
|
|
||||||
request.cookies.get('tlyq_session')?.value ||
|
|
||||||
request.cookies.get('session_issue')?.value
|
|
||||||
if (token) {
|
|
||||||
const payload = JSON.parse(Buffer.from(token.split('.')[1], 'base64').toString())
|
|
||||||
username = payload.username || 'unknown'
|
|
||||||
}
|
|
||||||
} catch { /* 解析失败,使用默认值 */ }
|
|
||||||
|
|
||||||
writeAuditLog({
|
|
||||||
userId: null,
|
|
||||||
username,
|
|
||||||
action: 'logout',
|
|
||||||
entityType: 'auth',
|
|
||||||
details: { message: '用户登出' },
|
|
||||||
ipAddress: getClientIP(request),
|
|
||||||
})
|
|
||||||
|
|
||||||
return logoutResponse()
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,6 @@ import { getDb } from '@/lib/db'
|
||||||
import { initDatabase } from '@/lib/db-schema'
|
import { initDatabase } from '@/lib/db-schema'
|
||||||
import { getCurrentUser } from '@/lib/auth'
|
import { getCurrentUser } from '@/lib/auth'
|
||||||
import { hasPermission } from '@/lib/permissions'
|
import { hasPermission } from '@/lib/permissions'
|
||||||
import { writeAuditLog, getClientIP } from '@/lib/audit'
|
|
||||||
import fs from 'fs'
|
import fs from 'fs'
|
||||||
|
|
||||||
export async function GET(_request: Request, { params }: { params: Promise<{ id: string }> }) {
|
export async function GET(_request: Request, { params }: { params: Promise<{ id: string }> }) {
|
||||||
|
|
@ -90,16 +89,6 @@ export async function DELETE(_request: NextRequest, { params }: { params: Promis
|
||||||
// 删除数据库记录
|
// 删除数据库记录
|
||||||
db.prepare('DELETE FROM reports WHERE id = ?').run(id)
|
db.prepare('DELETE FROM reports WHERE id = ?').run(id)
|
||||||
|
|
||||||
writeAuditLog({
|
|
||||||
userId: user.id,
|
|
||||||
apiKeyId: null,
|
|
||||||
action: 'delete',
|
|
||||||
entityType: 'report',
|
|
||||||
entityId: Number(id),
|
|
||||||
details: { deleted: { id: Number(id), title: report.title, type: report.type, period_start: report.period_start, period_end: report.period_end, file_path: report.file_path } },
|
|
||||||
ipAddress: getClientIP(_request),
|
|
||||||
})
|
|
||||||
|
|
||||||
return NextResponse.json({ success: true })
|
return NextResponse.json({ success: true })
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
const msg = e instanceof Error ? e.message : '删除失败'
|
const msg = e instanceof Error ? e.message : '删除失败'
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,6 @@ import { getDb } from '@/lib/db'
|
||||||
import { initDatabase } from '@/lib/db-schema'
|
import { initDatabase } from '@/lib/db-schema'
|
||||||
import { getCurrentUser } from '@/lib/auth'
|
import { getCurrentUser } from '@/lib/auth'
|
||||||
import { hasPermission } from '@/lib/permissions'
|
import { hasPermission } from '@/lib/permissions'
|
||||||
import { writeAuditLog, getClientIP } from '@/lib/audit'
|
|
||||||
import JSZip from 'jszip'
|
import JSZip from 'jszip'
|
||||||
import fs from 'fs'
|
import fs from 'fs'
|
||||||
|
|
||||||
|
|
@ -44,16 +43,6 @@ export async function POST(request: NextRequest) {
|
||||||
|
|
||||||
const zipBuffer = await zip.generateAsync({ type: 'nodebuffer' })
|
const zipBuffer = await zip.generateAsync({ type: 'nodebuffer' })
|
||||||
|
|
||||||
writeAuditLog({
|
|
||||||
userId: user.id,
|
|
||||||
apiKeyId: null,
|
|
||||||
action: 'export',
|
|
||||||
entityType: 'report',
|
|
||||||
entityId: null,
|
|
||||||
details: { exported_count: ids.length, ids },
|
|
||||||
ipAddress: getClientIP(request),
|
|
||||||
})
|
|
||||||
|
|
||||||
const d = new Date()
|
const d = new Date()
|
||||||
const today = `${d.getFullYear()}-${String(d.getMonth()+1).padStart(2,'0')}-${String(d.getDate()).padStart(2,'0')}`
|
const today = `${d.getFullYear()}-${String(d.getMonth()+1).padStart(2,'0')}-${String(d.getDate()).padStart(2,'0')}`
|
||||||
const downloadName = `reports_${today}.zip`
|
const downloadName = `reports_${today}.zip`
|
||||||
|
|
|
||||||
|
|
@ -17,10 +17,6 @@ export function initDatabase(): void {
|
||||||
|
|
||||||
// 迁移:添加 parts_name 列
|
// 迁移:添加 parts_name 列
|
||||||
try { db.exec('ALTER TABLE tickets ADD COLUMN parts_name TEXT') } catch { /* 列已存在 */ }
|
try { db.exec('ALTER TABLE tickets ADD COLUMN parts_name TEXT') } catch { /* 列已存在 */ }
|
||||||
// 迁移:添加 audit_logs.username 列(共享库 write-audit-log.ts 写入此列)
|
|
||||||
try { db.exec('ALTER TABLE audit_logs ADD COLUMN username TEXT') } catch { /* 列已存在 */ }
|
|
||||||
// 迁移:添加 audit_logs.api_key_id 列(共享库 audit-schema.ts 已定义)
|
|
||||||
try { db.exec('ALTER TABLE audit_logs ADD COLUMN api_key_id INTEGER REFERENCES api_keys(id)') } catch { /* 列已存在 */ }
|
|
||||||
|
|
||||||
// 迁移:添加 ticket_type 列
|
// 迁移:添加 ticket_type 列
|
||||||
try { db.exec('ALTER TABLE tickets ADD COLUMN ticket_type TEXT') } catch { /* 列已存在 */ }
|
try { db.exec('ALTER TABLE tickets ADD COLUMN ticket_type TEXT') } catch { /* 列已存在 */ }
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue