fix(auth): use loginWithJti to update authentication-related test cases and prevent errors (#6175)

* refactor(auth): update login method to use loginWithJti for test cases
This commit is contained in:
Sheldon Guo 2025-02-07 17:45:48 +08:00 committed by GitHub
parent ad13bc60c4
commit 0144e2e510
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
35 changed files with 98 additions and 71 deletions

View File

@ -10,6 +10,7 @@
import { vi } from 'vitest';
import { BaseAuth } from '../base/auth';
import { AuthErrorCode } from '../auth';
import jwt from 'jsonwebtoken';
describe('base-auth', () => {
it('should validate username', () => {
@ -56,7 +57,7 @@ describe('base-auth', () => {
app: {
authManager: {
jwt: {
decode: () => ({ userId: 1, roleName: 'admin' }),
decode: () => ({ userId: 1, roleName: 'admin', signInTime: Date.now() }),
blacklist: {
has: () => false,
},
@ -64,6 +65,11 @@ describe('base-auth', () => {
tokenController: {
check: () => ({ status: 'valid' }),
removeLoginExpiredTokens: async () => null,
getConfig: async () => ({
tokenExpirationTime: '30m',
sessionExpirationTime: '1d',
expiredTokenRenewLimit: '15m',
}),
},
},
},
@ -95,7 +101,7 @@ describe('base-auth', () => {
app: {
authManager: {
jwt: {
decode: () => ({ userId: 1, roleName: 'admin' }),
decode: () => ({ userId: 1, roleName: 'admin', signInTime: Date.now() }),
blacklist: {
has: () => false,
},
@ -103,6 +109,11 @@ describe('base-auth', () => {
tokenController: {
check: () => ({ status: 'valid' }),
removeLoginExpiredTokens: () => null,
getConfig: async () => ({
tokenExpirationTime: '30m',
sessionExpirationTime: '1d',
expiredTokenRenewLimit: '15m',
}),
},
},
},
@ -159,7 +170,7 @@ describe('base-auth', () => {
},
tokenController: {
add: () => 'access',
getConfig: () => ({
getConfig: async () => ({
tokenExpirationTime: '30m',
sessionExpirationTime: '1d',
expiredTokenRenewLimit: '15m',

View File

@ -9,6 +9,7 @@
import { Database } from '@nocobase/database';
import { MockServer, createMockServer } from '@nocobase/test';
import jwt, { JwtPayload } from 'jsonwebtoken';
import { vi } from 'vitest';
import { AuthErrorCode } from '../auth';
@ -37,7 +38,7 @@ describe('middleware', () => {
const hasFn = vi.fn();
const addFn = vi.fn();
beforeEach(async () => {
await agent.login(1);
await agent.loginWithJti(1);
app.authManager.setTokenBlacklistService({
has: hasFn,
add: addFn,
@ -52,16 +53,18 @@ describe('middleware', () => {
it('basic', async () => {
const res = await agent.resource('auth').check();
const token = res.request.header['Authorization'].replace('Bearer ', '');
const { jti } = jwt.decode(token) as JwtPayload;
expect(res.status).toBe(200);
expect(hasFn).toHaveBeenCalledWith(token);
expect(hasFn).toHaveBeenCalledWith(jti);
});
it('signOut should add token to blacklist', async () => {
// signOut will add token
const res = await agent.resource('auth').signOut();
const token = res.request.header['Authorization'].replace('Bearer ', '');
const { jti } = jwt.decode(token) as JwtPayload;
expect(addFn).toHaveBeenCalledWith({
token,
token: jti,
// Date or String is ok
expiration: expect.any(String),
});

View File

@ -102,7 +102,7 @@ export class BaseAuth extends Auth {
const tokenPolicy = await this.tokenController.getConfig();
if (!signInTime || Date.now() - signInTime > tokenPolicy.sessionExpirationTime) {
if (signInTime && Date.now() - signInTime > tokenPolicy.sessionExpirationTime) {
this.ctx.throw(401, {
message: this.ctx.t('Your session has expired. Please sign in again.', { ns: localeNamespace }),
code: AuthErrorCode.EXPIRED_SESSION,
@ -164,7 +164,7 @@ export class BaseAuth extends Auth {
url: this.ctx.originalUrl,
headers: JSON.stringify(this.ctx?.req?.headers),
});
const isStreamRequest = this.ctx.req.headers['accept'] === 'text/event-stream';
const isStreamRequest = this.ctx?.req?.headers?.accept === 'text/event-stream';
if (isStreamRequest) {
this.ctx.throw(401, {

View File

@ -137,6 +137,7 @@ export class MockServer extends Application {
userId: typeof userOrId === 'number' ? userOrId : userOrId?.id,
temp: true,
roleName,
signInTime: Date.now(),
},
process.env.APP_KEY,
{

View File

@ -42,7 +42,7 @@ describe('acl', () => {
},
});
adminAgent = app.agent().login(admin);
adminAgent = await app.agent().loginWithJti(admin);
uiSchemaRepository = db.getRepository('uiSchemas');
});
@ -126,7 +126,7 @@ describe('acl', () => {
userPlugin = app.getPlugin('users') as UsersPlugin;
const testAgent = app.agent().login(u1);
const testAgent = await app.agent().loginWithJti(u1);
// @ts-ignore
const response1 = await testAgent.resource('repairs').list({
@ -247,7 +247,7 @@ describe('acl', () => {
});
const userPlugin = app.getPlugin('users') as UsersPlugin;
const adminAgent = app.agent().login(rootUser);
const adminAgent = await app.agent().loginWithJti(rootUser);
expect(await db.getCollection('roles').repository.count()).toBe(3);
@ -802,7 +802,7 @@ describe('acl', () => {
},
});
const userAgent = app.agent().login(user);
const userAgent = await app.agent().loginWithJti(user);
const schema = {
'x-uid': 'test',
@ -864,7 +864,7 @@ describe('acl', () => {
filterByTk: 1,
});
const rootAgent = app.agent().login(rootUser);
const rootAgent = await app.agent().loginWithJti(rootUser);
const response = await rootAgent
// @ts-ignore

View File

@ -138,7 +138,7 @@ describe('destroy action with acl', () => {
const a1 = await A.repository.findOne({ filter: { title: 'a1' } });
const response = await app.agent().login(1).resource('a.bs', a1.get('id')).list();
const response = await (await await app.agent().loginWithJti(1)).resource('a.bs', a1.get('id')).list();
expect(response.statusCode).toEqual(200);
});

View File

@ -114,7 +114,7 @@ describe('association test', () => {
},
});
const userAgent = app.agent().login(user);
const userAgent = await app.agent().loginWithJti(user);
const postCommentsResp = await userAgent.resource('posts.userComments', post.get('id')).list({});
expect(postCommentsResp.statusCode).toEqual(200);
@ -168,9 +168,9 @@ describe.skip('association field acl', () => {
});
const userPlugin = app.getPlugin('users') as UsersPlugin;
userAgent = app.agent().login(user);
userAgent = await app.agent().loginWithJti(user);
adminAgent = app.agent().login(admin);
adminAgent = await app.agent().loginWithJti(admin);
await db.getRepository('collections').create({
values: {

View File

@ -55,9 +55,9 @@ describe('configuration', () => {
});
const userPlugin = app.getPlugin('users') as UsersPlugin;
adminAgent = app.agent().login(admin);
adminAgent = await app.agent().loginWithJti(admin);
userAgent = app.agent().login(user);
userAgent = await app.agent().loginWithJti(user);
guestAgent = app.agent();
});

View File

@ -24,7 +24,7 @@ describe('get action with acl', () => {
const users = await UserRepo.create({
values: [{ nickname: 'a', roles: [{ name: 'test' }] }],
});
userAgent = app.agent().login(users[0]);
userAgent = await app.agent().loginWithJti(users[0]);
Post = app.db.collection({
name: 'posts',

View File

@ -30,7 +30,7 @@ describe('list action with acl', () => {
{ id: 3, nickname: 'a', roles: [{ name: 'user' }] },
],
});
userAgent = app.agent().login(users[0], 'user');
userAgent = await app.agent().loginWithJti(users[0], 'user');
Post = app.db.collection({
name: 'posts',
@ -220,7 +220,10 @@ describe('list action with acl', () => {
// );
// @ts-ignore
const response = await app.agent().login(users[0].id, 'user').set('X-With-ACL-Meta', true).resource('posts').list();
const response = await (await app.agent().loginWithJti(users[0].id, 'user'))
.set('X-With-ACL-Meta', true)
.resource('posts')
.list();
const data = response.body;
expect(data.meta.allowedActions.view).toEqual(expect.arrayContaining([1, 2, 3]));
expect(data.meta.allowedActions.update).toEqual(expect.arrayContaining([1, 2]));
@ -388,7 +391,7 @@ describe('list association action with acl', () => {
},
});
const userAgent = app.agent().login(user, 'newRole').set('X-With-ACL-Meta', true);
const userAgent = await (await app.agent().loginWithJti(user, 'newRole')).set('X-With-ACL-Meta', true);
const createResp = await userAgent.resource('posts').create({
values: {

View File

@ -47,8 +47,8 @@ describe('middleware', () => {
});
const userPlugin = app.getPlugin('users') as UsersPlugin;
adminAgent = app.agent().login(admin);
memberAgent = app.agent().login(member);
adminAgent = await app.agent().loginWithJti(admin);
memberAgent = await app.agent().loginWithJti(member);
await db.getRepository('collections').create({
values: {
@ -135,7 +135,7 @@ describe('middleware', () => {
},
},
});
const response = await app.agent().login(member).resource('posts').create({
const response = await (await app.agent().loginWithJti(member)).resource('posts').create({
values: {},
});

View File

@ -77,7 +77,7 @@ describe('own test', () => {
pluginUser = app.getPlugin('users');
adminAgent = app.agent().login(admin);
adminAgent = await app.agent().loginWithJti(admin);
user = await db.getRepository('users').create({
values: {
@ -86,7 +86,7 @@ describe('own test', () => {
},
});
userAgent = app.agent().login(user);
userAgent = await app.agent().loginWithJti(user);
});
it('should list without createBy', async () => {

View File

@ -44,7 +44,7 @@ describe('role check action', () => {
},
});
const agent = app.agent().login(user);
const agent = await app.agent().loginWithJti(user);
// @ts-ignore
const response = await agent.resource('roles').check();
@ -92,7 +92,7 @@ describe('role check action', () => {
},
});
const agent: any = app.agent().login(user);
const agent: any = await app.agent().loginWithJti(user);
const checkResp1 = await agent.resource('roles').check();
const actions = checkResp1.body.data.actions;

View File

@ -42,7 +42,7 @@ describe('role resource api', () => {
});
const userPlugin = app.getPlugin('users') as UsersPlugin;
adminAgent = app.agent().login(admin);
adminAgent = await app.agent().loginWithJti(admin);
});
it('should grant resource by createRepository', async () => {

View File

@ -45,7 +45,7 @@ describe('role api', () => {
});
const userPlugin = app.getPlugin('users') as UsersPlugin;
adminAgent = app.agent().login(admin);
adminAgent = await app.agent().loginWithJti(admin);
});
it('should have permission to users collection with strategy', async () => {
@ -64,7 +64,7 @@ describe('role api', () => {
},
});
const userAgent = app.agent().login(user1);
const userAgent = await app.agent().loginWithJti(user1);
const response = await userAgent.resource('users').list();
expect(response.statusCode).toBe(200);

View File

@ -35,7 +35,7 @@ describe('scope api', () => {
});
const userPlugin = app.getPlugin('users') as UsersPlugin;
adminAgent = app.agent().login(admin);
adminAgent = await app.agent().loginWithJti(admin);
});
it('should create scope of resource', async () => {

View File

@ -36,7 +36,7 @@ describe('snippet', () => {
});
const userPlugin: any = app.getPlugin('users');
const userAgent: any = app.agent().login(user);
const userAgent: any = await app.agent().loginWithJti(user);
const createCollectionResponse = await userAgent.resource('collections').create({});
expect(createCollectionResponse.statusCode).toEqual(403);
@ -57,7 +57,7 @@ describe('snippet', () => {
},
});
const userAgent: any = app.agent().login(testUser);
const userAgent: any = await app.agent().loginWithJti(testUser);
const listResp = await userAgent.resource('users').list();
@ -79,7 +79,7 @@ describe('snippet', () => {
},
});
const userAgent: any = app.agent().login(testUser);
const userAgent: any = await app.agent().loginWithJti(testUser);
const getResp = await userAgent.resource('dataSources.roles', 'main').get({
filterByTk: 'testRole',
@ -110,7 +110,7 @@ describe('snippet', () => {
},
});
const userAgent: any = app.agent().login(testUser);
const userAgent: any = await app.agent().loginWithJti(testUser);
const getResp = await userAgent.resource('roles.dataSourcesCollections', 'testRole').list({
filter: {

View File

@ -36,7 +36,7 @@ describe('actions', () => {
});
agent = app.agent();
adminAgent = app.agent().login(adminUser);
adminAgent = await app.agent().loginWithJti(adminUser);
});
afterEach(async () => {
@ -166,7 +166,7 @@ describe('actions', () => {
});
// list with user
const userAgent: any = app.agent().login(testUser).set('x-role', 'testRole');
const userAgent: any = (await app.agent().loginWithJti(testUser)).set('x-role', 'testRole');
const listResp = await userAgent.resource('items').list({});
expect(listResp.status).toBe(200);

View File

@ -41,7 +41,7 @@ describe('acl', () => {
},
});
adminAgent = app.agent().login(admin);
adminAgent = await app.agent().loginWithJti(admin);
uiSchemaRepository = db.getRepository('uiSchemas');
await db.getRepository('collections').create({
context: {},

View File

@ -40,7 +40,7 @@ describe('write role to acl', () => {
},
});
const agent = app.agent().login(user);
const agent = await app.agent().loginWithJti(user);
// @ts-ignore
const response = await agent.resource('roles').check();

View File

@ -256,11 +256,14 @@ describe('actions', () => {
password: '12345',
},
});
const res3 = await agent.login(user1).post('/auth:changePassword').set({ 'X-Authenticator': 'basic' }).send({
oldPassword: '12345',
newPassword: '123456',
confirmPassword: '123456',
});
const res3 = await (await agent.loginWithJti(user1))
.post('/auth:changePassword')
.set({ 'X-Authenticator': 'basic' })
.send({
oldPassword: '12345',
newPassword: '123456',
confirmPassword: '123456',
});
expect(res3.statusCode).toEqual(200);
});
@ -278,7 +281,7 @@ describe('actions', () => {
password: '12345',
},
});
const userAgent = await agent.login(user);
const userAgent = await agent.loginWithJti(user);
const res = await userAgent.post('/auth:changePassword').set({ 'X-Authenticator': 'basic' }).send({
oldPassword: '12345',

View File

@ -24,6 +24,9 @@ class MockContext {
constructor({ app }: { app: MockServer }) {
this.app = app;
}
get logger() {
return this.app.logger;
}
res = {
setHeader: (key: string, value: string) => {
this.header.set(key, value);

View File

@ -16,7 +16,7 @@ describe('backup files', () => {
beforeEach(async () => {
app = await createApp();
adminAgent = app.agent().login(1);
adminAgent = await app.agent().loginWithJti(1);
});
afterEach(async () => {

View File

@ -14,6 +14,7 @@ export async function prepareApp(): Promise<MockServer> {
registerActions: true,
acl: true,
plugins: [
'auth',
'acl',
'error-handler',
'field-sort',

View File

@ -42,7 +42,7 @@ describe('tree', () => {
});
const userPlugin = app.getPlugin('users');
const agent = app.agent().login(user);
const agent = await app.agent().loginWithJti(user);
agent.set('X-With-ACL-Meta', 'true');
app.acl.allow('table_a', ['*']);
app.acl.allow('collections', ['*']);

View File

@ -117,7 +117,7 @@ describe('data source with acl', () => {
},
});
const adminAgent: any = app.agent().login(adminUser).set('x-data-source', 'mockInstance1');
const adminAgent: any = (await app.agent().loginWithJti(adminUser)).set('x-data-source', 'mockInstance1');
const listRes = await adminAgent.resource('api/posts').list();
expect(listRes.status).toBe(200);
expect(middlewareFn).toBeCalledTimes(1);
@ -130,7 +130,7 @@ describe('data source with acl', () => {
},
});
const adminAgent: any = app.agent().login(adminUser).set('x-data-source', 'mockInstance1');
const adminAgent: any = (await app.agent().loginWithJti(adminUser)).set('x-data-source', 'mockInstance1');
const postRes = await adminAgent.resource('api/posts').list({});
expect(postRes.status).toBe(200);
});
@ -142,7 +142,7 @@ describe('data source with acl', () => {
},
});
const adminAgent: any = app.agent().login(adminUser);
const adminAgent: any = await app.agent().loginWithJti(adminUser);
await adminAgent.resource('dataSources.roles', 'mockInstance1').update({
filterByTk: 'member',
@ -195,9 +195,9 @@ describe('data source with acl', () => {
context: {},
});
const adminAgent: any = app.agent().login(adminUser);
const adminAgent: any = await app.agent().loginWithJti(adminUser);
const testUserAgent: any = app.agent().login(testUser);
const testUserAgent: any = await app.agent().loginWithJti(testUser);
const listRes = await testUserAgent.resource('posts').list({});
expect(listRes.status).toBe(403);
@ -251,10 +251,11 @@ describe('data source with acl', () => {
},
});
const adminAgent: any = app.agent().login(adminUser);
const adminAgent: any = await app.agent().loginWithJti(adminUser);
// should get permission error
const testUserAgent = getDataSourceAgent(app.agent().login(testUser), 'mockInstance1');
const testAgent = await app.agent().loginWithJti(testUser);
const testUserAgent = getDataSourceAgent(testAgent, 'mockInstance1');
// @ts-ignore
const listRes = await testUserAgent.resource('api/posts').list({});
@ -312,10 +313,10 @@ describe('data source with acl', () => {
},
});
const adminAgent: any = app.agent().login(adminUser);
const adminAgent: any = await app.agent().loginWithJti(adminUser);
// should get permission error
const testUserAgent = getDataSourceAgent(app.agent().login(testUser), 'mockInstance1');
const testUserAgent = getDataSourceAgent(await app.agent().loginWithJti(testUser), 'mockInstance1');
const createResourceResp = await adminAgent.resource('dataSources.rolesResourcesScopes', 'mockInstance1').create({
values: {
@ -401,7 +402,7 @@ describe('data source with acl', () => {
// call roles check
// @ts-ignore
const checkRep = await app.agent().login(testUser).resource('roles').check({});
const checkRep = await (await app.agent().loginWithJti(testUser)).resource('roles').check({});
expect(checkRep.status).toBe(200);
const checkData = checkRep.body;
@ -432,7 +433,7 @@ describe('data source with acl', () => {
});
// get role
const adminRoleResp = await app.agent().login(adminUser).resource('dataSources.roles', 'main').get({
const adminRoleResp = await (await app.agent().loginWithJti(adminUser)).resource('dataSources.roles', 'main').get({
filterByTk: 'admin',
});
@ -453,7 +454,7 @@ describe('data source with acl', () => {
expect(updateRoleRes.status).toBe(200);
const adminRoleResp2 = await app.agent().login(adminUser).resource('dataSources.roles', 'main').get({
const adminRoleResp2 = await (await app.agent().loginWithJti(adminUser)).resource('dataSources.roles', 'main').get({
filterByTk: 'admin',
});

View File

@ -43,7 +43,7 @@ describe('inapp message channels', () => {
],
});
userAgents = users.map((user) => app.agent().login(user));
userAgents = await Promise.all(users.map((user) => app.agent().loginWithJti(user)));
currUserAgent = userAgents[0];
currUserId = users[0].id;
});

View File

@ -33,7 +33,7 @@ describe('actions', () => {
});
agent = app.agent();
adminAgent = app.agent().login(adminUser);
adminAgent = await app.agent().loginWithJti(adminUser);
});
afterEach(async () => {

View File

@ -36,7 +36,7 @@ describe('actions', () => {
});
agent = app.agent();
adminAgent = app.agent().login(adminUser);
adminAgent = await app.agent().loginWithJti(adminUser);
});
afterEach(async () => {

View File

@ -42,7 +42,7 @@ describe('workflow > action-trigger', () => {
UserRepo = db.getCollection('users').repository;
root = await UserRepo.findOne({});
rootAgent = app.agent().login(root);
rootAgent = await app.agent().loginWithJti(root);
users = await UserRepo.create({
values: [
@ -51,7 +51,7 @@ describe('workflow > action-trigger', () => {
],
});
userAgents = users.map((user) => app.agent().login(user));
userAgents = await Promise.all(users.map((user) => app.agent().loginWithJti(user)));
});
afterEach(() => app.destroy());

View File

@ -44,7 +44,7 @@ describe('workflow > instructions > manual', () => {
{ id: 3, nickname: 'b' },
]);
userAgents = users.map((user) => app.agent().login(user));
userAgents = await Promise.all(users.map((user) => app.agent().loginWithJti(user)));
workflow = await WorkflowModel.create({
enabled: true,

View File

@ -44,7 +44,7 @@ describe('workflow > instructions > manual', () => {
{ id: 3, nickname: 'b' },
]);
userAgents = users.map((user) => app.agent().login(user));
userAgents = await Promise.all(users.map((user) => app.agent().loginWithJti(user)));
workflow = await WorkflowModel.create({
enabled: true,

View File

@ -524,6 +524,7 @@ describe('workflow > instructions > request', () => {
const token = jwt.sign(
{
userId: user.id,
signInTime: Date.now(),
},
process.env.APP_KEY,
{

View File

@ -47,7 +47,7 @@ describe('workflow > actions > executions', () => {
{ id: 3, nickname: 'b' },
],
});
userAgents = users.map((user) => app.agent().login(user));
userAgents = await Promise.all(users.map((user) => app.agent().loginWithJti(user)));
});
afterEach(async () => await app.destroy());

View File

@ -40,7 +40,7 @@ describe('workflow > triggers > collection', () => {
TagRepo = db.getCollection('tags').repository;
const user = await app.db.getRepository('users').findOne();
agent = app.agent().login(user);
agent = await app.agent().loginWithJti(user);
});
afterEach(() => app.destroy());