diff --git a/packages/core/acl/src/acl-role.ts b/packages/core/acl/src/acl-role.ts index 75908e715e..f80299ba6f 100644 --- a/packages/core/acl/src/acl-role.ts +++ b/packages/core/acl/src/acl-role.ts @@ -10,6 +10,7 @@ export interface RoleActionParams { own?: boolean; whitelist?: string[]; blacklist?: string[]; + [key: string]: any; } @@ -22,7 +23,10 @@ export class ACLRole { resources = new Map(); snippets: Set = new Set(); - constructor(public acl: ACL, public name: string) {} + constructor( + public acl: ACL, + public name: string, + ) {} getResource(name: string): ACLResource | undefined { return this.resources.get(name); @@ -56,7 +60,8 @@ export class ACLRole { } 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) { resource = new ACLResource({ diff --git a/packages/core/acl/src/acl.ts b/packages/core/acl/src/acl.ts index 678587f64f..47309d70c7 100644 --- a/packages/core/acl/src/acl.ts +++ b/packages/core/acl/src/acl.ts @@ -76,14 +76,6 @@ export class ACL extends EventEmitter { 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], - }; - } } }); diff --git a/packages/plugins/acl/src/server/__tests__/acl.test.ts b/packages/plugins/acl/src/server/__tests__/acl.test.ts index e898b8a101..b6caefc012 100644 --- a/packages/plugins/acl/src/server/__tests__/acl.test.ts +++ b/packages/plugins/acl/src/server/__tests__/acl.test.ts @@ -386,6 +386,58 @@ describe('acl', () => { ).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 () => { const role = await db.getRepository('roles').create({ values: { @@ -402,6 +454,7 @@ describe('acl', () => { name: 'c1', title: 'table1', }, + context: {}, }); // create c2 collection diff --git a/packages/plugins/acl/src/server/__tests__/prepare.ts b/packages/plugins/acl/src/server/__tests__/prepare.ts index f6bcbb2bd5..d55970cbf2 100644 --- a/packages/plugins/acl/src/server/__tests__/prepare.ts +++ b/packages/plugins/acl/src/server/__tests__/prepare.ts @@ -8,6 +8,7 @@ export async function prepareApp(): Promise { plugins: ['error-handler', 'users', 'ui-schema-storage', 'collection-manager', 'auth'], }); + await app.db.clean({ drop: true }); app.plugin(PluginACL, { name: 'acl', }); diff --git a/packages/plugins/acl/src/server/server.ts b/packages/plugins/acl/src/server/server.ts index eca673b159..e3f6f14cc3 100644 --- a/packages/plugins/acl/src/server/server.ts +++ b/packages/plugins/acl/src/server/server.ts @@ -517,6 +517,39 @@ export class PluginACL extends Plugin { 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( async (ctx: Context, next) => { const { actionName, resourceName, resourceOf } = ctx.action;