fix(认证): 修复首次登录改密跳转
This commit is contained in:
@@ -6,12 +6,27 @@ import ForbiddenView from '@/views/auth/ForbiddenView.vue'
|
||||
import LoginView from '@/views/auth/LoginView.vue'
|
||||
import MenuResourceView from '@/views/management/MenuResourceView.vue'
|
||||
import { useLoginStore } from '@/stores/login'
|
||||
import { ApiResponseError } from '@/utils/api-response'
|
||||
import { readStoredAuthSession } from '@/utils/auth-storage'
|
||||
|
||||
function firstAuthorizedPath(loginStore: ReturnType<typeof useLoginStore>) {
|
||||
return loginStore.firstAuthorizedPath ?? '/forbidden'
|
||||
}
|
||||
|
||||
function safeRedirectPath(value: unknown) {
|
||||
return typeof value === 'string' && value.startsWith('/') && !value.startsWith('//')
|
||||
? value
|
||||
: null
|
||||
}
|
||||
|
||||
function isPasswordChangeRequired(error: unknown) {
|
||||
return (
|
||||
error instanceof ApiResponseError &&
|
||||
String(error.code) === '40300' &&
|
||||
error.message === '请先修改密码'
|
||||
)
|
||||
}
|
||||
|
||||
const router = createRouter({
|
||||
history: createWebHistory(import.meta.env.BASE_URL),
|
||||
routes: [
|
||||
@@ -65,6 +80,7 @@ const router = createRouter({
|
||||
|
||||
router.beforeEach(async (to) => {
|
||||
const loginStore = useLoginStore()
|
||||
const requestedRedirect = safeRedirectPath(to.query.redirect)
|
||||
|
||||
if (to.name === 'login' && loginStore.isLoggedIn) {
|
||||
if (!readStoredAuthSession()) {
|
||||
@@ -72,9 +88,14 @@ router.beforeEach(async (to) => {
|
||||
return true
|
||||
}
|
||||
|
||||
return loginStore.user?.passwordChangeRequired
|
||||
? { name: 'change-password' }
|
||||
: firstAuthorizedPath(loginStore)
|
||||
if (loginStore.user?.passwordChangeRequired) {
|
||||
return {
|
||||
name: 'change-password',
|
||||
query: requestedRedirect ? { redirect: requestedRedirect } : undefined,
|
||||
}
|
||||
}
|
||||
|
||||
return requestedRedirect ?? firstAuthorizedPath(loginStore)
|
||||
}
|
||||
|
||||
if (to.meta.requiresAuth && !loginStore.isLoggedIn) {
|
||||
@@ -88,15 +109,22 @@ router.beforeEach(async (to) => {
|
||||
return true
|
||||
}
|
||||
|
||||
// The backend intentionally blocks /auth/me and /authorization/me until a
|
||||
// forced password change is complete. The login response already supplies
|
||||
// the authenticated user's requirement, so don't call those endpoints here.
|
||||
if (to.name === 'change-password') {
|
||||
return true
|
||||
}
|
||||
|
||||
if (loginStore.user?.passwordChangeRequired) {
|
||||
return { name: 'change-password', query: { redirect: to.fullPath } }
|
||||
}
|
||||
|
||||
try {
|
||||
const user = await loginStore.ensureCurrentUser()
|
||||
|
||||
if (user?.passwordChangeRequired && to.name !== 'change-password') {
|
||||
return { name: 'change-password' }
|
||||
}
|
||||
|
||||
if (!user?.passwordChangeRequired && to.name === 'change-password') {
|
||||
return firstAuthorizedPath(loginStore)
|
||||
if (user?.passwordChangeRequired) {
|
||||
return { name: 'change-password', query: { redirect: to.fullPath } }
|
||||
}
|
||||
|
||||
if (to.name === 'menu-resource') {
|
||||
@@ -113,7 +141,13 @@ router.beforeEach(async (to) => {
|
||||
}
|
||||
|
||||
return true
|
||||
} catch {
|
||||
} catch (error: unknown) {
|
||||
// A forced-change response is an authenticated session state, not an
|
||||
// expired session. Keep the token so the user can call the change endpoint.
|
||||
if (isPasswordChangeRequired(error)) {
|
||||
return { name: 'change-password', query: { redirect: to.fullPath } }
|
||||
}
|
||||
|
||||
loginStore.clearSession()
|
||||
return {
|
||||
name: 'login',
|
||||
|
||||
Reference in New Issue
Block a user