@opengis/cms 0.0.56 → 0.0.58
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 +131 -131
- package/dist/AddNewItemInTree-05PSSEFi.js +76 -0
- package/dist/ArticlesPage-CFjE_cw_.js +298 -0
- package/dist/CollectionsBreadcrumb-BCxeRikP.js +4 -0
- package/dist/CollectionsBreadcrumb.vue_vue_type_script_setup_true_lang-umRzB5mY.js +53 -0
- package/dist/CollectionsPage-DHfPNql6.js +124 -0
- package/dist/{CreateForm-BMOBeP4G.js → CreateForm-5FvT45vH.js} +1 -1
- package/dist/Dashboard-C1eGscNd.js +358 -0
- package/dist/EditCollectionPage-DIr1tdtn.js +187 -0
- package/dist/{EmptyData-DaZt_nAm.js → EmptyData-DxPrSXhV.js} +1 -1
- package/dist/{MenuAddPage-Bf48Z-ah.js → MenuAddPage-D-p3gFgm.js} +40 -35
- package/dist/MenuBody-rN5j4YBu.js +125 -0
- package/dist/MenuItemPage-BoJw885D.js +1027 -0
- package/dist/MenuList-DFEBS0NB.js +172 -0
- package/dist/MenuPage-BCZB_S8j.js +107 -0
- package/dist/MenuWrapper-AZ_8s-zd.js +12 -0
- package/dist/MonacoEditor-Db-3Jc3E.js +4 -0
- package/dist/{UniversalTable.vue_vue_type_script_setup_true_lang-CJGTsd1V.js → UniversalTable-CzqPG-tY.js} +12 -12
- package/dist/{UniversalTablePagination.vue_vue_type_script_setup_true_lang-GYZd_gkA.js → UniversalTablePagination-4gL47A7I.js} +1 -1
- package/dist/VsFormTags-CMjiu9sY.js +114 -0
- package/dist/VsPreview-DwETkOpb.js +63 -0
- package/dist/contentForm-CtMhQTG0.js +489 -0
- package/dist/getField-CpwVE28P.js +179 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.html +29 -29
- package/dist/index.js +72 -71
- package/dist/style.css +1 -1
- package/dist/vs-builder-edit-D-q1o8tF.js +604 -0
- package/dist/vs-builder-monaco-B3Jj0V31.js +33 -0
- package/dist/vs-builder-preview-BH4VAM3a.js +44 -0
- package/dist/vs-form-custom-datatable-BDZo48w3.js +317 -0
- package/dist/vs-form-integer-BZ855R3g.js +61 -0
- package/dist/vs-form-media-select-NY27EaG1.js +837 -0
- package/dist/vs-form-reference-list-Dtv8fJJU.js +1536 -0
- package/dist/vs-form-reletion-link-BhzNQszm.js +34 -0
- package/dist/vs-form-tiptap-DDFQjRjY.js +4 -0
- package/dist/vs-form-tiptap.vue_vue_type_script_setup_true_lang-DGgsqXwg.js +11 -0
- package/dist/vs-richtext-md-C098v_6Q.js +4 -0
- package/dist/vs-richtext-md.vue_vue_type_script_setup_true_lang-Ct8uTV-J.js +14 -0
- package/input-types.json +9 -9
- package/locales/en.json +815 -814
- package/locales/uk.json +813 -812
- package/module/cms/cls/content.status.json +17 -17
- package/module/cms/cls/user_type.json +9 -9
- package/module/cms/form/admin.users.form.json +77 -77
- package/module/cms/select/cms.page_type.sql +1 -1
- package/module/cms/select/news_tag_id.sql +11 -11
- package/module/cms/table/admin.users.table.json +53 -53
- package/module/cms/table/collection.default.table.json +96 -96
- package/module/cms/table/single.default.table.json +116 -116
- package/package.json +68 -68
- package/plugin.js +43 -43
- package/server/app.js +35 -35
- package/server/config.js +4 -4
- package/server/functions/getContent.js +45 -45
- package/server/functions/getDraftKey.js +22 -22
- package/server/functions/getSearchData.js +31 -31
- package/server/functions/getTags.js +30 -30
- package/server/functions/getUser.js +27 -27
- package/server/functions/utils/mock.reply.js +55 -55
- package/server/index.js +22 -22
- package/server/migrations/fixes.sql +129 -129
- package/server/migrations/site.sql +595 -595
- package/server/plugins/adminHook.js +78 -78
- package/server/plugins/hook.js +59 -59
- package/server/plugins/vite.js +75 -75
- package/server/routes/category/controllers/cms.category.delete.js +21 -21
- package/server/routes/category/controllers/cms.category.get.js +17 -17
- package/server/routes/category/controllers/cms.category.list.js +16 -16
- package/server/routes/category/controllers/cms.category.post.js +21 -21
- package/server/routes/category/controllers/cms.category.put.js +23 -23
- package/server/routes/category/index.mjs +22 -22
- package/server/routes/cms/controllers/cmsStat.js +55 -55
- package/server/routes/cms/controllers/cmsSuggest.js +57 -57
- package/server/routes/cms/controllers/deleteContent.js +113 -113
- package/server/routes/cms/controllers/deleteMedia.js +76 -76
- package/server/routes/cms/controllers/downloadMedia.js +84 -84
- package/server/routes/cms/controllers/getContent.js +113 -113
- package/server/routes/cms/controllers/getContentBySlug.js +93 -93
- package/server/routes/cms/controllers/insertContent.js +217 -217
- package/server/routes/cms/controllers/listMedia.js +155 -155
- package/server/routes/cms/controllers/metadataMedia.js +39 -39
- package/server/routes/cms/controllers/properties.get.js +18 -18
- package/server/routes/cms/controllers/properties.post.js +99 -99
- package/server/routes/cms/controllers/searchContent.js +214 -214
- package/server/routes/cms/controllers/translate.js +89 -89
- package/server/routes/cms/controllers/updateContent.js +266 -264
- package/server/routes/cms/controllers/uploadMedia.js +79 -79
- package/server/routes/cms/functions/getSettings.js +48 -48
- package/server/routes/cms/index.mjs +112 -112
- package/server/routes/cms/utils/additionalData.js +35 -35
- package/server/routes/cms/utils/getCollection.js +89 -89
- package/server/routes/cms/utils/getSingle.js +188 -183
- package/server/routes/cms/utils/inputTypes.js +5 -5
- package/server/routes/cms/utils/insertContentLocalization.js +104 -104
- package/server/routes/cms/utils/requestTranslation.js +85 -85
- package/server/routes/cms/utils/updateLocalization.js +47 -47
- package/server/routes/cmsSpace/controllers/deleteSpace.js +25 -25
- package/server/routes/cmsSpace/controllers/getSpaces.js +27 -27
- package/server/routes/cmsSpace/controllers/insertSpace.js +21 -21
- package/server/routes/cmsSpace/controllers/updateSpace.js +23 -23
- package/server/routes/cmsSpace/index.mjs +20 -20
- package/server/routes/contentType/controllers/addContentType.js +160 -160
- package/server/routes/contentType/controllers/contentTypeList.js +54 -54
- package/server/routes/contentType/controllers/delContentType.js +75 -75
- package/server/routes/contentType/controllers/editContentType.js +88 -81
- package/server/routes/contentType/controllers/getContentType.js +65 -57
- package/server/routes/contentType/index.mjs +35 -35
- package/server/routes/contentType/utils/updateContents.js +44 -44
- package/server/routes/contentType/utils/updateCustomContentTable.js +53 -53
- package/server/routes/feedback/controllers/email.list.js +24 -24
- package/server/routes/feedback/controllers/feedback.js +48 -48
- package/server/routes/feedback/controllers/feedback.list.js +37 -37
- package/server/routes/feedback/controllers/news.subscriptions.js +44 -44
- package/server/routes/feedback/index.mjs +71 -71
- package/server/routes/logs/controllers/export.user.logs.js +77 -77
- package/server/routes/logs/controllers/user.logs.js +44 -44
- package/server/routes/logs/index.mjs +9 -9
- package/server/routes/menu/controllers/addMenu.js +37 -37
- package/server/routes/menu/controllers/delMenu.js +31 -31
- package/server/routes/menu/controllers/editMenu.js +41 -41
- package/server/routes/menu/controllers/getMenu.js +24 -24
- package/server/routes/menu/functions/getMenu.js +50 -50
- package/server/routes/menu/index.mjs +13 -13
- package/server/routes/migration/controllers/collectionToCustom.js +137 -137
- package/server/routes/migration/index.mjs +8 -8
- package/server/routes/root.mjs +8 -8
- package/server/routes/tags/controllers/add.tags.js +24 -24
- package/server/routes/tags/controllers/del.tags.js +19 -19
- package/server/routes/tags/controllers/edit.tags.js +25 -25
- package/server/routes/tags/controllers/get.tags.js +15 -15
- package/server/routes/tags/index.mjs +14 -14
- package/server/templates/cls/cms.category_type.json +9 -9
- package/server/templates/cls/cms.content_review_status.json +9 -9
- package/server/templates/cls/cms.content_status.json +9 -9
- package/server/templates/cls/cms.content_type.json +9 -9
- package/server/templates/cls/cms.lang.json +9 -9
- package/server/templates/page/login.html +126 -126
- package/utils.d.ts +52 -52
- package/utils.js +8 -8
- package/dist/ArticlesPage-BcR1hbds.js +0 -286
- package/dist/BuilderPage-CK_osM89.js +0 -386
- package/dist/CollectionsBreadcrumb.vue_vue_type_script_setup_true_lang-CnOe9ORD.js +0 -45
- package/dist/CollectionsPage-JfmrHNR_.js +0 -110
- package/dist/EditCollectionPage-Cw3GQYRe.js +0 -809
- package/dist/MenuItemPage-CXn5HC8j.js +0 -1366
- package/dist/MenuPage-tJZtK46W.js +0 -106
- package/dist/contentForm-B6gHgGkz.js +0 -586
- package/dist/getField-Y5WXnRR0.js +0 -2948
|
@@ -1,218 +1,218 @@
|
|
|
1
|
-
import { config, checkSQL, getTemplate, pgClients, dataInsert, logger } from '@opengis/fastify-table/utils.js';
|
|
2
|
-
|
|
3
|
-
import inputTypes from '../utils/inputTypes.js';
|
|
4
|
-
|
|
5
|
-
import updateLocalization from '../utils/updateLocalization.js';
|
|
6
|
-
|
|
7
|
-
const defaultColumns = [
|
|
8
|
-
'content_id',
|
|
9
|
-
'space_id',
|
|
10
|
-
'content_type_id',
|
|
11
|
-
'created_at',
|
|
12
|
-
'updated_at',
|
|
13
|
-
'published_at',
|
|
14
|
-
'revision',
|
|
15
|
-
'locale',
|
|
16
|
-
'status',
|
|
17
|
-
'slug',
|
|
18
|
-
'title',
|
|
19
|
-
'created_by',
|
|
20
|
-
'published_by',
|
|
21
|
-
'updated_by',
|
|
22
|
-
'meta',
|
|
23
|
-
];
|
|
24
|
-
|
|
25
|
-
export default async function insertContent(req, reply) {
|
|
26
|
-
const {
|
|
27
|
-
pg = pgClients.client,
|
|
28
|
-
params = {},
|
|
29
|
-
user = {},
|
|
30
|
-
body = {},
|
|
31
|
-
headers = {},
|
|
32
|
-
} = req;
|
|
33
|
-
|
|
34
|
-
const { type, id = body?.id } = params;
|
|
35
|
-
|
|
36
|
-
if (!type) {
|
|
37
|
-
return reply.status(400).send('not enough params: type');
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
const arr = config.pg ? await pg.query(`select array_agg(relname)::text[] from pg_class a
|
|
41
|
-
left join pg_namespace b on a.relnamespace=b.oid
|
|
42
|
-
where a.relam=2 and b.nspname='data'`).then(el => el.rows?.[0]?.array_agg || []) : [];
|
|
43
|
-
|
|
44
|
-
const { content_id: contentId, type: contentType } = await pg.query(
|
|
45
|
-
'select content_id, (select type from site.content_types where content_type_id=t.content_type_id) from site.contents t where slug=$1',
|
|
46
|
-
[['single', 'pages'].includes(type) ? id : type],
|
|
47
|
-
).then(el => el.rows?.[0] || {});
|
|
48
|
-
|
|
49
|
-
const ctypeId = contentId && contentId !== 'pages' && contentType === 'single' ? await pg.query(
|
|
50
|
-
'select content_type_id from site.contents where content_id=$1',
|
|
51
|
-
[contentId],
|
|
52
|
-
).then(el => el.rows?.[0]?.content_type_id) : null;
|
|
53
|
-
|
|
54
|
-
if (!arr.length && (ctypeId || type) !== 'pages') {
|
|
55
|
-
return reply.status(400).send('empty schema: data');
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
const table = arr.find(el => el === params.type);
|
|
59
|
-
|
|
60
|
-
const { ctid, dbtable, columns: contentColumns } = await pg.query(
|
|
61
|
-
'select content_type_id as ctid, table_name as dbtable, columns from site.content_types where $1 in (content_type_id, name)',
|
|
62
|
-
[type === 'single' && id ? id : (ctypeId || type)],
|
|
63
|
-
).then(el => el.rows?.[0] || {});
|
|
64
|
-
|
|
65
|
-
const loadTable = (ctypeId || type) === 'pages' ? await getTemplate('table', 'single.default.table') : {};
|
|
66
|
-
|
|
67
|
-
const columns = (ctypeId || type) === 'pages'
|
|
68
|
-
? (loadTable?.columns || []).concat(contentColumns.filter(col => loadTable?.columns.findIndex(el => el.name === col.name) === -1))
|
|
69
|
-
: contentColumns;
|
|
70
|
-
|
|
71
|
-
// site.content_data, includes singletone
|
|
72
|
-
if (((!table && !dbtable) || (ctypeId || type) === 'pages')) {
|
|
73
|
-
const cid = await pg.query(
|
|
74
|
-
'select content_id from site.contents where content_type_id=$1 limit 1',
|
|
75
|
-
[ctid || 'pages'],
|
|
76
|
-
).then(el => el.rows?.[0]?.content_id);
|
|
77
|
-
|
|
78
|
-
const ctid1 = body.content_type_id || ctid || 'pages';
|
|
79
|
-
|
|
80
|
-
if (!cid) {
|
|
81
|
-
return reply.status(404).send('contents not found');
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
const columnList = columns?.map?.(el => el.name) || [];
|
|
85
|
-
const types = columns?.reduce?.((acc, curr) => ({ ...acc, [curr.name]: curr.type || 'text' }), {}) || {};
|
|
86
|
-
const keys = Object.keys(body || {}).filter(key => columnList.includes(key) && !defaultColumns.includes(key));
|
|
87
|
-
|
|
88
|
-
if (!Object.keys(body || {}).length) {
|
|
89
|
-
return reply.status(400).send('invalid payload');
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
// const xss = checkXSS({ body });
|
|
93
|
-
const sql = checkSQL({ body });
|
|
94
|
-
|
|
95
|
-
if (/*xss.error ||*/ sql.error && false) {
|
|
96
|
-
logger.file(`injection/${/*xss.error ? 'xss' : */'sql'}/cms`, {
|
|
97
|
-
table,
|
|
98
|
-
...params,
|
|
99
|
-
uid: user?.uid,
|
|
100
|
-
...(/*xss.error ? xss : */sql),
|
|
101
|
-
});
|
|
102
|
-
return reply
|
|
103
|
-
.status(409)
|
|
104
|
-
.send(
|
|
105
|
-
`Дані містять заборонені ${/*xss.error ? 'xss' : */'sql'} символи. Приберіть їх та спробуйте ще раз`
|
|
106
|
-
);
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
const client = await pg.connect();
|
|
110
|
-
|
|
111
|
-
try {
|
|
112
|
-
await client.query('begin');
|
|
113
|
-
const res = await dataInsert({
|
|
114
|
-
pg: client,
|
|
115
|
-
table: 'site.contents',
|
|
116
|
-
id,
|
|
117
|
-
data: { ...body, content_type_id: ctid1 },
|
|
118
|
-
uid: user?.uid,
|
|
119
|
-
}).then(el => el.rows?.[0] || {});
|
|
120
|
-
|
|
121
|
-
if (!res?.content_id) throw new Error('insert contents error');
|
|
122
|
-
|
|
123
|
-
await Promise.all(keys.map(async key => dataInsert({
|
|
124
|
-
pg: client,
|
|
125
|
-
table: 'site.content_data',
|
|
126
|
-
data: {
|
|
127
|
-
field_key: key,
|
|
128
|
-
content_id: res.content_id,
|
|
129
|
-
object_id: res.content_id,
|
|
130
|
-
field_type: types[key] || 'text',
|
|
131
|
-
field_value: inputTypes[types[key] || ''] === 'json' ? undefined : body[key],
|
|
132
|
-
field_value_object: inputTypes[types[key] || ''] === 'json' ? body[key] : undefined,
|
|
133
|
-
},
|
|
134
|
-
uid: user?.uid,
|
|
135
|
-
})));
|
|
136
|
-
|
|
137
|
-
await updateLocalization(client, res.content_id, body, ctid1, user?.uid);
|
|
138
|
-
|
|
139
|
-
if (body?.tag_list?.length) {
|
|
140
|
-
await Promise.all(body.tag_list.map(async tag => dataInsert({
|
|
141
|
-
pg: client,
|
|
142
|
-
table: 'site.tag_data',
|
|
143
|
-
data: {
|
|
144
|
-
tag_id: tag,
|
|
145
|
-
data_id: id,
|
|
146
|
-
},
|
|
147
|
-
uid: user?.uid,
|
|
148
|
-
})));
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
await client.query('commit');
|
|
152
|
-
|
|
153
|
-
return {
|
|
154
|
-
id: res.content_id, rows: [res].filter(Boolean)
|
|
155
|
-
};
|
|
156
|
-
} catch (err) {
|
|
157
|
-
await client.query('rollback');
|
|
158
|
-
return reply.status(500).send(err.toString());
|
|
159
|
-
} finally {
|
|
160
|
-
client.release();
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
// custom table
|
|
165
|
-
if (!table && !dbtable) {
|
|
166
|
-
return reply.status(400).send('invalid params: type');
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
const client = await pg.connect();
|
|
170
|
-
|
|
171
|
-
try {
|
|
172
|
-
await client.query('begin');
|
|
173
|
-
|
|
174
|
-
// const types = columns?.reduce?.((acc, curr) => ({ ...acc, [curr.name]: inputTypes[curr.type] || 'text' }), {}) || {};
|
|
175
|
-
const { rows = [] } = await dataInsert({
|
|
176
|
-
pg: client,
|
|
177
|
-
id,
|
|
178
|
-
table: 'data.' + `"${(table || dbtable)}"`,
|
|
179
|
-
data: body,
|
|
180
|
-
referer: headers?.referer,
|
|
181
|
-
uid: user?.uid,
|
|
182
|
-
}).catch(err => {
|
|
183
|
-
if (err.message?.includes?.('unique constraint')) {
|
|
184
|
-
throw new Error('Порушенні унікальності: ' + err.message?.match?.(/([^']+)/g)?.[1]);
|
|
185
|
-
}
|
|
186
|
-
throw err;
|
|
187
|
-
}) || {};
|
|
188
|
-
|
|
189
|
-
const idRes = rows?.[0]?.id;
|
|
190
|
-
|
|
191
|
-
if (!idRes) {
|
|
192
|
-
throw new Error('content insert error');
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
await updateLocalization(client, idRes, body, ctid, user?.uid);
|
|
196
|
-
|
|
197
|
-
if (body?.tag_list?.length) {
|
|
198
|
-
await Promise.all(body.tag_list.map(async tag => dataInsert({
|
|
199
|
-
pg: client,
|
|
200
|
-
table: 'site.tag_data',
|
|
201
|
-
data: {
|
|
202
|
-
tag_id: tag,
|
|
203
|
-
data_id: id || idRes,
|
|
204
|
-
},
|
|
205
|
-
uid: user?.uid,
|
|
206
|
-
})));
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
await client.query('commit');
|
|
210
|
-
|
|
211
|
-
return reply.status(200).send({ id: idRes, rows });
|
|
212
|
-
} catch (err) {
|
|
213
|
-
await client.query('rollback');
|
|
214
|
-
return reply.status(500).send(err.toString());
|
|
215
|
-
} finally {
|
|
216
|
-
client.release();
|
|
217
|
-
}
|
|
1
|
+
import { config, checkSQL, getTemplate, pgClients, dataInsert, logger } from '@opengis/fastify-table/utils.js';
|
|
2
|
+
|
|
3
|
+
import inputTypes from '../utils/inputTypes.js';
|
|
4
|
+
|
|
5
|
+
import updateLocalization from '../utils/updateLocalization.js';
|
|
6
|
+
|
|
7
|
+
const defaultColumns = [
|
|
8
|
+
'content_id',
|
|
9
|
+
'space_id',
|
|
10
|
+
'content_type_id',
|
|
11
|
+
'created_at',
|
|
12
|
+
'updated_at',
|
|
13
|
+
'published_at',
|
|
14
|
+
'revision',
|
|
15
|
+
'locale',
|
|
16
|
+
'status',
|
|
17
|
+
'slug',
|
|
18
|
+
'title',
|
|
19
|
+
'created_by',
|
|
20
|
+
'published_by',
|
|
21
|
+
'updated_by',
|
|
22
|
+
'meta',
|
|
23
|
+
];
|
|
24
|
+
|
|
25
|
+
export default async function insertContent(req, reply) {
|
|
26
|
+
const {
|
|
27
|
+
pg = pgClients.client,
|
|
28
|
+
params = {},
|
|
29
|
+
user = {},
|
|
30
|
+
body = {},
|
|
31
|
+
headers = {},
|
|
32
|
+
} = req;
|
|
33
|
+
|
|
34
|
+
const { type, id = body?.id } = params;
|
|
35
|
+
|
|
36
|
+
if (!type) {
|
|
37
|
+
return reply.status(400).send('not enough params: type');
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const arr = config.pg ? await pg.query(`select array_agg(relname)::text[] from pg_class a
|
|
41
|
+
left join pg_namespace b on a.relnamespace=b.oid
|
|
42
|
+
where a.relam=2 and b.nspname='data'`).then(el => el.rows?.[0]?.array_agg || []) : [];
|
|
43
|
+
|
|
44
|
+
const { content_id: contentId, type: contentType } = await pg.query(
|
|
45
|
+
'select content_id, (select type from site.content_types where content_type_id=t.content_type_id) from site.contents t where slug=$1',
|
|
46
|
+
[['single', 'pages'].includes(type) ? id : type],
|
|
47
|
+
).then(el => el.rows?.[0] || {});
|
|
48
|
+
|
|
49
|
+
const ctypeId = contentId && contentId !== 'pages' && contentType === 'single' ? await pg.query(
|
|
50
|
+
'select content_type_id from site.contents where content_id=$1',
|
|
51
|
+
[contentId],
|
|
52
|
+
).then(el => el.rows?.[0]?.content_type_id) : null;
|
|
53
|
+
|
|
54
|
+
if (!arr.length && (ctypeId || type) !== 'pages') {
|
|
55
|
+
return reply.status(400).send('empty schema: data');
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const table = arr.find(el => el === params.type);
|
|
59
|
+
|
|
60
|
+
const { ctid, dbtable, columns: contentColumns } = await pg.query(
|
|
61
|
+
'select content_type_id as ctid, table_name as dbtable, columns from site.content_types where $1 in (content_type_id, name)',
|
|
62
|
+
[type === 'single' && id ? id : (ctypeId || type)],
|
|
63
|
+
).then(el => el.rows?.[0] || {});
|
|
64
|
+
|
|
65
|
+
const loadTable = (ctypeId || type) === 'pages' ? await getTemplate('table', 'single.default.table') : {};
|
|
66
|
+
|
|
67
|
+
const columns = (ctypeId || type) === 'pages'
|
|
68
|
+
? (loadTable?.columns || []).concat((contentColumns || []).filter(col => loadTable?.columns.findIndex(el => el.name === col.name) === -1))
|
|
69
|
+
: contentColumns;
|
|
70
|
+
|
|
71
|
+
// site.content_data, includes singletone
|
|
72
|
+
if (((!table && !dbtable) || (ctypeId || type) === 'pages')) {
|
|
73
|
+
const cid = await pg.query(
|
|
74
|
+
'select content_id from site.contents where content_type_id=$1 limit 1',
|
|
75
|
+
[ctid || 'pages'],
|
|
76
|
+
).then(el => el.rows?.[0]?.content_id);
|
|
77
|
+
|
|
78
|
+
const ctid1 = body.content_type_id || ctid || 'pages';
|
|
79
|
+
|
|
80
|
+
if (!cid) {
|
|
81
|
+
return reply.status(404).send('contents not found');
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const columnList = columns?.map?.(el => el.name) || [];
|
|
85
|
+
const types = columns?.reduce?.((acc, curr) => ({ ...acc, [curr.name]: curr.type || 'text' }), {}) || {};
|
|
86
|
+
const keys = Object.keys(body || {}).filter(key => columnList.includes(key) && !defaultColumns.includes(key));
|
|
87
|
+
|
|
88
|
+
if (!Object.keys(body || {}).length) {
|
|
89
|
+
return reply.status(400).send('invalid payload');
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// const xss = checkXSS({ body });
|
|
93
|
+
const sql = checkSQL({ body });
|
|
94
|
+
|
|
95
|
+
if (/*xss.error ||*/ sql.error && false) {
|
|
96
|
+
logger.file(`injection/${/*xss.error ? 'xss' : */'sql'}/cms`, {
|
|
97
|
+
table,
|
|
98
|
+
...params,
|
|
99
|
+
uid: user?.uid,
|
|
100
|
+
...(/*xss.error ? xss : */sql),
|
|
101
|
+
});
|
|
102
|
+
return reply
|
|
103
|
+
.status(409)
|
|
104
|
+
.send(
|
|
105
|
+
`Дані містять заборонені ${/*xss.error ? 'xss' : */'sql'} символи. Приберіть їх та спробуйте ще раз`
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
const client = await pg.connect();
|
|
110
|
+
|
|
111
|
+
try {
|
|
112
|
+
await client.query('begin');
|
|
113
|
+
const res = await dataInsert({
|
|
114
|
+
pg: client,
|
|
115
|
+
table: 'site.contents',
|
|
116
|
+
id,
|
|
117
|
+
data: { ...body, content_type_id: ctid1 },
|
|
118
|
+
uid: user?.uid,
|
|
119
|
+
}).then(el => el.rows?.[0] || {});
|
|
120
|
+
|
|
121
|
+
if (!res?.content_id) throw new Error('insert contents error');
|
|
122
|
+
|
|
123
|
+
await Promise.all(keys.map(async key => dataInsert({
|
|
124
|
+
pg: client,
|
|
125
|
+
table: 'site.content_data',
|
|
126
|
+
data: {
|
|
127
|
+
field_key: key,
|
|
128
|
+
content_id: res.content_id,
|
|
129
|
+
object_id: res.content_id,
|
|
130
|
+
field_type: types[key] || 'text',
|
|
131
|
+
field_value: inputTypes[types[key] || ''] === 'json' ? undefined : body[key],
|
|
132
|
+
field_value_object: inputTypes[types[key] || ''] === 'json' ? body[key] : undefined,
|
|
133
|
+
},
|
|
134
|
+
uid: user?.uid,
|
|
135
|
+
})));
|
|
136
|
+
|
|
137
|
+
await updateLocalization(client, res.content_id, body, ctid1, user?.uid);
|
|
138
|
+
|
|
139
|
+
if (body?.tag_list?.length) {
|
|
140
|
+
await Promise.all(body.tag_list.map(async tag => dataInsert({
|
|
141
|
+
pg: client,
|
|
142
|
+
table: 'site.tag_data',
|
|
143
|
+
data: {
|
|
144
|
+
tag_id: tag,
|
|
145
|
+
data_id: id,
|
|
146
|
+
},
|
|
147
|
+
uid: user?.uid,
|
|
148
|
+
})));
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
await client.query('commit');
|
|
152
|
+
|
|
153
|
+
return {
|
|
154
|
+
id: res.content_id, rows: [res].filter(Boolean)
|
|
155
|
+
};
|
|
156
|
+
} catch (err) {
|
|
157
|
+
await client.query('rollback');
|
|
158
|
+
return reply.status(500).send(err.toString());
|
|
159
|
+
} finally {
|
|
160
|
+
client.release();
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// custom table
|
|
165
|
+
if (!table && !dbtable) {
|
|
166
|
+
return reply.status(400).send('invalid params: type');
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
const client = await pg.connect();
|
|
170
|
+
|
|
171
|
+
try {
|
|
172
|
+
await client.query('begin');
|
|
173
|
+
|
|
174
|
+
// const types = columns?.reduce?.((acc, curr) => ({ ...acc, [curr.name]: inputTypes[curr.type] || 'text' }), {}) || {};
|
|
175
|
+
const { rows = [] } = await dataInsert({
|
|
176
|
+
pg: client,
|
|
177
|
+
id,
|
|
178
|
+
table: 'data.' + `"${(table || dbtable)}"`,
|
|
179
|
+
data: body,
|
|
180
|
+
referer: headers?.referer,
|
|
181
|
+
uid: user?.uid,
|
|
182
|
+
}).catch(err => {
|
|
183
|
+
if (err.message?.includes?.('unique constraint')) {
|
|
184
|
+
throw new Error('Порушенні унікальності: ' + err.message?.match?.(/([^']+)/g)?.[1]);
|
|
185
|
+
}
|
|
186
|
+
throw err;
|
|
187
|
+
}) || {};
|
|
188
|
+
|
|
189
|
+
const idRes = rows?.[0]?.id;
|
|
190
|
+
|
|
191
|
+
if (!idRes) {
|
|
192
|
+
throw new Error('content insert error');
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
await updateLocalization(client, idRes, body, ctid, user?.uid);
|
|
196
|
+
|
|
197
|
+
if (body?.tag_list?.length) {
|
|
198
|
+
await Promise.all(body.tag_list.map(async tag => dataInsert({
|
|
199
|
+
pg: client,
|
|
200
|
+
table: 'site.tag_data',
|
|
201
|
+
data: {
|
|
202
|
+
tag_id: tag,
|
|
203
|
+
data_id: id || idRes,
|
|
204
|
+
},
|
|
205
|
+
uid: user?.uid,
|
|
206
|
+
})));
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
await client.query('commit');
|
|
210
|
+
|
|
211
|
+
return reply.status(200).send({ id: idRes, rows });
|
|
212
|
+
} catch (err) {
|
|
213
|
+
await client.query('rollback');
|
|
214
|
+
return reply.status(500).send(err.toString());
|
|
215
|
+
} finally {
|
|
216
|
+
client.release();
|
|
217
|
+
}
|
|
218
218
|
}
|