fix(acl): grant action with table without createdAt field (#2562)

This commit is contained in:
ChengLei Shao 2023-08-29 17:01:14 +08:00 committed by GitHub
parent 83c1792582
commit 050e1e0215
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 94 additions and 10 deletions

View File

@ -10,6 +10,7 @@ export interface RoleActionParams {
own?: boolean; own?: boolean;
whitelist?: string[]; whitelist?: string[];
blacklist?: string[]; blacklist?: string[];
[key: string]: any; [key: string]: any;
} }
@ -22,7 +23,10 @@ export class ACLRole {
resources = new Map<string, ACLResource>(); resources = new Map<string, ACLResource>();
snippets: Set<string> = new Set(); snippets: Set<string> = new Set();
constructor(public acl: ACL, public name: string) {} constructor(
public acl: ACL,
public name: string,
) {}
getResource(name: string): ACLResource | undefined { getResource(name: string): ACLResource | undefined {
return this.resources.get(name); return this.resources.get(name);
@ -56,7 +60,8 @@ export class ACLRole {
} }
public grantAction(path: string, options?: RoleActionParams) { public grantAction(path: string, options?: RoleActionParams) {
let { resource, resourceName, actionName } = this.getResourceActionFromPath(path); let { resource } = this.getResourceActionFromPath(path);
const { resourceName, actionName } = this.getResourceActionFromPath(path);
if (!resource) { if (!resource) {
resource = new ACLResource({ resource = new ACLResource({

View File

@ -76,14 +76,6 @@ export class ACL extends EventEmitter {
whitelist: ctx.params.fields, whitelist: ctx.params.fields,
}; };
} }
if (actionName === 'view' && ctx.params.fields) {
const appendFields = ['id', 'createdAt', 'updatedAt'];
ctx.params = {
...lodash.omit(ctx.params, 'fields'),
fields: [...ctx.params.fields, ...appendFields],
};
}
} }
}); });

View File

@ -386,6 +386,58 @@ describe('acl', () => {
).toBeNull(); ).toBeNull();
}); });
it('should not append createdAt field when collection has no createdAt field', async () => {
const role = await db.getRepository('roles').create({
values: {
name: 'new',
strategy: {
actions: ['list'],
},
},
});
await db.getRepository('collections').create({
values: {
name: 'c1',
autoGenId: false,
fields: [
{ name: 'name', type: 'string', primaryKey: true },
{ name: 'title', type: 'string' },
],
timestamps: false,
},
context: {},
});
await adminAgent.resource('roles.resources', 'new').create({
values: {
name: 'c1',
usingActionsConfig: true,
actions: [
{
name: 'view',
fields: ['title'],
},
],
},
});
expect(
acl.can({
role: 'new',
resource: 'c1',
action: 'view',
}),
).toMatchObject({
role: 'new',
resource: 'c1',
action: 'view',
params: {
fields: ['title', 'name'],
},
});
});
it('should works with resources actions', async () => { it('should works with resources actions', async () => {
const role = await db.getRepository('roles').create({ const role = await db.getRepository('roles').create({
values: { values: {
@ -402,6 +454,7 @@ describe('acl', () => {
name: 'c1', name: 'c1',
title: 'table1', title: 'table1',
}, },
context: {},
}); });
// create c2 collection // create c2 collection

View File

@ -8,6 +8,7 @@ export async function prepareApp(): Promise<MockServer> {
plugins: ['error-handler', 'users', 'ui-schema-storage', 'collection-manager', 'auth'], plugins: ['error-handler', 'users', 'ui-schema-storage', 'collection-manager', 'auth'],
}); });
await app.db.clean({ drop: true });
app.plugin(PluginACL, { app.plugin(PluginACL, {
name: 'acl', name: 'acl',
}); });

View File

@ -517,6 +517,39 @@ export class PluginACL extends Plugin {
const parseJsonTemplate = this.app.acl.parseJsonTemplate; const parseJsonTemplate = this.app.acl.parseJsonTemplate;
this.app.acl.beforeGrantAction(async (ctx) => {
const actionName = this.app.acl.resolveActionAlias(ctx.actionName);
if (lodash.isPlainObject(ctx.params)) {
if (actionName === 'view' && ctx.params.fields) {
const appendFields = [];
const collection = this.app.db.getCollection(ctx.resourceName);
if (!collection) {
return;
}
if (collection.model.primaryKeyAttribute) {
appendFields.push(collection.model.primaryKeyAttribute);
}
if (collection.model.rawAttributes['createdAt']) {
appendFields.push('createdAt');
}
if (collection.model.rawAttributes['updatedAt']) {
appendFields.push('updatedAt');
}
ctx.params = {
...lodash.omit(ctx.params, 'fields'),
fields: [...ctx.params.fields, ...appendFields],
};
}
}
});
this.app.acl.use( this.app.acl.use(
async (ctx: Context, next) => { async (ctx: Context, next) => {
const { actionName, resourceName, resourceOf } = ctx.action; const { actionName, resourceName, resourceOf } = ctx.action;