@opengis/fastify-table 1.0.36 → 1.0.37

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.
Files changed (46) hide show
  1. package/Changelog.md +4 -0
  2. package/crud/controllers/insert.js +29 -29
  3. package/crud/controllers/update.js +31 -31
  4. package/crud/funcs/getOpt.js +10 -10
  5. package/crud/funcs/setOpt.js +16 -16
  6. package/crud/index.js +29 -29
  7. package/helper.js +28 -28
  8. package/notification/controllers/userNotifications.js +19 -19
  9. package/notification/funcs/addNotification.js +8 -8
  10. package/notification/index.js +19 -19
  11. package/package.json +1 -1
  12. package/pg/pgClients.js +20 -20
  13. package/policy/funcs/checkPolicy.js +74 -74
  14. package/policy/funcs/sqlInjection.js +33 -33
  15. package/policy/index.js +14 -14
  16. package/redis/client.js +8 -8
  17. package/redis/funcs/redisClients.js +2 -2
  18. package/redis/index.js +19 -19
  19. package/server/templates/form/test.dataset.form.json +411 -411
  20. package/server/templates/select/test.storage.data.json +2 -2
  21. package/server/templates/table/test.dataset.table.json +24 -24
  22. package/table/controllers/data.js +57 -57
  23. package/table/controllers/form.js +10 -10
  24. package/table/controllers/suggest.js +60 -60
  25. package/table/controllers/utils/getSelect.js +20 -20
  26. package/table/controllers/utils/getSelectMeta.js +66 -66
  27. package/table/controllers/utils/getTemplate.js +28 -28
  28. package/table/funcs/getFilterSQL/index.js +75 -75
  29. package/table/funcs/getFilterSQL/util/formatValue.js +142 -142
  30. package/table/funcs/getFilterSQL/util/getCustomQuery.js +13 -13
  31. package/table/funcs/getFilterSQL/util/getFilterQuery.js +73 -73
  32. package/table/funcs/getFilterSQL/util/getOptimizedQuery.js +12 -12
  33. package/table/funcs/metaFormat/getSelectVal.js +20 -20
  34. package/table/funcs/metaFormat/index.js +26 -26
  35. package/table/index.js +42 -42
  36. package/test/api/crud.test.js +56 -56
  37. package/test/api/crud.xss.test.js +71 -71
  38. package/test/api/notification.test.js +37 -37
  39. package/test/api/table.test.js +57 -57
  40. package/test/funcs/notification.test.js +31 -31
  41. package/widget/controllers/utils/historyFormat.js +76 -76
  42. package/widget/controllers/utils/obj2db.js +13 -13
  43. package/widget/controllers/widget.del.js +44 -41
  44. package/widget/controllers/widget.get.js +86 -77
  45. package/widget/controllers/widget.set.js +70 -64
  46. package/widget/index.js +29 -29
package/Changelog.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # fastify-table
2
2
 
3
+ ## 1.0.37 - 23.05.2024
4
+
5
+ - add gallery widget
6
+
3
7
  ## 1.0.36 - 22.05.2024
4
8
 
5
9
  - fix filter api array processing
@@ -1,29 +1,29 @@
1
- import dataInsert from '../funcs/dataInsert.js';
2
- import getToken from '../funcs/getToken.js';
3
- import checkXSS from './utils/checkXSS.js';
4
- import getTemplate from '../../table/controllers/utils/getTemplate.js';
5
-
6
- export default async function insert(req) {
7
- const loadTemplate = await getTemplate('table', req.params.table);
8
- const { table } = loadTemplate || req.params || {};
9
- if (!table) return { status: 404, message: 'table is required' };
10
-
11
- const { funcs, session, params } = req;
12
- const tokenDataString = await getToken({
13
- funcs, session, token: params.table, mode: 'a', json: 0,
14
- });
15
-
16
- const { form, add } = JSON.parse(tokenDataString || '{}');
17
-
18
- const formData = form ? await getTemplate('form', form) : {};
19
-
20
- const xssCheck = checkXSS({ body: req.body, schema: formData?.schema });
21
-
22
- if (xssCheck.error && formData?.xssCheck !== false) {
23
- req.log.warn({ name: 'injection/xss', msg: xssCheck.error, table }, req);
24
- return { message: 'Дані містять заборонені символи. Приберіть їх та спробуйте ще раз', status: 409 };
25
- }
26
-
27
- const res = await dataInsert({ table: add || table, data: req.body });
28
- return { rows: res.rows };
29
- }
1
+ import dataInsert from '../funcs/dataInsert.js';
2
+ import getToken from '../funcs/getToken.js';
3
+ import checkXSS from './utils/checkXSS.js';
4
+ import getTemplate from '../../table/controllers/utils/getTemplate.js';
5
+
6
+ export default async function insert(req) {
7
+ const loadTemplate = await getTemplate('table', req.params.table);
8
+ const { table } = loadTemplate || req.params || {};
9
+ if (!table) return { status: 404, message: 'table is required' };
10
+
11
+ const { funcs, session, params } = req;
12
+ const tokenDataString = await getToken({
13
+ funcs, session, token: params.table, mode: 'a', json: 0,
14
+ });
15
+
16
+ const { form, add } = JSON.parse(tokenDataString || '{}');
17
+
18
+ const formData = form ? await getTemplate('form', form) : {};
19
+
20
+ const xssCheck = checkXSS({ body: req.body, schema: formData?.schema });
21
+
22
+ if (xssCheck.error && formData?.xssCheck !== false) {
23
+ req.log.warn({ name: 'injection/xss', msg: xssCheck.error, table }, req);
24
+ return { message: 'Дані містять заборонені символи. Приберіть їх та спробуйте ще раз', status: 409 };
25
+ }
26
+
27
+ const res = await dataInsert({ table: add || table, data: req.body });
28
+ return { rows: res.rows };
29
+ }
@@ -1,31 +1,31 @@
1
- import dataUpdate from '../funcs/dataUpdate.js';
2
- import getToken from '../funcs/getToken.js';
3
- import checkXSS from './utils/checkXSS.js';
4
- import getTemplate from '../../table/controllers/utils/getTemplate.js';
5
-
6
- export default async function update(req) {
7
- const loadTemplate = await getTemplate('table', req.params.table);
8
- const { table } = loadTemplate || req.params || {};
9
- const { id } = req.params || {};
10
- if (!req.params?.table) return { message: 'table is required', status: 404 };
11
- if (!id) return { message: 'id is required', status: 404 };
12
-
13
- const { funcs, session, params } = req;
14
- const tokenDataString = await getToken({
15
- funcs, session, token: params.table, mode: 'w', json: 0,
16
- });
17
-
18
- const tokenData = JSON.parse(tokenDataString || '{}');
19
-
20
- const formData = tokenData?.form ? await getTemplate('form', tokenData.form) : {};
21
-
22
- const xssCheck = checkXSS({ body: req.body, schema: formData?.schema });
23
-
24
- if (xssCheck.error && formData?.xssCheck !== false) {
25
- req.log.warn({ name: 'injection/xss', msg: xssCheck.error, table }, req);
26
- return { message: 'Дані містять заборонені символи. Приберіть їх та спробуйте ще раз', status: 409 };
27
- }
28
-
29
- const res = await dataUpdate({ table: tokenData?.table || table, id: tokenData?.id || id, data: req.body });
30
- return res;
31
- }
1
+ import dataUpdate from '../funcs/dataUpdate.js';
2
+ import getToken from '../funcs/getToken.js';
3
+ import checkXSS from './utils/checkXSS.js';
4
+ import getTemplate from '../../table/controllers/utils/getTemplate.js';
5
+
6
+ export default async function update(req) {
7
+ const loadTemplate = await getTemplate('table', req.params.table);
8
+ const { table } = loadTemplate || req.params || {};
9
+ const { id } = req.params || {};
10
+ if (!req.params?.table) return { message: 'table is required', status: 404 };
11
+ if (!id) return { message: 'id is required', status: 404 };
12
+
13
+ const { funcs, session, params } = req;
14
+ const tokenDataString = await getToken({
15
+ funcs, session, token: params.table, mode: 'w', json: 0,
16
+ });
17
+
18
+ const tokenData = JSON.parse(tokenDataString || '{}');
19
+
20
+ const formData = tokenData?.form ? await getTemplate('form', tokenData.form) : {};
21
+
22
+ const xssCheck = checkXSS({ body: req.body, schema: formData?.schema });
23
+
24
+ if (xssCheck.error && formData?.xssCheck !== false) {
25
+ req.log.warn({ name: 'injection/xss', msg: xssCheck.error, table }, req);
26
+ return { message: 'Дані містять заборонені символи. Приберіть їх та спробуйте ще раз', status: 409 };
27
+ }
28
+
29
+ const res = await dataUpdate({ table: tokenData?.table || table, id: tokenData?.id || id, data: req.body });
30
+ return res;
31
+ }
@@ -1,10 +1,10 @@
1
- import getRedis from '../../redis/funcs/getRedis.js';
2
-
3
- export default async function getOpt(token, funcs) {
4
- const rclient = getRedis({ db: 0, funcs });
5
-
6
- const key = `opt:${token}`;
7
- const data = await rclient.get(key);
8
- if (!data) return null;
9
- return JSON.parse(data);
10
- }
1
+ import getRedis from '../../redis/funcs/getRedis.js';
2
+
3
+ export default async function getOpt(token, funcs) {
4
+ const rclient = getRedis({ db: 0, funcs });
5
+
6
+ const key = `opt:${token}`;
7
+ const data = await rclient.get(key);
8
+ if (!data) return null;
9
+ return JSON.parse(data);
10
+ }
@@ -1,16 +1,16 @@
1
- import { createHash } from 'crypto';
2
- import getRedis from '../../redis/funcs/getRedis.js';
3
-
4
- function md5(string) {
5
- return createHash('md5').update(string).digest('hex');
6
- }
7
-
8
- export default async function setOpt(params) {
9
- const token = Buffer.from(md5(typeof params === 'object' ? JSON.stringify(params) : params), 'hex').toString('base64').replace(/[+-=]+/g, '');
10
- // const token = md5(params);
11
- const key = `opt:${token}`;
12
-
13
- const rclient = getRedis({ db: 0, funcs: params.funcs });
14
- await rclient.set(key, JSON.stringify(params), 'EX', 60 * 60);
15
- return token;
16
- }
1
+ import { createHash } from 'crypto';
2
+ import getRedis from '../../redis/funcs/getRedis.js';
3
+
4
+ function md5(string) {
5
+ return createHash('md5').update(string).digest('hex');
6
+ }
7
+
8
+ export default async function setOpt(params) {
9
+ const token = Buffer.from(md5(typeof params === 'object' ? JSON.stringify(params) : params), 'hex').toString('base64').replace(/[+-=]+/g, '');
10
+ // const token = md5(params);
11
+ const key = `opt:${token}`;
12
+
13
+ const rclient = getRedis({ db: 0, funcs: params.funcs });
14
+ await rclient.set(key, JSON.stringify(params), 'EX', 60 * 60);
15
+ return token;
16
+ }
package/crud/index.js CHANGED
@@ -1,29 +1,29 @@
1
- import getOPt from './funcs/getOpt.js';
2
- import setOpt from './funcs/setOpt.js';
3
- import isFileExists from './funcs/isFileExists.js';
4
- import dataUpdate from './funcs/dataUpdate.js';
5
- import dataInsert from './funcs/dataInsert.js';
6
-
7
- import update from './controllers/update.js';
8
- import insert from './controllers/insert.js';
9
- import deleteCrud from './controllers/deleteCrud.js';
10
-
11
- // import config from '../config.js';
12
-
13
- async function plugin(fastify, config = {}) {
14
- const prefix = config.prefix || '/api';
15
- // funcs
16
- fastify.decorate('setOpt', setOpt);
17
- fastify.decorate('getOpt', getOPt);
18
- fastify.decorate('dataUpdate', dataUpdate);
19
- fastify.decorate('dataInsert', dataInsert);
20
-
21
- fastify.decorate('isFileExists', isFileExists);
22
-
23
- // api
24
- fastify.put(`${prefix}/table/:table/:id`, {}, update);
25
- fastify.delete(`${prefix}/table/:table/:id`, {}, deleteCrud);
26
- fastify.post(`${prefix}/table/:table`, {}, insert);
27
- }
28
-
29
- export default plugin;
1
+ import getOPt from './funcs/getOpt.js';
2
+ import setOpt from './funcs/setOpt.js';
3
+ import isFileExists from './funcs/isFileExists.js';
4
+ import dataUpdate from './funcs/dataUpdate.js';
5
+ import dataInsert from './funcs/dataInsert.js';
6
+
7
+ import update from './controllers/update.js';
8
+ import insert from './controllers/insert.js';
9
+ import deleteCrud from './controllers/deleteCrud.js';
10
+
11
+ // import config from '../config.js';
12
+
13
+ async function plugin(fastify, config = {}) {
14
+ const prefix = config.prefix || '/api';
15
+ // funcs
16
+ fastify.decorate('setOpt', setOpt);
17
+ fastify.decorate('getOpt', getOPt);
18
+ fastify.decorate('dataUpdate', dataUpdate);
19
+ fastify.decorate('dataInsert', dataInsert);
20
+
21
+ fastify.decorate('isFileExists', isFileExists);
22
+
23
+ // api
24
+ fastify.put(`${prefix}/table/:table/:id`, {}, update);
25
+ fastify.delete(`${prefix}/table/:table/:id`, {}, deleteCrud);
26
+ fastify.post(`${prefix}/table/:table`, {}, insert);
27
+ }
28
+
29
+ export default plugin;
package/helper.js CHANGED
@@ -1,28 +1,28 @@
1
- // This file contains code that we reuse
2
- // between our tests.
3
- import Fastify from 'fastify';
4
- import config from './test/config.js';
5
- import appService from './index.js';
6
-
7
- import rclient from './redis/client.js';
8
- import pgClients from './pg/pgClients.js';
9
-
10
- // automatically build and tear down our instance
11
- async function build(t) {
12
- // you can set all the options supported by the fastify CLI command
13
- // const argv = [AppPath]
14
- process.env.NODE_ENV = 'production';
15
- const app = Fastify({ logger: false });
16
- app.register(appService, config);
17
- // close the app after we are done
18
- t.after(() => {
19
- // console.log('close app');
20
- pgClients.client.end();
21
- rclient.quit();
22
- app.close();
23
- });
24
-
25
- return app;
26
- }
27
-
28
- export default build;
1
+ // This file contains code that we reuse
2
+ // between our tests.
3
+ import Fastify from 'fastify';
4
+ import config from './test/config.js';
5
+ import appService from './index.js';
6
+
7
+ import rclient from './redis/client.js';
8
+ import pgClients from './pg/pgClients.js';
9
+
10
+ // automatically build and tear down our instance
11
+ async function build(t) {
12
+ // you can set all the options supported by the fastify CLI command
13
+ // const argv = [AppPath]
14
+ process.env.NODE_ENV = 'production';
15
+ const app = Fastify({ logger: false });
16
+ app.register(appService, config);
17
+ // close the app after we are done
18
+ t.after(() => {
19
+ // console.log('close app');
20
+ pgClients.client.end();
21
+ rclient.quit();
22
+ app.close();
23
+ });
24
+
25
+ return app;
26
+ }
27
+
28
+ export default build;
@@ -1,19 +1,19 @@
1
- export default async function userNotifications({
2
- pg, session = {}, query = {},
3
- }) {
4
- const time = Date.now();
5
- try {
6
- const { uid } = session.passport?.user || {};
7
- if (!uid) return { error: 'access restricted', status: 403 };
8
-
9
- const queryFunc = query.nocache ? pg.query : pg.queryCache;
10
-
11
- // queryCache not supports $1 params
12
- const { rows } = await queryFunc(`select notification_id as id, notification_type as type,
13
- notification_status as status, title, body, link, uid from crm.notification where uid='${uid}'`);
14
- return { time: Date.now() - time, total: rows?.length, rows };
15
- }
16
- catch (err) {
17
- return { error: err.toString(), status: 500 };
18
- }
19
- }
1
+ export default async function userNotifications({
2
+ pg, session = {}, query = {},
3
+ }) {
4
+ const time = Date.now();
5
+ try {
6
+ const { uid } = session.passport?.user || {};
7
+ if (!uid) return { error: 'access restricted', status: 403 };
8
+
9
+ const queryFunc = query.nocache ? pg.query : pg.queryCache;
10
+
11
+ // queryCache not supports $1 params
12
+ const { rows } = await queryFunc(`select notification_id as id, notification_type as type,
13
+ notification_status as status, title, body, link, uid from crm.notification where uid='${uid}'`);
14
+ return { time: Date.now() - time, total: rows?.length, rows };
15
+ }
16
+ catch (err) {
17
+ return { error: err.toString(), status: 500 };
18
+ }
19
+ }
@@ -1,8 +1,8 @@
1
- export default async function addNotification({
2
- pg, session = {}, title, body, link, notificationType, uid: uid1,
3
- }) {
4
- const uid = uid1 || session.passport?.user?.uid || {};
5
- const { id, status } = await pg.one(`insert into crm.notification(title, body, link, notification_type, uid)
6
- values($1,$2,$3,$4,$5) returning notification_id as id, notification_status as status`, [title, body, link, notificationType, uid]);
7
- return { id, status };
8
- }
1
+ export default async function addNotification({
2
+ pg, session = {}, title, body, link, notificationType, uid: uid1,
3
+ }) {
4
+ const uid = uid1 || session.passport?.user?.uid || {};
5
+ const { id, status } = await pg.one(`insert into crm.notification(title, body, link, notification_type, uid)
6
+ values($1,$2,$3,$4,$5) returning notification_id as id, notification_status as status`, [title, body, link, notificationType, uid]);
7
+ return { id, status };
8
+ }
@@ -1,19 +1,19 @@
1
- // api
2
- import userNotifications from './controllers/userNotifications.js';
3
- // funcs
4
- import addNotification from './funcs/addNotification.js';
5
-
6
- async function plugin(fastify, config = {}) {
7
- const prefix = config.prefix || '/api';
8
- fastify.route({
9
- method: 'GET',
10
- url: `${prefix}/notification`,
11
- config: {
12
- policy: ['user'], // implement user auth check policy??
13
- },
14
- handler: userNotifications,
15
- });
16
- fastify.decorate('addNotification', addNotification);
17
- }
18
-
19
- export default plugin;
1
+ // api
2
+ import userNotifications from './controllers/userNotifications.js';
3
+ // funcs
4
+ import addNotification from './funcs/addNotification.js';
5
+
6
+ async function plugin(fastify, config = {}) {
7
+ const prefix = config.prefix || '/api';
8
+ fastify.route({
9
+ method: 'GET',
10
+ url: `${prefix}/notification`,
11
+ config: {
12
+ policy: ['user'], // implement user auth check policy??
13
+ },
14
+ handler: userNotifications,
15
+ });
16
+ fastify.decorate('addNotification', addNotification);
17
+ }
18
+
19
+ export default plugin;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opengis/fastify-table",
3
- "version": "1.0.36",
3
+ "version": "1.0.37",
4
4
  "type": "module",
5
5
  "description": "core-plugins",
6
6
  "main": "index.js",
package/pg/pgClients.js CHANGED
@@ -1,20 +1,20 @@
1
- import pg from 'pg';
2
- import config from '../config.js';
3
- import init from './funcs/init.js';
4
-
5
- const pgClients = {};
6
- if (config.pg) {
7
- const client = new pg.Pool({
8
- host: config.pg?.host || '127.0.0.1',
9
- port: config.pg?.port || 5432,
10
- database: config.pg?.database || 'postgres',
11
- user: config.pg?.user || 'postgres',
12
- password: config.pg?.password || 'postgres',
13
- });
14
- client.init = async () => {
15
- await init(client);
16
- };
17
- client.init();
18
- pgClients.client = client;
19
- }
20
- export default pgClients;
1
+ import pg from 'pg';
2
+ import config from '../config.js';
3
+ import init from './funcs/init.js';
4
+
5
+ const pgClients = {};
6
+ if (config.pg) {
7
+ const client = new pg.Pool({
8
+ host: config.pg?.host || '127.0.0.1',
9
+ port: config.pg?.port || 5432,
10
+ database: config.pg?.database || 'postgres',
11
+ user: config.pg?.user || 'postgres',
12
+ password: config.pg?.password || 'postgres',
13
+ });
14
+ client.init = async () => {
15
+ await init(client);
16
+ };
17
+ client.init();
18
+ pgClients.client = client;
19
+ }
20
+ export default pgClients;
@@ -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
+ }