@opengis/fastify-table 1.2.2 → 1.2.4
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/package.json +1 -1
- package/server/migrations/0.sql +10 -6
- package/server/plugins/crud/funcs/utils/logChanges.js +14 -2
- package/server/plugins/crud/funcs/validateData.js +22 -0
- package/server/routes/crud/controllers/insert.js +14 -3
- package/server/routes/crud/controllers/update.js +13 -1
- package/utils.js +2 -0
package/package.json
CHANGED
package/server/migrations/0.sql
CHANGED
|
@@ -35,8 +35,8 @@ if (_returnType != 'text') then
|
|
|
35
35
|
|
|
36
36
|
DROP FUNCTION IF EXISTS next_id();
|
|
37
37
|
|
|
38
|
-
CREATE EXTENSION if not exists "uuid-ossp";
|
|
39
|
-
ALTER EXTENSION "uuid-ossp" SET SCHEMA public;
|
|
38
|
+
/* CREATE EXTENSION if not exists "uuid-ossp";
|
|
39
|
+
ALTER EXTENSION "uuid-ossp" SET SCHEMA public; */
|
|
40
40
|
|
|
41
41
|
CREATE OR REPLACE FUNCTION next_id()
|
|
42
42
|
RETURNS text AS
|
|
@@ -44,7 +44,9 @@ if (_returnType != 'text') then
|
|
|
44
44
|
DECLARE
|
|
45
45
|
|
|
46
46
|
BEGIN
|
|
47
|
-
return replace(public.uuid_generate_v4()::text, '-', '');
|
|
47
|
+
-- return replace(public.uuid_generate_v4()::text, '-', '');
|
|
48
|
+
-- return replace(gen_random_uuid()::text, '-', ''); -- native from postgres 13 onward
|
|
49
|
+
return encode(public.gen_random_bytes(6), 'hex');
|
|
48
50
|
END;
|
|
49
51
|
$BODY$
|
|
50
52
|
LANGUAGE plpgsql VOLATILE
|
|
@@ -61,8 +63,8 @@ if (_returnType != 'text') then
|
|
|
61
63
|
else
|
|
62
64
|
raise notice 'skip default reassign';
|
|
63
65
|
|
|
64
|
-
CREATE EXTENSION if not exists "uuid-ossp";
|
|
65
|
-
ALTER EXTENSION "uuid-ossp" SET SCHEMA public;
|
|
66
|
+
/* CREATE EXTENSION if not exists "uuid-ossp";
|
|
67
|
+
ALTER EXTENSION "uuid-ossp" SET SCHEMA public; */
|
|
66
68
|
|
|
67
69
|
CREATE OR REPLACE FUNCTION next_id()
|
|
68
70
|
RETURNS text AS
|
|
@@ -70,7 +72,9 @@ else
|
|
|
70
72
|
DECLARE
|
|
71
73
|
|
|
72
74
|
BEGIN
|
|
73
|
-
return replace(public.uuid_generate_v4()::text, '-', '');
|
|
75
|
+
-- return replace(public.uuid_generate_v4()::text, '-', '');
|
|
76
|
+
-- return replace(gen_random_uuid()::text, '-', ''); -- native from postgres 13 onward
|
|
77
|
+
return encode(public.gen_random_bytes(6), 'hex');
|
|
74
78
|
END;
|
|
75
79
|
$BODY$
|
|
76
80
|
LANGUAGE plpgsql VOLATILE
|
|
@@ -1,6 +1,18 @@
|
|
|
1
1
|
import getTemplate from '../../..//table/funcs/getTemplate.js';
|
|
2
2
|
import { metaFormat } from '@opengis/fastify-table/utils.js';
|
|
3
3
|
|
|
4
|
+
const defaultTitles = {
|
|
5
|
+
// editor_date: 'Дата оновлення',
|
|
6
|
+
// editor_id: 'Редактор',
|
|
7
|
+
// сdate: 'Дата створення',
|
|
8
|
+
// uid: 'Автор',
|
|
9
|
+
body: 'Зміст',
|
|
10
|
+
// entity_id: 'ID Сутності',
|
|
11
|
+
// entity_type: 'Таблиця сутності',
|
|
12
|
+
file_path: 'Шлях до файлу',
|
|
13
|
+
uploaded_name: 'Назва файлу',
|
|
14
|
+
};
|
|
15
|
+
|
|
4
16
|
function getValue(val) {
|
|
5
17
|
if (!val) return null;
|
|
6
18
|
return typeof val === 'object'
|
|
@@ -67,10 +79,10 @@ export default async function logChanges({
|
|
|
67
79
|
await metaFormat({ rows: [data], cls, sufix: false });
|
|
68
80
|
}
|
|
69
81
|
|
|
70
|
-
const newObj = Object.fromEntries(Object.entries(data || {}).map(el => ([[titles[el[0]] || el[0]], el[1]])));
|
|
82
|
+
const newObj = Object.fromEntries(Object.entries(data || {}).map(el => ([[titles[el[0]] || defaultTitles[el[0]] || el[0]], el[1]])));
|
|
71
83
|
const changesData = Object.keys(newObj || {}).map(el => ({
|
|
72
84
|
change_id: changeId,
|
|
73
|
-
entity_key:
|
|
85
|
+
entity_key: el,
|
|
74
86
|
value_old: getValue(old?.[el]),
|
|
75
87
|
value_new: type === 'DELETE' ? null : getValue(newObj?.[el]),
|
|
76
88
|
uid,
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
|
|
2
|
+
const emailReg = /(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])/g;
|
|
3
|
+
|
|
4
|
+
export default function validateData({ body = {}, schema = {} }) {
|
|
5
|
+
const requiredFields = Object.keys(schema).filter(key => schema[key].validators?.includes('required'));
|
|
6
|
+
|
|
7
|
+
const emptyRequiredKey = Object.keys(body).find(key => requiredFields.includes(key) && !body[key]);
|
|
8
|
+
|
|
9
|
+
if (emptyRequiredKey) {
|
|
10
|
+
return { error: 'empty required', key: emptyRequiredKey };
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const emailFields = Object.keys(schema).filter(key => schema[key].type === 'Email');
|
|
14
|
+
|
|
15
|
+
const invalidEmailKey = Object.keys(body).find(key => body[key] && emailFields.includes(key) && !body[key].match(emailReg));
|
|
16
|
+
|
|
17
|
+
if (invalidEmailKey) {
|
|
18
|
+
return { error: 'invalid email', key: emptyRequiredKey, val: body[invalidEmailKey] };
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return { message: 'ok' };
|
|
22
|
+
}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
|
-
applyHook, getAccess, getTemplate, checkXSS, dataInsert, getToken, config,
|
|
3
|
-
pgClients,
|
|
2
|
+
applyHook, getAccess, getTemplate, checkXSS, dataInsert, getToken, config, pgClients, logger, validateData,
|
|
4
3
|
} from '../../../../utils.js';
|
|
5
4
|
|
|
6
5
|
export default async function insert(req) {
|
|
@@ -44,10 +43,22 @@ export default async function insert(req) {
|
|
|
44
43
|
const xssCheck = checkXSS({ body, schema });
|
|
45
44
|
|
|
46
45
|
if (xssCheck.error && formData?.xssCheck !== false) {
|
|
47
|
-
|
|
46
|
+
logger.file('injection/xss', { table, form: form || loadTemplate?.form, body, uid: user?.uid, msg: xssCheck.error });
|
|
48
47
|
return { message: 'Дані містять заборонені символи. Приберіть їх та спробуйте ще раз', status: 409 };
|
|
49
48
|
}
|
|
50
49
|
|
|
50
|
+
const fieldCheck = validateData({ body, schema });
|
|
51
|
+
|
|
52
|
+
if (fieldCheck.error) {
|
|
53
|
+
logger.file('injection/sql', {
|
|
54
|
+
table,
|
|
55
|
+
form: form || loadTemplate?.form,
|
|
56
|
+
uid: user?.uid,
|
|
57
|
+
...fieldCheck,
|
|
58
|
+
});
|
|
59
|
+
return { message: 'Дані не пройшли валідацію. Приберіть некоректні дані та спробуйте ще раз', status: 409 };
|
|
60
|
+
}
|
|
61
|
+
|
|
51
62
|
if (![add, table].includes('admin.users')) {
|
|
52
63
|
Object.assign(body, { uid: user?.uid, editor_id: user?.uid });
|
|
53
64
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
|
-
pgClients, applyHook, getAccess, getTemplate, checkXSS, dataInsert, dataUpdate, logger, getToken,
|
|
2
|
+
pgClients, applyHook, getAccess, getTemplate, checkXSS, dataInsert, dataUpdate, logger, getToken, validateData,
|
|
3
3
|
} from '../../../../utils.js';
|
|
4
4
|
import config from '../../../../config.js';
|
|
5
5
|
import insert from './insert.js';
|
|
@@ -62,6 +62,18 @@ export default async function update(req) {
|
|
|
62
62
|
return { message: 'Дані містять заборонені символи. Приберіть їх та спробуйте ще раз', status: 409 };
|
|
63
63
|
}
|
|
64
64
|
|
|
65
|
+
const fieldCheck = validateData({ body, schema });
|
|
66
|
+
|
|
67
|
+
if (fieldCheck.error) {
|
|
68
|
+
logger.file('injection/sql', {
|
|
69
|
+
table,
|
|
70
|
+
form: form || loadTemplate?.form,
|
|
71
|
+
uid: user?.uid,
|
|
72
|
+
...fieldCheck,
|
|
73
|
+
});
|
|
74
|
+
return { message: 'Дані не пройшли валідацію. Приберіть некоректні дані та спробуйте ще раз', status: 409 };
|
|
75
|
+
}
|
|
76
|
+
|
|
65
77
|
const res = await dataUpdate({
|
|
66
78
|
table: loadTemplate?.table || table,
|
|
67
79
|
id,
|
package/utils.js
CHANGED
|
@@ -40,6 +40,7 @@ import getToken from './server/plugins/crud/funcs/getToken.js';
|
|
|
40
40
|
import setToken from './server/plugins/crud/funcs/setToken.js';
|
|
41
41
|
import getOpt from './server/plugins/crud/funcs/getOpt.js';
|
|
42
42
|
import setOpt from './server/plugins/crud/funcs/setOpt.js';
|
|
43
|
+
import validateData from './server/plugins/crud/funcs/validateData.js';
|
|
43
44
|
|
|
44
45
|
// policy
|
|
45
46
|
import checkXSS from './server/plugins/policy/funcs/checkXSS.js';
|
|
@@ -98,6 +99,7 @@ export {
|
|
|
98
99
|
getOpt,
|
|
99
100
|
setOpt,
|
|
100
101
|
setToken,
|
|
102
|
+
validateData,
|
|
101
103
|
|
|
102
104
|
// crud
|
|
103
105
|
dataInsert,
|