adminizer 4.6.0 → 4.7.0-build.221
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 +12 -0
- package/assets/RelationDialogStack-CnHFOYyR.css +1 -0
- package/assets/RelationDialogStack-DI2bZxQX.js +20 -0
- package/assets/add-4213XScp.js +1 -0
- package/assets/add-group--F1XxfJ1.js +1 -0
- package/assets/add-group-form-DKRXC2n-.js +1 -0
- package/assets/add-user-b9HfMq7z.js +1 -0
- package/assets/add-user-form-UXAToWQd.js +1 -0
- package/assets/app-Clx8f5hd.css +1 -0
- package/assets/app-layout-C02ja4OI.js +1 -0
- package/assets/app-shell-D8wtkECO.js +1 -0
- package/assets/app-sidebar-BR5_zwxj.js +1 -0
- package/assets/app-sidebar-header-BZbIBQjq.js +1 -0
- package/assets/app.js +59 -7990
- package/assets/breadcrumbs-CODaqVkB.js +1 -0
- package/assets/catalog-6ZZjWdFs.js +6 -0
- package/assets/dashboard-CftAdKiH.js +3 -0
- package/assets/date-picker-DSOkNiNo.js +1 -0
- package/assets/del-modal-Cd4M7af8.js +1 -0
- package/assets/dynamic-controls-BsrJhPDY.js +1 -0
- package/assets/geo-json-CzR5JBXL.js +1 -0
- package/assets/handsontable-BI98OF5R.js +336 -0
- package/assets/history-DLHSU7Ak.js +1 -0
- package/assets/home-NcQ7nnU0.js +2 -0
- package/assets/icon-C2JNaLxH.js +1 -0
- package/assets/init-user-D2HSyXup.js +1 -0
- package/assets/input-error-CH2caTtO.js +1 -0
- package/assets/jsoneditor-DVNQmA6G.js +3869 -0
- package/assets/list-CFU0-TgN.js +4 -0
- package/assets/login-DFSLEO17.js +1 -0
- package/assets/manifest.json +246 -273
- package/assets/material-icon-Bx9pGQiQ.js +1 -0
- package/assets/media-manager-WcKe1EvD.js +6 -0
- package/assets/module-CT7PC6pc.js +1 -0
- package/assets/monaco-Bl4zdWCn.js +11 -0
- package/assets/nav-footer-BiSQkPt4.js +1 -0
- package/assets/nav-main-rTH0PfDw.js +1 -0
- package/assets/nav-user-Bj6cWs0a.js +1 -0
- package/assets/notification-Bi-PX87D.js +20 -0
- package/assets/pagination-render-AKJvTIRA.js +1 -0
- package/assets/register-BTP4uxsK.js +1 -0
- package/assets/ru-eW0WKkga.js +1 -0
- package/assets/theme-switcher-Dm8EOGzx.js +1 -0
- package/assets/toast-editor-DOg_gvSp.js +668 -0
- package/assets/user-filters-list-YUfR4XMI.js +1 -0
- package/assets/user-info-BgSbT02v.js +1 -0
- package/assets/user-menu-content-TQTXHIv6.js +1 -0
- package/assets/{vanilla-picker-l5rcX3cq.js → vanilla-picker-B3LgXoKV.js} +1 -7
- package/assets/welcome-vLwTu1R6.js +1 -0
- package/controllers/add.d.ts +1 -1
- package/controllers/add.js +20 -26
- package/controllers/addGroup.d.ts +1 -1
- package/controllers/addGroup.js +7 -15
- package/controllers/addUser.d.ts +1 -1
- package/controllers/addUser.js +10 -16
- package/controllers/catalog/Catalog.d.ts +1 -1
- package/controllers/catalog/Catalog.js +1 -10
- package/controllers/catalog/FrontendCatalogAdapter.d.ts +3 -3
- package/controllers/catalog/FrontendCatalogAdapter.js +0 -6
- package/controllers/catalog/FrontentCatalogAdapter.d.ts +3 -3
- package/controllers/catalog/FrontentCatalogAdapter.js +0 -4
- package/controllers/ckeditorUpload.js +2 -18
- package/controllers/dashboard.d.ts +1 -1
- package/controllers/dashboard.js +2 -5
- package/controllers/edit.js +24 -37
- package/controllers/editGroup.d.ts +1 -1
- package/controllers/editGroup.js +10 -21
- package/controllers/editUser.d.ts +1 -1
- package/controllers/editUser.js +11 -23
- package/controllers/exportData.d.ts +6 -0
- package/controllers/exportData.js +315 -0
- package/controllers/feed.d.ts +6 -0
- package/controllers/feed.js +73 -0
- package/controllers/feedback/feedbackController.d.ts +1 -1
- package/controllers/feedback/feedbackController.js +5 -7
- package/controllers/filter-fields/columns.d.ts +11 -0
- package/controllers/filter-fields/columns.js +106 -0
- package/controllers/filter-fields/filterFields.d.ts +10 -0
- package/controllers/filter-fields/filterFields.js +141 -0
- package/controllers/filter-fields/getAllUserFilters.d.ts +6 -0
- package/controllers/filter-fields/getAllUserFilters.js +115 -0
- package/controllers/filter-fields/groups.d.ts +5 -0
- package/controllers/filter-fields/groups.js +26 -0
- package/controllers/filter-fields/savedFilters.d.ts +25 -0
- package/controllers/filter-fields/savedFilters.js +317 -0
- package/controllers/getAllWidgets.d.ts +1 -1
- package/controllers/getAllWidgets.js +1 -9
- package/controllers/history-actions/HistoryController.js +6 -31
- package/controllers/initUser.js +6 -5
- package/controllers/inlineUpdate.d.ts +7 -0
- package/controllers/inlineUpdate.js +148 -0
- package/controllers/list.d.ts +1 -1
- package/controllers/list.js +383 -70
- package/controllers/listUserFilters.d.ts +5 -0
- package/controllers/listUserFilters.js +26 -0
- package/controllers/login.js +2 -2
- package/controllers/media-manager/mediaManagerApi.js +0 -9
- package/controllers/navigation/edit.js +3 -9
- package/controllers/notifications/NotificationController.d.ts +1 -1
- package/controllers/notifications/NotificationController.js +12 -36
- package/controllers/register.js +10 -9
- package/controllers/remove.js +10 -19
- package/controllers/timezones.d.ts +1 -1
- package/controllers/timezones.js +0 -6
- package/controllers/userApiKey.d.ts +7 -0
- package/controllers/userApiKey.js +36 -0
- package/controllers/view.js +14 -26
- package/controllers/welcome.d.ts +1 -1
- package/controllers/welcome.js +0 -4
- package/controllers/widgets/Action.d.ts +1 -1
- package/controllers/widgets/Action.js +1 -9
- package/controllers/widgets/Custom.d.ts +1 -1
- package/controllers/widgets/Custom.js +1 -9
- package/controllers/widgets/Info.d.ts +1 -1
- package/controllers/widgets/Info.js +1 -9
- package/controllers/widgets/filterInfo.d.ts +1 -0
- package/controllers/widgets/filterInfo.js +44 -0
- package/controllers/widgets/switch.d.ts +1 -1
- package/controllers/widgets/switch.js +1 -9
- package/controllers/widgetsDB.d.ts +1 -1
- package/controllers/widgetsDB.js +2 -8
- package/helpers/accessRightsHelper.d.ts +1 -1
- package/helpers/accessRightsHelper.js +5 -4
- package/helpers/apiKeyHelper.d.ts +5 -0
- package/helpers/apiKeyHelper.js +8 -0
- package/helpers/configHelper.js +12 -15
- package/helpers/controllerHelper.d.ts +14 -21
- package/helpers/controllerHelper.js +50 -83
- package/helpers/fieldsHelper.js +3 -3
- package/helpers/filterDatetimeHelper.d.ts +5 -0
- package/helpers/filterDatetimeHelper.js +84 -0
- package/helpers/inertiaActionsHelper.d.ts +2 -2
- package/helpers/inertiaActionsHelper.js +5 -4
- package/helpers/inertiaAddHelper.d.ts +3 -414
- package/helpers/inertiaAddHelper.js +39 -15
- package/helpers/inertiaGroupHelper.d.ts +2 -2
- package/helpers/inertiaGroupHelper.js +3 -3
- package/helpers/inertiaListHelper.d.ts +7 -3
- package/helpers/inertiaListHelper.js +26 -12
- package/helpers/inertiaMenuHelper.d.ts +1 -0
- package/helpers/inertiaMenuHelper.js +15 -3
- package/helpers/inertiaUserHelper.d.ts +3 -2
- package/helpers/inertiaUserHelper.js +7 -3
- package/helpers/menuHelper.d.ts +5 -2
- package/helpers/menuHelper.js +64 -12
- package/helpers/viteHelper.js +1 -2
- package/index.d.ts +6 -2
- package/index.js +6 -2
- package/interfaces/adminpanelConfig.d.ts +126 -39
- package/interfaces/internalModelAccess.d.ts +37 -0
- package/interfaces/internalModelAccess.js +1 -0
- package/interfaces/listQueryBuilder.d.ts +22 -0
- package/interfaces/listQueryBuilder.js +1 -0
- package/interfaces/queryCriteria.d.ts +54 -0
- package/interfaces/queryCriteria.js +1 -0
- package/interfaces/types.d.ts +1 -13
- package/lib/Adminizer.d.ts +4 -2
- package/lib/Adminizer.js +29 -10
- package/lib/DataAccessor.d.ts +8 -5
- package/lib/DataAccessor.js +89 -42
- package/lib/I18n.d.ts +5 -1
- package/lib/I18n.js +45 -19
- package/lib/MiddlewareManager.d.ts +8 -0
- package/lib/MiddlewareManager.js +53 -0
- package/lib/ai-assistant/OpenAiModelService.d.ts +3 -3
- package/lib/ai-assistant/OpenAiModelService.js +23 -24
- package/lib/catalog/Navigation.d.ts +1 -0
- package/lib/catalog/Navigation.js +12 -11
- package/lib/controls/jsoneditor/JsonEditor.d.ts +1 -2
- package/lib/controls/markdown/ToastUiEditor.d.ts +1 -2
- package/lib/feedback/FeedbackHandler.js +2 -2
- package/lib/filters/ConditionValidator.d.ts +107 -0
- package/lib/filters/ConditionValidator.js +483 -0
- package/lib/filters/CustomFilterHandler.d.ts +122 -0
- package/lib/filters/CustomFilterHandler.js +131 -0
- package/lib/filters/FilterCustomFieldHandler.d.ts +2 -0
- package/lib/filters/FilterCustomFieldHandler.js +2 -0
- package/lib/filters/FilterService.d.ts +82 -0
- package/lib/filters/FilterService.js +323 -0
- package/lib/filters/index.d.ts +6 -0
- package/lib/filters/index.js +4 -0
- package/lib/history-actions/AbstractHistoryAdapter.d.ts +5 -4
- package/lib/history-actions/AbstractHistoryAdapter.js +45 -30
- package/lib/history-actions/DefaultHistoryAdapter.d.ts +2 -0
- package/lib/history-actions/DefaultHistoryAdapter.js +12 -6
- package/lib/history-actions/HistoryHandler.js +1 -1
- package/lib/list-query-builder/ListQueryBuilder.d.ts +117 -0
- package/lib/list-query-builder/ListQueryBuilder.js +707 -0
- package/lib/media-manager/AbstractMediaManager.d.ts +9 -8
- package/lib/media-manager/DefaultMediaManager.d.ts +2 -0
- package/lib/media-manager/DefaultMediaManager.js +27 -15
- package/lib/media-manager/Items.d.ts +4 -1
- package/lib/media-manager/Items.js +62 -59
- package/lib/media-manager/MediaManagerHandler.js +1 -1
- package/lib/media-manager/helpers/MediaManagerHelper.d.ts +5 -1
- package/lib/media-manager/helpers/MediaManagerHelper.js +38 -4
- package/lib/model/AbstractModel.d.ts +33 -25
- package/lib/model/AbstractModel.js +54 -2
- package/lib/model/InternalModelAccessFactory.d.ts +18 -0
- package/lib/model/InternalModelAccessFactory.js +82 -0
- package/lib/model/ModelHandler.d.ts +6 -0
- package/lib/model/ModelHandler.js +14 -0
- package/lib/model/adapter/sequelize.d.ts +32 -10
- package/lib/model/adapter/sequelize.js +409 -62
- package/lib/model/adapter/typeorm.d.ts +62 -0
- package/lib/model/adapter/typeorm.js +777 -0
- package/lib/model/internalModelAccessToken.d.ts +1 -0
- package/lib/model/internalModelAccessToken.js +1 -0
- package/lib/model/internalModelRepository.d.ts +3 -0
- package/lib/model/internalModelRepository.js +4 -0
- package/lib/notifications/AbstractNotificationService.d.ts +3 -0
- package/lib/notifications/AbstractNotificationService.js +42 -36
- package/lib/notifications/GeneralNotificationService.js +37 -40
- package/lib/notifications/SystemNotificationService.js +33 -36
- package/lib/requestProcessor.js +0 -3
- package/lib/ui-i18n/getUiTranslations.d.ts +1 -0
- package/lib/ui-i18n/getUiTranslations.js +3 -0
- package/lib/ui-i18n/uiTranslationKeys.d.ts +6 -0
- package/lib/ui-i18n/uiTranslationKeys.js +268 -0
- package/lib/widgets/widgetHandler.d.ts +7 -2
- package/lib/widgets/widgetHandler.js +98 -18
- package/models/FilterAP.d.ts +116 -0
- package/models/FilterAP.js +68 -0
- package/models/FilterColumnAP.d.ts +32 -0
- package/models/FilterColumnAP.js +21 -0
- package/models/GroupAP.d.ts +1 -1
- package/models/HistoryActionsAP.d.ts +3 -3
- package/models/MediaManagerMetaAP.d.ts +1 -1
- package/models/NavigationAP.d.ts +1 -1
- package/models/UserAP.d.ts +6 -1
- package/models/UserAP.js +4 -0
- package/package.json +39 -32
- package/policies/authPolicies.d.ts +12 -0
- package/policies/authPolicies.js +104 -0
- package/policies/permissionResolvers.d.ts +12 -0
- package/policies/permissionResolvers.js +52 -0
- package/services/FeedService.d.ts +70 -0
- package/services/FeedService.js +334 -0
- package/system/Router.d.ts +1 -0
- package/system/Router.js +136 -59
- package/system/bindAccessRights.js +11 -30
- package/system/bindAuthorization.js +18 -18
- package/system/bindCors.js +16 -1
- package/system/bindCustomFilterHandlers.d.ts +2 -0
- package/system/bindCustomFilterHandlers.js +4 -0
- package/system/bindInertia.js +18 -61
- package/system/bindReqFunctions.js +10 -2
- package/system/bindTranslations.js +7 -3
- package/system/buildInternalModelAccess.d.ts +4 -0
- package/system/buildInternalModelAccess.js +59 -0
- package/system/defaults.js +18 -14
- package/system/routePolicies.d.ts +2 -0
- package/system/routePolicies.js +29 -0
- package/translations/en.json +151 -39
- package/translations/ru.json +211 -64
- package/ui/components/handsontable.js +13 -27
- package/ui/components/ui/dialog-stack.js +1 -3
- package/ui/components/ui/popover.js +1 -1
- package/ui/components/ui/sidebar.js +1 -1
- package/assets/RelationDialogStack-D9UVEF9s.js +0 -407
- package/assets/RelationDialogStack-DV8OITPR.css +0 -4
- package/assets/add-BlvzWQKF.js +0 -1
- package/assets/add-group-1Uoq9NWe.js +0 -1
- package/assets/add-group-form-B01gwDGu.js +0 -1
- package/assets/add-user-BQCAsaRy.js +0 -1
- package/assets/add-user-form-Cgwc9JkI.js +0 -1
- package/assets/app-DaOMy1nl.css +0 -72
- package/assets/app-layout-CAm60qoE.js +0 -1
- package/assets/app-shell-QWCtn9ye.js +0 -1
- package/assets/app-sidebar-CfaYbnSy.js +0 -1
- package/assets/app-sidebar-header-BsPFDhZ8.js +0 -1
- package/assets/breadcrumbs-CZZirDj8.js +0 -1
- package/assets/catalog-k5myk7fk.js +0 -6
- package/assets/dashboard-BkL9ybBw.js +0 -3
- package/assets/date-picker-B5AZ_7Q9.js +0 -1
- package/assets/del-modal-BoyXZloG.js +0 -1
- package/assets/dynamic-controls-k61T9W2P.js +0 -1
- package/assets/form-1WGY0YgG.js +0 -1
- package/assets/form-DJapG3qF.js +0 -1
- package/assets/geo-json-DsMUHo0l.js +0 -4
- package/assets/handsontable-PxYdjN8c.js +0 -298
- package/assets/history-CluyR-yJ.js +0 -1
- package/assets/home-Dug9zBzM.js +0 -2
- package/assets/icon-DfDLMG5f.js +0 -1
- package/assets/init-user-CF80MEnT.js +0 -1
- package/assets/input-error-DuuqFgZa.js +0 -1
- package/assets/jsoneditor-De1FvcYu.js +0 -3882
- package/assets/list-CuexshNt.js +0 -1
- package/assets/list-table-BsEWjTKY.js +0 -22
- package/assets/login-eDemYzN-.js +0 -1
- package/assets/material-icon-DMT8KdmE.js +0 -1
- package/assets/media-manager-DfYa_mT_.js +0 -14
- package/assets/module-Cd4Tm6uq.js +0 -1
- package/assets/monaco-BhBYtg3d.js +0 -11
- package/assets/nav-footer-D3olYxtz.js +0 -1
- package/assets/nav-main-BctqyzeV.js +0 -1
- package/assets/nav-user-Bn1Lt-BZ.js +0 -1
- package/assets/notification-D64qvni-.js +0 -27
- package/assets/pagination-render-DxD78ahJ.js +0 -1
- package/assets/register-349PwYbe.js +0 -1
- package/assets/theme-switcher-DfExsHW2.js +0 -1
- package/assets/toast-editor-ESK5iWPx.js +0 -845
- package/assets/user-info-DtBK5Kh8.js +0 -1
- package/assets/user-menu-content-0XYOCMaA.js +0 -1
- package/assets/welcome-PDp-gUei.js +0 -1
- package/controllers/form.d.ts +0 -1
- package/controllers/form.js +0 -86
- package/helpers/formHelper.d.ts +0 -6
- package/helpers/formHelper.js +0 -38
- package/helpers/inertiaFromHelper.d.ts +0 -11
- package/helpers/inertiaFromHelper.js +0 -98
- package/helpers/runtimeMode.d.ts +0 -1
- package/helpers/runtimeMode.js +0 -3
- package/lib/PolicyManager.d.ts +0 -8
- package/lib/PolicyManager.js +0 -53
- package/lib/datatable/NodeTable.d.ts +0 -49
- package/lib/datatable/NodeTable.js +0 -207
- package/lib/model/adapter/waterline.d.ts +0 -32
- package/lib/model/adapter/waterline.js +0 -180
- package/migrations/index.d.ts +0 -3
- package/migrations/index.js +0 -4
- package/migrations/knex/20250106000001_adminizer_init.d.ts +0 -8
- package/migrations/knex/20250106000001_adminizer_init.js +0 -164
- package/migrations/umzug/0001.d.ts +0 -7
- package/migrations/umzug/0001.js +0 -121
- package/migrations/umzugExports.d.ts +0 -2
- package/migrations/umzugExports.js +0 -9
- package/system/bindForms.d.ts +0 -2
- package/system/bindForms.js +0 -20
- /package/{policies → middlewares}/addMessages.d.ts +0 -0
- /package/{policies → middlewares}/addMessages.js +0 -0
- /package/{policies → middlewares}/checkAuth.d.ts +0 -0
- /package/{policies → middlewares}/checkAuth.js +0 -0
- /package/{policies → middlewares}/setLocale.d.ts +0 -0
- /package/{policies → middlewares}/setLocale.js +0 -0
package/lib/I18n.js
CHANGED
|
@@ -6,7 +6,10 @@ export class I18n {
|
|
|
6
6
|
devMode;
|
|
7
7
|
static locales = {};
|
|
8
8
|
defaultLocale;
|
|
9
|
+
defaultDirectory;
|
|
9
10
|
directory;
|
|
11
|
+
customDirectory;
|
|
12
|
+
missingDirectory;
|
|
10
13
|
extension;
|
|
11
14
|
cookieName;
|
|
12
15
|
sessionVarName;
|
|
@@ -16,15 +19,27 @@ export class I18n {
|
|
|
16
19
|
static localeCache = {};
|
|
17
20
|
static resMethods = ["__", "__n", "getLocale", "isPreferredLocale"];
|
|
18
21
|
constructor(options = {}) {
|
|
19
|
-
this.devMode = process.env.
|
|
22
|
+
this.devMode = process.env.ADMINIZER_ENV === "dev";
|
|
20
23
|
this.defaultLocale = options.defaultLocale || "en";
|
|
21
|
-
|
|
24
|
+
const runtimeDefaultTranslationsPath = path.resolve(import.meta.dirname, "../translations");
|
|
25
|
+
const sourceTranslationsPath = path.resolve(import.meta.dirname, "../../src/translations");
|
|
26
|
+
this.defaultDirectory = this.devMode
|
|
27
|
+
? (fs.existsSync(sourceTranslationsPath) ? sourceTranslationsPath : runtimeDefaultTranslationsPath)
|
|
28
|
+
: runtimeDefaultTranslationsPath;
|
|
29
|
+
this.customDirectory = options.directory ? path.resolve(options.directory) : undefined;
|
|
30
|
+
this.missingDirectory = options.missingDirectory ? path.resolve(options.missingDirectory) : undefined;
|
|
31
|
+
this.directory = this.customDirectory || this.defaultDirectory;
|
|
22
32
|
this.extension = options.extension || ".json";
|
|
23
33
|
this.cookieName = options.cookieName || "lang";
|
|
24
34
|
this.sessionVarName = options.sessionVarName || "locale";
|
|
25
35
|
this.indent = options.indent || "\t";
|
|
26
36
|
if (options.locales) {
|
|
27
|
-
options.locales.forEach((locale) =>
|
|
37
|
+
options.locales.forEach((locale) => {
|
|
38
|
+
this.readFile(locale, this.defaultDirectory);
|
|
39
|
+
if (this.customDirectory && this.customDirectory !== this.defaultDirectory) {
|
|
40
|
+
this.readFile(locale, this.customDirectory);
|
|
41
|
+
}
|
|
42
|
+
});
|
|
28
43
|
}
|
|
29
44
|
this.setLocale(this.defaultLocale);
|
|
30
45
|
}
|
|
@@ -75,16 +90,17 @@ export class I18n {
|
|
|
75
90
|
const localeDictionary = I18n.locales[locale] || {};
|
|
76
91
|
const translation = localeDictionary[singular];
|
|
77
92
|
if (!translation && this.devMode) {
|
|
78
|
-
|
|
79
|
-
I18n.locales[locale][singular] = plural ? { one: singular, other: plural } : singular;
|
|
80
|
-
this.writeFile(locale);
|
|
93
|
+
this.writeMissingTranslation(locale, singular, plural);
|
|
81
94
|
}
|
|
82
95
|
return translation || (plural ? { one: singular, other: plural } : singular);
|
|
83
96
|
}
|
|
84
|
-
readFile(locale) {
|
|
85
|
-
const file = this.locateFile(locale);
|
|
97
|
+
readFile(locale, directory = this.directory) {
|
|
98
|
+
const file = this.locateFile(locale, directory);
|
|
86
99
|
if (!this.devMode && I18n.localeCache[file]) {
|
|
87
|
-
I18n.locales[locale] =
|
|
100
|
+
I18n.locales[locale] = {
|
|
101
|
+
...(I18n.locales[locale] || {}),
|
|
102
|
+
...I18n.localeCache[file]
|
|
103
|
+
};
|
|
88
104
|
return;
|
|
89
105
|
}
|
|
90
106
|
try {
|
|
@@ -95,34 +111,44 @@ export class I18n {
|
|
|
95
111
|
...parsed
|
|
96
112
|
};
|
|
97
113
|
if (!this.devMode) {
|
|
98
|
-
I18n.localeCache[file] =
|
|
114
|
+
I18n.localeCache[file] = parsed;
|
|
99
115
|
}
|
|
100
116
|
}
|
|
101
117
|
catch (error) {
|
|
102
118
|
if (this.devMode) {
|
|
103
119
|
Adminizer.log.warn(`Failed to read locale file ${file}:`, error);
|
|
104
120
|
}
|
|
105
|
-
I18n.locales[locale] = {};
|
|
121
|
+
I18n.locales[locale] = I18n.locales[locale] || {};
|
|
106
122
|
}
|
|
107
123
|
}
|
|
108
|
-
|
|
109
|
-
|
|
124
|
+
locateFile(locale, directory = this.directory) {
|
|
125
|
+
return path.normalize(`${directory}/${locale}${this.extension}`);
|
|
126
|
+
}
|
|
127
|
+
writeMissingTranslation(locale, singular, plural) {
|
|
128
|
+
if (!this.missingDirectory)
|
|
110
129
|
return;
|
|
111
|
-
const file = this.locateFile(locale);
|
|
130
|
+
const file = this.locateFile(locale, this.missingDirectory);
|
|
112
131
|
const tmpFile = `${file}.tmp`;
|
|
113
132
|
const dir = path.dirname(file);
|
|
133
|
+
const value = plural ? { one: singular, other: plural } : singular;
|
|
114
134
|
try {
|
|
115
135
|
fs.mkdirSync(dir, { recursive: true });
|
|
116
|
-
|
|
136
|
+
let missingTranslations = {};
|
|
137
|
+
if (fs.existsSync(file)) {
|
|
138
|
+
const data = fs.readFileSync(file, "utf8");
|
|
139
|
+
missingTranslations = JSON.parse(data);
|
|
140
|
+
}
|
|
141
|
+
if (Object.prototype.hasOwnProperty.call(missingTranslations, singular)) {
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
missingTranslations[singular] = value;
|
|
145
|
+
fs.writeFileSync(tmpFile, JSON.stringify(missingTranslations, null, this.indent), "utf8");
|
|
117
146
|
fs.renameSync(tmpFile, file);
|
|
118
147
|
}
|
|
119
148
|
catch (error) {
|
|
120
|
-
Adminizer.log.error(`Failed to write
|
|
149
|
+
Adminizer.log.error(`Failed to write missing translation file ${file}:`, error);
|
|
121
150
|
}
|
|
122
151
|
}
|
|
123
|
-
locateFile(locale) {
|
|
124
|
-
return path.normalize(`${this.directory}/${locale}${this.extension}`);
|
|
125
|
-
}
|
|
126
152
|
static appendLocale(locale, data) {
|
|
127
153
|
I18n.locales[locale] = { ...I18n.locales[locale], ...data };
|
|
128
154
|
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { Adminizer } from "./Adminizer";
|
|
2
|
+
declare class MiddlewareManager {
|
|
3
|
+
private readonly _adminizer;
|
|
4
|
+
constructor(adminizer: Adminizer);
|
|
5
|
+
loadMiddlewares(): Promise<void>;
|
|
6
|
+
bindMiddlewares(middleware: MiddlewareType[], action: MiddlewareType): MiddlewareType[];
|
|
7
|
+
}
|
|
8
|
+
export default MiddlewareManager;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import * as fs from "fs";
|
|
2
|
+
import * as path from "path";
|
|
3
|
+
import { Adminizer } from "./Adminizer.js";
|
|
4
|
+
import { pathToFileURL } from "url";
|
|
5
|
+
class MiddlewareManager {
|
|
6
|
+
_adminizer;
|
|
7
|
+
constructor(adminizer) {
|
|
8
|
+
this._adminizer = adminizer;
|
|
9
|
+
}
|
|
10
|
+
async loadMiddlewares() {
|
|
11
|
+
try {
|
|
12
|
+
const middlewaresDirPath = path.join(import.meta.dirname, "../middlewares");
|
|
13
|
+
const middlewaresDir = fs.readdirSync(middlewaresDirPath);
|
|
14
|
+
for (const middlewareFile of middlewaresDir) {
|
|
15
|
+
if (path.extname(middlewareFile).toLowerCase() === ".js") {
|
|
16
|
+
const middlewarePath = path.join(middlewaresDirPath, middlewareFile);
|
|
17
|
+
const middleware = (await import(pathToFileURL(middlewarePath).href)).default;
|
|
18
|
+
if (typeof middleware === "function" &&
|
|
19
|
+
Array.isArray(this._adminizer.config.middlewares)) {
|
|
20
|
+
this._adminizer.config.middlewares.push(middleware);
|
|
21
|
+
}
|
|
22
|
+
else {
|
|
23
|
+
Adminizer.log.error(`Adminizer > Middleware ${middlewareFile} is not a function`);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
Adminizer.log.info("Adminizer middlewares loaded");
|
|
28
|
+
}
|
|
29
|
+
catch (e) {
|
|
30
|
+
Adminizer.log.error("Adminizer > Could not load middlewares", e);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
bindMiddlewares(middleware, action) {
|
|
34
|
+
const result = [];
|
|
35
|
+
const bindMiddleware = (middleware) => {
|
|
36
|
+
if (typeof middleware === "function") {
|
|
37
|
+
result.push(middleware);
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
Adminizer.log.error("AdminPanel: Middleware format unknown: " + middleware);
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
if (Array.isArray(middleware)) {
|
|
44
|
+
middleware.forEach(bindMiddleware);
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
bindMiddleware(middleware);
|
|
48
|
+
}
|
|
49
|
+
result.push(action);
|
|
50
|
+
return result;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
export default MiddlewareManager;
|
|
@@ -3,9 +3,9 @@ import { AiAssistantMessage } from '../../interfaces/types';
|
|
|
3
3
|
import { UserAP } from '../../models/UserAP';
|
|
4
4
|
import { Adminizer } from '../Adminizer';
|
|
5
5
|
import { ActionType } from '../../interfaces/adminpanelConfig';
|
|
6
|
-
import {
|
|
6
|
+
import { ModelResource } from '../../interfaces/types';
|
|
7
7
|
import { DataAccessor } from '../DataAccessor';
|
|
8
|
-
type DataAccessorFactory = (
|
|
8
|
+
type DataAccessorFactory = (modelResource: ModelResource, user: UserAP, action: ActionType) => DataAccessor;
|
|
9
9
|
export declare class OpenAiModelService extends AbstractAiModelService {
|
|
10
10
|
private readonly createAccessor;
|
|
11
11
|
constructor(adminizer: Adminizer, accessorFactory?: DataAccessorFactory);
|
|
@@ -13,7 +13,7 @@ export declare class OpenAiModelService extends AbstractAiModelService {
|
|
|
13
13
|
private handleCreate;
|
|
14
14
|
private parseInstruction;
|
|
15
15
|
private usageMessage;
|
|
16
|
-
private
|
|
16
|
+
private resolveModelResource;
|
|
17
17
|
private normalizeModelConfig;
|
|
18
18
|
private userHasPermission;
|
|
19
19
|
private getPermissionToken;
|
|
@@ -16,7 +16,7 @@ export class OpenAiModelService extends AbstractAiModelService {
|
|
|
16
16
|
name: 'OpenAI fixture agent',
|
|
17
17
|
description: 'Executes structured commands with DataAccessor using the current user permissions.',
|
|
18
18
|
});
|
|
19
|
-
this.createAccessor = accessorFactory ?? ((
|
|
19
|
+
this.createAccessor = accessorFactory ?? ((modelResource, user, action) => new DataAccessor(adminizer, user, modelResource, action));
|
|
20
20
|
}
|
|
21
21
|
async generateReply(prompt, _history, user) {
|
|
22
22
|
const instruction = this.parseInstruction(prompt);
|
|
@@ -31,28 +31,28 @@ export class OpenAiModelService extends AbstractAiModelService {
|
|
|
31
31
|
}
|
|
32
32
|
}
|
|
33
33
|
async handleCreate(instruction, user) {
|
|
34
|
-
const
|
|
35
|
-
if (!
|
|
36
|
-
return `Model "${instruction.
|
|
34
|
+
const modelResource = this.resolveModelResource(instruction.modelResource);
|
|
35
|
+
if (!modelResource || !modelResource.model) {
|
|
36
|
+
return `Model "${instruction.modelResource}" is not available in this project.`;
|
|
37
37
|
}
|
|
38
|
-
if (!this.userHasPermission(
|
|
39
|
-
return `User "${user.login}" does not have permission to create ${
|
|
38
|
+
if (!this.userHasPermission(modelResource, user, 'add')) {
|
|
39
|
+
return `User "${user.login}" does not have permission to create ${modelResource.name} records.`;
|
|
40
40
|
}
|
|
41
41
|
if (!instruction.payload || typeof instruction.payload !== 'object') {
|
|
42
42
|
return 'The "create" action requires a "data" object with field values.';
|
|
43
43
|
}
|
|
44
44
|
try {
|
|
45
|
-
const accessor = this.createAccessor(
|
|
46
|
-
const created = await
|
|
45
|
+
const accessor = this.createAccessor(modelResource, user, 'add');
|
|
46
|
+
const created = await modelResource.model.create(instruction.payload, accessor);
|
|
47
47
|
const preview = JSON.stringify(created, null, 2);
|
|
48
|
-
const recordId = this.extractPrimaryKey(created,
|
|
48
|
+
const recordId = this.extractPrimaryKey(created, modelResource);
|
|
49
49
|
const idMessage = recordId !== undefined ? ` (id: ${recordId})` : '';
|
|
50
|
-
return `Record created in ${
|
|
50
|
+
return `Record created in ${modelResource.name}${idMessage}:\n${preview}`;
|
|
51
51
|
}
|
|
52
52
|
catch (error) {
|
|
53
53
|
const message = error instanceof Error ? error.message : String(error);
|
|
54
54
|
Adminizer.log.error('OpenAI agent failed to create record', error);
|
|
55
|
-
return `Failed to create ${
|
|
55
|
+
return `Failed to create ${modelResource.name} record: ${message}`;
|
|
56
56
|
}
|
|
57
57
|
}
|
|
58
58
|
parseInstruction(prompt) {
|
|
@@ -69,15 +69,15 @@ export class OpenAiModelService extends AbstractAiModelService {
|
|
|
69
69
|
if (!['create', 'list', 'update', 'delete'].includes(action)) {
|
|
70
70
|
return null;
|
|
71
71
|
}
|
|
72
|
-
const
|
|
73
|
-
if (!
|
|
72
|
+
const modelResource = this.extractString(parsed, ['modelResource', 'model']);
|
|
73
|
+
if (!modelResource) {
|
|
74
74
|
return null;
|
|
75
75
|
}
|
|
76
76
|
const payload = this.extractObject(parsed, ['data', 'payload', 'record']);
|
|
77
77
|
const criteria = this.extractObject(parsed, ['criteria', 'where', 'filter']);
|
|
78
78
|
return {
|
|
79
79
|
action: action,
|
|
80
|
-
|
|
80
|
+
modelResource,
|
|
81
81
|
payload,
|
|
82
82
|
criteria,
|
|
83
83
|
};
|
|
@@ -93,14 +93,14 @@ export class OpenAiModelService extends AbstractAiModelService {
|
|
|
93
93
|
'```json',
|
|
94
94
|
'{',
|
|
95
95
|
' "action": "create",',
|
|
96
|
-
' "
|
|
96
|
+
' "modelResource": "Example",',
|
|
97
97
|
' "data": { "title": "Hello from the agent" }',
|
|
98
98
|
'}',
|
|
99
99
|
'```',
|
|
100
100
|
'The agent uses DataAccessor, so any field-level restrictions from your account are respected.',
|
|
101
101
|
].join('\n');
|
|
102
102
|
}
|
|
103
|
-
|
|
103
|
+
resolveModelResource(modelName) {
|
|
104
104
|
const models = this.adminizer.config.models;
|
|
105
105
|
if (!models) {
|
|
106
106
|
return null;
|
|
@@ -127,7 +127,6 @@ export class OpenAiModelService extends AbstractAiModelService {
|
|
|
127
127
|
return {
|
|
128
128
|
name: configName,
|
|
129
129
|
uri: `${this.adminizer.config.routePrefix}/model/${configName}`,
|
|
130
|
-
type: 'model',
|
|
131
130
|
config: normalizedConfig,
|
|
132
131
|
model,
|
|
133
132
|
};
|
|
@@ -148,20 +147,20 @@ export class OpenAiModelService extends AbstractAiModelService {
|
|
|
148
147
|
}
|
|
149
148
|
return { ...baseConfig, ...config };
|
|
150
149
|
}
|
|
151
|
-
userHasPermission(
|
|
152
|
-
const token = this.getPermissionToken(
|
|
150
|
+
userHasPermission(modelResource, user, action) {
|
|
151
|
+
const token = this.getPermissionToken(modelResource, action);
|
|
153
152
|
return this.adminizer.accessRightsHelper.hasPermission(token, user);
|
|
154
153
|
}
|
|
155
|
-
getPermissionToken(
|
|
154
|
+
getPermissionToken(modelResource, action) {
|
|
156
155
|
const verb = ACTION_TOKENS[action];
|
|
157
|
-
const modelName =
|
|
158
|
-
return `${verb}-${modelName}
|
|
156
|
+
const modelName = modelResource.model?.modelname ?? modelResource.config?.model ?? modelResource.name;
|
|
157
|
+
return `${verb}-${modelName}-model`.toLowerCase();
|
|
159
158
|
}
|
|
160
|
-
extractPrimaryKey(record,
|
|
159
|
+
extractPrimaryKey(record, modelResource) {
|
|
161
160
|
if (!record) {
|
|
162
161
|
return undefined;
|
|
163
162
|
}
|
|
164
|
-
const primaryKey =
|
|
163
|
+
const primaryKey = modelResource.model?.primaryKey ?? 'id';
|
|
165
164
|
return record[primaryKey];
|
|
166
165
|
}
|
|
167
166
|
extractString(source, keys) {
|
|
@@ -14,6 +14,7 @@ export declare class StorageService {
|
|
|
14
14
|
protected readonly adminizer: Adminizer;
|
|
15
15
|
readonly ready: Promise<void>;
|
|
16
16
|
constructor(adminizer: Adminizer, id: string, model: string);
|
|
17
|
+
private navigationModel;
|
|
17
18
|
initModel(): Promise<void>;
|
|
18
19
|
getId(): string;
|
|
19
20
|
buildTree(): Promise<any>;
|
|
@@ -13,17 +13,18 @@ export class StorageService {
|
|
|
13
13
|
this.model = model.toLowerCase();
|
|
14
14
|
this.ready = this.initModel();
|
|
15
15
|
}
|
|
16
|
+
navigationModel() {
|
|
17
|
+
return this.adminizer.modelHandler.internal("navigation").get(this.model);
|
|
18
|
+
}
|
|
16
19
|
async initModel() {
|
|
17
|
-
|
|
18
|
-
const navigation = await this.adminizer.modelHandler.model.get(this.model)["_findOne"]({ label: this.id });
|
|
20
|
+
const navigation = await this.navigationModel().findOne({ where: { label: this.id } });
|
|
19
21
|
if (navigation) {
|
|
20
22
|
Adminizer.log.info(`Found existing navigation: ${this.id}`);
|
|
21
23
|
await this.populateFromTree(navigation.tree);
|
|
22
24
|
}
|
|
23
25
|
else {
|
|
24
26
|
const newNavigation = { label: this.id, tree: [] };
|
|
25
|
-
|
|
26
|
-
await this.adminizer.modelHandler.model.get(this.model)["_create"](newNavigation);
|
|
27
|
+
await this.navigationModel().create(newNavigation);
|
|
27
28
|
Adminizer.log.info(`Created a new navigation: ${this.id}`);
|
|
28
29
|
}
|
|
29
30
|
}
|
|
@@ -99,8 +100,7 @@ export class StorageService {
|
|
|
99
100
|
async saveToDB() {
|
|
100
101
|
let tree = await this.buildTree();
|
|
101
102
|
try {
|
|
102
|
-
|
|
103
|
-
await this.adminizer.modelHandler.model.get(this.model)["_update"]({ label: this.id }, { tree: tree });
|
|
103
|
+
await this.navigationModel().update({ where: { label: this.id } }, { tree: tree });
|
|
104
104
|
}
|
|
105
105
|
catch (e) {
|
|
106
106
|
console.log(e);
|
|
@@ -208,12 +208,14 @@ class NavigationItem extends AbstractItem {
|
|
|
208
208
|
this.adminizer = adminizer;
|
|
209
209
|
this.storageServices = storageServices;
|
|
210
210
|
}
|
|
211
|
+
contentModel() {
|
|
212
|
+
return this.adminizer.modelHandler.internal("navigation").get(this.model);
|
|
213
|
+
}
|
|
211
214
|
async create(data, catalogId) {
|
|
212
215
|
let storage = this.storageServices.get(catalogId);
|
|
213
216
|
let storageData = null;
|
|
214
217
|
if (data._method === 'select') {
|
|
215
|
-
|
|
216
|
-
let record = await this.adminizer.modelHandler.model.get(this.model)["_findOne"]({ id: data.record });
|
|
218
|
+
let record = await this.contentModel().findOne({ where: { id: data.record } });
|
|
217
219
|
storageData = await this.dataPreparation({
|
|
218
220
|
record: record,
|
|
219
221
|
parentId: data.parentId,
|
|
@@ -275,13 +277,12 @@ class NavigationItem extends AbstractItem {
|
|
|
275
277
|
return await storage.findElementById(itemId);
|
|
276
278
|
}
|
|
277
279
|
/**
|
|
278
|
-
* @deprecated reason:
|
|
280
|
+
* @deprecated reason: transition to Inertia
|
|
279
281
|
* // TODO: need passing custom React module
|
|
280
282
|
*/
|
|
281
283
|
async getAddTemplate(req) {
|
|
282
284
|
let type = 'model.link';
|
|
283
|
-
|
|
284
|
-
let itemsDB = await this.adminizer.modelHandler.model.get(this.model)["_find"]({});
|
|
285
|
+
let itemsDB = await this.contentModel().find({});
|
|
285
286
|
let items = itemsDB.map((item) => {
|
|
286
287
|
return {
|
|
287
288
|
id: item.id,
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { AbstractControls, ControlType, Path, Config } from "../AbstractControls";
|
|
2
|
-
import { EditorOptions } from "@toast-ui/editor/types/editor";
|
|
3
2
|
import { Adminizer } from "../../Adminizer";
|
|
4
3
|
export declare class JsonEditor extends AbstractControls {
|
|
5
|
-
readonly config:
|
|
4
|
+
readonly config: Record<string, string | string[] | object | number | boolean>;
|
|
6
5
|
readonly name: string;
|
|
7
6
|
readonly path: Path;
|
|
8
7
|
readonly type: ControlType;
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { AbstractControls, ControlType, Path, Config } from "../AbstractControls";
|
|
2
|
-
import { EditorOptions } from "@toast-ui/editor/types/editor";
|
|
3
2
|
import { Adminizer } from "../../Adminizer";
|
|
4
3
|
export declare class ToastUiEditor extends AbstractControls {
|
|
5
|
-
readonly config:
|
|
4
|
+
readonly config: Record<string, string | string[] | object | number | boolean>;
|
|
6
5
|
readonly name: string;
|
|
7
6
|
readonly path: Path;
|
|
8
7
|
readonly type: ControlType;
|
|
@@ -8,8 +8,8 @@ export class FeedbackHandler {
|
|
|
8
8
|
}
|
|
9
9
|
register(handler) {
|
|
10
10
|
this.handler = handler;
|
|
11
|
-
const
|
|
12
|
-
bindFeedbackController(this.adminizer,
|
|
11
|
+
const middlewares = this.adminizer.config.middlewares ?? [];
|
|
12
|
+
bindFeedbackController(this.adminizer, middlewares);
|
|
13
13
|
Adminizer.log.info('FeedbackHandler registered');
|
|
14
14
|
}
|
|
15
15
|
isRegistered() {
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { FilterCondition, FilterOperator } from '../../models/FilterAP';
|
|
2
|
+
/**
|
|
3
|
+
* Security event types for logging suspicious filter attempts
|
|
4
|
+
*/
|
|
5
|
+
export type SecurityEventType = 'MAX_DEPTH_EXCEEDED' | 'TOO_MANY_CONDITIONS' | 'TOO_MANY_TOTAL_CONDITIONS' | 'DANGEROUS_SQL' | 'TOO_MANY_IN_VALUES' | 'STRING_TOO_LONG';
|
|
6
|
+
/**
|
|
7
|
+
* Security event details for logging
|
|
8
|
+
*/
|
|
9
|
+
export interface SecurityEvent {
|
|
10
|
+
type: SecurityEventType;
|
|
11
|
+
conditionId: string;
|
|
12
|
+
details: string;
|
|
13
|
+
timestamp: Date;
|
|
14
|
+
value?: any;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Logger interface for security events
|
|
18
|
+
*/
|
|
19
|
+
export interface SecurityLogger {
|
|
20
|
+
warn: (...args: any[]) => void;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Validation result
|
|
24
|
+
*/
|
|
25
|
+
export interface ValidationResult {
|
|
26
|
+
valid: boolean;
|
|
27
|
+
errors: ValidationError[];
|
|
28
|
+
securityEvents?: SecurityEvent[];
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Validation error
|
|
32
|
+
*/
|
|
33
|
+
export interface ValidationError {
|
|
34
|
+
conditionId: string;
|
|
35
|
+
field?: string;
|
|
36
|
+
message: string;
|
|
37
|
+
code: string;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Field configuration for validation
|
|
41
|
+
*/
|
|
42
|
+
export interface FieldConfig {
|
|
43
|
+
type: string;
|
|
44
|
+
required?: boolean;
|
|
45
|
+
maxLength?: number;
|
|
46
|
+
min?: number;
|
|
47
|
+
max?: number;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* ConditionValidator - validates filter conditions
|
|
51
|
+
*
|
|
52
|
+
* Validates:
|
|
53
|
+
* - Field existence
|
|
54
|
+
* - Operator validity for field type
|
|
55
|
+
* - Value type and format
|
|
56
|
+
* - Security limits (depth, array size, etc.)
|
|
57
|
+
*
|
|
58
|
+
* Security logging:
|
|
59
|
+
* Set ConditionValidator.logger to enable logging of suspicious attempts
|
|
60
|
+
*/
|
|
61
|
+
export declare class ConditionValidator {
|
|
62
|
+
private fieldsConfig;
|
|
63
|
+
private allowedFields?;
|
|
64
|
+
/**
|
|
65
|
+
* Static logger for security events
|
|
66
|
+
* Set this to enable logging of suspicious filter attempts
|
|
67
|
+
*/
|
|
68
|
+
static logger: SecurityLogger | null;
|
|
69
|
+
/**
|
|
70
|
+
* Collected security events during validation
|
|
71
|
+
*/
|
|
72
|
+
private securityEvents;
|
|
73
|
+
constructor(fieldsConfig: Record<string, FieldConfig>, allowedFields?: string[]);
|
|
74
|
+
/**
|
|
75
|
+
* Validate array of conditions
|
|
76
|
+
*/
|
|
77
|
+
validate(conditions: FilterCondition[]): ValidationResult;
|
|
78
|
+
/**
|
|
79
|
+
* Log a security event (suspicious filter attempt)
|
|
80
|
+
*/
|
|
81
|
+
private logSecurityEvent;
|
|
82
|
+
/**
|
|
83
|
+
* Validate single condition recursively
|
|
84
|
+
*/
|
|
85
|
+
private validateCondition;
|
|
86
|
+
/**
|
|
87
|
+
* Check if operator is valid for field type
|
|
88
|
+
*/
|
|
89
|
+
private isOperatorValidForType;
|
|
90
|
+
/**
|
|
91
|
+
* Validate value for operator and field type
|
|
92
|
+
*/
|
|
93
|
+
private validateValue;
|
|
94
|
+
/**
|
|
95
|
+
* Validate raw SQL for obvious injection attempts
|
|
96
|
+
*/
|
|
97
|
+
private validateRawSQL;
|
|
98
|
+
/**
|
|
99
|
+
* Get list of allowed operators for a field
|
|
100
|
+
*/
|
|
101
|
+
getOperatorsForField(fieldName: string): FilterOperator[];
|
|
102
|
+
/**
|
|
103
|
+
* Get list of allowed operators for a field type
|
|
104
|
+
*/
|
|
105
|
+
getOperatorsForType(fieldType: string): FilterOperator[];
|
|
106
|
+
}
|
|
107
|
+
export default ConditionValidator;
|