From c876a69443e403d8ceee48460b0338cd8de6bd44 Mon Sep 17 00:00:00 2001 From: aiyimickey <39365912+aiyimickey@users.noreply.github.com> Date: Thu, 2 Jul 2026 11:25:44 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20localadmin=20displayName=20=E4=BB=8E?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=E5=BA=93=E8=AF=BB=E5=8F=96=EF=BC=9BSidebar?= =?UTF-8?q?=20=E6=9D=83=E9=99=90=E9=A9=B1=E5=8A=A8=E5=AF=BC=E8=88=AA?= =?UTF-8?q?=EF=BC=88userRole=20prop=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/api/auth/login/route.ts | 11 +++++++---- src/app/client-layout.tsx | 2 +- src/components/Sidebar.tsx | 5 +---- 3 files changed, 9 insertions(+), 9 deletions(-) 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: [