mirror of
https://github.com/nocobase/nocobase
synced 2024-11-15 10:26:45 +00:00
fix(acl): grant action with table without createdAt field (#2562)
This commit is contained in:
parent
83c1792582
commit
050e1e0215
@ -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({
|
||||||
|
@ -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],
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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',
|
||||||
});
|
});
|
||||||
|
@ -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;
|
||||||
|
Loading…
Reference in New Issue
Block a user