From 77df158026a2b315fb5bb781eb3feda79b9d5759 Mon Sep 17 00:00:00 2001 From: Mohan Date: Mon, 10 Aug 2026 09:06:42 +0800 Subject: [PATCH] feat(page): add admin user list with role guard --- src/router/index.ts | 8 ++ src/stores/auth.ts | 11 +++ src/views/admin/AdminLayout.vue | 1 + src/views/admin/UserListView.vue | 165 +++++++++++++++++++++++++++++++ 4 files changed, 185 insertions(+) create mode 100644 src/views/admin/UserListView.vue diff --git a/src/router/index.ts b/src/router/index.ts index a167668..b7b7d7b 100644 --- a/src/router/index.ts +++ b/src/router/index.ts @@ -59,6 +59,12 @@ const router = createRouter({ path: 'tags', name: 'AdminTagList', component: () => import('@/views/admin/TagListView.vue') + }, + { + path: 'users', + name: 'AdminUserList', + component: () => import('@/views/admin/UserListView.vue'), + meta: { requiresAdmin: true } } ] } @@ -72,6 +78,8 @@ router.beforeEach((to, _from, next) => { next('/login') } else if (to.meta.guestOnly && auth.isLoggedIn) { next('/admin') + } else if (to.meta.requiresAdmin && !auth.isAdmin) { + next('/admin/articles') } else { next() } diff --git a/src/stores/auth.ts b/src/stores/auth.ts index c8cabf4..4e869bb 100644 --- a/src/stores/auth.ts +++ b/src/stores/auth.ts @@ -8,6 +8,16 @@ export const useAuthStore = defineStore('auth', () => { const refreshToken = ref(localStorage.getItem('refreshToken')) const username = ref(localStorage.getItem('username')) const isLoggedIn = computed(() => !!token.value) + const isAdmin = computed(() => { + if (!token.value) return false + try { + const payload = JSON.parse(atob(token.value.split('.')[1].replace(/-/g, '+').replace(/_/g, '/'))) + const roles: string[] = payload.roles ?? [] + return roles.includes('ADMIN') + } catch { + return false + } + }) async function register(request: RegisterRequest) { const resp = await authApi.apiAuthRegisterPost(request) @@ -54,6 +64,7 @@ export const useAuthStore = defineStore('auth', () => { refreshToken, username, isLoggedIn, + isAdmin, register, login, logout, diff --git a/src/views/admin/AdminLayout.vue b/src/views/admin/AdminLayout.vue index c3915c3..ffe003e 100644 --- a/src/views/admin/AdminLayout.vue +++ b/src/views/admin/AdminLayout.vue @@ -22,6 +22,7 @@ async function handleLogout() {
diff --git a/src/views/admin/UserListView.vue b/src/views/admin/UserListView.vue new file mode 100644 index 0000000..446da78 --- /dev/null +++ b/src/views/admin/UserListView.vue @@ -0,0 +1,165 @@ + + + + + \ No newline at end of file