@opengis/admin 0.1.94 → 0.1.96

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. package/dist/{IconChevronDown-Ckqp2kHy.js → IconChevronDown-uM7Af3-i.js} +1 -1
  2. package/dist/{add-page-CA861uWt.js → add-page-BgPkyqnr.js} +18 -14
  3. package/dist/{admin-interface-CwikaMBm.js → admin-interface-x__pW8O9.js} +52 -51
  4. package/dist/{admin-view-DqduP4RF.js → admin-view-CApDgTHa.js} +153 -148
  5. package/dist/admin.js +1 -1
  6. package/dist/admin.umd.cjs +55 -55
  7. package/dist/{card-view-DZF9Tt0-.js → card-view-CUEAR-Gl.js} +1 -1
  8. package/dist/{edit-page-WEzJslvP.js → edit-page-Xu43ZBzj.js} +1 -1
  9. package/dist/{import-file-BW7hdzkG.js → import-file-CLrvcYj9.js} +5254 -5176
  10. package/dist/style.css +1 -1
  11. package/module/settings/card/admin.roles.table/access.hbs +3 -6
  12. package/module/settings/card/admin.roles.table/index.yml +12 -8
  13. package/module/settings/form/admin.roles.form.json +19 -17
  14. package/module/settings/menu.json +13 -3
  15. package/package.json +3 -3
  16. package/plugin.js +1 -1
  17. package/server/helpers/core/badge.js +16 -0
  18. package/server/helpers/core/buttonHelper.js +14 -0
  19. package/server/helpers/core/select.js +50 -0
  20. package/server/helpers/{controllers → core}/token.js +1 -1
  21. package/server/helpers/index.js +28 -0
  22. package/server/helpers/list/descriptionList.js +19 -10
  23. package/server/helpers/list/tableList.js +32 -19
  24. package/server/helpers/temp/contentList.js +58 -0
  25. package/server/helpers/temp/ifCond.js +101 -0
  26. package/server/helpers/utils/button.js +6 -0
  27. package/server/helpers/utils/buttonDel.js +6 -0
  28. package/server/plugins/access/funcs/getAdminAccess.js +1 -3
  29. package/server/routes/access/controllers/access.group.post.js +11 -6
  30. package/server/routes/access/index.mjs +1 -56
  31. package/server/routes/access/schema.mjs +58 -0
  32. package/server/routes/data/controllers/cardData.js +2 -2
  33. package/server/routes/notifications/funcs/sendNotification.js +27 -40
  34. package/server/helpers/controllers/badge.js +0 -12
  35. package/server/helpers/controllers/hb.js +0 -3
  36. package/server/helpers/controllers/map.js +0 -3
  37. package/server/helpers/controllers/mls.js +0 -3
  38. package/server/helpers/controllers/vue.js +0 -3
  39. package/server/helpers/index.mjs +0 -29
@@ -0,0 +1,101 @@
1
+ /**
2
+ * Перетинає два масиви
3
+ *
4
+ * @example
5
+ * // returns [1, 4, 5, 6]
6
+ * intersect([1,2,3,4,5,6],[1,4,5,6,7,8,9,11])
7
+ * @param {Array} a
8
+ * @param {Array} b
9
+ * @returns {Array} Returns new intersect array
10
+ */
11
+ function intersect(a, b) {
12
+ let aN = a; let bN = b;
13
+ if (b.length > a.length) {
14
+ [aN, bN] = [bN, aN];
15
+ }
16
+ return aN.filter((e) => bN.includes(e));
17
+ }
18
+
19
+ /**
20
+ * Створення шаблона або його частини внаслідок перевірки значення із веб-запиту та заздалегідь прописаного значення.
21
+ * Дозволяє змінювати наповнення сторінки через ряд перевірок. Є можливість внесення додаткової умови - що робити, коли умова не виконується.
22
+ *
23
+ * @summary Перевірка двох значень та виконання коду при виконанні умови, а також у всіх інших випадках.
24
+ * @priority 5
25
+ * @alias ifCond
26
+ * @type helper
27
+ * @tag condition
28
+ * @example
29
+ * {{#ifCond @root.req.domain 'in' 'help.softpro.ua,123'}} {{select user.uid data="get_full_uid"}} {{^}} Умова не виконана {{/ifCond}}
30
+ * @example
31
+ * {{#ifCond "1234567890" 'in' @root.user.group_list}} 1=1 {{^}} uid='{{uid}}' {{/ifCond}}
32
+ * @example
33
+ * {{#ifCond 'debug' 'in' @root.setting.core.setting}}Умова виконана{{^}}Не виконана умова{{/ifCond}}
34
+ * @param {Array} args Параметри для значень і умов
35
+ * @param {Array} args[0]] Перше значення
36
+ * @param {Array} args[1]] Оператор
37
+ * @param {Array} args[2]] Друге значення
38
+ * @returns {String} Returns HTML
39
+ */
40
+ export default function ifCond(v1, operator, v2, options) {
41
+ const __obj = this;
42
+
43
+ switch (operator) {
44
+ case '==':
45
+ return (v1 == v2) ? options.fn(__obj) : options.inverse(__obj);
46
+ case '!=':
47
+ return (v1 != v2) ? options.fn(__obj) : options.inverse(__obj);
48
+ case '===':
49
+ return (v1 === v2) ? options.fn(__obj) : options.inverse(__obj);
50
+ case '!==':
51
+ return (v1 !== v2) ? options.fn(__obj) : options.inverse(__obj);
52
+ case '&&':
53
+ return (v1 && v2) ? options.fn(__obj) : options.inverse(__obj);
54
+ case '||':
55
+ return (v1 || v2) ? options.fn(__obj) : options.inverse(__obj);
56
+ case '<':
57
+ return (v1 < v2) ? options.fn(__obj) : options.inverse(__obj);
58
+ case '<=':
59
+ return (v1 <= v2) ? options.fn(__obj) : options.inverse(__obj);
60
+ case '>':
61
+ return (v1 > v2) ? options.fn(__obj) : options.inverse(__obj);
62
+ case '>=':
63
+ return (v1 >= v2) ? options.fn(__obj) : options.inverse(__obj);
64
+ case '&':
65
+ return intersect(v1, v2).length !== 0
66
+ ? options.fn(__obj)
67
+ : options.inverse(__obj);
68
+ case '!~':
69
+ return (v1 || '').indexOf(v2) === -1
70
+ ? options.fn(__obj)
71
+ : options.inverse(__obj);
72
+ case '~':
73
+ return (v1 || '').indexOf(v2) !== -1
74
+ ? options.fn(__obj)
75
+ : options.inverse(__obj);
76
+ case 'period':
77
+ return (new Date(v1) < new Date() && new Date(v2) > new Date())
78
+ ? options.fn(__obj)
79
+ : options.inverse(__obj);
80
+ case 'in': {
81
+ if (typeof v2 === 'string') v2 = v2.split(',').map(item => item.trim());
82
+
83
+ if (Array.isArray(v1)) {
84
+ return v1.some((value) => v2.includes(value.toString()))
85
+ ? options.fn(__obj)
86
+ : options.inverse(__obj);
87
+ }
88
+ return v2.includes(v1?.toString())
89
+ ? options.fn(__obj)
90
+ : options.inverse(__obj);
91
+ }
92
+ case 'not in': {
93
+ if (typeof v2 === 'string') v2 = v2.split(',').map(item => item.trim());
94
+ return !v2.includes(v1?.toString())
95
+ ? options.fn(__obj)
96
+ : options.inverse(__obj);
97
+ }
98
+ default:
99
+ return options.inverse(__obj);
100
+ }
101
+ }
@@ -0,0 +1,6 @@
1
+
2
+
3
+ export default function button(token, title) {
4
+ return `<button onclick="window.v3plugin.$form({ token: '${token}' })"
5
+ class="inline-flex items-center px-2 py-1 text-sm font-medium text-white duration-300 bg-blue-600 border border-transparent rounded-lg gap-x-2 hover:bg-blue-700 hover:text-white">${title || 'Додати'}</button>`;
6
+ }
@@ -0,0 +1,6 @@
1
+
2
+
3
+ export default function button(token, title) {
4
+ return `<button onclick="window.v3plugin.$api({ api: '/api/table/${token}', method:'delete',confirm: { title:'Підтвердити операцію', text: 'Ви впевнені що хочете вилучити запис?', cancel: 'Скасувати', confirm : 'Виконати'} })"
5
+ class="inline-flex items-center px-2 py-1 text-sm font-medium text-white duration-300 bg-red-600 border border-transparent rounded-lg gap-x-2 hover:bg-red-700 hover:text-white">${title || 'Вилучити'}</button>`;
6
+ }
@@ -7,9 +7,7 @@ export default async function getAdminAccess({
7
7
  return { message: 'not enough params: id', status: 400 };
8
8
  }
9
9
 
10
- if (config?.auth?.disable) return;
11
-
12
- if (!config?.local && user?.user_type?.includes('admin')) {
10
+ if (!config?.local && !['admin'].includes(user.user_type, user.type)) {
13
11
  return { message: 'access restricted: admin', status: 403 };
14
12
  }
15
13
  }
@@ -7,8 +7,8 @@ export default async function accessGroupPost({
7
7
  pg = pgClients.client, params = {}, session = {}, body = {},
8
8
  }) {
9
9
  const { id } = params;
10
- const { user = {} } = session?.passport || {};
11
- const uid = config?.auth?.disable ? '1' : user?.uid;
10
+ const { user } = session?.passport || {};
11
+ if (!user) return { status: 403, message: 'access restricted' }
12
12
 
13
13
  // restrict access - admin only
14
14
  const check = await getAdminAccess({ id, user });
@@ -21,11 +21,16 @@ export default async function accessGroupPost({
21
21
  }
22
22
 
23
23
  if (routes?.length) {
24
- const q = `delete from admin.access where role_id='${id.replace(/'/g, "''")}';
25
- insert into admin.access(role_id,route_id,actions)
26
- values ${routes.filter((el) => el?.path && Object.hasOwn(el, 'actions')).map((el) => `('${id.replace(/'/g, "''")}','${el.path.replace(/'/g, "''")}',${el.actions?.length ? `'{ ${el.actions} }'::text[]` : 'null'})`)}`;
24
+ // delete from admin.access where role_id=$1;
25
+ await pg.query(`delete from admin.access where role_id=$1;`, [id]);
27
26
 
28
- await pg.query(q);
27
+
28
+ const q = `insert into admin.access(role_id,route_id,actions) values ($1,$2,$3)`;
29
+ await Promise.all(routes.filter(el => el.actions).map(el => pg.query(q, [id, el.path, el.actions])))
30
+
31
+ const { rows } = await pg.query(`select a.route_id as path, b.actions as actions from admin.routes a
32
+ left join admin.access b on a.route_id=b.route_id
33
+ where b.role_id=$1`, [id]);
29
34
 
30
35
  if (!users?.length) {
31
36
  return { message: { id, routes: rows }, status: 200 };
@@ -1,61 +1,6 @@
1
1
  import accessGroup from "./controllers/access.group.js";
2
2
  import accessGroupPost from "./controllers/access.group.post.js";
3
-
4
- const accessGroupSchema = {
5
- params: {
6
- type: 'object',
7
- properties: {
8
- id: { type: 'string', pattern: '^([\\d\\w._-]+)$' },
9
- },
10
- required: ['id'],
11
- },
12
- };
13
-
14
- const accessGroupPostSchema = {
15
- params: {
16
- type: 'object',
17
- properties: {
18
- id: { type: 'string', pattern: '^([\\d\\w._-]+)$' },
19
- },
20
- required: ['id'],
21
- },
22
- body: {
23
- type: 'object',
24
- properties: {
25
- users: {
26
- type: 'array',
27
- items: {
28
- type: 'object',
29
- properties: {
30
- id: {
31
- type: 'string',
32
- pattern: '^([\\d\\w._-]+)$',
33
- },
34
- },
35
- },
36
- },
37
- routes: {
38
- type: 'array',
39
- items: {
40
- type: 'object',
41
- properties: {
42
- path: {
43
- type: 'string',
44
- pattern: '^([\\d\\w._-]+)$',
45
- },
46
- actions: {
47
- type: 'array',
48
- items: {
49
- type: 'string',
50
- enum: ['get', 'add', 'edit', 'del'],
51
- },
52
- },
53
- },
54
- },
55
- },
56
- },
57
- },
58
- };
3
+ import { accessGroupPostSchema, accessGroupSchema } from "./schema.mjs";
59
4
 
60
5
  export default async function route(fastify) {
61
6
  fastify.get('/access-group/:id', { schema: accessGroupSchema }, accessGroup);
@@ -0,0 +1,58 @@
1
+ export default null;
2
+ export { accessGroupSchema, accessGroupPostSchema }
3
+
4
+ const accessGroupSchema = {
5
+ params: {
6
+ type: 'object',
7
+ properties: {
8
+ id: { type: 'string', pattern: '^([\\d\\w._-]+)$' },
9
+ },
10
+ required: ['id'],
11
+ },
12
+ };
13
+
14
+ const accessGroupPostSchema = {
15
+ params: {
16
+ type: 'object',
17
+ properties: {
18
+ id: { type: 'string', pattern: '^([\\d\\w._-]+)$' },
19
+ },
20
+ required: ['id'],
21
+ },
22
+ body: {
23
+ type: 'object',
24
+ properties: {
25
+ users: {
26
+ type: 'array',
27
+ items: {
28
+ type: 'object',
29
+ properties: {
30
+ id: {
31
+ type: 'string',
32
+ pattern: '^([\\d\\w._-]+)$',
33
+ },
34
+ },
35
+ },
36
+ },
37
+ routes: {
38
+ type: 'array',
39
+ /*items: {
40
+ type: 'object',
41
+ properties: {
42
+ path: {
43
+ type: 'string',
44
+ pattern: '^([\\d\\w._-]+)$',
45
+ },
46
+ actions: {
47
+ type: 'array',
48
+ items: {
49
+ type: 'string',
50
+ enum: ['get', 'add', 'edit', 'del'],
51
+ },
52
+ },
53
+ },
54
+ },*/
55
+ },
56
+ },
57
+ },
58
+ };
@@ -27,8 +27,8 @@ export default async function getCardData(req) {
27
27
  if (message) return { message };
28
28
 
29
29
  // conditions
30
- index.panels.forEach(el => {
31
- el.items = el.items.filter(el => conditions(el.conditions, rows[0]));
30
+ index.panels?.filter(el => el.items).forEach(el => {
31
+ el.items = el.items?.filter(el => conditions(el.conditions, rows[0]));
32
32
  })
33
33
  // tokens result
34
34
  const tokens = {};
@@ -45,9 +45,10 @@ export default async function notification({
45
45
 
46
46
  const keyTo = `${pg.options?.database}:mail:${provider[0]}:${to || ''}${id || ''}${table || ''}${title || ''}`;
47
47
  const uniqueTo = await rclient.setnx(keyTo, 1);
48
- logger.info('notification/sent', { keyTo, send: uniqueTo, nocache });
48
+
49
49
 
50
50
  if (!uniqueTo && !nocache) {
51
+ logger.file('notification/sent', { keyTo, send: uniqueTo, nocache });
51
52
  return `already sent: ${keyTo}`;
52
53
  }
53
54
  await rclient.expire(keyTo, 1000 * 600);
@@ -60,46 +61,32 @@ export default async function notification({
60
61
  return 'notification provider - must be array and not empty';
61
62
  }
62
63
 
63
- try {
64
- const html = await generateNotificationContent({
65
- pg, table, template, id, message, data,
64
+ const html = await generateNotificationContent({
65
+ pg, table, template, id, message, data,
66
+ });
67
+
68
+ if (provider.includes('email')) {
69
+ const files = Array.isArray(file) ? file : [file];
70
+ const attachments = files?.length && false ? await Promise.all(files?.filter((el) => el).map(async (el) => {
71
+ /* const content = await downloadFile(el, { buffer: true }); // ?
72
+ return {
73
+ filename: el.split('/').pop(),
74
+ encoding: 'base64',
75
+ content,
76
+ }; */
77
+ })) : [];
78
+
79
+ const toEmail = Array.isArray(to) ? to.map((emails) => emails.match(emailReg)?.join(',')) : to;
80
+
81
+ const result = await sendEmail({
82
+ attachments,
83
+ html,
84
+ subject: title,
85
+ from,
86
+ to: toEmail,
66
87
  });
67
88
 
68
- // return html;
69
-
70
- if (provider.includes('email')) {
71
- const files = Array.isArray(file) ? file : [file];
72
- const attachments = files?.length && false ? await Promise.all(files?.filter((el) => el).map(async (el) => {
73
- /* const content = await downloadFile(el, { buffer: true }); // ?
74
- return {
75
- filename: el.split('/').pop(),
76
- encoding: 'base64',
77
- content,
78
- }; */
79
- })) : [];
80
-
81
- const toEmail = Array.isArray(to) ? to.map((emails) => emails.match(emailReg)?.join(',')) : to;
82
-
83
- const result = await sendEmail({
84
- attachments,
85
- html,
86
- subject: title,
87
- from,
88
- to: toEmail,
89
- });
90
-
91
- logger.info('notification', {
92
- provider, title, to: toEmail, from, result, len: message?.length, files,
93
- });
94
-
95
- return result;
96
- }
97
- return null;
98
- }
99
- catch (err) {
100
- logger.info('notification/error', {
101
- provider, from, to, err: err.toString(),
102
- });
103
- throw err;
89
+ return result;
104
90
  }
91
+ return null;
105
92
  }
@@ -1,12 +0,0 @@
1
- export default async function badge(data, options = {}) {
2
- if (!data) return '-';
3
- //const cls = await getSelect(options.data, { val: data, full: 1 });
4
-
5
- return data;
6
- /*const html = cls?.map((el) => {
7
- const color = bscolor[el.color] || el.color || '#aaa';
8
- return `<span class="el-tag el-tag--mini" style="color:${color || '#aaa'};border-color:${color || '#aaa'};background:unset;">
9
- ${funcs.locale(el.id, { lang: root.lang, prefix: opt.data, type: 'cls' }) || el.text}</span>`;
10
- }).join(', ');
11
- return html;*/
12
- }
@@ -1,3 +0,0 @@
1
- export default async function _hb() {
2
- return '';
3
- }
@@ -1,3 +0,0 @@
1
- export default async function map() {
2
- return '';
3
- }
@@ -1,3 +0,0 @@
1
- export default async function _mls(data, options={}) {
2
- return data.hash?.ua || options?.hash?.ua || '';
3
- }
@@ -1,3 +0,0 @@
1
- export default async function _vue() {
2
- return '';
3
- }
@@ -1,29 +0,0 @@
1
- import _hb from "./controllers/hb.js";
2
- import _vue from "./controllers/vue.js";
3
- import map from "./controllers/map.js";
4
- import _mls from "./controllers/mls.js";
5
- import badge from "./controllers/badge.js";
6
- import token from "./controllers/token.js";
7
-
8
- // list
9
-
10
- import descriptionList from "./list/descriptionList.js";
11
- import tableList from "./list/tableList.js";
12
- import buttonHelper from "./list/buttonHelper.js";
13
-
14
- import { handlebars } from "@opengis/fastify-table/utils.js";
15
-
16
- export default async function route(fastify) {
17
- handlebars.registerHelper('_hb', _hb);
18
- handlebars.registerHelper('_vue', _vue);
19
- handlebars.registerHelper('map', map);
20
- handlebars.registerHelper('mls', _mls);
21
- handlebars.registerHelper('badge', badge);
22
- handlebars.registerHelper('token', token);
23
-
24
-
25
- // list
26
- handlebars.registerHelper('descriptionList', descriptionList);
27
- handlebars.registerHelper('tableList', tableList);
28
- handlebars.registerHelper('button', buttonHelper);
29
- }