@opengis/cms 0.0.51 → 0.0.52
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/dist/{ArticlesPage-BcR1hbds.js → ArticlesPage-Cddv2qte.js} +5 -5
- package/dist/{BuilderPage-CK_osM89.js → BuilderPage-BgcBJcw7.js} +158 -158
- package/dist/{CollectionsBreadcrumb.vue_vue_type_script_setup_true_lang-CnOe9ORD.js → CollectionsBreadcrumb.vue_vue_type_script_setup_true_lang-C-k8QGA-.js} +1 -1
- package/dist/{CollectionsPage-JfmrHNR_.js → CollectionsPage-d5MLIIAG.js} +3 -3
- package/dist/{CreateForm-BMOBeP4G.js → CreateForm-B0srHu5e.js} +2 -2
- package/dist/{EditCollectionPage-DtgvKGm-.js → EditCollectionPage-NUVatLkY.js} +65 -59
- package/dist/{EmptyData-DaZt_nAm.js → EmptyData-BSW20VKP.js} +5 -5
- package/dist/{MenuAddPage-Bf48Z-ah.js → MenuAddPage-Cn3JN04F.js} +3 -3
- package/dist/{MenuItemPage-BSwUW8tv.js → MenuItemPage-B0Th9EOe.js} +3 -3
- package/dist/{MenuPage-tJZtK46W.js → MenuPage-DQpD3IXx.js} +4 -4
- package/dist/{MonacoEditor.vue_vue_type_script_setup_true_lang-B1DrxmQX.js → MonacoEditor.vue_vue_type_script_setup_true_lang-CTKNG0qR.js} +2 -2
- package/dist/{UniversalTable.vue_vue_type_script_setup_true_lang-CJGTsd1V.js → UniversalTable.vue_vue_type_script_setup_true_lang-DW6O-xoY.js} +6 -6
- package/dist/{UniversalTablePagination.vue_vue_type_script_setup_true_lang-GYZd_gkA.js → UniversalTablePagination.vue_vue_type_script_setup_true_lang-DBIPBmpm.js} +4 -4
- package/dist/contentForm-C4Jp-FbQ.js +586 -0
- package/dist/{getField-C7EZs-YQ.js → getField-CKcz_b0t.js} +960 -933
- package/dist/index.js +10 -10
- package/dist/style.css +1 -1
- package/dist/{vuedraggable-CoAPPFYd.js → vuedraggable-mqqAYsch.js} +107 -107
- package/locales/en.json +6 -1
- package/locales/uk.json +4 -1
- package/package.json +4 -4
- package/server/functions/getContent.js +6 -15
- package/server/functions/getSearchData.js +2 -12
- package/server/functions/utils/mock.reply.js +56 -0
- package/server/routes/cms/controllers/getPermissions.js +15 -15
- package/server/routes/cms/controllers/listMedia.js +30 -3
- package/server/routes/cms/controllers/searchContent.js +2 -2
- package/server/routes/cms/controllers/setPermissions.js +49 -49
- package/server/templates/select/core.user_mentioned.sql +1 -1
- package/dist/contentForm-NcG15_5z.js +0 -553
package/locales/en.json
CHANGED
|
@@ -126,7 +126,10 @@
|
|
|
126
126
|
"dragToBuild": "Drag and drop content blocks here to build your collection structure",
|
|
127
127
|
"collectionCreated": "Collection created successfully",
|
|
128
128
|
"collectionCreationFailed": "Error creating collection",
|
|
129
|
-
"pinPublication": "Pin Publication"
|
|
129
|
+
"pinPublication": "Pin Publication",
|
|
130
|
+
"enLocalization": "EN localization",
|
|
131
|
+
"translateContentSuccess": "Content translated successfully",
|
|
132
|
+
"translateContentError": "Error translating content"
|
|
130
133
|
},
|
|
131
134
|
"articles": {
|
|
132
135
|
"title": "Articles",
|
|
@@ -478,6 +481,8 @@
|
|
|
478
481
|
"configure": "Configure",
|
|
479
482
|
"successTitle": "Success",
|
|
480
483
|
"successMessage": "Settings saved successfully",
|
|
484
|
+
"translateContentSuccess": "Content translated successfully",
|
|
485
|
+
"translateContentError": "Error translating content",
|
|
481
486
|
"errorTitle": "Error",
|
|
482
487
|
"errorMessage": "Error saving settings",
|
|
483
488
|
"generateNewKey": "Generate New Key",
|
package/locales/uk.json
CHANGED
|
@@ -126,7 +126,10 @@
|
|
|
126
126
|
"dragToBuild": "Перетягніть блоки контенту сюди, щоб створити структуру колекції",
|
|
127
127
|
"collectionCreated": "Колекція успішно створена",
|
|
128
128
|
"collectionCreationFailed": "Помилка при створенні колекції",
|
|
129
|
-
"pinPublication": "Закріпити публікацію"
|
|
129
|
+
"pinPublication": "Закріпити публікацію",
|
|
130
|
+
"enLocalization": "EN локалізація",
|
|
131
|
+
"translateContentSuccess": "Контент успішно перекладений",
|
|
132
|
+
"translateContentError": "Помилка при перекладі контенту"
|
|
130
133
|
},
|
|
131
134
|
"articles": {
|
|
132
135
|
"title": "Сторінки",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@opengis/cms",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.52",
|
|
4
4
|
"description": "cms",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"author": "Softpro",
|
|
@@ -41,10 +41,10 @@
|
|
|
41
41
|
"devDependencies": {
|
|
42
42
|
"@fastify/compress": "^8.1.0",
|
|
43
43
|
"@opengis/core": "^0.0.30",
|
|
44
|
-
"@opengis/fastify-table": "^2.0.
|
|
44
|
+
"@opengis/fastify-table": "^2.0.143",
|
|
45
45
|
"@opengis/filter": "^0.1.31",
|
|
46
46
|
"@opengis/form": "^0.0.109",
|
|
47
|
-
"@opengis/richtext": "0.0.
|
|
47
|
+
"@opengis/richtext": "0.0.45",
|
|
48
48
|
"@vueuse/head": "2.0.0",
|
|
49
49
|
"js-yaml": "^4.1.0",
|
|
50
50
|
"lucide-vue-next": "0.344.0",
|
|
@@ -65,4 +65,4 @@
|
|
|
65
65
|
"vitest": "3.2.4",
|
|
66
66
|
"vue-tsc": "^2.2.10"
|
|
67
67
|
}
|
|
68
|
-
}
|
|
68
|
+
}
|
|
@@ -1,25 +1,14 @@
|
|
|
1
1
|
import { createHash } from 'node:crypto';
|
|
2
2
|
|
|
3
3
|
import { config, getRedis, pgClients } from '@opengis/fastify-table/utils.js';
|
|
4
|
-
|
|
4
|
+
import { createMockReply } from './utils/mock.reply.js';
|
|
5
5
|
import getContent from '../routes/cms/controllers/getContent.js';
|
|
6
6
|
|
|
7
7
|
const pg = pgClients.client;
|
|
8
8
|
const rclient = getRedis();
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
status: (statusCode) => {
|
|
13
|
-
Object.assign(mockReply.response, { status: statusCode });
|
|
14
|
-
return mockReply;
|
|
15
|
-
},
|
|
16
|
-
send: (result) => {
|
|
17
|
-
Object.assign(mockReply.response, typeof result === 'object' ? result : { message: result });
|
|
18
|
-
return { ...mockReply.response };
|
|
19
|
-
},
|
|
20
|
-
};
|
|
21
|
-
|
|
22
|
-
export default async function getContentBySlug({ slug, filter, tags, state, locale, contextQuery, collection = 'pages', ttl = 3600, fields, limit = 12, page = 1 } = {}) {
|
|
10
|
+
|
|
11
|
+
export default async function getContentBySlug({ slug, filter, tags, state, locale, contextQuery, collection = 'pages', ttl = 3600, fields, limit = 12, page = 1, order, desc } = {}) {
|
|
23
12
|
if (!slug) {
|
|
24
13
|
// return { error: 'not enough params: slug', code: 400 };
|
|
25
14
|
}
|
|
@@ -43,7 +32,9 @@ export default async function getContentBySlug({ slug, filter, tags, state, loca
|
|
|
43
32
|
return { cache: true, ...cacheData };
|
|
44
33
|
}
|
|
45
34
|
|
|
46
|
-
const req = { pg: pgClients.client, params: { type: collection, id: slug }, query: { filter, tags, state, contextQuery, locale, fields, limit, page } };
|
|
35
|
+
const req = { pg: pgClients.client, params: { type: collection, id: slug }, query: { filter, tags, state, contextQuery, locale, fields, limit, page, order, desc } };
|
|
36
|
+
|
|
37
|
+
const mockReply = createMockReply();
|
|
47
38
|
const result = await getContent(req, mockReply, true);
|
|
48
39
|
|
|
49
40
|
if (ttl) {
|
|
@@ -1,24 +1,13 @@
|
|
|
1
1
|
import { createHash } from 'node:crypto';
|
|
2
2
|
|
|
3
3
|
import { config, getRedis, pgClients } from '@opengis/fastify-table/utils.js';
|
|
4
|
+
import { createMockReply } from './utils/mock.reply.js';
|
|
4
5
|
|
|
5
6
|
import searchContent from '../routes/cms/controllers/searchContent.js';
|
|
6
7
|
|
|
7
8
|
const pg = pgClients.client;
|
|
8
9
|
const rclient = getRedis();
|
|
9
10
|
|
|
10
|
-
const mockReply = {
|
|
11
|
-
response: {},
|
|
12
|
-
status: (statusCode) => {
|
|
13
|
-
Object.assign(mockReply.response, { status: statusCode });
|
|
14
|
-
return mockReply;
|
|
15
|
-
},
|
|
16
|
-
send: (result) => {
|
|
17
|
-
Object.assign(mockReply.response, typeof result === 'object' ? result : { message: result });
|
|
18
|
-
return { ...mockReply.response };
|
|
19
|
-
},
|
|
20
|
-
};
|
|
21
|
-
|
|
22
11
|
export default async function getSearchData({ page = 1, limit = 12, ttl = 3600, search, locale, tags, filter, contentType, asc } = {}) {
|
|
23
12
|
// check if any crud operations performed, if not - return cached response
|
|
24
13
|
const crudInc = await rclient.get(`pg:site.contents:crud`) || 0;
|
|
@@ -31,6 +20,7 @@ export default async function getSearchData({ page = 1, limit = 12, ttl = 3600,
|
|
|
31
20
|
return { cache: true, ...cacheData };
|
|
32
21
|
}
|
|
33
22
|
|
|
23
|
+
const mockReply = createMockReply();
|
|
34
24
|
const result = await searchContent({ pg, query: { search, locale, page, limit, tags, filter, contentType } }, mockReply);
|
|
35
25
|
|
|
36
26
|
if (ttl) {
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @template T
|
|
3
|
+
* @typedef {Object} MockReplyResponse
|
|
4
|
+
* @property {number} [status] - HTTP статус-код
|
|
5
|
+
* @property {T} [data] - Дані відповіді (якщо передано об'єкт)
|
|
6
|
+
* @property {string} [message] - Повідомлення (якщо передано рядок)
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Створює ізольований mock-об'єкт reply для тестування Fastify-хендлерів.
|
|
11
|
+
* Імітує методи `status()` та `send()`.
|
|
12
|
+
*
|
|
13
|
+
* @template T
|
|
14
|
+
* @returns {{
|
|
15
|
+
* status: (statusCode: number) => any,
|
|
16
|
+
* send: (result: T | string) => MockReplyResponse<T>
|
|
17
|
+
* }}
|
|
18
|
+
*/
|
|
19
|
+
export function createMockReply() {
|
|
20
|
+
/** @type {MockReplyResponse<any>} */
|
|
21
|
+
|
|
22
|
+
let response = {};
|
|
23
|
+
|
|
24
|
+
return {
|
|
25
|
+
/**
|
|
26
|
+
* Встановлює HTTP статус-код.
|
|
27
|
+
* Повертає той самий reply для чейнінгу.
|
|
28
|
+
*
|
|
29
|
+
* @param {number} statusCode
|
|
30
|
+
* @returns {any}
|
|
31
|
+
*/
|
|
32
|
+
status(statusCode) {
|
|
33
|
+
response.status = statusCode;
|
|
34
|
+
return this;
|
|
35
|
+
},
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Імітує Fastify reply.send().
|
|
39
|
+
* Якщо передано об'єкт — він додається як data.
|
|
40
|
+
* Якщо передано рядок — додається як message.
|
|
41
|
+
*
|
|
42
|
+
* @param {T | string} result
|
|
43
|
+
* @returns {MockReplyResponse<T>}
|
|
44
|
+
*/
|
|
45
|
+
send(result) {
|
|
46
|
+
response = {
|
|
47
|
+
...response,
|
|
48
|
+
...(typeof result === 'object'
|
|
49
|
+
? { data: result }
|
|
50
|
+
: { message: result }),
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
return response;
|
|
54
|
+
},
|
|
55
|
+
};
|
|
56
|
+
}
|
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
import { pgClients } from '@opengis/fastify-table/utils.js';
|
|
2
|
-
|
|
3
|
-
export default async function getPermissions(req, reply) {
|
|
4
|
-
const { pg = pgClients.client, params = {}, user = {} } = req;
|
|
5
|
-
|
|
6
|
-
if (!user?.uid) {
|
|
7
|
-
return reply.status(401).send('unauthorized');
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
const { rows = [] } = await pg.query(
|
|
11
|
-
`select * from site.permissions where ${params.id ? 'user_id=$1' : 'true'}`,
|
|
12
|
-
[params.id].filter(Boolean),
|
|
13
|
-
);
|
|
14
|
-
|
|
15
|
-
return { permissions: rows };
|
|
1
|
+
import { pgClients } from '@opengis/fastify-table/utils.js';
|
|
2
|
+
|
|
3
|
+
export default async function getPermissions(req, reply) {
|
|
4
|
+
const { pg = pgClients.client, params = {}, user = {} } = req;
|
|
5
|
+
|
|
6
|
+
if (!user?.uid) {
|
|
7
|
+
return reply.status(401).send('unauthorized');
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const { rows = [] } = await pg.query(
|
|
11
|
+
`select * from site.permissions where ${params.id ? 'user_id=$1' : 'true'}`,
|
|
12
|
+
[params.id].filter(Boolean),
|
|
13
|
+
);
|
|
14
|
+
|
|
15
|
+
return { permissions: rows };
|
|
16
16
|
}
|
|
@@ -23,7 +23,7 @@ const rootDir = path.resolve(getFolder(config, 'local'));
|
|
|
23
23
|
const dir = '/files';
|
|
24
24
|
|
|
25
25
|
const filesizeCache = {};
|
|
26
|
-
const
|
|
26
|
+
const fileMtimeCache = {};
|
|
27
27
|
|
|
28
28
|
mkdirSync(path.join(rootDir, dir), { recursive: true });
|
|
29
29
|
|
|
@@ -89,8 +89,33 @@ export default async function listMedia(req, reply) {
|
|
|
89
89
|
const filepath = media ? media.url : ('/files/' + (el.path.split('/files/')[1] ? el.path.split('/files/')[1] + '/' : '') + el.name);
|
|
90
90
|
|
|
91
91
|
if (!filesizeCache[filepath]) {
|
|
92
|
-
const { size } = await stat(path.join(rootDir, filepath));
|
|
92
|
+
const { mtime, size } = await stat(path.join(rootDir, filepath));
|
|
93
93
|
Object.assign(filesizeCache, { [filepath]: size });
|
|
94
|
+
mtime.setHours(0, 0, 0, 0); // strip hours from timestamp, leave only date
|
|
95
|
+
Object.assign(fileMtimeCache, { [filepath]: mtime });
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
const [, from, to] = q ? (q.match(/between\s+'(\d{4}-\d{2}-\d{2})'::date\s+and\s+'(\d{4}-\d{2}-\d{2})'::date/i) || []) : [];
|
|
100
|
+
|
|
101
|
+
// skip entirely if invalid dates passed to query.filter
|
|
102
|
+
if ((from && new Date(from).toString() === 'Invalid Date') || (to && new Date(to).toString() === 'Invalid Date')) {
|
|
103
|
+
return null;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// skip if file modification date does not match filter value
|
|
107
|
+
if (fileMtimeCache[filepath] && from && to && (new Date(from) > fileMtimeCache[filepath] || new Date(to) < fileMtimeCache[filepath])) {
|
|
108
|
+
return null;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const dt = q && !q.includes('between') ? query.filter.match(/\d{4}-\d{2}-\d{2}/)?.[0] : null;
|
|
112
|
+
const date = dt ? new Date(dt) : null;
|
|
113
|
+
// skip timezone offset
|
|
114
|
+
if (date) { date.setHours(0, 0, 0, 0); }
|
|
115
|
+
|
|
116
|
+
// filter by exact date
|
|
117
|
+
if (fileMtimeCache[filepath] && date && (new Date(date).getTime() !== fileMtimeCache[filepath].getTime())) {
|
|
118
|
+
return null;
|
|
94
119
|
}
|
|
95
120
|
|
|
96
121
|
const mime = getMimeType(el.name) || '';
|
|
@@ -116,10 +141,12 @@ export default async function listMedia(req, reply) {
|
|
|
116
141
|
url: filepath,
|
|
117
142
|
mime,
|
|
118
143
|
preview,
|
|
144
|
+
updated_at: fileMtimeCache[filepath].toISOString(),
|
|
119
145
|
}
|
|
120
146
|
}));
|
|
121
147
|
|
|
122
|
-
|
|
148
|
+
// filter empty items, such as filtered out by query.filter=updated_at (not from db, but from fs.stat)
|
|
149
|
+
Object.assign(result, { data: subdirs.concat(files.filter(Boolean)) });
|
|
123
150
|
return result;
|
|
124
151
|
|
|
125
152
|
}
|
|
@@ -94,11 +94,11 @@ export default async function searchContent({
|
|
|
94
94
|
const collections = contents.filter(el => el.content_type === 'collection' && el.table_name);
|
|
95
95
|
|
|
96
96
|
// const totals = await pg.query(`select json_object_agg(oid::regclass, reltuples) from pg_class`).then(el => el.rows?.[0]?.json_object_agg || {});
|
|
97
|
-
const allSingles = await pg.query(`select count(*)::int from site.contents where content_type_id in (select content_type_id from site.content_types where type = 'single'
|
|
97
|
+
const allSingles = await pg.query(`select count(*)::int from site.contents where content_type_id in (select content_type_id from site.content_types where type = 'single') and status='published'`).then(el => el.rows?.[0]?.count || 0);
|
|
98
98
|
const allCollectionTables = await pg.query(`select array_agg(table_name) from site.content_types where type = 'collection' and table_name is not null`).then(el => el.rows?.[0]?.array_agg || []);
|
|
99
99
|
|
|
100
100
|
const allCollections = await Promise.all(allCollectionTables.map(async tablename => {
|
|
101
|
-
const total = pg.queryCache ? await pg.queryCache(`select count(*)::int from data."${tablename}"`, { table: `data.${tablename}` }).then(el => el.rows?.[0]?.count || 0) : 0;
|
|
101
|
+
const total = pg.queryCache ? await pg.queryCache(`select count(*)::int from data."${tablename}" where status='published'`, { table: `data.${tablename}` }).then(el => el.rows?.[0]?.count || 0) : 0;
|
|
102
102
|
return total;
|
|
103
103
|
})).then(el => el.reduce((acc, curr) => acc + (curr || 0), 0) || 0);
|
|
104
104
|
|
|
@@ -1,50 +1,50 @@
|
|
|
1
|
-
import { logger, pgClients, dataInsert } from '@opengis/fastify-table/utils.js';
|
|
2
|
-
|
|
3
|
-
export default async function setPermissions(req, reply) {
|
|
4
|
-
const { pg = pgClients.client, params = {}, user = {}, body = {} } = req;
|
|
5
|
-
|
|
6
|
-
if (!user?.uid) {
|
|
7
|
-
return reply.status(401).send('unauthorized');
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
if (!params.id) {
|
|
11
|
-
return reply.status(400).send('not enough params: id');
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
const client = await pg.connect()
|
|
15
|
-
const result = {};
|
|
16
|
-
try {
|
|
17
|
-
await client.query('BEGIN');
|
|
18
|
-
|
|
19
|
-
const { rowCount = 0 } = await client.query(
|
|
20
|
-
`delete from site.permissions where user_id=$1`,
|
|
21
|
-
[params.id].filter(Boolean),
|
|
22
|
-
);
|
|
23
|
-
|
|
24
|
-
Object.assign(result, { deleted: rowCount });
|
|
25
|
-
|
|
26
|
-
if (Array.isArray(body.permissions) && body.permissions?.length) {
|
|
27
|
-
body.permissions.forEach((el) => {
|
|
28
|
-
Object.assign(el, { user_id: el.user_id || params.id });
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
await Promise.all(body.permissions.map(async (el) => dataInsert({
|
|
32
|
-
pg: client,
|
|
33
|
-
table: 'site.permissions',
|
|
34
|
-
data: el,
|
|
35
|
-
uid: user.uid,
|
|
36
|
-
})));
|
|
37
|
-
|
|
38
|
-
Object.assign(result, { inserted: body.permissions.length });
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
await client.query('COMMIT');
|
|
42
|
-
return reply.status(200).send(result);
|
|
43
|
-
} catch (err) {
|
|
44
|
-
await client.query('ROLLBACK');
|
|
45
|
-
logger.file('cms/permissions', { error: err.toString(), stack: err.stack });
|
|
46
|
-
return reply.status(500).send('set permissions error');
|
|
47
|
-
} finally {
|
|
48
|
-
client.release();
|
|
49
|
-
}
|
|
1
|
+
import { logger, pgClients, dataInsert } from '@opengis/fastify-table/utils.js';
|
|
2
|
+
|
|
3
|
+
export default async function setPermissions(req, reply) {
|
|
4
|
+
const { pg = pgClients.client, params = {}, user = {}, body = {} } = req;
|
|
5
|
+
|
|
6
|
+
if (!user?.uid) {
|
|
7
|
+
return reply.status(401).send('unauthorized');
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
if (!params.id) {
|
|
11
|
+
return reply.status(400).send('not enough params: id');
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const client = await pg.connect()
|
|
15
|
+
const result = {};
|
|
16
|
+
try {
|
|
17
|
+
await client.query('BEGIN');
|
|
18
|
+
|
|
19
|
+
const { rowCount = 0 } = await client.query(
|
|
20
|
+
`delete from site.permissions where user_id=$1`,
|
|
21
|
+
[params.id].filter(Boolean),
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
Object.assign(result, { deleted: rowCount });
|
|
25
|
+
|
|
26
|
+
if (Array.isArray(body.permissions) && body.permissions?.length) {
|
|
27
|
+
body.permissions.forEach((el) => {
|
|
28
|
+
Object.assign(el, { user_id: el.user_id || params.id });
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
await Promise.all(body.permissions.map(async (el) => dataInsert({
|
|
32
|
+
pg: client,
|
|
33
|
+
table: 'site.permissions',
|
|
34
|
+
data: el,
|
|
35
|
+
uid: user.uid,
|
|
36
|
+
})));
|
|
37
|
+
|
|
38
|
+
Object.assign(result, { inserted: body.permissions.length });
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
await client.query('COMMIT');
|
|
42
|
+
return reply.status(200).send(result);
|
|
43
|
+
} catch (err) {
|
|
44
|
+
await client.query('ROLLBACK');
|
|
45
|
+
logger.file('cms/permissions', { error: err.toString(), stack: err.stack });
|
|
46
|
+
return reply.status(500).send('set permissions error');
|
|
47
|
+
} finally {
|
|
48
|
+
client.release();
|
|
49
|
+
}
|
|
50
50
|
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
select uid, coalesce(sur_name,'')||coalesce(' '||user_name,'') as text, email from admin.users
|
|
1
|
+
select uid, coalesce(sur_name,'')||coalesce(' '||user_name,'') as text, email from admin.users
|
|
2
2
|
where enabled order by coalesce(sur_name,'')||coalesce(' '||user_name,'')
|