@opengis/fastify-table 1.0.18 → 1.0.19
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 +52 -52
- package/notification/controllers/userNotifications.js +1 -1
- package/package.json +22 -22
- package/pg/funcs/autoIndex.js +89 -89
- package/pg/funcs/getMeta.js +27 -27
- package/pg/funcs/getPG.js +29 -29
- package/pg/funcs/init.js +42 -42
- package/pg/funcs/pgClients.js +2 -2
- package/pg/pgClients.js +20 -20
- package/policy/funcs/checkPolicy.js +74 -74
- package/policy/funcs/sqlInjection.js +33 -33
- package/policy/index.js +14 -14
- package/redis/client.js +8 -8
- package/redis/funcs/getRedis.js +23 -23
- package/redis/funcs/redisClients.js +2 -2
- package/redis/index.js +19 -19
- package/server/migrations/notifications.sql +14 -0
- package/server/templates/form/test.dataset.form.json +411 -411
- package/server/templates/select/test.storage.data.json +3 -0
- package/server/templates/select/test.storage.data.sql +1 -0
- package/server/templates/table/test.dataset.table.json +25 -0
- package/table/controllers/data.js +57 -57
- package/table/controllers/filter.js +32 -32
- package/table/controllers/form.js +10 -10
- package/table/controllers/search.js +41 -0
- package/table/controllers/suggest.js +60 -60
- package/table/controllers/utils/getSelect.js +20 -20
- package/table/controllers/utils/getSelectMeta.js +66 -66
- 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 +26 -26
- package/table/index.js +38 -25
- package/test/api/notification.test.js +0 -19
- package/test/api/table.test.js +57 -49
- package/test/api/widget.test.js +39 -0
- package/test/funcs/notification.test.js +31 -0
- package/widget/controllers/widget.del.js +3 -2
- package/widget/controllers/widget.set.js +1 -1
- package/widget/index.js +8 -17
|
@@ -1,74 +1,74 @@
|
|
|
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
|
-
/*= == 1.File injection === */
|
|
26
|
-
if (JSON.stringify(params || {})?.includes('../') || JSON.stringify(query || {})?.includes('../') || path?.includes('../')) {
|
|
27
|
-
log.warn({
|
|
28
|
-
name: 'injection/file', params, query, message: 'access restricted: 1',
|
|
29
|
-
});
|
|
30
|
-
return { message: 'access restricted: 1', status: 403 };
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
/*= == 1.1 File === */
|
|
34
|
-
const allowExtPublic = ['.png', '.jpg', '.svg'];
|
|
35
|
-
const ext = path.toLowerCase().substr(-4);
|
|
36
|
-
if (path.includes('files/') && allowExtPublic.includes(ext)) return null;
|
|
37
|
-
|
|
38
|
-
/*= == 2.SQL Injection policy: no-sql === */
|
|
39
|
-
if (!policy.includes('no-sql')) {
|
|
40
|
-
const stopWords = block.filter((el) => path.includes(el));
|
|
41
|
-
if (stopWords?.length) {
|
|
42
|
-
log.warn({ name: 'injection/sql', stopWords, message: 'access restricted: 2' });
|
|
43
|
-
return { message: 'access restricted: 2', status: 403 };
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
/* Check is Not API */
|
|
47
|
-
const isApi = ['/files/', '/api/format/', '/api-user/', '/logger', '/file/'].filter((el) => path.includes(el)).length;
|
|
48
|
-
if (!isApi) return null;
|
|
49
|
-
|
|
50
|
-
/*= == 3. policy: referer === */
|
|
51
|
-
if (!hs?.referer?.includes?.(hostname) && policy.includes('referer') && !config.local && !config.debug) {
|
|
52
|
-
log.warn({ name: 'referer', message: 'access restricted: 3' });
|
|
53
|
-
return { message: 'access restricted: 3', status: 403 };
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
/*= == policy: public === */
|
|
57
|
-
if (policy.includes('public')) {
|
|
58
|
-
return null;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
/*= == 4. policy: site auth === */
|
|
62
|
-
if (!policy.includes('site') && sid === 1 && isUser && !config.local && !config.debug) {
|
|
63
|
-
log.warn({ name: 'site', message: 'access restricted: 4' });
|
|
64
|
-
return { message: 'access restricted: 4', status: 403 };
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
/*= == 5. base policy: block api === */
|
|
68
|
-
if (sid === 35 && !isUser && isServer && !config.local && !config.debug) {
|
|
69
|
-
log.warn({ name: 'api', message: 'access restricted: 5' });
|
|
70
|
-
return { message: 'access restricted: 5', status: 403 };
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
return null;
|
|
74
|
-
}
|
|
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
|
+
/*= == 1.File injection === */
|
|
26
|
+
if (JSON.stringify(params || {})?.includes('../') || JSON.stringify(query || {})?.includes('../') || path?.includes('../')) {
|
|
27
|
+
log.warn({
|
|
28
|
+
name: 'injection/file', params, query, message: 'access restricted: 1',
|
|
29
|
+
});
|
|
30
|
+
return { message: 'access restricted: 1', status: 403 };
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/*= == 1.1 File === */
|
|
34
|
+
const allowExtPublic = ['.png', '.jpg', '.svg'];
|
|
35
|
+
const ext = path.toLowerCase().substr(-4);
|
|
36
|
+
if (path.includes('files/') && allowExtPublic.includes(ext)) return null;
|
|
37
|
+
|
|
38
|
+
/*= == 2.SQL Injection policy: no-sql === */
|
|
39
|
+
if (!policy.includes('no-sql')) {
|
|
40
|
+
const stopWords = block.filter((el) => path.includes(el));
|
|
41
|
+
if (stopWords?.length) {
|
|
42
|
+
log.warn({ name: 'injection/sql', stopWords, message: 'access restricted: 2' });
|
|
43
|
+
return { message: 'access restricted: 2', status: 403 };
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
/* Check is Not API */
|
|
47
|
+
const isApi = ['/files/', '/api/format/', '/api-user/', '/logger', '/file/'].filter((el) => path.includes(el)).length;
|
|
48
|
+
if (!isApi) return null;
|
|
49
|
+
|
|
50
|
+
/*= == 3. policy: referer === */
|
|
51
|
+
if (!hs?.referer?.includes?.(hostname) && policy.includes('referer') && !config.local && !config.debug) {
|
|
52
|
+
log.warn({ name: 'referer', message: 'access restricted: 3' });
|
|
53
|
+
return { message: 'access restricted: 3', status: 403 };
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/*= == policy: public === */
|
|
57
|
+
if (policy.includes('public')) {
|
|
58
|
+
return null;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/*= == 4. policy: site auth === */
|
|
62
|
+
if (!policy.includes('site') && sid === 1 && isUser && !config.local && !config.debug) {
|
|
63
|
+
log.warn({ name: 'site', message: 'access restricted: 4' });
|
|
64
|
+
return { message: 'access restricted: 4', status: 403 };
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/*= == 5. base policy: block api === */
|
|
68
|
+
if (sid === 35 && !isUser && isServer && !config.local && !config.debug) {
|
|
69
|
+
log.warn({ name: 'api', message: 'access restricted: 5' });
|
|
70
|
+
return { message: 'access restricted: 5', status: 403 };
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
return null;
|
|
74
|
+
}
|
|
@@ -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];
|
package/redis/funcs/getRedis.js
CHANGED
|
@@ -1,23 +1,23 @@
|
|
|
1
|
-
import Redis from 'ioredis';
|
|
2
|
-
import config from '../../config.js';
|
|
3
|
-
import redisClients from './redisClients.js';
|
|
4
|
-
|
|
5
|
-
function getRedis({ db }) {
|
|
6
|
-
if (!config.redis) return null;
|
|
7
|
-
if (redisClients[db]) return redisClients[db];
|
|
8
|
-
|
|
9
|
-
const redisConfig = {
|
|
10
|
-
db,
|
|
11
|
-
keyPrefix: `${config.db}:`,
|
|
12
|
-
host: config.redis?.host || '127.0.0.1',
|
|
13
|
-
port: config.redis?.port || 6379, // Redis port
|
|
14
|
-
family: 4, // 4 (IPv4) or 6 (IPv6)
|
|
15
|
-
closeClient: true,
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
redisClients[db] = new Redis(redisConfig);
|
|
19
|
-
|
|
20
|
-
return redisClients[db];
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export default getRedis;
|
|
1
|
+
import Redis from 'ioredis';
|
|
2
|
+
import config from '../../config.js';
|
|
3
|
+
import redisClients from './redisClients.js';
|
|
4
|
+
|
|
5
|
+
function getRedis({ db }) {
|
|
6
|
+
if (!config.redis) return null;
|
|
7
|
+
if (redisClients[db]) return redisClients[db];
|
|
8
|
+
|
|
9
|
+
const redisConfig = {
|
|
10
|
+
db,
|
|
11
|
+
keyPrefix: `${config.db}:`,
|
|
12
|
+
host: config.redis?.host || '127.0.0.1',
|
|
13
|
+
port: config.redis?.port || 6379, // Redis port
|
|
14
|
+
family: 4, // 4 (IPv4) or 6 (IPv6)
|
|
15
|
+
closeClient: true,
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
redisClients[db] = new Redis(redisConfig);
|
|
19
|
+
|
|
20
|
+
return redisClients[db];
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export default getRedis;
|
|
@@ -1,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;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
CREATE TABLE IF NOT EXISTS crm.notification();
|
|
2
|
+
ALTER TABLE crm.notification DROP CONSTRAINT IF EXISTS notification_key;
|
|
3
|
+
ALTER TABLE crm.notification ADD COLUMN IF NOT EXISTS notification_id text NOT NULL DEFAULT admin.next_id();
|
|
4
|
+
ALTER TABLE crm.notification ADD COLUMN IF NOT EXISTS notification_user_id text;
|
|
5
|
+
ALTER TABLE crm.notification ADD COLUMN IF NOT EXISTS notification_type text DEFAULT 'notify'::text;
|
|
6
|
+
ALTER TABLE crm.notification ADD COLUMN IF NOT EXISTS notification_status text DEFAULT 'not sent'::text;
|
|
7
|
+
ALTER TABLE crm.notification ADD COLUMN IF NOT EXISTS title text;
|
|
8
|
+
ALTER TABLE crm.notification ADD COLUMN IF NOT EXISTS body text;
|
|
9
|
+
ALTER TABLE crm.notification ADD COLUMN IF NOT EXISTS link text;
|
|
10
|
+
ALTER TABLE crm.notification ADD COLUMN IF NOT EXISTS uid text;
|
|
11
|
+
ALTER TABLE crm.notification ADD COLUMN IF NOT EXISTS cdate timestamp without time zone DEFAULT (now())::timestamp without time zone;
|
|
12
|
+
ALTER TABLE crm.notification ADD COLUMN IF NOT EXISTS editor_id text;
|
|
13
|
+
ALTER TABLE crm.notification ADD COLUMN IF NOT EXISTS editor_date timestamp without time zone;
|
|
14
|
+
ALTER TABLE crm.notification ADD CONSTRAINT notification_key PRIMARY KEY (notification_id);
|