@opengis/fastify-table 1.0.90 → 1.0.91
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 +4 -0
- package/crud/controllers/deleteCrud.js +22 -19
- package/crud/controllers/insert.js +58 -54
- package/crud/controllers/update.js +61 -59
- package/crud/funcs/dataDelete.js +19 -15
- package/crud/funcs/dataInsert.js +30 -24
- package/crud/funcs/dataUpdate.js +29 -24
- package/crud/funcs/getAccess.js +53 -53
- package/crud/funcs/getOpt.js +10 -10
- package/crud/funcs/setOpt.js +16 -16
- package/crud/funcs/utils/logChanges.js +71 -0
- package/crud/index.js +36 -36
- package/helper.js +28 -28
- package/index.js +97 -97
- package/notification/controllers/userNotifications.js +19 -19
- package/notification/funcs/addNotification.js +8 -8
- package/package.json +1 -1
- package/pg/pgClients.js +20 -20
- package/policy/funcs/checkPolicy.js +83 -83
- package/policy/funcs/sqlInjection.js +33 -33
- package/policy/index.js +14 -14
- package/redis/client.js +8 -8
- package/redis/funcs/redisClients.js +2 -2
- package/redis/index.js +19 -19
- package/server/migrations/0.sql +78 -78
- package/server/migrations/log.sql +63 -26
- package/server/templates/form/test.dataset.form.json +411 -411
- package/server/templates/table/test.dataset.table.json +28 -28
- package/server/templates/table/test.gis.map.table.json +44 -44
- package/table/controllers/data.js +103 -103
- package/table/controllers/suggest.js +79 -79
- package/table/controllers/table.js +52 -49
- package/table/controllers/utils/gisIRColumn.js +68 -68
- package/table/funcs/getFilterSQL/index.js +75 -75
- package/table/funcs/getFilterSQL/util/formatValue.js +142 -142
- package/table/funcs/getFilterSQL/util/getCustomQuery.js +13 -13
- package/table/funcs/getFilterSQL/util/getFilterQuery.js +73 -73
- package/table/funcs/getFilterSQL/util/getOptimizedQuery.js +12 -12
- package/table/funcs/getFilterSQL/util/getTableSql.js +34 -34
- package/table/funcs/metaFormat/getSelectVal.js +20 -20
- package/table/funcs/metaFormat/index.js +28 -28
- package/test/api/crud.test.js +88 -88
- package/test/api/table.test.js +89 -89
- package/test/api/widget.test.js +117 -114
- package/test/funcs/crud.test.js +122 -76
- package/util/controllers/properties.add.js +57 -51
- package/util/controllers/status.monitor.js +8 -8
- package/widget/controllers/utils/historyFormat.js +76 -76
- package/widget/controllers/utils/obj2db.js +13 -13
- package/widget/controllers/widget.del.js +44 -44
- package/widget/controllers/widget.get.js +98 -96
- package/widget/controllers/widget.set.js +76 -70
- package/widget/index.js +40 -40
|
@@ -1,83 +1,83 @@
|
|
|
1
|
-
import block from './sqlInjection.js';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Middleware func
|
|
5
|
-
*
|
|
6
|
-
* @type function
|
|
7
|
-
* @alias checkPolicy
|
|
8
|
-
* @summary Функція дозволяє налаштувати доступ до сайту або API для адмін. та публічної частини веб-ресурсу
|
|
9
|
-
* @param {String} path - назва апі
|
|
10
|
-
* @returns {object|null} Returns object
|
|
11
|
-
*/
|
|
12
|
-
|
|
13
|
-
export default function checkPolicy(req) {
|
|
14
|
-
const {
|
|
15
|
-
originalUrl: path, hostname, query, params, headers: hs, log, sid = 35, funcs = {},
|
|
16
|
-
} = req;
|
|
17
|
-
const user = req.user || req.session?.passport?.user;
|
|
18
|
-
|
|
19
|
-
const { config } = funcs;
|
|
20
|
-
const isUser = config.debug || !!user;
|
|
21
|
-
|
|
22
|
-
const isServer = process.argv[2];
|
|
23
|
-
const { policy = [] } = req.routeOptions?.config || {};
|
|
24
|
-
|
|
25
|
-
/*= == 0.Check superadmin access === */
|
|
26
|
-
if (policy.includes('superadmin') && user?.user_type !== 'superadmin') {
|
|
27
|
-
log.warn({
|
|
28
|
-
name: 'api/superadmin', params, query, body: JSON.stringify(req?.body || {}).substring(30), message: 'access restricted: 0',
|
|
29
|
-
});
|
|
30
|
-
return { message: 'access restricted: 0', status: 403 };
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
/*= == 1.File injection === */
|
|
34
|
-
if (JSON.stringify(params || {})?.includes('../') || JSON.stringify(query || {})?.includes('../') || path?.includes('../')) {
|
|
35
|
-
log.warn({
|
|
36
|
-
name: 'injection/file', params, query, message: 'access restricted: 1',
|
|
37
|
-
});
|
|
38
|
-
return { message: 'access restricted: 1', status: 403 };
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
/*= == 1.1 File === */
|
|
42
|
-
const allowExtPublic = ['.png', '.jpg', '.svg'];
|
|
43
|
-
const ext = path.toLowerCase().substr(-4);
|
|
44
|
-
if (path.includes('files/') && allowExtPublic.includes(ext)) return null;
|
|
45
|
-
|
|
46
|
-
/*= == 2.SQL Injection policy: no-sql === */
|
|
47
|
-
if (!policy.includes('no-sql')) {
|
|
48
|
-
// skip polyline param - data filter (geometry bounds)
|
|
49
|
-
const stopWords = block.filter((el) => path.replace(query.polyline, '').includes(el));
|
|
50
|
-
if (stopWords?.length) {
|
|
51
|
-
log.warn({ name: 'injection/sql', stopWords, message: 'access restricted: 2' });
|
|
52
|
-
return { message: 'access restricted: 2', status: 403 };
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
/* Check is Not API */
|
|
56
|
-
const isApi = ['/files/', '/api/format/', '/api-user/', '/logger', '/file/'].filter((el) => path.includes(el)).length;
|
|
57
|
-
if (!isApi) return null;
|
|
58
|
-
|
|
59
|
-
/*= == 3. policy: referer === */
|
|
60
|
-
if (!hs?.referer?.includes?.(hostname) && policy.includes('referer') && !config.local && !config.debug) {
|
|
61
|
-
log.warn({ name: 'referer', message: 'access restricted: 3' });
|
|
62
|
-
return { message: 'access restricted: 3', status: 403 };
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
/*= == policy: public === */
|
|
66
|
-
if (policy.includes('public')) {
|
|
67
|
-
return null;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
/*= == 4. policy: site auth === */
|
|
71
|
-
if (!policy.includes('site') && sid === 1 && isUser && !config.local && !config.debug) {
|
|
72
|
-
log.warn({ name: 'site', message: 'access restricted: 4' });
|
|
73
|
-
return { message: 'access restricted: 4', status: 403 };
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
/*= == 5. base policy: block api === */
|
|
77
|
-
if (sid === 35 && !isUser && isServer && !config.local && !config.debug) {
|
|
78
|
-
log.warn({ name: 'api', message: 'access restricted: 5' });
|
|
79
|
-
return { message: 'access restricted: 5', status: 403 };
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
return null;
|
|
83
|
-
}
|
|
1
|
+
import block from './sqlInjection.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Middleware func
|
|
5
|
+
*
|
|
6
|
+
* @type function
|
|
7
|
+
* @alias checkPolicy
|
|
8
|
+
* @summary Функція дозволяє налаштувати доступ до сайту або API для адмін. та публічної частини веб-ресурсу
|
|
9
|
+
* @param {String} path - назва апі
|
|
10
|
+
* @returns {object|null} Returns object
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
export default function checkPolicy(req) {
|
|
14
|
+
const {
|
|
15
|
+
originalUrl: path, hostname, query, params, headers: hs, log, sid = 35, funcs = {},
|
|
16
|
+
} = req;
|
|
17
|
+
const user = req.user || req.session?.passport?.user;
|
|
18
|
+
|
|
19
|
+
const { config } = funcs;
|
|
20
|
+
const isUser = config.debug || !!user;
|
|
21
|
+
|
|
22
|
+
const isServer = process.argv[2];
|
|
23
|
+
const { policy = [] } = req.routeOptions?.config || {};
|
|
24
|
+
|
|
25
|
+
/*= == 0.Check superadmin access === */
|
|
26
|
+
if (policy.includes('superadmin') && user?.user_type !== 'superadmin') {
|
|
27
|
+
log.warn({
|
|
28
|
+
name: 'api/superadmin', params, query, body: JSON.stringify(req?.body || {}).substring(30), message: 'access restricted: 0',
|
|
29
|
+
});
|
|
30
|
+
return { message: 'access restricted: 0', status: 403 };
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/*= == 1.File injection === */
|
|
34
|
+
if (JSON.stringify(params || {})?.includes('../') || JSON.stringify(query || {})?.includes('../') || path?.includes('../')) {
|
|
35
|
+
log.warn({
|
|
36
|
+
name: 'injection/file', params, query, message: 'access restricted: 1',
|
|
37
|
+
});
|
|
38
|
+
return { message: 'access restricted: 1', status: 403 };
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/*= == 1.1 File === */
|
|
42
|
+
const allowExtPublic = ['.png', '.jpg', '.svg'];
|
|
43
|
+
const ext = path.toLowerCase().substr(-4);
|
|
44
|
+
if (path.includes('files/') && allowExtPublic.includes(ext)) return null;
|
|
45
|
+
|
|
46
|
+
/*= == 2.SQL Injection policy: no-sql === */
|
|
47
|
+
if (!policy.includes('no-sql')) {
|
|
48
|
+
// skip polyline param - data filter (geometry bounds)
|
|
49
|
+
const stopWords = block.filter((el) => path.replace(query.polyline, '').includes(el));
|
|
50
|
+
if (stopWords?.length) {
|
|
51
|
+
log.warn({ name: 'injection/sql', stopWords, message: 'access restricted: 2' });
|
|
52
|
+
return { message: 'access restricted: 2', status: 403 };
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
/* Check is Not API */
|
|
56
|
+
const isApi = ['/files/', '/api/format/', '/api-user/', '/logger', '/file/'].filter((el) => path.includes(el)).length;
|
|
57
|
+
if (!isApi) return null;
|
|
58
|
+
|
|
59
|
+
/*= == 3. policy: referer === */
|
|
60
|
+
if (!hs?.referer?.includes?.(hostname) && policy.includes('referer') && !config.local && !config.debug) {
|
|
61
|
+
log.warn({ name: 'referer', message: 'access restricted: 3' });
|
|
62
|
+
return { message: 'access restricted: 3', status: 403 };
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/*= == policy: public === */
|
|
66
|
+
if (policy.includes('public')) {
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/*= == 4. policy: site auth === */
|
|
71
|
+
if (!policy.includes('site') && sid === 1 && isUser && !config.local && !config.debug) {
|
|
72
|
+
log.warn({ name: 'site', message: 'access restricted: 4' });
|
|
73
|
+
return { message: 'access restricted: 4', status: 403 };
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/*= == 5. base policy: block api === */
|
|
77
|
+
if (sid === 35 && !isUser && isServer && !config.local && !config.debug) {
|
|
78
|
+
log.warn({ name: 'api', message: 'access restricted: 5' });
|
|
79
|
+
return { message: 'access restricted: 5', status: 403 };
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
@@ -1,33 +1,33 @@
|
|
|
1
|
-
const sqlInjection = [
|
|
2
|
-
'()',
|
|
3
|
-
'^',
|
|
4
|
-
'*',
|
|
5
|
-
'like ',
|
|
6
|
-
'@variable',
|
|
7
|
-
'@@variable',
|
|
8
|
-
'group by ',
|
|
9
|
-
'union ',
|
|
10
|
-
'select ',
|
|
11
|
-
'having ',
|
|
12
|
-
'as injectx',
|
|
13
|
-
'where ',
|
|
14
|
-
'rlike ',
|
|
15
|
-
'if(',
|
|
16
|
-
'sleep(',
|
|
17
|
-
'waitfor delay',
|
|
18
|
-
'benchmark(',
|
|
19
|
-
'pg_sleep(',
|
|
20
|
-
"'\\\"",
|
|
21
|
-
'randomblob(',
|
|
22
|
-
'order by ',
|
|
23
|
-
'union all ',
|
|
24
|
-
'+or',
|
|
25
|
-
'or ',
|
|
26
|
-
'and ',
|
|
27
|
-
"'' ",
|
|
28
|
-
'""" ',
|
|
29
|
-
'<script',
|
|
30
|
-
'javascript:',
|
|
31
|
-
]
|
|
32
|
-
|
|
33
|
-
export default sqlInjection;
|
|
1
|
+
const sqlInjection = [
|
|
2
|
+
'()',
|
|
3
|
+
'^',
|
|
4
|
+
'*',
|
|
5
|
+
'like ',
|
|
6
|
+
'@variable',
|
|
7
|
+
'@@variable',
|
|
8
|
+
'group by ',
|
|
9
|
+
'union ',
|
|
10
|
+
'select ',
|
|
11
|
+
'having ',
|
|
12
|
+
'as injectx',
|
|
13
|
+
'where ',
|
|
14
|
+
'rlike ',
|
|
15
|
+
'if(',
|
|
16
|
+
'sleep(',
|
|
17
|
+
'waitfor delay',
|
|
18
|
+
'benchmark(',
|
|
19
|
+
'pg_sleep(',
|
|
20
|
+
"'\\\"",
|
|
21
|
+
'randomblob(',
|
|
22
|
+
'order by ',
|
|
23
|
+
'union all ',
|
|
24
|
+
'+or',
|
|
25
|
+
'or ',
|
|
26
|
+
'and ',
|
|
27
|
+
"'' ",
|
|
28
|
+
'""" ',
|
|
29
|
+
'<script',
|
|
30
|
+
'javascript:',
|
|
31
|
+
]
|
|
32
|
+
|
|
33
|
+
export default sqlInjection;
|
package/policy/index.js
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
// import fp from 'fastify-plugin';
|
|
2
|
-
|
|
3
|
-
import checkPolicy from './funcs/checkPolicy.js';
|
|
4
|
-
|
|
5
|
-
async function plugin(fastify) {
|
|
6
|
-
fastify.addHook('onRequest', async (request, reply) => {
|
|
7
|
-
const hookData = checkPolicy(request);
|
|
8
|
-
if (hookData?.status && hookData?.message) {
|
|
9
|
-
return reply.status(hookData?.status).send(hookData.message);
|
|
10
|
-
}
|
|
11
|
-
});
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export default plugin;
|
|
1
|
+
// import fp from 'fastify-plugin';
|
|
2
|
+
|
|
3
|
+
import checkPolicy from './funcs/checkPolicy.js';
|
|
4
|
+
|
|
5
|
+
async function plugin(fastify) {
|
|
6
|
+
fastify.addHook('onRequest', async (request, reply) => {
|
|
7
|
+
const hookData = checkPolicy(request);
|
|
8
|
+
if (hookData?.status && hookData?.message) {
|
|
9
|
+
return reply.status(hookData?.status).send(hookData.message);
|
|
10
|
+
}
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export default plugin;
|
package/redis/client.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import redisClients from './funcs/redisClients.js';
|
|
2
|
-
import getRedis from './funcs/getRedis.js';
|
|
3
|
-
|
|
4
|
-
if (!redisClients[0]) {
|
|
5
|
-
getRedis({ db: 0 });
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
export default redisClients[0];
|
|
1
|
+
import redisClients from './funcs/redisClients.js';
|
|
2
|
+
import getRedis from './funcs/getRedis.js';
|
|
3
|
+
|
|
4
|
+
if (!redisClients[0]) {
|
|
5
|
+
getRedis({ db: 0 });
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export default redisClients[0];
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const redisClients = {};
|
|
2
|
-
export default redisClients;
|
|
1
|
+
const redisClients = {};
|
|
2
|
+
export default redisClients;
|
package/redis/index.js
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
// import client from './client.js';
|
|
2
|
-
import getRedis from './funcs/getRedis.js';
|
|
3
|
-
// import client from './funcs/redisClients.js';
|
|
4
|
-
|
|
5
|
-
function close(fastify) {
|
|
6
|
-
fastify.rclient.quit();
|
|
7
|
-
// fastify.rclient2.quit();
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
async function plugin(fastify) {
|
|
11
|
-
const client = getRedis({ db: 0, funcs: fastify });
|
|
12
|
-
client.getJSON = client.get;
|
|
13
|
-
fastify.decorate('rclient', client);
|
|
14
|
-
fastify.decorate('getRedis', getRedis);
|
|
15
|
-
// fastify.decorate('rclient2', client2);
|
|
16
|
-
fastify.addHook('onClose', close);
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export default plugin;
|
|
1
|
+
// import client from './client.js';
|
|
2
|
+
import getRedis from './funcs/getRedis.js';
|
|
3
|
+
// import client from './funcs/redisClients.js';
|
|
4
|
+
|
|
5
|
+
function close(fastify) {
|
|
6
|
+
fastify.rclient.quit();
|
|
7
|
+
// fastify.rclient2.quit();
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
async function plugin(fastify) {
|
|
11
|
+
const client = getRedis({ db: 0, funcs: fastify });
|
|
12
|
+
client.getJSON = client.get;
|
|
13
|
+
fastify.decorate('rclient', client);
|
|
14
|
+
fastify.decorate('getRedis', getRedis);
|
|
15
|
+
// fastify.decorate('rclient2', client2);
|
|
16
|
+
fastify.addHook('onClose', close);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export default plugin;
|
package/server/migrations/0.sql
CHANGED
|
@@ -1,78 +1,78 @@
|
|
|
1
|
-
-- fix error if function exists and return type not text i.e bigint
|
|
2
|
-
|
|
3
|
-
do $$
|
|
4
|
-
|
|
5
|
-
declare
|
|
6
|
-
m record;
|
|
7
|
-
_pk text;
|
|
8
|
-
_tables json;
|
|
9
|
-
_returnType text;
|
|
10
|
-
|
|
11
|
-
begin
|
|
12
|
-
|
|
13
|
-
select format_type(p.prorettype, null) as return_type
|
|
14
|
-
from pg_proc p
|
|
15
|
-
where p.proname = 'next_id'
|
|
16
|
-
and p.pronamespace = 'public'::regnamespace into _returnType;
|
|
17
|
-
|
|
18
|
-
if (_returnType != 'text') then
|
|
19
|
-
raise notice 'default reassign start: % -> text', _returnType;
|
|
20
|
-
|
|
21
|
-
CREATE EXTENSION if not exists "uuid-ossp";
|
|
22
|
-
|
|
23
|
-
SELECT json_object_agg(a.attrelid::regclass, a.attname)
|
|
24
|
-
FROM pg_catalog.pg_attribute a
|
|
25
|
-
LEFT JOIN pg_catalog.pg_attrdef d ON (a.attrelid, a.attnum) = (d.adrelid, d.adnum)
|
|
26
|
-
WHERE NOT a.attisdropped -- no dropped (dead) columns
|
|
27
|
-
AND a.attnum > 0 -- no system columns
|
|
28
|
-
AND pg_get_expr(d.adbin, d.adrelid) = 'next_id()' into _tables;
|
|
29
|
-
|
|
30
|
-
FOR m in (select json_object_keys(_tables) as table) loop
|
|
31
|
-
_pk = _tables->>m.table;
|
|
32
|
-
raise notice 'drop default: %,%', m.table, _pk;
|
|
33
|
-
EXECUTE('alter table '|| m.table || ' alter column ' || _pk || ' set default null;');
|
|
34
|
-
end loop;
|
|
35
|
-
|
|
36
|
-
DROP FUNCTION IF EXISTS next_id();
|
|
37
|
-
|
|
38
|
-
CREATE EXTENSION if not exists "uuid-ossp";
|
|
39
|
-
|
|
40
|
-
CREATE OR REPLACE FUNCTION next_id()
|
|
41
|
-
RETURNS text AS
|
|
42
|
-
$BODY$
|
|
43
|
-
DECLARE
|
|
44
|
-
|
|
45
|
-
BEGIN
|
|
46
|
-
return replace(uuid_generate_v4()::text, '-', '');
|
|
47
|
-
END;
|
|
48
|
-
$BODY$
|
|
49
|
-
LANGUAGE plpgsql VOLATILE
|
|
50
|
-
COST 100;
|
|
51
|
-
|
|
52
|
-
FOR m in (select json_object_keys(_tables) as table) loop
|
|
53
|
-
_pk = _tables->>m.table;
|
|
54
|
-
raise notice 'reassign default: %, %', m.table, _pk;
|
|
55
|
-
EXECUTE('alter table '|| m.table || ' alter column ' || _pk || ' set default next_id();');
|
|
56
|
-
end loop;
|
|
57
|
-
|
|
58
|
-
raise notice 'reassign default finish: %', _tables;
|
|
59
|
-
|
|
60
|
-
else
|
|
61
|
-
raise notice 'skip default reassign';
|
|
62
|
-
|
|
63
|
-
CREATE EXTENSION if not exists "uuid-ossp";
|
|
64
|
-
|
|
65
|
-
CREATE OR REPLACE FUNCTION next_id()
|
|
66
|
-
RETURNS text AS
|
|
67
|
-
$BODY$
|
|
68
|
-
DECLARE
|
|
69
|
-
|
|
70
|
-
BEGIN
|
|
71
|
-
return replace(uuid_generate_v4()::text, '-', '');
|
|
72
|
-
END;
|
|
73
|
-
$BODY$
|
|
74
|
-
LANGUAGE plpgsql VOLATILE
|
|
75
|
-
COST 100;
|
|
76
|
-
end if;
|
|
77
|
-
|
|
78
|
-
end $$
|
|
1
|
+
-- fix error if function exists and return type not text i.e bigint
|
|
2
|
+
|
|
3
|
+
do $$
|
|
4
|
+
|
|
5
|
+
declare
|
|
6
|
+
m record;
|
|
7
|
+
_pk text;
|
|
8
|
+
_tables json;
|
|
9
|
+
_returnType text;
|
|
10
|
+
|
|
11
|
+
begin
|
|
12
|
+
|
|
13
|
+
select format_type(p.prorettype, null) as return_type
|
|
14
|
+
from pg_proc p
|
|
15
|
+
where p.proname = 'next_id'
|
|
16
|
+
and p.pronamespace = 'public'::regnamespace into _returnType;
|
|
17
|
+
|
|
18
|
+
if (_returnType != 'text') then
|
|
19
|
+
raise notice 'default reassign start: % -> text', _returnType;
|
|
20
|
+
|
|
21
|
+
CREATE EXTENSION if not exists "uuid-ossp";
|
|
22
|
+
|
|
23
|
+
SELECT json_object_agg(a.attrelid::regclass, a.attname)
|
|
24
|
+
FROM pg_catalog.pg_attribute a
|
|
25
|
+
LEFT JOIN pg_catalog.pg_attrdef d ON (a.attrelid, a.attnum) = (d.adrelid, d.adnum)
|
|
26
|
+
WHERE NOT a.attisdropped -- no dropped (dead) columns
|
|
27
|
+
AND a.attnum > 0 -- no system columns
|
|
28
|
+
AND pg_get_expr(d.adbin, d.adrelid) = 'next_id()' into _tables;
|
|
29
|
+
|
|
30
|
+
FOR m in (select json_object_keys(_tables) as table) loop
|
|
31
|
+
_pk = _tables->>m.table;
|
|
32
|
+
raise notice 'drop default: %,%', m.table, _pk;
|
|
33
|
+
EXECUTE('alter table '|| m.table || ' alter column ' || _pk || ' set default null;');
|
|
34
|
+
end loop;
|
|
35
|
+
|
|
36
|
+
DROP FUNCTION IF EXISTS next_id();
|
|
37
|
+
|
|
38
|
+
CREATE EXTENSION if not exists "uuid-ossp";
|
|
39
|
+
|
|
40
|
+
CREATE OR REPLACE FUNCTION next_id()
|
|
41
|
+
RETURNS text AS
|
|
42
|
+
$BODY$
|
|
43
|
+
DECLARE
|
|
44
|
+
|
|
45
|
+
BEGIN
|
|
46
|
+
return replace(uuid_generate_v4()::text, '-', '');
|
|
47
|
+
END;
|
|
48
|
+
$BODY$
|
|
49
|
+
LANGUAGE plpgsql VOLATILE
|
|
50
|
+
COST 100;
|
|
51
|
+
|
|
52
|
+
FOR m in (select json_object_keys(_tables) as table) loop
|
|
53
|
+
_pk = _tables->>m.table;
|
|
54
|
+
raise notice 'reassign default: %, %', m.table, _pk;
|
|
55
|
+
EXECUTE('alter table '|| m.table || ' alter column ' || _pk || ' set default next_id();');
|
|
56
|
+
end loop;
|
|
57
|
+
|
|
58
|
+
raise notice 'reassign default finish: %', _tables;
|
|
59
|
+
|
|
60
|
+
else
|
|
61
|
+
raise notice 'skip default reassign';
|
|
62
|
+
|
|
63
|
+
CREATE EXTENSION if not exists "uuid-ossp";
|
|
64
|
+
|
|
65
|
+
CREATE OR REPLACE FUNCTION next_id()
|
|
66
|
+
RETURNS text AS
|
|
67
|
+
$BODY$
|
|
68
|
+
DECLARE
|
|
69
|
+
|
|
70
|
+
BEGIN
|
|
71
|
+
return replace(uuid_generate_v4()::text, '-', '');
|
|
72
|
+
END;
|
|
73
|
+
$BODY$
|
|
74
|
+
LANGUAGE plpgsql VOLATILE
|
|
75
|
+
COST 100;
|
|
76
|
+
end if;
|
|
77
|
+
|
|
78
|
+
end $$
|
|
@@ -1,44 +1,81 @@
|
|
|
1
1
|
create schema if not exists log;
|
|
2
2
|
|
|
3
|
+
-- DROP TABLE IF EXISTS log.table_changes cascade;
|
|
3
4
|
CREATE TABLE IF NOT EXISTS log.table_changes();
|
|
4
|
-
ALTER TABLE log.table_changes
|
|
5
|
-
ALTER TABLE log.table_changes ADD COLUMN IF NOT EXISTS table_change_id text NOT NULL DEFAULT next_id();
|
|
6
|
-
|
|
7
|
-
ALTER TABLE log.table_changes ADD COLUMN IF NOT EXISTS entity_type text;
|
|
8
|
-
ALTER TABLE log.table_changes ADD COLUMN IF NOT EXISTS entity_id text; -- object_id
|
|
5
|
+
ALTER TABLE log.table_changes ADD COLUMN IF NOT EXISTS change_id text NOT NULL DEFAULT next_id();
|
|
9
6
|
ALTER TABLE log.table_changes ADD COLUMN IF NOT EXISTS change_type text;
|
|
10
|
-
ALTER TABLE log.table_changes ADD COLUMN IF NOT EXISTS change_key text;
|
|
11
7
|
ALTER TABLE log.table_changes ADD COLUMN IF NOT EXISTS change_date date;
|
|
12
|
-
ALTER TABLE log.table_changes ADD COLUMN IF NOT EXISTS
|
|
13
|
-
ALTER TABLE log.table_changes ADD COLUMN IF NOT EXISTS
|
|
14
|
-
ALTER TABLE log.table_changes ADD COLUMN IF NOT EXISTS
|
|
15
|
-
ALTER TABLE log.table_changes ADD COLUMN IF NOT EXISTS date_new timestamp without time zone;
|
|
16
|
-
ALTER TABLE log.table_changes ADD COLUMN IF NOT EXISTS number_old numeric;
|
|
17
|
-
ALTER TABLE log.table_changes ADD COLUMN IF NOT EXISTS number_new numeric;
|
|
18
|
-
ALTER TABLE log.table_changes ADD COLUMN IF NOT EXISTS bool_old boolean;
|
|
19
|
-
ALTER TABLE log.table_changes ADD COLUMN IF NOT EXISTS bool_new boolean;
|
|
20
|
-
ALTER TABLE log.table_changes ADD COLUMN IF NOT EXISTS text_old text;
|
|
21
|
-
ALTER TABLE log.table_changes ADD COLUMN IF NOT EXISTS text_new text;
|
|
22
|
-
|
|
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
|
|
23
11
|
ALTER TABLE log.table_changes ADD COLUMN IF NOT EXISTS uid text;
|
|
24
12
|
ALTER TABLE log.table_changes ADD COLUMN IF NOT EXISTS cdate timestamp without time zone DEFAULT (now())::timestamp without time zone;
|
|
25
13
|
ALTER TABLE log.table_changes ADD COLUMN IF NOT EXISTS editor_id text;
|
|
26
14
|
ALTER TABLE log.table_changes ADD COLUMN IF NOT EXISTS editor_date timestamp without time zone;
|
|
27
|
-
ALTER TABLE log.table_changes ADD CONSTRAINT log_table_changes_pkey PRIMARY KEY (table_change_id);
|
|
28
15
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
ALTER TABLE log.
|
|
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;
|
|
32
27
|
|
|
28
|
+
-- DROP TABLE IF EXISTS log.user_auth;
|
|
29
|
+
CREATE TABLE IF NOT EXISTS log.user_auth();
|
|
33
30
|
ALTER TABLE log.user_auth ADD COLUMN IF NOT EXISTS user_auth_id text NOT NULL DEFAULT next_id();
|
|
34
|
-
|
|
35
31
|
ALTER TABLE log.user_auth ADD COLUMN IF NOT EXISTS user_id text;
|
|
36
|
-
ALTER TABLE log.user_auth ADD COLUMN IF NOT EXISTS
|
|
37
|
-
ALTER TABLE log.user_auth ADD COLUMN IF NOT EXISTS
|
|
38
|
-
|
|
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;
|
|
39
34
|
ALTER TABLE log.user_auth ADD COLUMN IF NOT EXISTS uid text;
|
|
40
35
|
ALTER TABLE log.user_auth ADD COLUMN IF NOT EXISTS cdate timestamp without time zone DEFAULT (now())::timestamp without time zone;
|
|
41
36
|
ALTER TABLE log.user_auth ADD COLUMN IF NOT EXISTS editor_id text;
|
|
42
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);
|
|
43
67
|
ALTER TABLE log.user_auth ADD CONSTRAINT log_user_auth_pkey PRIMARY KEY (user_auth_id);
|
|
44
|
-
-- ALTER TABLE log.user_auth ADD CONSTRAINT log_user_auth_user_id_fkey FOREIGN KEY (user_id) REFERENCES admin.users (uid) MATCH SIMPLE;
|
|
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
|
+
alter table log.table_changes drop column if exists table_change_id;
|