adminizer 4.1.0-build.2 → 4.1.0-build.21

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.
Files changed (197) hide show
  1. package/Readme.md +11 -1
  2. package/assets/{VanillaJSONEditor-FUe77pIA.js → VanillaJSONEditor-D-Lx670g.js} +1 -1
  3. package/assets/add-BP_u3Tjl.js +1 -0
  4. package/assets/add-form-nffmiYTh.js +1 -0
  5. package/assets/add-group-D4vcHlm-.js +1 -0
  6. package/assets/{add-group-form-dzadPSfL.js → add-group-form-gNJW11-q.js} +1 -1
  7. package/assets/add-user-DWh3Nas0.js +1 -0
  8. package/assets/add-user-form-BJ0FsZYJ.js +1 -0
  9. package/assets/{app-DMmad2-f.css → app-C3OdwOHy.css} +1 -1
  10. package/assets/{app-layout-D1m9Kvxq.js → app-layout-DYsRFUuP.js} +1 -1
  11. package/assets/{app-shell-BWMRMkHM.js → app-shell-Dd9Eknik.js} +1 -1
  12. package/assets/app-sidebar-BOmu6-Sl.js +1 -0
  13. package/assets/{app-sidebar-header-DLAFi13E.js → app-sidebar-header-CoXSzWxk.js} +1 -1
  14. package/assets/app.js +2 -2
  15. package/assets/{breadcrumbs-CQNon4Vl.js → breadcrumbs-BmAq4fHT.js} +1 -1
  16. package/assets/{button-CQ9t1kLz.js → button-C9B_5Jf_.js} +1 -1
  17. package/assets/{checkbox-W0nGAXIj.js → checkbox-Fg27sL_1.js} +1 -1
  18. package/assets/{compiler-runtime-tM4jBQ-T.js → compiler-runtime-hB6dAw2d.js} +1 -1
  19. package/assets/dashboard-BOltB2Hq.css +1 -0
  20. package/assets/dashboard-Ddh74NBQ.js +3 -0
  21. package/assets/{date-picker-B__dVVqj.js → date-picker-DI1cCO7K.js} +1 -1
  22. package/assets/{dropdown-menu-SEBnEIiL.js → dropdown-menu-Bhj17ENm.js} +1 -1
  23. package/assets/{field-renderer-CapylJU9.js → field-renderer-DVHZF6HS.js} +3 -3
  24. package/assets/form-BgWdwvz1.js +1 -0
  25. package/assets/form-DgtErfln.js +1 -0
  26. package/assets/{geo-json-CwteYDGB.js → geo-json-BjiyTtMu.js} +1 -1
  27. package/assets/{handsontable-BCnjOpBr.js → handsontable-4mjU_b0n.js} +1 -1
  28. package/assets/home-CHntBHJa.js +2 -0
  29. package/assets/{icon-Bz9BMaD0.js → icon-Dt0vBgDO.js} +1 -1
  30. package/assets/index-B8BS9wMC.js +1 -0
  31. package/assets/{index-DEk3sC8d.js → index-BKCgnGj_.js} +1 -1
  32. package/assets/{index-C0SL3SHw.js → index-BykbU6Ee.js} +1 -1
  33. package/assets/index-CaJgc5EZ.js +1 -0
  34. package/assets/{index-BcE9FUM6.js → index-Cgp8OfuI.js} +1 -1
  35. package/assets/{index-DTRTjOmh.js → index-Cw5o84pO.js} +1 -1
  36. package/assets/{init-user-D9mW-g14.js → init-user-JfCKJ5Ce.js} +1 -1
  37. package/assets/{input-DF7Ue23C.js → input-CvRbIbk4.js} +1 -1
  38. package/assets/{input-error-BBygona6.js → input-error-DMK7cAt7.js} +1 -1
  39. package/assets/{label-Z506NKsW.js → label-CSLFe9Bz.js} +1 -1
  40. package/assets/list-B2Oa5O_Q.js +1 -0
  41. package/assets/{list-table-DB1sEQLF.js → list-table-DA9MhywL.js} +5 -5
  42. package/assets/{login-DrGaTWhY.js → login-DQwGtdis.js} +1 -1
  43. package/assets/manifest.json +491 -470
  44. package/assets/{material-icon-CItZiB53.js → material-icon-BJg8o_fs.js} +1 -1
  45. package/assets/module-DWXp59Vg.js +1 -0
  46. package/assets/{monaco-editor-DqAqwxw4.js → monaco-editor-CJs0_GlD.js} +1 -1
  47. package/assets/{multi-select-oabtVhUP.js → multi-select-BvRpAW8r.js} +1 -1
  48. package/assets/{nav-footer-CM-yHiRs.js → nav-footer-Bs4dmN1d.js} +1 -1
  49. package/assets/{nav-main-Q3xofGRT.js → nav-main-Bq3IMk4C.js} +1 -1
  50. package/assets/{nav-user-Ds8i0Pa2.js → nav-user-CbB22J5O.js} +1 -1
  51. package/assets/{pagination-render-B57pOpFy.js → pagination-render-DuXDDbC_.js} +1 -1
  52. package/assets/{popover-I249Gg2O.js → popover-DtoGI2b1.js} +1 -1
  53. package/assets/{register-C9FQIDtS.js → register-BSogVF0h.js} +1 -1
  54. package/assets/{select-D1N8zRPY.js → select-BWepUw-9.js} +1 -1
  55. package/assets/{sidebar-4D-sX2l4.js → sidebar-CAHsHdjM.js} +2 -2
  56. package/assets/skeleton-COOcAA8f.js +1 -0
  57. package/assets/{sonner-Dzckw3U3.js → sonner-BI0IFOQN.js} +1 -1
  58. package/assets/{toast-editor-FbrFd1ft.js → toast-editor-CMK7QtF1.js} +1 -1
  59. package/assets/{tooltip-D2ehgLlB.js → tooltip-DHwpLKOI.js} +1 -1
  60. package/assets/{use-appearance-Co6mO0dV.js → use-appearance-DRfIqTgw.js} +1 -1
  61. package/assets/{use-window-size-B8l6Bpkf.js → use-window-size-h0Sh_NvX.js} +1 -1
  62. package/assets/{user-info-DBYoAJYJ.js → user-info-DFrmpJ4y.js} +1 -1
  63. package/assets/{user-menu-content-qkvdkUVd.js → user-menu-content-DPXQdERj.js} +1 -1
  64. package/assets/welcome-B4WCIXKf.js +1 -0
  65. package/controllers/add.js +3 -3
  66. package/controllers/addGroup.js +2 -4
  67. package/controllers/addUser.js +4 -6
  68. package/controllers/catalog/Catalog.js +2 -2
  69. package/controllers/catalog/FrontentCatalogAdapter.js +1 -2
  70. package/controllers/ckeditorUpload.js +2 -3
  71. package/controllers/dashboard.js +16 -2
  72. package/controllers/edit.js +3 -4
  73. package/controllers/editGroup.js +2 -4
  74. package/controllers/editUser.js +3 -5
  75. package/controllers/form.js +2 -3
  76. package/controllers/getAllWidgets.js +3 -3
  77. package/controllers/initUser.js +1 -2
  78. package/controllers/list.js +5 -5
  79. package/controllers/login.js +31 -15
  80. package/controllers/media-manager/mediaManagerAdapter.js +1 -2
  81. package/controllers/media-manager/mediaManagerApi.js +2 -2
  82. package/controllers/navigation/edit.js +2 -2
  83. package/controllers/register.js +1 -4
  84. package/controllers/remove.js +3 -3
  85. package/controllers/timezones.js +1 -1
  86. package/controllers/view.js +3 -3
  87. package/controllers/welcome.js +1 -1
  88. package/controllers/widgets/Action.js +2 -2
  89. package/controllers/widgets/Custom.js +2 -2
  90. package/controllers/widgets/Info.js +2 -2
  91. package/controllers/widgets/switch.js +2 -2
  92. package/controllers/widgetsDB.js +5 -5
  93. package/helpers/accessRightsHelper.d.ts +6 -2
  94. package/helpers/accessRightsHelper.js +21 -3
  95. package/helpers/configHelper.js +2 -1
  96. package/helpers/controllerHelper.js +1 -1
  97. package/helpers/fieldsHelper.d.ts +1 -1
  98. package/helpers/fieldsHelper.js +1 -1
  99. package/helpers/inertiaActionsHelper.js +1 -1
  100. package/helpers/inertiaAddHelper.d.ts +1 -1
  101. package/helpers/inertiaAddHelper.js +2 -0
  102. package/helpers/inertiaFromHelper.js +2 -0
  103. package/helpers/inertiaGroupHelper.d.ts +4 -2
  104. package/helpers/inertiaGroupHelper.js +1 -1
  105. package/helpers/inertiaListHelper.js +5 -5
  106. package/helpers/inertiaMenuHelper.js +2 -2
  107. package/helpers/inertiaUserHelper.d.ts +7 -1
  108. package/helpers/inertiaUserHelper.js +5 -1
  109. package/helpers/menuHelper.d.ts +2 -1
  110. package/helpers/menuHelper.js +8 -2
  111. package/index.d.ts +4 -1
  112. package/index.js +7 -1
  113. package/interfaces/adminpanelConfig.d.ts +19 -23
  114. package/interfaces/global.d.ts +8 -26
  115. package/interfaces/types.d.ts +1 -1
  116. package/lib/Adminizer.d.ts +2 -0
  117. package/lib/Adminizer.js +26 -6
  118. package/lib/catalog/AbstractCatalog.js +0 -1
  119. package/lib/catalog/Navigation.js +6 -7
  120. package/lib/datatable/NodeTable.js +2 -5
  121. package/lib/inertia/inertiaAdapter.js +0 -1
  122. package/lib/media-manager/AbstractMediaManager.d.ts +2 -2
  123. package/lib/media-manager/AbstractMediaManager.js +1 -1
  124. package/lib/media-manager/Items.js +0 -3
  125. package/lib/v4/DataAccessor.d.ts +5 -2
  126. package/lib/v4/DataAccessor.js +31 -14
  127. package/lib/v4/I18n.js +2 -0
  128. package/lib/v4/POWCaptcha.js +0 -1
  129. package/lib/v4/PolicyManager.js +0 -1
  130. package/lib/v4/helper/jwt.d.ts +10 -0
  131. package/lib/v4/helper/jwt.js +18 -0
  132. package/lib/v4/model/AbstractModel.d.ts +5 -1
  133. package/lib/v4/model/AbstractModel.js +2 -3
  134. package/lib/v4/model/ModelHandler.js +0 -1
  135. package/lib/v4/model/adapter/sequelize.d.ts +11 -2
  136. package/lib/v4/model/adapter/sequelize.js +451 -118
  137. package/lib/v4/model/adapter/waterline.js +5 -3
  138. package/lib/widgets/abstractAction.d.ts +1 -1
  139. package/lib/widgets/abstractCustom.d.ts +27 -12
  140. package/lib/widgets/abstractCustom.js +8 -2
  141. package/lib/widgets/abstractInfo.d.ts +1 -1
  142. package/lib/widgets/abstractInfo.js +1 -1
  143. package/lib/widgets/abstractLink.d.ts +1 -0
  144. package/lib/widgets/abstractSwitch.d.ts +1 -1
  145. package/lib/widgets/abstractWidgetBase.d.ts +1 -1
  146. package/lib/widgets/widgetHandler.d.ts +27 -3
  147. package/lib/widgets/widgetHandler.js +25 -25
  148. package/models/GroupAP.d.ts +8 -0
  149. package/models/NavigationAP.d.ts +5 -0
  150. package/models/UserAP.d.ts +24 -2
  151. package/models/UserAP.js +2 -2
  152. package/package.json +23 -11
  153. package/policies/checkAuth.js +4 -3
  154. package/policies/setLocale.js +2 -2
  155. package/system/Router.js +6 -14
  156. package/system/bindAccessRights.js +0 -4
  157. package/system/bindAuthorization.js +4 -5
  158. package/system/bindDev.js +1 -0
  159. package/system/bindInertia.js +9 -9
  160. package/system/bindMediaManager.js +0 -1
  161. package/system/bindModels.js +7 -2
  162. package/system/bindNavigation.js +0 -1
  163. package/system/bindReqFunctions.js +15 -0
  164. package/translations/ru.json +17 -8
  165. package/assets/add-ZITr43GJ.js +0 -1
  166. package/assets/add-form-CYOfr0Ef.js +0 -1
  167. package/assets/add-group-B332wN8K.js +0 -1
  168. package/assets/add-user-TC-mYdsB.js +0 -1
  169. package/assets/add-user-form-y2f_1_lM.js +0 -1
  170. package/assets/app-sidebar-BCtaEFGb.js +0 -1
  171. package/assets/dashboard-BR602KhL.js +0 -1
  172. package/assets/form-DOUNk3o2.js +0 -1
  173. package/assets/form-lOKv4Qbw.js +0 -1
  174. package/assets/home-Ch6QfTIt.js +0 -2
  175. package/assets/index-Cdb9ACvz.js +0 -1
  176. package/assets/index-K81GbF6O.js +0 -1
  177. package/assets/list-Qyd7ecQH.js +0 -1
  178. package/assets/module-DBaykv8l.js +0 -1
  179. package/assets/welcome-D2adQ8EU.js +0 -1
  180. package/controllers/processInstallFinalize.d.ts +0 -1
  181. package/controllers/processInstallFinalize.js +0 -16
  182. package/controllers/processInstallStep.d.ts +0 -1
  183. package/controllers/processInstallStep.js +0 -132
  184. package/lib/installStepper/InstallStepAbstract.d.ts +0 -52
  185. package/lib/installStepper/InstallStepAbstract.js +0 -69
  186. package/lib/installStepper/finalizeStep.d.ts +0 -21
  187. package/lib/installStepper/finalizeStep.js +0 -48
  188. package/lib/installStepper/installStepper.d.ts +0 -40
  189. package/lib/installStepper/installStepper.js +0 -195
  190. package/models/MediaManagerAP.d.ts +0 -46
  191. package/models/MediaManagerAP.js +0 -45
  192. package/models/MediaManagerAssociationsAP.d.ts +0 -28
  193. package/models/MediaManagerAssociationsAP.js +0 -27
  194. package/models/MediaManagerMetaAP.d.ts +0 -22
  195. package/models/MediaManagerMetaAP.js +0 -21
  196. package/system/bindInstallStepper.d.ts +0 -2
  197. package/system/bindInstallStepper.js +0 -23
@@ -1,15 +1,15 @@
1
1
  export default async function getAllWidgets(req, res) {
2
2
  if (req.adminizer.config.auth.enable) {
3
- if (!req.session.UserAP) {
3
+ if (!req.user) {
4
4
  return res.redirect(`${req.adminizer.config.routePrefix}/model/userap/login`);
5
5
  }
6
- else if (!req.adminizer.accessRightsHelper.hasPermission(`widgets`, req.session.UserAP)) {
6
+ else if (!req.adminizer.accessRightsHelper.hasPermission(`widgets`, req.user)) {
7
7
  return res.sendStatus(403);
8
8
  }
9
9
  }
10
10
  if (req.method.toUpperCase() === 'GET') {
11
11
  try {
12
- return res.json({ widgets: await req.adminizer.widgetHandler.getAll(req.session.UserAP) });
12
+ return res.json({ widgets: await req.adminizer.widgetHandler.getAll(req.user, req.i18n) });
13
13
  }
14
14
  catch (e) {
15
15
  return res.status(500).send({ error: e.message || 'Internal Server Error' });
@@ -29,12 +29,11 @@ export default async function initUser(req, res) {
29
29
  }
30
30
  try {
31
31
  Adminizer.log.debug(`Created admin`);
32
- let passwordHashed = generate(login + password);
32
+ let passwordHashed = generate(login + password + process.env.AP_PASSWORD_SALT);
33
33
  password = 'masked';
34
34
  // TODO refactor CRUD functions for DataAccessor usage
35
35
  await req.adminizer.modelHandler.model.get("UserAP")["_create"]({
36
36
  login: login,
37
- password: password,
38
37
  passwordHashed: passwordHashed,
39
38
  fullName: "Administrator",
40
39
  isActive: true,
@@ -9,14 +9,14 @@ export default async function list(req, res) {
9
9
  return res.status(404).send({ error: 'Not Found' });
10
10
  }
11
11
  if (req.adminizer.config.auth.enable) {
12
- if (!req.session.UserAP) {
12
+ if (!req.user) {
13
13
  return res.redirect(`${req.adminizer.config.routePrefix}/model/userap/login`);
14
14
  }
15
- else if (!req.adminizer.accessRightsHelper.hasPermission(`read-${entity.name}-model`, req.session.UserAP)) {
15
+ else if (!req.adminizer.accessRightsHelper.hasPermission(`read-${entity.name}-model`, req.user)) {
16
16
  return res.sendStatus(403);
17
17
  }
18
18
  }
19
- let dataAccessor = new DataAccessor(req, entity, "list");
19
+ let dataAccessor = new DataAccessor(req.adminizer, req.user, entity, "list");
20
20
  let fields = dataAccessor.getFieldsConfig();
21
21
  const header = inertiaListHelper(entity, req, fields);
22
22
  let start = "0";
@@ -46,8 +46,8 @@ export default async function list(req, res) {
46
46
  const searchMap = new Map();
47
47
  for (let i = 0; i < searchColumns.length; i++) {
48
48
  const column = searchColumns[i];
49
- const value = searchColumnValues[i] || ""; // Если нет значения, ставим пустую строку
50
- searchMap.set(column, value); // Если column повторяется, перезаписываем
49
+ const value = searchColumnValues[i] || "";
50
+ searchMap.set(column, value);
51
51
  }
52
52
  const searchPairs = Array.from(searchMap.entries()).map(([column, value]) => ({
53
53
  column,
@@ -1,6 +1,9 @@
1
1
  import { POWCaptcha } from "../lib/v4/POWCaptcha";
2
2
  import passwordHash from "password-hash";
3
3
  import { inertiaLoginHelper } from "../helpers/inertiaAutHelper";
4
+ import { Adminizer } from "../lib/Adminizer";
5
+ import { signUser } from "../lib/v4/helper/jwt";
6
+ import { serialize } from "cookie";
4
7
  export default async function login(req, res) {
5
8
  const powCaptcha = new POWCaptcha();
6
9
  if (req.originalUrl.indexOf("login") >= 0) {
@@ -11,11 +14,6 @@ export default async function login(req, res) {
11
14
  let login = req.body.login;
12
15
  let password = req.body.password;
13
16
  let captchaSolution = req.body.captchaSolution;
14
- // Verify CAPTCHA solution
15
- const isCaptchaValid = powCaptcha.check(captchaSolution, `login:${req.ip}`);
16
- if (!isCaptchaValid) {
17
- return inertiaAdminMessage(req, "Invalid CAPTCHA solution", 'captchaSolution');
18
- }
19
17
  let user;
20
18
  try {
21
19
  // TODO refactor CRUD functions for DataAccessor usage
@@ -28,11 +26,17 @@ export default async function login(req, res) {
28
26
  if (!user) {
29
27
  return res.sendStatus(404);
30
28
  }
31
- if (req.session.UserAP.isAdministrator) {
32
- req.session.adminPretender = req.session.UserAP;
33
- req.session.UserAP = user;
34
- return res.sendStatus(200);
29
+ if (req.user.isAdministrator) {
30
+ req.session.userPretended = user;
31
+ // return res.sendStatus(200);
32
+ return req.Inertia.redirect(`${req.adminizer.config.routePrefix}`);
35
33
  }
34
+ return req.Inertia.redirect(`${req.adminizer.config.routePrefix}/`);
35
+ }
36
+ // Verify CAPTCHA solution
37
+ const isCaptchaValid = powCaptcha.check(captchaSolution, `login:${req.ip}`);
38
+ if (!isCaptchaValid) {
39
+ return inertiaAdminMessage(req, "Invalid CAPTCHA solution", 'captchaSolution');
36
40
  }
37
41
  if (!user) {
38
42
  return inertiaAdminMessage(req, "Wrong username", 'login');
@@ -42,12 +46,18 @@ export default async function login(req, res) {
42
46
  //Here we use the captchaSolution key to output messages unrelated to the form fields.
43
47
  return inertiaAdminMessage(req, "Profile is not confirmed, please contact to administrator", 'captchaSolution');
44
48
  }
45
- if (passwordHash.verify(login + password, user.passwordHashed)) {
49
+ if (passwordHash.verify(login + password + process.env.AP_PASSWORD_SALT, user.passwordHashed)) {
46
50
  if (user.expires && Date.now() > Date.parse(user.expires)) {
47
51
  //Here we use the captchaSolution key to output messages unrelated to the form fields.
48
52
  return inertiaAdminMessage(req, "Profile expired, contact the administrator", 'captchaSolution');
49
53
  }
50
- req.session.UserAP = user;
54
+ const token = signUser(user, req.adminizer.jwtSecret);
55
+ res.setHeader('Set-Cookie', serialize('adminizer_jwt', token, {
56
+ httpOnly: true,
57
+ sameSite: 'lax',
58
+ path: '/',
59
+ maxAge: 60 * 60 * 24 * 7 * 2,
60
+ }));
51
61
  return req.Inertia.redirect(`${req.adminizer.config.routePrefix}`);
52
62
  }
53
63
  else {
@@ -69,17 +79,23 @@ export default async function login(req, res) {
69
79
  }
70
80
  }
71
81
  else if (req.originalUrl.indexOf("logout") >= 0) {
72
- if (req.session.adminPretender && req.session.adminPretender.id && req.session.UserAP && req.session.UserAP.id) {
73
- req.session.UserAP = req.session.adminPretender;
74
- req.session.adminPretender = {};
82
+ if (req.session.userPretended && req.session.userPretended.id && req.user && req.user.id) {
83
+ delete (req.session.userPretended);
75
84
  return req.Inertia.redirect(`${req.adminizer.config.routePrefix}/`);
76
85
  }
77
- req.session.UserAP = undefined;
86
+ req.user = undefined;
87
+ res.setHeader('Set-Cookie', serialize('adminizer_jwt', '', {
88
+ httpOnly: true,
89
+ sameSite: 'lax',
90
+ path: '/',
91
+ expires: new Date(0),
92
+ }));
78
93
  req.Inertia.redirect(`${req.adminizer.config.routePrefix}/model/userap/login`);
79
94
  }
80
95
  return res.status(404);
81
96
  }
82
97
  async function inertiaAdminMessage(req, message, messageType) {
98
+ Adminizer.log.warn(message);
83
99
  const powCaptcha = new POWCaptcha();
84
100
  const captchaTask = await powCaptcha.getJob(`login:${req.ip}`);
85
101
  let errors = {};
@@ -123,7 +123,6 @@ export class MediaManagerAdapter {
123
123
  }
124
124
  try {
125
125
  const item = await this.manager.upload(req.file, filename, origFileName, group);
126
- console.log(item);
127
126
  if (item) {
128
127
  return res.send({
129
128
  msg: "success",
@@ -150,7 +149,7 @@ export class MediaManagerAdapter {
150
149
  return;
151
150
  }
152
151
  catch (e) {
153
- console.log(e);
152
+ console.error(e);
154
153
  }
155
154
  }
156
155
  }
@@ -4,10 +4,10 @@ export async function mediaManagerController(req, res) {
4
4
  const method = req.method.toUpperCase();
5
5
  let id = req.params.id ? req.params.id : '';
6
6
  if (req.adminizer.config.auth.enable) {
7
- if (!req.session.UserAP) {
7
+ if (!req.user) {
8
8
  return res.redirect(`${req.adminizer.config.routePrefix}/model/userap/login`);
9
9
  }
10
- else if (!req.adminizer.accessRightsHelper.hasPermission(`catalog-${id}`, req.session.UserAP)) {
10
+ else if (!req.adminizer.accessRightsHelper.hasPermission(`catalog-${id}`, req.user)) {
11
11
  return res.sendStatus(403);
12
12
  }
13
13
  }
@@ -2,12 +2,12 @@ import { ControllerHelper } from "../../helpers/controllerHelper";
2
2
  import { DataAccessor } from "../../lib/v4/DataAccessor";
3
3
  export default async function edit(req, res) {
4
4
  if (req.adminizer.config.auth.enable) {
5
- if (!req.session.UserAP) {
5
+ if (!req.user) {
6
6
  return res.redirect(`${req.adminizer.config.routePrefix}/model/userap/login`);
7
7
  }
8
8
  }
9
9
  let entity = ControllerHelper.findEntityObject(req);
10
- let dataAccessor = new DataAccessor(req, entity, "edit");
10
+ let dataAccessor = new DataAccessor(req.adminizer, req.user, entity, "edit");
11
11
  let record = await entity.model.findOne({ id: req.params.id }, dataAccessor);
12
12
  return res.redirect(`${req.adminizer.config.routePrefix}/catalog/navigation/${record.label}`);
13
13
  }
@@ -5,7 +5,6 @@ export default async function register(req, res) {
5
5
  return res.redirect(`${req.adminizer.config.routePrefix}/`);
6
6
  }
7
7
  if (req.method.toUpperCase() === "POST") {
8
- // console.log("req.body", req.body);
9
8
  for (const key of ["login", "fullName", "password"]) {
10
9
  if (!req.body[key]) {
11
10
  let errors = {};
@@ -40,12 +39,11 @@ export default async function register(req, res) {
40
39
  }
41
40
  else {
42
41
  try {
43
- let passwordHashed = generate(req.body.login + req.body.password);
42
+ let passwordHashed = generate(req.body.login + req.body.password + process.env.AP_PASSWORD_SALT);
44
43
  let password = 'masked';
45
44
  // TODO refactor CRUD functions for DataAccessor usage
46
45
  let userap = await req.adminizer.modelHandler.model.get("UserAP")["_create"]({
47
46
  login: req.body.login,
48
- password: password,
49
47
  passwordHashed: passwordHashed,
50
48
  fullName: req.body.fullName,
51
49
  email: req.body.email,
@@ -53,7 +51,6 @@ export default async function register(req, res) {
53
51
  });
54
52
  // TODO refactor CRUD functions for DataAccessor usage
55
53
  let defaultUserGroup = await req.adminizer.modelHandler.model.get("GroupAP")["_findOne"]({ name: req.adminizer.config.registration.defaultUserGroup });
56
- console.log(userap);
57
54
  // TODO refactor CRUD functions for DataAccessor usage
58
55
  await req.adminizer.modelHandler.model.get("UserAP")["_updateOne"]({ id: userap.id }, {
59
56
  groups: [defaultUserGroup.id]
@@ -18,10 +18,10 @@ export default async function remove(req, res) {
18
18
  return res.redirect(`${req.adminizer.config.routePrefix}/${entity.uri}`);
19
19
  }
20
20
  if (req.adminizer.config.auth.enable) {
21
- if (!req.session.UserAP) {
21
+ if (!req.user) {
22
22
  return res.redirect(`${req.adminizer.config.routePrefix}/model/userap/login`);
23
23
  }
24
- else if (!req.adminizer.accessRightsHelper.hasPermission(`delete-${entity.name}-model`, req.session.UserAP)) {
24
+ else if (!req.adminizer.accessRightsHelper.hasPermission(`delete-${entity.name}-model`, req.user)) {
25
25
  return res.sendStatus(403);
26
26
  }
27
27
  }
@@ -31,7 +31,7 @@ export default async function remove(req, res) {
31
31
  let record;
32
32
  let dataAccessor;
33
33
  try {
34
- dataAccessor = new DataAccessor(req, entity, "remove");
34
+ dataAccessor = new DataAccessor(req.adminizer, req.user, entity, "remove");
35
35
  record = await entity.model.findOne({ id: req.params.id }, dataAccessor);
36
36
  }
37
37
  catch (e) {
@@ -1,6 +1,6 @@
1
1
  export default async function timezones(req, res) {
2
2
  if (req.adminizer.config.auth.enable) {
3
- if (!req.session.UserAP) {
3
+ if (!req.user) {
4
4
  return res.redirect(`${req.adminizer.config.routePrefix}/model/userap/login`);
5
5
  }
6
6
  }
@@ -18,14 +18,14 @@ export default async function view(req, res) {
18
18
  return res.status(404).send({ error: 'Not Found' });
19
19
  }
20
20
  if (req.adminizer.config.auth.enable) {
21
- if (!req.session.UserAP) {
21
+ if (!req.user) {
22
22
  return res.redirect(`${req.adminizer.config.routePrefix}/model/userap/login`);
23
23
  }
24
- else if (!req.adminizer.accessRightsHelper.hasPermission(`read-${entity.name}-model`, req.session.UserAP)) {
24
+ else if (!req.adminizer.accessRightsHelper.hasPermission(`read-${entity.name}-model`, req.user)) {
25
25
  return res.sendStatus(403);
26
26
  }
27
27
  }
28
- let dataAccessor = new DataAccessor(req, entity, "view");
28
+ let dataAccessor = new DataAccessor(req.adminizer, req.user, entity, "view");
29
29
  let fields = dataAccessor.getFieldsConfig();
30
30
  let record;
31
31
  try {
@@ -2,7 +2,7 @@
2
2
  * Welcome text
3
3
  */
4
4
  export default function welcome(req, res) {
5
- if (req.adminizer.config.auth.enable && !req.session.UserAP) {
5
+ if (!req.user) {
6
6
  return res.redirect(`${req.adminizer.config.routePrefix}/model/userap/login`);
7
7
  }
8
8
  let text = '';
@@ -4,10 +4,10 @@ export async function widgetActionController(req, res) {
4
4
  return res.status(404).send({ error: 'Not Found' });
5
5
  }
6
6
  if (req.adminizer.config.auth.enable) {
7
- if (!req.session.UserAP) {
7
+ if (!req.user) {
8
8
  return res.redirect(`${req.adminizer.config.routePrefix}/model/userap/login`);
9
9
  }
10
- else if (!req.adminizer.accessRightsHelper.hasPermission(`widget-${widgetId}`, req.session.UserAP)) {
10
+ else if (!req.adminizer.accessRightsHelper.hasPermission(`widget-${widgetId}`, req.user)) {
11
11
  return res.sendStatus(403);
12
12
  }
13
13
  }
@@ -4,10 +4,10 @@ export async function widgetCustomController(req, res) {
4
4
  return res.status(404).send({ error: 'Not Found' });
5
5
  }
6
6
  if (req.adminizer.config.auth.enable) {
7
- if (!req.session.UserAP) {
7
+ if (!req.user) {
8
8
  return res.redirect(`${req.adminizer.config.routePrefix}/model/userap/login`);
9
9
  }
10
- else if (!req.adminizer.accessRightsHelper.hasPermission(`widget-${widgetId}`, req.session.UserAP)) {
10
+ else if (!req.adminizer.accessRightsHelper.hasPermission(`widget-${widgetId}`, req.user)) {
11
11
  return res.sendStatus(403);
12
12
  }
13
13
  }
@@ -4,10 +4,10 @@ export async function widgetInfoController(req, res) {
4
4
  return res.status(404).send({ error: 'Not Found' });
5
5
  }
6
6
  if (req.adminizer.config.auth.enable) {
7
- if (!req.session.UserAP) {
7
+ if (!req.user) {
8
8
  return res.redirect(`${req.adminizer.config.routePrefix}/model/userap/login`);
9
9
  }
10
- else if (!req.adminizer.accessRightsHelper.hasPermission(`widget-${widgetId}`, req.session.UserAP)) {
10
+ else if (!req.adminizer.accessRightsHelper.hasPermission(`widget-${widgetId}`, req.user)) {
11
11
  return res.sendStatus(403);
12
12
  }
13
13
  }
@@ -4,10 +4,10 @@ export async function widgetSwitchController(req, res) {
4
4
  return res.status(404).send({ error: 'Not Found' });
5
5
  }
6
6
  if (req.adminizer.config.auth.enable) {
7
- if (!req.session.UserAP) {
7
+ if (!req.user) {
8
8
  return res.redirect(`${req.adminizer.config.routePrefix}/model/userap/login`);
9
9
  }
10
- else if (!req.adminizer.accessRightsHelper.hasPermission(`widget-${widgetId}`, req.session.UserAP)) {
10
+ else if (!req.adminizer.accessRightsHelper.hasPermission(`widget-${widgetId}`, req.user)) {
11
11
  return res.sendStatus(403);
12
12
  }
13
13
  }
@@ -2,17 +2,17 @@ export default async function widgetsDB(req, res) {
2
2
  let id = 0;
3
3
  let auth = req.adminizer.config.auth.enable;
4
4
  if (auth) {
5
- if (!req.session.UserAP) {
5
+ if (!req.user) {
6
6
  return res.redirect(`${req.adminizer.config.routePrefix}/model/userap/login`);
7
7
  }
8
- else if (!req.adminizer.accessRightsHelper.hasPermission(`widgets`, req.session.UserAP)) {
8
+ else if (!req.adminizer.accessRightsHelper.hasPermission(`widgets`, req.user)) {
9
9
  return res.sendStatus(403);
10
10
  }
11
- id = req.session.UserAP.id;
11
+ id = req.user.id;
12
12
  }
13
13
  if (req.method.toUpperCase() === 'GET') {
14
14
  try {
15
- let widgets = await req.adminizer.widgetHandler.getWidgetsDB(id, auth);
15
+ let widgets = await req.adminizer.widgetHandler.getWidgetsDB(id, auth, req.i18n);
16
16
  return res.json({ widgetsDB: widgets });
17
17
  }
18
18
  catch (e) {
@@ -25,7 +25,7 @@ export default async function widgetsDB(req, res) {
25
25
  }
26
26
  try {
27
27
  return res.json({
28
- userID: await req.adminizer.widgetHandler.setWidgetsDB(id, req.body.widgets, auth),
28
+ userID: await req.adminizer.widgetHandler.setWidgetsDB(id, req.body, auth),
29
29
  status: 'ok'
30
30
  });
31
31
  }
@@ -1,3 +1,4 @@
1
+ import { UserAP } from "models/UserAP";
1
2
  import { AccessRightsToken } from "../interfaces/types";
2
3
  import { Adminizer } from "../lib/Adminizer";
3
4
  export declare class AccessRightsHelper {
@@ -9,6 +10,9 @@ export declare class AccessRightsHelper {
9
10
  getTokens(): AccessRightsToken[];
10
11
  getTokensByDepartment(department: string): AccessRightsToken[];
11
12
  getAllDepartments(): string[];
12
- enoughPermissions(tokens: string[], user: ModelsAP["UserAP"]): boolean;
13
- hasPermission(tokenId: string, user: ModelsAP["UserAP"]): boolean;
13
+ enoughPermissions(tokens: string[], user: UserAP): boolean;
14
+ hasPermission(tokenId: string, user: UserAP): boolean;
15
+ }
16
+ export declare class GroupsAccessRightsHelper {
17
+ static hasAccess(user: UserAP, groupsAccessRights?: string[]): boolean;
14
18
  }
@@ -6,12 +6,13 @@ export class AccessRightsHelper {
6
6
  this.adminizer = adminizer;
7
7
  }
8
8
  registerToken(accessRightsToken) {
9
+ accessRightsToken.id = accessRightsToken.id.toLowerCase();
9
10
  if (!accessRightsToken.id || !accessRightsToken.name || !accessRightsToken.description || !accessRightsToken.department) {
10
11
  throw new Error("Adminpanel > Can not register token: Missed one or more required parameters");
11
12
  }
12
13
  for (let token of this._tokens) {
13
14
  if (token.id === accessRightsToken.id) {
14
- throw new Error("Adminpanel > Can not register token: Token with this id already registered");
15
+ throw new Error(`Adminpanel > Can not register token: Token with this id ["${token.id}"] already registered`);
15
16
  }
16
17
  }
17
18
  this._tokens.push(accessRightsToken);
@@ -42,6 +43,11 @@ export class AccessRightsHelper {
42
43
  return tokens.some((token) => this.hasPermission(token, user));
43
44
  }
44
45
  hasPermission(tokenId, user) {
46
+ if (!tokenId) {
47
+ Adminizer.log.error(`AccessRightsHelper > hasPermission no tokenId: ${tokenId}`);
48
+ return false;
49
+ }
50
+ tokenId = tokenId.toLowerCase();
45
51
  if (!this.adminizer.config.auth.enable) {
46
52
  return true;
47
53
  }
@@ -50,9 +56,21 @@ export class AccessRightsHelper {
50
56
  }
51
57
  const tokenIsValid = this._tokens.some((token) => token.id === tokenId);
52
58
  if (!tokenIsValid) {
53
- Adminizer.log.error("Adminpanel > Token is not valid");
59
+ Adminizer.log.error("Adminpanel > Token is not valid", tokenId, user.login);
54
60
  return false;
55
61
  }
56
- return user.groups.some((group) => group.tokens.includes(tokenId));
62
+ return user.groups.some((group) => group.tokens?.includes(tokenId));
63
+ }
64
+ }
65
+ export class GroupsAccessRightsHelper {
66
+ static hasAccess(user, groupsAccessRights) {
67
+ const userGroups = user.groups?.map(group => group.name.toLowerCase());
68
+ if (groupsAccessRights) {
69
+ const allowedGroups = groupsAccessRights.map(item => item.toLowerCase());
70
+ return userGroups?.some(group => allowedGroups.includes(group)) ?? false;
71
+ }
72
+ else {
73
+ return true;
74
+ }
57
75
  }
58
76
  }
@@ -77,7 +77,7 @@ export class ConfigHelper {
77
77
  }
78
78
  // Boolean notation: `true` means field is visible; `false` means field is hidden.
79
79
  if (typeof config === "boolean") {
80
- return config ? { title: key } : false;
80
+ return config ? { title: key } : { visible: false };
81
81
  }
82
82
  // String notation: Interpreted as the field title.
83
83
  if (typeof config === "string") {
@@ -86,6 +86,7 @@ export class ConfigHelper {
86
86
  // Object notation: Allows full customization of the field.
87
87
  if (typeof config === "object" && config !== null) {
88
88
  config.title = config.title || key;
89
+ config.visible = config.visible === undefined ? true : Boolean(config.visible);
89
90
  // For association types, determine display field by checking model attributes.
90
91
  if (["association", "association-many"].includes(config.type)) {
91
92
  let associatedModelAttributes = {};
@@ -84,7 +84,7 @@ export class ControllerHelper {
84
84
  const entityType = req.params.entityType;
85
85
  if (!entityType) {
86
86
  const extractedEntityType = req.originalUrl.split('/')[2];
87
- if (["form", "model", "wizard"].includes(extractedEntityType)) {
87
+ if (["form", "model"].includes(extractedEntityType)) {
88
88
  return extractedEntityType;
89
89
  }
90
90
  else {
@@ -10,7 +10,7 @@ export type Field = {
10
10
  type?: FieldsTypes;
11
11
  groupsAccessRights?: string[];
12
12
  } | string | boolean;
13
- /** for populated fields' configs */
13
+ /** For render associalitons fields */
14
14
  populated: {
15
15
  [key: string]: Field;
16
16
  } | undefined;
@@ -42,7 +42,7 @@ export class FieldsHelper {
42
42
  name: modelName, config: req.adminizer.config.models[modelName],
43
43
  model: Model, uri: `${req.adminizer.config.routePrefix}/model/${modelName}`, type: "model"
44
44
  };
45
- let dataAccessor = new DataAccessor(req, entity, action);
45
+ let dataAccessor = new DataAccessor(req.adminizer, req.user, entity, action);
46
46
  list = await Model.find({}, dataAccessor);
47
47
  }
48
48
  catch (e) {
@@ -4,7 +4,7 @@ export default function inertiaActionsHelper(actionType, entity, req) {
4
4
  const actions = req.adminizer.menuHelper.getGlobalActions(entity.config, actionType);
5
5
  if (actions && actions.length > 0) {
6
6
  actions.forEach(function (action) {
7
- if (req.adminizer.accessRightsHelper.hasPermission(action.accessRightsToken, req.session.UserAP)) {
7
+ if (req.adminizer.accessRightsHelper.hasPermission(action.accessRightsToken, req.user)) {
8
8
  resActions.push({
9
9
  link: action.link,
10
10
  id: action.id,
@@ -436,7 +436,7 @@ export declare function getControlsOptions(fieldConfig: BaseFieldConfig, req: Re
436
436
  };
437
437
  path: {};
438
438
  };
439
- export declare function inputText(type: string, isIn: string[]): "email" | "password" | "number" | "date" | "time" | "color" | "month" | "week" | "range" | "text" | "select" | "datetime-local";
439
+ export declare function inputText(type: string, isIn: string[]): "email" | "password" | "date" | "time" | "number" | "color" | "month" | "week" | "range" | "text" | "select" | "datetime-local";
440
440
  export declare function getControl(req: ReqType, type: ControlType, name: string | undefined, defaultControlName: string): AbstractControls;
441
441
  export declare function setSelectMany(isIn: string[], value: string[] | undefined): {
442
442
  initOptions: {
@@ -25,6 +25,8 @@ export default function inertiaAddHelper(req, entity, fields, record, view = fal
25
25
  continue;
26
26
  let field = fields[key];
27
27
  let fieldConfig = field.config;
28
+ if (!!fieldConfig.visible === false)
29
+ continue;
28
30
  const type = (fieldConfig.type || fieldConfig.type).toLowerCase();
29
31
  //@ts-ignore TODO: fix model validations
30
32
  const isIn = typeof fieldConfig.isIn === 'object' ? fieldConfig.isIn : (field.model && typeof { ...field.model.validations }.isIn === 'object' ? { ...field.model.validations }.isIn : []);
@@ -9,6 +9,8 @@ export default function inertiaFormHelper(req, postLink, formData) {
9
9
  };
10
10
  for (const key of Object.keys(formData)) {
11
11
  let field = formData[key];
12
+ if (field.visible === false)
13
+ continue;
12
14
  const type = (field.type || field.type).toLowerCase();
13
15
  const isIn = field.isIn ?? [];
14
16
  let label = field.title ?? '';
@@ -1,3 +1,5 @@
1
+ import { GroupAP } from "models/GroupAP";
2
+ import { UserAP } from "models/UserAP";
1
3
  import { AccessRightsToken, Entity, PropsField } from "../interfaces/types";
2
4
  interface groupedTokens {
3
5
  header: string;
@@ -20,7 +22,7 @@ interface listProps extends Record<string | number | symbol, unknown> {
20
22
  users: PropsField[];
21
23
  groupedTokens: groupedTokens[];
22
24
  }
23
- export declare function inertiaGroupHelper(entity: Entity, req: ReqType, users: ModelsAP["UserAP"][], groupedTokens: {
25
+ export declare function inertiaGroupHelper(entity: Entity, req: ReqType, users: UserAP[], groupedTokens: {
24
26
  [key: string]: AccessRightsToken[];
25
- }, group?: ModelsAP["GroupAP"], view?: boolean): listProps;
27
+ }, group?: GroupAP, view?: boolean): listProps;
26
28
  export {};
@@ -55,7 +55,7 @@ export function inertiaGroupHelper(entity, req, users, groupedTokens, group, vie
55
55
  label: token.name,
56
56
  tooltip: token.description,
57
57
  name: `token-checkbox-${token.id}`,
58
- value: group ? (group.tokens && group.tokens.includes(token.id)) : false,
58
+ value: group ? (group.tokens && group.tokens?.includes(token.id)) : false,
59
59
  type: 'checkbox'
60
60
  });
61
61
  }
@@ -24,22 +24,22 @@ export function inertiaListHelper(entity, req, fields) {
24
24
  searchBtn: req.i18n.__('Search'),
25
25
  resetBtn: req.i18n.__('Reset'),
26
26
  };
27
- if (entity.config.add && req.adminizer.accessRightsHelper.hasPermission(`create-${entity.name}-model`, req.session.UserAP)) {
27
+ if (entity.config.add && req.adminizer.accessRightsHelper.hasPermission(`create-${entity.name}-model`, req.user)) {
28
28
  props.crudActions.createTitle = req.i18n.__('create');
29
29
  }
30
- if (req.adminizer.accessRightsHelper.hasPermission(`update-${entity.name}-model`, req.session.UserAP)) {
30
+ if (req.adminizer.accessRightsHelper.hasPermission(`update-${entity.name}-model`, req.user)) {
31
31
  props.crudActions.editTitle = req.i18n.__('Edit');
32
32
  }
33
- if (req.adminizer.accessRightsHelper.hasPermission(`read-${entity.name}-model`, req.session.UserAP)) {
33
+ if (req.adminizer.accessRightsHelper.hasPermission(`read-${entity.name}-model`, req.user)) {
34
34
  props.crudActions.viewsTitle = req.i18n.__('View');
35
35
  }
36
- if (req.adminizer.accessRightsHelper.hasPermission(`delete-${entity.name}-model`, req.session.UserAP)) {
36
+ if (req.adminizer.accessRightsHelper.hasPermission(`delete-${entity.name}-model`, req.user)) {
37
37
  props.crudActions.deleteTitle = req.i18n.__('Delete');
38
38
  }
39
39
  props.actions = inertiaActionsHelper(actionType, entity, req);
40
40
  if (req.adminizer.menuHelper.hasInlineActions(entity.config, 'list')) {
41
41
  for (const inlineAction of req.adminizer.menuHelper.getInlineActions(entity.config, 'list')) {
42
- if (req.adminizer.accessRightsHelper.hasPermission(inlineAction.accessRightsToken, req.session.UserAP)) {
42
+ if (req.adminizer.accessRightsHelper.hasPermission(inlineAction.accessRightsToken, req.user)) {
43
43
  props.inlineActions.push({
44
44
  icon: inlineAction.icon,
45
45
  id: inlineAction.id,
@@ -5,7 +5,7 @@ export class InertiaMenuHelper {
5
5
  }
6
6
  getMenuItems(req) {
7
7
  let menu = [];
8
- for (const menuItem of this.adminizer.menuHelper.getMenuItems()) {
8
+ for (const menuItem of this.adminizer.menuHelper.getMenuItems(req.user)) {
9
9
  const menuItemTokens = menuItem.actions ? menuItem.actions.map(item => {
10
10
  return item.accessRightsToken;
11
11
  }).filter(item => {
@@ -13,7 +13,7 @@ export class InertiaMenuHelper {
13
13
  }) : [];
14
14
  if (menuItem.accessRightsToken)
15
15
  menuItemTokens.push(menuItem.accessRightsToken);
16
- if (this.adminizer.accessRightsHelper.enoughPermissions(menuItemTokens, req.session.UserAP)) {
16
+ if (this.adminizer.accessRightsHelper.enoughPermissions(menuItemTokens, req.user)) {
17
17
  menu.push(menuItem);
18
18
  }
19
19
  }
@@ -1,3 +1,5 @@
1
+ import { GroupAP } from "models/GroupAP";
2
+ import { UserAP } from "models/UserAP";
1
3
  import { Entity, PropsField } from "../interfaces/types";
2
4
  interface listProps extends Record<string | number | symbol, unknown> {
3
5
  edit: boolean;
@@ -16,6 +18,10 @@ interface listProps extends Record<string | number | symbol, unknown> {
16
18
  fields: PropsField[];
17
19
  groups: PropsField[];
18
20
  locales: Record<string, string>[];
21
+ userPretend: {
22
+ label: string;
23
+ postLink: string;
24
+ };
19
25
  }
20
- export declare function inertiaUserHelper(entity: Entity, req: ReqType, groups: ModelsAP["GroupAP"][], user?: ModelsAP["UserAP"], view?: boolean): listProps;
26
+ export declare function inertiaUserHelper(entity: Entity, req: ReqType, groups: GroupAP[], user?: UserAP, view?: boolean): listProps;
21
27
  export {};