@opengis/fastify-table 1.0.74 → 1.0.76

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 (64) hide show
  1. package/.eslintrc.cjs +42 -42
  2. package/Changelog.md +237 -229
  3. package/README.md +26 -26
  4. package/config.js +10 -10
  5. package/cron/controllers/cronApi.js +22 -22
  6. package/cron/controllers/utils/cronList.js +1 -1
  7. package/cron/funcs/addCron.js +131 -131
  8. package/cron/index.js +10 -10
  9. package/crud/controllers/deleteCrud.js +1 -1
  10. package/crud/controllers/utils/checkXSS.js +45 -45
  11. package/crud/controllers/utils/xssInjection.js +72 -72
  12. package/crud/funcs/dataDelete.js +15 -15
  13. package/crud/funcs/dataUpdate.js +24 -24
  14. package/crud/funcs/getAccess.js +2 -1
  15. package/crud/funcs/getToken.js +27 -27
  16. package/crud/funcs/isFileExists.js +13 -13
  17. package/crud/funcs/setToken.js +53 -53
  18. package/crud/index.js +36 -36
  19. package/index.js +97 -97
  20. package/migration/exec.migrations.js +75 -75
  21. package/notification/controllers/testEmail.js +49 -49
  22. package/notification/funcs/sendNotification.js +111 -111
  23. package/notification/funcs/utils/sendEmail.js +39 -39
  24. package/notification/index.js +38 -38
  25. package/package.json +26 -26
  26. package/pg/funcs/getPG.js +30 -30
  27. package/redis/funcs/getRedis.js +23 -23
  28. package/server/migrations/0.sql +64 -13
  29. package/server/migrations/crm.sql +150 -150
  30. package/server/migrations/log.sql +43 -43
  31. package/server.js +14 -14
  32. package/table/controllers/card.js +44 -44
  33. package/table/controllers/filter.js +37 -37
  34. package/table/controllers/form.js +28 -28
  35. package/table/controllers/search.js +72 -72
  36. package/table/controllers/suggest.js +62 -62
  37. package/table/controllers/table.js +44 -44
  38. package/table/controllers/utils/getSelectMeta.js +66 -66
  39. package/table/controllers/utils/getTemplate.js +28 -28
  40. package/table/controllers/utils/getTemplates.js +18 -18
  41. package/table/funcs/getFilterSQL/util/getTableSql.js +34 -34
  42. package/table/funcs/metaFormat/index.js +27 -27
  43. package/table/index.js +78 -78
  44. package/test/api/crud.test.js +18 -11
  45. package/test/api/crud.xss.test.js +72 -72
  46. package/test/api/notification.test.js +37 -37
  47. package/test/api/table.test.js +57 -57
  48. package/test/api/widget.test.js +114 -114
  49. package/test/config.example +18 -18
  50. package/test/funcs/crud.test.js +76 -76
  51. package/test/funcs/notification.test.js +31 -31
  52. package/test/funcs/pg.test.js +34 -34
  53. package/test/funcs/redis.test.js +19 -19
  54. package/test/templates/cls/test.json +9 -9
  55. package/test/templates/form/cp_building.form.json +32 -32
  56. package/test/templates/select/account_id.json +3 -3
  57. package/test/templates/select/storage.data.json +2 -2
  58. package/test/templates/table/gis.dataset.table.json +20 -20
  59. package/util/controllers/next.id.js +4 -4
  60. package/util/controllers/properties.add.js +50 -50
  61. package/util/controllers/properties.get.js +19 -19
  62. package/util/controllers/status.monitor.js +3 -0
  63. package/util/index.js +4 -3
  64. package/widget/index.js +40 -40
@@ -1,28 +1,28 @@
1
- import { readFile } from 'fs/promises';
2
- import fs from 'fs';
3
- import path from 'path';
4
- import config from '../../../config.js';
5
-
6
- const loadTemplate = {};
7
-
8
- export default async function getTemplateDir(type, name) {
9
- if (!type) return null;
10
- if (!name) return null;
11
-
12
- const cwd = process.cwd();
13
- const typeDir = path.join(cwd, (config.templateDir || 'server/templates'), type);
14
-
15
- if (!loadTemplate[type]) {
16
- const typeList = fs.existsSync(typeDir) ? fs.readdirSync(typeDir) : [];
17
- loadTemplate[type] = typeList;
18
- }
19
-
20
- const fullname = loadTemplate[type].find((el) => path.parse(el).name === name);
21
- const ext = fullname ? path.extname(fullname)?.slice(1) : null;
22
- if (!ext) return null;
23
-
24
- const sql = loadTemplate[type].includes(`${name}.sql`) ? await readFile(path.join(typeDir, `${name}.sql`), 'utf-8') : null;
25
- const data = loadTemplate[type].includes(`${name}.json`) ? JSON.parse(await readFile(path.join(typeDir, `${name}.json`), 'utf-8')) : await readFile(path.join(typeDir, `${name}.${ext}`), 'utf-8');
26
- if (sql) return { ...data || {}, sql };
27
- return data;
28
- }
1
+ import { readFile } from 'fs/promises';
2
+ import fs from 'fs';
3
+ import path from 'path';
4
+ import config from '../../../config.js';
5
+
6
+ const loadTemplate = {};
7
+
8
+ export default async function getTemplateDir(type, name) {
9
+ if (!type) return null;
10
+ if (!name) return null;
11
+
12
+ const cwd = process.cwd();
13
+ const typeDir = path.join(cwd, (config.templateDir || 'server/templates'), type);
14
+
15
+ if (!loadTemplate[type]) {
16
+ const typeList = fs.existsSync(typeDir) ? fs.readdirSync(typeDir) : [];
17
+ loadTemplate[type] = typeList;
18
+ }
19
+
20
+ const fullname = loadTemplate[type].find((el) => path.parse(el).name === name);
21
+ const ext = fullname ? path.extname(fullname)?.slice(1) : null;
22
+ if (!ext) return null;
23
+
24
+ const sql = loadTemplate[type].includes(`${name}.sql`) ? await readFile(path.join(typeDir, `${name}.sql`), 'utf-8') : null;
25
+ const data = loadTemplate[type].includes(`${name}.json`) ? JSON.parse(await readFile(path.join(typeDir, `${name}.json`), 'utf-8')) : await readFile(path.join(typeDir, `${name}.${ext}`), 'utf-8');
26
+ if (sql) return { ...data || {}, sql };
27
+ return data;
28
+ }
@@ -1,18 +1,18 @@
1
- import fs from 'fs';
2
- import path from 'path';
3
- import config from '../../../config.js';
4
-
5
- const loadTemplate = {};
6
-
7
- export default async function getTemplateDir(type) {
8
- if (!type) return null;
9
-
10
- const cwd = process.cwd();
11
- const typeDir = path.join(cwd, (config.templateDir || 'server/templates'), type);
12
-
13
- if (!loadTemplate[type]) {
14
- const typeList = fs.existsSync(typeDir) ? fs.readdirSync(typeDir) : [];
15
- loadTemplate[type] = typeList;
16
- }
17
- return loadTemplate[type];
18
- }
1
+ import fs from 'fs';
2
+ import path from 'path';
3
+ import config from '../../../config.js';
4
+
5
+ const loadTemplate = {};
6
+
7
+ export default async function getTemplateDir(type) {
8
+ if (!type) return null;
9
+
10
+ const cwd = process.cwd();
11
+ const typeDir = path.join(cwd, (config.templateDir || 'server/templates'), type);
12
+
13
+ if (!loadTemplate[type]) {
14
+ const typeList = fs.existsSync(typeDir) ? fs.readdirSync(typeDir) : [];
15
+ loadTemplate[type] = typeList;
16
+ }
17
+ return loadTemplate[type];
18
+ }
@@ -1,34 +1,34 @@
1
- function getTable(table) {
2
- const result = table?.toLowerCase()?.replace(/[\n\r]+/g, ' ')?.split(' from ')?.filter((el) => /^[a-z0-9_]+\.[a-z0-9_]+/.test(el))
3
- ?.map((el) => el.split(/[ )]/)[0]);
4
- return result;
5
- }
6
-
7
- /**
8
- * @param {Number} opt.json - (1|0) 1 - Результат - Object, 0 - String
9
- * @param {String} opt.query - запит до таблиці
10
- * @param {String} opt.hash - інформація з хешу по запиту
11
- */
12
- const tableSql = {};
13
- async function getTableSql({
14
- pg, body, table, fields,
15
- }) {
16
- if (tableSql[table]) return tableSql[table];
17
-
18
- const fieldList = fields.map((el) => el.name);
19
-
20
- const tableList = body?.sql?.map((el) => getTable(el.sql)).reduce((acc, el) => acc.concat(el), []).filter((el) => fieldList.includes(pg.pk[el]));
21
-
22
- if (!tableList) { tableSql[table] = []; return []; }
23
-
24
- const data = await Promise.all(tableList?.map(async (tableEl) => {
25
- const { fields: fieldsEl } = await pg.query(`select * from ${tableEl} limit 0`);
26
- return fieldsEl.map((el) => ({ name: el.name, table: tableEl, pk: pg.pk[tableEl] }));
27
- }));
28
-
29
- tableSql[table] = data.reduce((acc, el) => acc.concat(el), []);
30
-
31
- return tableSql[table];
32
- }
33
-
34
- export default getTableSql;
1
+ function getTable(table) {
2
+ const result = table?.toLowerCase()?.replace(/[\n\r]+/g, ' ')?.split(' from ')?.filter((el) => /^[a-z0-9_]+\.[a-z0-9_]+/.test(el))
3
+ ?.map((el) => el.split(/[ )]/)[0]);
4
+ return result;
5
+ }
6
+
7
+ /**
8
+ * @param {Number} opt.json - (1|0) 1 - Результат - Object, 0 - String
9
+ * @param {String} opt.query - запит до таблиці
10
+ * @param {String} opt.hash - інформація з хешу по запиту
11
+ */
12
+ const tableSql = {};
13
+ async function getTableSql({
14
+ pg, body, table, fields,
15
+ }) {
16
+ if (tableSql[table]) return tableSql[table];
17
+
18
+ const fieldList = fields.map((el) => el.name);
19
+
20
+ const tableList = body?.sql?.map((el) => getTable(el.sql)).reduce((acc, el) => acc.concat(el), []).filter((el) => fieldList.includes(pg.pk[el]));
21
+
22
+ if (!tableList) { tableSql[table] = []; return []; }
23
+
24
+ const data = await Promise.all(tableList?.map(async (tableEl) => {
25
+ const { fields: fieldsEl } = await pg.query(`select * from ${tableEl} limit 0`);
26
+ return fieldsEl.map((el) => ({ name: el.name, table: tableEl, pk: pg.pk[tableEl] }));
27
+ }));
28
+
29
+ tableSql[table] = data.reduce((acc, el) => acc.concat(el), []);
30
+
31
+ return tableSql[table];
32
+ }
33
+
34
+ export default getTableSql;
@@ -1,27 +1,27 @@
1
- import getTemplate from '../../controllers/utils/getTemplate.js';
2
- import getSelectVal from './getSelectVal.js';
3
-
4
- export default async function metaFormat({ rows, table }) {
5
- const loadTable = await getTemplate('table', table);
6
- const selectCols = loadTable?.columns?.filter((e) => e.data);
7
- if (!selectCols?.length) return rows;
8
-
9
- // cls & select format
10
-
11
- await Promise.all(selectCols?.map(async (attr) => {
12
- const values = [...new Set(rows?.map((el) => el[attr.name]).flat())].filter((el) => el);
13
- if (!values.length) return null;
14
-
15
- const cls = await getSelectVal({ name: attr.data, values });
16
- if (!cls) return null;
17
- rows.forEach(el => {
18
- const val = el[attr.name]?.map?.(c => cls[c] || c) || cls[el[attr.name]] || el[attr.name];
19
- if (!val) return;
20
- Object.assign(el, { [val?.color ? `${attr.name}_data` : `${attr.name}_text`]: (val.color ? val : val.text || val) });
21
- });
22
-
23
- return null;
24
- }));
25
-
26
- return rows;
27
- }
1
+ import getTemplate from '../../controllers/utils/getTemplate.js';
2
+ import getSelectVal from './getSelectVal.js';
3
+
4
+ export default async function metaFormat({ rows, table }) {
5
+ const loadTable = await getTemplate('table', table);
6
+ const selectCols = loadTable?.columns?.filter((e) => e.data);
7
+ if (!selectCols?.length) return rows;
8
+
9
+ // cls & select format
10
+
11
+ await Promise.all(selectCols?.map(async (attr) => {
12
+ const values = [...new Set(rows?.map((el) => el[attr.name]).flat())].filter((el) => el);
13
+ if (!values.length) return null;
14
+
15
+ const cls = await getSelectVal({ name: attr.data, values });
16
+ if (!cls) return null;
17
+ rows.forEach(el => {
18
+ const val = el[attr.name]?.map?.(c => cls[c] || c) || cls[el[attr.name]] || el[attr.name];
19
+ if (!val) return;
20
+ Object.assign(el, { [val?.color ? `${attr.name}_data` : `${attr.name}_text`]: (val.color ? val : val.text || val) });
21
+ });
22
+
23
+ return null;
24
+ }));
25
+
26
+ return rows;
27
+ }
package/table/index.js CHANGED
@@ -1,78 +1,78 @@
1
- import suggest from './controllers/suggest.js';
2
- import data from './controllers/data.js';
3
- import table from './controllers/table.js';
4
- import card from './controllers/card.js';
5
- import search from './controllers/search.js';
6
- import filter from './controllers/filter.js';
7
- import form from './controllers/form.js';
8
- import metaFormat from './funcs/metaFormat/index.js';
9
- import getFilterSQL from './funcs/getFilterSQL/index.js';
10
- import getTemplate from './controllers/utils/getTemplate.js';
11
-
12
- const tableSchema = {
13
- querystring: {
14
- page: { type: 'string', pattern: '^(\\d+)$' },
15
- order: { type: 'string', pattern: '^(\\d+)$' },
16
- filter: { type: 'string', pattern: '^([\\w\\d_-]+)=([\\w\\d_-]+)$' },
17
- },
18
- params: {
19
- id: { type: 'string', pattern: '^([\\d\\w]+)$' },
20
- table: { type: 'string', pattern: '^([\\w\\d_.]+)$' },
21
- },
22
- };
23
-
24
- const searchSchema = {
25
- querystring: {
26
- page: { type: 'string', pattern: '^(\\d+)$' },
27
- limit: { type: 'string', pattern: '^(\\d+)$' },
28
- order: { type: 'string', pattern: '^([\\w_.]+)$' },
29
- desc: { type: 'string', pattern: '^(desc)|(asc)$' },
30
- key: { type: 'string', pattern: '^([\\w\\d_]+)$' },
31
- table: { type: 'string', pattern: '^([\\w\\d_.]+)$' },
32
- sql: { type: 'string', pattern: '^(\\d)$' },
33
- },
34
- };
35
-
36
- const suggestSchema = {
37
- querystring: {
38
- lang: { type: 'string', pattern: '^([\\w.]+)$' },
39
- // parent: { type: 'string', pattern: '^([\\w,./]+)$' },
40
- sel: { type: 'string', pattern: '^([\\w,./]+)$' },
41
- name: { type: 'string', pattern: '^([\\w,./]+)$' },
42
- // key: { type: 'string', pattern: '^([\\w\\d_]+)$' },
43
- // val: { type: 'string', pattern: '^([\\w.,]+)$' },
44
- sql: { type: 'string', pattern: '^(\\d)$' },
45
- },
46
- params: {
47
- id: { type: 'string', pattern: '^([\\d\\w]+)$' },
48
- },
49
- };
50
-
51
- const formSchema = {
52
- params: {
53
- form: { type: 'string', pattern: '^([\\w\\d_.]+)$' },
54
- },
55
- };
56
-
57
- const filterSchema = {
58
- params: {
59
- table: { type: 'string', pattern: '^([\\w\\d_.]+)$' },
60
- },
61
- };
62
-
63
- async function plugin(fastify, config = {}) {
64
- const prefix = config.prefix || '/api';
65
- fastify.decorate('metaFormat', metaFormat);
66
- fastify.decorate('getFilterSQL', getFilterSQL);
67
- fastify.decorate('getTemplate', getTemplate);
68
-
69
- fastify.get(`${prefix}/suggest/:data`, { schema: suggestSchema }, suggest);
70
- fastify.get(`${prefix}/data/:table/:id?`, { schema: tableSchema }, data); // vs.crm.data.api с node
71
- fastify.get(`${prefix}/table/:table/:id`, { schema: tableSchema }, table);
72
- fastify.get(`${prefix}/card/:table/:id`, { schema: tableSchema }, card);
73
- fastify.get(`${prefix}/search`, { schema: searchSchema }, search);
74
- fastify.get(`${prefix}/filter/:table`, { schema: filterSchema }, filter);
75
- fastify.get(`${prefix}/form/:form`, { schema: formSchema }, form);
76
- }
77
-
78
- export default plugin;
1
+ import suggest from './controllers/suggest.js';
2
+ import data from './controllers/data.js';
3
+ import table from './controllers/table.js';
4
+ import card from './controllers/card.js';
5
+ import search from './controllers/search.js';
6
+ import filter from './controllers/filter.js';
7
+ import form from './controllers/form.js';
8
+ import metaFormat from './funcs/metaFormat/index.js';
9
+ import getFilterSQL from './funcs/getFilterSQL/index.js';
10
+ import getTemplate from './controllers/utils/getTemplate.js';
11
+
12
+ const tableSchema = {
13
+ querystring: {
14
+ page: { type: 'string', pattern: '^(\\d+)$' },
15
+ order: { type: 'string', pattern: '^(\\d+)$' },
16
+ filter: { type: 'string', pattern: '^([\\w\\d_-]+)=([\\w\\d_-]+)$' },
17
+ },
18
+ params: {
19
+ id: { type: 'string', pattern: '^([\\d\\w]+)$' },
20
+ table: { type: 'string', pattern: '^([\\w\\d_.]+)$' },
21
+ },
22
+ };
23
+
24
+ const searchSchema = {
25
+ querystring: {
26
+ page: { type: 'string', pattern: '^(\\d+)$' },
27
+ limit: { type: 'string', pattern: '^(\\d+)$' },
28
+ order: { type: 'string', pattern: '^([\\w_.]+)$' },
29
+ desc: { type: 'string', pattern: '^(desc)|(asc)$' },
30
+ key: { type: 'string', pattern: '^([\\w\\d_]+)$' },
31
+ table: { type: 'string', pattern: '^([\\w\\d_.]+)$' },
32
+ sql: { type: 'string', pattern: '^(\\d)$' },
33
+ },
34
+ };
35
+
36
+ const suggestSchema = {
37
+ querystring: {
38
+ lang: { type: 'string', pattern: '^([\\w.]+)$' },
39
+ // parent: { type: 'string', pattern: '^([\\w,./]+)$' },
40
+ sel: { type: 'string', pattern: '^([\\w,./]+)$' },
41
+ name: { type: 'string', pattern: '^([\\w,./]+)$' },
42
+ // key: { type: 'string', pattern: '^([\\w\\d_]+)$' },
43
+ // val: { type: 'string', pattern: '^([\\w.,]+)$' },
44
+ sql: { type: 'string', pattern: '^(\\d)$' },
45
+ },
46
+ params: {
47
+ id: { type: 'string', pattern: '^([\\d\\w]+)$' },
48
+ },
49
+ };
50
+
51
+ const formSchema = {
52
+ params: {
53
+ form: { type: 'string', pattern: '^([\\w\\d_.]+)$' },
54
+ },
55
+ };
56
+
57
+ const filterSchema = {
58
+ params: {
59
+ table: { type: 'string', pattern: '^([\\w\\d_.]+)$' },
60
+ },
61
+ };
62
+
63
+ async function plugin(fastify, config = {}) {
64
+ const prefix = config.prefix || '/api';
65
+ fastify.decorate('metaFormat', metaFormat);
66
+ fastify.decorate('getFilterSQL', getFilterSQL);
67
+ fastify.decorate('getTemplate', getTemplate);
68
+
69
+ fastify.get(`${prefix}/suggest/:data`, { schema: suggestSchema }, suggest);
70
+ fastify.get(`${prefix}/data/:table/:id?`, { schema: tableSchema }, data); // vs.crm.data.api с node
71
+ fastify.get(`${prefix}/table/:table/:id`, { schema: tableSchema }, table);
72
+ fastify.get(`${prefix}/card/:table/:id`, { schema: tableSchema }, card);
73
+ fastify.get(`${prefix}/search`, { schema: searchSchema }, search);
74
+ fastify.get(`${prefix}/filter/:table`, { schema: filterSchema }, filter);
75
+ fastify.get(`${prefix}/form/:form`, { schema: formSchema }, form);
76
+ }
77
+
78
+ export default plugin;
@@ -4,11 +4,18 @@ import assert from 'node:assert';
4
4
  import build from '../../helper.js';
5
5
 
6
6
  import config from '../config.js';
7
+ import pgClients from '../../pg/pgClients.js';
8
+
9
+ const mapId = '5400000';
7
10
 
8
11
  test('api crud', async (t) => {
9
12
  const app = await build(t);
10
13
  const prefix = config.prefix || '/api';
11
14
 
15
+ // delete old test data before test
16
+ const { rowCount } = await pgClients.client.query('delete from gis.map where map_id=$1', [mapId]);
17
+ console.log(rowCount);
18
+
12
19
  app.addHook('onRequest', async (req) => {
13
20
  req.session = { passport: { user: { uid: '1' } } };
14
21
  req.user = req.session.passport.user;
@@ -21,61 +28,61 @@ test('api crud', async (t) => {
21
28
  url: `${prefix}/table/test.gis.map.table`,
22
29
  body: {
23
30
  alias: 'testMap',
24
- map_id: '5400000',
31
+ map_id: mapId,
25
32
  ord: 1,
26
33
  enabled: false,
27
34
  tags: ['unit', 'test'],
28
35
  },
29
36
  });
30
37
  // console.log(res);
31
- // assert.ok(res.json().rows ? res.json().rows[0]?.map_id : res.json().map_id, res.json().status);
38
+ assert.ok(res.json().rows ? res.json().rows[0]?.map_id : res.json().map_id, res.json().status);
32
39
  assert.ok(111);
33
40
  });
34
41
 
35
42
  await t.test('POST /properties/:id', async () => {
36
43
  const res = await app.inject({
37
44
  method: 'POST',
38
- url: `${prefix}/properties/5400000`,
45
+ url: `${prefix}/properties/${mapId}`,
39
46
  body: {
40
47
  custom_alias: 'testMap',
41
48
  custom_ord: 5,
42
49
  },
43
50
  });
44
- assert.ok(res.json().message.rows.length, res.json().status);
51
+ assert.ok(res.json().message?.rows?.length, res.json().status);
45
52
  });
46
53
 
47
54
  await t.test('GET /properties/:id', async () => {
48
55
  const res = await app.inject({
49
56
  method: 'GET',
50
- url: `${prefix}/properties/5400000`,
57
+ url: `${prefix}/properties/${mapId}`,
51
58
  });
52
- assert.ok(res.json().message.custom_alias, res.json().status);
59
+ assert.ok(res.json().message?.custom_alias, res.json().status);
53
60
  });
54
61
 
55
62
  await t.test('PUT /update', async () => {
56
63
  const res = await app.inject({
57
64
  method: 'PUT',
58
- url: `${prefix}/table/test.gis.map.table/5400000`,
65
+ url: `${prefix}/table/test.gis.map.table/${mapId}`,
59
66
  body: {
60
67
  editor_id: '11',
61
68
  alias: 'testMapEdit',
62
- map_id: '5400000',
69
+ map_id: mapId,
63
70
  ord: 2,
64
71
  enabled: true,
65
72
  tags: ['unittest'],
66
73
  },
67
74
  });
68
75
  // console.log(res);
69
- // assert.ok((res.json().rows ? res.json().rows[0]?.editor_id : res.json().editor_id) === '11', res.json().status);
76
+ assert.ok((res.json().rows ? res.json().rows[0]?.editor_id : res.json().editor_id) === '11', res.json().status);
70
77
  assert.ok(11);
71
78
  });
72
79
 
73
80
  await t.test('DELETE /delete', async () => {
74
81
  const res = await app.inject({
75
82
  method: 'DELETE',
76
- url: `${prefix}/table/test.gis.map.table/5400000`,
83
+ url: `${prefix}/table/test.gis.map.table/${mapId}`,
77
84
  });
78
85
 
79
- assert.ok(res.json(), res.json().status);
86
+ assert.ok(res.json().msg?.map_id === mapId, res.json().status);
80
87
  });
81
88
  });
@@ -1,72 +1,72 @@
1
- import { test } from 'node:test';
2
- import assert from 'node:assert';
3
-
4
- import build from '../../helper.js';
5
-
6
- import setToken from '../../crud/funcs/setToken.js';
7
- import config from '../config.js';
8
-
9
- test('api crud xss', async (t) => {
10
- const app = await build(t);
11
- const session = { passport: { user: { uid: '1' } } };
12
- app.addHook('onRequest', async (req) => {
13
- req.session = session;
14
- });
15
- // app.decorateRequest('session', session);
16
-
17
- const prefix = config.prefix || '/api';
18
-
19
- let addTokens;
20
- let editTokens;
21
-
22
- // before
23
- t.test('setToken', async () => {
24
- addTokens = setToken({
25
- ids: [JSON.stringify({ add: 'gis.dataset', form: 'test.dataset.form' })],
26
- mode: 'a',
27
- uid: 1,
28
- array: 1,
29
- });
30
- editTokens = setToken({
31
- ids: [JSON.stringify({ id: '5400000', table: 'gis.dataset', form: 'test.dataset.form' })],
32
- mode: 'w',
33
- uid: 1,
34
- array: 1,
35
- });
36
- assert.ok(addTokens.length === 1 && editTokens.length === 1, 'invalid token');
37
- });
38
-
39
- await t.test('POST /insert', async () => {
40
- const res = await app.inject({
41
- method: 'POST',
42
- url: `${prefix}/table/${addTokens[0]}`,
43
- body: { dataset_name: '<a onClick="alert("XSS Injection")">xss injection</a>', dataset_id: '5400000' },
44
- });
45
-
46
- const rep = JSON.parse(res?.body);
47
- console.log(rep)
48
- assert.ok(rep.status, 409);
49
- });
50
-
51
- await t.test('PUT /update', async () => {
52
- const res = await app.inject({
53
- method: 'PUT',
54
- url: `${prefix}/table/${editTokens[0]}/${editTokens[0]}`,
55
- body: { editor_id: '11', dataset_name: '<a onClick="alert("XSS Injection")">xss injection</a>' },
56
- });
57
-
58
- const rep = JSON.parse(res?.body);
59
- console.log(rep)
60
- assert.equal(rep.status, 409);
61
- });
62
- await t.test('DELETE /delete', async () => {
63
- const res = await app.inject({
64
- method: 'DELETE',
65
- url: `${prefix}/table/gis.dataset/5400000`,
66
- });
67
-
68
- const rep = JSON.parse(res?.body);
69
- console.log(rep)
70
- assert.ok(rep);
71
- });
72
- });
1
+ import { test } from 'node:test';
2
+ import assert from 'node:assert';
3
+
4
+ import build from '../../helper.js';
5
+
6
+ import setToken from '../../crud/funcs/setToken.js';
7
+ import config from '../config.js';
8
+
9
+ test('api crud xss', async (t) => {
10
+ const app = await build(t);
11
+ const session = { passport: { user: { uid: '1' } } };
12
+ app.addHook('onRequest', async (req) => {
13
+ req.session = session;
14
+ });
15
+ // app.decorateRequest('session', session);
16
+
17
+ const prefix = config.prefix || '/api';
18
+
19
+ let addTokens;
20
+ let editTokens;
21
+
22
+ // before
23
+ t.test('setToken', async () => {
24
+ addTokens = setToken({
25
+ ids: [JSON.stringify({ add: 'gis.dataset', form: 'test.dataset.form' })],
26
+ mode: 'a',
27
+ uid: 1,
28
+ array: 1,
29
+ });
30
+ editTokens = setToken({
31
+ ids: [JSON.stringify({ id: '5400000', table: 'gis.dataset', form: 'test.dataset.form' })],
32
+ mode: 'w',
33
+ uid: 1,
34
+ array: 1,
35
+ });
36
+ assert.ok(addTokens.length === 1 && editTokens.length === 1, 'invalid token');
37
+ });
38
+
39
+ await t.test('POST /insert', async () => {
40
+ const res = await app.inject({
41
+ method: 'POST',
42
+ url: `${prefix}/table/${addTokens[0]}`,
43
+ body: { dataset_name: '<a onClick="alert("XSS Injection")">xss injection</a>', dataset_id: '5400000' },
44
+ });
45
+
46
+ const rep = JSON.parse(res?.body);
47
+ console.log(rep)
48
+ assert.ok(rep.status, 409);
49
+ });
50
+
51
+ await t.test('PUT /update', async () => {
52
+ const res = await app.inject({
53
+ method: 'PUT',
54
+ url: `${prefix}/table/${editTokens[0]}/${editTokens[0]}`,
55
+ body: { editor_id: '11', dataset_name: '<a onClick="alert("XSS Injection")">xss injection</a>' },
56
+ });
57
+
58
+ const rep = JSON.parse(res?.body);
59
+ console.log(rep)
60
+ assert.equal(rep.status, 409);
61
+ });
62
+ await t.test('DELETE /delete', async () => {
63
+ const res = await app.inject({
64
+ method: 'DELETE',
65
+ url: `${prefix}/table/gis.dataset/5400000`,
66
+ });
67
+
68
+ const rep = JSON.parse(res?.body);
69
+ console.log(rep)
70
+ assert.ok(rep);
71
+ });
72
+ });