@opengis/fastify-table 1.0.45 → 1.0.47
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/Changelog.md +8 -0
- package/crud/controllers/properties.add.js +51 -0
- package/crud/controllers/properties.get.js +20 -0
- package/crud/index.js +35 -29
- package/package.json +1 -1
- package/server/migrations/admin.sql +246 -0
- package/server/migrations/crm.sql +31 -1
- package/table/controllers/data.js +4 -2
- package/table/controllers/utils/getTemplate.js +28 -28
- package/test/api/crud.test.js +20 -0
package/Changelog.md
CHANGED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import dataInsert from "../funcs/dataInsert.js";
|
|
2
|
+
|
|
3
|
+
const table = 'crm.properties';
|
|
4
|
+
|
|
5
|
+
function checkKeyType({ body, key }) {
|
|
6
|
+
if (typeof body[key] === 'number' && !body[key].toString().includes('.')) {
|
|
7
|
+
return { [key]: 'int' };
|
|
8
|
+
} else if (typeof body[key] === 'object') {
|
|
9
|
+
return { [key]: 'json' };
|
|
10
|
+
} else if (Date.parse(body[key], 'yyyy/MM/ddTHH:mm:ss.000Z')) {
|
|
11
|
+
return { [key]: 'date' };
|
|
12
|
+
}
|
|
13
|
+
return { [key]: 'text' };
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export default async function addExtraProperties({
|
|
17
|
+
pg, params = {}, body = {},
|
|
18
|
+
}) {
|
|
19
|
+
const { id } = params;
|
|
20
|
+
if (!id) {
|
|
21
|
+
return { message: 'not enougn params: 1', status: 400 };
|
|
22
|
+
}
|
|
23
|
+
const extraProperties = Object.keys(body);
|
|
24
|
+
if (!extraProperties.length) {
|
|
25
|
+
return { message: 'not enougn params: 2', status: 400 };
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
if (!pg.pk?.[table]) {
|
|
29
|
+
return { message: 'table not found: crm.properties', status: 400 };
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
try {
|
|
33
|
+
await pg.query(`delete from crm.properties where object_id=$1`, [id]);
|
|
34
|
+
const keyTypeMatch = extraProperties.filter((key) => body[key]).reduce((acc, curr) => Object.assign(acc, checkKeyType({ body, key: curr })), {});
|
|
35
|
+
const res = await Promise.all(Object.keys(keyTypeMatch).map(async (key) => {
|
|
36
|
+
const propertyType = keyTypeMatch[key];
|
|
37
|
+
const { rows = [] } = await dataInsert({
|
|
38
|
+
pg, table, data: {
|
|
39
|
+
property_type: propertyType,
|
|
40
|
+
property_key: key,
|
|
41
|
+
object_id: id,
|
|
42
|
+
[`property_${propertyType}`]: body[key],
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
return { id: rows[0]?.property_id, type: propertyType, value: body[key] };
|
|
46
|
+
}));
|
|
47
|
+
return { message: { rows: res }, status: 200 };
|
|
48
|
+
} catch (err) {
|
|
49
|
+
return { error: err.toString(), status: 500 };
|
|
50
|
+
}
|
|
51
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export default async function getExtraProperties({
|
|
2
|
+
pg, params = {},
|
|
3
|
+
}) {
|
|
4
|
+
const { id } = params;
|
|
5
|
+
if (!id) {
|
|
6
|
+
return { message: 'not enougn params', status: 400 };
|
|
7
|
+
}
|
|
8
|
+
try {
|
|
9
|
+
const { rows = [] } = pg.pk?.['crm.properties']
|
|
10
|
+
? await pg.query(`select property_key, property_type, property_text, property_int,
|
|
11
|
+
property_json, property_date from crm.properties where property_key is not null and object_id=$1`, [id])
|
|
12
|
+
: {};
|
|
13
|
+
if (!rows.length) return {};
|
|
14
|
+
|
|
15
|
+
const data = rows.reduce((acc, curr) => Object.assign(acc, { [curr.property_key]: curr[`property_${curr.property_type}`] }), {});
|
|
16
|
+
return { message: data, status: 200 };
|
|
17
|
+
} catch (err) {
|
|
18
|
+
return { error: err.toString(), status: 500 };
|
|
19
|
+
}
|
|
20
|
+
}
|
package/crud/index.js
CHANGED
|
@@ -1,29 +1,35 @@
|
|
|
1
|
-
import getOPt from './funcs/getOpt.js';
|
|
2
|
-
import setOpt from './funcs/setOpt.js';
|
|
3
|
-
import isFileExists from './funcs/isFileExists.js';
|
|
4
|
-
import dataUpdate from './funcs/dataUpdate.js';
|
|
5
|
-
import dataInsert from './funcs/dataInsert.js';
|
|
6
|
-
|
|
7
|
-
import update from './controllers/update.js';
|
|
8
|
-
import insert from './controllers/insert.js';
|
|
9
|
-
import deleteCrud from './controllers/deleteCrud.js';
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
fastify.decorate('
|
|
20
|
-
|
|
21
|
-
fastify.decorate('
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
fastify.
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
|
|
1
|
+
import getOPt from './funcs/getOpt.js';
|
|
2
|
+
import setOpt from './funcs/setOpt.js';
|
|
3
|
+
import isFileExists from './funcs/isFileExists.js';
|
|
4
|
+
import dataUpdate from './funcs/dataUpdate.js';
|
|
5
|
+
import dataInsert from './funcs/dataInsert.js';
|
|
6
|
+
|
|
7
|
+
import update from './controllers/update.js';
|
|
8
|
+
import insert from './controllers/insert.js';
|
|
9
|
+
import deleteCrud from './controllers/deleteCrud.js';
|
|
10
|
+
|
|
11
|
+
import getExtraProperties from './controllers/properties.get.js';
|
|
12
|
+
import addExtraProperties from './controllers/properties.add.js';
|
|
13
|
+
|
|
14
|
+
// import config from '../config.js';
|
|
15
|
+
|
|
16
|
+
async function plugin(fastify, config = {}) {
|
|
17
|
+
const prefix = config.prefix || '/api';
|
|
18
|
+
// funcs
|
|
19
|
+
fastify.decorate('setOpt', setOpt);
|
|
20
|
+
fastify.decorate('getOpt', getOPt);
|
|
21
|
+
fastify.decorate('dataUpdate', dataUpdate);
|
|
22
|
+
fastify.decorate('dataInsert', dataInsert);
|
|
23
|
+
|
|
24
|
+
fastify.decorate('isFileExists', isFileExists);
|
|
25
|
+
|
|
26
|
+
// api
|
|
27
|
+
fastify.put(`${prefix}/table/:table/:id`, {}, update);
|
|
28
|
+
fastify.delete(`${prefix}/table/:table/:id`, {}, deleteCrud);
|
|
29
|
+
fastify.post(`${prefix}/table/:table`, {}, insert);
|
|
30
|
+
|
|
31
|
+
fastify.get(`${prefix}/properties/:id`, {}, getExtraProperties);
|
|
32
|
+
fastify.post(`${prefix}/properties/:id`, {}, addExtraProperties);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export default plugin;
|
package/package.json
CHANGED
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
create schema if not exists admin;
|
|
2
|
+
|
|
3
|
+
-- DROP TABLE is exists admin.users;
|
|
4
|
+
CREATE TABLE if not exists admin.users();
|
|
5
|
+
ALTER TABLE admin.users add column if not exists uid text NOT NULL DEFAULT next_id();
|
|
6
|
+
ALTER TABLE admin.users DROP CONSTRAINT if exists admin_user_uid_pkey cascade;
|
|
7
|
+
|
|
8
|
+
ALTER TABLE admin.users add column if not exists login text;
|
|
9
|
+
ALTER TABLE admin.users add column if not exists password text NOT NULL DEFAULT ''::text;
|
|
10
|
+
ALTER TABLE admin.users add column if not exists user_name text;
|
|
11
|
+
ALTER TABLE admin.users add column if not exists sur_name text;
|
|
12
|
+
ALTER TABLE admin.users add column if not exists father_name text;
|
|
13
|
+
ALTER TABLE admin.users add column if not exists email text;
|
|
14
|
+
ALTER TABLE admin.users add column if not exists phone text;
|
|
15
|
+
ALTER TABLE admin.users add column if not exists avatar text;
|
|
16
|
+
ALTER TABLE admin.users add column if not exists enabled boolean;
|
|
17
|
+
ALTER TABLE admin.users add column if not exists user_personal_code text;
|
|
18
|
+
ALTER TABLE admin.users add column if not exists last_activity_date timestamp without time zone;
|
|
19
|
+
ALTER TABLE admin.users add column if not exists user_type text DEFAULT 'regular'::text;
|
|
20
|
+
ALTER TABLE admin.users add column if not exists salt text;
|
|
21
|
+
ALTER TABLE admin.users add column if not exists cdate timestamp without time zone DEFAULT date_trunc('seconds'::text, now());
|
|
22
|
+
ALTER TABLE admin.users add column if not exists editor_id text;
|
|
23
|
+
ALTER TABLE admin.users add column if not exists editor_date timestamp without time zone;
|
|
24
|
+
|
|
25
|
+
ALTER TABLE admin.users add CONSTRAINT admin_user_uid_pkey PRIMARY KEY (uid);
|
|
26
|
+
|
|
27
|
+
COMMENT ON COLUMN admin.users.uid IS 'ID користувача';
|
|
28
|
+
COMMENT ON COLUMN admin.users.login IS 'Логін користувача';
|
|
29
|
+
COMMENT ON COLUMN admin.users.password IS 'Пароль користувача';
|
|
30
|
+
COMMENT ON COLUMN admin.users.user_name IS 'Ім''я користувача';
|
|
31
|
+
COMMENT ON COLUMN admin.users.sur_name IS 'Прізвище користувача';
|
|
32
|
+
COMMENT ON COLUMN admin.users.father_name IS 'По-батькові користувача';
|
|
33
|
+
COMMENT ON COLUMN admin.users.email IS 'Ел. пошта користувача';
|
|
34
|
+
COMMENT ON COLUMN admin.users.phone IS 'Номер телефону користувача';
|
|
35
|
+
COMMENT ON COLUMN admin.users.avatar IS 'Аватар';
|
|
36
|
+
COMMENT ON COLUMN admin.users.enabled IS 'Вкл. / Відкл';
|
|
37
|
+
COMMENT ON COLUMN admin.users.last_activity_date IS 'Дата останньої активності';
|
|
38
|
+
COMMENT ON COLUMN admin.users.user_type IS 'Тип користувача';
|
|
39
|
+
COMMENT ON COLUMN admin.users.salt IS 'Сіль';
|
|
40
|
+
|
|
41
|
+
-- drop table if exists admin.user_group;
|
|
42
|
+
CREATE TABLE if not exists admin.user_group();
|
|
43
|
+
alter table admin.user_group DROP CONSTRAINT if exists admin_user_group_id_pkey cascade;
|
|
44
|
+
|
|
45
|
+
ALTER TABLE admin.user_group ADD COLUMN if not exists user_group_id text;
|
|
46
|
+
ALTER TABLE admin.user_group ALTER COLUMN user_group_id SET NOT NULL;
|
|
47
|
+
ALTER TABLE admin.user_group ALTER COLUMN user_group_id SET DEFAULT next_id();
|
|
48
|
+
ALTER TABLE admin.user_group ADD COLUMN if not exists group_name text;
|
|
49
|
+
ALTER TABLE admin.user_group ADD COLUMN if not exists enabled boolean;
|
|
50
|
+
ALTER TABLE admin.user_group ADD COLUMN if not exists cdate timestamp without time zone;
|
|
51
|
+
ALTER TABLE admin.user_group ALTER COLUMN cdate SET DEFAULT date_trunc('seconds'::text, now());
|
|
52
|
+
ALTER TABLE admin.user_group ADD COLUMN if not exists uid text;
|
|
53
|
+
ALTER TABLE admin.user_group ADD COLUMN if not exists editor_id text;
|
|
54
|
+
ALTER TABLE admin.user_group ADD COLUMN if not exists editor_date timestamp without time zone;
|
|
55
|
+
|
|
56
|
+
ALTER TABLE admin.user_group
|
|
57
|
+
ADD CONSTRAINT admin_user_group_id_pkey PRIMARY KEY(user_group_id);
|
|
58
|
+
|
|
59
|
+
COMMENT ON COLUMN admin.user_group.user_group_id IS 'Вкл./Выкл.';
|
|
60
|
+
COMMENT ON COLUMN admin.user_group.group_name IS 'Назва групи';
|
|
61
|
+
COMMENT ON COLUMN admin.user_group.enabled IS 'Вкл./Відкл.';
|
|
62
|
+
COMMENT ON COLUMN admin.user_group.cdate IS 'Дата створення';
|
|
63
|
+
COMMENT ON COLUMN admin.user_group.uid IS 'Хто створив';
|
|
64
|
+
COMMENT ON COLUMN admin.user_group.editor_id IS 'Останній редагувач';
|
|
65
|
+
COMMENT ON COLUMN admin.user_group.editor_date IS 'Дата останнього редагування';
|
|
66
|
+
|
|
67
|
+
-- drop table if exists admin.user_access;
|
|
68
|
+
CREATE TABLE if not exists admin.user_access();
|
|
69
|
+
alter table admin.user_access DROP CONSTRAINT if exists admin_user_access_id_pkey;
|
|
70
|
+
alter table admin.user_access DROP CONSTRAINT if exists admin_user_access_user_group_id_fkey;
|
|
71
|
+
alter table admin.user_access DROP CONSTRAINT if exists admin_user_access_interface_id_uid_unique;
|
|
72
|
+
alter table admin.user_access DROP CONSTRAINT if exists admin_user_access_interface_id_fkey;
|
|
73
|
+
|
|
74
|
+
alter table admin.user_access add column if not exists user_access_id text NOT NULL DEFAULT next_id();
|
|
75
|
+
alter table admin.user_access add column if not exists interface_id text NOT NULL;
|
|
76
|
+
alter table admin.user_access add column if not exists user_group_id text;
|
|
77
|
+
alter table admin.user_access add column if not exists user_uid text;
|
|
78
|
+
alter table admin.user_access add column if not exists scope text;
|
|
79
|
+
alter table admin.user_access add column if not exists actions text[];
|
|
80
|
+
ALTER TABLE admin.user_access ADD COLUMN IF NOT EXISTS access_granted text;
|
|
81
|
+
ALTER TABLE admin.user_access ADD COLUMN IF NOT EXISTS access_granted_time timestamp without time zone;
|
|
82
|
+
alter table admin.user_access add column if not exists cdate timestamp without time zone NOT NULL DEFAULT date_trunc('seconds'::text, now());
|
|
83
|
+
alter table admin.user_access add column if not exists uid text;
|
|
84
|
+
alter table admin.user_access add column if not exists editor_id text;
|
|
85
|
+
alter table admin.user_access add column if not exists editor_date timestamp without time zone;
|
|
86
|
+
|
|
87
|
+
alter table admin.user_access
|
|
88
|
+
add CONSTRAINT admin_user_access_id_pkey PRIMARY KEY (user_access_id);
|
|
89
|
+
|
|
90
|
+
alter table admin.user_access
|
|
91
|
+
add CONSTRAINT admin_user_access_user_group_id_fkey FOREIGN KEY (user_group_id) REFERENCES admin.user_group (user_group_id);
|
|
92
|
+
|
|
93
|
+
alter table admin.user_access
|
|
94
|
+
add CONSTRAINT admin_user_access_interface_id_uid_unique UNIQUE (interface_id, user_uid, user_group_id);
|
|
95
|
+
alter table admin.user_access
|
|
96
|
+
add constraint admin_user_access_interface_id_fkey FOREIGN KEY (interface_id) REFERENCES admin.interface_list(interface_id);
|
|
97
|
+
|
|
98
|
+
COMMENT ON TABLE admin.user_access IS 'Налаштування прав. Відношення груп / окремих користувачів до шаблонів';
|
|
99
|
+
COMMENT ON COLUMN admin.user_access.interface_id IS 'ID шаблона';
|
|
100
|
+
COMMENT ON COLUMN admin.user_access.user_group_id IS 'ID групи';
|
|
101
|
+
COMMENT ON COLUMN admin.user_access.user_uid IS 'ID користувача';
|
|
102
|
+
COMMENT ON COLUMN admin.user_access.scope IS 'Обмеження виведення (власні, відповідальний, всі)';
|
|
103
|
+
COMMENT ON COLUMN admin.user_access.actions IS 'Доступні дії';
|
|
104
|
+
COMMENT ON COLUMN admin.user_access.access_granted IS 'Ідентифікатор користувача який надав доступ';
|
|
105
|
+
COMMENT ON COLUMN admin.user_access.access_granted_time IS 'Час коли надали доступ';
|
|
106
|
+
|
|
107
|
+
CREATE INDEX if not exists admin_user_access_interface_id_idx
|
|
108
|
+
ON admin.user_access USING btree (interface_id COLLATE pg_catalog."default");
|
|
109
|
+
|
|
110
|
+
CREATE INDEX if not exists admin_user_access_user_group_id_idx
|
|
111
|
+
ON admin.user_access USING btree (user_group_id COLLATE pg_catalog."default");
|
|
112
|
+
|
|
113
|
+
-- DROP TABLE if exists admin.user_group_rel;
|
|
114
|
+
CREATE TABLE if not exists admin.user_group_rel();
|
|
115
|
+
ALTER TABLE admin.user_group_rel DROP CONSTRAINT IF EXISTS admin_user_group_rel_pkey;
|
|
116
|
+
ALTER TABLE admin.user_group_rel DROP CONSTRAINT IF EXISTS admin_user_group_rel_user_group_id_fkey;
|
|
117
|
+
ALTER TABLE admin.user_group_rel DROP CONSTRAINT IF EXISTS admin_user_group_rel_user_uid_fkey;
|
|
118
|
+
ALTER TABLE admin.user_group_rel DROP CONSTRAINT IF EXISTS admin_user_group_rel_user_uid_user_group_id_key;
|
|
119
|
+
|
|
120
|
+
ALTER TABLE admin.user_group_rel ADD COLUMN IF NOT EXISTS ugr_id text NOT NULL DEFAULT next_id();
|
|
121
|
+
ALTER TABLE admin.user_group_rel ADD COLUMN IF NOT EXISTS user_uid text NOT NULL;
|
|
122
|
+
ALTER TABLE admin.user_group_rel ADD COLUMN IF NOT EXISTS user_group_id text NOT NULL;
|
|
123
|
+
ALTER TABLE admin.user_group_rel ADD COLUMN IF NOT EXISTS cdate timestamp without time zone DEFAULT date_trunc('seconds'::text, now());
|
|
124
|
+
ALTER TABLE admin.user_group_rel ADD COLUMN IF NOT EXISTS uid text;
|
|
125
|
+
ALTER TABLE admin.user_group_rel ADD COLUMN IF NOT EXISTS editor_id text;
|
|
126
|
+
ALTER TABLE admin.user_group_rel ADD COLUMN IF NOT EXISTS editor_date timestamp without time zone;
|
|
127
|
+
ALTER TABLE admin.user_group_rel ADD COLUMN IF NOT EXISTS expiration date;
|
|
128
|
+
ALTER TABLE admin.user_group_rel ADD COLUMN IF NOT EXISTS access_granted text;
|
|
129
|
+
ALTER TABLE admin.user_group_rel ADD COLUMN IF NOT EXISTS access_granted_time timestamp without time zone;
|
|
130
|
+
|
|
131
|
+
ALTER TABLE admin.user_group_rel ADD CONSTRAINT admin_user_group_rel_pkey PRIMARY KEY (ugr_id);
|
|
132
|
+
ALTER TABLE admin.user_group_rel ADD CONSTRAINT admin_user_group_rel_user_group_id_fkey FOREIGN KEY (user_group_id) REFERENCES admin.user_group (user_group_id);
|
|
133
|
+
ALTER TABLE admin.user_group_rel ADD CONSTRAINT admin_user_group_rel_user_uid_fkey FOREIGN KEY (user_uid) REFERENCES admin.users (uid);
|
|
134
|
+
ALTER TABLE admin.user_group_rel ADD CONSTRAINT admin_user_group_rel_user_uid_user_group_id_key UNIQUE (user_uid, user_group_id);
|
|
135
|
+
|
|
136
|
+
COMMENT ON TABLE admin.user_group_rel IS 'Відношення користувачів до груп';
|
|
137
|
+
COMMENT ON COLUMN admin.user_group_rel.user_uid IS 'ID користувача';
|
|
138
|
+
COMMENT ON COLUMN admin.user_group_rel.user_group_id IS 'ID групи';
|
|
139
|
+
COMMENT ON COLUMN admin.user_group_rel.uid IS 'Користувач, який створив запис в БД';
|
|
140
|
+
COMMENT ON COLUMN admin.user_group_rel.expiration IS 'закінчення терміну дії доступу до групи';
|
|
141
|
+
COMMENT ON COLUMN admin.user_group_rel.access_granted IS 'Ідентифікатор користувача який надав доступ';
|
|
142
|
+
COMMENT ON COLUMN admin.user_group_rel.access_granted_time IS 'Час коли надали доступ';
|
|
143
|
+
|
|
144
|
+
CREATE INDEX IF NOT EXISTS admin_user_group_access_user_uid_idx ON admin.user_group_rel USING btree (user_uid COLLATE pg_catalog."default");
|
|
145
|
+
|
|
146
|
+
CREATE INDEX IF NOT EXISTS admin_user_group_rel_cdate_btree_idx ON admin.user_group_rel USING btree (cdate);
|
|
147
|
+
|
|
148
|
+
CREATE INDEX IF NOT EXISTS admin_user_group_rel_editor_date_btree_idx ON admin.user_group_rel USING btree (editor_date);
|
|
149
|
+
|
|
150
|
+
CREATE INDEX IF NOT EXISTS admin_user_group_rel_user_uid_gin_idx ON admin.user_group_rel USING gin (user_uid COLLATE pg_catalog."default" gin_trgm_ops);
|
|
151
|
+
|
|
152
|
+
CREATE INDEX IF NOT EXISTS admin_user_group_user_group_id_idx ON admin.user_group_rel USING btree (user_group_id COLLATE pg_catalog."default");
|
|
153
|
+
|
|
154
|
+
-- DROP TABLE if exists admin.menu;
|
|
155
|
+
CREATE TABLE if not exists admin.menu();
|
|
156
|
+
alter table admin.menu DROP CONSTRAINT if exists admin_menu_id_pkey cascade;
|
|
157
|
+
alter table admin.menu DROP CONSTRAINT if exists admin_menu_name_unique;
|
|
158
|
+
|
|
159
|
+
alter table admin.menu add column if not exists menu_id text NOT NULL default next_id();
|
|
160
|
+
alter table admin.menu add column if not exists name text;
|
|
161
|
+
alter table admin.menu add column if not exists ord numeric;
|
|
162
|
+
alter table admin.menu add column if not exists enabled boolean NOT NULL DEFAULT true;
|
|
163
|
+
alter table admin.menu add column if not exists uid text;
|
|
164
|
+
alter table admin.menu add column if not exists editor_id text;
|
|
165
|
+
alter table admin.menu add column if not exists editor_date timestamp without time zone;
|
|
166
|
+
alter table admin.menu add column if not exists cdate timestamp without time zone DEFAULT now();
|
|
167
|
+
alter table admin.menu add CONSTRAINT admin_menu_id_pkey PRIMARY KEY (menu_id);
|
|
168
|
+
alter table admin.menu add CONSTRAINT admin_menu_name_unique UNIQUE (name);
|
|
169
|
+
|
|
170
|
+
COMMENT ON TABLE admin.menu IS 'Пункти меню';
|
|
171
|
+
COMMENT ON COLUMN admin.menu.menu_id IS 'Ідентифікатор пункту меню';
|
|
172
|
+
COMMENT ON COLUMN admin.menu.name IS 'Назва пункту меню';
|
|
173
|
+
COMMENT ON COLUMN admin.menu.ord IS 'Порядковий номер';
|
|
174
|
+
COMMENT ON COLUMN admin.menu.enabled IS 'On / Off';
|
|
175
|
+
|
|
176
|
+
-- DROP TABLE if exists admin.interface_list;
|
|
177
|
+
CREATE TABLE if not exists admin.interface_list();
|
|
178
|
+
alter table admin.interface_list DROP CONSTRAINT if exists admin_interface_id_pkey cascade;
|
|
179
|
+
|
|
180
|
+
alter table admin.interface_list add column if not exists interface_id text NOT NULL default next_id();
|
|
181
|
+
alter table admin.interface_list add column if not exists alias text NOT NULL;
|
|
182
|
+
alter table admin.interface_list add column if not exists title text;
|
|
183
|
+
alter table admin.interface_list add column if not exists public boolean;
|
|
184
|
+
alter table admin.interface_list add column if not exists menu_id text;
|
|
185
|
+
alter table admin.interface_list add column if not exists uid text;
|
|
186
|
+
alter table admin.interface_list add column if not exists editor_id text;
|
|
187
|
+
alter table admin.interface_list add column if not exists editor_date timestamp without time zone;
|
|
188
|
+
alter table admin.interface_list add column if not exists cdate timestamp without time zone DEFAULT now();
|
|
189
|
+
alter table admin.interface_list add column if not exists enabled boolean NOT NULL DEFAULT true;
|
|
190
|
+
alter table admin.interface_list add CONSTRAINT admin_interface_id_pkey PRIMARY KEY (interface_id);
|
|
191
|
+
alter table admin.interface_list add constraint admin_interface_menu_id_fkey FOREIGN KEY (menu_id) REFERENCES admin.menu(menu_id);
|
|
192
|
+
|
|
193
|
+
COMMENT ON TABLE admin.interface_list IS 'Список інтерфейсів';
|
|
194
|
+
COMMENT ON COLUMN admin.interface_list.interface_id IS 'Ідентифікатор інтерфейса';
|
|
195
|
+
COMMENT ON COLUMN admin.interface_list.alias IS 'Назва файлу інтерфейса';
|
|
196
|
+
COMMENT ON COLUMN admin.interface_list.title IS 'Назва інтерфейсу українською';
|
|
197
|
+
COMMENT ON COLUMN admin.interface_list.public IS 'Ознака чи для всіх показується';
|
|
198
|
+
COMMENT ON COLUMN admin.interface_list.enabled IS 'On / Off';
|
|
199
|
+
COMMENT ON COLUMN admin.interface_list.menu_id IS 'Пункт меню (для collapse)';
|
|
200
|
+
|
|
201
|
+
CREATE EXTENSION if not exists pgcrypto SCHEMA public VERSION "1.3";
|
|
202
|
+
CREATE OR REPLACE FUNCTION admin.crypt(text, text) RETURNS text AS '$libdir/pgcrypto', 'pg_crypt' LANGUAGE c IMMUTABLE STRICT COST 1;
|
|
203
|
+
|
|
204
|
+
-- DROP FUNCTION admin.insert_update_user_before();
|
|
205
|
+
CREATE OR REPLACE FUNCTION admin.insert_update_user_before()
|
|
206
|
+
RETURNS trigger AS
|
|
207
|
+
|
|
208
|
+
$BODY$
|
|
209
|
+
DECLARE
|
|
210
|
+
|
|
211
|
+
iterations int;
|
|
212
|
+
hash character varying;
|
|
213
|
+
|
|
214
|
+
BEGIN
|
|
215
|
+
|
|
216
|
+
if(TG_OP='INSERT' or (TG_OP='UPDATE' and new.password<>old.password)) then
|
|
217
|
+
if(char_length(new.password) <> 0 and char_length(new.password) < 8) then
|
|
218
|
+
--raise exception 'password must be longer than 8 characters';
|
|
219
|
+
end if;
|
|
220
|
+
new.salt=md5(now()::text);
|
|
221
|
+
--raise exception '%','change pass';
|
|
222
|
+
if(new.salt ='') then
|
|
223
|
+
new.salt=gen_salt('md5');
|
|
224
|
+
end if;
|
|
225
|
+
iterations = 10;
|
|
226
|
+
hash='';
|
|
227
|
+
|
|
228
|
+
loop
|
|
229
|
+
if iterations=0 then
|
|
230
|
+
exit;
|
|
231
|
+
end if;
|
|
232
|
+
hash = md5(new.password||hash||new.salt);
|
|
233
|
+
iterations=iterations-1;
|
|
234
|
+
end loop;
|
|
235
|
+
new.password=admin.crypt(hash,new.salt);
|
|
236
|
+
|
|
237
|
+
end if;
|
|
238
|
+
RETURN new;
|
|
239
|
+
END
|
|
240
|
+
$BODY$
|
|
241
|
+
|
|
242
|
+
LANGUAGE plpgsql VOLATILE COST 100;
|
|
243
|
+
|
|
244
|
+
DROP TRIGGER if exists insert_update_user_before on admin.users;
|
|
245
|
+
CREATE TRIGGER insert_update_user_before BEFORE INSERT OR UPDATE ON admin.users FOR EACH ROW
|
|
246
|
+
EXECUTE PROCEDURE admin.insert_update_user_before();
|
|
@@ -115,4 +115,34 @@ ALTER TABLE crm.cls ADD COLUMN IF NOT EXISTS cdate timestamp without time zone D
|
|
|
115
115
|
ALTER TABLE crm.cls ADD COLUMN IF NOT EXISTS editor_id text;
|
|
116
116
|
ALTER TABLE crm.cls ADD COLUMN IF NOT EXISTS editor_date timestamp without time zone;
|
|
117
117
|
ALTER TABLE crm.cls ADD CONSTRAINT crm_cls_pkey PRIMARY KEY (cls_id);
|
|
118
|
-
ALTER TABLE crm.cls ADD CONSTRAINT crm_cls_unique UNIQUE (code, parent);
|
|
118
|
+
ALTER TABLE crm.cls ADD CONSTRAINT crm_cls_unique UNIQUE (code, parent);
|
|
119
|
+
|
|
120
|
+
-- DROP TABLE crm.properties;
|
|
121
|
+
CREATE TABLE IF NOT EXISTS crm.properties();
|
|
122
|
+
ALTER TABLE crm.properties DROP CONSTRAINT IF EXISTS crm_properties_pkey;
|
|
123
|
+
ALTER TABLE crm.properties ADD COLUMN IF NOT EXISTS property_id text NOT NULL DEFAULT next_id();
|
|
124
|
+
|
|
125
|
+
ALTER TABLE crm.properties ADD COLUMN IF NOT EXISTS table_name text;
|
|
126
|
+
COMMENT ON COLUMN crm.properties.table_name IS 'Таблиця';
|
|
127
|
+
ALTER TABLE crm.properties ADD COLUMN IF NOT EXISTS object_id text;
|
|
128
|
+
COMMENT ON COLUMN crm.properties.object_id IS 'ID Об''єкту';
|
|
129
|
+
ALTER TABLE crm.properties ADD COLUMN IF NOT EXISTS property_key text;
|
|
130
|
+
COMMENT ON COLUMN crm.properties.object_id IS 'Назва атрибуту';
|
|
131
|
+
ALTER TABLE crm.properties ADD COLUMN IF NOT EXISTS property_text text;
|
|
132
|
+
COMMENT ON COLUMN crm.properties.property_text IS 'Текст';
|
|
133
|
+
ALTER TABLE crm.properties ADD COLUMN IF NOT EXISTS property_int integer;
|
|
134
|
+
COMMENT ON COLUMN crm.properties.property_int IS 'Integer';
|
|
135
|
+
ALTER TABLE crm.properties ADD COLUMN IF NOT EXISTS property_json json;
|
|
136
|
+
COMMENT ON COLUMN crm.properties.property_json IS 'JSON';
|
|
137
|
+
ALTER TABLE crm.properties ADD COLUMN IF NOT EXISTS property_date date;
|
|
138
|
+
COMMENT ON COLUMN crm.properties.property_json IS 'Дата';
|
|
139
|
+
ALTER TABLE crm.properties ADD COLUMN IF NOT EXISTS property_type text;
|
|
140
|
+
COMMENT ON COLUMN crm.properties.property_type IS 'Тип даних';
|
|
141
|
+
|
|
142
|
+
ALTER TABLE crm.properties ADD COLUMN IF NOT EXISTS uid text NOT NULL DEFAULT '1'::text;
|
|
143
|
+
ALTER TABLE crm.properties ADD COLUMN IF NOT EXISTS editor_id text;
|
|
144
|
+
ALTER TABLE crm.properties ADD COLUMN IF NOT EXISTS editor_date timestamp without time zone;
|
|
145
|
+
ALTER TABLE crm.properties ADD COLUMN IF NOT EXISTS cdate timestamp without time zone DEFAULT now();
|
|
146
|
+
ALTER TABLE crm.properties ADD COLUMN IF NOT EXISTS files json;
|
|
147
|
+
|
|
148
|
+
ALTER TABLE crm.properties ADD CONSTRAINT crm_properties_pkey PRIMARY KEY(property_id);
|
|
@@ -17,7 +17,9 @@ export default async function data(req) {
|
|
|
17
17
|
const {
|
|
18
18
|
table, columns, sql, cardSql, filters, form, meta,
|
|
19
19
|
} = loadTable;
|
|
20
|
-
const { pk, columns: dbColumns } = await getMeta(table);
|
|
20
|
+
const { pk, columns: dbColumns = [] } = await getMeta(table);
|
|
21
|
+
|
|
22
|
+
if (!pk) return { message: `table not found: ${table}`, status: 404 };
|
|
21
23
|
|
|
22
24
|
const cols = columns.map((el) => el.name || el).join(',');
|
|
23
25
|
const columnList = dbColumns.map((el) => el.name || el).join(',');
|
|
@@ -46,7 +48,7 @@ export default async function data(req) {
|
|
|
46
48
|
|
|
47
49
|
const where = [(params.id ? ` "${pk}" = $1` : null), keyQuery, loadTable.query, fData.q, state, custom, search].filter((el) => el);
|
|
48
50
|
const cardColumns = cardSqlFiltered.length ? `,${cardSqlFiltered.map((el) => el.name)}` : '';
|
|
49
|
-
const q = `select ${pk ? `"${pk}" as id,` : ''} ${query.id || query.key ? '*' : cols || '*'} ${cardColumns} from ${table} t ${sqlTable} ${cardSqlTable} where ${where.join(' and ') || 'true'} ${order} ${offset} limit ${limit}`;
|
|
51
|
+
const q = `select ${pk ? `"${pk}" as id,` : ''} ${columnList.includes('geom') ? `st_asgeojson(geom)::json as geom,` : ''} ${query.id || query.key ? '*' : cols || '*'} ${cardColumns} from ${table} t ${sqlTable} ${cardSqlTable} where ${where.join(' and ') || 'true'} ${order} ${offset} limit ${limit}`;
|
|
50
52
|
|
|
51
53
|
if (query.sql === '1') { return q; }
|
|
52
54
|
|
|
@@ -1,28 +1,28 @@
|
|
|
1
|
-
import { readFile } from 'fs/promises';
|
|
2
|
-
import fs from 'fs';
|
|
3
|
-
import path from 'path';
|
|
4
|
-
import config from '../../../config.js';
|
|
5
|
-
|
|
6
|
-
const loadTemplate = {};
|
|
7
|
-
|
|
8
|
-
export default async function getTemplateDir(type, name) {
|
|
9
|
-
if (!type) return null;
|
|
10
|
-
if (!name) return null;
|
|
11
|
-
|
|
12
|
-
const cwd = process.cwd();
|
|
13
|
-
const typeDir = path.join(cwd, (config.templateDir || 'server/templates'), type);
|
|
14
|
-
|
|
15
|
-
if (!loadTemplate[type]) {
|
|
16
|
-
const typeList = fs.existsSync(typeDir) ? fs.readdirSync(typeDir) : [];
|
|
17
|
-
loadTemplate[type] = typeList;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
const fullname = loadTemplate[type].find((el) => path.parse(el).name === name);
|
|
21
|
-
const ext = fullname ? path.extname(fullname)?.slice(1) : null;
|
|
22
|
-
if (!ext) return null;
|
|
23
|
-
|
|
24
|
-
const sql = loadTemplate[type].includes(`${name}.sql`) ? await readFile(path.join(typeDir, `${name}.sql`), 'utf-8') : null;
|
|
25
|
-
const data = loadTemplate[type].includes(`${name}.json`) ? JSON.parse(await readFile(path.join(typeDir, `${name}.json`), 'utf-8')) : await readFile(path.join(typeDir, `${name}.${ext}`), 'utf-8');
|
|
26
|
-
if (sql) return { ...data || {}, sql };
|
|
27
|
-
return data;
|
|
28
|
-
}
|
|
1
|
+
import { readFile } from 'fs/promises';
|
|
2
|
+
import fs from 'fs';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import config from '../../../config.js';
|
|
5
|
+
|
|
6
|
+
const loadTemplate = {};
|
|
7
|
+
|
|
8
|
+
export default async function getTemplateDir(type, name) {
|
|
9
|
+
if (!type) return null;
|
|
10
|
+
if (!name) return null;
|
|
11
|
+
|
|
12
|
+
const cwd = process.cwd();
|
|
13
|
+
const typeDir = path.join(cwd, (config.templateDir || 'server/templates'), type);
|
|
14
|
+
|
|
15
|
+
if (!loadTemplate[type]) {
|
|
16
|
+
const typeList = fs.existsSync(typeDir) ? fs.readdirSync(typeDir) : [];
|
|
17
|
+
loadTemplate[type] = typeList;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const fullname = loadTemplate[type].find((el) => path.parse(el).name === name);
|
|
21
|
+
const ext = fullname ? path.extname(fullname)?.slice(1) : null;
|
|
22
|
+
if (!ext) return null;
|
|
23
|
+
|
|
24
|
+
const sql = loadTemplate[type].includes(`${name}.sql`) ? await readFile(path.join(typeDir, `${name}.sql`), 'utf-8') : null;
|
|
25
|
+
const data = loadTemplate[type].includes(`${name}.json`) ? JSON.parse(await readFile(path.join(typeDir, `${name}.json`), 'utf-8')) : await readFile(path.join(typeDir, `${name}.${ext}`), 'utf-8');
|
|
26
|
+
if (sql) return { ...data || {}, sql };
|
|
27
|
+
return data;
|
|
28
|
+
}
|
package/test/api/crud.test.js
CHANGED
|
@@ -26,6 +26,26 @@ test('api crud', async (t) => {
|
|
|
26
26
|
assert.ok(rep.rows ? rep.rows[0]?.map_id : rep.map_id);
|
|
27
27
|
});
|
|
28
28
|
|
|
29
|
+
await t.test('POST /properties/:id', async () => {
|
|
30
|
+
const res = await app.inject({
|
|
31
|
+
method: 'POST',
|
|
32
|
+
url: `${prefix}/properties/5400000`,
|
|
33
|
+
body: {
|
|
34
|
+
custom_alias: 'testMap',
|
|
35
|
+
custom_ord: 5,
|
|
36
|
+
},
|
|
37
|
+
});
|
|
38
|
+
assert.ok(res.json().message.rows.length, 'not ok');
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
await t.test('GET /properties/:id', async () => {
|
|
42
|
+
const res = await app.inject({
|
|
43
|
+
method: 'GET',
|
|
44
|
+
url: `${prefix}/properties/5400000`,
|
|
45
|
+
});
|
|
46
|
+
assert.ok(res.json().message.custom_alias, 'not ok');
|
|
47
|
+
});
|
|
48
|
+
|
|
29
49
|
await t.test('PUT /update', async () => {
|
|
30
50
|
const res = await app.inject({
|
|
31
51
|
method: 'PUT',
|