fix: 修复强制重置密码流程与表单状态
- 修正强制改密跳转及免旧密码的服务端校验 - 统一双端表单错误布局与更新按钮加载状态 - 补充认证服务和强制改密路由测试
This commit is contained in:
@@ -0,0 +1,65 @@
|
||||
import { createMemoryHistory, createRouter } from 'vue-router';
|
||||
|
||||
import { describe, expect, it, vi } from 'vitest';
|
||||
|
||||
import {
|
||||
buildForcePasswordRoute,
|
||||
isForcePasswordRoute,
|
||||
isPasswordResetRequired,
|
||||
resolveForcePasswordPath,
|
||||
} from '#/utils/password-reset';
|
||||
|
||||
vi.mock('element-plus', () => ({
|
||||
ElMessage: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock('#/locales', () => ({
|
||||
$t: (key: string) => key,
|
||||
}));
|
||||
|
||||
function createTestRouter() {
|
||||
return createRouter({
|
||||
history: createMemoryHistory(),
|
||||
routes: [
|
||||
{
|
||||
name: 'FallbackNotFound',
|
||||
path: '/:path(.*)*',
|
||||
component: { template: '<div />' },
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
describe('password reset route', () => {
|
||||
it('can resolve the forced password path before Profile is registered', () => {
|
||||
const router = createTestRouter();
|
||||
const route = router.resolve(buildForcePasswordRoute());
|
||||
|
||||
expect(route.fullPath).toBe('/profile?force=1&tab=password');
|
||||
expect(isForcePasswordRoute(route)).toBe(true);
|
||||
expect(resolveForcePasswordPath(router)).toBe(
|
||||
'/profile?force=1&tab=password',
|
||||
);
|
||||
});
|
||||
|
||||
it('matches Profile after the dynamic route is registered', () => {
|
||||
const router = createTestRouter();
|
||||
const targetPath = router.resolve(buildForcePasswordRoute()).fullPath;
|
||||
|
||||
router.addRoute({
|
||||
name: 'Profile',
|
||||
path: '/profile',
|
||||
component: { template: '<div />' },
|
||||
});
|
||||
|
||||
expect(router.resolve(targetPath).name).toBe('Profile');
|
||||
});
|
||||
|
||||
it('uses the account state as the authoritative password reset signal', () => {
|
||||
expect(isPasswordResetRequired({ passwordResetRequired: true })).toBe(true);
|
||||
expect(isPasswordResetRequired({ passwordResetRequired: false })).toBe(
|
||||
false,
|
||||
);
|
||||
expect(isPasswordResetRequired()).toBe(false);
|
||||
});
|
||||
});
|
||||
@@ -5,12 +5,13 @@ import { ElMessage } from 'element-plus';
|
||||
import { $t } from '#/locales';
|
||||
|
||||
const FORCE_PASSWORD_NOTICE_INTERVAL = 1500;
|
||||
const PROFILE_PATH = '/profile';
|
||||
|
||||
let lastForcePasswordNoticeAt = 0;
|
||||
|
||||
export function buildForcePasswordRoute() {
|
||||
return {
|
||||
name: 'Profile',
|
||||
path: PROFILE_PATH,
|
||||
query: {
|
||||
force: '1',
|
||||
tab: 'password',
|
||||
@@ -19,16 +20,20 @@ export function buildForcePasswordRoute() {
|
||||
}
|
||||
|
||||
export function isForcePasswordRoute(
|
||||
route: Pick<{ name?: string | symbol | null; query?: Record<string, any> }, 'name' | 'query'>,
|
||||
route: Pick<{ path?: string; query?: Record<string, any> }, 'path' | 'query'>,
|
||||
) {
|
||||
return route.name === 'Profile' && route.query?.tab === 'password';
|
||||
return route.path === PROFILE_PATH && route.query?.tab === 'password';
|
||||
}
|
||||
|
||||
export function shouldForcePasswordChange(
|
||||
userInfo?: null | Record<string, any>,
|
||||
forceChangePassword?: boolean,
|
||||
) {
|
||||
return !!forceChangePassword || !!userInfo?.passwordResetRequired;
|
||||
return !!forceChangePassword || isPasswordResetRequired(userInfo);
|
||||
}
|
||||
|
||||
export function isPasswordResetRequired(userInfo?: null | Record<string, any>) {
|
||||
return !!userInfo?.passwordResetRequired;
|
||||
}
|
||||
|
||||
export function resolveForcePasswordPath(router: Router) {
|
||||
|
||||
Reference in New Issue
Block a user