diff --git a/packages/plugins/@nocobase/plugin-acl/src/client/__e2e__/collection.test.ts b/packages/plugins/@nocobase/plugin-acl/src/client/__e2e__/collection.test.ts index 5404b725b..c23b86510 100644 --- a/packages/plugins/@nocobase/plugin-acl/src/client/__e2e__/collection.test.ts +++ b/packages/plugins/@nocobase/plugin-acl/src/client/__e2e__/collection.test.ts @@ -1,5 +1,5 @@ import { expect, test } from '@nocobase/test/e2e'; -import { oneTableBlock } from './utils'; +import { oneTableBlock, newTableBlock } from './utils'; test.describe('view', () => { test('general permission', async ({ page, mockPage, mockRole, updateRole }) => { @@ -23,8 +23,9 @@ test.describe('view', () => { await page.reload(); await expect(page.getByLabel('block-item-CardItem-general-table')).toBeVisible(); }); - test('individual collection permission', async ({ page, mockPage, mockRole, updateRole }) => { + test('individual collection permission', async ({ page, mockPage, mockRole, mockRecord, updateRole }) => { await mockPage(oneTableBlock).goto(); + await mockRecord('general'); //新建角色并切换到新角色 const roleData = await mockRole({ allowNewMenu: true, @@ -56,6 +57,7 @@ test.describe('view', () => { }); await page.reload(); await expect(page.getByLabel('block-item-CardItem-general-table')).toBeVisible(); + await expect(page.getByLabel('action-Action.Link-View')).toBeVisible(); await expect(page.getByRole('button', { name: 'singleLineText' })).not.toBeVisible(); await expect(page.getByRole('button', { name: 'phone' })).not.toBeVisible(); }); @@ -258,6 +260,54 @@ test.describe('update', () => { await page.reload(); await expect(page.getByLabel('action-Action.Link-Edit')).toBeVisible(); }); + test('individual collection permission support new data block', async ({ + page, + mockPage, + mockRole, + mockRecord, + updateRole, + }) => { + await mockPage(newTableBlock).goto(); + await mockRecord('general'); + //新建角色并切换到新角色 + const roleData = await mockRole({ + allowNewMenu: true, + strategy: { + actions: ['update'], + }, + resources: [ + { + usingActionsConfig: true, + name: 'general', + actions: [{ name: 'view' }], + }, + ], + }); + await page.evaluate((roleData) => { + window.localStorage.setItem('NOCOBASE_ROLE', roleData.name); + }, roleData); + await page.reload(); + await mockPage(newTableBlock).goto(); + await expect(page.getByLabel('block-item-CardItem-general-table')).toBeVisible(); + await expect(page.getByLabel('action-Action.Link-Edit')).not.toBeVisible(); + await updateRole({ + name: roleData.name, + resources: [ + { + usingActionsConfig: true, + name: 'general', + actions: [ + { + name: 'view', + }, + { name: 'update' }, + ], + }, + ], + }); + await page.reload(); + await expect(page.getByLabel('action-Action.Link-Edit')).toBeVisible(); + }); test('individual collection permission with fields', async ({ page, mockPage, mockRole, mockRecord }) => { await mockPage(oneTableBlock).goto(); await mockRecord('general'); @@ -311,7 +361,7 @@ test.describe('destroy', () => { await page.reload(); await expect(page.getByLabel('action-Action-Delete-destroy-general-table')).toBeVisible(); }); - test('individual collection permission', async ({ page, mockPage, mockRole, updateRole }) => { + test('individual collection permission', async ({ page, mockPage, mockRole, mockRecord, updateRole }) => { await mockPage().goto(); //新建角色并切换到新角色 const roleData = await mockRole({ @@ -332,8 +382,11 @@ test.describe('destroy', () => { }, roleData); await page.reload(); await mockPage(oneTableBlock).goto(); + await mockRecord('general'); await expect(page.getByLabel('block-item-CardItem-general-table')).toBeVisible(); await expect(page.getByLabel('action-Action-Delete-destroy-general-table')).not.toBeVisible(); + await expect(page.getByLabel('action-Action.Link-Delete')).not.toBeVisible(); + await updateRole({ name: roleData.name, resources: [ @@ -351,6 +404,57 @@ test.describe('destroy', () => { }); await page.reload(); await expect(page.getByLabel('action-Action-Delete-destroy-general-table')).toBeVisible(); + await expect(page.getByLabel('action-Action.Link-Delete')).toBeVisible(); + }); + test('individual collection permission support new data block', async ({ + page, + mockPage, + mockRole, + mockRecord, + updateRole, + }) => { + await mockPage().goto(); + //新建角色并切换到新角色 + const roleData = await mockRole({ + allowNewMenu: true, + strategy: { + actions: ['destroy'], + }, + resources: [ + { + usingActionsConfig: true, + name: 'general', + actions: [{ name: 'view' }], + }, + ], + }); + await page.evaluate((roleData) => { + window.localStorage.setItem('NOCOBASE_ROLE', roleData.name); + }, roleData); + await page.reload(); + await mockPage(newTableBlock).goto(); + await mockRecord('general'); + await expect(page.getByLabel('block-item-CardItem-general-table')).toBeVisible(); + await expect(page.getByLabel('action-Action-Delete-destroy-general-table')).not.toBeVisible(); + await expect(page.getByLabel('action-Action.Link-Delete-')).not.toBeVisible(); + await updateRole({ + name: roleData.name, + resources: [ + { + usingActionsConfig: true, + name: 'general', + actions: [ + { + name: 'view', + }, + { name: 'destroy' }, + ], + }, + ], + }); + await page.reload(); + await expect(page.getByLabel('action-Action-Delete-destroy-general-table')).toBeVisible(); + await expect(page.getByLabel('action-Action.Link-Delete-')).toBeVisible(); }); }); diff --git a/packages/plugins/@nocobase/plugin-acl/src/client/__e2e__/utils.ts b/packages/plugins/@nocobase/plugin-acl/src/client/__e2e__/utils.ts index d61e9c282..c67278a46 100644 --- a/packages/plugins/@nocobase/plugin-acl/src/client/__e2e__/utils.ts +++ b/packages/plugins/@nocobase/plugin-acl/src/client/__e2e__/utils.ts @@ -2182,6 +2182,34 @@ export const oneTableBlock: PageConfig = { 'x-async': false, 'x-index': 4, }, + k4602nzuf6r: { + _isJSONSchemaObject: true, + version: '2.0', + title: '{{ t("Delete") }}', + 'x-action': 'destroy', + 'x-component': 'Action.Link', + 'x-toolbar': 'ActionSchemaToolbar', + 'x-settings': 'actionSettings:delete', + 'x-component-props': { + icon: 'DeleteOutlined', + confirm: { + title: "{{t('Delete record')}}", + content: "{{t('Are you sure you want to delete it?')}}", + }, + useProps: '{{ useDestroyActionProps }}', + }, + 'x-action-settings': { + triggerWorkflows: [], + }, + 'x-decorator': 'ACLActionProvider', + 'x-designer-props': { + linkageAction: true, + }, + type: 'void', + 'x-uid': 'a6mt7vf9g67', + 'x-async': false, + 'x-index': 5, + }, }, 'x-uid': 'mi05lvz5sj2', 'x-async': false, @@ -2548,3 +2576,545 @@ export const oneTableBlock: PageConfig = { 'x-index': 1, }, }; + +export const newTableBlock: PageConfig = { + collections: general, + pageSchema: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': 'Page', + properties: { + '46txyuq0grs': { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': 'Grid', + 'x-initializer': 'page:addBlock', + properties: { + zahcrjgcnp9: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': 'Grid.Row', + properties: { + au2rt1euteu: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': 'Grid.Col', + properties: { + ml4odxr7n6g: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-decorator': 'TableBlockProvider', + 'x-acl-action': 'general:list', + 'x-decorator-props': { + collection: 'general', + dataSource: 'main', + action: 'list', + params: { + pageSize: 20, + }, + rowKey: 'id', + showIndex: true, + dragSort: false, + disableTemplate: false, + }, + 'x-toolbar': 'BlockSchemaToolbar', + 'x-settings': 'blockSettings:table', + 'x-component': 'CardItem', + 'x-filter-targets': [], + properties: { + actions: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-initializer': 'table:configureActions', + 'x-component': 'ActionBar', + 'x-component-props': { + style: { + marginBottom: 'var(--nb-spacing)', + }, + }, + properties: { + slrfnm3niyj: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + title: '{{ t("Bulk update") }}', + 'x-component': 'Action', + 'x-align': 'right', + 'x-acl-action': 'update', + 'x-decorator': 'ACLActionProvider', + 'x-acl-action-props': { + skipScopeCheck: true, + }, + 'x-action': 'customize:bulkUpdate', + 'x-toolbar': 'ActionSchemaToolbar', + 'x-settings': 'actionSettings:bulkUpdate', + 'x-action-settings': { + assignedValues: {}, + updateMode: 'selected', + onSuccess: { + manualClose: true, + redirecting: false, + successMessage: '{{t("Updated successfully")}}', + }, + }, + 'x-component-props': { + icon: 'EditOutlined', + useProps: '{{ useCustomizeBulkUpdateActionProps }}', + }, + 'x-uid': 'n1qxijc21mx', + 'x-async': false, + 'x-index': 1, + }, + '2zkhhoww1fr': { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + title: '{{t("Bulk edit")}}', + 'x-component': 'Action', + 'x-action': 'customize:bulkEdit', + 'x-action-settings': { + updateMode: 'selected', + }, + 'x-component-props': { + openMode: 'drawer', + icon: 'EditOutlined', + }, + 'x-align': 'right', + 'x-decorator': 'ACLActionProvider', + 'x-toolbar': 'ActionSchemaToolbar', + 'x-settings': 'actionSettings:bulkEdit', + 'x-acl-action': 'update', + 'x-acl-action-props': { + skipScopeCheck: true, + }, + properties: { + drawer: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + title: '{{t("Bulk edit")}}', + 'x-component': 'Action.Container', + 'x-component-props': { + className: 'nb-action-popup', + }, + properties: { + tabs: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': 'Tabs', + 'x-component-props': {}, + 'x-initializer': 'TabPaneInitializersForBulkEditFormBlock', + properties: { + tab1: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + title: '{{t("Bulk edit")}}', + 'x-component': 'Tabs.TabPane', + 'x-designer': 'Tabs.Designer', + 'x-component-props': {}, + properties: { + grid: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': 'Grid', + 'x-initializer': 'popup:bulkEdit:addBlock', + 'x-uid': '8nuffbe34bb', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': '4oldm9wc10s', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': '194thgnvcpy', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': '1x3ly7atx00', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': '75x1gquc69a', + 'x-async': false, + 'x-index': 2, + }, + huteob4p7ua: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-action': 'create', + 'x-acl-action': 'create', + title: "{{t('Add new')}}", + 'x-toolbar': 'ActionSchemaToolbar', + 'x-settings': 'actionSettings:addNew', + 'x-component': 'Action', + 'x-decorator': 'ACLActionProvider', + 'x-component-props': { + openMode: 'drawer', + type: 'primary', + component: 'CreateRecordAction', + icon: 'PlusOutlined', + }, + 'x-align': 'right', + 'x-acl-action-props': { + skipScopeCheck: true, + }, + properties: { + drawer: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + title: '{{ t("Add record") }}', + 'x-component': 'Action.Container', + 'x-component-props': { + className: 'nb-action-popup', + }, + properties: { + tabs: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': 'Tabs', + 'x-component-props': {}, + 'x-initializer': 'TabPaneInitializersForCreateFormBlock', + properties: { + tab1: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + title: '{{t("Add new")}}', + 'x-component': 'Tabs.TabPane', + 'x-designer': 'Tabs.Designer', + 'x-component-props': {}, + properties: { + grid: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': 'Grid', + 'x-initializer': 'popup:addNew:addBlock', + 'x-uid': 'yjj9tl588o1', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': '0zjlqupqrd0', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': 'sjmso5vq3bc', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': '131b76phmyr', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': '4ekiy4xn5ip', + 'x-async': false, + 'x-index': 3, + }, + xi969uyvexr: { + _isJSONSchemaObject: true, + version: '2.0', + title: '{{ t("Delete") }}', + 'x-action': 'destroy', + 'x-component': 'Action', + 'x-toolbar': 'ActionSchemaToolbar', + 'x-settings': 'actionSettings:bulkDelete', + 'x-decorator': 'ACLActionProvider', + 'x-acl-action-props': { + skipScopeCheck: true, + }, + 'x-component-props': { + icon: 'DeleteOutlined', + confirm: { + title: "{{t('Delete record')}}", + content: "{{t('Are you sure you want to delete it?')}}", + }, + useProps: '{{ useBulkDestroyActionProps }}', + }, + 'x-action-settings': { + triggerWorkflows: [], + }, + 'x-acl-action': 'general:destroy', + 'x-align': 'right', + type: 'void', + 'x-uid': 'x5nhm8j5prk', + 'x-async': false, + 'x-index': 4, + }, + }, + 'x-uid': 's99upcj5h12', + 'x-async': false, + 'x-index': 1, + }, + '1pflm3akx4z': { + _isJSONSchemaObject: true, + version: '2.0', + type: 'array', + 'x-initializer': 'table:configureColumns', + 'x-component': 'TableV2', + 'x-component-props': { + rowKey: 'id', + rowSelection: { + type: 'checkbox', + }, + useProps: '{{ useTableBlockProps }}', + }, + properties: { + actions: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + title: '{{ t("Actions") }}', + 'x-action-column': 'actions', + 'x-decorator': 'TableV2.Column.ActionBar', + 'x-component': 'TableV2.Column', + 'x-designer': 'TableV2.ActionColumnDesigner', + 'x-initializer': 'table:configureItemActions', + properties: { + '0vgecinvudu': { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-decorator': 'DndContext', + 'x-component': 'Space', + 'x-component-props': { + split: '|', + }, + properties: { + kieddfdng7p: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + title: '{{ t("View") }}', + 'x-action': 'view', + 'x-toolbar': 'ActionSchemaToolbar', + 'x-settings': 'actionSettings:view', + 'x-component': 'Action.Link', + 'x-component-props': { + openMode: 'drawer', + }, + 'x-decorator': 'ACLActionProvider', + 'x-designer-props': { + linkageAction: true, + }, + properties: { + drawer: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + title: '{{ t("View record") }}', + 'x-component': 'Action.Container', + 'x-component-props': { + className: 'nb-action-popup', + }, + properties: { + tabs: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': 'Tabs', + 'x-component-props': {}, + 'x-initializer': 'TabPaneInitializers', + properties: { + tab1: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + title: '{{t("Details")}}', + 'x-component': 'Tabs.TabPane', + 'x-designer': 'Tabs.Designer', + 'x-component-props': {}, + properties: { + grid: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': 'Grid', + 'x-initializer': 'popup:common:addBlock', + 'x-uid': '2k0540e57ol', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': 's7gi356fs70', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': '8grec6h6mtp', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': 'assiov38tvg', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': 'utm143emmhc', + 'x-async': false, + 'x-index': 1, + }, + is523lf1al3: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + title: '{{ t("Edit") }}', + 'x-action': 'update', + 'x-toolbar': 'ActionSchemaToolbar', + 'x-settings': 'actionSettings:edit', + 'x-component': 'Action.Link', + 'x-component-props': { + openMode: 'drawer', + icon: 'EditOutlined', + }, + 'x-decorator': 'ACLActionProvider', + 'x-designer-props': { + linkageAction: true, + }, + properties: { + drawer: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + title: '{{ t("Edit record") }}', + 'x-component': 'Action.Container', + 'x-component-props': { + className: 'nb-action-popup', + }, + properties: { + tabs: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': 'Tabs', + 'x-component-props': {}, + 'x-initializer': 'TabPaneInitializers', + properties: { + tab1: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + title: '{{t("Edit")}}', + 'x-component': 'Tabs.TabPane', + 'x-designer': 'Tabs.Designer', + 'x-component-props': {}, + properties: { + grid: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': 'Grid', + 'x-initializer': 'popup:common:addBlock', + 'x-uid': 'wsyp993s4e3', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': 'cffbmo4sb6k', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': '9dwrb18ntjm', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': 'rz924lz6i2u', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': 'nkrdjd1jz5j', + 'x-async': false, + 'x-index': 2, + }, + k4602nzuf6r: { + _isJSONSchemaObject: true, + version: '2.0', + title: '{{ t("Delete") }}', + 'x-action': 'destroy', + 'x-component': 'Action.Link', + 'x-toolbar': 'ActionSchemaToolbar', + 'x-settings': 'actionSettings:delete', + 'x-component-props': { + icon: 'DeleteOutlined', + confirm: { + title: "{{t('Delete record')}}", + content: "{{t('Are you sure you want to delete it?')}}", + }, + useProps: '{{ useDestroyActionProps }}', + }, + 'x-action-settings': { + triggerWorkflows: [], + }, + 'x-decorator': 'ACLActionProvider', + 'x-designer-props': { + linkageAction: true, + }, + type: 'void', + 'x-uid': 'a6mt7vf9g67', + 'x-async': false, + 'x-index': 3, + }, + }, + 'x-uid': '7q9j7135hk4', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': 'c8iecn06wyp', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': 'm0blrbf9bzr', + 'x-async': false, + 'x-index': 2, + }, + }, + 'x-uid': '63uhxny4lrn', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': 'tcne2atmx0n', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': 'bk1yx2i13k8', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': 'if4rb336r5q', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': '532o6vwg8bi', + 'x-async': true, + 'x-index': 1, + }, +};