@nocobase/app-template-default 1.0.0-beta.73 → 1.0.0-beta.75
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/AGENTS.md +8 -2
- package/README.MD +3 -1
- package/cli/plugins.ts +2 -1
- package/client/components/default-access-editor.tsx +183 -0
- package/client/components/permission-editor.tsx +216 -150
- package/client/components/role-list.tsx +85 -0
- package/client/lib/navigation-transform.ts +29 -1
- package/client/locales/system/settings-en-US.ts +74 -2
- package/client/locales/system/settings-zh-CN.ts +66 -2
- package/client/pages/settings/default-access-form.tsx +499 -0
- package/client/pages/settings/default-access-model.ts +154 -0
- package/client/pages/settings/default-access.tsx +407 -0
- package/client/pages/settings/permission-filters.tsx +43 -37
- package/client/pages/settings/permission-management-page.tsx +105 -0
- package/client/pages/settings/permissions-model.ts +37 -1
- package/client/pages/settings/role-form.tsx +46 -18
- package/client/pages/settings/roles.tsx +26 -43
- package/client/pages/settings/routes.ts +78 -19
- package/client/pages/settings/shared.tsx +3 -0
- package/client/pages/settings/users.tsx +1 -1
- package/client/plugins.ts +2 -0
- package/client/routing/route-navigation.ts +21 -1
- package/package.json +25 -23
- package/server/plugins.ts +2 -0
- package/tests/components/default-access.test.tsx +554 -0
- package/tests/components/page-harness.test.tsx +132 -112
- package/tests/components/permission-editor.test.tsx +233 -73
- package/tests/components/permission-management-tabs.test.tsx +128 -0
- package/tests/components/role-list.test.tsx +136 -0
- package/tests/components/roles.test.tsx +85 -0
- package/tests/components/user-permissions.test.tsx +12 -0
- package/tests/logic/authorization-assignment-safety.test.ts +82 -0
- package/tests/logic/client-routes.test.ts +8 -0
- package/tests/logic/default-access-model.test.ts +167 -0
- package/tests/logic/foundation-integration.test.ts +62 -0
- package/tests/logic/permission-management-routes.test.ts +64 -0
- package/tests/logic/settings-permissions.test.ts +89 -0
- package/vitest.config.ts +2 -2
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
import { useTranslation } from '@nocobase/i18n/client';
|
|
12
12
|
import {
|
|
13
13
|
useAuthorizationClient,
|
|
14
|
+
useCan,
|
|
14
15
|
type AuthorizationOptionsResponse,
|
|
15
16
|
type LocalizedText,
|
|
16
17
|
type PermissionGrant,
|
|
@@ -20,6 +21,7 @@ import { pagePermissionResources } from './page-permissions.js';
|
|
|
20
21
|
import { pagePermissionTitles } from './page-permission-titles.js';
|
|
21
22
|
import { useEffect, useMemo, useRef, useState, type ReactElement } from 'react';
|
|
22
23
|
import {
|
|
24
|
+
Link,
|
|
23
25
|
useLocation,
|
|
24
26
|
useNavigate,
|
|
25
27
|
useOutletContext,
|
|
@@ -72,6 +74,10 @@ function RoleEditor(): ReactElement {
|
|
|
72
74
|
const options = useSettingsData<{ data: AuthorizationOptionsResponse }>(
|
|
73
75
|
'authorization/permissionSets/options',
|
|
74
76
|
);
|
|
77
|
+
const canReadDefaults = useCan({
|
|
78
|
+
resource: { type: 'settings', id: 'authorization.default-access' },
|
|
79
|
+
action: 'read',
|
|
80
|
+
}).can;
|
|
75
81
|
const canCreate = useRolePermission('create');
|
|
76
82
|
const canUpdate = useRolePermission('update');
|
|
77
83
|
const [nameDraft, setNameDraft] = useState<string>();
|
|
@@ -113,14 +119,35 @@ function RoleEditor(): ReactElement {
|
|
|
113
119
|
title: { key: 'settings.userPermissions' },
|
|
114
120
|
order: 0,
|
|
115
121
|
subsections: [
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
122
|
+
...[
|
|
123
|
+
{
|
|
124
|
+
name: 'users.information',
|
|
125
|
+
title: 'userInformation',
|
|
126
|
+
actions: ['read', 'create', 'update', 'invite', 'delete'],
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
name: 'users.security',
|
|
130
|
+
title: 'accountSecurity',
|
|
131
|
+
actions: [
|
|
132
|
+
'reset-password',
|
|
133
|
+
'disable',
|
|
134
|
+
'enable',
|
|
135
|
+
'revoke-sessions',
|
|
136
|
+
],
|
|
137
|
+
},
|
|
138
|
+
{
|
|
139
|
+
name: 'users.roles',
|
|
140
|
+
title: 'roleAssignment',
|
|
141
|
+
actions: ['assign-role'],
|
|
142
|
+
},
|
|
143
|
+
].map((group) => ({
|
|
144
|
+
name: group.name,
|
|
145
|
+
title: { key: `settings.${group.title}` },
|
|
119
146
|
resources: [
|
|
120
147
|
{
|
|
121
148
|
type: 'user',
|
|
122
149
|
id: '*',
|
|
123
|
-
title: { key:
|
|
150
|
+
title: { key: `settings.${group.title}` },
|
|
124
151
|
actions: [
|
|
125
152
|
{ name: 'read', title: { key: 'settings.readUsers' } },
|
|
126
153
|
{ name: 'create', title: { key: 'settings.createUsers' } },
|
|
@@ -141,10 +168,10 @@ function RoleEditor(): ReactElement {
|
|
|
141
168
|
name: 'revoke-sessions',
|
|
142
169
|
title: { key: 'settings.revokeSessions' },
|
|
143
170
|
},
|
|
144
|
-
],
|
|
171
|
+
].filter((action) => group.actions.includes(action.name)),
|
|
145
172
|
},
|
|
146
173
|
],
|
|
147
|
-
},
|
|
174
|
+
})),
|
|
148
175
|
],
|
|
149
176
|
},
|
|
150
177
|
...source.sections.map((section) => ({
|
|
@@ -316,13 +343,23 @@ function RoleEditor(): ReactElement {
|
|
|
316
343
|
{t('settings.protectedHint')}
|
|
317
344
|
</p>
|
|
318
345
|
)}
|
|
346
|
+
{canReadDefaults && (
|
|
347
|
+
<div>
|
|
348
|
+
<Link
|
|
349
|
+
to='/default-access'
|
|
350
|
+
className='text-sm text-foreground underline-offset-4 hover:underline'
|
|
351
|
+
>
|
|
352
|
+
{t('settings.defaultAccess.manage')}
|
|
353
|
+
</Link>
|
|
354
|
+
</div>
|
|
355
|
+
)}
|
|
319
356
|
<PermissionEditor
|
|
320
357
|
sections={sections}
|
|
321
358
|
readOnly={!allowed || busy}
|
|
322
359
|
labels={{
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
360
|
+
dataRanges: (count) => t('settings.dataRanges', { count }),
|
|
361
|
+
scopeExplanation: t('settings.scopeExplanation'),
|
|
362
|
+
scopeHintFor: (name) => t('settings.scopeHintFor', { name }),
|
|
326
363
|
levelFor: (name) => t('settings.levelFor', { name }),
|
|
327
364
|
search: t('settings.permissionSearch'),
|
|
328
365
|
enabledOnly: t('settings.enabledOnly'),
|
|
@@ -330,8 +367,6 @@ function RoleEditor(): ReactElement {
|
|
|
330
367
|
empty: t('settings.noPermissions'),
|
|
331
368
|
noResults: t('settings.noResults'),
|
|
332
369
|
navigation: t('settings.permissionCategories'),
|
|
333
|
-
summary: (enabled, total) =>
|
|
334
|
-
t('settings.permissionSummary', { enabled, total }),
|
|
335
370
|
}}
|
|
336
371
|
onEnabledChange={(id, enabled) => {
|
|
337
372
|
if (!catalog) return;
|
|
@@ -342,13 +377,6 @@ function RoleEditor(): ReactElement {
|
|
|
342
377
|
);
|
|
343
378
|
setDirty(true);
|
|
344
379
|
}}
|
|
345
|
-
onEnabledBatchChange={(changes) => {
|
|
346
|
-
if (!catalog) return;
|
|
347
|
-
setGrantsDraft((current) =>
|
|
348
|
-
setPermissions(current ?? grants, catalog, changes),
|
|
349
|
-
);
|
|
350
|
-
setDirty(true);
|
|
351
|
-
}}
|
|
352
380
|
onLevelChange={(id, value) => {
|
|
353
381
|
if (value === 'customFilter') {
|
|
354
382
|
setEditingScope(id);
|
|
@@ -7,11 +7,10 @@ import type {
|
|
|
7
7
|
import { type ReactElement } from 'react';
|
|
8
8
|
import { Link, Outlet, useLocation, useSearchParams } from 'react-router';
|
|
9
9
|
import { ShieldCheckIcon, PlusIcon } from 'lucide-react';
|
|
10
|
-
import {
|
|
11
|
-
import { PageHeader } from '#components/page-header';
|
|
10
|
+
import { PermissionManagementPage } from './permission-management-page.js';
|
|
12
11
|
import { Input } from '#components/ui/input';
|
|
13
12
|
import { Button } from '#components/ui/button';
|
|
14
|
-
import {
|
|
13
|
+
import { RoleList } from '#components/role-list';
|
|
15
14
|
import {
|
|
16
15
|
Empty,
|
|
17
16
|
EmptyTitle,
|
|
@@ -60,12 +59,10 @@ export default function RolesPage(): ReactElement {
|
|
|
60
59
|
) : null;
|
|
61
60
|
return (
|
|
62
61
|
<>
|
|
63
|
-
<
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
actions={rows.length || search ? create : undefined}
|
|
68
|
-
/>
|
|
62
|
+
<PermissionManagementPage
|
|
63
|
+
tab='roles'
|
|
64
|
+
actions={rows.length || search ? create : undefined}
|
|
65
|
+
>
|
|
69
66
|
<div className='flex items-center gap-3'>
|
|
70
67
|
<Input
|
|
71
68
|
className='sm:max-w-xs'
|
|
@@ -95,39 +92,25 @@ export default function RolesPage(): ReactElement {
|
|
|
95
92
|
) : (
|
|
96
93
|
!request.error &&
|
|
97
94
|
(rows.length ? (
|
|
98
|
-
<
|
|
99
|
-
{
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
{role.key}
|
|
118
|
-
</p>
|
|
119
|
-
</div>
|
|
120
|
-
</div>
|
|
121
|
-
<Badge variant='secondary'>
|
|
122
|
-
{t(
|
|
123
|
-
role.protection
|
|
124
|
-
? 'settings.protected'
|
|
125
|
-
: 'settings.custom',
|
|
126
|
-
)}
|
|
127
|
-
</Badge>
|
|
128
|
-
</Link>
|
|
129
|
-
))}
|
|
130
|
-
</div>
|
|
95
|
+
<RoleList
|
|
96
|
+
ariaLabel={t('settings.roles')}
|
|
97
|
+
roles={rows.map((role) => ({
|
|
98
|
+
key: role.key,
|
|
99
|
+
title: text(role.title ?? role.key),
|
|
100
|
+
to: {
|
|
101
|
+
pathname: `${encodeURIComponent(role.key)}/edit`,
|
|
102
|
+
search: location.search,
|
|
103
|
+
},
|
|
104
|
+
protected: Boolean(role.protection),
|
|
105
|
+
}))}
|
|
106
|
+
labels={{
|
|
107
|
+
name: t('settings.roleName'),
|
|
108
|
+
key: t('settings.key'),
|
|
109
|
+
type: t('settings.roleType'),
|
|
110
|
+
protected: t('settings.protected'),
|
|
111
|
+
custom: t('settings.custom'),
|
|
112
|
+
}}
|
|
113
|
+
/>
|
|
131
114
|
) : (
|
|
132
115
|
<Empty className='min-h-48 border border-dashed'>
|
|
133
116
|
<EmptyMedia variant='icon'>
|
|
@@ -156,7 +139,7 @@ export default function RolesPage(): ReactElement {
|
|
|
156
139
|
</Empty>
|
|
157
140
|
))
|
|
158
141
|
)}
|
|
159
|
-
</
|
|
142
|
+
</PermissionManagementPage>
|
|
160
143
|
<Outlet context={{ reload: request.reload }} />
|
|
161
144
|
</>
|
|
162
145
|
);
|
|
@@ -1,4 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
Settings,
|
|
3
|
+
Users,
|
|
4
|
+
ShieldCheck,
|
|
5
|
+
KeyRound,
|
|
6
|
+
ListFilter,
|
|
7
|
+
} from 'lucide-react';
|
|
2
8
|
import {
|
|
3
9
|
defineAppRoutes,
|
|
4
10
|
type AppClientRouteContribution,
|
|
@@ -41,35 +47,88 @@ const systemSettingsRoutes: AppClientRouteContribution = defineAppRoutes([
|
|
|
41
47
|
],
|
|
42
48
|
},
|
|
43
49
|
{
|
|
44
|
-
name: '
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
resource: { type: 'settings', id: 'authorization.permission-sets' },
|
|
49
|
-
action: 'read',
|
|
50
|
+
name: 'permissionManagement',
|
|
51
|
+
navigation: {
|
|
52
|
+
title: 'settings.permissionManagement',
|
|
53
|
+
icon: ShieldCheck,
|
|
50
54
|
},
|
|
51
|
-
|
|
52
|
-
breadcrumb: { title: 'settings.roles' },
|
|
53
|
-
componentLoader: () => import('./roles.js'),
|
|
55
|
+
breadcrumb: { title: 'settings.permissionManagement' },
|
|
54
56
|
children: [
|
|
55
57
|
{
|
|
56
|
-
name: '
|
|
57
|
-
path: '
|
|
58
|
+
name: 'settingsRoles',
|
|
59
|
+
path: '/roles',
|
|
60
|
+
auth: 'required',
|
|
58
61
|
authz: {
|
|
59
62
|
resource: {
|
|
60
63
|
type: 'settings',
|
|
61
64
|
id: 'authorization.permission-sets',
|
|
62
65
|
},
|
|
63
|
-
action: '
|
|
66
|
+
action: 'read',
|
|
64
67
|
},
|
|
65
|
-
|
|
66
|
-
|
|
68
|
+
navigation: { title: 'settings.roles', icon: KeyRound },
|
|
69
|
+
breadcrumb: { title: 'settings.roles' },
|
|
70
|
+
componentLoader: () => import('./roles.js'),
|
|
71
|
+
children: [
|
|
72
|
+
{
|
|
73
|
+
name: 'settingsRoleCreate',
|
|
74
|
+
path: 'create',
|
|
75
|
+
authz: {
|
|
76
|
+
resource: {
|
|
77
|
+
type: 'settings',
|
|
78
|
+
id: 'authorization.permission-sets',
|
|
79
|
+
},
|
|
80
|
+
action: 'create',
|
|
81
|
+
},
|
|
82
|
+
breadcrumb: { title: 'settings.newRole' },
|
|
83
|
+
componentLoader: () => import('./role-form.js'),
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
name: 'settingsRoleEdit',
|
|
87
|
+
path: ':key/edit',
|
|
88
|
+
breadcrumb: { title: 'settings.editRole' },
|
|
89
|
+
componentLoader: () => import('./role-form.js'),
|
|
90
|
+
},
|
|
91
|
+
],
|
|
67
92
|
},
|
|
68
93
|
{
|
|
69
|
-
name: '
|
|
70
|
-
path: '
|
|
71
|
-
|
|
72
|
-
|
|
94
|
+
name: 'settingsDefaultAccess',
|
|
95
|
+
path: '/default-access',
|
|
96
|
+
auth: 'required',
|
|
97
|
+
authz: {
|
|
98
|
+
resource: {
|
|
99
|
+
type: 'settings',
|
|
100
|
+
id: 'authorization.default-access',
|
|
101
|
+
},
|
|
102
|
+
action: 'read',
|
|
103
|
+
},
|
|
104
|
+
navigation: {
|
|
105
|
+
title: 'settings.defaultAccess.title',
|
|
106
|
+
icon: ListFilter,
|
|
107
|
+
},
|
|
108
|
+
breadcrumb: { title: 'settings.defaultAccess.title' },
|
|
109
|
+
componentLoader: () => import('./default-access.js'),
|
|
110
|
+
children: [
|
|
111
|
+
{
|
|
112
|
+
name: 'settingsDefaultAccessCreate',
|
|
113
|
+
path: 'create',
|
|
114
|
+
authz: {
|
|
115
|
+
resource: {
|
|
116
|
+
type: 'settings',
|
|
117
|
+
id: 'authorization.default-access',
|
|
118
|
+
},
|
|
119
|
+
action: 'create',
|
|
120
|
+
},
|
|
121
|
+
breadcrumb: { title: 'settings.defaultAccess.new' },
|
|
122
|
+
componentLoader: () => import('./default-access-form.js'),
|
|
123
|
+
},
|
|
124
|
+
// Read permission opens the full rule even when the viewer may not update it.
|
|
125
|
+
{
|
|
126
|
+
name: 'settingsDefaultAccessEdit',
|
|
127
|
+
path: ':key/edit',
|
|
128
|
+
breadcrumb: { title: 'settings.defaultAccess.edit' },
|
|
129
|
+
componentLoader: () => import('./default-access-form.js'),
|
|
130
|
+
},
|
|
131
|
+
],
|
|
73
132
|
},
|
|
74
133
|
],
|
|
75
134
|
},
|
|
@@ -78,6 +78,7 @@ export function ConfirmAction({
|
|
|
78
78
|
title,
|
|
79
79
|
description,
|
|
80
80
|
confirmLabel,
|
|
81
|
+
error,
|
|
81
82
|
busy,
|
|
82
83
|
onCancel,
|
|
83
84
|
onConfirm,
|
|
@@ -86,6 +87,7 @@ export function ConfirmAction({
|
|
|
86
87
|
readonly title: string;
|
|
87
88
|
readonly description: ReactNode;
|
|
88
89
|
readonly confirmLabel?: string;
|
|
90
|
+
readonly error?: ReactNode;
|
|
89
91
|
readonly busy: boolean;
|
|
90
92
|
readonly onCancel: () => void;
|
|
91
93
|
readonly onConfirm: () => void;
|
|
@@ -102,6 +104,7 @@ export function ConfirmAction({
|
|
|
102
104
|
<AlertDialogHeader>
|
|
103
105
|
<AlertDialogTitle>{title}</AlertDialogTitle>
|
|
104
106
|
<AlertDialogDescription>{description}</AlertDialogDescription>
|
|
107
|
+
{error}
|
|
105
108
|
</AlertDialogHeader>
|
|
106
109
|
<AlertDialogFooter>
|
|
107
110
|
<AlertDialogCancel disabled={busy}>
|
|
@@ -250,7 +250,7 @@ export default function UsersPage(): ReactElement {
|
|
|
250
250
|
enableHiding: false,
|
|
251
251
|
cell: ({ row }) => (
|
|
252
252
|
<Link
|
|
253
|
-
className='font-medium text-
|
|
253
|
+
className='font-medium text-foreground underline-offset-4 hover:underline'
|
|
254
254
|
to={{
|
|
255
255
|
pathname: row.original.id,
|
|
256
256
|
search: location.search,
|
package/client/plugins.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import foundation from '@nocobase/app-plugin-foundation/client';
|
|
1
2
|
import defaultAccess from '@nocobase/app-plugin-authz-default-access/client';
|
|
2
3
|
import sharingRules from '@nocobase/app-plugin-authz-sharing-rules/client';
|
|
3
4
|
import restrictionRules from '@nocobase/app-plugin-authz-restriction-rules/client';
|
|
@@ -34,6 +35,7 @@ const clientPlugins: AppClientPlugins = defineClientPlugins([
|
|
|
34
35
|
file(),
|
|
35
36
|
scheduler(),
|
|
36
37
|
mail(),
|
|
38
|
+
foundation({ settingsGroup: true }),
|
|
37
39
|
]);
|
|
38
40
|
|
|
39
41
|
export default clientPlugins;
|
|
@@ -11,6 +11,8 @@ import { EMPTY_ARRAY } from '#lib/constants';
|
|
|
11
11
|
import { transformNavigation } from '#lib/navigation-transform';
|
|
12
12
|
|
|
13
13
|
export interface RouteNavigationItem {
|
|
14
|
+
/** Route keys represented by a single sidebar entry whose content uses tabs. */
|
|
15
|
+
readonly activeRouteKeys?: readonly string[];
|
|
14
16
|
readonly section?: boolean;
|
|
15
17
|
readonly route: AppClientRegisteredRoute;
|
|
16
18
|
readonly children: readonly RouteNavigationItem[];
|
|
@@ -45,7 +47,25 @@ export function selectedNavigationId(
|
|
|
45
47
|
denied: ReadonlySet<string> = new Set(),
|
|
46
48
|
): string | undefined {
|
|
47
49
|
const matches = matchRouteTree(routes, pathname);
|
|
48
|
-
const
|
|
50
|
+
const items = buildRouteNavigation(routes, denied);
|
|
51
|
+
const represented = (
|
|
52
|
+
nodes: readonly RouteNavigationItem[],
|
|
53
|
+
): AppClientRegisteredRoute | undefined => {
|
|
54
|
+
for (const item of nodes) {
|
|
55
|
+
if (
|
|
56
|
+
item.activeRouteKeys?.some((key) =>
|
|
57
|
+
matches?.some(({ route }) => routeKey(route) === key),
|
|
58
|
+
)
|
|
59
|
+
)
|
|
60
|
+
return item.route;
|
|
61
|
+
const child = represented(item.children);
|
|
62
|
+
if (child) return child;
|
|
63
|
+
}
|
|
64
|
+
return undefined;
|
|
65
|
+
};
|
|
66
|
+
const active = represented(items);
|
|
67
|
+
if (active) return routeKey(active);
|
|
68
|
+
const pages = navigationPages(items);
|
|
49
69
|
const visible = new Set(pages.map(routeKey));
|
|
50
70
|
const selected =
|
|
51
71
|
matches
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nocobase/app-template-default",
|
|
3
3
|
"displayName": "Default Template",
|
|
4
|
-
"version": "1.0.0-beta.
|
|
4
|
+
"version": "1.0.0-beta.75",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"prettier": "@nocobase/dev-config/prettier",
|
|
7
7
|
"engines": {
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
},
|
|
10
10
|
"nocobase": {
|
|
11
11
|
"templateKind": "app",
|
|
12
|
-
"defaultTemplateVersion": "1.0.0-beta.
|
|
12
|
+
"defaultTemplateVersion": "1.0.0-beta.75"
|
|
13
13
|
},
|
|
14
14
|
"devDependencies": {
|
|
15
15
|
"@ai-sdk/react": "4.0.131",
|
|
@@ -72,10 +72,10 @@
|
|
|
72
72
|
"tar": "^7.5.22",
|
|
73
73
|
"@xyflow/react": "^12.11.5",
|
|
74
74
|
"elkjs": "^0.10.2",
|
|
75
|
-
"@nocobase/app-client": "^4.0.0-beta.
|
|
75
|
+
"@nocobase/app-client": "^4.0.0-beta.1",
|
|
76
76
|
"@nocobase/app-plugin-template-print": "0.0.2-beta.2",
|
|
77
|
-
"@nocobase/app-skills": "0.1.0-beta.
|
|
78
|
-
"@nocobase/app-testing": "0.1.0-beta.
|
|
77
|
+
"@nocobase/app-skills": "0.1.0-beta.43",
|
|
78
|
+
"@nocobase/app-testing": "0.1.0-beta.6",
|
|
79
79
|
"@nocobase/app-websocket": "^0.1.0-beta.1",
|
|
80
80
|
"@nocobase/dev-config": "0.1.0-beta.24",
|
|
81
81
|
"@nocobase/drive": "^0.1.0-beta.7",
|
|
@@ -139,36 +139,38 @@
|
|
|
139
139
|
"@oclif/core": "^4.14.0",
|
|
140
140
|
"better-auth": "1.7.5",
|
|
141
141
|
"hono": "^4.13.2",
|
|
142
|
-
"@nocobase/app-plugin-agents": "^1.0.0-beta.
|
|
142
|
+
"@nocobase/app-plugin-agents": "^1.0.0-beta.17",
|
|
143
143
|
"@nocobase/app-plugin-api-keys": "^1.0.0-beta.18",
|
|
144
|
-
"@nocobase/app-plugin-authentication": "^2.0.0-beta.
|
|
145
|
-
"@nocobase/app-plugin-authorization": "^1.0.0-beta.
|
|
144
|
+
"@nocobase/app-plugin-authentication": "^2.0.0-beta.12",
|
|
145
|
+
"@nocobase/app-plugin-authorization": "^1.0.0-beta.30",
|
|
146
146
|
"@nocobase/app-plugin-database-explorer": "^1.0.0-beta.16",
|
|
147
|
-
"@nocobase/app-plugin-file": "^1.0.0-beta.
|
|
148
|
-
"@nocobase/app-plugin-
|
|
149
|
-
"@nocobase/app-plugin-
|
|
150
|
-
"@nocobase/app-plugin-
|
|
151
|
-
"@nocobase/app-plugin-notification
|
|
152
|
-
"@nocobase/app-plugin-notification-
|
|
153
|
-
"@nocobase/app-plugin-
|
|
154
|
-
"@nocobase/app-plugin-
|
|
155
|
-
"@nocobase/app-
|
|
147
|
+
"@nocobase/app-plugin-file": "^1.0.0-beta.26",
|
|
148
|
+
"@nocobase/app-plugin-foundation": "^0.1.0-beta.0",
|
|
149
|
+
"@nocobase/app-plugin-i18n": "^1.0.0-beta.18",
|
|
150
|
+
"@nocobase/app-plugin-knowledge": "^0.1.0-beta.9",
|
|
151
|
+
"@nocobase/app-plugin-notification": "^1.0.0-beta.29",
|
|
152
|
+
"@nocobase/app-plugin-notification-in-app": "^1.0.0-beta.27",
|
|
153
|
+
"@nocobase/app-plugin-notification-providers": "^0.2.0-beta.14",
|
|
154
|
+
"@nocobase/app-plugin-scheduler": "^1.0.0-beta.19",
|
|
155
|
+
"@nocobase/app-plugin-users": "^2.0.0-beta.8",
|
|
156
|
+
"@nocobase/app-server": "^3.0.0-beta.1",
|
|
156
157
|
"@nocobase/config": "^0.1.0-beta.3",
|
|
157
158
|
"@nocobase/db": "^1.0.0-beta.21",
|
|
158
159
|
"@nocobase/db-sqlite": "^0.1.0-beta.6",
|
|
159
160
|
"@nocobase/service-provider": "^0.0.2-beta.2",
|
|
160
161
|
"@nocobase/snowflake": "^1.0.0-beta.4",
|
|
161
|
-
"@nocobase/app-plugin-authz-default-access": "^1.0.0-beta.
|
|
162
|
-
"@nocobase/app-plugin-authz-sharing-rules": "^1.0.0-beta.
|
|
163
|
-
"@nocobase/app-plugin-authz-restriction-rules": "^1.0.0-beta.
|
|
164
|
-
"@nocobase/authorization": "^1.0.0-beta.
|
|
162
|
+
"@nocobase/app-plugin-authz-default-access": "^1.0.0-beta.15",
|
|
163
|
+
"@nocobase/app-plugin-authz-sharing-rules": "^1.0.0-beta.15",
|
|
164
|
+
"@nocobase/app-plugin-authz-restriction-rules": "^1.0.0-beta.14",
|
|
165
|
+
"@nocobase/authorization": "^1.0.0-beta.15",
|
|
165
166
|
"@nocobase/queue": "^0.1.0-beta.9",
|
|
166
167
|
"@nocobase/jobs": "^0.1.0-beta.3",
|
|
167
168
|
"@nocobase/lifecycle": "^0.1.0-beta.3",
|
|
168
|
-
"@nocobase/i18n": "^2.0.0-beta.
|
|
169
|
+
"@nocobase/i18n": "^2.0.0-beta.1",
|
|
169
170
|
"@nocobase/caching": "^0.1.0-beta.3",
|
|
170
171
|
"@nocobase/repository-input": "^0.1.0-beta.3",
|
|
171
|
-
"@nocobase/app-cli": "^1.0.0-beta.
|
|
172
|
+
"@nocobase/app-cli": "^1.0.0-beta.26",
|
|
173
|
+
"@nocobase/app-plugin-mail": "^1.0.0-beta.16",
|
|
172
174
|
"@nocobase/realtime": "^0.1.0-beta.3"
|
|
173
175
|
},
|
|
174
176
|
"description": "NocoBase 3 application template with the standard product capabilities.",
|
package/server/plugins.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import foundation from '@nocobase/app-plugin-foundation/server';
|
|
1
2
|
import defaultAccess from '@nocobase/app-plugin-authz-default-access/server';
|
|
2
3
|
import sharingRules from '@nocobase/app-plugin-authz-sharing-rules/server';
|
|
3
4
|
import restrictionRules from '@nocobase/app-plugin-authz-restriction-rules/server';
|
|
@@ -34,6 +35,7 @@ const serverPlugins: AppServerPlugins = defineServerPlugins([
|
|
|
34
35
|
file,
|
|
35
36
|
scheduler,
|
|
36
37
|
mail,
|
|
38
|
+
foundation,
|
|
37
39
|
]);
|
|
38
40
|
|
|
39
41
|
export default serverPlugins;
|