@opengis/fastify-table 1.1.126 → 1.1.128

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 CHANGED
@@ -1,9 +1,15 @@
1
1
  {
2
2
  "name": "@opengis/fastify-table",
3
- "version": "1.1.126",
3
+ "version": "1.1.128",
4
4
  "type": "module",
5
5
  "description": "core-plugins",
6
- "keywords": ["fastify", "table", "crud", "pg", "backend" ],
6
+ "keywords": [
7
+ "fastify",
8
+ "table",
9
+ "crud",
10
+ "pg",
11
+ "backend"
12
+ ],
7
13
  "main": "index.js",
8
14
  "files": [
9
15
  "server/*",
@@ -1,188 +1,191 @@
1
- create schema if not exists admin;
2
- create schema if not exists public;
3
- CREATE EXTENSION if not exists pg_trgm SCHEMA public VERSION "1.5";
4
-
5
-
6
- -- Admin Menu
7
- -- DROP TABLE if exists admin.menu;
8
- CREATE TABLE if not exists admin.menu();
9
- alter table admin.menu DROP CONSTRAINT if exists admin_menu_id_pkey cascade;
10
- alter table admin.menu DROP CONSTRAINT if exists admin_menu_name_unique;
11
-
12
- alter table admin.menu add column if not exists menu_id text NOT NULL default next_id();
13
- alter table admin.menu add column if not exists name text;
14
- alter table admin.menu add column if not exists ord numeric;
15
- alter table admin.menu add column if not exists enabled boolean NOT NULL DEFAULT true;
16
- alter table admin.menu add column if not exists uid text;
17
- alter table admin.menu add column if not exists editor_id text;
18
- alter table admin.menu add column if not exists editor_date timestamp without time zone;
19
- alter table admin.menu add column if not exists cdate timestamp without time zone DEFAULT now();
20
- alter table admin.menu add CONSTRAINT admin_menu_id_pkey PRIMARY KEY (menu_id);
21
- alter table admin.menu add CONSTRAINT admin_menu_name_unique UNIQUE (name);
22
-
23
- COMMENT ON TABLE admin.menu IS 'Пункти меню';
24
- COMMENT ON COLUMN admin.menu.menu_id IS 'Ідентифікатор пункту меню';
25
- COMMENT ON COLUMN admin.menu.name IS 'Назва пункту меню';
26
- COMMENT ON COLUMN admin.menu.ord IS 'Порядковий номер';
27
- COMMENT ON COLUMN admin.menu.enabled IS 'On / Off';
28
-
29
-
30
-
31
-
32
- -- Role (Group)
33
- -- drop table if exists admin.roles;
34
- CREATE TABLE if not exists admin.roles();
35
- alter table admin.roles DROP CONSTRAINT if exists admin_roles_id_pkey cascade;
36
-
37
- ALTER TABLE admin.roles ADD COLUMN if not exists role_id text NOT NULL DEFAULT next_id();
38
- ALTER TABLE admin.roles ADD COLUMN if not exists name text;
39
- ALTER TABLE admin.roles ADD COLUMN if not exists enabled boolean;
40
- ALTER TABLE admin.roles ADD COLUMN if not exists info text;
41
- ALTER TABLE admin.roles ADD COLUMN if not exists cdate timestamp without time zone DEFAULT date_trunc('seconds'::text, now());
42
- ALTER TABLE admin.roles ADD COLUMN if not exists uid text;
43
- ALTER TABLE admin.roles ADD COLUMN if not exists editor_id text;
44
- ALTER TABLE admin.roles ADD COLUMN if not exists editor_date timestamp without time zone;
45
-
46
- ALTER TABLE admin.roles ADD CONSTRAINT admin_roles_id_pkey PRIMARY KEY(role_id);
47
-
48
- COMMENT ON TABLE admin.roles IS 'Групи';
49
- COMMENT ON COLUMN admin.roles.role_id IS 'ID';
50
- COMMENT ON COLUMN admin.roles.name IS 'Назва групи';
51
- COMMENT ON COLUMN admin.roles.enabled IS 'On / Off';
52
- COMMENT ON COLUMN admin.roles.info IS 'Опис групи';
53
- COMMENT ON COLUMN admin.roles.cdate IS 'Дата створення';
54
- COMMENT ON COLUMN admin.roles.uid IS 'Хто створив';
55
- COMMENT ON COLUMN admin.roles.editor_id IS 'Останній редагувач';
56
- COMMENT ON COLUMN admin.roles.editor_date IS 'Дата останнього редагування';
57
-
58
- -- Routes (Interfaces)
59
- -- DROP TABLE if exists admin.routes;
60
- CREATE TABLE if not exists admin.routes();
61
- alter table admin.routes DROP CONSTRAINT if exists admin_route_id_pkey cascade;
62
- alter table admin.routes DROP constraint if exists admin_route_menu_id_fkey cascade;
63
- alter table admin.routes DROP constraint if exists admin_route_alias_query_unique cascade;
64
-
65
- alter table admin.routes add column if not exists route_id text;
66
- alter table admin.routes alter column route_id set not null;
67
- alter table admin.routes alter column route_id set default next_id();
68
- alter table admin.routes add column if not exists alias text;
69
- alter table admin.routes alter column alias drop not null;
70
- -- alter table admin.routes alter column alias set not null;
71
- alter table admin.routes add column if not exists table_name text;
72
- alter table admin.routes alter column table_name drop not null;
73
- -- alter table admin.routes alter column table_name set not null;
74
- alter table admin.routes add column if not exists query text;
75
- alter table admin.routes add column if not exists actions text[];
76
- alter table admin.routes add column if not exists access text;
77
- alter table admin.routes add column if not exists title text;
78
- alter table admin.routes add column if not exists public boolean;
79
- alter table admin.routes add column if not exists menu_id text;
80
- alter table admin.routes add column if not exists uid text;
81
- alter table admin.routes add column if not exists editor_id text;
82
- alter table admin.routes add column if not exists editor_date timestamp without time zone;
83
- alter table admin.routes add column if not exists cdate timestamp without time zone DEFAULT now();
84
- alter table admin.routes alter column cdate set DEFAULT now();
85
- alter table admin.routes add column if not exists enabled boolean;
86
- alter table admin.routes alter column enabled set NOT NULL;
87
- alter table admin.routes alter column enabled set DEFAULT true;
88
-
89
- alter table admin.routes add CONSTRAINT admin_route_id_pkey PRIMARY KEY (route_id);
90
- alter table admin.routes add constraint admin_route_menu_id_fkey FOREIGN KEY (menu_id) REFERENCES admin.menu(menu_id);
91
-
92
- -- alter table admin.routes add CONSTRAINT admin_route_alias_query_unique UNIQUE (alias, query);
93
-
94
- COMMENT ON TABLE admin.routes IS 'Список інтерфейсів';
95
- COMMENT ON COLUMN admin.routes.route_id IS 'Ідентифікатор інтерфейса';
96
- COMMENT ON COLUMN admin.routes.alias IS 'Назва файлу інтерфейса';
97
-
98
- COMMENT ON COLUMN admin.routes.table_name IS 'Таблиця в БД';
99
- comment on column admin.routes.query is 'Запит до таблиці';
100
- COMMENT ON COLUMN admin.routes.actions IS 'Дії';
101
- COMMENT ON COLUMN admin.routes.access IS 'Рівень доступу';
102
- COMMENT ON COLUMN admin.routes.title IS 'Назва інтерфейсу українською';
103
- COMMENT ON COLUMN admin.routes.public IS 'Ознака чи для всіх показується';
104
- COMMENT ON COLUMN admin.routes.enabled IS 'On / Off';
105
- COMMENT ON COLUMN admin.routes.menu_id IS 'Пункт меню (для collapse)';
106
-
107
- -- User <> Role (Group)
108
- -- DROP TABLE if exists admin.user_roles;
109
-
110
- CREATE TABLE if not exists admin.user_roles();
111
- ALTER TABLE admin.user_roles DROP CONSTRAINT IF EXISTS admin_user_roles_role_id_pkey;
112
- ALTER TABLE admin.user_roles DROP CONSTRAINT IF EXISTS admin_user_roles_pkey;
113
- ALTER TABLE admin.user_roles DROP CONSTRAINT IF EXISTS admin_user_roles_role_id_fkey;
114
- ALTER TABLE admin.user_roles DROP CONSTRAINT IF EXISTS admin_user_roles_user_uid_fkey;
115
- ALTER TABLE admin.user_roles DROP CONSTRAINT IF EXISTS admin_user_roles_user_uid_role_id_key;
116
-
117
- ALTER TABLE admin.user_roles ADD COLUMN IF NOT EXISTS ugr_id text NOT NULL DEFAULT next_id();
118
- ALTER TABLE admin.user_roles ADD COLUMN IF NOT EXISTS user_uid text NOT NULL;
119
- ALTER TABLE admin.user_roles ADD COLUMN IF NOT EXISTS role_id text NOT NULL;
120
- ALTER TABLE admin.user_roles ADD COLUMN IF NOT EXISTS cdate timestamp without time zone DEFAULT date_trunc('seconds'::text, now());
121
- ALTER TABLE admin.user_roles ADD COLUMN IF NOT EXISTS uid text;
122
- ALTER TABLE admin.user_roles ADD COLUMN IF NOT EXISTS editor_id text;
123
- ALTER TABLE admin.user_roles ADD COLUMN IF NOT EXISTS editor_date timestamp without time zone;
124
- ALTER TABLE admin.user_roles ADD COLUMN IF NOT EXISTS expiration date;
125
- ALTER TABLE admin.user_roles ADD COLUMN IF NOT EXISTS access_granted text;
126
- ALTER TABLE admin.user_roles ADD COLUMN IF NOT EXISTS access_granted_time timestamp without time zone;
127
-
128
- ALTER TABLE admin.user_roles ADD CONSTRAINT admin_user_roles_pkey PRIMARY KEY (ugr_id);
129
-
130
-
131
- COMMENT ON TABLE admin.user_roles IS 'Відношення користувачів до груп';
132
- COMMENT ON COLUMN admin.user_roles.user_uid IS 'ID користувача';
133
- COMMENT ON COLUMN admin.user_roles.role_id IS 'ID групи';
134
- COMMENT ON COLUMN admin.user_roles.uid IS 'Користувач, який створив запис в БД';
135
- COMMENT ON COLUMN admin.user_roles.expiration IS 'закінчення терміну дії доступу до групи';
136
- COMMENT ON COLUMN admin.user_roles.access_granted IS 'Ідентифікатор користувача який надав доступ';
137
- COMMENT ON COLUMN admin.user_roles.access_granted_time IS 'Час коли надали доступ';
138
-
139
- CREATE INDEX IF NOT EXISTS admin_user_roles_access_user_uid_idx ON admin.user_roles USING btree (user_uid COLLATE pg_catalog."default");
140
- CREATE INDEX IF NOT EXISTS admin_user_roles_cdate_btree_idx ON admin.user_roles USING btree (cdate);
141
- CREATE INDEX IF NOT EXISTS admin_user_roles_editor_date_btree_idx ON admin.user_roles USING btree (editor_date);
142
- CREATE INDEX IF NOT EXISTS admin_user_roles_user_uid_gin_idx ON admin.user_roles USING gin (user_uid COLLATE pg_catalog."default" gin_trgm_ops);
143
- CREATE INDEX IF NOT EXISTS admin_user_roles_role_id_idx ON admin.user_roles USING btree (role_id COLLATE pg_catalog."default");
144
-
145
-
146
- -- Route (Interface) <> User / Role (Group)
147
- -- drop table if exists admin.role_access;
148
- drop table if exists admin.access;
149
-
150
- CREATE TABLE if not exists admin.role_access();
151
- alter table admin.role_access DROP CONSTRAINT if exists admin_access_id_pkey;
152
- alter table admin.role_access DROP CONSTRAINT if exists admin_role_access_id_pkey;
153
- alter table admin.role_access DROP CONSTRAINT if exists admin_access_role_id_fkey;
154
- alter table admin.role_access DROP CONSTRAINT if exists admin_access_route_id_uid_unique;
155
- alter table admin.role_access DROP CONSTRAINT if exists admin_access_route_id_fkey;
156
-
157
- alter table admin.role_access add column if not exists access_id text NOT NULL DEFAULT next_id();
158
- alter table admin.role_access add column if not exists route_id text NOT NULL;
159
- alter table admin.role_access add column if not exists role_id text;
160
- alter table admin.role_access add column if not exists user_uid text;
161
- alter table admin.role_access add column if not exists scope text;
162
- alter table admin.role_access add column if not exists actions text[];
163
- ALTER TABLE admin.role_access ADD COLUMN IF NOT EXISTS access_granted text;
164
- ALTER TABLE admin.role_access ADD COLUMN IF NOT EXISTS access_granted_time timestamp without time zone;
165
- alter table admin.role_access add column if not exists cdate timestamp without time zone NOT NULL DEFAULT date_trunc('seconds'::text, now());
166
- alter table admin.role_access add column if not exists uid text;
167
- alter table admin.role_access add column if not exists editor_id text;
168
- alter table admin.role_access add column if not exists editor_date timestamp without time zone;
169
-
170
- alter table admin.role_access add CONSTRAINT admin_role_access_id_pkey PRIMARY KEY (access_id);
171
- alter table admin.role_access add CONSTRAINT admin_access_role_id_fkey FOREIGN KEY (role_id) REFERENCES admin.roles (role_id);
172
- alter table admin.role_access add CONSTRAINT admin_access_route_id_uid_unique UNIQUE (route_id, user_uid, role_id);
173
- alter table admin.role_access add constraint admin_access_route_id_fkey FOREIGN KEY (route_id) REFERENCES admin.routes(route_id);
174
-
175
-
176
- COMMENT ON TABLE admin.role_access IS 'Налаштування прав. Відношення груп / окремих користувачів до шаблонів';
177
- COMMENT ON COLUMN admin.role_access.route_id IS 'ID шаблона';
178
- COMMENT ON COLUMN admin.role_access.role_id IS 'ID групи';
179
- COMMENT ON COLUMN admin.role_access.user_uid IS 'ID користувача';
180
- COMMENT ON COLUMN admin.role_access.scope IS 'Обмеження виведення (власні, відповідальний, всі)';
181
- COMMENT ON COLUMN admin.role_access.actions IS 'Доступні дії';
182
- COMMENT ON COLUMN admin.role_access.access_granted IS 'Ідентифікатор користувача який надав доступ';
183
- COMMENT ON COLUMN admin.role_access.access_granted_time IS 'Час коли надали доступ';
184
-
185
- CREATE INDEX if not exists admin_access_route_id_idx ON admin.role_access USING btree (route_id COLLATE pg_catalog."default");
186
- CREATE INDEX if not exists admin_access_role_id_idx ON admin.role_access USING btree (role_id COLLATE pg_catalog."default");
187
-
188
-
1
+ create schema if not exists admin;
2
+ create schema if not exists public;
3
+ CREATE EXTENSION if not exists pg_trgm SCHEMA public VERSION "1.5";
4
+
5
+
6
+ -- Admin Menu
7
+ -- DROP TABLE if exists admin.menu;
8
+ CREATE TABLE if not exists admin.menu();
9
+ alter table admin.menu DROP CONSTRAINT if exists admin_menu_id_pkey cascade;
10
+ alter table admin.menu DROP CONSTRAINT if exists admin_menu_name_unique;
11
+
12
+ alter table admin.menu add column if not exists menu_id text NOT NULL default next_id();
13
+ alter table admin.menu add column if not exists name text;
14
+ alter table admin.menu add column if not exists ord numeric;
15
+ alter table admin.menu add column if not exists enabled boolean NOT NULL DEFAULT true;
16
+ alter table admin.menu add column if not exists uid text;
17
+ alter table admin.menu add column if not exists editor_id text;
18
+ alter table admin.menu add column if not exists editor_date timestamp without time zone;
19
+ alter table admin.menu add column if not exists cdate timestamp without time zone DEFAULT now();
20
+ alter table admin.menu add CONSTRAINT admin_menu_id_pkey PRIMARY KEY (menu_id);
21
+ alter table admin.menu add CONSTRAINT admin_menu_name_unique UNIQUE (name);
22
+
23
+ COMMENT ON TABLE admin.menu IS 'Пункти меню';
24
+ COMMENT ON COLUMN admin.menu.menu_id IS 'Ідентифікатор пункту меню';
25
+ COMMENT ON COLUMN admin.menu.name IS 'Назва пункту меню';
26
+ COMMENT ON COLUMN admin.menu.ord IS 'Порядковий номер';
27
+ COMMENT ON COLUMN admin.menu.enabled IS 'On / Off';
28
+
29
+
30
+
31
+
32
+ -- Role (Group)
33
+ -- drop table if exists admin.roles;
34
+ CREATE TABLE if not exists admin.roles();
35
+ alter table admin.roles DROP CONSTRAINT if exists admin_roles_id_pkey cascade;
36
+
37
+ ALTER TABLE admin.roles ADD COLUMN if not exists role_id text NOT NULL DEFAULT next_id();
38
+ ALTER TABLE admin.roles ADD COLUMN if not exists name text;
39
+ ALTER TABLE admin.roles ADD COLUMN if not exists enabled boolean;
40
+ ALTER TABLE admin.roles ADD COLUMN if not exists info text;
41
+ ALTER TABLE admin.roles ADD COLUMN if not exists cdate timestamp without time zone DEFAULT date_trunc('seconds'::text, now());
42
+ ALTER TABLE admin.roles ADD COLUMN if not exists uid text;
43
+ ALTER TABLE admin.roles ADD COLUMN if not exists editor_id text;
44
+ ALTER TABLE admin.roles ADD COLUMN if not exists editor_date timestamp without time zone;
45
+
46
+ ALTER TABLE admin.roles ADD CONSTRAINT admin_roles_id_pkey PRIMARY KEY(role_id);
47
+
48
+ COMMENT ON TABLE admin.roles IS 'Групи';
49
+ COMMENT ON COLUMN admin.roles.role_id IS 'ID';
50
+ COMMENT ON COLUMN admin.roles.name IS 'Назва групи';
51
+ COMMENT ON COLUMN admin.roles.enabled IS 'On / Off';
52
+ COMMENT ON COLUMN admin.roles.info IS 'Опис групи';
53
+ COMMENT ON COLUMN admin.roles.cdate IS 'Дата створення';
54
+ COMMENT ON COLUMN admin.roles.uid IS 'Хто створив';
55
+ COMMENT ON COLUMN admin.roles.editor_id IS 'Останній редагувач';
56
+ COMMENT ON COLUMN admin.roles.editor_date IS 'Дата останнього редагування';
57
+
58
+ -- Routes (Interfaces)
59
+ -- DROP TABLE if exists admin.routes;
60
+ CREATE TABLE if not exists admin.routes();
61
+ alter table admin.routes DROP CONSTRAINT if exists admin_route_id_pkey cascade;
62
+ alter table admin.routes DROP constraint if exists admin_route_menu_id_fkey cascade;
63
+ alter table admin.routes DROP constraint if exists admin_route_alias_query_unique cascade;
64
+
65
+ alter table admin.routes add column if not exists route_id text;
66
+ alter table admin.routes alter column route_id set not null;
67
+ alter table admin.routes alter column route_id set default next_id();
68
+ alter table admin.routes add column if not exists alias text;
69
+ alter table admin.routes alter column alias drop not null;
70
+ -- alter table admin.routes alter column alias set not null;
71
+ alter table admin.routes add column if not exists table_name text;
72
+ alter table admin.routes alter column table_name drop not null;
73
+ -- alter table admin.routes alter column table_name set not null;
74
+ alter table admin.routes add column if not exists query text;
75
+ alter table admin.routes add column if not exists actions text[];
76
+ alter table admin.routes add column if not exists access text;
77
+ alter table admin.routes add column if not exists title text;
78
+ alter table admin.routes add column if not exists public boolean;
79
+ alter table admin.routes add column if not exists menu_id text;
80
+ alter table admin.routes add column if not exists uid text;
81
+ alter table admin.routes add column if not exists editor_id text;
82
+ alter table admin.routes add column if not exists editor_date timestamp without time zone;
83
+ alter table admin.routes add column if not exists cdate timestamp without time zone DEFAULT now();
84
+ alter table admin.routes alter column cdate set DEFAULT now();
85
+ alter table admin.routes add column if not exists enabled boolean;
86
+ alter table admin.routes alter column enabled set NOT NULL;
87
+ alter table admin.routes alter column enabled set DEFAULT true;
88
+
89
+ alter table admin.routes add CONSTRAINT admin_route_id_pkey PRIMARY KEY (route_id);
90
+ alter table admin.routes add constraint admin_route_menu_id_fkey FOREIGN KEY (menu_id) REFERENCES admin.menu(menu_id);
91
+
92
+ -- alter table admin.routes add CONSTRAINT admin_route_alias_query_unique UNIQUE (alias, query);
93
+
94
+ COMMENT ON TABLE admin.routes IS 'Список інтерфейсів';
95
+ COMMENT ON COLUMN admin.routes.route_id IS 'Ідентифікатор інтерфейса';
96
+ COMMENT ON COLUMN admin.routes.alias IS 'Назва файлу інтерфейса';
97
+
98
+ COMMENT ON COLUMN admin.routes.table_name IS 'Таблиця в БД';
99
+ comment on column admin.routes.query is 'Запит до таблиці';
100
+ COMMENT ON COLUMN admin.routes.actions IS 'Дії';
101
+ COMMENT ON COLUMN admin.routes.access IS 'Рівень доступу';
102
+ COMMENT ON COLUMN admin.routes.title IS 'Назва інтерфейсу українською';
103
+ COMMENT ON COLUMN admin.routes.public IS 'Ознака чи для всіх показується';
104
+ COMMENT ON COLUMN admin.routes.enabled IS 'On / Off';
105
+ COMMENT ON COLUMN admin.routes.menu_id IS 'Пункт меню (для collapse)';
106
+
107
+ -- User <> Role (Group)
108
+ -- DROP TABLE if exists admin.user_roles;
109
+
110
+ CREATE TABLE if not exists admin.user_roles();
111
+ ALTER TABLE admin.user_roles DROP CONSTRAINT IF EXISTS admin_user_roles_role_id_pkey;
112
+ ALTER TABLE admin.user_roles DROP CONSTRAINT IF EXISTS admin_user_roles_pkey;
113
+ ALTER TABLE admin.user_roles DROP CONSTRAINT IF EXISTS admin_user_roles_role_id_fkey;
114
+ ALTER TABLE admin.user_roles DROP CONSTRAINT IF EXISTS admin_user_roles_user_uid_fkey;
115
+ ALTER TABLE admin.user_roles DROP CONSTRAINT IF EXISTS admin_user_roles_user_uid_role_id_key;
116
+
117
+ ALTER TABLE admin.user_roles ADD COLUMN IF NOT EXISTS ugr_id text NOT NULL DEFAULT next_id();
118
+ ALTER TABLE admin.user_roles ADD COLUMN IF NOT EXISTS user_uid text NOT NULL;
119
+ ALTER TABLE admin.user_roles ADD COLUMN IF NOT EXISTS role_id text NOT NULL;
120
+ ALTER TABLE admin.user_roles ADD COLUMN IF NOT EXISTS cdate timestamp without time zone DEFAULT date_trunc('seconds'::text, now());
121
+ ALTER TABLE admin.user_roles ADD COLUMN IF NOT EXISTS uid text;
122
+ ALTER TABLE admin.user_roles ADD COLUMN IF NOT EXISTS editor_id text;
123
+ ALTER TABLE admin.user_roles ADD COLUMN IF NOT EXISTS editor_date timestamp without time zone;
124
+ ALTER TABLE admin.user_roles ADD COLUMN IF NOT EXISTS expiration date;
125
+ ALTER TABLE admin.user_roles ADD COLUMN IF NOT EXISTS access_granted text;
126
+ ALTER TABLE admin.user_roles ADD COLUMN IF NOT EXISTS access_granted_time timestamp without time zone;
127
+ ALTER TABLE admin.user_roles ADD COLUMN IF NOT EXISTS actions text [];
128
+
129
+ ALTER TABLE admin.user_roles ADD CONSTRAINT admin_user_roles_pkey PRIMARY KEY (ugr_id);
130
+ ALTER TABLE admin.user_roles ADD CONSTRAINT admin_user_roles_user_uid_role_id_key UNIQUE (user_uid, role_id);
131
+
132
+
133
+ COMMENT ON TABLE admin.user_roles IS 'Відношення користувачів до груп';
134
+ COMMENT ON COLUMN admin.user_roles.user_uid IS 'ID користувача';
135
+ COMMENT ON COLUMN admin.user_roles.role_id IS 'ID групи';
136
+ COMMENT ON COLUMN admin.user_roles.uid IS 'Користувач, який створив запис в БД';
137
+ COMMENT ON COLUMN admin.user_roles.expiration IS 'закінчення терміну дії доступу до групи';
138
+ COMMENT ON COLUMN admin.user_roles.access_granted IS 'Ідентифікатор користувача який надав доступ';
139
+ COMMENT ON COLUMN admin.user_roles.access_granted_time IS 'Час коли надали доступ';
140
+ COMMENT ON COLUMN admin.user_roles.actions IS 'Рівень доступу користувача в межах групи';
141
+
142
+ CREATE INDEX IF NOT EXISTS admin_user_roles_access_user_uid_idx ON admin.user_roles USING btree (user_uid COLLATE pg_catalog."default");
143
+ CREATE INDEX IF NOT EXISTS admin_user_roles_cdate_btree_idx ON admin.user_roles USING btree (cdate);
144
+ CREATE INDEX IF NOT EXISTS admin_user_roles_editor_date_btree_idx ON admin.user_roles USING btree (editor_date);
145
+ CREATE INDEX IF NOT EXISTS admin_user_roles_user_uid_gin_idx ON admin.user_roles USING gin (user_uid COLLATE pg_catalog."default" gin_trgm_ops);
146
+ CREATE INDEX IF NOT EXISTS admin_user_roles_role_id_idx ON admin.user_roles USING btree (role_id COLLATE pg_catalog."default");
147
+
148
+
149
+ -- Route (Interface) <> User / Role (Group)
150
+ -- drop table if exists admin.role_access;
151
+ drop table if exists admin.access;
152
+
153
+ CREATE TABLE if not exists admin.role_access();
154
+ alter table admin.role_access DROP CONSTRAINT if exists admin_access_id_pkey;
155
+ alter table admin.role_access DROP CONSTRAINT if exists admin_role_access_id_pkey;
156
+ alter table admin.role_access DROP CONSTRAINT if exists admin_access_role_id_fkey;
157
+ alter table admin.role_access DROP CONSTRAINT if exists admin_access_route_id_uid_unique;
158
+ alter table admin.role_access DROP CONSTRAINT if exists admin_access_route_id_fkey;
159
+
160
+ alter table admin.role_access add column if not exists access_id text NOT NULL DEFAULT next_id();
161
+ alter table admin.role_access add column if not exists route_id text NOT NULL;
162
+ alter table admin.role_access add column if not exists role_id text;
163
+ alter table admin.role_access add column if not exists user_uid text;
164
+ alter table admin.role_access add column if not exists scope text;
165
+ alter table admin.role_access add column if not exists actions text[];
166
+ ALTER TABLE admin.role_access ADD COLUMN IF NOT EXISTS access_granted text;
167
+ ALTER TABLE admin.role_access ADD COLUMN IF NOT EXISTS access_granted_time timestamp without time zone;
168
+ alter table admin.role_access add column if not exists cdate timestamp without time zone NOT NULL DEFAULT date_trunc('seconds'::text, now());
169
+ alter table admin.role_access add column if not exists uid text;
170
+ alter table admin.role_access add column if not exists editor_id text;
171
+ alter table admin.role_access add column if not exists editor_date timestamp without time zone;
172
+
173
+ alter table admin.role_access add CONSTRAINT admin_role_access_id_pkey PRIMARY KEY (access_id);
174
+ alter table admin.role_access add CONSTRAINT admin_access_role_id_fkey FOREIGN KEY (role_id) REFERENCES admin.roles (role_id);
175
+ alter table admin.role_access add CONSTRAINT admin_access_route_id_uid_unique UNIQUE (route_id, user_uid, role_id);
176
+ alter table admin.role_access add constraint admin_access_route_id_fkey FOREIGN KEY (route_id) REFERENCES admin.routes(route_id);
177
+
178
+
179
+ COMMENT ON TABLE admin.role_access IS 'Налаштування прав. Відношення груп / окремих користувачів до шаблонів';
180
+ COMMENT ON COLUMN admin.role_access.route_id IS 'ID шаблона';
181
+ COMMENT ON COLUMN admin.role_access.role_id IS 'ID групи';
182
+ COMMENT ON COLUMN admin.role_access.user_uid IS 'ID користувача';
183
+ COMMENT ON COLUMN admin.role_access.scope IS 'Обмеження виведення (власні, відповідальний, всі)';
184
+ COMMENT ON COLUMN admin.role_access.actions IS 'Доступні дії';
185
+ COMMENT ON COLUMN admin.role_access.access_granted IS 'Ідентифікатор користувача який надав доступ';
186
+ COMMENT ON COLUMN admin.role_access.access_granted_time IS 'Час коли надали доступ';
187
+
188
+ CREATE INDEX if not exists admin_access_route_id_idx ON admin.role_access USING btree (route_id COLLATE pg_catalog."default");
189
+ CREATE INDEX if not exists admin_access_role_id_idx ON admin.role_access USING btree (role_id COLLATE pg_catalog."default");
190
+
191
+
@@ -1,52 +1,74 @@
1
- import pgClients from '../../pg/pgClients.js';
2
- import getTemplate from '../../table/funcs/getTemplate.js';
3
- import applyHook from '../../hook/funcs/applyHook.js';
4
-
5
- const q = `select a.route_id as id, coalesce(b.actions,array['view']) as "userActions", b.scope as "userScope"
6
- from admin.routes a
7
- left join admin.role_access b on
8
- a.route_id=b.route_id
9
- left join admin.roles c on
10
- b.role_id=c.role_id
11
- and c.enabled
12
- left join admin.user_roles d on
13
- c.role_id=d.role_id
14
- and ( case when
15
- d.expiration is not null
16
- then d.expiration > CURRENT_DATE
17
- else 1=1
18
- end )
19
- where $1 in (a.route_id, a.alias, a.table_name) and $2 in (b.user_uid, d.user_uid)`;
20
-
21
- export default async function getAccess({ table, user = {} }) {
22
- if (!table) return null;
23
-
24
- const hookData = await applyHook('getAccess', { table, user });
25
- if (hookData) return hookData;
26
-
27
- const { uid, user_type: userType = 'regular' } = user;
28
-
29
- if (userType.includes('admin')) {
30
- return { actions: ['view', 'edit', 'add', 'del'], query: '1=1' };
31
- }
32
-
33
- const body = await getTemplate('table', table);
34
- const tableActions = ['view'].concat(body?.actions || body?.action_default || []);
35
-
36
- if (body?.public || body?.access === 'public') {
37
- return { actions: tableActions, query: '1=1' };
38
- }
39
-
40
- if (body?.access === 'user' && uid) {
41
- return { actions: tableActions, query: '1=1' };
42
- }
43
-
44
- const { userScope, userActions = [] } = uid
45
- ? await pgClients.client.query(q, [table, uid]).then(el => el.rows?.[0] || {})
46
- : {};
47
-
48
- const query = uid && userScope === 'my' ? `uid='${uid}'` : '1=1';
49
- const actions = userActions.filter((el => tableActions.includes(el)));
50
-
51
- return { scope: userScope, actions, query };
52
- }
1
+ import pgClients from '../../pg/pgClients.js';
2
+ import getTemplate from '../../table/funcs/getTemplate.js';
3
+ import applyHook from '../../hook/funcs/applyHook.js';
4
+
5
+ /**
6
+ * @param {Array} user_roles.actions Actions - user actions <> group actions
7
+ * @param {Array} role_access.actions Actions - user actions = group actions
8
+ * @param {String} body.actions Actions from table template
9
+ * @param {String} table Table name / Interface alias
10
+ * @param {Object} user User object
11
+ * @param {String} user.uid User ID
12
+ * @param {String} user.user_type User type
13
+ * @returns { scope: String, actions: String[], query: String }
14
+ */
15
+
16
+ const q = `select a.route_id as id, coalesce(d.actions, b.actions, array['view']) as actions, b.scope, c.role_id
17
+ from admin.routes a
18
+ left join admin.role_access b on
19
+ a.route_id=b.route_id
20
+ left join admin.roles c on
21
+ b.role_id=c.role_id
22
+ and c.enabled
23
+ left join admin.user_roles d on
24
+ c.role_id=d.role_id
25
+ and ( case when
26
+ d.expiration is not null
27
+ then d.expiration > CURRENT_DATE
28
+ else 1=1
29
+ end )
30
+ where $1 in (a.route_id, a.alias, a.table_name) and $2 in (b.user_uid, d.user_uid)`;
31
+
32
+ export default async function getAccess({ table, user = {} }) {
33
+ if (!table) return null;
34
+
35
+ const hookData = await applyHook('getAccess', { table, user });
36
+ if (hookData) return hookData;
37
+
38
+ const { uid, user_type: userType = 'regular' } = user;
39
+
40
+ if (userType.includes('admin')) {
41
+ return { actions: ['view', 'edit', 'add', 'del'], query: '1=1' };
42
+ }
43
+
44
+ const body = await getTemplate('table', table);
45
+ const tableActions = ['view'].concat(body?.actions || body?.action_default || []);
46
+
47
+ if (body?.public || body?.access === 'public') {
48
+ return { actions: tableActions, query: '1=1' };
49
+ }
50
+
51
+ if (body?.access === 'user' && uid) {
52
+ return { actions: tableActions, query: '1=1' };
53
+ }
54
+
55
+ if (!uid) {
56
+ return { actions: [], query: '1=1' };
57
+ }
58
+
59
+ const userAccess = await pgClients.client.query(q, [table, uid])
60
+ .then(el => ({
61
+ ...el.rows[0] || {},
62
+ roles: el.rows?.map?.(row => row.role_id) || [],
63
+ actions: el.rows?.map?.(row => row.actions).flat() || [],
64
+ }));
65
+
66
+ const query = userAccess?.scope === 'my' ? `uid='${uid}'` : '1=1';
67
+ const actions = userAccess?.actions?.filter?.((el, idx, arr) => arr.indexOf(el) === idx && tableActions.includes(el));
68
+ return {
69
+ scope: userAccess?.scope,
70
+ roles: userAccess?.roles,
71
+ actions,
72
+ query,
73
+ };
74
+ }
@@ -1,105 +1,106 @@
1
- import { config, logger } from '@opengis/fastify-table/utils.js';
2
- import block from '../sqlInjection.js';
3
-
4
- /**
5
- * Middleware func
6
- *
7
- * @type function
8
- * @alias checkPolicy
9
- * @summary Функція дозволяє налаштувати доступ до сайту або API для адмін. та публічної частини веб-ресурсу
10
- * @param {String} path - назва апі
11
- * @returns {object|null} Returns object
12
- */
13
-
14
- export default function checkPolicy(req) {
15
- const {
16
- originalUrl: path, hostname, query, params, headers, method, session, routeOptions, unittest,
17
- } = req;
18
- const body = JSON.stringify(req?.body || {}).substring(30);
19
- const isAdmin = process.env.NODE_ENV === 'admin' || hostname.split(':').shift() === config.adminDomain || hostname.startsWith('admin');
20
- const user = req.user || session?.passport?.user;
21
-
22
- const isUser = config?.debug || !!user;
23
-
24
- const isServer = process.argv[2];
25
- const { policy = [] } = routeOptions?.config || {};
26
-
27
- /*= == 0.Check superadmin access === */
28
- if (policy.includes('superadmin') && user?.user_type !== 'superadmin') {
29
- logger.file('access', {
30
- path, method, params, query, body, message: 'access restricted: not superadmin', uid: user?.uid,
31
- });
32
- return { message: 'access restricted: 0', status: 403 };
33
- }
34
-
35
- /*= == 1.File injection === */
36
- if (JSON.stringify(params || {})?.includes('../') || JSON.stringify(query || {})?.includes('../') || path?.includes('../')) {
37
- logger.file('injection/file', {
38
- path, method, params, query, body, message: 'access restricted: 1', uid: user?.uid,
39
- });
40
- return { message: 'access restricted: 1', status: 403 };
41
- }
42
-
43
- /* === 1.1 File === */
44
- const allowExtPublic = ['.png', '.jpg', '.svg'];
45
- const ext = path.toLowerCase().substr(-4);
46
- if (path.includes('files/') && allowExtPublic.includes(ext)) return null;
47
-
48
- /* === 2.SQL Injection policy: no-sql === */
49
- if (!policy.includes('no-sql')) {
50
- // skip polyline param - data filter (geometry bounds)
51
- const stopWords = block.filter((el) => path.replace(query.polyline, '').includes(el));
52
- if (stopWords?.length) {
53
- logger.file('injection/sql', {
54
- path, method, params, query, body, stopWords, message: 'access restricted: 2', uid: user?.uid,
55
- });
56
- return { message: 'access restricted: 2', status: 403 };
57
- }
58
- }
59
- /* policy: skip if not API */
60
- const isApi = ['/files/', '/api/format/', '/api', '/api-user/', '/logger', '/file/'].filter((el) => path.includes(el)).length;
61
- if (!isApi) {
62
- return null;
63
- }
64
-
65
- /* === policy: public === */
66
- if (policy.includes('public')) {
67
- return null;
68
- }
69
-
70
- /* === 3. policy: user === */
71
- if (!user && policy.includes('user') && false) {
72
- logger.file('policy/user', {
73
- path, method, params, query, body, message: 'access restricted: 3',
74
- });
75
- return { message: 'access restricted: 3', status: 403 };
76
- }
77
-
78
- /* === 4. policy: referer === */
79
- if (!headers?.referer?.includes?.(hostname) && policy.includes('referer') && !config.local && !config.debug) {
80
- logger.file('policy/referer', {
81
- path, method, params, query, body, message: 'access restricted: 4', uid: user?.uid,
82
- });
83
- return { message: 'access restricted: 4', status: 403 };
84
- }
85
-
86
- /* === 5. policy: site auth === */
87
- if (!policy.includes('site') && !isAdmin && !config.local && !config.debug && !unittest
88
- && !['/auth/redirect', '/logout', `${config.prefix || '/api'}/login`].find(el => path.includes(el))) {
89
- logger.file('policy/site', {
90
- path, method, params, query, body, message: 'access restricted: 5', uid: user?.uid,
91
- });
92
- return { message: 'access restricted: 5', status: 403 };
93
- }
94
-
95
- /* === 6. base policy: block api, except login === */
96
- if (isAdmin && !isUser && isServer && !config.local && !config.debug
97
- && !path.startsWith(`${config.prefix || '/api'}/login`)) {
98
- logger.file('policy/api', {
99
- path, method, params, query, body, message: 'access restricted: 6', uid: user?.uid,
100
- });
101
- return { message: 'access restricted: 6', status: 403 };
102
- }
103
-
104
- return null;
105
- }
1
+ import { config, logger } from '../../../../utils.js';
2
+ import block from '../sqlInjection.js';
3
+
4
+ /**
5
+ * Middleware func
6
+ *
7
+ * @type function
8
+ * @alias checkPolicy
9
+ * @summary Функція дозволяє налаштувати доступ до сайту або API для адмін. та публічної частини веб-ресурсу
10
+ * @param {String} path - назва апі
11
+ * @returns {object|null} Returns object
12
+ */
13
+
14
+ export default function checkPolicy(req) {
15
+ const {
16
+ originalUrl: path, hostname, query, params, headers, method, session, routeOptions, unittest,
17
+ } = req;
18
+ const body = JSON.stringify(req?.body || {}).substring(30);
19
+
20
+ const isAdmin = process.env.NODE_ENV === 'admin' || hostname.split(':').shift() === config.adminDomain || config.admin || hostname.startsWith('admin');
21
+ const user = req.user || session?.passport?.user;
22
+
23
+ const isUser = config?.debug || !!user;
24
+
25
+ const isServer = process.argv[2];
26
+ const { policy = [] } = routeOptions?.config || {};
27
+
28
+ /*= == 0.Check superadmin access === */
29
+ if (policy.includes('superadmin') && user?.user_type !== 'superadmin') {
30
+ logger.file('access', {
31
+ path, method, params, query, body, message: 'access restricted: not superadmin', uid: user?.uid,
32
+ });
33
+ return { message: 'access restricted: 0', status: 403 };
34
+ }
35
+
36
+ /*= == 1.File injection === */
37
+ if (JSON.stringify(params || {})?.includes('../') || JSON.stringify(query || {})?.includes('../') || path?.includes('../')) {
38
+ logger.file('injection/file', {
39
+ path, method, params, query, body, message: 'access restricted: 1', uid: user?.uid,
40
+ });
41
+ return { message: 'access restricted: 1', status: 403 };
42
+ }
43
+
44
+ /* === 1.1 File === */
45
+ const allowExtPublic = ['.png', '.jpg', '.svg'];
46
+ const ext = path.toLowerCase().substr(-4);
47
+ if (path.includes('files/') && allowExtPublic.includes(ext)) return null;
48
+
49
+ /* === 2.SQL Injection policy: no-sql === */
50
+ if (!policy.includes('no-sql')) {
51
+ // skip polyline param - data filter (geometry bounds)
52
+ const stopWords = block.filter((el) => path.replace(query.polyline, '').includes(el));
53
+ if (stopWords?.length) {
54
+ logger.file('injection/sql', {
55
+ path, method, params, query, body, stopWords, message: 'access restricted: 2', uid: user?.uid,
56
+ });
57
+ return { message: 'access restricted: 2', status: 403 };
58
+ }
59
+ }
60
+ /* policy: skip if not API */
61
+ const isApi = ['/files/', '/api/format/', '/api', '/api-user/', '/logger', '/file/'].filter((el) => path.includes(el)).length;
62
+ if (!isApi) {
63
+ return null;
64
+ }
65
+
66
+ /* === policy: public === */
67
+ if (policy.includes('public')) {
68
+ return null;
69
+ }
70
+
71
+ /* === 3. policy: user === */
72
+ if (!user && policy.includes('user') && false) {
73
+ logger.file('policy/user', {
74
+ path, method, params, query, body, message: 'access restricted: 3',
75
+ });
76
+ return { message: 'access restricted: 3', status: 403 };
77
+ }
78
+
79
+ /* === 4. policy: referer === */
80
+ if (!headers?.referer?.includes?.(hostname) && policy.includes('referer') && !config.local && !config.debug) {
81
+ logger.file('policy/referer', {
82
+ path, method, params, query, body, message: 'access restricted: 4', uid: user?.uid,
83
+ });
84
+ return { message: 'access restricted: 4', status: 403 };
85
+ }
86
+
87
+ /* === 5. policy: site auth === */
88
+ if (!policy.includes('site') && !isAdmin && !config.local && !config.debug && !unittest
89
+ && !['/auth/redirect', '/logout', `${config.prefix || '/api'}/login`].find(el => path.includes(el))) {
90
+ logger.file('policy/site', {
91
+ path, method, params, query, body, message: 'access restricted: 5', uid: user?.uid,
92
+ });
93
+ return { message: 'access restricted: 5', status: 403 };
94
+ }
95
+
96
+ /* === 6. base policy: block api, except login === */
97
+ if (isAdmin && !isUser && isServer && !config.local && !config.debug
98
+ && !path.startsWith(`${config.prefix || '/api'}/login`)) {
99
+ logger.file('policy/api', {
100
+ path, method, params, query, body, message: 'access restricted: 6', uid: user?.uid,
101
+ });
102
+ return { message: 'access restricted: 6', status: 403 };
103
+ }
104
+
105
+ return null;
106
+ }
@@ -1,8 +1,6 @@
1
1
  import config from '../../../../config.js';
2
2
  import xssInjection from '../xssInjection.js';
3
3
 
4
- // RTE - rich text editor
5
-
6
4
  function checkXSS({ body, schema = {} }) {
7
5
  const data = typeof body === 'string' ? body : JSON.stringify(body);
8
6
  const stopWords = xssInjection.filter((el) => data.toLowerCase().includes(el));
@@ -11,7 +9,7 @@ function checkXSS({ body, schema = {} }) {
11
9
  const stopSpecialSymbols = data.match(/\p{S}OR\p{S}|\p{P}OR\p{P}| OR |\+OR\+/gi);
12
10
  if (stopSpecialSymbols?.length) stopSpecialSymbols?.forEach((el) => stopWords.push(el));
13
11
 
14
- // escape arrows on non-RTE
12
+ // escape arrows on non-rich text editor inputs
15
13
  const skipScreening = config.skipScreening || ['Summernote', 'Tiny', 'Ace', 'Texteditor'];
16
14
  Object.keys(body)
17
15
  .filter((key) => ['<', '>'].find((el) => body[key]?.includes?.(el))
@@ -20,23 +18,17 @@ function checkXSS({ body, schema = {} }) {
20
18
  Object.assign(body, { [key]: body[key].replace(/</g, '&lt;').replace(/>/g, '&gt;') });
21
19
  });
22
20
 
23
- // try { } catch (err) { return { error: err.toString() }; }
24
-
25
21
  if (!stopWords.length) return { body };
26
22
 
27
23
  const disabledCheckFields = Object.keys(schema || {})?.filter((el) => schema?.[el]?.xssCheck === false); // exclude specific columns
28
24
 
29
- // check RTE
30
- /* const richTextFields = Object.keys(schema).filter((el) => skipScreening.includes(schema[el]?.type));
31
- richTextFields.filter((key) => !checkList.find((el) => body[key].includes(el)))?.forEach((key) => {
32
- disabledCheckFields.push(key);
33
- }); */
34
-
35
25
  const field = Object.keys(body)
36
26
  ?.find((key) => body[key]?.toLowerCase
37
27
  && !disabledCheckFields.includes(key)
28
+ && (skipScreening.includes(schema?.[key]?.type) ? stopWords.find(el => !['href=', 'src='].includes(el)) : true)
38
29
  && body[key].toLowerCase().includes(stopWords[0]));
39
30
  if (field) {
31
+ console.error(stopWords[0], field, body[field]);
40
32
  return { error: `rule: ${stopWords[0]} | attr: ${field} | val: ${body[field]}`, body };
41
33
  }
42
34
  return { body };
@@ -1,70 +1,70 @@
1
- import { getPG } from '@opengis/fastify-table/utils.js';
2
- import logger from '../../logger/getLogger.js';
3
- import autoIndex from '../../pg/funcs/autoIndex.js';
4
- import pgClients from '../../pg/pgClients.js';
5
-
6
- import getSelect from './getSelect.js';
7
-
8
- const limit = 50;
9
- const selectMeta = {};
10
-
11
- export default async function getSelectMeta({ name, pg = pgClients.client, nocache }) {
12
- if (selectMeta[name] && !nocache) return selectMeta[name];
13
-
14
- const cls = await getSelect(name, pg);
15
- const pg1 = cls?.db ? getPG(cls.db) : pg;
16
- if (!pg1?.pk) await pg1.init();
17
-
18
- if (!cls) return null;
19
- if (cls.arr) return cls;
20
- if (!cls.sql) return null;
21
-
22
- const { sql: original } = cls;
23
- if (!original.toLowerCase) { console.log(`sql select null: ${name}`); return null; }
24
-
25
- const sql = `with c(id,text) as (select * from (${original})q limit ${limit}) select * from c`;
26
-
27
- /*= == meta table === */
28
-
29
- const tableNew = original.toLowerCase().replace(/\n/g, ' ').split(' from ').filter((el) => /^[a-z0-9_]+\.[a-z0-9_]+/.test(el))
30
- .map((el) => el.split(/[ )]/)[0].replace(/[\r\n]+/g, ''));
31
-
32
- const dataOrigin = await pg1.query(sql?.replace(`limit ${limit}`, 'limit 0'));
33
-
34
- const dataOrigin1 = await pg1.query(`${original} limit 0`);
35
-
36
- // const table = getTable(original);
37
- const count = cls?.count ?? await pg1.query(`select count(*) from (${original})q`).then((el) => el?.rows?.[0].count);
38
-
39
- // column name
40
- const cols = dataOrigin.fields.map((el) => el.name);
41
- const originalCols = dataOrigin1.fields.map((el) => el.name);
42
- const type = dataOrigin.fields.map((el) => pg1.pgType?.[el.dataTypeID] || 'text');
43
-
44
- autoIndex({ table: tableNew[0], columns: [originalCols[1]].concat(cls?.searchColumn?.split(',')), gin: 1 }).catch(err => logger.error(err));
45
-
46
- const searchColumn = cls?.searchColumn || (
47
- dataOrigin.fields.find((el) => el.name === 'search') ? 'search' : dataOrigin1.fields[1].name);
48
-
49
- const searchQuery = `(${searchColumn.split(',').map((el) => `lower("${el}") ~ $1 `).join(' or ')})`;
50
- // console.log(dataOrigin1.fields.map((el) => el.name).join(','));
51
- const data = {
52
- minLength: cls.minLength,
53
- limit: cls.limit,
54
- type: type.join(','),
55
- cols: cols.join(','),
56
- originalCols: originalCols.join(','),
57
- pk: originalCols[0],
58
- db: cls.db,
59
- original: `select * from (${original})q`,
60
- sql,
61
- count,
62
- searchQuery,
63
- table: tableNew.join(','),
64
- time: new Date().toISOString(),
65
-
66
- };
67
-
68
- selectMeta[name] = data;
69
- return data;
70
- }
1
+ import logger from '../../logger/getLogger.js';
2
+ import autoIndex from '../../pg/funcs/autoIndex.js';
3
+ import getPG from '../../pg/funcs/getPG.js';
4
+ import pgClients from '../../pg/pgClients.js';
5
+
6
+ import getSelect from './getSelect.js';
7
+
8
+ const limit = 50;
9
+ const selectMeta = {};
10
+
11
+ export default async function getSelectMeta({ name, pg = pgClients.client, nocache }) {
12
+ if (selectMeta[name] && !nocache) return selectMeta[name];
13
+
14
+ const cls = await getSelect(name, pg);
15
+ const pg1 = cls?.db ? getPG(cls.db) : pg;
16
+ if (!pg1?.pk) await pg1.init();
17
+
18
+ if (!cls) return null;
19
+ if (cls.arr) return cls;
20
+ if (!cls.sql) return null;
21
+
22
+ const { sql: original } = cls;
23
+ if (!original.toLowerCase) { console.log(`sql select null: ${name}`); return null; }
24
+
25
+ const sql = `with c(id,text) as (select * from (${original})q limit ${limit}) select * from c`;
26
+
27
+ /*= == meta table === */
28
+
29
+ const tableNew = original.toLowerCase().replace(/\n/g, ' ').split(' from ').filter((el) => /^[a-z0-9_]+\.[a-z0-9_]+/.test(el))
30
+ .map((el) => el.split(/[ )]/)[0].replace(/[\r\n]+/g, ''));
31
+
32
+ const dataOrigin = await pg1.query(sql?.replace(`limit ${limit}`, 'limit 0'));
33
+
34
+ const dataOrigin1 = await pg1.query(`${original} limit 0`);
35
+
36
+ // const table = getTable(original);
37
+ const count = cls?.count ?? await pg1.query(`select count(*) from (${original})q`).then((el) => el?.rows?.[0].count);
38
+
39
+ // column name
40
+ const cols = dataOrigin.fields.map((el) => el.name);
41
+ const originalCols = dataOrigin1.fields.map((el) => el.name);
42
+ const type = dataOrigin.fields.map((el) => pg1.pgType?.[el.dataTypeID] || 'text');
43
+
44
+ autoIndex({ table: tableNew[0], columns: [originalCols[1]].concat(cls?.searchColumn?.split(',')), gin: 1 }).catch(err => logger.error(err));
45
+
46
+ const searchColumn = cls?.searchColumn || (
47
+ dataOrigin.fields.find((el) => el.name === 'search') ? 'search' : dataOrigin1.fields[1].name);
48
+
49
+ const searchQuery = `(${searchColumn.split(',').map((el) => `lower("${el}") ~ $1 `).join(' or ')})`;
50
+ // console.log(dataOrigin1.fields.map((el) => el.name).join(','));
51
+ const data = {
52
+ minLength: cls.minLength,
53
+ limit: cls.limit,
54
+ type: type.join(','),
55
+ cols: cols.join(','),
56
+ originalCols: originalCols.join(','),
57
+ pk: originalCols[0],
58
+ db: cls.db,
59
+ original: `select * from (${original})q`,
60
+ sql,
61
+ count,
62
+ searchQuery,
63
+ table: tableNew.join(','),
64
+ time: new Date().toISOString(),
65
+
66
+ };
67
+
68
+ selectMeta[name] = data;
69
+ return data;
70
+ }
@@ -1,22 +1,22 @@
1
- import update from './controllers/update.js';
2
- import insert from './controllers/insert.js';
3
- import deleteCrud from './controllers/deleteCrud.js';
4
- import table from './controllers/table.js';
5
-
6
- const tableSchema = {
7
- params: {
8
- id: { type: 'string', pattern: '^([\\d\\w]+)$' },
9
- table: { type: 'string', pattern: '^([\\w\\d_.]+)$' },
10
- },
11
- };
12
-
13
- async function plugin(fastify, config = {}) {
14
- const prefix = config.prefix || '/api';
15
- const policy = ['public'];
16
- fastify.put(`${prefix}/table/:table/:id?`, { config: { policy }, schema: tableSchema }, update);
17
- fastify.delete(`${prefix}/table/:table/:id?`, { config: { policy }, schema: tableSchema }, deleteCrud);
18
- fastify.post(`${prefix}/table/:table/:id?`, { config: { policy }, schema: tableSchema }, insert);
19
- fastify.get(`${prefix}/table/:table/:id?`, { config: { policy }, schema: tableSchema }, table);
20
- }
21
-
22
- export default plugin;
1
+ import update from './controllers/update.js';
2
+ import insert from './controllers/insert.js';
3
+ import deleteCrud from './controllers/deleteCrud.js';
4
+ import table from './controllers/table.js';
5
+
6
+ const tableSchema = {
7
+ params: {
8
+ id: { type: 'string', pattern: '^([\\w\\d_.]+)$' },
9
+ table: { type: 'string', pattern: '^([\\w\\d_.]+)$' },
10
+ },
11
+ };
12
+
13
+ async function plugin(fastify, config = {}) {
14
+ const prefix = config.prefix || '/api';
15
+ const policy = ['public'];
16
+ fastify.put(`${prefix}/table/:table/:id?`, { config: { policy }, schema: tableSchema }, update);
17
+ fastify.delete(`${prefix}/table/:table/:id?`, { config: { policy }, schema: tableSchema }, deleteCrud);
18
+ fastify.post(`${prefix}/table/:table/:id?`, { config: { policy }, schema: tableSchema }, insert);
19
+ fastify.get(`${prefix}/table/:table/:id?`, { config: { policy }, schema: tableSchema }, table);
20
+ }
21
+
22
+ export default plugin;