adminizer 5.0.0-build.8 → 5.1.0-build.24
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/assets/abnfDiagram-VCTEODGH-DFY3Pztx.js +1 -0
- package/assets/add-31tS-g4V.js +1 -0
- package/assets/add-group-Cf3zT7WE.js +1 -0
- package/assets/add-user-C62wOna-.js +1 -0
- package/assets/ai-assistant/agent.es.js +28464 -0
- package/assets/app-DPmI-MvN.css +1 -0
- package/assets/app-vdHbjOQX.js +138 -0
- package/assets/arc-DP4o1zz3.js +1 -0
- package/assets/architectureDiagram-5GKGNRK7-BjXW5Zu0.js +36 -0
- package/assets/asmcrypto-DZeQH0LC.js +1 -0
- package/assets/blockDiagram-I7D4REHJ-BUPnDwN0.js +129 -0
- package/assets/c4Diagram-7LVT6UL2-Cmb_dAhd.js +38 -0
- package/assets/{catalog-BEvJZYJP.js → catalog-C-y5rMaG.js} +3 -3
- package/assets/channel-CkJRUsq_.js +1 -0
- package/assets/chunk-2Q5K7J3B-CmS-dWwQ.js +1 -0
- package/assets/chunk-5VM5RSS4-Cqs2Ow64.js +15 -0
- package/assets/chunk-F27PBJKO-BoMCpJA1.js +1 -0
- package/assets/chunk-IMKFNOWR-DlDcPk1x.js +231 -0
- package/assets/chunk-JWPE2WC7-DzL_SU8s.js +1 -0
- package/assets/chunk-POPQ4Y6H-Cwq2-Vb8.js +1 -0
- package/assets/chunk-SVP7TREG-BfRHY5FU.js +88 -0
- package/assets/chunk-TICWLB2K-CRP7rHkW.js +206 -0
- package/assets/chunk-XXDRQBXY-Bg2jg-98.js +1 -0
- package/assets/classDiagram-ZZMXUADV-D4EF3HGj.js +1 -0
- package/assets/classDiagram-v2-VYDZK3BY-D4EF3HGj.js +1 -0
- package/assets/controls/ckeditor.es.js +9382 -9320
- package/assets/controls/handsontable.es.js +11971 -11938
- package/assets/controls/jsoneditor.es.js +10442 -10233
- package/assets/controls/toast-ui.es.js +1308 -1279
- package/assets/cose-bilkent-JH36ORCC-CCJ0SGyO.js +1 -0
- package/assets/cynefin-OW5HDTMX-B2Jx5fw3.js +166 -0
- package/assets/cynefinDiagram-5FMLGOSQ-DuK0Lb62.js +62 -0
- package/assets/cytoscape.esm-DzSz-X2X.js +321 -0
- package/assets/dagre-GXQ25YYZ-DnOYexET.js +4 -0
- package/assets/dashboard-X8k4X6Sw.js +3 -0
- package/assets/debounce-B3mXI_sx.js +1 -0
- package/assets/defaultLocale-DX6XiGOO.js +1 -0
- package/assets/diagram-S7CK7UJ4-DDgPBHsK.js +30 -0
- package/assets/diagram-UQ7AKVKN-qlL0GZs8.js +41 -0
- package/assets/diagram-VSXAHHWV-CQbiU1_c.js +3 -0
- package/assets/diagram-VX7I27RA-DFDI9_au.js +24 -0
- package/assets/diagram-Z3DM3KII-B5C9dtmJ.js +24 -0
- package/assets/docs-BiZOD7PP.js +1 -0
- package/assets/ebnfDiagram-PWID7BFC-CLMUsXEI.js +1 -0
- package/assets/erDiagram-RLTQ6QDP-ax9Xol5-.js +99 -0
- package/assets/flowDiagram-HODETNUW-CvaH7l3S.js +168 -0
- package/assets/ganttDiagram-EL5Y4UJY-Cga5U19j.js +292 -0
- package/assets/gitGraphDiagram-WWUBYQGX-B6o1T3-d.js +106 -0
- package/assets/history-CVBJUNSQ.js +1 -0
- package/assets/infoDiagram-27XIBGKW-BpWxgBCE.js +2 -0
- package/assets/init-Gi6I4Gst.js +1 -0
- package/assets/init-user-xSvnFTF0.js +1 -0
- package/assets/isObject-DL-BuaBl.js +1 -0
- package/assets/ishikawaDiagram-5VMMS53U-zE83db4H.js +70 -0
- package/assets/journeyDiagram-3NMN7TZE-DZNVFqrX.js +139 -0
- package/assets/kanban-definition-UXKFOSKX-CqxNgk27.js +89 -0
- package/assets/katex-HP8lGamR.js +257 -0
- package/assets/layout-CN3kt_jt.js +1 -0
- package/assets/linear-nvkaQ6BA.js +1 -0
- package/assets/{list-DhK0McVn.js → list-CrIU2eZz.js} +2 -2
- package/assets/login-CX9xVjCn.js +1 -0
- package/assets/manifest.json +834 -58
- package/assets/media-manager-BfYftLIH.js +6 -0
- package/assets/mermaid.core-C0V1NaVJ.js +310 -0
- package/assets/mindmap-definition-YA3MSWOX-Bh7_d9f1.js +96 -0
- package/assets/module-DPEvnad3.js +1 -0
- package/assets/notification-Dqpt5AIZ.js +20 -0
- package/assets/ordinal-Cboi1Yqb.js +1 -0
- package/assets/pegDiagram-XKGWAZYB-DMnjm6Z1.js +1 -0
- package/assets/pieDiagram-E7YTZNPT-D-RWCgYb.js +39 -0
- package/assets/quadrantDiagram-AXDQQJYC-BNBGP7RM.js +7 -0
- package/assets/railroadDiagram-O6MQD6OU-BIjVPT01.js +1 -0
- package/assets/register-CF4KQ97e.js +1 -0
- package/assets/requirementDiagram-BXWQKSXE-VPrtGdjM.js +84 -0
- package/assets/ru-CFJ4fysR.js +1 -0
- package/assets/sankeyDiagram-P5KCCOFB-ct9mLF3U.js +40 -0
- package/assets/sequenceDiagram-WJ2MYXX4-TC06Mbmw.js +162 -0
- package/assets/sizeCapture-INFHLROL-BMMwriCf.js +1 -0
- package/assets/stateDiagram-D77RDMKH-DtwYRPCX.js +1 -0
- package/assets/stateDiagram-v2-MP3YSRHH-C1yB0O5U.js +1 -0
- package/assets/swimlanes-42K2YHIH-DE3hRbbr.js +1 -0
- package/assets/swimlanesDiagram-VR7AAH4N-Ce4l1sQD.js +8 -0
- package/assets/timeline-definition-24CTP7MA-N7s_hfjj.js +120 -0
- package/assets/toNumber-DZb-r9sy.js +1 -0
- package/assets/use-appearance-DYTIKpT2.js +1 -0
- package/assets/user-filters-list-fR0YNJ3l.js +1 -0
- package/assets/vennDiagram-4TSXK5OY-Dj5bFQkR.js +34 -0
- package/assets/wardleyDiagram-VM6X3IG4-83ax25Z6.js +78 -0
- package/assets/welcome-v11MTsRK.js +1 -0
- package/assets/with-app-layout-CH6RIib1.js +31 -0
- package/assets/xychartDiagram-S5SC5T6Z-CW9Br5Xp.js +7 -0
- package/controllers/access-rights/permissionOptions.d.ts +2 -0
- package/controllers/access-rights/permissionOptions.js +23 -0
- package/controllers/add.js +2 -2
- package/controllers/addGroup.js +15 -6
- package/controllers/ai/AiAgentController.d.ts +66 -0
- package/controllers/ai/AiAgentController.js +435 -0
- package/controllers/ai/AiAssistantController.d.ts +0 -4
- package/controllers/ai/AiAssistantController.js +4 -78
- package/controllers/catalog/FrontendCatalogAdapter.js +7 -8
- package/controllers/docs/index.d.ts +22 -0
- package/controllers/docs/index.js +126 -0
- package/controllers/edit.js +2 -2
- package/controllers/editGroup.js +15 -6
- package/controllers/filter-fields/savedFilters.js +1 -1
- package/controllers/history-actions/HistoryController.js +7 -7
- package/controllers/inlineUpdate.js +10 -3
- package/controllers/list.js +1 -1
- package/controllers/login.js +1 -1
- package/controllers/notifications/NotificationController.js +14 -8
- package/controllers/view.js +3 -3
- package/controllers/widgets/filterInfo.js +1 -1
- package/helpers/accessRightsHelper.d.ts +30 -3
- package/helpers/accessRightsHelper.js +140 -12
- package/helpers/assetVersionHelper.d.ts +14 -0
- package/helpers/assetVersionHelper.js +42 -0
- package/helpers/configHelper.js +19 -18
- package/helpers/controllerHelper.d.ts +1 -0
- package/helpers/controllerHelper.js +25 -15
- package/helpers/fieldsHelper.d.ts +2 -1
- package/helpers/fieldsHelper.js +11 -5
- package/helpers/inertiaActionsHelper.d.ts +1 -1
- package/helpers/inertiaActionsHelper.js +4 -5
- package/helpers/inertiaAddHelper.d.ts +1 -1
- package/helpers/inertiaAddHelper.js +7 -6
- package/helpers/inertiaGroupHelper.js +10 -2
- package/helpers/inertiaListHelper.d.ts +1 -1
- package/helpers/inertiaListHelper.js +7 -8
- package/helpers/inertiaMenuHelper.d.ts +7 -2
- package/helpers/inertiaMenuHelper.js +12 -27
- package/helpers/menuHelper.d.ts +11 -1
- package/helpers/menuHelper.js +12 -0
- package/helpers/modelResourceHelper.d.ts +9 -0
- package/helpers/modelResourceHelper.js +43 -0
- package/helpers/navigationAccessHelper.d.ts +13 -0
- package/helpers/navigationAccessHelper.js +45 -0
- package/index.d.ts +11 -0
- package/index.js +11 -0
- package/interfaces/adminpanelConfig.d.ts +160 -2
- package/interfaces/queryCriteria.d.ts +13 -0
- package/interfaces/types.d.ts +169 -0
- package/lib/Adminizer.d.ts +8 -0
- package/lib/Adminizer.js +29 -2
- package/lib/DataAccessor.d.ts +100 -3
- package/lib/DataAccessor.js +454 -245
- package/lib/access-graph/AccessGraphResolver.d.ts +136 -0
- package/lib/access-graph/AccessGraphResolver.js +605 -0
- package/lib/access-graph/RecordAccessCache.d.ts +23 -0
- package/lib/access-graph/RecordAccessCache.js +30 -0
- package/lib/access-graph/RecordAccessResolver.d.ts +83 -0
- package/lib/access-graph/RecordAccessResolver.js +295 -0
- package/lib/access-graph/shared.d.ts +60 -0
- package/lib/access-graph/shared.js +121 -0
- package/lib/admin-links/AdminLinkHandler.d.ts +72 -0
- package/lib/admin-links/AdminLinkHandler.js +183 -0
- package/lib/ai-assistant/AbstractAiConversationHistoryService.d.ts +39 -0
- package/lib/ai-assistant/AbstractAiConversationHistoryService.js +98 -0
- package/lib/ai-assistant/AbstractAiModelService.d.ts +139 -2
- package/lib/ai-assistant/AbstractAiModelService.js +154 -1
- package/lib/ai-assistant/AiAgentRunManager.d.ts +35 -0
- package/lib/ai-assistant/AiAgentRunManager.js +109 -0
- package/lib/ai-assistant/AiAssistantAgentSkillHandler.d.ts +61 -0
- package/lib/ai-assistant/AiAssistantAgentSkillHandler.js +90 -0
- package/lib/ai-assistant/AiAssistantHandler.d.ts +1 -0
- package/lib/ai-assistant/AiAssistantHandler.js +4 -0
- package/lib/ai-assistant/AiAssistantUiMethodHandler.d.ts +60 -0
- package/lib/ai-assistant/AiAssistantUiMethodHandler.js +144 -0
- package/lib/ai-assistant/builtinAgentSkills.d.ts +9 -0
- package/lib/ai-assistant/builtinAgentSkills.js +259 -0
- package/lib/ai-assistant/jsonSafe.d.ts +13 -0
- package/lib/ai-assistant/jsonSafe.js +81 -0
- package/lib/app-manager/AdminizerApp.d.ts +31 -2
- package/lib/app-manager/AppManager.js +43 -42
- package/lib/app-manager/ConfigLayerHandler.js +4 -0
- package/lib/docs/AbstractDocumentation.d.ts +100 -0
- package/lib/docs/AbstractDocumentation.js +108 -0
- package/lib/docs/DocumentationHandler.d.ts +100 -0
- package/lib/docs/DocumentationHandler.js +198 -0
- package/lib/docs/FileDocumentation.d.ts +47 -0
- package/lib/docs/FileDocumentation.js +189 -0
- package/lib/docs/docsAgentSkills.d.ts +10 -0
- package/lib/docs/docsAgentSkills.js +93 -0
- package/lib/filters/FilterService.js +4 -3
- package/lib/history-actions/AbstractHistoryAdapter.d.ts +26 -1
- package/lib/history-actions/AbstractHistoryAdapter.js +155 -25
- package/lib/media-manager/helpers/MediaManagerHelper.js +9 -7
- package/lib/model/AbstractModel.d.ts +48 -0
- package/lib/model/AbstractModel.js +14 -4
- package/lib/model/ModelHandler.d.ts +50 -2
- package/lib/model/ModelHandler.js +117 -8
- package/lib/model/adapter/sequelize.d.ts +43 -3
- package/lib/model/adapter/sequelize.js +317 -138
- package/lib/model/adapter/typeorm.d.ts +16 -0
- package/lib/model/adapter/typeorm.js +136 -9
- package/lib/notifications/GeneralNotificationService.js +6 -5
- package/lib/notifications/SystemNotificationService.js +1 -1
- package/lib/ui-i18n/uiTranslationKeys.d.ts +2 -1
- package/lib/ui-i18n/uiTranslationKeys.js +42 -1
- package/lib/widgets/widgetHandler.js +10 -6
- package/models/Group.d.ts +2 -1
- package/package.json +35 -23
- package/policies/authPolicies.js +6 -6
- package/policies/permissionResolvers.d.ts +1 -0
- package/policies/permissionResolvers.js +3 -0
- package/system/Router.js +21 -3
- package/system/bindAccessRights.js +13 -3
- package/system/bindDocs.d.ts +13 -0
- package/system/bindDocs.js +77 -0
- package/system/bindInertia.js +30 -7
- package/system/buildInternalModelAccess.d.ts +8 -0
- package/system/buildInternalModelAccess.js +36 -4
- package/system/defaults.js +7 -1
- package/system/validateSystemModels.js +29 -9
- package/assets/add-DED_wpga.js +0 -1
- package/assets/add-group-CL80RdYb.js +0 -1
- package/assets/add-user-BRmwvQB8.js +0 -1
- package/assets/app-DNXiApCk.css +0 -1
- package/assets/app-layout-86yxiZOy.js +0 -1
- package/assets/app.js +0 -138
- package/assets/dashboard-ZP6K2s_8.js +0 -3
- package/assets/debounce-BMmXVQ06.js +0 -1
- package/assets/history-M61Bcv02.js +0 -1
- package/assets/init-user-8aUohVDq.js +0 -1
- package/assets/login-CO4laf6m.js +0 -1
- package/assets/media-manager-BDbpSSjH.js +0 -6
- package/assets/module-DfBneaUl.js +0 -1
- package/assets/notification-CVnQf3ef.js +0 -20
- package/assets/register-DBYIMXGQ.js +0 -1
- package/assets/ru-rYKdQbWF.js +0 -1
- package/assets/use-appearance-_EbbjHTh.js +0 -1
- package/assets/user-filters-list-DXhGLFTn.js +0 -1
- package/assets/welcome-CLxvXkcg.js +0 -1
package/index.d.ts
CHANGED
|
@@ -27,6 +27,9 @@ export * from "./lib/media-manager/AbstractMediaManager.js";
|
|
|
27
27
|
export * from "./lib/controls/Control.js";
|
|
28
28
|
export * from "./lib/controls/ControlsHandler.js";
|
|
29
29
|
export * from "./lib/Adminizer.js";
|
|
30
|
+
export * from "./lib/docs/AbstractDocumentation.js";
|
|
31
|
+
export * from "./lib/docs/DocumentationHandler.js";
|
|
32
|
+
export * from "./lib/docs/FileDocumentation.js";
|
|
30
33
|
export * from "./lib/I18n.js";
|
|
31
34
|
export * from "./models/Group.js";
|
|
32
35
|
export * from "./models/User.js";
|
|
@@ -43,7 +46,15 @@ export * from "./lib/helper/jwt.js";
|
|
|
43
46
|
export * from "./lib/notifications/AbstractNotificationService.js";
|
|
44
47
|
export * from "./lib/POWCaptcha.js";
|
|
45
48
|
export * from "./lib/ai-assistant/AbstractAiModelService.js";
|
|
49
|
+
export * from "./lib/ai-assistant/AbstractAiConversationHistoryService.js";
|
|
46
50
|
export * from "./lib/ai-assistant/AiAssistantHandler.js";
|
|
51
|
+
export * from "./lib/ai-assistant/AiAgentRunManager.js";
|
|
52
|
+
export * from "./lib/ai-assistant/jsonSafe.js";
|
|
53
|
+
export * from "./lib/ai-assistant/AiAssistantUiMethodHandler.js";
|
|
54
|
+
export * from "./lib/ai-assistant/AiAssistantAgentSkillHandler.js";
|
|
55
|
+
export * from "./lib/admin-links/AdminLinkHandler.js";
|
|
56
|
+
export * from "./helpers/modelResourceHelper.js";
|
|
57
|
+
export * from "./helpers/navigationAccessHelper.js";
|
|
47
58
|
export * from "./lib/DataAccessor.js";
|
|
48
59
|
export * from "./lib/history-actions/AbstractHistoryAdapter.js";
|
|
49
60
|
export * from "./lib/filters/CustomFilterHandler.js";
|
package/index.js
CHANGED
|
@@ -27,6 +27,9 @@ export * from "./lib/media-manager/AbstractMediaManager.js";
|
|
|
27
27
|
export * from "./lib/controls/Control.js";
|
|
28
28
|
export * from "./lib/controls/ControlsHandler.js";
|
|
29
29
|
export * from "./lib/Adminizer.js";
|
|
30
|
+
export * from "./lib/docs/AbstractDocumentation.js";
|
|
31
|
+
export * from "./lib/docs/DocumentationHandler.js";
|
|
32
|
+
export * from "./lib/docs/FileDocumentation.js";
|
|
30
33
|
export * from "./lib/I18n.js";
|
|
31
34
|
export * from "./models/Group.js";
|
|
32
35
|
export * from "./models/User.js";
|
|
@@ -43,7 +46,15 @@ export * from "./lib/helper/jwt.js";
|
|
|
43
46
|
export * from "./lib/notifications/AbstractNotificationService.js";
|
|
44
47
|
export * from "./lib/POWCaptcha.js";
|
|
45
48
|
export * from "./lib/ai-assistant/AbstractAiModelService.js";
|
|
49
|
+
export * from "./lib/ai-assistant/AbstractAiConversationHistoryService.js";
|
|
46
50
|
export * from "./lib/ai-assistant/AiAssistantHandler.js";
|
|
51
|
+
export * from "./lib/ai-assistant/AiAgentRunManager.js";
|
|
52
|
+
export * from "./lib/ai-assistant/jsonSafe.js";
|
|
53
|
+
export * from "./lib/ai-assistant/AiAssistantUiMethodHandler.js";
|
|
54
|
+
export * from "./lib/ai-assistant/AiAssistantAgentSkillHandler.js";
|
|
55
|
+
export * from "./lib/admin-links/AdminLinkHandler.js";
|
|
56
|
+
export * from "./helpers/modelResourceHelper.js";
|
|
57
|
+
export * from "./helpers/navigationAccessHelper.js";
|
|
47
58
|
export * from "./lib/DataAccessor.js";
|
|
48
59
|
export * from "./lib/history-actions/AbstractHistoryAdapter.js";
|
|
49
60
|
export * from "./lib/filters/CustomFilterHandler.js";
|
|
@@ -75,6 +75,26 @@ export interface AdminpanelConfig {
|
|
|
75
75
|
models: {
|
|
76
76
|
[key: string]: ModelConfig;
|
|
77
77
|
};
|
|
78
|
+
/**
|
|
79
|
+
* Relationship-based record access (ReBAC): each key declares one access graph —
|
|
80
|
+
* models whose records inherit visibility from a root model down parent edges.
|
|
81
|
+
* Membership is granted once, on root records (same `through` form as the membership
|
|
82
|
+
* variant of `userAccessRelation`), and every model of the graph is filtered by it
|
|
83
|
+
* transitively. The graph wins over a covered model's own `userAccessRelation`: once a
|
|
84
|
+
* graph covers a model, that declaration stops applying. Declaring both is a configuration
|
|
85
|
+
* error and is reported as one when the graph compiles.
|
|
86
|
+
* Global CRUD tokens remain the upper bound: the graph narrows visibility, it never
|
|
87
|
+
* grants access the token gates denied.
|
|
88
|
+
*
|
|
89
|
+
* EXPERIMENTAL: the configuration format and access semantics may change in a minor release.
|
|
90
|
+
* Declaring this section makes Adminizer log a warning at boot naming the graphs in use.
|
|
91
|
+
*
|
|
92
|
+
* @beta
|
|
93
|
+
*
|
|
94
|
+
*/
|
|
95
|
+
accessGraph?: {
|
|
96
|
+
[graphKey: string]: AccessGraphConfig;
|
|
97
|
+
};
|
|
78
98
|
/**
|
|
79
99
|
* For custom adminpanel sections, displays inside header
|
|
80
100
|
* */
|
|
@@ -107,6 +127,14 @@ export interface AdminpanelConfig {
|
|
|
107
127
|
sectionHandlers?: {
|
|
108
128
|
[section: string]: (user: User, links: HrefConfig[]) => HrefConfig[];
|
|
109
129
|
};
|
|
130
|
+
/**
|
|
131
|
+
* Presentation metadata for navbar sections, keyed by section name.
|
|
132
|
+
* The sections themselves are declared by the `section` field of individual
|
|
133
|
+
* links; this map only controls how a section header is drawn.
|
|
134
|
+
*/
|
|
135
|
+
sections?: {
|
|
136
|
+
[section: string]: NavbarSectionConfig;
|
|
137
|
+
};
|
|
110
138
|
};
|
|
111
139
|
/**
|
|
112
140
|
* Policies that will be executed before going to every page
|
|
@@ -223,6 +251,14 @@ export interface AdminpanelConfig {
|
|
|
223
251
|
defaultModel?: string;
|
|
224
252
|
models?: string[];
|
|
225
253
|
};
|
|
254
|
+
/**
|
|
255
|
+
* Knowledge base (built-in documentation). The implementation is
|
|
256
|
+
* registered separately: `adminizer.documentationHandler.register(service)`.
|
|
257
|
+
*/
|
|
258
|
+
documentation?: {
|
|
259
|
+
/** Master switch of the subsystem; nothing is brought up unless `true` */
|
|
260
|
+
enabled?: boolean;
|
|
261
|
+
};
|
|
226
262
|
cors?: {
|
|
227
263
|
enabled: boolean;
|
|
228
264
|
origin: string[] | string;
|
|
@@ -299,9 +335,14 @@ export interface ModelConfig {
|
|
|
299
335
|
adapter?: string;
|
|
300
336
|
title: string;
|
|
301
337
|
/**
|
|
302
|
-
*
|
|
338
|
+
* Physical host ORM model name.
|
|
303
339
|
* */
|
|
304
340
|
model: string;
|
|
341
|
+
/**
|
|
342
|
+
* Required only when two or more Adminizer resources use the same host model.
|
|
343
|
+
* The primary resource is selected for associations that reference the host model.
|
|
344
|
+
*/
|
|
345
|
+
primary?: boolean;
|
|
305
346
|
/**
|
|
306
347
|
* Optional display name for history. Should be a attribute of the model, or a function.
|
|
307
348
|
*/
|
|
@@ -392,16 +433,117 @@ export interface ModelConfig {
|
|
|
392
433
|
* */
|
|
393
434
|
identifierField?: string;
|
|
394
435
|
/** In this field we can set model field, for which we want to check user access right.
|
|
395
|
-
* May be association or association-many to User or Group
|
|
436
|
+
* May be association or association-many to User or Group
|
|
437
|
+
*
|
|
438
|
+
* @deprecated Declare record access with {@link AdminpanelConfig.accessGraph} instead.
|
|
439
|
+
* The membership form (`{field, through, via, group}`) is a single-edge access graph
|
|
440
|
+
* written in a second syntax — same `membership` declaration, `field` becomes the
|
|
441
|
+
* `include` edge's `parent`. The string and `{field, via}` forms have no graph
|
|
442
|
+
* equivalent yet (the graph seeds root ids from membership rows, not from an owner
|
|
443
|
+
* foreign key), so this option is removed in stages rather than at once.
|
|
444
|
+
* Note that this option is already inert wherever an `accessGraph` covers the model:
|
|
445
|
+
* the graph wins and the declaration below is ignored.
|
|
446
|
+
*
|
|
447
|
+
* TODO: removal plan, its prerequisites and the migration recipe live in
|
|
448
|
+
* `.ai-notes/todo/user-access-relation-removal.md`; the reasoning behind the
|
|
449
|
+
* deprecation — including the one behaviour the graph does not reproduce (its root
|
|
450
|
+
* model becomes record-restricted too) — in `.ai-notes/user-access-relation-deprecation.md`.
|
|
451
|
+
*/
|
|
396
452
|
userAccessRelation?: {
|
|
397
453
|
field: string;
|
|
398
454
|
via?: string;
|
|
455
|
+
/** Membership form: a join model holding exactly one relation to the model `field` points at,
|
|
456
|
+
* a `via` relation to User and, optionally, a `group` relation to Group. Records are then
|
|
457
|
+
* filtered to the targets the user has a membership row for. */
|
|
458
|
+
through?: string;
|
|
459
|
+
/** Field in `through` that associates with Group. When set, a membership only counts for the
|
|
460
|
+
* actions whose CRUD token (`<verb>-<model>-model`) that group carries, so the same user may
|
|
461
|
+
* hold different rights in different targets. Global tokens remain the upper bound: this
|
|
462
|
+
* narrows rows, it never grants access the token gates denied. */
|
|
463
|
+
group?: string;
|
|
399
464
|
} | string;
|
|
400
465
|
userAccessRelationCallback?: (userWithGroups: UserWithGroups, record: any) => boolean;
|
|
401
466
|
}
|
|
402
467
|
type UserWithGroups = User & {
|
|
403
468
|
groups: Group[];
|
|
404
469
|
};
|
|
470
|
+
/** CRUD verb of the action being performed, as used in `<verb>-<model>-model` tokens. */
|
|
471
|
+
export type AccessGraphActionVerb = "create" | "read" | "update" | "delete";
|
|
472
|
+
/** Ids of the root records the user may see, `"all"` for an explicit bypass, or
|
|
473
|
+
* `undefined` to fall back to the declared `membership`. */
|
|
474
|
+
export type AccessGraphRootIds = unknown[] | "all" | undefined;
|
|
475
|
+
/**
|
|
476
|
+
* One access graph: a root model carrying memberships plus the models that inherit
|
|
477
|
+
* its visibility down explicit parent edges.
|
|
478
|
+
*/
|
|
479
|
+
export interface AccessGraphConfig {
|
|
480
|
+
/** Root model of the graph; memberships are granted on its records. */
|
|
481
|
+
root: string;
|
|
482
|
+
/**
|
|
483
|
+
* Membership declaration at the root: `through` is a join model holding exactly one
|
|
484
|
+
* relation to the root model, a `via` relation to User and, optionally, a `group`
|
|
485
|
+
* relation to Group. With `group` declared, a membership only counts for the actions
|
|
486
|
+
* whose CRUD token (`<verb>-<model>-model`, checked against the model being accessed)
|
|
487
|
+
* that group carries.
|
|
488
|
+
*/
|
|
489
|
+
membership?: {
|
|
490
|
+
through: string;
|
|
491
|
+
via: string;
|
|
492
|
+
group?: string;
|
|
493
|
+
};
|
|
494
|
+
/**
|
|
495
|
+
* Models covered by the graph. Each entry names the association alias the model uses
|
|
496
|
+
* to look at its parent in the graph; the parent model is derived from that alias and
|
|
497
|
+
* must itself belong to the graph (the root or another `include` entry). Exactly one
|
|
498
|
+
* edge per model — the parent is never guessed from foreign keys.
|
|
499
|
+
*/
|
|
500
|
+
include?: {
|
|
501
|
+
[modelName: string]: {
|
|
502
|
+
/** Association alias on this model pointing at its parent in the graph. */
|
|
503
|
+
parent: string;
|
|
504
|
+
};
|
|
505
|
+
};
|
|
506
|
+
/**
|
|
507
|
+
* Stage 2: denormalized root-id columns. For a listed model the read filter collapses
|
|
508
|
+
* to one step — `{<column>: {in: graphRootIds}}` — instead of walking the parent chain.
|
|
509
|
+
* The column is maintained by the application; Adminizer only filters by it. The model
|
|
510
|
+
* still declares its `include` edge — writes keep validating the chosen parent.
|
|
511
|
+
*/
|
|
512
|
+
graphRootField?: {
|
|
513
|
+
[modelName: string]: string;
|
|
514
|
+
};
|
|
515
|
+
/**
|
|
516
|
+
* Stage 3: compile the read filter into one nested-subquery SQL emitted by the adapter
|
|
517
|
+
* instead of materializing intermediate id lists in the application. Applies when every
|
|
518
|
+
* model on the path (and the membership model) lives on the same adapter connection;
|
|
519
|
+
* otherwise the resolver falls back to per-level materialization automatically. The SQL
|
|
520
|
+
* is generated from this declaration — no hand-written queries.
|
|
521
|
+
*
|
|
522
|
+
* Why it exists: the default walk costs one query per level of the chain, and the last of
|
|
523
|
+
* them carries every intermediate id the user can reach as a literal `IN (...)` list. The
|
|
524
|
+
* price of the filter therefore grows with the size of the user's data, not with the size
|
|
525
|
+
* of the page — a member of 500 projects ships ~25 000 task ids to render 25 rows, while
|
|
526
|
+
* the pushed-down form emits one statement of constant size whatever the account holds.
|
|
527
|
+
* The accounts it slows down first are the biggest ones.
|
|
528
|
+
*
|
|
529
|
+
* Setting it is a permission, not a guarantee: a chain that cannot be compiled goes back to
|
|
530
|
+
* materialization, and the write path never uses pushdown at all. The fallback is invisible in
|
|
531
|
+
* the result, so it is logged — one warning per model, naming the graph and the reason. Silence
|
|
532
|
+
* means the chain compiled.
|
|
533
|
+
*/
|
|
534
|
+
pushdown?: boolean;
|
|
535
|
+
/**
|
|
536
|
+
* Token id that lets its holders see the whole graph unfiltered. Matched against the
|
|
537
|
+
* token grants of the user's global groups; it does not need to be a registered token.
|
|
538
|
+
*/
|
|
539
|
+
bypassToken?: string;
|
|
540
|
+
/**
|
|
541
|
+
* Replaces the membership source at the root without touching the graph below it.
|
|
542
|
+
* Returning `undefined` falls back to the declared `membership`; `"all"` is the
|
|
543
|
+
* explicit bypass. The result is still bounded by global tokens.
|
|
544
|
+
*/
|
|
545
|
+
resolveGraphRootIds?: (user: User, actionVerb: AccessGraphActionVerb) => Promise<AccessGraphRootIds> | AccessGraphRootIds;
|
|
546
|
+
}
|
|
405
547
|
export type ModelFieldConfig = (BaseFieldConfig | TuiEditorFieldConfig) & {
|
|
406
548
|
groupsAccessRights?: string[];
|
|
407
549
|
};
|
|
@@ -583,6 +725,22 @@ export interface HrefConfig {
|
|
|
583
725
|
*/
|
|
584
726
|
section?: string;
|
|
585
727
|
}
|
|
728
|
+
/**
|
|
729
|
+
* Presentation of a single navbar section header.
|
|
730
|
+
*/
|
|
731
|
+
export interface NavbarSectionConfig {
|
|
732
|
+
/**
|
|
733
|
+
* Icon of the section header. Also used as the section's trigger in the
|
|
734
|
+
* collapsed (icon-only) sidebar.
|
|
735
|
+
*/
|
|
736
|
+
icon?: MaterialIcon;
|
|
737
|
+
/**
|
|
738
|
+
* Explicit position of the section. Sections carrying an `order` are sorted
|
|
739
|
+
* ascending and placed before the ones without it, which keep the default
|
|
740
|
+
* ordering (`Platform` first, `System` last, the rest alphabetically).
|
|
741
|
+
*/
|
|
742
|
+
order?: number;
|
|
743
|
+
}
|
|
586
744
|
export interface MediaManagerConfig {
|
|
587
745
|
fileStoragePath: string;
|
|
588
746
|
allowMIME?: string[];
|
|
@@ -47,6 +47,19 @@ export interface QueryCriteria<TModel = any> {
|
|
|
47
47
|
where?: CriteriaWhere<TModel>;
|
|
48
48
|
select?: CriteriaSelect;
|
|
49
49
|
populate?: CriteriaPopulate<TModel>;
|
|
50
|
+
/**
|
|
51
|
+
* Record-access confinement of single populated associations, keyed by association
|
|
52
|
+
* name and ANDed into the populate JOIN's ON clause: a populated record failing the
|
|
53
|
+
* condition arrives as its bare foreign-key value instead of an object, while the
|
|
54
|
+
* owning row itself stays in the result — unlike `populate.<field>.where`, which
|
|
55
|
+
* confines the owning rows.
|
|
56
|
+
*
|
|
57
|
+
* Set exclusively by `DataAccessor.pushDownPopulateAccess` for the associations the
|
|
58
|
+
* adapter declared pushdown-capable (`AbstractModel.canPushdownPopulateAccess`);
|
|
59
|
+
* `sanitizeUserRelationAccess` discards an incoming value, so hand-built criteria
|
|
60
|
+
* cannot suppress the association verification that trusts this key.
|
|
61
|
+
*/
|
|
62
|
+
populateOn?: Record<string, CriteriaWhere>;
|
|
50
63
|
sort?: CriteriaSort;
|
|
51
64
|
limit?: number;
|
|
52
65
|
skip?: number;
|
package/interfaces/types.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { AbstractModel } from "../lib/model/AbstractModel.js";
|
|
2
2
|
import { ModelConfig } from "./adminpanelConfig.js";
|
|
3
|
+
import type { User } from "../models/User.js";
|
|
3
4
|
export interface ModelResource {
|
|
4
5
|
name: string;
|
|
5
6
|
config?: ModelConfig;
|
|
@@ -11,7 +12,24 @@ export interface AccessRightsToken {
|
|
|
11
12
|
description: string;
|
|
12
13
|
department: string;
|
|
13
14
|
id: string;
|
|
15
|
+
getOptions?: (user: User) => Promise<PermissionOption[]>;
|
|
16
|
+
check?: (user: User, context?: PermissionContext) => Promise<boolean>;
|
|
14
17
|
}
|
|
18
|
+
export interface PermissionOption {
|
|
19
|
+
id: string;
|
|
20
|
+
name: string;
|
|
21
|
+
description?: string;
|
|
22
|
+
}
|
|
23
|
+
export interface PermissionContext {
|
|
24
|
+
rights?: string[];
|
|
25
|
+
[key: string]: unknown;
|
|
26
|
+
}
|
|
27
|
+
/** Serialized as a JSON string in Group.tokens for a contextual token. */
|
|
28
|
+
export interface GroupPermissionGrant {
|
|
29
|
+
tokenId: string;
|
|
30
|
+
rights: string[];
|
|
31
|
+
}
|
|
32
|
+
export type PermissionGrant = string | GroupPermissionGrant;
|
|
15
33
|
export interface PropsField {
|
|
16
34
|
label: string;
|
|
17
35
|
type: string;
|
|
@@ -70,3 +88,154 @@ export interface AiAssistantModelInfo {
|
|
|
70
88
|
name: string;
|
|
71
89
|
description?: string;
|
|
72
90
|
}
|
|
91
|
+
/**
|
|
92
|
+
* Streaming agent contract.
|
|
93
|
+
*
|
|
94
|
+
* A model service that only implements `generateReply` stays a plain chat
|
|
95
|
+
* model; services that also implement the optional agent members below are
|
|
96
|
+
* driven by the streaming UI (tool calls, reasoning, attachments, per-user
|
|
97
|
+
* server-side session). See AbstractAiModelService.
|
|
98
|
+
*/
|
|
99
|
+
/** One SSE frame of a run. `type` drives how the UI folds it into the thread. */
|
|
100
|
+
export type AiAgentStreamEvent = {
|
|
101
|
+
type: 'text.delta' | 'text.done' | 'reasoning.delta' | 'reasoning.done' | 'tool.start' | 'tool.done' | 'tool.error' | 'step.done' | 'turn.done' | 'done' | 'error' | string;
|
|
102
|
+
[key: string]: unknown;
|
|
103
|
+
};
|
|
104
|
+
export type AiAgentPublish = (event: AiAgentStreamEvent) => void;
|
|
105
|
+
export interface AiAgentTokenUsage {
|
|
106
|
+
inputTokens?: number;
|
|
107
|
+
outputTokens?: number;
|
|
108
|
+
totalTokens?: number;
|
|
109
|
+
}
|
|
110
|
+
/** One selectable LLM inside an agent service. */
|
|
111
|
+
export interface AiAgentModelOption {
|
|
112
|
+
id: string;
|
|
113
|
+
contextWindow: number | null;
|
|
114
|
+
maxOutputTokens: number | null;
|
|
115
|
+
vision: boolean;
|
|
116
|
+
/** Relative spend multiplier (×1 = median-priced model); null if unknown. */
|
|
117
|
+
costCoefficient: number | null;
|
|
118
|
+
[key: string]: unknown;
|
|
119
|
+
}
|
|
120
|
+
/** State of the user's server-side agent session. */
|
|
121
|
+
export interface AiAgentSessionMeta {
|
|
122
|
+
model: string;
|
|
123
|
+
contextWindow: number;
|
|
124
|
+
vision: boolean;
|
|
125
|
+
turns: number;
|
|
126
|
+
contextTokens: number;
|
|
127
|
+
totalUsage: AiAgentTokenUsage;
|
|
128
|
+
[key: string]: unknown;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Whether the service can talk to its LLM yet. Services that need no
|
|
132
|
+
* provisioning simply omit `getConnectionStatus()` and are treated as ready.
|
|
133
|
+
*/
|
|
134
|
+
export interface AiAgentConnectionStatus {
|
|
135
|
+
state: 'ready' | 'registering' | 'waiting_retry' | 'setup_required' | 'error';
|
|
136
|
+
provider?: string;
|
|
137
|
+
baseUrl?: string;
|
|
138
|
+
source?: string | null;
|
|
139
|
+
nextAttemptAt?: string | null;
|
|
140
|
+
lastError?: string | null;
|
|
141
|
+
expiresAt?: string | null;
|
|
142
|
+
[key: string]: unknown;
|
|
143
|
+
}
|
|
144
|
+
/** States for which an agent can describe its connection screen. */
|
|
145
|
+
export type AiAgentConnectionState = Exclude<AiAgentConnectionStatus['state'], 'ready'>;
|
|
146
|
+
/**
|
|
147
|
+
* Declarative connection screen supplied by an agent service. The shared panel
|
|
148
|
+
* owns rendering, while the agent owns its copy, CTA and which status details
|
|
149
|
+
* are useful to expose.
|
|
150
|
+
*/
|
|
151
|
+
export interface AiAgentConnectionScreen {
|
|
152
|
+
title?: string;
|
|
153
|
+
description?: string;
|
|
154
|
+
icon?: 'spinner' | 'bot' | 'error';
|
|
155
|
+
action?: {
|
|
156
|
+
label: string;
|
|
157
|
+
href: string;
|
|
158
|
+
};
|
|
159
|
+
/** Status values the agent wants to render on this screen. */
|
|
160
|
+
details?: Array<{
|
|
161
|
+
field: string;
|
|
162
|
+
label?: string;
|
|
163
|
+
format?: 'text' | 'local-time';
|
|
164
|
+
tone?: 'muted' | 'error';
|
|
165
|
+
}>;
|
|
166
|
+
}
|
|
167
|
+
/** Normalized budget / rate limits of the provider key, when it exposes them. */
|
|
168
|
+
export interface AiAgentLimits {
|
|
169
|
+
provider: string;
|
|
170
|
+
supported: boolean;
|
|
171
|
+
overBudget?: boolean;
|
|
172
|
+
message?: string;
|
|
173
|
+
maxBudgetUsd?: number | null;
|
|
174
|
+
spentUsd?: number | null;
|
|
175
|
+
remainingBudgetUsd?: number | null;
|
|
176
|
+
budgetResetAt?: string | null;
|
|
177
|
+
burstMaxBudgetUsd?: number | null;
|
|
178
|
+
burstSpentUsd?: number | null;
|
|
179
|
+
burstRemainingBudgetUsd?: number | null;
|
|
180
|
+
burstResetAt?: string | null;
|
|
181
|
+
burstDurationLabel?: string | null;
|
|
182
|
+
rpmLimit?: number | null;
|
|
183
|
+
tpmLimit?: number | null;
|
|
184
|
+
fetchedAt?: string;
|
|
185
|
+
[key: string]: unknown;
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Copy the panel shows instead of its neutral defaults. `getUiHints(locale)`
|
|
189
|
+
* receives the admin user's locale, so agents can return localized copy.
|
|
190
|
+
*/
|
|
191
|
+
export interface AiAgentUiHints {
|
|
192
|
+
title?: string;
|
|
193
|
+
welcomeHint?: string;
|
|
194
|
+
composerPlaceholder?: string;
|
|
195
|
+
suggestions?: string[];
|
|
196
|
+
/** Setting an operator must fill in before the service can connect. */
|
|
197
|
+
setupSetting?: string;
|
|
198
|
+
/** Where to fill it in; rendered as a button on the connection loader. */
|
|
199
|
+
setupUrl?: string;
|
|
200
|
+
/**
|
|
201
|
+
* Per-state pages rendered while this agent is not ready. `default` is
|
|
202
|
+
* used for any state without its own screen.
|
|
203
|
+
*/
|
|
204
|
+
connectionScreens?: Partial<Record<AiAgentConnectionState | 'default', AiAgentConnectionScreen>>;
|
|
205
|
+
[key: string]: unknown;
|
|
206
|
+
}
|
|
207
|
+
/** A browser-side capability which an agent may call through `ui.method`. */
|
|
208
|
+
export interface AiAgentUiMethod {
|
|
209
|
+
id: string;
|
|
210
|
+
title: string;
|
|
211
|
+
description: string;
|
|
212
|
+
inputSchema: Record<string, unknown>;
|
|
213
|
+
action: string;
|
|
214
|
+
accessRightsToken?: string;
|
|
215
|
+
}
|
|
216
|
+
/** Declarative UI contract consumed by the shared assistant panel. */
|
|
217
|
+
export interface AiAgentUiSchema extends AiAgentUiHints {
|
|
218
|
+
commands: Array<{
|
|
219
|
+
id: string;
|
|
220
|
+
description?: string;
|
|
221
|
+
}>;
|
|
222
|
+
uiMethods?: AiAgentUiMethod[];
|
|
223
|
+
panels: {
|
|
224
|
+
history: boolean;
|
|
225
|
+
models: boolean;
|
|
226
|
+
limits: boolean;
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
/** An uploaded file as handed to the agent service (multer memory storage). */
|
|
230
|
+
export interface AiAgentUploadedFile {
|
|
231
|
+
originalname: string;
|
|
232
|
+
mimetype: string;
|
|
233
|
+
size: number;
|
|
234
|
+
buffer: Buffer;
|
|
235
|
+
}
|
|
236
|
+
/** What the service reports back about a stored upload, if it stores them. */
|
|
237
|
+
export interface AiAgentSavedFile {
|
|
238
|
+
id?: string;
|
|
239
|
+
name?: string;
|
|
240
|
+
[key: string]: unknown;
|
|
241
|
+
}
|
package/lib/Adminizer.d.ts
CHANGED
|
@@ -27,6 +27,10 @@ import { ControllerHandler } from "./app-manager/ControllerHandler.js";
|
|
|
27
27
|
import { AssetHandler } from "./app-manager/AssetHandler.js";
|
|
28
28
|
import { ConfigLayerHandler } from "./app-manager/ConfigLayerHandler.js";
|
|
29
29
|
import { AccessRightsHandler } from "./access-rights/AccessRightsHandler.js";
|
|
30
|
+
import { AiAssistantUiMethodHandler } from './ai-assistant/AiAssistantUiMethodHandler.js';
|
|
31
|
+
import { AdminLinkHandler } from './admin-links/AdminLinkHandler.js';
|
|
32
|
+
import { AiAssistantAgentSkillHandler } from './ai-assistant/AiAssistantAgentSkillHandler.js';
|
|
33
|
+
import { DocumentationHandler } from './docs/DocumentationHandler.js';
|
|
30
34
|
export declare function createAdminizerLogger(): winston.Logger;
|
|
31
35
|
export interface EmitAsyncOptions {
|
|
32
36
|
/**
|
|
@@ -54,6 +58,10 @@ export declare class Adminizer {
|
|
|
54
58
|
notificationHandler: NotificationHandler;
|
|
55
59
|
historyHandler: HistoryHandler;
|
|
56
60
|
private _aiAssistantHandler?;
|
|
61
|
+
aiAssistantUiMethodHandler: AiAssistantUiMethodHandler;
|
|
62
|
+
adminLinkHandler: AdminLinkHandler;
|
|
63
|
+
aiAssistantAgentSkillHandler: AiAssistantAgentSkillHandler;
|
|
64
|
+
documentationHandler: DocumentationHandler;
|
|
57
65
|
modelHandler: ModelHandler;
|
|
58
66
|
widgetHandler: WidgetHandler;
|
|
59
67
|
customFilterHandler: CustomFilterHandler;
|
package/lib/Adminizer.js
CHANGED
|
@@ -37,12 +37,18 @@ import { bindCors } from "../system/bindCors.js";
|
|
|
37
37
|
import bindHistory from "../system/bindHistory.js";
|
|
38
38
|
import bindCustomFilterHandlers from "../system/bindCustomFilterHandlers.js";
|
|
39
39
|
import { FeedbackHandler } from "./feedback/FeedbackHandler.js";
|
|
40
|
-
import {
|
|
40
|
+
import { refreshInternalModelAccess } from "../system/buildInternalModelAccess.js";
|
|
41
|
+
import { validateAccessGraph } from "./access-graph/AccessGraphResolver.js";
|
|
41
42
|
import { AppManager } from "./app-manager/AppManager.js";
|
|
42
43
|
import { ControllerHandler } from "./app-manager/ControllerHandler.js";
|
|
43
44
|
import { AssetHandler } from "./app-manager/AssetHandler.js";
|
|
44
45
|
import { ConfigLayerHandler } from "./app-manager/ConfigLayerHandler.js";
|
|
45
46
|
import { AccessRightsHandler } from "./access-rights/AccessRightsHandler.js";
|
|
47
|
+
import { AiAssistantUiMethodHandler } from './ai-assistant/AiAssistantUiMethodHandler.js';
|
|
48
|
+
import { AdminLinkHandler } from './admin-links/AdminLinkHandler.js';
|
|
49
|
+
import { AiAssistantAgentSkillHandler } from './ai-assistant/AiAssistantAgentSkillHandler.js';
|
|
50
|
+
import { DocumentationHandler } from './docs/DocumentationHandler.js';
|
|
51
|
+
import bindDocs from '../system/bindDocs.js';
|
|
46
52
|
const logFilePath = "logs/app.log";
|
|
47
53
|
function ensureLogDirectory(filePath) {
|
|
48
54
|
const logDirectory = path.dirname(filePath);
|
|
@@ -109,6 +115,10 @@ export class Adminizer {
|
|
|
109
115
|
notificationHandler;
|
|
110
116
|
historyHandler;
|
|
111
117
|
_aiAssistantHandler;
|
|
118
|
+
aiAssistantUiMethodHandler;
|
|
119
|
+
adminLinkHandler;
|
|
120
|
+
aiAssistantAgentSkillHandler;
|
|
121
|
+
documentationHandler;
|
|
112
122
|
modelHandler;
|
|
113
123
|
widgetHandler;
|
|
114
124
|
customFilterHandler;
|
|
@@ -141,10 +151,19 @@ export class Adminizer {
|
|
|
141
151
|
this.catalogTemplateComponentHandler = new CatalogTemplateComponentHandler();
|
|
142
152
|
this.mediaManagerHandler = new MediaManagerHandler();
|
|
143
153
|
this.feedbackHandler = new FeedbackHandler(this);
|
|
154
|
+
this.aiAssistantUiMethodHandler = new AiAssistantUiMethodHandler(this);
|
|
155
|
+
this.adminLinkHandler = new AdminLinkHandler(this);
|
|
156
|
+
this.aiAssistantAgentSkillHandler = new AiAssistantAgentSkillHandler(this);
|
|
157
|
+
this.documentationHandler = new DocumentationHandler(this, () => bindDocs(this));
|
|
144
158
|
this.controllerHandler = new ControllerHandler(this);
|
|
145
159
|
this.assetHandler = new AssetHandler(this);
|
|
146
160
|
this.configLayerHandler = new ConfigLayerHandler(this);
|
|
147
161
|
this.appManager = new AppManager(this);
|
|
162
|
+
// App model (un)registration changes what the record-access resolvers may query,
|
|
163
|
+
// so the internal allowlists must follow; config-layer rebuilds refresh them
|
|
164
|
+
// synchronously inside rebuildConfig itself.
|
|
165
|
+
this.emitter.on("app:model:registered", () => refreshInternalModelAccess(this));
|
|
166
|
+
this.emitter.on("app:model:unregistered", () => refreshInternalModelAccess(this));
|
|
148
167
|
}
|
|
149
168
|
/**
|
|
150
169
|
* Shared AI assistant model registry.
|
|
@@ -257,7 +276,10 @@ export class Adminizer {
|
|
|
257
276
|
this.emitter.emit('adminizer:init');
|
|
258
277
|
// validate models
|
|
259
278
|
validateSystemModels(this);
|
|
260
|
-
|
|
279
|
+
refreshInternalModelAccess(this);
|
|
280
|
+
// Fail loud on structural accessGraph errors at boot; later config rebuilds only
|
|
281
|
+
// log them and the affected models fail closed at access time.
|
|
282
|
+
validateAccessGraph(this);
|
|
261
283
|
bindCustomFilterHandlers(this);
|
|
262
284
|
this.config.rootPath = path.resolve(import.meta.dirname + "/..");
|
|
263
285
|
await this.middlewareManager.loadMiddlewares();
|
|
@@ -293,6 +315,11 @@ export class Adminizer {
|
|
|
293
315
|
bindHistory(this);
|
|
294
316
|
this.router = new Router(this);
|
|
295
317
|
await this.router.bind(); // must be after binding policies and req/res functions
|
|
318
|
+
// Documentation (knowledge base) wires itself on register(); this call
|
|
319
|
+
// covers a service registered before the config was read. It runs after
|
|
320
|
+
// the router so those routes sit behind the same middleware stack a
|
|
321
|
+
// service registered after init() gets.
|
|
322
|
+
this.documentationHandler.activate();
|
|
296
323
|
/**
|
|
297
324
|
* Adminizer loaded
|
|
298
325
|
* This call is used so that other apps can know that the admin panel is present in the panel and has been loaded, and can activate their logic.
|