fix: error when data scope is set to own data and the table lacks a creator field (#6428)

* fix: resolve error when query has createdById but table lacks it

* chore: update logic and add test

* fix: filter params get collection
This commit is contained in:
ajie 2025-03-13 15:20:11 +08:00 committed by GitHub
parent f84e2c470b
commit 85e16912cf
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 93 additions and 0 deletions

View File

@ -460,6 +460,23 @@ export class ACL extends EventEmitter {
}
}
// 检查 $or 条件中的 createdById
if (params?.filter?.$or?.length) {
const checkCreatedById = (items) => {
return items.some(
(x) =>
'createdById' in x || x.$or?.some((y) => 'createdById' in y) || x.$and?.some((y) => 'createdById' in y),
);
};
if (checkCreatedById(params.filter.$or)) {
const collection = ctx.db.getCollection(resourceName);
if (!collection || !collection.getField('createdById')) {
throw new NoPermissionError('createdById field not found');
}
}
}
return params;
}

View File

@ -425,4 +425,80 @@ describe('union role: full permissions', async () => {
expect(getSystemSettingsResponse.status).toBe(200);
expect(getSystemSettingsResponse.body.data.roleMode).toStrictEqual(SystemRoleMode.allowUseUnion);
});
it(`should response no permission when createdById field is missing in data tables`, async () => {
let getRolesResponse = await agent.resource('roles').list({ pageSize: 30 });
expect(getRolesResponse.statusCode).toBe(403);
const dataSourceRoleRepo = db.getRepository('dataSourcesRoles');
const dataSourceRole1 = await dataSourceRoleRepo.findOne({
where: { dataSourceKey: 'main', roleName: role1.name },
});
await dataSourceRoleRepo.update({
filter: { id: dataSourceRole1.id },
values: {
strategy: { actions: ['view:own'] },
},
});
const dataSourceRole2 = await dataSourceRoleRepo.findOne({
where: { dataSourceKey: 'main', roleName: role2.name },
});
await dataSourceRoleRepo.update({
filter: { id: dataSourceRole2.id },
values: {
strategy: { actions: ['view:own'] },
},
});
agent = await app.agent().login(user, role1.name);
getRolesResponse = await agent.resource('roles').list({ pageSize: 30 });
expect(getRolesResponse.statusCode).toBe(403);
agent = await app.agent().login(user, role2.name);
getRolesResponse = await agent.resource('roles').list({ pageSize: 30 });
expect(getRolesResponse.statusCode).toBe(403);
agent = await app.agent().login(user, UNION_ROLE_KEY);
getRolesResponse = await agent.resource('roles').list({ pageSize: 30 });
expect(getRolesResponse.statusCode).toBe(403);
});
it(`should response allowedActions no edit when createdById field is missing in data tables and set edit:own`, async () => {
const dataSourceRoleRepo = db.getRepository('dataSourcesRoles');
const dataSourceRole1 = await dataSourceRoleRepo.findOne({
where: { dataSourceKey: 'main', roleName: role1.name },
});
await dataSourceRoleRepo.update({
filter: { id: dataSourceRole1.id },
values: {
strategy: { actions: ['view', 'edit:own'] },
},
});
const dataSourceRole2 = await dataSourceRoleRepo.findOne({
where: { dataSourceKey: 'main', roleName: role2.name },
});
await dataSourceRoleRepo.update({
filter: { id: dataSourceRole2.id },
values: {
strategy: { actions: ['view', 'edit:own'] },
},
});
agent = (await (await app.agent().login(user, role1.name)).set({ 'X-With-ACL-Meta': true })) as any;
let getRolesResponse = await agent.resource('roles').list({ pageSize: 30 });
expect(getRolesResponse.statusCode).toBe(200);
expect(getRolesResponse.body.meta.allowedActions.update.length).toBe(0);
agent = (await (await app.agent().login(user, role2.name)).set({ 'X-With-ACL-Meta': true })) as any;
getRolesResponse = await agent.resource('roles').list({ pageSize: 30 });
expect(getRolesResponse.statusCode).toBe(200);
expect(getRolesResponse.body.meta.allowedActions.update.length).toBe(0);
agent = (await (await app.agent().login(user, UNION_ROLE_KEY)).set({ 'X-With-ACL-Meta': true })) as any;
getRolesResponse = await agent.resource('roles').list({ pageSize: 30 });
expect(getRolesResponse.statusCode).toBe(200);
expect(getRolesResponse.body.meta.allowedActions.update.length).toBe(0);
});
});