@opengis/fastify-table 1.1.31 → 1.1.33
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 +26 -26
- package/config.js +10 -10
- package/cron/controllers/cronApi.js +22 -22
- package/cron/controllers/utils/cronList.js +1 -1
- package/cron/funcs/addCron.js +131 -131
- package/cron/index.js +10 -10
- package/crud/controllers/utils/checkXSS.js +45 -45
- package/crud/controllers/utils/xssInjection.js +72 -72
- package/crud/funcs/getToken.js +27 -27
- package/crud/funcs/isFileExists.js +13 -13
- package/crud/funcs/setToken.js +53 -53
- package/index.js +15 -2
- package/logger/createFileStream.js +50 -0
- package/logger/getHooks.js +15 -0
- package/logger/getLogger.js +35 -0
- package/logger/labels.js +11 -0
- package/logger/logger.test.api.js +41 -0
- package/logger/serializers.js +24 -0
- package/notification/controllers/testEmail.js +49 -49
- package/notification/funcs/utils/sendEmail.js +39 -39
- package/package.json +3 -1
- package/pg/funcs/getPG.js +30 -30
- package/redis/funcs/getRedis.js +23 -23
- package/server/migrations/log.sql +80 -80
- package/server/migrations/properties.sql +8 -2
- package/server.js +26 -14
- package/table/controllers/card.js +44 -44
- package/table/controllers/form.js +28 -28
- package/test/api/crud.xss.test.js +72 -72
- package/test/config.example +18 -18
- package/test/funcs/pg.test.js +34 -34
- package/test/funcs/redis.test.js +19 -19
- package/test/templates/cls/test.json +9 -9
- package/test/templates/form/cp_building.form.json +32 -32
- package/test/templates/select/account_id.json +3 -3
- package/test/templates/select/storage.data.json +2 -2
- package/test/templates/table/gis.dataset.table.json +20 -20
- package/util/controllers/logger.file.js +91 -90
- package/util/controllers/next.id.js +4 -4
- package/util/controllers/properties.get.js +19 -19
- package/util/controllers/utils/checkUserAccess.js +17 -19
- package/util/controllers/utils/getRootDir.js +22 -21
- package/util/index.js +23 -23
- package/utils.js +2 -0
package/redis/funcs/getRedis.js
CHANGED
|
@@ -1,23 +1,23 @@
|
|
|
1
|
-
import Redis from 'ioredis';
|
|
2
|
-
import config from '../../config.js';
|
|
3
|
-
import redisClients from './redisClients.js';
|
|
4
|
-
|
|
5
|
-
function getRedis({ db } = { db: 0 }) {
|
|
6
|
-
if (!config.redis) return null;
|
|
7
|
-
if (redisClients[db]) return redisClients[db];
|
|
8
|
-
|
|
9
|
-
const redisConfig = {
|
|
10
|
-
db,
|
|
11
|
-
keyPrefix: `${config.db}:`,
|
|
12
|
-
host: config.redis?.host || '127.0.0.1',
|
|
13
|
-
port: config.redis?.port || 6379, // Redis port
|
|
14
|
-
family: 4, // 4 (IPv4) or 6 (IPv6)
|
|
15
|
-
closeClient: true,
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
redisClients[db] = new Redis(redisConfig);
|
|
19
|
-
|
|
20
|
-
return redisClients[db];
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export default getRedis;
|
|
1
|
+
import Redis from 'ioredis';
|
|
2
|
+
import config from '../../config.js';
|
|
3
|
+
import redisClients from './redisClients.js';
|
|
4
|
+
|
|
5
|
+
function getRedis({ db } = { db: 0 }) {
|
|
6
|
+
if (!config.redis) return null;
|
|
7
|
+
if (redisClients[db]) return redisClients[db];
|
|
8
|
+
|
|
9
|
+
const redisConfig = {
|
|
10
|
+
db,
|
|
11
|
+
keyPrefix: `${config.db}:`,
|
|
12
|
+
host: config.redis?.host || '127.0.0.1',
|
|
13
|
+
port: config.redis?.port || 6379, // Redis port
|
|
14
|
+
family: 4, // 4 (IPv4) or 6 (IPv6)
|
|
15
|
+
closeClient: true,
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
redisClients[db] = new Redis(redisConfig);
|
|
19
|
+
|
|
20
|
+
return redisClients[db];
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export default getRedis;
|
|
@@ -1,81 +1,81 @@
|
|
|
1
|
-
create schema if not exists log;
|
|
2
|
-
|
|
3
|
-
-- DROP TABLE IF EXISTS log.table_changes cascade;
|
|
4
|
-
CREATE TABLE IF NOT EXISTS log.table_changes();
|
|
5
|
-
ALTER TABLE log.table_changes ADD COLUMN IF NOT EXISTS change_id text NOT NULL DEFAULT next_id();
|
|
6
|
-
ALTER TABLE log.table_changes ADD COLUMN IF NOT EXISTS change_type text;
|
|
7
|
-
ALTER TABLE log.table_changes ADD COLUMN IF NOT EXISTS change_date date;
|
|
8
|
-
ALTER TABLE log.table_changes ADD COLUMN IF NOT EXISTS change_user_id text;
|
|
9
|
-
ALTER TABLE log.table_changes ADD COLUMN IF NOT EXISTS entity_type text; -- table_name
|
|
10
|
-
ALTER TABLE log.table_changes ADD COLUMN IF NOT EXISTS entity_id text; -- object_id
|
|
11
|
-
ALTER TABLE log.table_changes ADD COLUMN IF NOT EXISTS uid text;
|
|
12
|
-
ALTER TABLE log.table_changes ADD COLUMN IF NOT EXISTS cdate timestamp without time zone DEFAULT (now())::timestamp without time zone;
|
|
13
|
-
ALTER TABLE log.table_changes ADD COLUMN IF NOT EXISTS editor_id text;
|
|
14
|
-
ALTER TABLE log.table_changes ADD COLUMN IF NOT EXISTS editor_date timestamp without time zone;
|
|
15
|
-
|
|
16
|
-
-- DROP TABLE IF EXISTS log.table_changes_data;
|
|
17
|
-
CREATE TABLE IF NOT EXISTS log.table_changes_data();
|
|
18
|
-
ALTER TABLE log.table_changes_data ADD COLUMN IF NOT EXISTS change_data_id text NOT NULL DEFAULT next_id();
|
|
19
|
-
ALTER TABLE log.table_changes_data ADD COLUMN IF NOT EXISTS change_id text not null;
|
|
20
|
-
ALTER TABLE log.table_changes_data ADD COLUMN IF NOT EXISTS entity_key text; -- column_name
|
|
21
|
-
ALTER TABLE log.table_changes_data ADD COLUMN IF NOT EXISTS value_old text;
|
|
22
|
-
ALTER TABLE log.table_changes_data ADD COLUMN IF NOT EXISTS value_new text;
|
|
23
|
-
ALTER TABLE log.table_changes_data ADD COLUMN IF NOT EXISTS uid text;
|
|
24
|
-
ALTER TABLE log.table_changes_data ADD COLUMN IF NOT EXISTS cdate timestamp without time zone DEFAULT (now())::timestamp without time zone;
|
|
25
|
-
ALTER TABLE log.table_changes_data ADD COLUMN IF NOT EXISTS editor_id text;
|
|
26
|
-
ALTER TABLE log.table_changes_data ADD COLUMN IF NOT EXISTS editor_date timestamp without time zone;
|
|
27
|
-
|
|
28
|
-
-- DROP TABLE IF EXISTS log.user_auth;
|
|
29
|
-
CREATE TABLE IF NOT EXISTS log.user_auth();
|
|
30
|
-
ALTER TABLE log.user_auth ADD COLUMN IF NOT EXISTS user_auth_id text NOT NULL DEFAULT next_id();
|
|
31
|
-
ALTER TABLE log.user_auth ADD COLUMN IF NOT EXISTS user_id text;
|
|
32
|
-
ALTER TABLE log.user_auth ADD COLUMN IF NOT EXISTS auth_date timestamp without time zone;
|
|
33
|
-
ALTER TABLE log.user_auth ADD COLUMN IF NOT EXISTS auth_type text;
|
|
34
|
-
ALTER TABLE log.user_auth ADD COLUMN IF NOT EXISTS uid text;
|
|
35
|
-
ALTER TABLE log.user_auth ADD COLUMN IF NOT EXISTS cdate timestamp without time zone DEFAULT (now())::timestamp without time zone;
|
|
36
|
-
ALTER TABLE log.user_auth ADD COLUMN IF NOT EXISTS editor_id text;
|
|
37
|
-
ALTER TABLE log.user_auth ADD COLUMN IF NOT EXISTS editor_date timestamp without time zone;
|
|
38
|
-
|
|
39
|
-
COMMENT ON TABLE log.table_changes IS 'Логи подій змін в БД';
|
|
40
|
-
COMMENT ON COLUMN log.table_changes.change_type IS 'Тип події (insert / update / delete)';
|
|
41
|
-
COMMENT ON COLUMN log.table_changes.change_date IS 'Дата внесення змін до БД';
|
|
42
|
-
COMMENT ON COLUMN log.table_changes.entity_type IS 'Таблиця, до якої вносяться зміни';
|
|
43
|
-
COMMENT ON COLUMN log.table_changes.entity_id IS 'ID строки, до якої вносяться зміни';
|
|
44
|
-
COMMENT ON COLUMN log.table_changes.change_user_id IS 'Ініціатор внесення змін';
|
|
45
|
-
|
|
46
|
-
COMMENT ON TABLE log.table_changes_data IS 'Логи змін в таблицях БД';
|
|
47
|
-
COMMENT ON COLUMN log.table_changes_data.change_id IS 'ID події зміни в БД';
|
|
48
|
-
COMMENT ON COLUMN log.table_changes_data.entity_key IS 'Колонка таблиці, до якої вносяться зміни';
|
|
49
|
-
COMMENT ON COLUMN log.table_changes_data.value_old IS 'Старе значення';
|
|
50
|
-
COMMENT ON COLUMN log.table_changes_data.value_new IS 'Нове значення';
|
|
51
|
-
|
|
52
|
-
COMMENT ON TABLE log.user_auth IS 'Логи авторизації';
|
|
53
|
-
COMMENT ON COLUMN log.user_auth.user_id IS 'ID користувача';
|
|
54
|
-
COMMENT ON COLUMN log.user_auth.auth_date IS 'Дата авторизації';
|
|
55
|
-
COMMENT ON COLUMN log.user_auth.auth_type IS 'Тип авторизації';
|
|
56
|
-
|
|
57
|
-
ALTER TABLE log.table_changes DROP CONSTRAINT IF EXISTS log_table_changes_pkey cascade;
|
|
58
|
-
ALTER TABLE log.table_changes_data DROP CONSTRAINT IF EXISTS log_table_changes_data_pkey;
|
|
59
|
-
ALTER TABLE log.table_changes_data DROP CONSTRAINT IF EXISTS log_table_changes_data_change_id_fkey;
|
|
60
|
-
ALTER TABLE log.user_auth DROP CONSTRAINT IF EXISTS log_user_auth_pkey;
|
|
61
|
-
ALTER TABLE log.user_auth DROP CONSTRAINT IF EXISTS log_user_auth_user_id_fkey;
|
|
62
|
-
|
|
63
|
-
ALTER TABLE log.table_changes ADD CONSTRAINT log_table_changes_pkey PRIMARY KEY (change_id);
|
|
64
|
-
ALTER TABLE log.table_changes_data ADD CONSTRAINT log_table_changes_data_pkey PRIMARY KEY (change_data_id);
|
|
65
|
-
ALTER TABLE log.table_changes_data ADD CONSTRAINT log_table_changes_data_change_id_fkey FOREIGN KEY (change_id)
|
|
66
|
-
REFERENCES log.table_changes (change_id);
|
|
67
|
-
ALTER TABLE log.user_auth ADD CONSTRAINT log_user_auth_pkey PRIMARY KEY (user_auth_id);
|
|
68
|
-
-- ALTER TABLE log.user_auth ADD CONSTRAINT log_user_auth_user_id_fkey FOREIGN KEY (user_id) REFERENCES admin.users (uid) MATCH SIMPLE;
|
|
69
|
-
|
|
70
|
-
/* drop old columns */
|
|
71
|
-
alter table log.table_changes drop column if exists date_new;
|
|
72
|
-
alter table log.table_changes drop column if exists date_old;
|
|
73
|
-
alter table log.table_changes drop column if exists number_new;
|
|
74
|
-
alter table log.table_changes drop column if exists number_old;
|
|
75
|
-
alter table log.table_changes drop column if exists json_new;
|
|
76
|
-
alter table log.table_changes drop column if exists json_old;
|
|
77
|
-
alter table log.table_changes drop column if exists text_new;
|
|
78
|
-
alter table log.table_changes drop column if exists text_old;
|
|
79
|
-
alter table log.table_changes drop column if exists bool_new;
|
|
80
|
-
alter table log.table_changes drop column if exists bool_old;
|
|
1
|
+
create schema if not exists log;
|
|
2
|
+
|
|
3
|
+
-- DROP TABLE IF EXISTS log.table_changes cascade;
|
|
4
|
+
CREATE TABLE IF NOT EXISTS log.table_changes();
|
|
5
|
+
ALTER TABLE log.table_changes ADD COLUMN IF NOT EXISTS change_id text NOT NULL DEFAULT next_id();
|
|
6
|
+
ALTER TABLE log.table_changes ADD COLUMN IF NOT EXISTS change_type text;
|
|
7
|
+
ALTER TABLE log.table_changes ADD COLUMN IF NOT EXISTS change_date date;
|
|
8
|
+
ALTER TABLE log.table_changes ADD COLUMN IF NOT EXISTS change_user_id text;
|
|
9
|
+
ALTER TABLE log.table_changes ADD COLUMN IF NOT EXISTS entity_type text; -- table_name
|
|
10
|
+
ALTER TABLE log.table_changes ADD COLUMN IF NOT EXISTS entity_id text; -- object_id
|
|
11
|
+
ALTER TABLE log.table_changes ADD COLUMN IF NOT EXISTS uid text;
|
|
12
|
+
ALTER TABLE log.table_changes ADD COLUMN IF NOT EXISTS cdate timestamp without time zone DEFAULT (now())::timestamp without time zone;
|
|
13
|
+
ALTER TABLE log.table_changes ADD COLUMN IF NOT EXISTS editor_id text;
|
|
14
|
+
ALTER TABLE log.table_changes ADD COLUMN IF NOT EXISTS editor_date timestamp without time zone;
|
|
15
|
+
|
|
16
|
+
-- DROP TABLE IF EXISTS log.table_changes_data;
|
|
17
|
+
CREATE TABLE IF NOT EXISTS log.table_changes_data();
|
|
18
|
+
ALTER TABLE log.table_changes_data ADD COLUMN IF NOT EXISTS change_data_id text NOT NULL DEFAULT next_id();
|
|
19
|
+
ALTER TABLE log.table_changes_data ADD COLUMN IF NOT EXISTS change_id text not null;
|
|
20
|
+
ALTER TABLE log.table_changes_data ADD COLUMN IF NOT EXISTS entity_key text; -- column_name
|
|
21
|
+
ALTER TABLE log.table_changes_data ADD COLUMN IF NOT EXISTS value_old text;
|
|
22
|
+
ALTER TABLE log.table_changes_data ADD COLUMN IF NOT EXISTS value_new text;
|
|
23
|
+
ALTER TABLE log.table_changes_data ADD COLUMN IF NOT EXISTS uid text;
|
|
24
|
+
ALTER TABLE log.table_changes_data ADD COLUMN IF NOT EXISTS cdate timestamp without time zone DEFAULT (now())::timestamp without time zone;
|
|
25
|
+
ALTER TABLE log.table_changes_data ADD COLUMN IF NOT EXISTS editor_id text;
|
|
26
|
+
ALTER TABLE log.table_changes_data ADD COLUMN IF NOT EXISTS editor_date timestamp without time zone;
|
|
27
|
+
|
|
28
|
+
-- DROP TABLE IF EXISTS log.user_auth;
|
|
29
|
+
CREATE TABLE IF NOT EXISTS log.user_auth();
|
|
30
|
+
ALTER TABLE log.user_auth ADD COLUMN IF NOT EXISTS user_auth_id text NOT NULL DEFAULT next_id();
|
|
31
|
+
ALTER TABLE log.user_auth ADD COLUMN IF NOT EXISTS user_id text;
|
|
32
|
+
ALTER TABLE log.user_auth ADD COLUMN IF NOT EXISTS auth_date timestamp without time zone;
|
|
33
|
+
ALTER TABLE log.user_auth ADD COLUMN IF NOT EXISTS auth_type text;
|
|
34
|
+
ALTER TABLE log.user_auth ADD COLUMN IF NOT EXISTS uid text;
|
|
35
|
+
ALTER TABLE log.user_auth ADD COLUMN IF NOT EXISTS cdate timestamp without time zone DEFAULT (now())::timestamp without time zone;
|
|
36
|
+
ALTER TABLE log.user_auth ADD COLUMN IF NOT EXISTS editor_id text;
|
|
37
|
+
ALTER TABLE log.user_auth ADD COLUMN IF NOT EXISTS editor_date timestamp without time zone;
|
|
38
|
+
|
|
39
|
+
COMMENT ON TABLE log.table_changes IS 'Логи подій змін в БД';
|
|
40
|
+
COMMENT ON COLUMN log.table_changes.change_type IS 'Тип події (insert / update / delete)';
|
|
41
|
+
COMMENT ON COLUMN log.table_changes.change_date IS 'Дата внесення змін до БД';
|
|
42
|
+
COMMENT ON COLUMN log.table_changes.entity_type IS 'Таблиця, до якої вносяться зміни';
|
|
43
|
+
COMMENT ON COLUMN log.table_changes.entity_id IS 'ID строки, до якої вносяться зміни';
|
|
44
|
+
COMMENT ON COLUMN log.table_changes.change_user_id IS 'Ініціатор внесення змін';
|
|
45
|
+
|
|
46
|
+
COMMENT ON TABLE log.table_changes_data IS 'Логи змін в таблицях БД';
|
|
47
|
+
COMMENT ON COLUMN log.table_changes_data.change_id IS 'ID події зміни в БД';
|
|
48
|
+
COMMENT ON COLUMN log.table_changes_data.entity_key IS 'Колонка таблиці, до якої вносяться зміни';
|
|
49
|
+
COMMENT ON COLUMN log.table_changes_data.value_old IS 'Старе значення';
|
|
50
|
+
COMMENT ON COLUMN log.table_changes_data.value_new IS 'Нове значення';
|
|
51
|
+
|
|
52
|
+
COMMENT ON TABLE log.user_auth IS 'Логи авторизації';
|
|
53
|
+
COMMENT ON COLUMN log.user_auth.user_id IS 'ID користувача';
|
|
54
|
+
COMMENT ON COLUMN log.user_auth.auth_date IS 'Дата авторизації';
|
|
55
|
+
COMMENT ON COLUMN log.user_auth.auth_type IS 'Тип авторизації';
|
|
56
|
+
|
|
57
|
+
ALTER TABLE log.table_changes DROP CONSTRAINT IF EXISTS log_table_changes_pkey cascade;
|
|
58
|
+
ALTER TABLE log.table_changes_data DROP CONSTRAINT IF EXISTS log_table_changes_data_pkey;
|
|
59
|
+
ALTER TABLE log.table_changes_data DROP CONSTRAINT IF EXISTS log_table_changes_data_change_id_fkey;
|
|
60
|
+
ALTER TABLE log.user_auth DROP CONSTRAINT IF EXISTS log_user_auth_pkey;
|
|
61
|
+
ALTER TABLE log.user_auth DROP CONSTRAINT IF EXISTS log_user_auth_user_id_fkey;
|
|
62
|
+
|
|
63
|
+
ALTER TABLE log.table_changes ADD CONSTRAINT log_table_changes_pkey PRIMARY KEY (change_id);
|
|
64
|
+
ALTER TABLE log.table_changes_data ADD CONSTRAINT log_table_changes_data_pkey PRIMARY KEY (change_data_id);
|
|
65
|
+
ALTER TABLE log.table_changes_data ADD CONSTRAINT log_table_changes_data_change_id_fkey FOREIGN KEY (change_id)
|
|
66
|
+
REFERENCES log.table_changes (change_id);
|
|
67
|
+
ALTER TABLE log.user_auth ADD CONSTRAINT log_user_auth_pkey PRIMARY KEY (user_auth_id);
|
|
68
|
+
-- ALTER TABLE log.user_auth ADD CONSTRAINT log_user_auth_user_id_fkey FOREIGN KEY (user_id) REFERENCES admin.users (uid) MATCH SIMPLE;
|
|
69
|
+
|
|
70
|
+
/* drop old columns */
|
|
71
|
+
alter table log.table_changes drop column if exists date_new;
|
|
72
|
+
alter table log.table_changes drop column if exists date_old;
|
|
73
|
+
alter table log.table_changes drop column if exists number_new;
|
|
74
|
+
alter table log.table_changes drop column if exists number_old;
|
|
75
|
+
alter table log.table_changes drop column if exists json_new;
|
|
76
|
+
alter table log.table_changes drop column if exists json_old;
|
|
77
|
+
alter table log.table_changes drop column if exists text_new;
|
|
78
|
+
alter table log.table_changes drop column if exists text_old;
|
|
79
|
+
alter table log.table_changes drop column if exists bool_new;
|
|
80
|
+
alter table log.table_changes drop column if exists bool_old;
|
|
81
81
|
alter table log.table_changes drop column if exists table_change_id;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
create schema if not exists admin;
|
|
2
|
-
create schema if not exists
|
|
2
|
+
create schema if not exists crm;
|
|
3
3
|
|
|
4
4
|
-- drop old
|
|
5
5
|
DROP TABLE IF EXISTS setting.extra_data;
|
|
@@ -72,7 +72,10 @@ drop table if exists admin.custom_column cascade;
|
|
|
72
72
|
CREATE TABLE IF NOT EXISTS admin.custom_column();
|
|
73
73
|
ALTER TABLE admin.custom_column DROP CONSTRAINT IF EXISTS admin_custom_column_column_id_pkey cascade;
|
|
74
74
|
alter table admin.custom_column drop constraint if exists admin_custom_column_key_entity_uid_unique;
|
|
75
|
-
|
|
75
|
+
|
|
76
|
+
ALTER TABLE admin.custom_column ADD COLUMN IF NOT EXISTS column_id text;
|
|
77
|
+
ALTER TABLE admin.custom_column ALTER COLUMN column_id SET NOT NULL;
|
|
78
|
+
ALTER TABLE admin.custom_column ALTER COLUMN column_id SET DEFAULT next_id();
|
|
76
79
|
|
|
77
80
|
ALTER TABLE admin.custom_column ADD COLUMN IF NOT EXISTS name text;
|
|
78
81
|
ALTER TABLE admin.custom_column ADD COLUMN IF NOT EXISTS entity text;
|
|
@@ -104,6 +107,7 @@ CREATE TABLE if not exists crm.extra_data();
|
|
|
104
107
|
ALTER TABLE crm.extra_data DROP CONSTRAINT IF EXISTS crm_extra_data_pkey;
|
|
105
108
|
ALTER TABLE crm.extra_data DROP CONSTRAINT IF EXISTS crm_extra_data_property_id_fkey;
|
|
106
109
|
ALTER TABLE crm.extra_data DROP CONSTRAINT IF EXISTS crm_extra_data_property_key_object_id_entity_unique;
|
|
110
|
+
|
|
107
111
|
ALTER TABLE crm.extra_data ADD COLUMN IF NOT EXISTS extra_data_id text;
|
|
108
112
|
ALTER TABLE crm.extra_data ALTER COLUMN extra_data_id SET NOT NULL;
|
|
109
113
|
ALTER TABLE crm.extra_data ALTER COLUMN extra_data_id SET DEFAULT next_id();
|
|
@@ -121,7 +125,9 @@ ALTER TABLE crm.extra_data ALTER COLUMN cdate SET DEFAULT date_trunc('seconds'::
|
|
|
121
125
|
ALTER TABLE crm.extra_data ADD COLUMN IF NOT EXISTS editor_id text;
|
|
122
126
|
ALTER TABLE crm.extra_data ADD COLUMN IF NOT EXISTS editor_date timestamp without time zone;
|
|
123
127
|
ALTER TABLE crm.extra_data ADD COLUMN IF NOT EXISTS files json;
|
|
128
|
+
|
|
124
129
|
ALTER TABLE crm.extra_data ADD CONSTRAINT crm_extra_data_pkey PRIMARY KEY (extra_data_id);
|
|
130
|
+
-- delete from crm.extra_data where property_id not in (select column_id from admin.custom_column);
|
|
125
131
|
ALTER TABLE crm.extra_data ADD CONSTRAINT crm_extra_data_property_id_fkey FOREIGN KEY (property_id) REFERENCES admin.custom_column (column_id) MATCH SIMPLE;
|
|
126
132
|
ALTER TABLE crm.extra_data ADD CONSTRAINT crm_extra_data_property_key_object_id_entity_unique UNIQUE (property_key, object_id, property_entity);
|
|
127
133
|
|
package/server.js
CHANGED
|
@@ -1,14 +1,26 @@
|
|
|
1
|
-
// This file contains code that we reuse
|
|
2
|
-
// between our tests.
|
|
3
|
-
import Fastify from 'fastify';
|
|
4
|
-
import config from './test/config.js';
|
|
5
|
-
import appService from './index.js';
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
app
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
1
|
+
// This file contains code that we reuse
|
|
2
|
+
// between our tests.
|
|
3
|
+
import Fastify from 'fastify';
|
|
4
|
+
import config from './test/config.js';
|
|
5
|
+
import appService from './index.js';
|
|
6
|
+
import logger from './logger/getLogger.js';
|
|
7
|
+
import loggerTest from './logger/logger.test.api.js';
|
|
8
|
+
|
|
9
|
+
const app = Fastify({ logger });
|
|
10
|
+
app.register(appService, config);
|
|
11
|
+
|
|
12
|
+
app.get('/logger-test', {
|
|
13
|
+
schema: {
|
|
14
|
+
querystring: {
|
|
15
|
+
name: { type: 'string' },
|
|
16
|
+
excitement: { type: 'integer' },
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
}, loggerTest);
|
|
20
|
+
|
|
21
|
+
app.listen({ host: '0.0.0.0', port: process.env.PORT || 3000 }, (err) => {
|
|
22
|
+
if (err) {
|
|
23
|
+
app.log.error(err);
|
|
24
|
+
process.exit(1);
|
|
25
|
+
}
|
|
26
|
+
});
|
|
@@ -1,44 +1,44 @@
|
|
|
1
|
-
import getTemplate from './utils/getTemplate.js';
|
|
2
|
-
import getMeta from '../../pg/funcs/getMeta.js';
|
|
3
|
-
import metaFormat from '../funcs/metaFormat/index.js';
|
|
4
|
-
|
|
5
|
-
export default async function card(req) {
|
|
6
|
-
const time = Date.now();
|
|
7
|
-
const {
|
|
8
|
-
pg, params = {}, query = {}, opt = {},
|
|
9
|
-
} = req;
|
|
10
|
-
|
|
11
|
-
const loadTable = await getTemplate('table', params.table);
|
|
12
|
-
|
|
13
|
-
if (!loadTable) { return { message: 'template not found', status: 404 }; }
|
|
14
|
-
|
|
15
|
-
const {
|
|
16
|
-
table, columns, meta, sql, cardSql,
|
|
17
|
-
} = loadTable;
|
|
18
|
-
|
|
19
|
-
const { pk, columns: dbColumns = [] } = await getMeta(table);
|
|
20
|
-
|
|
21
|
-
if (!pk) return { message: `table not found: ${table}`, status: 404 };
|
|
22
|
-
|
|
23
|
-
const cols = columns.map((el) => el.name || el).join(',');
|
|
24
|
-
const columnList = dbColumns.map((el) => el.name || el).join(',');
|
|
25
|
-
const sqlTable = sql?.filter?.((el) => !el?.disabled && el?.sql?.replace).map((el, i) => ` left join lateral (${el.sql}) ${el.name || `t${i}`} on 1=1 `)?.join('') || '';
|
|
26
|
-
const cardSqlFiltered = opt.id || params.id ? cardSql?.filter?.((el) => !el?.disabled && el?.name && el?.sql?.replace) : [];
|
|
27
|
-
const cardSqlTable = cardSqlFiltered?.length ? cardSqlFiltered.map((el, i) => ` left join lateral (select json_agg(row_to_json(q)) as ${el.name} from (${el.sql})q) ct${i} on 1=1 `).join('') || '' : '';
|
|
28
|
-
|
|
29
|
-
const where = [`"${pk}" = $1`, loadTable.query].filter((el) => el);
|
|
30
|
-
const cardColumns = cardSqlFiltered?.length ? `,${cardSqlFiltered.map((el) => el.name)}` : '';
|
|
31
|
-
const q = `select ${pk ? `"${pk}" as id,` : ''} ${columnList.includes('geom') ? 'st_asgeojson(geom)::json as geom,' : ''} ${cols || '*'} ${cardColumns} from ${table} t ${sqlTable} ${cardSqlTable}
|
|
32
|
-
where ${where.join(' and ') || 'true'} limit 1`;
|
|
33
|
-
|
|
34
|
-
if (query.sql === '1') { return q; }
|
|
35
|
-
|
|
36
|
-
const { rows } = await pg.query(q, [opt.id || params.id]);
|
|
37
|
-
|
|
38
|
-
await metaFormat({ rows, table: params.table });
|
|
39
|
-
|
|
40
|
-
const data = meta.card?.length ? meta.card.reduce((acc, curr) => Object.assign(acc, { [columns.find((col) => col.name === curr)?.ua || '']: rows[0][curr] }), {}) : {};
|
|
41
|
-
return {
|
|
42
|
-
time: Date.now() - time, data,
|
|
43
|
-
};
|
|
44
|
-
}
|
|
1
|
+
import getTemplate from './utils/getTemplate.js';
|
|
2
|
+
import getMeta from '../../pg/funcs/getMeta.js';
|
|
3
|
+
import metaFormat from '../funcs/metaFormat/index.js';
|
|
4
|
+
|
|
5
|
+
export default async function card(req) {
|
|
6
|
+
const time = Date.now();
|
|
7
|
+
const {
|
|
8
|
+
pg, params = {}, query = {}, opt = {},
|
|
9
|
+
} = req;
|
|
10
|
+
|
|
11
|
+
const loadTable = await getTemplate('table', params.table);
|
|
12
|
+
|
|
13
|
+
if (!loadTable) { return { message: 'template not found', status: 404 }; }
|
|
14
|
+
|
|
15
|
+
const {
|
|
16
|
+
table, columns, meta, sql, cardSql,
|
|
17
|
+
} = loadTable;
|
|
18
|
+
|
|
19
|
+
const { pk, columns: dbColumns = [] } = await getMeta(table);
|
|
20
|
+
|
|
21
|
+
if (!pk) return { message: `table not found: ${table}`, status: 404 };
|
|
22
|
+
|
|
23
|
+
const cols = columns.map((el) => el.name || el).join(',');
|
|
24
|
+
const columnList = dbColumns.map((el) => el.name || el).join(',');
|
|
25
|
+
const sqlTable = sql?.filter?.((el) => !el?.disabled && el?.sql?.replace).map((el, i) => ` left join lateral (${el.sql}) ${el.name || `t${i}`} on 1=1 `)?.join('') || '';
|
|
26
|
+
const cardSqlFiltered = opt.id || params.id ? cardSql?.filter?.((el) => !el?.disabled && el?.name && el?.sql?.replace) : [];
|
|
27
|
+
const cardSqlTable = cardSqlFiltered?.length ? cardSqlFiltered.map((el, i) => ` left join lateral (select json_agg(row_to_json(q)) as ${el.name} from (${el.sql})q) ct${i} on 1=1 `).join('') || '' : '';
|
|
28
|
+
|
|
29
|
+
const where = [`"${pk}" = $1`, loadTable.query].filter((el) => el);
|
|
30
|
+
const cardColumns = cardSqlFiltered?.length ? `,${cardSqlFiltered.map((el) => el.name)}` : '';
|
|
31
|
+
const q = `select ${pk ? `"${pk}" as id,` : ''} ${columnList.includes('geom') ? 'st_asgeojson(geom)::json as geom,' : ''} ${cols || '*'} ${cardColumns} from ${table} t ${sqlTable} ${cardSqlTable}
|
|
32
|
+
where ${where.join(' and ') || 'true'} limit 1`;
|
|
33
|
+
|
|
34
|
+
if (query.sql === '1') { return q; }
|
|
35
|
+
|
|
36
|
+
const { rows } = await pg.query(q, [opt.id || params.id]);
|
|
37
|
+
|
|
38
|
+
await metaFormat({ rows, table: params.table });
|
|
39
|
+
|
|
40
|
+
const data = meta.card?.length ? meta.card.reduce((acc, curr) => Object.assign(acc, { [columns.find((col) => col.name === curr)?.ua || '']: rows[0][curr] }), {}) : {};
|
|
41
|
+
return {
|
|
42
|
+
time: Date.now() - time, data,
|
|
43
|
+
};
|
|
44
|
+
}
|
|
@@ -1,28 +1,28 @@
|
|
|
1
|
-
import getTemplate from './utils/getTemplate.js';
|
|
2
|
-
|
|
3
|
-
const sql = `select property_key as key, property_json as json, property_int as int,
|
|
4
|
-
property_text as text from admin.properties where 1=1`;
|
|
5
|
-
|
|
6
|
-
async function getSettings({ pg }) {
|
|
7
|
-
const { rows = [] } = await pg.query(sql);
|
|
8
|
-
const data = rows.reduce((acc, curr) => Object.assign(acc, { [curr.key]: curr.json || curr.int || curr.text }), {});
|
|
9
|
-
return data;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export default async function formFunction(req) {
|
|
13
|
-
const time = Date.now();
|
|
14
|
-
const { pg, params } = req;
|
|
15
|
-
const form = await getTemplate('form', params.form);
|
|
16
|
-
if (!form) { return { status: 404, message: 'not found' }; }
|
|
17
|
-
|
|
18
|
-
// replace settings
|
|
19
|
-
const arr = JSON.stringify(form).match(/{{settings.([^}]*)}}/g);
|
|
20
|
-
if (arr?.length) {
|
|
21
|
-
const string = JSON.stringify(form);
|
|
22
|
-
const settings = await getSettings({ pg });
|
|
23
|
-
const match = arr.reduce((acc, curr) => Object.assign(acc, { [curr]: settings[curr.replace(/^{{settings./g, '').replace(/}}$/, '')] }), {});
|
|
24
|
-
const res = Object.keys(match).reduce((s, m) => s.replace(m, match[m]), string);
|
|
25
|
-
return { time: Date.now() - time, form: JSON.parse(res) };
|
|
26
|
-
}
|
|
27
|
-
return { time: Date.now() - time, form };
|
|
28
|
-
}
|
|
1
|
+
import getTemplate from './utils/getTemplate.js';
|
|
2
|
+
|
|
3
|
+
const sql = `select property_key as key, property_json as json, property_int as int,
|
|
4
|
+
property_text as text from admin.properties where 1=1`;
|
|
5
|
+
|
|
6
|
+
async function getSettings({ pg }) {
|
|
7
|
+
const { rows = [] } = await pg.query(sql);
|
|
8
|
+
const data = rows.reduce((acc, curr) => Object.assign(acc, { [curr.key]: curr.json || curr.int || curr.text }), {});
|
|
9
|
+
return data;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export default async function formFunction(req) {
|
|
13
|
+
const time = Date.now();
|
|
14
|
+
const { pg, params } = req;
|
|
15
|
+
const form = await getTemplate('form', params.form);
|
|
16
|
+
if (!form) { return { status: 404, message: 'not found' }; }
|
|
17
|
+
|
|
18
|
+
// replace settings
|
|
19
|
+
const arr = JSON.stringify(form).match(/{{settings.([^}]*)}}/g);
|
|
20
|
+
if (arr?.length) {
|
|
21
|
+
const string = JSON.stringify(form);
|
|
22
|
+
const settings = await getSettings({ pg });
|
|
23
|
+
const match = arr.reduce((acc, curr) => Object.assign(acc, { [curr]: settings[curr.replace(/^{{settings./g, '').replace(/}}$/, '')] }), {});
|
|
24
|
+
const res = Object.keys(match).reduce((s, m) => s.replace(m, match[m]), string);
|
|
25
|
+
return { time: Date.now() - time, form: JSON.parse(res) };
|
|
26
|
+
}
|
|
27
|
+
return { time: Date.now() - time, form };
|
|
28
|
+
}
|
|
@@ -1,72 +1,72 @@
|
|
|
1
|
-
import { test } from 'node:test';
|
|
2
|
-
import assert from 'node:assert';
|
|
3
|
-
|
|
4
|
-
import build from '../../helper.js';
|
|
5
|
-
|
|
6
|
-
import setToken from '../../crud/funcs/setToken.js';
|
|
7
|
-
import config from '../config.js';
|
|
8
|
-
|
|
9
|
-
test('api crud xss', async (t) => {
|
|
10
|
-
const app = await build(t);
|
|
11
|
-
const session = { passport: { user: { uid: '1' } } };
|
|
12
|
-
app.addHook('onRequest', async (req) => {
|
|
13
|
-
req.session = session;
|
|
14
|
-
});
|
|
15
|
-
// app.decorateRequest('session', session);
|
|
16
|
-
|
|
17
|
-
const prefix = config.prefix || '/api';
|
|
18
|
-
|
|
19
|
-
let addTokens;
|
|
20
|
-
let editTokens;
|
|
21
|
-
|
|
22
|
-
// before
|
|
23
|
-
t.test('setToken', async () => {
|
|
24
|
-
addTokens = setToken({
|
|
25
|
-
ids: [JSON.stringify({ add: 'gis.dataset', form: 'test.dataset.form' })],
|
|
26
|
-
mode: 'a',
|
|
27
|
-
uid: 1,
|
|
28
|
-
array: 1,
|
|
29
|
-
});
|
|
30
|
-
editTokens = setToken({
|
|
31
|
-
ids: [JSON.stringify({ id: '5400000', table: 'gis.dataset', form: 'test.dataset.form' })],
|
|
32
|
-
mode: 'w',
|
|
33
|
-
uid: 1,
|
|
34
|
-
array: 1,
|
|
35
|
-
});
|
|
36
|
-
assert.ok(addTokens.length === 1 && editTokens.length === 1, 'invalid token');
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
await t.test('POST /insert', async () => {
|
|
40
|
-
const res = await app.inject({
|
|
41
|
-
method: 'POST',
|
|
42
|
-
url: `${prefix}/table/${addTokens[0]}`,
|
|
43
|
-
body: { dataset_name: '<a onClick="alert("XSS Injection")">xss injection</a>', dataset_id: '5400000' },
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
const rep = JSON.parse(res?.body);
|
|
47
|
-
console.log(rep)
|
|
48
|
-
assert.ok(rep.status, 409);
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
await t.test('PUT /update', async () => {
|
|
52
|
-
const res = await app.inject({
|
|
53
|
-
method: 'PUT',
|
|
54
|
-
url: `${prefix}/table/${editTokens[0]}/${editTokens[0]}`,
|
|
55
|
-
body: { editor_id: '11', dataset_name: '<a onClick="alert("XSS Injection")">xss injection</a>' },
|
|
56
|
-
});
|
|
57
|
-
|
|
58
|
-
const rep = JSON.parse(res?.body);
|
|
59
|
-
console.log(rep)
|
|
60
|
-
assert.equal(rep.status, 409);
|
|
61
|
-
});
|
|
62
|
-
await t.test('DELETE /delete', async () => {
|
|
63
|
-
const res = await app.inject({
|
|
64
|
-
method: 'DELETE',
|
|
65
|
-
url: `${prefix}/table/gis.dataset/5400000`,
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
const rep = JSON.parse(res?.body);
|
|
69
|
-
console.log(rep)
|
|
70
|
-
assert.ok(rep);
|
|
71
|
-
});
|
|
72
|
-
});
|
|
1
|
+
import { test } from 'node:test';
|
|
2
|
+
import assert from 'node:assert';
|
|
3
|
+
|
|
4
|
+
import build from '../../helper.js';
|
|
5
|
+
|
|
6
|
+
import setToken from '../../crud/funcs/setToken.js';
|
|
7
|
+
import config from '../config.js';
|
|
8
|
+
|
|
9
|
+
test('api crud xss', async (t) => {
|
|
10
|
+
const app = await build(t);
|
|
11
|
+
const session = { passport: { user: { uid: '1' } } };
|
|
12
|
+
app.addHook('onRequest', async (req) => {
|
|
13
|
+
req.session = session;
|
|
14
|
+
});
|
|
15
|
+
// app.decorateRequest('session', session);
|
|
16
|
+
|
|
17
|
+
const prefix = config.prefix || '/api';
|
|
18
|
+
|
|
19
|
+
let addTokens;
|
|
20
|
+
let editTokens;
|
|
21
|
+
|
|
22
|
+
// before
|
|
23
|
+
t.test('setToken', async () => {
|
|
24
|
+
addTokens = setToken({
|
|
25
|
+
ids: [JSON.stringify({ add: 'gis.dataset', form: 'test.dataset.form' })],
|
|
26
|
+
mode: 'a',
|
|
27
|
+
uid: 1,
|
|
28
|
+
array: 1,
|
|
29
|
+
});
|
|
30
|
+
editTokens = setToken({
|
|
31
|
+
ids: [JSON.stringify({ id: '5400000', table: 'gis.dataset', form: 'test.dataset.form' })],
|
|
32
|
+
mode: 'w',
|
|
33
|
+
uid: 1,
|
|
34
|
+
array: 1,
|
|
35
|
+
});
|
|
36
|
+
assert.ok(addTokens.length === 1 && editTokens.length === 1, 'invalid token');
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
await t.test('POST /insert', async () => {
|
|
40
|
+
const res = await app.inject({
|
|
41
|
+
method: 'POST',
|
|
42
|
+
url: `${prefix}/table/${addTokens[0]}`,
|
|
43
|
+
body: { dataset_name: '<a onClick="alert("XSS Injection")">xss injection</a>', dataset_id: '5400000' },
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
const rep = JSON.parse(res?.body);
|
|
47
|
+
console.log(rep)
|
|
48
|
+
assert.ok(rep.status, 409);
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
await t.test('PUT /update', async () => {
|
|
52
|
+
const res = await app.inject({
|
|
53
|
+
method: 'PUT',
|
|
54
|
+
url: `${prefix}/table/${editTokens[0]}/${editTokens[0]}`,
|
|
55
|
+
body: { editor_id: '11', dataset_name: '<a onClick="alert("XSS Injection")">xss injection</a>' },
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
const rep = JSON.parse(res?.body);
|
|
59
|
+
console.log(rep)
|
|
60
|
+
assert.equal(rep.status, 409);
|
|
61
|
+
});
|
|
62
|
+
await t.test('DELETE /delete', async () => {
|
|
63
|
+
const res = await app.inject({
|
|
64
|
+
method: 'DELETE',
|
|
65
|
+
url: `${prefix}/table/gis.dataset/5400000`,
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
const rep = JSON.parse(res?.body);
|
|
69
|
+
console.log(rep)
|
|
70
|
+
assert.ok(rep);
|
|
71
|
+
});
|
|
72
|
+
});
|
package/test/config.example
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
import config from '../config.js';
|
|
2
|
-
|
|
3
|
-
Object.assign(config, {
|
|
4
|
-
folder: 'test/templates',
|
|
5
|
-
pg: {
|
|
6
|
-
host: '192.168.3.160',
|
|
7
|
-
port: 5434,
|
|
8
|
-
database: 'mbk_rivne_dma',
|
|
9
|
-
user: 'postgres',
|
|
10
|
-
password: 'postgres',
|
|
11
|
-
},
|
|
12
|
-
redis: {
|
|
13
|
-
host: '192.168.3.160',
|
|
14
|
-
port: 6379,
|
|
15
|
-
family: 4,
|
|
16
|
-
},
|
|
17
|
-
});
|
|
18
|
-
export default config;
|
|
1
|
+
import config from '../config.js';
|
|
2
|
+
|
|
3
|
+
Object.assign(config, {
|
|
4
|
+
folder: 'test/templates',
|
|
5
|
+
pg: {
|
|
6
|
+
host: '192.168.3.160',
|
|
7
|
+
port: 5434,
|
|
8
|
+
database: 'mbk_rivne_dma',
|
|
9
|
+
user: 'postgres',
|
|
10
|
+
password: 'postgres',
|
|
11
|
+
},
|
|
12
|
+
redis: {
|
|
13
|
+
host: '192.168.3.160',
|
|
14
|
+
port: 6379,
|
|
15
|
+
family: 4,
|
|
16
|
+
},
|
|
17
|
+
});
|
|
18
|
+
export default config;
|