diff --git a/src/app/api/auth/login/route.ts b/src/app/api/auth/login/route.ts index f7b168e..7496160 100644 --- a/src/app/api/auth/login/route.ts +++ b/src/app/api/auth/login/route.ts @@ -24,12 +24,13 @@ export async function POST(request: NextRequest) { // localadmin 密码验证(查询数据库存储的密码) if (username === 'localadmin') { - const users = dbQuery<{ password_hash: string; role: string }>(`SELECT password_hash, role FROM users WHERE username = 'localadmin'`) + const users = dbQuery<{ password_hash: string; role: string; display_name: string | null }>(`SELECT password_hash, role, display_name FROM users WHERE username = 'localadmin'`) if (users.length === 0) { return NextResponse.json({ error: 'localadmin 未配置' }, { status: 401 }) } + const localadminUser = users[0] // 与数据库存储的 bcrypt 哈希比较 - if (!bcrypt.compareSync(password, users[0].password_hash)) { + if (!bcrypt.compareSync(password, localadminUser.password_hash)) { writeAuditLog({ exec: dbExec }, { username, action: 'login_failed', entityType: 'auth', details: { method: 'localadmin', reason: 'wrong_password' }, @@ -38,7 +39,9 @@ export async function POST(request: NextRequest) { return NextResponse.json({ error: '密码错误' }, { status: 401 }) } - const token = signJwt({ secret: authConfig.jwtSecret, payload: { username: 'localadmin', role: 'admin', displayName: 'localadmin' } }) + const displayName = localadminUser.display_name || 'localadmin' + const role = localadminUser.role || 'admin' + const token = signJwt({ secret: authConfig.jwtSecret, payload: { username: 'localadmin', role, displayName } }) writeAuditLog({ exec: dbExec }, { username, action: 'login', entityType: 'auth', @@ -47,7 +50,7 @@ export async function POST(request: NextRequest) { }) const response = NextResponse.json({ - user: { username: 'localadmin', role: 'admin', displayName: 'localadmin' }, + user: { username: 'localadmin', role, displayName }, }) response.cookies.set('tlyq_session', token, { httpOnly: true, secure: false, sameSite: 'lax', path: '/', maxAge: 604800, diff --git a/src/app/client-layout.tsx b/src/app/client-layout.tsx index 4912cbf..f8b9a5f 100644 --- a/src/app/client-layout.tsx +++ b/src/app/client-layout.tsx @@ -28,7 +28,7 @@ export default function ClientLayout({ children }: { children: React.ReactNode } return (
- +
{children}
diff --git a/src/components/Sidebar.tsx b/src/components/Sidebar.tsx index e05a7c3..b07f506 100644 --- a/src/components/Sidebar.tsx +++ b/src/components/Sidebar.tsx @@ -8,13 +8,10 @@ import { hasPermission } from '@/lib/permissions' interface NavItem { label: string; href: string; icon: React.ComponentType<{ size?: number }>; permission?: string } interface NavSection { title?: string; items: NavItem[] } -export default function Sidebar() { +export default function Sidebar({ userRole = 'viewer' }: { userRole?: string }) { const pathname = usePathname() const isActive = (href: string) => pathname === href || (href !== '/' && pathname.startsWith(href)) - // 默认显示所有导航项(客户端权限在 API 层强制验证,此处仅 UI 过滤) - const userRole = 'admin' // TODO: 从 cookie 或 session 读取实际角色 - const sections: NavSection[] = [ { items: [