cabloy 5.1.190 → 5.1.191
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.cabloy-version +1 -1
- package/CHANGELOG.md +10 -0
- package/README.md +2 -2
- package/package.json +1 -1
- package/repo-docs/.vitepress/config.mjs +1 -0
- package/repo-docs/demo.md +12 -0
- package/repo-docs/index.md +3 -0
- package/zova/packages-zova/zova/package.json +2 -2
- package/zova/src/suite/a-home/modules/home-passport/src/model/passport.ts +2 -7
- package/zova/src/suite/cabloy-basic/modules/basic-details/src/bean/tableCell.actionOperationsRow.tsx +19 -13
- package/zova/src/suite/cabloy-basic/modules/basic-details/src/component/blockDetails/controller.tsx +11 -0
- package/zova/src/suite/cabloy-basic/modules/basic-details/src/component/blockToolbarBulk/controller.tsx +7 -4
- package/zova/src/suite/cabloy-basic/modules/basic-details/src/component/formFieldDetails/controller.tsx +14 -0
- package/zova/src/suite/cabloy-basic/modules/basic-details/src/lib/detailsPermissions.ts +65 -0
- package/zova/src/suite/cabloy-basic/modules/basic-details/src/lib/index.ts +1 -0
- package/zova/src/suite/cabloy-basic/modules/basic-details/src/lib/utils.ts +3 -3
- package/zova/src/suite/cabloy-basic/modules/basic-details/src/types/details.ts +6 -1
- package/zova/src/suite/cabloy-basic/modules/basic-details/test/lib/detailsPermissions.test.ts +125 -0
- package/zova/src/suite-vendor/a-zova/modules/a-openapi/package.json +1 -1
- package/zova/src/suite-vendor/a-zova/modules/a-openapi/src/types/permissions.ts +2 -8
- package/zova/src/suite-vendor/a-zova/modules/a-table/package.json +1 -1
- package/zova/src/suite-vendor/a-zova/modules/a-table/src/component/table/controller.tsx +2 -1
- package/zova/src/suite-vendor/a-zova/package.json +3 -3
package/.cabloy-version
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
5.1.
|
|
1
|
+
5.1.191
|
package/CHANGELOG.md
CHANGED
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
[](https://www.npmjs.com/package/cabloy)
|
|
5
5
|
[](https://www.npmjs.com/package/cabloy)
|
|
6
6
|
[](https://cabloy.com)
|
|
7
|
-
[](https://cabloy.com)
|
|
7
|
+
[](https://cabloy.com/demo)
|
|
8
8
|
|
|
9
9
|
Cabloy is a Node.js fullstack framework for AI vibe coding, with AI Spec-Driven Development for traceable, evidence-backed delivery.
|
|
10
10
|
|
|
@@ -12,7 +12,7 @@ Cabloy is a Node.js fullstack framework for AI vibe coding, with AI Spec-Driven
|
|
|
12
12
|
|
|
13
13
|
Instead of stitching separate backend and frontend stacks together, Cabloy keeps their contracts, tooling, and guidance connected in one repository. [AI Spec-Driven Development](https://cabloy.com/ai/ai-spec-driven-development) provides the disciplined path from confirmed Specs to evidence-backed delivery; its precise engineering method is Traceable Spec Delivery. Vona is its backend framework and runtime layer, and Zova is its frontend framework and application layer. Cabloy Basic and Cabloy Start are related, complete edition baselines built on that shared architecture; see [Editions Overview](https://cabloy.com/editions/overview) for their deliberate differences.
|
|
14
14
|
|
|
15
|
-
[Documentation](https://cabloy.com) · [npm](https://www.npmjs.com/package/cabloy) · [
|
|
15
|
+
[Documentation](https://cabloy.com) · [npm](https://www.npmjs.com/package/cabloy) · [Demo](https://cabloy.com/demo) · [GitHub](https://github.com/cabloy/cabloy)
|
|
16
16
|
|
|
17
17
|
## Fullstack Principles
|
|
18
18
|
|
package/package.json
CHANGED
|
@@ -245,6 +245,7 @@ export default defineConfig({
|
|
|
245
245
|
{ text: 'Frontend (Zova)', link: '/frontend/introduction', activeMatch: '^/frontend/' },
|
|
246
246
|
],
|
|
247
247
|
},
|
|
248
|
+
{ text: 'Demo', link: '/demo' },
|
|
248
249
|
{ text: 'Blogs', link: '/blogs/', activeMatch: '^/blogs/' },
|
|
249
250
|
{ text: 'Editions', link: '/editions/overview', activeMatch: '^/editions/' },
|
|
250
251
|
{ text: 'AI Development', link: '/ai/introduction', activeMatch: '^/ai/' },
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Demo
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# Demo
|
|
6
|
+
|
|
7
|
+
Explore the Cabloy demonstration sites:
|
|
8
|
+
|
|
9
|
+
| Site | URL |
|
|
10
|
+
| ---------- | ---------------------------------------------------------------- |
|
|
11
|
+
| Web site | [https://demo.cabloy.com/](https://demo.cabloy.com/) |
|
|
12
|
+
| Admin site | [https://demo.cabloy.com/admin/](https://demo.cabloy.com/admin/) |
|
package/repo-docs/index.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "zova",
|
|
3
|
-
"version": "5.1.
|
|
3
|
+
"version": "5.1.167",
|
|
4
4
|
"gitHead": "2c5c19284bab738e492856189acb6fad74b8a7b7",
|
|
5
5
|
"description": "A vue3 framework with ioc",
|
|
6
6
|
"keywords": [
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
},
|
|
47
47
|
"dependencies": {
|
|
48
48
|
"zova-core": "^5.1.92",
|
|
49
|
-
"zova-suite-a-zova": "^5.1.
|
|
49
|
+
"zova-suite-a-zova": "^5.1.166"
|
|
50
50
|
},
|
|
51
51
|
"devDependencies": {
|
|
52
52
|
"clean-package": "^2.2.0",
|
|
@@ -10,12 +10,7 @@ import type {
|
|
|
10
10
|
import { combineQueries, isNil } from '@cabloy/utils';
|
|
11
11
|
import { SchemaObject } from 'openapi3-ts/oas31';
|
|
12
12
|
import { $QueryEnsureFresh, $QueryGetFresh, BeanModelBase, Model } from 'zova-module-a-model';
|
|
13
|
-
import {
|
|
14
|
-
IPermissionHintGeneral,
|
|
15
|
-
IResourceFormActionRowNameRecord,
|
|
16
|
-
IResourceTableActionNameRecord,
|
|
17
|
-
TypeOpenapiPermissions,
|
|
18
|
-
} from 'zova-module-a-openapi';
|
|
13
|
+
import { IPermissionHintGeneral, TypeOpenapiPermissions } from 'zova-module-a-openapi';
|
|
19
14
|
import { ApiApiHomeUserPassportloginOauthPath, OpenApiBaseURL } from 'zova-module-home-api';
|
|
20
15
|
import { isRoleSiteAdmitted } from 'zova-module-home-base';
|
|
21
16
|
|
|
@@ -272,7 +267,7 @@ export class ModelPassport extends BeanModelBase {
|
|
|
272
267
|
|
|
273
268
|
public checkPermission(
|
|
274
269
|
permissions: TypeOpenapiPermissions | undefined,
|
|
275
|
-
actionName?:
|
|
270
|
+
actionName?: string,
|
|
276
271
|
permissionHint?: IPermissionHintGeneral,
|
|
277
272
|
currentData?: Record<string, unknown> | readonly Record<string, unknown>[],
|
|
278
273
|
): boolean {
|
package/zova/src/suite/cabloy-basic/modules/basic-details/src/bean/tableCell.actionOperationsRow.tsx
CHANGED
|
@@ -14,7 +14,8 @@ import { VNode } from 'vue';
|
|
|
14
14
|
import { BeanBase } from 'zova';
|
|
15
15
|
import { TableCell } from 'zova-module-a-table';
|
|
16
16
|
|
|
17
|
-
import {
|
|
17
|
+
import { filterDetailsRowActions } from '../lib/detailsPermissions.js';
|
|
18
|
+
import { checkFormScene } from '../lib/utils.js';
|
|
18
19
|
|
|
19
20
|
declare module 'zova-module-a-openapi' {
|
|
20
21
|
export interface IResourceDetailsActionRowRecord {
|
|
@@ -37,16 +38,16 @@ export class TableCellActionOperationsRow extends BeanBase implements ITableCell
|
|
|
37
38
|
const { $celScope, $$table } = renderContext;
|
|
38
39
|
const actions = options.actions;
|
|
39
40
|
if (!actions || actions.length === 0) return false;
|
|
40
|
-
|
|
41
|
+
const $$details = $celScope.$$details!;
|
|
42
|
+
const actionsVisible = actions.filter(action => {
|
|
43
|
+
return checkFormScene($$details.formScene, action.options?.permission);
|
|
44
|
+
});
|
|
41
45
|
const renders: TypeTableCellRenderComponent[] = [];
|
|
42
|
-
for (const action of
|
|
46
|
+
for (const action of actionsVisible) {
|
|
43
47
|
const actionName = action.name;
|
|
44
48
|
const actionRender = action.render;
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
if (!actionRender) throw new Error(`should specify action render: ${actionName}`);
|
|
48
|
-
renders.push(actionRender);
|
|
49
|
-
}
|
|
49
|
+
if (!actionRender) throw new Error(`should specify action render: ${actionName}`);
|
|
50
|
+
renders.push(actionRender);
|
|
50
51
|
}
|
|
51
52
|
await $$table.cellRenderPrepare(renders);
|
|
52
53
|
return renders.length > 0;
|
|
@@ -60,13 +61,18 @@ export class TableCellActionOperationsRow extends BeanBase implements ITableCell
|
|
|
60
61
|
const { $celScope, $$table } = renderContext;
|
|
61
62
|
const actions = options.actions;
|
|
62
63
|
if (!actions || actions.length === 0) return;
|
|
64
|
+
const $$details = $celScope.$$details!;
|
|
65
|
+
const actionsAllowed = filterDetailsRowActions(
|
|
66
|
+
$$details.formScene,
|
|
67
|
+
$$details.checkPermission.bind($$details),
|
|
68
|
+
actions,
|
|
69
|
+
);
|
|
63
70
|
const domActions: VNode[] = [];
|
|
64
|
-
|
|
65
|
-
const
|
|
66
|
-
|
|
67
|
-
const options2 = Object.assign({ key: index }, action.options);
|
|
68
|
-
domActions.push($$table.cellRender(action.render!, options2, renderContext));
|
|
71
|
+
actionsAllowed.forEach((action, index) => {
|
|
72
|
+
const actionOptions = Object.assign({ key: index }, action.options);
|
|
73
|
+
domActions.push($$table.cellRender(action.render!, actionOptions, renderContext));
|
|
69
74
|
});
|
|
75
|
+
if (domActions.length === 0) return;
|
|
70
76
|
return <div class={options.class}>{domActions}</div>;
|
|
71
77
|
}
|
|
72
78
|
}
|
package/zova/src/suite/cabloy-basic/modules/basic-details/src/component/blockDetails/controller.tsx
CHANGED
|
@@ -13,6 +13,8 @@ import {
|
|
|
13
13
|
} from 'zova-module-a-openapi';
|
|
14
14
|
import { BeanControllerTableBase } from 'zova-module-a-table';
|
|
15
15
|
|
|
16
|
+
import type { TypeDetailsCheckPermission } from '../../types/details.js';
|
|
17
|
+
|
|
16
18
|
declare module 'zova-module-a-openapi' {
|
|
17
19
|
export interface IResourceBlockRecord {
|
|
18
20
|
'basic-details:blockDetails'?: ControllerBlockDetailsProps;
|
|
@@ -26,6 +28,7 @@ export interface ControllerBlockDetailsProps<
|
|
|
26
28
|
formMeta?: IFormMeta;
|
|
27
29
|
schemaRow?: ISchemaObjectExtensionField;
|
|
28
30
|
schemaForm?: ISchemaObjectExtensionField;
|
|
31
|
+
checkPermission?: TypeDetailsCheckPermission;
|
|
29
32
|
getDetailItems?: () => TData[] | undefined;
|
|
30
33
|
setDetailItems?: (detailItems: TData[]) => void;
|
|
31
34
|
}
|
|
@@ -70,6 +73,14 @@ export class ControllerBlockDetails<TData extends {} = {}> extends BeanControlle
|
|
|
70
73
|
return this.$props.schemaForm!;
|
|
71
74
|
}
|
|
72
75
|
|
|
76
|
+
checkPermission(...args: Parameters<TypeDetailsCheckPermission>) {
|
|
77
|
+
const checkPermission = this.$props.checkPermission;
|
|
78
|
+
if (!checkPermission) {
|
|
79
|
+
throw new Error('should provide enclosing Resource permission checker for details');
|
|
80
|
+
}
|
|
81
|
+
return checkPermission(...args);
|
|
82
|
+
}
|
|
83
|
+
|
|
73
84
|
public async setTableRef(tableRef: BeanControllerTableBase<TData> | undefined) {
|
|
74
85
|
this.tableRef = tableRef;
|
|
75
86
|
}
|
|
@@ -9,7 +9,7 @@ import { VNode } from 'vue';
|
|
|
9
9
|
import { BeanControllerBase, Use } from 'zova';
|
|
10
10
|
import { Controller } from 'zova-module-a-bean';
|
|
11
11
|
|
|
12
|
-
import {
|
|
12
|
+
import { filterDetailsBulkActions } from '../../lib/detailsPermissions.js';
|
|
13
13
|
|
|
14
14
|
declare module 'zova-module-a-openapi' {
|
|
15
15
|
export interface IResourceBlockRecord {
|
|
@@ -46,9 +46,12 @@ export class ControllerBlockToolbarBulk extends BeanControllerBase {
|
|
|
46
46
|
const actions = this.$props.actions;
|
|
47
47
|
if (!actions || actions.length === 0) return;
|
|
48
48
|
const domActions: VNode[] = [];
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
49
|
+
const allowedActions = filterDetailsBulkActions(
|
|
50
|
+
$$details.formScene,
|
|
51
|
+
$$details.checkPermission.bind($$details),
|
|
52
|
+
actions,
|
|
53
|
+
);
|
|
54
|
+
allowedActions.forEach((action, index) => {
|
|
52
55
|
const options = Object.assign({ key: index }, action.options);
|
|
53
56
|
const domAction = $jsx.render(action.render!, options, $celScope, this.$$renderContext);
|
|
54
57
|
if (!domAction) return;
|
|
@@ -8,6 +8,7 @@ import type {
|
|
|
8
8
|
IResourceFormFieldOptionsBase,
|
|
9
9
|
ISchemaObjectExtensionField,
|
|
10
10
|
TypeFormScene,
|
|
11
|
+
TypeOpenapiPermissions,
|
|
11
12
|
} from 'zova-module-a-openapi';
|
|
12
13
|
|
|
13
14
|
import { VNode } from 'vue';
|
|
@@ -16,6 +17,10 @@ import { ZovaJsx } from 'zova-jsx';
|
|
|
16
17
|
import { Controller } from 'zova-module-a-bean';
|
|
17
18
|
import { formMetaFromFormScene, ZFormField } from 'zova-module-a-form';
|
|
18
19
|
|
|
20
|
+
import type { TypeDetailsCheckPermission } from '../../types/details.js';
|
|
21
|
+
|
|
22
|
+
import { createDetailsPermissionChecker } from '../../lib/detailsPermissions.js';
|
|
23
|
+
|
|
19
24
|
declare module 'zova-module-a-openapi' {
|
|
20
25
|
export interface IResourceFormFieldRecord {
|
|
21
26
|
'basic-details:formFieldDetails'?: IResourceFormFieldDetailsOptions;
|
|
@@ -76,6 +81,14 @@ export class ControllerFormFieldDetails extends BeanControllerBase {
|
|
|
76
81
|
// blocks
|
|
77
82
|
const blocks = schemaRow?.rest?.blocks;
|
|
78
83
|
if (!blocks || blocks.length === 0) return;
|
|
84
|
+
const checkPermission: TypeDetailsCheckPermission = createDetailsPermissionChecker(
|
|
85
|
+
() =>
|
|
86
|
+
(formFieldRenderContext.celScope as { permissions?: TypeOpenapiPermissions }).permissions,
|
|
87
|
+
() => $$formField.$$form.formState.values as Record<string, unknown>,
|
|
88
|
+
(permissions, actionName, permissionHint, currentData) => {
|
|
89
|
+
return this.$passport.checkPermission(permissions, actionName, permissionHint, currentData);
|
|
90
|
+
},
|
|
91
|
+
);
|
|
79
92
|
const domBlocks: VNode[] = [];
|
|
80
93
|
blocks.forEach((block, index) => {
|
|
81
94
|
const options = deepExtend(
|
|
@@ -92,6 +105,7 @@ export class ControllerFormFieldDetails extends BeanControllerBase {
|
|
|
92
105
|
},
|
|
93
106
|
},
|
|
94
107
|
block.options,
|
|
108
|
+
{ checkPermission },
|
|
95
109
|
);
|
|
96
110
|
const domBlock = this.jsxZova.render(block.render!, options);
|
|
97
111
|
if (!domBlock) return;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
IPermissionHintGeneral,
|
|
3
|
+
IResourceRenderDetailsActionBulkOptionsAction,
|
|
4
|
+
IResourceRenderDetailsActionRowOptionsAction,
|
|
5
|
+
TypeFormScene,
|
|
6
|
+
TypeOpenapiPermissions,
|
|
7
|
+
} from 'zova-module-a-openapi';
|
|
8
|
+
|
|
9
|
+
import type { TypeDetailsCheckPermission } from '../types/details.js';
|
|
10
|
+
|
|
11
|
+
import { checkFormScene } from './utils.js';
|
|
12
|
+
|
|
13
|
+
export interface IDetailsPermissionAction {
|
|
14
|
+
name?: string;
|
|
15
|
+
options?: { permission?: IPermissionHintGeneral };
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function createDetailsPermissionChecker(
|
|
19
|
+
getPermissions: () => TypeOpenapiPermissions | undefined,
|
|
20
|
+
getCurrentData: () => Record<string, unknown> | undefined,
|
|
21
|
+
checkPermission: (
|
|
22
|
+
permissions: TypeOpenapiPermissions | undefined,
|
|
23
|
+
actionName?: string,
|
|
24
|
+
permissionHint?: IPermissionHintGeneral,
|
|
25
|
+
currentData?: Record<string, unknown>,
|
|
26
|
+
) => boolean,
|
|
27
|
+
): TypeDetailsCheckPermission {
|
|
28
|
+
return (actionName, permissionHint) => {
|
|
29
|
+
return checkPermission(getPermissions(), actionName, permissionHint, getCurrentData());
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function isDetailsActionAllowed(
|
|
34
|
+
formScene: TypeFormScene,
|
|
35
|
+
checkPermission: TypeDetailsCheckPermission,
|
|
36
|
+
action: IDetailsPermissionAction,
|
|
37
|
+
): boolean {
|
|
38
|
+
const permissionHint = action.options?.permission;
|
|
39
|
+
return checkFormScene(formScene, permissionHint) && checkPermission(action.name, permissionHint);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function filterDetailsActions<TAction extends IDetailsPermissionAction>(
|
|
43
|
+
formScene: TypeFormScene,
|
|
44
|
+
checkPermission: TypeDetailsCheckPermission,
|
|
45
|
+
actions: TAction[] | undefined,
|
|
46
|
+
): TAction[] {
|
|
47
|
+
if (!actions || actions.length === 0) return [];
|
|
48
|
+
return actions.filter(action => isDetailsActionAllowed(formScene, checkPermission, action));
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function filterDetailsBulkActions(
|
|
52
|
+
formScene: TypeFormScene,
|
|
53
|
+
checkPermission: TypeDetailsCheckPermission,
|
|
54
|
+
actions: IResourceRenderDetailsActionBulkOptionsAction[] | undefined,
|
|
55
|
+
) {
|
|
56
|
+
return filterDetailsActions(formScene, checkPermission, actions);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export function filterDetailsRowActions(
|
|
60
|
+
formScene: TypeFormScene,
|
|
61
|
+
checkPermission: TypeDetailsCheckPermission,
|
|
62
|
+
actions: IResourceRenderDetailsActionRowOptionsAction[] | undefined,
|
|
63
|
+
) {
|
|
64
|
+
return filterDetailsActions(formScene, checkPermission, actions);
|
|
65
|
+
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { IPermissionHintGeneral, TypeFormScene } from 'zova-module-a-openapi';
|
|
2
2
|
|
|
3
|
-
export function
|
|
3
|
+
export function checkFormScene(
|
|
4
4
|
formScene: TypeFormScene,
|
|
5
|
-
permissionHint?:
|
|
5
|
+
permissionHint?: IPermissionHintGeneral,
|
|
6
6
|
): boolean {
|
|
7
7
|
const formSceneHint = permissionHint?.formScene;
|
|
8
8
|
if (!formSceneHint) return true;
|
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
import 'zova-module-a-table';
|
|
2
2
|
import 'zova-module-a-openapi';
|
|
3
|
-
import type { IDetailsScope } from 'zova-module-a-openapi';
|
|
3
|
+
import type { IDetailsScope, IPermissionHintGeneral } from 'zova-module-a-openapi';
|
|
4
4
|
|
|
5
5
|
import { ControllerBlockDetails } from '../component/blockDetails/controller.jsx';
|
|
6
6
|
|
|
7
|
+
export type TypeDetailsCheckPermission = (
|
|
8
|
+
actionName?: string,
|
|
9
|
+
permissionHint?: IPermissionHintGeneral,
|
|
10
|
+
) => boolean;
|
|
11
|
+
|
|
7
12
|
declare module 'zova-module-a-openapi' {
|
|
8
13
|
export interface IJsxRenderContextDetails<TData extends {} = {}> {
|
|
9
14
|
$$details: ControllerBlockDetails<TData>;
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import type { IPermissionHintGeneral, TypeOpenapiPermissions } from 'zova-module-a-openapi';
|
|
2
|
+
|
|
3
|
+
import assert from 'node:assert/strict';
|
|
4
|
+
import test from 'node:test';
|
|
5
|
+
|
|
6
|
+
import {
|
|
7
|
+
createDetailsPermissionChecker,
|
|
8
|
+
filterDetailsBulkActions,
|
|
9
|
+
filterDetailsRowActions,
|
|
10
|
+
} from '../../src/lib/detailsPermissions.js';
|
|
11
|
+
|
|
12
|
+
test('details permission checker lazily reads the current enclosing Resource projection', () => {
|
|
13
|
+
let permissions: TypeOpenapiPermissions | undefined = true;
|
|
14
|
+
let currentData: Record<string, unknown> = { departmentId: 7 };
|
|
15
|
+
const calls: unknown[][] = [];
|
|
16
|
+
const checkPermission = createDetailsPermissionChecker(
|
|
17
|
+
() => permissions,
|
|
18
|
+
() => currentData,
|
|
19
|
+
(...args) => {
|
|
20
|
+
calls.push(args);
|
|
21
|
+
return true;
|
|
22
|
+
},
|
|
23
|
+
);
|
|
24
|
+
const permissionHint: IPermissionHintGeneral = { actionInherit: 'view' };
|
|
25
|
+
|
|
26
|
+
const firstPermissions = permissions;
|
|
27
|
+
const firstCurrentData = currentData;
|
|
28
|
+
assert.equal(checkPermission('grantSystemAdmin', permissionHint), true);
|
|
29
|
+
permissions = false;
|
|
30
|
+
currentData = { departmentId: 8 };
|
|
31
|
+
assert.equal(checkPermission('grantSystemAdmin', permissionHint), true);
|
|
32
|
+
|
|
33
|
+
assert.equal(calls.length, 2);
|
|
34
|
+
assert.strictEqual(calls[0][0], firstPermissions);
|
|
35
|
+
assert.strictEqual(calls[1][0], permissions);
|
|
36
|
+
assert.strictEqual(calls[0][3], firstCurrentData);
|
|
37
|
+
assert.strictEqual(calls[1][3], currentData);
|
|
38
|
+
assert.deepEqual(
|
|
39
|
+
calls.map(call => call.slice(1, 3)),
|
|
40
|
+
[
|
|
41
|
+
['grantSystemAdmin', permissionHint],
|
|
42
|
+
['grantSystemAdmin', permissionHint],
|
|
43
|
+
],
|
|
44
|
+
);
|
|
45
|
+
assert.equal(
|
|
46
|
+
calls.every(call => call.length === 4),
|
|
47
|
+
true,
|
|
48
|
+
);
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
test('bulk details actions apply form-scene filtering before the enclosing Resource checker', () => {
|
|
52
|
+
const calls: Array<[string | undefined, IPermissionHintGeneral | undefined]> = [];
|
|
53
|
+
const grantHint = { actionInherit: 'view', formScene: ['view'] };
|
|
54
|
+
const actions = [
|
|
55
|
+
{
|
|
56
|
+
name: 'hiddenInView',
|
|
57
|
+
render: 'test:hiddenInView',
|
|
58
|
+
options: { permission: { formScene: ['edit'] } },
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
name: 'denied',
|
|
62
|
+
render: 'test:denied',
|
|
63
|
+
options: { permission: { formScene: ['view'] } },
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
name: 'grantSystemAdmin',
|
|
67
|
+
render: 'test:grantSystemAdmin',
|
|
68
|
+
options: { permission: grantHint },
|
|
69
|
+
},
|
|
70
|
+
];
|
|
71
|
+
|
|
72
|
+
const allowed = filterDetailsBulkActions(
|
|
73
|
+
'view',
|
|
74
|
+
(actionName, permissionHint) => {
|
|
75
|
+
calls.push([actionName, permissionHint]);
|
|
76
|
+
return actionName === 'grantSystemAdmin';
|
|
77
|
+
},
|
|
78
|
+
actions as any,
|
|
79
|
+
);
|
|
80
|
+
|
|
81
|
+
assert.deepEqual(
|
|
82
|
+
allowed.map(action => action.name),
|
|
83
|
+
['grantSystemAdmin'],
|
|
84
|
+
);
|
|
85
|
+
assert.deepEqual(
|
|
86
|
+
calls.map(([actionName]) => actionName),
|
|
87
|
+
['denied', 'grantSystemAdmin'],
|
|
88
|
+
);
|
|
89
|
+
assert.strictEqual(calls[1][1], grantHint);
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
test('row details actions use the same enclosing Resource checker and form-scene gate', () => {
|
|
93
|
+
const calls: string[] = [];
|
|
94
|
+
const actions = [
|
|
95
|
+
{
|
|
96
|
+
name: 'hiddenInView',
|
|
97
|
+
render: 'test:hiddenInView',
|
|
98
|
+
options: { permission: { formScene: ['edit'] } },
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
name: 'allowed',
|
|
102
|
+
render: 'test:allowed',
|
|
103
|
+
options: { permission: { public: true } },
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
name: 'denied',
|
|
107
|
+
render: 'test:denied',
|
|
108
|
+
},
|
|
109
|
+
];
|
|
110
|
+
|
|
111
|
+
const allowed = filterDetailsRowActions(
|
|
112
|
+
'view',
|
|
113
|
+
actionName => {
|
|
114
|
+
calls.push(actionName!);
|
|
115
|
+
return actionName === 'allowed';
|
|
116
|
+
},
|
|
117
|
+
actions as any,
|
|
118
|
+
);
|
|
119
|
+
|
|
120
|
+
assert.deepEqual(
|
|
121
|
+
allowed.map(action => action.name),
|
|
122
|
+
['allowed'],
|
|
123
|
+
);
|
|
124
|
+
assert.deepEqual(calls, ['allowed', 'denied']);
|
|
125
|
+
});
|
|
@@ -52,12 +52,6 @@ export interface IPermissionHintTableActionBulk {
|
|
|
52
52
|
public?: boolean;
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
-
export interface IPermissionHintDetailsActionRow {
|
|
56
|
-
formScene?: TypeFormScene | TypeFormScene[];
|
|
57
|
-
}
|
|
55
|
+
export interface IPermissionHintDetailsActionRow extends IPermissionHintGeneral {}
|
|
58
56
|
|
|
59
|
-
export interface IPermissionHintDetailsActionBulk {
|
|
60
|
-
// actionInherit?: keyof IResourceDetailsActionBulkNameRecord;
|
|
61
|
-
// public?: boolean;
|
|
62
|
-
formScene?: TypeFormScene | TypeFormScene[];
|
|
63
|
-
}
|
|
57
|
+
export interface IPermissionHintDetailsActionBulk extends IPermissionHintGeneral {}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type {
|
|
2
|
+
IResourceDetailsActionRowOptionsBase,
|
|
2
3
|
IResourceTableActionRowOptionsBase,
|
|
3
4
|
ISchemaObjectExtensionField,
|
|
4
5
|
ISchemaObjectExtensionFieldRest,
|
|
@@ -466,7 +467,7 @@ export class ControllerTable<TData extends {} = {}> extends BeanControllerTableB
|
|
|
466
467
|
|
|
467
468
|
public cellRender(
|
|
468
469
|
render: TypeTableCellRenderComponent,
|
|
469
|
-
columnProps: IResourceTableActionRowOptionsBase,
|
|
470
|
+
columnProps: IResourceTableActionRowOptionsBase | IResourceDetailsActionRowOptionsBase,
|
|
470
471
|
renderContext: IJsxRenderContextTableCell,
|
|
471
472
|
) {
|
|
472
473
|
// render
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "zova-suite-a-zova",
|
|
3
|
-
"version": "5.1.
|
|
3
|
+
"version": "5.1.166",
|
|
4
4
|
"gitHead": "2c5c19284bab738e492856189acb6fad74b8a7b7",
|
|
5
5
|
"description": "zova",
|
|
6
6
|
"license": "MIT",
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"zova-module-a-logger": "^5.1.28",
|
|
22
22
|
"zova-module-a-meta": "^5.1.22",
|
|
23
23
|
"zova-module-a-model": "^5.1.37",
|
|
24
|
-
"zova-module-a-openapi": "^5.1.
|
|
24
|
+
"zova-module-a-openapi": "^5.1.55",
|
|
25
25
|
"zova-module-a-router": "^5.1.41",
|
|
26
26
|
"zova-module-a-routerstack": "^5.1.29",
|
|
27
27
|
"zova-module-a-routertabs": "^5.1.34",
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
"zova-module-a-ssrhmr": "^5.1.23",
|
|
30
30
|
"zova-module-a-ssrserver": "^5.1.26",
|
|
31
31
|
"zova-module-a-style": "^5.1.35",
|
|
32
|
-
"zova-module-a-table": "^5.1.
|
|
32
|
+
"zova-module-a-table": "^5.1.44",
|
|
33
33
|
"zova-module-a-zod": "^5.1.37",
|
|
34
34
|
"zova-module-a-zova": "^5.1.108"
|
|
35
35
|
},
|