adminizer 4.1.0-build.3 → 4.1.0-build.31
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/Readme.md +11 -1
- package/assets/{VanillaJSONEditor-FUe77pIA.js → VanillaJSONEditor-DTWads1Y.js} +104 -104
- package/assets/add-NjsCZZct.js +1 -0
- package/assets/add-form-DJnEBqvy.js +1 -0
- package/assets/add-group-CU2zD7To.js +1 -0
- package/assets/add-group-form-CQN_syZq.js +1 -0
- package/assets/add-user-BkTa9shp.js +1 -0
- package/assets/add-user-form-C7T14FsG.js +1 -0
- package/assets/{app-DMmad2-f.css → app-DVaaqBB5.css} +1 -1
- package/assets/app-layout-NY6MXzc5.js +1 -0
- package/assets/{app-shell-BWMRMkHM.js → app-shell-BjaxjNs9.js} +1 -1
- package/assets/app-sidebar-CLu13Pcu.js +1 -0
- package/assets/{app-sidebar-header-DLAFi13E.js → app-sidebar-header-5IaQpngt.js} +1 -1
- package/assets/app.js +9 -9
- package/assets/{breadcrumbs-CQNon4Vl.js → breadcrumbs-CDxSbsTe.js} +1 -1
- package/assets/button-BV-GbIpN.js +1 -0
- package/assets/catalog-Cc6Mk9sX.css +1 -0
- package/assets/catalog-CeUUKxG9.js +17 -0
- package/assets/{checkbox-W0nGAXIj.js → checkbox-DrkQu16U.js} +1 -1
- package/assets/{compiler-runtime-tM4jBQ-T.js → compiler-runtime-Cj7rbuyn.js} +2 -2
- package/assets/dashboard-BOltB2Hq.css +1 -0
- package/assets/dashboard-BTmXuc5F.js +3 -0
- package/assets/{date-picker-B__dVVqj.js → date-picker-hoDPF9Am.js} +1 -1
- package/assets/debounce-qdyXyOeG.js +1 -0
- package/assets/del-modal-BUVjhY0k.js +6 -0
- package/assets/dialog-stack-BAuaxCy1.js +1 -0
- package/assets/dropdown-menu-CeMIoM8d.js +1 -0
- package/assets/{field-renderer-CapylJU9.js → field-renderer-zGC76llY.js} +3 -3
- package/assets/form-CN2xVSMK.js +1 -0
- package/assets/form-DOt5Fa6e.js +1 -0
- package/assets/{geo-json-CwteYDGB.js → geo-json-VtXcqPd9.js} +1 -1
- package/assets/group-link-add-CCNISxeF.js +1 -0
- package/assets/{handsontable-BCnjOpBr.js → handsontable-DrEU6lOi.js} +1 -1
- package/assets/home-3FBATYFh.js +2 -0
- package/assets/{icon-Bz9BMaD0.js → icon-CqJOMij7.js} +1 -1
- package/assets/index-BCpOvf4m.js +1 -0
- package/assets/{index-BbXEMx9n.js → index-B__NksD2.js} +1 -1
- package/assets/{index-DTRTjOmh.js → index-C0o7vG6r.js} +3 -3
- package/assets/{index-C0SL3SHw.js → index-CcxvoJO6.js} +1 -1
- package/assets/{index-D5ir9iUV.js → index-Cq31rrfZ.js} +1 -1
- package/assets/{index-K81GbF6O.js → index-DN1K56yz.js} +1 -1
- package/assets/{index-DrWfGwtf.js → index-DU8vYhyh.js} +1 -1
- package/assets/{index-BcE9FUM6.js → index-DoVAC0HX.js} +1 -1
- package/assets/{index-BC0yfOHo.js → index-lqMxC6QB.js} +1 -1
- package/assets/{index-DEk3sC8d.js → index-oMAR28Sy.js} +1 -1
- package/assets/{init-user-D9mW-g14.js → init-user-BBfP40-3.js} +1 -1
- package/assets/{input-DF7Ue23C.js → input-B7wUhbil.js} +1 -1
- package/assets/{input-error-BBygona6.js → input-error-DFk1EyT_.js} +1 -1
- package/assets/item-add-CX7EOX0H.js +1 -0
- package/assets/{label-Z506NKsW.js → label-GEoZpZr4.js} +1 -1
- package/assets/list-DqIUjXSX.js +1 -0
- package/assets/list-table-1aXDvDPl.js +57 -0
- package/assets/{login-DrGaTWhY.js → login-Bv4hqwaM.js} +2 -2
- package/assets/manifest.json +788 -604
- package/assets/{material-icon-CItZiB53.js → material-icon-BAd3Wrgn.js} +1 -1
- package/assets/module-DziT22BH.js +1 -0
- package/assets/{monaco-editor-DqAqwxw4.js → monaco-editor-B5kndNv5.js} +1 -1
- package/assets/{multi-select-oabtVhUP.js → multi-select-CSxVlxon.js} +2 -2
- package/assets/{nav-footer-CM-yHiRs.js → nav-footer-Vm24wf5X.js} +1 -1
- package/assets/{nav-main-Q3xofGRT.js → nav-main-JVt9gzn8.js} +1 -1
- package/assets/{nav-user-Ds8i0Pa2.js → nav-user-DgYX0wO7.js} +1 -1
- package/assets/{pagination-render-B57pOpFy.js → pagination-render-B12W01AJ.js} +1 -1
- package/assets/{popover-I249Gg2O.js → popover-B3ZOyoLQ.js} +1 -1
- package/assets/{register-C9FQIDtS.js → register-D8SyTFBZ.js} +1 -1
- package/assets/{select-D1N8zRPY.js → select-MzwxLt1D.js} +2 -2
- package/assets/{sidebar-4D-sX2l4.js → sidebar-DGp3i7GG.js} +2 -2
- package/assets/skeleton-C3gmNc1Z.js +1 -0
- package/assets/{sonner-Dzckw3U3.js → sonner-MAL0i2dq.js} +1 -1
- package/assets/{toast-editor-FbrFd1ft.js → toast-editor-DRP2u8-X.js} +1 -1
- package/assets/{tooltip-D2ehgLlB.js → tooltip-Du62rBCn.js} +1 -1
- package/assets/{use-appearance-Co6mO0dV.js → use-appearance-DeUiDZ72.js} +1 -1
- package/assets/{use-window-size-B8l6Bpkf.js → use-window-size-ChEjEujj.js} +1 -1
- package/assets/{user-info-DBYoAJYJ.js → user-info-C_11jYGE.js} +1 -1
- package/assets/{user-menu-content-qkvdkUVd.js → user-menu-content-BNRzhEo_.js} +2 -2
- package/assets/welcome-C9BMKsoY.js +1 -0
- package/controllers/add.js +10 -10
- package/controllers/addGroup.js +2 -4
- package/controllers/addUser.js +4 -6
- package/controllers/catalog/Catalog.d.ts +1 -1
- package/controllers/catalog/Catalog.js +42 -36
- package/controllers/catalog/FrontentCatalogAdapter.d.ts +39 -25
- package/controllers/catalog/FrontentCatalogAdapter.js +55 -55
- package/controllers/ckeditorUpload.js +2 -3
- package/controllers/dashboard.js +16 -2
- package/controllers/edit.js +10 -14
- package/controllers/editGroup.js +2 -4
- package/controllers/editUser.js +3 -5
- package/controllers/form.js +2 -3
- package/controllers/getAllWidgets.js +3 -3
- package/controllers/initUser.js +1 -2
- package/controllers/list.js +6 -6
- package/controllers/login.js +31 -15
- package/controllers/media-manager/mediaManagerAdapter.js +1 -2
- package/controllers/media-manager/mediaManagerApi.js +2 -2
- package/controllers/navigation/edit.js +2 -2
- package/controllers/register.js +1 -4
- package/controllers/remove.js +3 -3
- package/controllers/timezones.js +1 -1
- package/controllers/view.js +3 -3
- package/controllers/welcome.js +1 -1
- package/controllers/widgets/Action.js +2 -2
- package/controllers/widgets/Custom.js +2 -2
- package/controllers/widgets/Info.js +2 -2
- package/controllers/widgets/switch.js +2 -2
- package/controllers/widgetsDB.js +5 -5
- package/helpers/JsUtils.d.ts +1 -0
- package/helpers/JsUtils.js +3 -0
- package/helpers/accessRightsHelper.d.ts +6 -2
- package/helpers/accessRightsHelper.js +26 -3
- package/helpers/configHelper.js +2 -1
- package/helpers/controllerHelper.js +39 -18
- package/helpers/fieldsHelper.d.ts +4 -3
- package/helpers/fieldsHelper.js +5 -1
- package/helpers/inertiaActionsHelper.js +1 -1
- package/helpers/inertiaAddHelper.d.ts +3 -4
- package/helpers/inertiaAddHelper.js +27 -7
- package/helpers/inertiaFromHelper.js +2 -0
- package/helpers/inertiaGroupHelper.d.ts +4 -2
- package/helpers/inertiaGroupHelper.js +1 -1
- package/helpers/inertiaListHelper.js +5 -5
- package/helpers/inertiaMenuHelper.d.ts +1 -1
- package/helpers/inertiaMenuHelper.js +2 -2
- package/helpers/inertiaUserHelper.d.ts +7 -1
- package/helpers/inertiaUserHelper.js +5 -1
- package/helpers/menuHelper.d.ts +4 -3
- package/helpers/menuHelper.js +22 -15
- package/index.d.ts +5 -3
- package/index.js +8 -3
- package/interfaces/adminpanelConfig.d.ts +29 -32
- package/interfaces/global.d.ts +10 -28
- package/interfaces/types.d.ts +1 -1
- package/lib/Adminizer.d.ts +4 -2
- package/lib/Adminizer.js +33 -11
- package/lib/media-manager/AbstractMediaManager.d.ts +2 -2
- package/lib/media-manager/AbstractMediaManager.js +1 -1
- package/lib/media-manager/Items.js +0 -3
- package/lib/requestProcessor.js +10 -3
- package/lib/v4/DataAccessor.d.ts +5 -2
- package/lib/v4/DataAccessor.js +44 -19
- package/lib/v4/I18n.js +2 -0
- package/lib/v4/POWCaptcha.js +0 -1
- package/lib/v4/PolicyManager.js +0 -1
- package/lib/{catalog → v4/catalog}/AbstractCatalog.d.ts +79 -41
- package/lib/{catalog → v4/catalog}/AbstractCatalog.js +49 -41
- package/lib/v4/catalog/Navigation.d.ts +43 -0
- package/lib/v4/catalog/Navigation.js +457 -0
- package/lib/{controls → v4/controls}/AbstractControls.d.ts +1 -1
- package/lib/{controls → v4/controls}/codeEditor/MonacoEditor.d.ts +1 -1
- package/lib/{controls → v4/controls}/geojsoneditor/GeoEditor.d.ts +1 -1
- package/lib/{controls → v4/controls}/jsoneditor/JsonEditor.d.ts +1 -1
- package/lib/{controls → v4/controls}/markdown/ToastUiEditor.d.ts +1 -1
- package/lib/{controls → v4/controls}/table/Handsontable.d.ts +1 -1
- package/lib/{controls → v4/controls}/wysiwyg/CKeditor.d.ts +1 -1
- package/lib/{datatable → v4/datatable}/NodeTable.d.ts +3 -3
- package/lib/{datatable → v4/datatable}/NodeTable.js +8 -8
- package/lib/v4/helper/jwt.d.ts +10 -0
- package/lib/v4/helper/jwt.js +18 -0
- package/lib/{inertia → v4/inertia}/inertiaAdapter.js +0 -1
- package/lib/v4/model/AbstractModel.d.ts +5 -1
- package/lib/v4/model/AbstractModel.js +2 -3
- package/lib/v4/model/ModelHandler.js +1 -1
- package/lib/v4/model/adapter/sequelize.d.ts +11 -2
- package/lib/v4/model/adapter/sequelize.js +451 -118
- package/lib/v4/model/adapter/waterline.js +5 -3
- package/lib/{widgets → v4/widgets}/abstractAction.d.ts +1 -1
- package/lib/v4/widgets/abstractCustom.d.ts +28 -0
- package/lib/v4/widgets/abstractCustom.js +9 -0
- package/lib/{widgets → v4/widgets}/abstractInfo.d.ts +1 -1
- package/lib/{widgets → v4/widgets}/abstractInfo.js +1 -1
- package/lib/{widgets → v4/widgets}/abstractLink.d.ts +2 -1
- package/lib/{widgets → v4/widgets}/abstractSwitch.d.ts +1 -1
- package/lib/{widgets → v4/widgets}/abstractWidgetBase.d.ts +2 -2
- package/lib/{widgets → v4/widgets}/widgetHandler.d.ts +29 -5
- package/lib/{widgets → v4/widgets}/widgetHandler.js +25 -25
- package/models/GroupAP.d.ts +8 -0
- package/models/NavigationAP.d.ts +7 -3
- package/models/NavigationAP.js +5 -6
- package/models/UserAP.d.ts +24 -2
- package/models/UserAP.js +2 -2
- package/package.json +27 -11
- package/policies/checkAuth.js +4 -3
- package/policies/setLocale.js +2 -2
- package/system/Router.js +8 -16
- package/system/bindAccessRights.js +0 -4
- package/system/bindAuthorization.js +4 -5
- package/system/bindControls.js +6 -6
- package/system/bindDev.js +1 -0
- package/system/bindInertia.js +12 -11
- package/system/bindMediaManager.js +0 -1
- package/system/bindModels.js +8 -5
- package/system/bindNavigation.d.ts +2 -0
- package/system/bindNavigation.js +42 -42
- package/system/bindReqFunctions.js +15 -0
- package/system/defaults.js +2 -2
- package/translations/ru.json +17 -8
- package/assets/add-ZITr43GJ.js +0 -1
- package/assets/add-form-CYOfr0Ef.js +0 -1
- package/assets/add-group-B332wN8K.js +0 -1
- package/assets/add-group-form-dzadPSfL.js +0 -1
- package/assets/add-user-TC-mYdsB.js +0 -1
- package/assets/add-user-form-y2f_1_lM.js +0 -1
- package/assets/app-layout-D1m9Kvxq.js +0 -1
- package/assets/app-sidebar-BCtaEFGb.js +0 -1
- package/assets/button-CQ9t1kLz.js +0 -1
- package/assets/dashboard-BR602KhL.js +0 -1
- package/assets/dropdown-menu-SEBnEIiL.js +0 -1
- package/assets/form-DOUNk3o2.js +0 -1
- package/assets/form-lOKv4Qbw.js +0 -1
- package/assets/home-Ch6QfTIt.js +0 -2
- package/assets/index-Cdb9ACvz.js +0 -1
- package/assets/list-Qyd7ecQH.js +0 -1
- package/assets/list-table-DB1sEQLF.js +0 -62
- package/assets/module-DBaykv8l.js +0 -1
- package/assets/welcome-D2adQ8EU.js +0 -1
- package/controllers/processInstallFinalize.d.ts +0 -1
- package/controllers/processInstallFinalize.js +0 -16
- package/controllers/processInstallStep.d.ts +0 -1
- package/controllers/processInstallStep.js +0 -132
- package/lib/catalog/Navigation.d.ts +0 -0
- package/lib/catalog/Navigation.js +0 -532
- package/lib/installStepper/InstallStepAbstract.d.ts +0 -52
- package/lib/installStepper/InstallStepAbstract.js +0 -69
- package/lib/installStepper/finalizeStep.d.ts +0 -21
- package/lib/installStepper/finalizeStep.js +0 -48
- package/lib/installStepper/installStepper.d.ts +0 -40
- package/lib/installStepper/installStepper.js +0 -195
- package/lib/widgets/abstractCustom.d.ts +0 -13
- package/lib/widgets/abstractCustom.js +0 -3
- package/models/MediaManagerAP.d.ts +0 -46
- package/models/MediaManagerAP.js +0 -45
- package/models/MediaManagerAssociationsAP.d.ts +0 -28
- package/models/MediaManagerAssociationsAP.js +0 -27
- package/models/MediaManagerMetaAP.d.ts +0 -22
- package/models/MediaManagerMetaAP.js +0 -21
- package/system/bindInstallStepper.d.ts +0 -2
- package/system/bindInstallStepper.js +0 -23
- /package/lib/{catalog → v4/catalog}/CatalogHandler.d.ts +0 -0
- /package/lib/{catalog → v4/catalog}/CatalogHandler.js +0 -0
- /package/lib/{controls → v4/controls}/AbstractControls.js +0 -0
- /package/lib/{controls → v4/controls}/ControlsHandler.d.ts +0 -0
- /package/lib/{controls → v4/controls}/ControlsHandler.js +0 -0
- /package/lib/{controls → v4/controls}/codeEditor/MonacoEditor.js +0 -0
- /package/lib/{controls → v4/controls}/geojsoneditor/GeoEditor.js +0 -0
- /package/lib/{controls → v4/controls}/jsoneditor/JsonEditor.js +0 -0
- /package/lib/{controls → v4/controls}/markdown/ToastUiEditor.js +0 -0
- /package/lib/{controls → v4/controls}/table/Handsontable.js +0 -0
- /package/lib/{controls → v4/controls}/wysiwyg/CKeditor.js +0 -0
- /package/lib/{inertia → v4/inertia}/flash.d.ts +0 -0
- /package/lib/{inertia → v4/inertia}/flash.js +0 -0
- /package/lib/{inertia → v4/inertia}/inertiaAdapter.d.ts +0 -0
- /package/lib/{widgets → v4/widgets}/abstractAction.js +0 -0
- /package/lib/{widgets → v4/widgets}/abstractLink.js +0 -0
- /package/lib/{widgets → v4/widgets}/abstractSwitch.js +0 -0
- /package/lib/{widgets → v4/widgets}/abstractWidgetBase.js +0 -0
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { MaterialIcon } from "./MaaterialIcons";
|
|
2
2
|
import { EditorOptions } from "@toast-ui/editor/types/editor";
|
|
3
3
|
import { GridSettings as HandsontableSettings } from "handsontable/settings";
|
|
4
|
+
import { GroupAP } from "models/GroupAP";
|
|
5
|
+
import { UserAP } from "models/UserAP";
|
|
4
6
|
export type AdminpanelIcon = MaterialIcon;
|
|
5
7
|
export type FieldsTypes = "string" | "password" | "date" | "datetime" | "time" | "integer" | "number" | "float" | "color" | "email" | "month" | "week" | "range" | "boolean" | "binary" | "text" | "longtext" | "mediumtext" | "ckeditor" | "wysiwyg" | "texteditor" | "word" | 'tui' | 'tuieditor' | 'toast-ui' | "jsoneditor" | "json" | "array" | "object" | "ace" | "code" | "html" | "xml" | "aceeditor" | "menu" | "schedule" | "worktime" | "association" | "association-many" | "select" | "select-many" | "table" | "geojson" | "mediamanager" |
|
|
6
8
|
/**
|
|
@@ -37,7 +39,7 @@ export interface AdminpanelConfig {
|
|
|
37
39
|
* reference upload contoroller ~50 line
|
|
38
40
|
* */
|
|
39
41
|
models: {
|
|
40
|
-
[key: string]: ModelConfig
|
|
42
|
+
[key: string]: ModelConfig;
|
|
41
43
|
};
|
|
42
44
|
/**
|
|
43
45
|
* For custom adminpanel sections, displays inside header
|
|
@@ -121,23 +123,6 @@ export interface AdminpanelConfig {
|
|
|
121
123
|
* */
|
|
122
124
|
set?: SetFunction;
|
|
123
125
|
};
|
|
124
|
-
/**
|
|
125
|
-
* Wizards
|
|
126
|
-
* */
|
|
127
|
-
installStepper?: {
|
|
128
|
-
path: string;
|
|
129
|
-
data: {
|
|
130
|
-
[key: string]: FieldsModels;
|
|
131
|
-
};
|
|
132
|
-
/**
|
|
133
|
-
* Custom getter
|
|
134
|
-
* */
|
|
135
|
-
get?: GetFunction;
|
|
136
|
-
/**
|
|
137
|
-
* Custom setter
|
|
138
|
-
* */
|
|
139
|
-
set?: SetFunction;
|
|
140
|
-
};
|
|
141
126
|
/**
|
|
142
127
|
* Prime administrator login credentials
|
|
143
128
|
* */
|
|
@@ -178,12 +163,6 @@ export interface AdminpanelConfig {
|
|
|
178
163
|
* Navigation
|
|
179
164
|
*/
|
|
180
165
|
navigation?: NavigationConfig;
|
|
181
|
-
/**
|
|
182
|
-
* Path to modules views
|
|
183
|
-
*/
|
|
184
|
-
modulesViewsPath?: string;
|
|
185
|
-
/** @deprecated (module manager can be used it somehow) */
|
|
186
|
-
templateRootPath?: string;
|
|
187
166
|
mediamanager?: MediaManagerConfig;
|
|
188
167
|
/** System settings */
|
|
189
168
|
system?: {
|
|
@@ -199,9 +178,19 @@ export interface ModelConfig {
|
|
|
199
178
|
* */
|
|
200
179
|
model: string;
|
|
201
180
|
/**
|
|
202
|
-
*
|
|
181
|
+
* If the field is not definitely, then it will appear in Navbar
|
|
203
182
|
* */
|
|
204
|
-
|
|
183
|
+
navbar?: {
|
|
184
|
+
/**
|
|
185
|
+
* @default true
|
|
186
|
+
*/
|
|
187
|
+
visible?: boolean;
|
|
188
|
+
/**
|
|
189
|
+
* User groups who will see the menu item
|
|
190
|
+
* For which it will be shown if not established will be shown to all groups who have the rights to read
|
|
191
|
+
*/
|
|
192
|
+
groupsAccessRights?: string[];
|
|
193
|
+
};
|
|
205
194
|
/**
|
|
206
195
|
* Entity fields configuration
|
|
207
196
|
* */
|
|
@@ -228,7 +217,7 @@ export interface ModelConfig {
|
|
|
228
217
|
filter?: {
|
|
229
218
|
[key: string]: {
|
|
230
219
|
name: string;
|
|
231
|
-
criteria: any
|
|
220
|
+
criteria: Record<string, any>;
|
|
232
221
|
};
|
|
233
222
|
};
|
|
234
223
|
} | boolean;
|
|
@@ -256,6 +245,11 @@ export interface ModelConfig {
|
|
|
256
245
|
* Entity icon
|
|
257
246
|
* */
|
|
258
247
|
icon?: MaterialIcon;
|
|
248
|
+
/**
|
|
249
|
+
* The field that will be shown for communication
|
|
250
|
+
* @default `title` or `name`
|
|
251
|
+
*/
|
|
252
|
+
titleField?: string;
|
|
259
253
|
/**
|
|
260
254
|
* Force set primary key
|
|
261
255
|
* */
|
|
@@ -264,12 +258,12 @@ export interface ModelConfig {
|
|
|
264
258
|
* May be association or association-many to UserAP or GroupAP */
|
|
265
259
|
userAccessRelation?: {
|
|
266
260
|
field: string;
|
|
267
|
-
via
|
|
261
|
+
via?: string;
|
|
268
262
|
} | string;
|
|
269
263
|
userAccessRelationCallback?: (userWithGroups: UserWithGroups, record: any) => boolean;
|
|
270
264
|
}
|
|
271
|
-
type UserWithGroups =
|
|
272
|
-
groups:
|
|
265
|
+
type UserWithGroups = UserAP & {
|
|
266
|
+
groups: GroupAP[];
|
|
273
267
|
};
|
|
274
268
|
export interface FieldsForms {
|
|
275
269
|
[key: string]: FormFieldConfig;
|
|
@@ -306,6 +300,7 @@ export interface BaseFieldConfig {
|
|
|
306
300
|
identifierField?: string;
|
|
307
301
|
/**
|
|
308
302
|
* Label for associations
|
|
303
|
+
* @deprecated use model labelField prop
|
|
309
304
|
* */
|
|
310
305
|
displayField?: string;
|
|
311
306
|
/**
|
|
@@ -316,6 +311,8 @@ export interface BaseFieldConfig {
|
|
|
316
311
|
disabled?: boolean;
|
|
317
312
|
/** Show as required element HTML */
|
|
318
313
|
required?: boolean;
|
|
314
|
+
/** show or hode element, default `true` */
|
|
315
|
+
visible?: boolean;
|
|
319
316
|
}
|
|
320
317
|
export interface TuiEditorFieldConfig extends BaseFieldConfig {
|
|
321
318
|
type: 'tui' | 'tuieditor' | 'toast-ui';
|
|
@@ -403,7 +400,7 @@ export interface HrefConfig {
|
|
|
403
400
|
/**
|
|
404
401
|
* Only for view, controller still uses his own access rights token
|
|
405
402
|
* */
|
|
406
|
-
accessRightsToken?: string;
|
|
403
|
+
accessRightsToken?: string | undefined;
|
|
407
404
|
/**
|
|
408
405
|
* For menu items only
|
|
409
406
|
* */
|
|
@@ -426,7 +423,7 @@ export interface NavigationConfig {
|
|
|
426
423
|
}[];
|
|
427
424
|
allowContentInGroup?: boolean;
|
|
428
425
|
items: NavigationItemTypeConfig[];
|
|
429
|
-
movingGroupsRootOnly
|
|
426
|
+
movingGroupsRootOnly?: boolean;
|
|
430
427
|
}
|
|
431
428
|
export interface MediaManagerConfig {
|
|
432
429
|
allowMIME?: string[];
|
package/interfaces/global.d.ts
CHANGED
|
@@ -2,17 +2,12 @@ import { Adminizer } from "../lib/Adminizer";
|
|
|
2
2
|
import { NextFunction, Request, Response } from "express";
|
|
3
3
|
import multer from "multer";
|
|
4
4
|
import { I18n } from "../lib/v4/I18n";
|
|
5
|
-
import { Inertia } from "../lib/inertia/inertiaAdapter";
|
|
6
|
-
import { Flash } from "../lib/inertia/flash";
|
|
5
|
+
import { Inertia } from "../lib/v4/inertia/inertiaAdapter";
|
|
6
|
+
import { Flash } from "../lib/v4/inertia/flash";
|
|
7
|
+
import { UserAP } from "models/UserAP";
|
|
7
8
|
declare global {
|
|
9
|
+
/** @deprecated use import from TS model decalration */
|
|
8
10
|
type ModelsAP = {
|
|
9
|
-
GroupAP: {
|
|
10
|
-
id?: number;
|
|
11
|
-
name: string;
|
|
12
|
-
description?: string;
|
|
13
|
-
tokens?: string[];
|
|
14
|
-
users?: ModelsAP["UserAP"][];
|
|
15
|
-
};
|
|
16
11
|
MediaManagerAP: {
|
|
17
12
|
id?: string;
|
|
18
13
|
parent?: ModelsAP["MediaManagerAP"];
|
|
@@ -48,36 +43,20 @@ declare global {
|
|
|
48
43
|
label: string;
|
|
49
44
|
tree: any;
|
|
50
45
|
};
|
|
51
|
-
UserAP: {
|
|
52
|
-
id?: number;
|
|
53
|
-
login?: string;
|
|
54
|
-
fullName?: string;
|
|
55
|
-
email?: string;
|
|
56
|
-
passwordHashed?: string;
|
|
57
|
-
password?: string;
|
|
58
|
-
timezone?: string;
|
|
59
|
-
expires?: string;
|
|
60
|
-
locale?: string;
|
|
61
|
-
isDeleted?: boolean;
|
|
62
|
-
isActive?: boolean;
|
|
63
|
-
isAdministrator?: boolean;
|
|
64
|
-
groups?: ModelsAP["GroupAP"][];
|
|
65
|
-
widgets?: any;
|
|
66
|
-
isConfirmed?: boolean;
|
|
67
|
-
};
|
|
68
46
|
};
|
|
69
47
|
type reqSession = {
|
|
70
48
|
flashMessages: Record<string, string[]>;
|
|
71
49
|
xInertiaCurrentComponent: string | undefined;
|
|
72
|
-
UserAP:
|
|
50
|
+
UserAP: UserAP;
|
|
73
51
|
messages: {
|
|
74
52
|
adminError: string[];
|
|
75
53
|
adminSuccess: string[];
|
|
76
54
|
};
|
|
77
|
-
|
|
55
|
+
userPretended?: UserAP;
|
|
78
56
|
};
|
|
79
57
|
type FlashMessages = 'info' | 'error' | 'success' | string;
|
|
80
58
|
type ReqType = Request & {
|
|
59
|
+
user: UserAP;
|
|
81
60
|
Inertia: Inertia;
|
|
82
61
|
flash: Flash<FlashMessages>;
|
|
83
62
|
session: reqSession;
|
|
@@ -96,6 +75,9 @@ declare global {
|
|
|
96
75
|
i18n: I18n;
|
|
97
76
|
};
|
|
98
77
|
type ResType = Response & {
|
|
78
|
+
/**
|
|
79
|
+
* @deprecated // TODO delete after finish catalog
|
|
80
|
+
*/
|
|
99
81
|
viewAdmin(specifiedPath: string, locals?: any, cb_view?: Function): void;
|
|
100
82
|
};
|
|
101
83
|
type MiddlewareType = (req: ReqType, res: ResType, next: NextFunction) => void;
|
package/interfaces/types.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { AbstractModel } from "../lib/v4/model/AbstractModel";
|
|
2
2
|
import { ModelConfig } from "./adminpanelConfig";
|
|
3
|
-
export type EntityType = "form" | "model"
|
|
3
|
+
export type EntityType = "form" | "model";
|
|
4
4
|
export interface Entity {
|
|
5
5
|
name: string;
|
|
6
6
|
config?: ModelConfig;
|
package/lib/Adminizer.d.ts
CHANGED
|
@@ -4,13 +4,13 @@ import EventEmitter from 'events';
|
|
|
4
4
|
import { AdminpanelConfig } from "../interfaces/adminpanelConfig";
|
|
5
5
|
import PolicyManager from "./v4/PolicyManager";
|
|
6
6
|
import { ModelHandler } from "./v4/model/ModelHandler";
|
|
7
|
-
import { WidgetHandler } from "./widgets/widgetHandler";
|
|
7
|
+
import { WidgetHandler } from "./v4/widgets/widgetHandler";
|
|
8
8
|
import { AccessRightsHelper } from "../helpers/accessRightsHelper";
|
|
9
9
|
import { ConfigHelper } from "../helpers/configHelper";
|
|
10
10
|
import { AbstractAdapter } from "./v4/model/AbstractModel";
|
|
11
11
|
import { ViteDevServer } from 'vite';
|
|
12
12
|
import { MenuHelper } from "../helpers/menuHelper";
|
|
13
|
-
import { ControlsHandler } from "./controls/ControlsHandler";
|
|
13
|
+
import { ControlsHandler } from "./v4/controls/ControlsHandler";
|
|
14
14
|
export declare class Adminizer {
|
|
15
15
|
app: Express;
|
|
16
16
|
config: AdminpanelConfig;
|
|
@@ -24,8 +24,10 @@ export declare class Adminizer {
|
|
|
24
24
|
widgetHandler: WidgetHandler;
|
|
25
25
|
vite: ViteDevServer;
|
|
26
26
|
controlsHandler: ControlsHandler;
|
|
27
|
+
jwtSecret: string;
|
|
27
28
|
static logger: winston.Logger;
|
|
28
29
|
constructor(ormAdapters: AbstractAdapter[]);
|
|
30
|
+
getMiddleware(): (req: any, res: any) => void;
|
|
29
31
|
/**
|
|
30
32
|
* Vite middleware
|
|
31
33
|
* @protected
|
package/lib/Adminizer.js
CHANGED
|
@@ -9,7 +9,7 @@ import Router from "./../system/Router";
|
|
|
9
9
|
import bindAssets from "../system/bindAssets";
|
|
10
10
|
import bindDev from "../system/bindDev";
|
|
11
11
|
import bindDashboardWidgets from "../system/bindDashboardWidgets";
|
|
12
|
-
|
|
12
|
+
import bindNavigation from "../system/bindNavigation";
|
|
13
13
|
// import bindMediaManager from "../system/bindMediaManager";
|
|
14
14
|
import bindAccessRights from "../system/bindAccessRights";
|
|
15
15
|
import bindAuthorization from "../system/bindAuthorization";
|
|
@@ -17,7 +17,7 @@ import bindModels from "../system/bindModels";
|
|
|
17
17
|
import bindForms from "../system/bindForms";
|
|
18
18
|
import bindTranslations from "../system/bindTranslations";
|
|
19
19
|
import { ModelHandler } from "./v4/model/ModelHandler";
|
|
20
|
-
import { WidgetHandler } from "./widgets/widgetHandler";
|
|
20
|
+
import { WidgetHandler } from "./v4/widgets/widgetHandler";
|
|
21
21
|
import { AccessRightsHelper } from "../helpers/accessRightsHelper";
|
|
22
22
|
import bindReqFunctions from "../system/bindReqFunctions";
|
|
23
23
|
import { ConfigHelper } from "../helpers/configHelper";
|
|
@@ -28,7 +28,8 @@ import { createServer as createViteServer } from 'vite';
|
|
|
28
28
|
import { bindInertia } from "../system/bindInertia";
|
|
29
29
|
import { MenuHelper } from "../helpers/menuHelper";
|
|
30
30
|
import { bindControls } from "../system/bindControls";
|
|
31
|
-
import { ControlsHandler } from "./controls/ControlsHandler";
|
|
31
|
+
import { ControlsHandler } from "./v4/controls/ControlsHandler";
|
|
32
|
+
import { v4 as uuid } from "uuid";
|
|
32
33
|
export class Adminizer {
|
|
33
34
|
app;
|
|
34
35
|
config;
|
|
@@ -42,8 +43,9 @@ export class Adminizer {
|
|
|
42
43
|
widgetHandler;
|
|
43
44
|
vite;
|
|
44
45
|
controlsHandler;
|
|
46
|
+
jwtSecret = process.env.JWT_SECRET ?? uuid();
|
|
45
47
|
static logger = winston.createLogger({
|
|
46
|
-
level: "
|
|
48
|
+
level: process.env.LOG_LEVEL ?? "debug",
|
|
47
49
|
format: winston.format.combine(winston.format.timestamp(), winston.format.printf(({ timestamp, level, message, ...meta }) => {
|
|
48
50
|
const metaString = Object.keys(meta).length ? JSON.stringify(meta) : "";
|
|
49
51
|
return `[${timestamp}] ${level.toUpperCase()}: ${message} ${metaString}`;
|
|
@@ -58,6 +60,21 @@ export class Adminizer {
|
|
|
58
60
|
this._emitter = new EventEmitter();
|
|
59
61
|
this.ormAdapters = ormAdapters;
|
|
60
62
|
}
|
|
63
|
+
getMiddleware() {
|
|
64
|
+
return (req, res) => {
|
|
65
|
+
this.app(req, res, (err) => {
|
|
66
|
+
if (err) {
|
|
67
|
+
console.error("Error in Adminizer", err);
|
|
68
|
+
res.writeHead(500, { 'Content-Type': 'text/plain' });
|
|
69
|
+
res.end('Internal Server Error');
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
res.writeHead(404, { 'Content-Type': 'text/plain' });
|
|
73
|
+
res.end('Route Not Found in Adminizer');
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
};
|
|
77
|
+
}
|
|
61
78
|
/**
|
|
62
79
|
* Vite middleware
|
|
63
80
|
* @protected
|
|
@@ -76,6 +93,9 @@ export class Adminizer {
|
|
|
76
93
|
async init(config) {
|
|
77
94
|
// set cookie parser
|
|
78
95
|
this.app.use(cookieParser());
|
|
96
|
+
if (!config || Object.keys(config).length === 0) {
|
|
97
|
+
Adminizer.log.warn(`Adminizer init > Adminizer config is emtpy`);
|
|
98
|
+
}
|
|
79
99
|
// Set vite middleware
|
|
80
100
|
const isViteDev = process.env.VITE_ENV === "dev";
|
|
81
101
|
if (isViteDev)
|
|
@@ -105,28 +125,30 @@ export class Adminizer {
|
|
|
105
125
|
set: configForms.set ?? defaultForms.set
|
|
106
126
|
}
|
|
107
127
|
};
|
|
108
|
-
// console.log("CONFIG", this.config)
|
|
109
128
|
this.modelHandler = new ModelHandler();
|
|
129
|
+
// TODO: 'hot reload' unbind models & unbind forms
|
|
110
130
|
await bindModels(this);
|
|
111
131
|
await bindForms(this);
|
|
112
132
|
this.config.rootPath = path.resolve(import.meta.dirname + "/..");
|
|
113
133
|
this.policyManager = new PolicyManager(this);
|
|
114
134
|
await this.policyManager.loadPolicies();
|
|
135
|
+
// TODO: 'hot reload' problem with deleting access right tokens
|
|
115
136
|
this.accessRightsHelper = new AccessRightsHelper(this);
|
|
137
|
+
// Helpers go to construtor
|
|
116
138
|
this.configHelper = new ConfigHelper(this);
|
|
117
139
|
this.menuHelper = new MenuHelper(this.config);
|
|
118
140
|
this.widgetHandler = new WidgetHandler(this);
|
|
119
141
|
bindExpressUtils(this.app);
|
|
120
142
|
bindReqFunctions(this);
|
|
121
|
-
// add install stepper policy to check unfilled settings
|
|
122
|
-
// bindInstallStepper(this); // TODO It is necessary to provide an opportunity to be inserted by an intermediary after authorization, but before the admin panel, in order to block the user from managing the Installstepper's admin panel.
|
|
123
143
|
// Bind assets
|
|
124
144
|
bindAssets(this.app, this.config.routePrefix);
|
|
125
|
-
if (
|
|
126
|
-
|
|
145
|
+
if (!process.env.VITEST) {
|
|
146
|
+
if ((process.env.DEV && process.env.NODE_ENV !== 'production') || process.env.ADMINPANEL_FORCE_BIND_DEV === "TRUE") {
|
|
147
|
+
bindDev(this);
|
|
148
|
+
}
|
|
127
149
|
}
|
|
128
150
|
await bindDashboardWidgets(this);
|
|
129
|
-
|
|
151
|
+
bindNavigation(this);
|
|
130
152
|
// bindMediaManager(this);
|
|
131
153
|
await bindAccessRights(this);
|
|
132
154
|
if (I18n.appendLocale) {
|
|
@@ -164,7 +186,7 @@ export class Adminizer {
|
|
|
164
186
|
this.logger.error(`${error.message}\nStack: ${error.stack}`);
|
|
165
187
|
}
|
|
166
188
|
else {
|
|
167
|
-
this.logger.error(args.join(" "));
|
|
189
|
+
this.logger.error(args.join(" ") + "\n" + new Error().stack);
|
|
168
190
|
}
|
|
169
191
|
},
|
|
170
192
|
debug: (...args) => this.logger.debug(args.join(" ")),
|
|
@@ -143,10 +143,10 @@ export declare abstract class AbstractMediaManager {
|
|
|
143
143
|
uloadAllowedTypes: string[];
|
|
144
144
|
dir: string;
|
|
145
145
|
/**
|
|
146
|
-
|
|
146
|
+
|
|
147
147
|
*/
|
|
148
148
|
allowSearch: boolean;
|
|
149
|
-
|
|
149
|
+
/**⚠️ above the settings that need to be implemented*/
|
|
150
150
|
/**
|
|
151
151
|
* id for mediamanager instance
|
|
152
152
|
*/
|
|
@@ -324,12 +324,9 @@
|
|
|
324
324
|
// try {
|
|
325
325
|
// await fs.promises.access(file);
|
|
326
326
|
// await fs.promises.unlink(file);
|
|
327
|
-
// console.log('The file was successfully deleted');
|
|
328
327
|
// } catch (err) {
|
|
329
328
|
// if (err.code === 'ENOENT') {
|
|
330
|
-
// console.log('The file does not exist');
|
|
331
329
|
// } else if (err.code === 'EPERM') {
|
|
332
|
-
// console.log('You do not have permission to delete this file');
|
|
333
330
|
// } else {
|
|
334
331
|
// console.error(`An error occurred: ${err}`);
|
|
335
332
|
// }
|
package/lib/requestProcessor.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { isObject } from "../helpers/JsUtils";
|
|
1
2
|
import { Adminizer } from "./Adminizer";
|
|
2
3
|
/**
|
|
3
4
|
* Default helper that will contain all methods
|
|
@@ -29,11 +30,17 @@ export class RequestProcessor {
|
|
|
29
30
|
}
|
|
30
31
|
for (let key in postParams) {
|
|
31
32
|
let field = fields[key];
|
|
32
|
-
if (
|
|
33
|
-
|
|
34
|
-
continue;
|
|
33
|
+
if (key === 'sort') {
|
|
34
|
+
console.log(fields[key], key, postParams[key]);
|
|
35
35
|
}
|
|
36
|
+
// if (field.model.type === 'boolean') {
|
|
37
|
+
// postParams[key] = ['true', '1', 'yes', "TRUE", "on"].includes(postParams[key].toString().toLowerCase());
|
|
38
|
+
// continue;
|
|
39
|
+
// }
|
|
36
40
|
if (field.model.type === 'number') {
|
|
41
|
+
if (isObject(field.config) && field.config.type === "boolean" && typeof postParams[key] === "boolean") {
|
|
42
|
+
postParams[key] = postParams[key] ? 1 : 0;
|
|
43
|
+
}
|
|
37
44
|
postParams[key] = parseFloat(postParams[key]);
|
|
38
45
|
}
|
|
39
46
|
if (field.model.type === 'json') {
|
package/lib/v4/DataAccessor.d.ts
CHANGED
|
@@ -4,13 +4,16 @@
|
|
|
4
4
|
import { Entity } from "../../interfaces/types";
|
|
5
5
|
import { ActionType } from "../../interfaces/adminpanelConfig";
|
|
6
6
|
import { Fields } from "../../helpers/fieldsHelper";
|
|
7
|
+
import { Adminizer } from "../Adminizer";
|
|
8
|
+
import { UserAP } from "models/UserAP";
|
|
7
9
|
export declare class DataAccessor {
|
|
8
10
|
private readonly adminizer;
|
|
9
|
-
user:
|
|
11
|
+
user: UserAP;
|
|
10
12
|
entity: Entity;
|
|
11
13
|
action: ActionType;
|
|
12
14
|
private fields;
|
|
13
|
-
|
|
15
|
+
private actionVerb;
|
|
16
|
+
constructor(adminizer: Adminizer, user: UserAP, entity: Entity, action: ActionType);
|
|
14
17
|
/**
|
|
15
18
|
* Retrieves the fields for the given entity based on action type,
|
|
16
19
|
* taking into account access rights and configuration settings.
|
package/lib/v4/DataAccessor.js
CHANGED
|
@@ -1,16 +1,19 @@
|
|
|
1
1
|
import { ControllerHelper } from "../../helpers/controllerHelper";
|
|
2
2
|
import { Adminizer } from "../Adminizer";
|
|
3
|
+
import { isObject } from "../../helpers/JsUtils";
|
|
3
4
|
export class DataAccessor {
|
|
4
5
|
adminizer;
|
|
5
6
|
user;
|
|
6
7
|
entity;
|
|
7
8
|
action;
|
|
8
9
|
fields = null;
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
this.
|
|
10
|
+
actionVerb;
|
|
11
|
+
constructor(adminizer, user, entity, action) {
|
|
12
|
+
this.adminizer = adminizer;
|
|
13
|
+
this.user = user;
|
|
12
14
|
this.entity = entity;
|
|
13
15
|
this.action = action;
|
|
16
|
+
this.actionVerb = getTokenAction(this.action);
|
|
14
17
|
}
|
|
15
18
|
/**
|
|
16
19
|
* Retrieves the fields for the given entity based on action type,
|
|
@@ -26,10 +29,19 @@ export class DataAccessor {
|
|
|
26
29
|
}
|
|
27
30
|
// get action and field configs
|
|
28
31
|
const actionConfig = ControllerHelper.findActionConfig(this.entity, this.action);
|
|
29
|
-
const fieldsConfig = this.entity.config
|
|
32
|
+
const fieldsConfig = this.entity.config?.fields || {};
|
|
30
33
|
const modelAttributes = this.entity.model.attributes;
|
|
34
|
+
const tokenId = `${this.actionVerb}-${this.entity.model.modelname}-${this.entity.type}`;
|
|
35
|
+
if (!this.adminizer.accessRightsHelper.hasPermission(tokenId, this.user)) {
|
|
36
|
+
Adminizer.log.debug(`getFieldsConfig > No access rights to ${this.actionVerb} ${this.entity.type}: ${this.entity.model.modelname}`);
|
|
37
|
+
return undefined;
|
|
38
|
+
}
|
|
31
39
|
const result = {};
|
|
32
40
|
Object.entries(modelAttributes).forEach(([key, modelField]) => {
|
|
41
|
+
// The fields that are recorded separately from the connection in some ORMs, because they are processed at the level above them.
|
|
42
|
+
if (modelAttributes[key].primaryKeyForAssociation === true) {
|
|
43
|
+
return undefined;
|
|
44
|
+
}
|
|
33
45
|
// Checks for short type in Waterline: fieldName: 'string'
|
|
34
46
|
if (typeof modelField === "string") {
|
|
35
47
|
modelField = { type: modelField };
|
|
@@ -45,6 +57,7 @@ export class DataAccessor {
|
|
|
45
57
|
}
|
|
46
58
|
// Getting base field config
|
|
47
59
|
let fldConfig = { key: key, title: key };
|
|
60
|
+
let associatedModelConfig = undefined;
|
|
48
61
|
/** Combine the field configuration from global and action-specific configs
|
|
49
62
|
* (now combine it before check, earlier was opposite).
|
|
50
63
|
* Action-specific config should overwrite the global one */
|
|
@@ -66,42 +79,52 @@ export class DataAccessor {
|
|
|
66
79
|
let populatedModelFieldsConfig = {};
|
|
67
80
|
if (modelField.type === "association" || modelField.type === "association-many") {
|
|
68
81
|
const modelName = modelField.model || modelField.collection;
|
|
82
|
+
const tokenId = `read-${modelName}-${this.entity.type}`;
|
|
83
|
+
if (!this.adminizer.accessRightsHelper.hasPermission(tokenId, this.user)) {
|
|
84
|
+
Adminizer.log.silly(`No access rights to ${this.entity.type}: ${this.entity.model.modelname}`);
|
|
85
|
+
return undefined;
|
|
86
|
+
}
|
|
69
87
|
if (modelName) {
|
|
70
|
-
const
|
|
71
|
-
if (
|
|
88
|
+
const model = this.adminizer.modelHandler.model.get(modelName);
|
|
89
|
+
if (model) {
|
|
72
90
|
populatedModelFieldsConfig = this.getAssociatedFieldsConfig(modelName);
|
|
91
|
+
let _modelConfig = this.adminizer.config.models[modelName];
|
|
92
|
+
if (!isObject(_modelConfig))
|
|
93
|
+
throw `type error: model config of ${modelName} is ${typeof (this.adminizer.config.models[modelName])} expected object`;
|
|
94
|
+
associatedModelConfig = _modelConfig;
|
|
73
95
|
}
|
|
74
96
|
else {
|
|
75
|
-
Adminizer.log.error(`Model not found: ${modelName}`);
|
|
97
|
+
Adminizer.log.error(`DataAccessor > getFieldsConfig > Model not found: ${modelName} when ${key}`);
|
|
76
98
|
}
|
|
77
99
|
}
|
|
78
100
|
}
|
|
79
101
|
// Set required and type attributes
|
|
80
|
-
fldConfig.required = Boolean(fldConfig.required
|
|
102
|
+
fldConfig.required = Boolean(fldConfig.required ?? modelField.required);
|
|
81
103
|
// Default type for field. Could be fetched form config file or file model if not defined in config file.
|
|
82
104
|
fldConfig.type = (fldConfig.type || modelField.type).toLowerCase();
|
|
83
105
|
// Normalize final configuration
|
|
84
106
|
fldConfig = this.adminizer.configHelper.normalizeFieldConfig(this.adminizer, fldConfig, key, modelField);
|
|
85
107
|
// Add new field to result set
|
|
86
|
-
result[key] = { config: fldConfig, model: modelField, populated: populatedModelFieldsConfig };
|
|
108
|
+
result[key] = { config: fldConfig, model: modelField, populated: populatedModelFieldsConfig, modelConfig: associatedModelConfig };
|
|
87
109
|
});
|
|
88
110
|
this.fields = result;
|
|
89
111
|
return result;
|
|
90
112
|
}
|
|
91
113
|
getAssociatedFieldsConfig(modelName) {
|
|
92
|
-
const
|
|
93
|
-
if (!
|
|
114
|
+
const model = this.adminizer.modelHandler.model.get(modelName);
|
|
115
|
+
if (!model || !this.adminizer.config.models[modelName] || typeof this.adminizer.config.models[modelName] === "boolean") {
|
|
94
116
|
return undefined;
|
|
95
117
|
}
|
|
96
118
|
// Check if user has access to the associated model
|
|
97
|
-
const
|
|
98
|
-
const tokenId = `${actionVerb}-${modelName}-${this.entity.type}`;
|
|
119
|
+
const tokenId = `read-${modelName}-${this.entity.type}`;
|
|
99
120
|
if (!this.adminizer.accessRightsHelper.hasPermission(tokenId, this.user)) {
|
|
100
|
-
Adminizer.log.
|
|
121
|
+
Adminizer.log.debug(`getAssociatedFieldsConfig > No access rights to ${this.actionVerb} ${this.entity.type}: ${modelName}`);
|
|
101
122
|
return undefined;
|
|
102
123
|
}
|
|
103
124
|
const associatedFields = {};
|
|
104
125
|
const modelConfig = this.adminizer.config.models[modelName];
|
|
126
|
+
if (!isObject(modelConfig))
|
|
127
|
+
throw `Type error ModelConfig should is object`;
|
|
105
128
|
// Get the main fields configuration
|
|
106
129
|
const fieldsConfig = modelConfig.fields || {};
|
|
107
130
|
// Merge action-specific fields configuration if it exists
|
|
@@ -129,7 +152,7 @@ export class DataAccessor {
|
|
|
129
152
|
}
|
|
130
153
|
const mergedFieldsConfig = { ...fieldsConfig, ...actionSpecificConfig };
|
|
131
154
|
// Loop through model attributes and apply access checks
|
|
132
|
-
Object.entries(
|
|
155
|
+
Object.entries(model.attributes).forEach(([key, modelField]) => {
|
|
133
156
|
const fieldConfig = mergedFieldsConfig[key];
|
|
134
157
|
// Creating a basic config
|
|
135
158
|
let fldConfig = { key: key, title: key };
|
|
@@ -146,6 +169,7 @@ export class DataAccessor {
|
|
|
146
169
|
config: fldConfig,
|
|
147
170
|
model: modelField,
|
|
148
171
|
populated: undefined, // set undefined for already populated fields
|
|
172
|
+
modelConfig: undefined
|
|
149
173
|
};
|
|
150
174
|
});
|
|
151
175
|
return associatedFields;
|
|
@@ -327,7 +351,7 @@ export class DataAccessor {
|
|
|
327
351
|
throw new Error(`No intermediate record found in model "${intermediateRelation.model}" associated with user ID "${this.user.id}"`);
|
|
328
352
|
}
|
|
329
353
|
// Ensure there is only one associated intermediate record
|
|
330
|
-
const intermediateRecordCount = await intermediateModel.count({ [via]: this.user.id });
|
|
354
|
+
const intermediateRecordCount = await intermediateModel.count({ [via]: this.user.id }, this);
|
|
331
355
|
if (intermediateRecordCount > 1) {
|
|
332
356
|
throw new Error(`Multiple intermediate records found in model "${intermediateRelation.model}" associated with user ID "${this.user.id}". ` +
|
|
333
357
|
`Expected only one`);
|
|
@@ -363,10 +387,11 @@ export class DataAccessor {
|
|
|
363
387
|
const relation = modelAttributes[accessField];
|
|
364
388
|
if (relation && ['userap', 'groupap'].includes(relation.model.toLowerCase())) {
|
|
365
389
|
if (relation.model.toLowerCase() === 'userap') {
|
|
366
|
-
|
|
390
|
+
if (!this.user.isAdministrator) {
|
|
391
|
+
updatedRecord[accessField] = this.user.id;
|
|
392
|
+
}
|
|
367
393
|
}
|
|
368
394
|
else if (relation.model.toLowerCase() === 'groupap') {
|
|
369
|
-
// Works only for users with only one group, later it can be resolved with group weight
|
|
370
395
|
const userGroups = this.user.groups || [];
|
|
371
396
|
if (userGroups.length === 1) {
|
|
372
397
|
updatedRecord[accessField] = userGroups[0].id;
|
|
@@ -409,7 +434,7 @@ export class DataAccessor {
|
|
|
409
434
|
throw new Error(`No intermediate record found in model "${intermediateRelation.model}" linking user "${this.user.id}" to the main record`);
|
|
410
435
|
}
|
|
411
436
|
// Ensure there is only one associated intermediate record
|
|
412
|
-
const intermediateRecordCount = await intermediateModel.count({ [via]: this.user.id });
|
|
437
|
+
const intermediateRecordCount = await intermediateModel.count({ [via]: this.user.id }, this);
|
|
413
438
|
if (intermediateRecordCount > 1) {
|
|
414
439
|
throw new Error(`Multiple intermediate records found in model "${intermediateRelation.model}" associated with user ID "${this.user.id}". ` +
|
|
415
440
|
`Expected only one`);
|
package/lib/v4/I18n.js
CHANGED
|
@@ -104,7 +104,9 @@ export class I18n {
|
|
|
104
104
|
return;
|
|
105
105
|
const file = this.locateFile(locale);
|
|
106
106
|
const tmpFile = `${file}.tmp`;
|
|
107
|
+
const dir = path.dirname(file);
|
|
107
108
|
try {
|
|
109
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
108
110
|
fs.writeFileSync(tmpFile, JSON.stringify(I18n.locales[locale], null, this.indent), "utf8");
|
|
109
111
|
fs.renameSync(tmpFile, file);
|
|
110
112
|
}
|
package/lib/v4/POWCaptcha.js
CHANGED
|
@@ -54,7 +54,6 @@ export class POWCaptcha {
|
|
|
54
54
|
if (!task || task.label !== label)
|
|
55
55
|
return false;
|
|
56
56
|
// Verify the solution (should be equal to puzzleOptions.message)
|
|
57
|
-
// console.log("QUESTION", `${taskId}:${label}`)
|
|
58
57
|
if (`${taskId}:${label}` === captchaSolution) {
|
|
59
58
|
this.deleteTask(taskId);
|
|
60
59
|
return true;
|