鉴权改为登录态回库校验,新增 tokenValidAfter 失效时间,支持密码变更与 seed 重置后旧 token 立即失效 患者字段由 idCardHash 统一迁移为 idCard,新增身份证标准化逻辑并同步 C 端生命周期查询参数 组织模块增加小组删除限制(有成员时返回 409)并补充中文错误消息 任务取消接口支持可选 reason 字段(先透传事件层) 补齐 Prisma 迁移、文档说明和 E2E 用例(含设备模块与 token 失效场景)
60 lines
1.8 KiB
TypeScript
60 lines
1.8 KiB
TypeScript
import request from 'supertest';
|
|
import { Role } from '../../../src/generated/prisma/enums.js';
|
|
import {
|
|
closeE2EContext,
|
|
createE2EContext,
|
|
type E2EContext,
|
|
} from '../helpers/e2e-context.helper.js';
|
|
import {
|
|
expectErrorEnvelope,
|
|
expectSuccessEnvelope,
|
|
} from '../helpers/e2e-http.helper.js';
|
|
|
|
describe('Auth token revocation (e2e)', () => {
|
|
let ctx: E2EContext;
|
|
|
|
beforeAll(async () => {
|
|
ctx = await createE2EContext();
|
|
});
|
|
|
|
afterAll(async () => {
|
|
await closeE2EContext(ctx);
|
|
});
|
|
|
|
it('旧 token 在 tokenValidAfter 推进后失效', async () => {
|
|
const token = ctx.tokens[Role.DOCTOR];
|
|
const originalUser = await ctx.prisma.user.findUnique({
|
|
where: { id: ctx.fixtures.users.doctorAId },
|
|
select: { tokenValidAfter: true },
|
|
});
|
|
|
|
const beforeResponse = await request(ctx.app.getHttpServer())
|
|
.get('/auth/me')
|
|
.set('Authorization', `Bearer ${token}`);
|
|
|
|
expectSuccessEnvelope(beforeResponse, 200);
|
|
|
|
try {
|
|
await ctx.prisma.user.update({
|
|
where: { id: ctx.fixtures.users.doctorAId },
|
|
// 往未来推进一分钟,确保当前 token 的 iat 一定早于失效时间。
|
|
data: { tokenValidAfter: new Date(Date.now() + 60_000) },
|
|
});
|
|
|
|
const afterResponse = await request(ctx.app.getHttpServer())
|
|
.get('/auth/me')
|
|
.set('Authorization', `Bearer ${token}`);
|
|
|
|
expectErrorEnvelope(afterResponse, 401, 'Token 已失效,请重新登录');
|
|
} finally {
|
|
if (originalUser) {
|
|
// 恢复种子用户状态,避免串行 E2E 后续用例继续拿到失效 token。
|
|
await ctx.prisma.user.update({
|
|
where: { id: ctx.fixtures.users.doctorAId },
|
|
data: { tokenValidAfter: originalUser.tokenValidAfter },
|
|
});
|
|
}
|
|
}
|
|
});
|
|
});
|