From bb60df8b41c43382f97c973ec528a367fc8833be Mon Sep 17 00:00:00 2001 From: Feng Yue <2525275@gmail.com> Date: Wed, 13 Aug 2025 20:13:32 +0800 Subject: [PATCH] chore: redirect back to login page for deactivated users --- src/services/ldapService.js | 13 +++++++++++-- web/admin-spa/src/main.js | 5 +++++ web/admin-spa/src/router/index.js | 14 ++++++++++++-- web/admin-spa/src/stores/user.js | 30 +++++++++++++++++++++++++++++- 4 files changed, 57 insertions(+), 5 deletions(-) diff --git a/src/services/ldapService.js b/src/services/ldapService.js index 9ec220ce..6264e81d 100644 --- a/src/services/ldapService.js +++ b/src/services/ldapService.js @@ -447,10 +447,19 @@ class LdapService { // 6. 创建或更新本地用户 const user = await userService.createOrUpdateUser(userInfo) - // 7. 记录登录 + // 7. 检查用户是否被禁用 + if (!user.isActive) { + logger.security(`🔒 Disabled user LDAP login attempt: ${username} from LDAP authentication`) + return { + success: false, + message: 'Your account has been disabled. Please contact administrator.' + } + } + + // 8. 记录登录 await userService.recordUserLogin(user.id) - // 8. 创建用户会话 + // 9. 创建用户会话 const sessionToken = await userService.createUserSession(user.id) logger.info(`✅ LDAP authentication successful for user: ${username}`) diff --git a/web/admin-spa/src/main.js b/web/admin-spa/src/main.js index 478802ac..7fa8865a 100644 --- a/web/admin-spa/src/main.js +++ b/web/admin-spa/src/main.js @@ -5,6 +5,7 @@ import zhCn from 'element-plus/dist/locale/zh-cn.mjs' import 'element-plus/dist/index.css' import App from './App.vue' import router from './router' +import { useUserStore } from './stores/user' import './assets/styles/main.css' import './assets/styles/global.css' @@ -23,5 +24,9 @@ app.use(ElementPlus, { locale: zhCn }) +// 设置axios拦截器 +const userStore = useUserStore() +userStore.setupAxiosInterceptors() + // 挂载应用 app.mount('#app') diff --git a/web/admin-spa/src/router/index.js b/web/admin-spa/src/router/index.js index 7616410c..16a2b50a 100644 --- a/web/admin-spa/src/router/index.js +++ b/web/admin-spa/src/router/index.js @@ -169,8 +169,18 @@ router.beforeEach(async (to, from, next) => { if (to.meta.requiresUserAuth) { if (!userStore.isAuthenticated) { // 尝试检查本地存储的认证信息 - const isUserLoggedIn = await userStore.checkAuth() - if (!isUserLoggedIn) { + try { + const isUserLoggedIn = await userStore.checkAuth() + if (!isUserLoggedIn) { + return next('/user-login') + } + } catch (error) { + // If the error is about disabled account, redirect to login with error + if (error.message && error.message.includes('disabled')) { + // Import showToast to display the error + const { showToast } = await import('@/utils/toast') + showToast(error.message, 'error') + } return next('/user-login') } } diff --git a/web/admin-spa/src/stores/user.js b/web/admin-spa/src/stores/user.js index 8919e0d3..522688a9 100644 --- a/web/admin-spa/src/stores/user.js +++ b/web/admin-spa/src/stores/user.js @@ -1,5 +1,6 @@ import { defineStore } from 'pinia' import axios from 'axios' +import { showToast } from '@/utils/toast' const API_BASE = '/users' @@ -104,8 +105,13 @@ export const useUserStore = defineStore('user', { return response.data.user } } catch (error) { - if (error.response?.status === 401) { + if (error.response?.status === 401 || error.response?.status === 403) { + // 401: Invalid/expired session, 403: Account disabled this.clearAuth() + // If it's a disabled account error, throw a specific error + if (error.response?.status === 403) { + throw new Error(error.response.data?.message || 'Your account has been disabled') + } } throw error } @@ -184,6 +190,28 @@ export const useUserStore = defineStore('user', { if (this.sessionToken) { axios.defaults.headers.common['x-user-token'] = this.sessionToken } + }, + + // 🔧 设置axios拦截器 + setupAxiosInterceptors() { + // Response interceptor to handle disabled user responses globally + axios.interceptors.response.use( + (response) => response, + (error) => { + if (error.response?.status === 403) { + const message = error.response.data?.message + if (message && (message.includes('disabled') || message.includes('Account disabled'))) { + this.clearAuth() + showToast(message, 'error') + // Redirect to login page + if (window.location.pathname !== '/user-login') { + window.location.href = '/user-login' + } + } + } + return Promise.reject(error) + } + ) } } })