feat(web): add role-based menu item visibility

- Added platformRoles to User interface in UserMenu
- Implemented role checks for menu items:
  - Reviews: SKILL_ADMIN, NAMESPACE_ADMIN, SUPER_ADMIN
  - Promotions: SKILL_ADMIN, SUPER_ADMIN
  - User Management: USER_ADMIN, SUPER_ADMIN
  - Audit Log: AUDITOR, SUPER_ADMIN
- Added translations for new menu items
- Menu items now only show for users with appropriate permissions
This commit is contained in:
vsxd 2026-03-13 13:29:02 +08:00
parent 9905763f6b
commit 8d01cc0976
3 changed files with 42 additions and 5 deletions

View file

@ -46,6 +46,9 @@
"myNamespaces": "My Namespaces",
"stars": "Starred",
"reviews": "Review Management",
"promotions": "Promotion Management",
"users": "User Management",
"auditLog": "Audit Log",
"security": "Security Settings",
"accounts": "Account Merge",
"logout": "Logout"

View file

@ -46,6 +46,9 @@
"myNamespaces": "我的命名空间",
"stars": "我的星标",
"reviews": "审核管理",
"promotions": "推广管理",
"users": "用户管理",
"auditLog": "审计日志",
"security": "安全设置",
"accounts": "账号合并",
"logout": "退出登录"

View file

@ -11,6 +11,7 @@ import {
interface User {
displayName: string
avatarUrl?: string
platformRoles?: string[]
}
interface UserMenuProps {
@ -21,6 +22,12 @@ export function UserMenu({ user }: UserMenuProps) {
const { t } = useTranslation()
const navigate = useNavigate()
const hasRole = (role: string) => user.platformRoles?.includes(role) ?? false
const isReviewer = hasRole('SKILL_ADMIN') || hasRole('NAMESPACE_ADMIN') || hasRole('SUPER_ADMIN')
const isSkillAdmin = hasRole('SKILL_ADMIN') || hasRole('SUPER_ADMIN')
const isUserAdmin = hasRole('USER_ADMIN') || hasRole('SUPER_ADMIN')
const isAuditor = hasRole('AUDITOR') || hasRole('SUPER_ADMIN')
const handleLogout = async () => {
try {
await fetch('/api/auth/logout', { method: 'POST' })
@ -69,11 +76,35 @@ export function UserMenu({ user }: UserMenuProps) {
{t('user.menu.stars')}
</Link>
</DropdownMenuItem>
<DropdownMenuItem asChild>
<Link to="/dashboard/reviews" className="cursor-pointer">
{t('user.menu.reviews')}
</Link>
</DropdownMenuItem>
{isReviewer && (
<DropdownMenuItem asChild>
<Link to="/dashboard/reviews" className="cursor-pointer">
{t('user.menu.reviews')}
</Link>
</DropdownMenuItem>
)}
{isSkillAdmin && (
<DropdownMenuItem asChild>
<Link to="/dashboard/promotions" className="cursor-pointer">
{t('user.menu.promotions')}
</Link>
</DropdownMenuItem>
)}
{(isUserAdmin || isAuditor) && <DropdownMenuSeparator />}
{isUserAdmin && (
<DropdownMenuItem asChild>
<Link to="/admin/users" className="cursor-pointer">
{t('user.menu.users')}
</Link>
</DropdownMenuItem>
)}
{isAuditor && (
<DropdownMenuItem asChild>
<Link to="/admin/audit-log" className="cursor-pointer">
{t('user.menu.auditLog')}
</Link>
</DropdownMenuItem>
)}
<DropdownMenuSeparator />
<DropdownMenuItem asChild>
<Link to="/settings/security" className="cursor-pointer">