@opengis/fastify-table 1.1.43 → 1.1.45
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 +2 -1
- package/crud/controllers/deleteCrud.js +4 -3
- package/crud/controllers/insert.js +2 -2
- package/crud/controllers/update.js +2 -2
- package/crud/funcs/getAccess.js +21 -17
- package/crud/funcs/utils/logChanges.js +17 -31
- package/hook/funcs/applyHook.js +1 -1
- package/index.js +8 -2
- package/module/test/table/test.rest_zone.table.json +1 -0
- package/package.json +1 -1
- package/table/controllers/card.js +37 -6
- package/table/controllers/data.js +20 -9
- package/table/controllers/table.js +14 -2
- package/test/api/crud.xss.test.js +5 -13
- package/test/api/table.test.js +7 -0
package/Changelog.md
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
1
|
+
import {
|
|
2
|
+
dataDelete, getTemplate, getAccess, applyHook,
|
|
3
|
+
} from '../../utils.js';
|
|
3
4
|
|
|
4
5
|
export default async function deleteCrud(req) {
|
|
5
6
|
const { user, params = {} } = req || {};
|
|
@@ -11,7 +12,7 @@ export default async function deleteCrud(req) {
|
|
|
11
12
|
}
|
|
12
13
|
|
|
13
14
|
const { table: del, id } = hookData || req.params || {};
|
|
14
|
-
const { actions = [], scope, my } = await getAccess(
|
|
15
|
+
const { actions = [], scope, my } = await getAccess({ table: del, id, user }) || {};
|
|
15
16
|
|
|
16
17
|
if (!actions.includes('del') || (scope === 'my' && !my)) {
|
|
17
18
|
return { message: 'access restricted', status: 403 };
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
|
|
5
5
|
export default async function insert(req) {
|
|
6
6
|
const {
|
|
7
|
-
|
|
7
|
+
user, params = {}, body = {},
|
|
8
8
|
} = req || {};
|
|
9
9
|
const hookData = await applyHook('preInsert', { table: params?.table, user });
|
|
10
10
|
if (hookData?.message && hookData?.status) {
|
|
@@ -13,7 +13,7 @@ export default async function insert(req) {
|
|
|
13
13
|
|
|
14
14
|
const { form, table: add } = hookData || req.params || {};
|
|
15
15
|
|
|
16
|
-
const { actions = [] } = await getAccess(
|
|
16
|
+
const { actions = [] } = await getAccess({ table: add, user }) || {};
|
|
17
17
|
|
|
18
18
|
if (!actions.includes('edit')) {
|
|
19
19
|
return { message: 'access restricted', status: 403 };
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
|
|
5
5
|
export default async function update(req) {
|
|
6
6
|
const {
|
|
7
|
-
|
|
7
|
+
user, params = {}, body = {},
|
|
8
8
|
} = req || {};
|
|
9
9
|
const hookData = await applyHook('preUpdate', {
|
|
10
10
|
table: params?.table, id: params?.id, user,
|
|
@@ -15,7 +15,7 @@ export default async function update(req) {
|
|
|
15
15
|
|
|
16
16
|
const { form, table: edit, id } = hookData || req.params;
|
|
17
17
|
|
|
18
|
-
const { actions = [], scope, my } = await getAccess(
|
|
18
|
+
const { actions = [], scope, my } = await getAccess({ table: edit, id, user }) || {};
|
|
19
19
|
|
|
20
20
|
if (!actions.includes('edit') || (scope === 'my' && !my)) {
|
|
21
21
|
return { message: 'access restricted', status: 403 };
|
package/crud/funcs/getAccess.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import getMeta from '../../pg/funcs/getMeta.js';
|
|
2
2
|
import getTemplate from '../../table/controllers/utils/getTemplate.js';
|
|
3
3
|
import config from '../../config.js';
|
|
4
|
+
import pgClients from '../../pg/pgClients.js';
|
|
4
5
|
|
|
5
|
-
const q = `select a.route_id as id, b.actions, b.scope
|
|
6
|
+
const q = `select a.route_id as id, coalesce(b.actions,array['get']) as actions, b.scope
|
|
6
7
|
from admin.routes a
|
|
7
8
|
left join admin.access b on
|
|
8
9
|
a.route_id=b.route_id
|
|
@@ -16,36 +17,39 @@ left join admin.user_roles d on
|
|
|
16
17
|
then d.expiration > CURRENT_DATE
|
|
17
18
|
else 1=1
|
|
18
19
|
end )
|
|
19
|
-
where a.route_id
|
|
20
|
+
where $1 in (a.route_id, a.alias) and $2 in (b.user_uid, d.user_uid)`;
|
|
20
21
|
|
|
21
|
-
export default async function getAccess(
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
const { uid, user_type: userType } = session.passport?.user || {};
|
|
27
|
-
if (!uid || !template) return null;
|
|
22
|
+
export default async function getAccess({ table, id, user }) {
|
|
23
|
+
const { client: pg } = pgClients || {};
|
|
24
|
+
const { uid, user_type: userType } = user || {};
|
|
25
|
+
|
|
26
|
+
if (!uid || !table) return null;
|
|
28
27
|
|
|
29
28
|
if (!pg.pk?.['admin.access']) return null;
|
|
30
29
|
|
|
31
|
-
const
|
|
32
|
-
if (!table) return null;
|
|
30
|
+
const body = await getTemplate('table', table) || {};
|
|
31
|
+
if (!body?.table) return null;
|
|
32
|
+
|
|
33
|
+
if (config.auth?.disable || user?.user_type?.includes('admin') || body?.public) {
|
|
34
|
+
return { actions: ['get', 'edit', 'del'], my: true, query: '1=1' };
|
|
35
|
+
}
|
|
33
36
|
|
|
34
|
-
const { scope = 'my', actions = [] } = await pg.
|
|
35
|
-
// console.log(scope, actions);
|
|
37
|
+
const { scope = 'my', actions = [] } = await pg.query(q, [table, uid]).then((res) => res.rows?.[0] || {});
|
|
36
38
|
|
|
37
|
-
const { columns = [] } = await getMeta(table);
|
|
38
|
-
const columnList = columns.map((el) => el.name || el).join(',');
|
|
39
|
+
const { columns = [] } = await getMeta({ table: body?.table });
|
|
39
40
|
|
|
40
41
|
const query = userType?.includes('admin') ? '1=1' : {
|
|
41
42
|
my: `uid='${uid}'`,
|
|
42
|
-
responsible:
|
|
43
|
+
responsible: columns.map((el) => el?.name || el).includes('responsible_id')
|
|
43
44
|
? `responsible_id='${uid}'`
|
|
44
45
|
: `uid='${uid}'`,
|
|
45
46
|
all: '1=1',
|
|
46
47
|
}[scope];
|
|
47
48
|
|
|
48
|
-
const { my } = pg.pk?.[table] && id
|
|
49
|
+
const { my } = pg.pk?.[body?.table] && id
|
|
50
|
+
? await pg.query(`select uid=$1 as my from ${body?.table} where ${pg.pk?.[body?.table]}=$2`, [uid, id])
|
|
51
|
+
.then((res) => res.rows?.[0] || {})
|
|
52
|
+
: {};
|
|
49
53
|
|
|
50
54
|
return {
|
|
51
55
|
scope, actions, query, my,
|
|
@@ -1,28 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
if (!value) return null;
|
|
3
|
-
if (fieldType === 'geometry') {
|
|
4
|
-
return typeof value === 'object' ? `st_astext(st_geomfromgeojson('${JSON.stringify(value)}'::json))` : `st_astext('${value}'::geometry)`;
|
|
5
|
-
}
|
|
6
|
-
if (['integer', 'numeric', 'double precision'].includes(fieldType)) {
|
|
7
|
-
return value || null;
|
|
8
|
-
}
|
|
9
|
-
if (fieldType.includes('timestamp') || fieldType === 'date') {
|
|
10
|
-
if (typeof value === 'object') {
|
|
11
|
-
return value ? `'${value.toISOString()}'::${fieldType}` : null;
|
|
12
|
-
}
|
|
13
|
-
return value ? `'${value}'::${fieldType}` : null;
|
|
14
|
-
}
|
|
15
|
-
if (typeof value === 'object' || fieldType.includes('json')) {
|
|
16
|
-
if (Array.isArray(value)) {
|
|
17
|
-
return `'${JSON.stringify(value)}'`;
|
|
18
|
-
}
|
|
19
|
-
return `'${JSON.stringify(value)}'`;
|
|
20
|
-
}
|
|
21
|
-
if (Array.isArray(value)) {
|
|
22
|
-
return `'{ ${value.join(',')} }'::${fieldType}`;
|
|
23
|
-
}
|
|
24
|
-
return `'${value || null}'`;
|
|
25
|
-
}
|
|
1
|
+
import getMeta from '../../../pg/funcs/getMeta.js';
|
|
26
2
|
|
|
27
3
|
export default async function logChanges({
|
|
28
4
|
pg, table, id, data, uid = 1, type,
|
|
@@ -55,13 +31,23 @@ export default async function logChanges({
|
|
|
55
31
|
|
|
56
32
|
const old = type !== 'INSERT' ? await pg.query(q, [id]).then((res) => res.rows?.[0] || {}) : {};
|
|
57
33
|
|
|
58
|
-
const
|
|
59
|
-
const
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
34
|
+
const { columns = [] } = await getMeta({ table: 'log.table_changes_data' });
|
|
35
|
+
const names = columns.map((el) => el.name);
|
|
36
|
+
|
|
37
|
+
const res = await Promise.all(Object.keys(data || {}).map(async (el) => {
|
|
38
|
+
const filterData = Object.entries({
|
|
39
|
+
change_id: changeId, entity_key: el, value_old: old[el], value_new: data[el], uid,
|
|
40
|
+
})
|
|
41
|
+
.filter((el) => el[1] && names.includes(el[0]));
|
|
42
|
+
|
|
43
|
+
const insertQuery = `insert into log.table_changes_data (${filterData?.map((key) => `"${key[0]}"`).join(',')})
|
|
44
|
+
values (${filterData?.map((key, i) => `$${i + 1}`).join(',')}) returning *`;
|
|
45
|
+
|
|
46
|
+
const { rows = [] } = await pg.query(insertQuery, [...filterData.map((el) => (el[1] && typeof el[1] === 'object' && (!Array.isArray(el[1]) || typeof el[1]?.[0] === 'object') ? JSON.stringify(el[1]) : el[1]))]) || {};
|
|
47
|
+
return rows[0];
|
|
48
|
+
}));
|
|
63
49
|
|
|
64
|
-
const newData = type === 'DELETE' ? {} : (Array.isArray(res) ? res : [res]).reduce((acc, curr) => Object.assign(acc, { [curr.
|
|
50
|
+
const newData = type === 'DELETE' ? {} : (Array.isArray(res) ? res : [res]).reduce((acc, curr) => Object.assign(acc, { [curr.entity_key]: curr.value_new }), {});
|
|
65
51
|
// console.log('logChanges OK', type);
|
|
66
52
|
return {
|
|
67
53
|
change_id: changeId, entity_type: table, entity_id: id, uid, change_type: type, old, new: newData,
|
package/hook/funcs/applyHook.js
CHANGED
|
@@ -2,7 +2,7 @@ import config from '../../config.js';
|
|
|
2
2
|
import hookList from './hookList.js';
|
|
3
3
|
|
|
4
4
|
export default async function applyHook(name, data) {
|
|
5
|
-
const debug = config
|
|
5
|
+
const { debug } = config;
|
|
6
6
|
if (debug) console.log('applyHook', name);
|
|
7
7
|
if (!hookList[name]?.length) return null;
|
|
8
8
|
const result = {};
|
package/index.js
CHANGED
|
@@ -20,7 +20,7 @@ import userPlugin from './user/index.js';
|
|
|
20
20
|
|
|
21
21
|
// import pgClients from './pg/pgClients.js';
|
|
22
22
|
|
|
23
|
-
import { addTemplateDir, execMigrations } from './utils.js';
|
|
23
|
+
import { addTemplateDir, execMigrations, logger } from './utils.js';
|
|
24
24
|
|
|
25
25
|
async function plugin(fastify, opt) {
|
|
26
26
|
// console.log(opt);
|
|
@@ -65,8 +65,14 @@ async function plugin(fastify, opt) {
|
|
|
65
65
|
return reply.status(error.statusCode || 500).send(config.local ? error.toString() : 'ServerError');
|
|
66
66
|
});
|
|
67
67
|
|
|
68
|
+
execMigrations().catch(err => console.log(err));
|
|
68
69
|
// core migrations
|
|
69
|
-
|
|
70
|
+
/* try {
|
|
71
|
+
|
|
72
|
+
}
|
|
73
|
+
catch (err) {
|
|
74
|
+
logger.error(err);
|
|
75
|
+
} */
|
|
70
76
|
|
|
71
77
|
if (!fastify.funcs) {
|
|
72
78
|
fastify.addHook('onRequest', async (req) => {
|
package/package.json
CHANGED
|
@@ -1,14 +1,36 @@
|
|
|
1
1
|
import getTemplate from './utils/getTemplate.js';
|
|
2
2
|
import getMeta from '../../pg/funcs/getMeta.js';
|
|
3
3
|
import metaFormat from '../funcs/metaFormat/index.js';
|
|
4
|
+
import applyHook from '../../hook/funcs/applyHook.js';
|
|
5
|
+
import getAccess from '../../crud/funcs/getAccess.js';
|
|
4
6
|
|
|
5
7
|
export default async function card(req) {
|
|
6
8
|
const time = Date.now();
|
|
7
9
|
const {
|
|
8
|
-
pg, params = {}, query = {},
|
|
10
|
+
pg, user, params = {}, query = {},
|
|
9
11
|
} = req;
|
|
10
12
|
|
|
11
|
-
const
|
|
13
|
+
const hookData = await applyHook('preCard', {
|
|
14
|
+
table: params?.table, id: params?.id, user,
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
if (hookData?.message && hookData?.status) {
|
|
18
|
+
return { message: hookData?.message, status: hookData?.status };
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const {
|
|
22
|
+
actions = [], scope, my,
|
|
23
|
+
} = await getAccess({
|
|
24
|
+
table: hookData?.table || params.table,
|
|
25
|
+
id: hookData?.id || params?.id,
|
|
26
|
+
user,
|
|
27
|
+
}) || {};
|
|
28
|
+
|
|
29
|
+
if (!actions.includes('get') || (scope === 'my' && !my)) {
|
|
30
|
+
return { message: 'access restricted', status: 403 };
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const loadTable = await getTemplate('table', hookData?.table || params.table);
|
|
12
34
|
|
|
13
35
|
if (!loadTable) { return { message: 'template not found', status: 404 }; }
|
|
14
36
|
|
|
@@ -23,7 +45,7 @@ export default async function card(req) {
|
|
|
23
45
|
const cols = columns.map((el) => el.name || el).join(',');
|
|
24
46
|
const columnList = dbColumns.map((el) => el.name || el).join(',');
|
|
25
47
|
const sqlTable = sql?.filter?.((el) => !el?.disabled && el?.sql?.replace).map((el, i) => ` left join lateral (${el.sql}) ${el.name || `t${i}`} on 1=1 `)?.join('') || '';
|
|
26
|
-
const cardSqlFiltered =
|
|
48
|
+
const cardSqlFiltered = hookData?.id || params.id ? cardSql?.filter?.((el) => !el?.disabled && el?.name && el?.sql?.replace) : [];
|
|
27
49
|
const cardSqlTable = cardSqlFiltered?.length ? cardSqlFiltered.map((el, i) => ` left join lateral (select json_agg(row_to_json(q)) as ${el.name} from (${el.sql})q) ct${i} on 1=1 `).join('') || '' : '';
|
|
28
50
|
|
|
29
51
|
const where = [`"${pk}" = $1`, loadTable.query].filter((el) => el);
|
|
@@ -33,12 +55,21 @@ export default async function card(req) {
|
|
|
33
55
|
|
|
34
56
|
if (query.sql === '1') { return q; }
|
|
35
57
|
|
|
36
|
-
const { rows } = await pg.query(q, [
|
|
58
|
+
const { rows } = await pg.query(q, [hookData?.id || params.id]);
|
|
37
59
|
|
|
38
|
-
await metaFormat({ rows, table: params.table });
|
|
60
|
+
await metaFormat({ rows, table: hookData?.table || params.table });
|
|
39
61
|
|
|
40
62
|
const data = meta.card?.length ? meta.card.reduce((acc, curr) => Object.assign(acc, { [columns.find((col) => col.name === curr)?.ua || '']: rows[0][curr] }), {}) : {};
|
|
41
|
-
|
|
63
|
+
|
|
64
|
+
const afterHookData = await applyHook('afterCard', {
|
|
65
|
+
table: hookData?.table || params.table,
|
|
66
|
+
id: hookData?.id || params?.id,
|
|
67
|
+
user,
|
|
68
|
+
payload: {
|
|
69
|
+
time: Date.now() - time, data,
|
|
70
|
+
},
|
|
71
|
+
});
|
|
72
|
+
return afterHookData || {
|
|
42
73
|
time: Date.now() - time, data,
|
|
43
74
|
};
|
|
44
75
|
}
|
|
@@ -5,13 +5,13 @@ import metaFormat from '../funcs/metaFormat/index.js';
|
|
|
5
5
|
import getAccess from '../../crud/funcs/getAccess.js';
|
|
6
6
|
import setToken from '../../crud/funcs/setToken.js';
|
|
7
7
|
import gisIRColumn from './utils/gisIRColumn.js';
|
|
8
|
-
|
|
9
|
-
import
|
|
8
|
+
import applyHook from '../../hook/funcs/applyHook.js';
|
|
9
|
+
import config from '../../config.js';
|
|
10
10
|
|
|
11
11
|
const maxLimit = 100;
|
|
12
12
|
export default async function dataAPI(req) {
|
|
13
13
|
const {
|
|
14
|
-
pg, params, query = {},
|
|
14
|
+
pg, params, query = {}, user,
|
|
15
15
|
} = req;
|
|
16
16
|
const time = Date.now();
|
|
17
17
|
|
|
@@ -24,6 +24,18 @@ export default async function dataAPI(req) {
|
|
|
24
24
|
return { message: hookData?.message, status: hookData?.status };
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
+
const {
|
|
28
|
+
actions = [], scope, my, query: access,
|
|
29
|
+
} = await getAccess({
|
|
30
|
+
table: hookData?.table || params.table,
|
|
31
|
+
id: hookData?.id || params?.id,
|
|
32
|
+
user,
|
|
33
|
+
}) || {};
|
|
34
|
+
|
|
35
|
+
if (!actions.includes('get') || (scope === 'my' && !my)) {
|
|
36
|
+
return { message: 'access restricted', status: 403 };
|
|
37
|
+
}
|
|
38
|
+
|
|
27
39
|
const loadTable = await getTemplate('table', hookData?.table || params.table);
|
|
28
40
|
|
|
29
41
|
if (!loadTable) { return { message: 'template not found', status: 404 }; }
|
|
@@ -46,7 +58,7 @@ export default async function dataAPI(req) {
|
|
|
46
58
|
: '';
|
|
47
59
|
const columnList = dbColumns.map((el) => el.name || el).join(',');
|
|
48
60
|
const sqlTable = sql?.filter?.((el) => !el?.disabled && el?.sql?.replace).map((el, i) => ` left join lateral (${el.sql.replace('{{uid}}', uid)}) ${el.name || `t${i}`} on 1=1 `)?.join('') || '';
|
|
49
|
-
const cardSqlFiltered =
|
|
61
|
+
const cardSqlFiltered = hookData?.id || params.id ? (cardSql?.filter?.((el) => !el?.disabled && el?.name && el?.sql?.replace) || []) : [];
|
|
50
62
|
const cardSqlTable = cardSqlFiltered.length ? cardSqlFiltered.map((el, i) => ` left join lateral (select json_agg(row_to_json(q)) as ${el.name} from (${el.sql})q) ct${i} on 1=1 `).join('') || '' : '';
|
|
51
63
|
|
|
52
64
|
if (params.id && columnList.includes(params.id)) {
|
|
@@ -65,7 +77,7 @@ export default async function dataAPI(req) {
|
|
|
65
77
|
json: 1,
|
|
66
78
|
}) : {};
|
|
67
79
|
|
|
68
|
-
const keyQuery = query.key && loadTable.key && !(
|
|
80
|
+
const keyQuery = query.key && loadTable.key && !(hookData?.id || params.id) ? `${loadTable.key}=$1` : null;
|
|
69
81
|
|
|
70
82
|
const limit = Math.min(maxLimit, +(query.limit || 20));
|
|
71
83
|
|
|
@@ -79,16 +91,15 @@ export default async function dataAPI(req) {
|
|
|
79
91
|
const queryPolyline = meta?.bbox && query?.polyline ? `ST_Contains(ST_MakePolygon(ST_LineFromEncodedPolyline('${query?.polyline}')),${meta.bbox})` : undefined;
|
|
80
92
|
const bbox = meta?.bbox && queryBbox.filter((el) => !Number.isNaN(el))?.length === 4 ? `${meta.bbox} && 'box(${queryBbox[0]} ${queryBbox[1]},${queryBbox[2]} ${queryBbox[3]})'::box2d ` : undefined;
|
|
81
93
|
|
|
82
|
-
const
|
|
83
|
-
const where = [(opt?.id || params.id ? ` "${pk}" = $1` : null), keyQuery, loadTable.query, fData.q, search, access?.query || '1=1', bbox, queryPolyline].filter((el) => el);
|
|
94
|
+
const where = [(hookData?.id || params.id ? ` "${pk}" = $1` : null), keyQuery, loadTable.query, fData.q, search, access?.query || '1=1', bbox, queryPolyline].filter((el) => el);
|
|
84
95
|
const cardColumns = cardSqlFiltered.length ? `,${cardSqlFiltered.map((el) => el.name)}` : '';
|
|
85
96
|
const q = `select ${pk ? `"${pk}" as id,` : ''} ${columnList.includes('geom') ? 'st_asgeojson(geom)::json as geom,' : ''} ${query.id || query.key ? '*' : sqlColumns || cols || '*'} ${metaCols} ${cardColumns} from ${table} t ${sqlTable} ${cardSqlTable} where ${where.join(' and ') || 'true'} ${order} ${offset} limit ${limit}`;
|
|
86
97
|
|
|
87
98
|
if (query.sql === '1') { return q; }
|
|
88
99
|
|
|
89
|
-
const { rows } = await pg.query(q, (
|
|
100
|
+
const { rows } = await pg.query(q, (hookData?.id || params.id ? [hookData?.id || params.id] : null) || (query.key && loadTable.key ? [query.key] : []));
|
|
90
101
|
|
|
91
|
-
const total = keyQuery ||
|
|
102
|
+
const total = keyQuery || hookData?.id || params.id ? rows.length : await pg.queryCache(`select count(*) from ${table} t ${sqlTable} where ${where.join(' and ') || 'true'}`).then((el) => (el?.rows[0]?.count || 0) - 0);
|
|
92
103
|
|
|
93
104
|
await metaFormat({ rows, table: params.table });
|
|
94
105
|
const res = {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import getTemplate from './utils/getTemplate.js';
|
|
2
2
|
import getMeta from '../../pg/funcs/getMeta.js';
|
|
3
|
-
|
|
4
|
-
import
|
|
3
|
+
import applyHook from '../../hook/funcs/applyHook.js';
|
|
4
|
+
import getAccess from '../../crud/funcs/getAccess.js';
|
|
5
5
|
|
|
6
6
|
export default async function tableAPI(req) {
|
|
7
7
|
const {
|
|
@@ -24,6 +24,18 @@ export default async function tableAPI(req) {
|
|
|
24
24
|
if (!pg.pk?.[hookData?.table || params.table]) { return { message: 'not found', status: 404 }; }
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
+
const {
|
|
28
|
+
actions = [], scope, my,
|
|
29
|
+
} = await getAccess({
|
|
30
|
+
table: hookData?.table || params.table,
|
|
31
|
+
id: hookData?.id || params?.id,
|
|
32
|
+
user,
|
|
33
|
+
}) || {};
|
|
34
|
+
|
|
35
|
+
if (!actions.includes('get') || (scope === 'my' && !my)) {
|
|
36
|
+
return { message: 'access restricted', status: 403 };
|
|
37
|
+
}
|
|
38
|
+
|
|
27
39
|
const {
|
|
28
40
|
table, /* columns, */ form,
|
|
29
41
|
} = loadTable;
|
|
@@ -8,9 +8,10 @@ import config from '../config.js';
|
|
|
8
8
|
|
|
9
9
|
test('api crud xss', async (t) => {
|
|
10
10
|
const app = await build(t);
|
|
11
|
-
const session = { passport: { user: { uid: '1' } } };
|
|
11
|
+
const session = { passport: { user: { uid: '1', user_type: 'admin' } } };
|
|
12
12
|
app.addHook('onRequest', async (req) => {
|
|
13
13
|
req.session = session;
|
|
14
|
+
req.user = session.passport.user;
|
|
14
15
|
});
|
|
15
16
|
// app.decorateRequest('session', session);
|
|
16
17
|
|
|
@@ -42,10 +43,7 @@ test('api crud xss', async (t) => {
|
|
|
42
43
|
url: `${prefix}/table/${addTokens[0]}`,
|
|
43
44
|
body: { dataset_name: '<a onClick="alert("XSS Injection")">xss injection</a>', dataset_id: '5400000' },
|
|
44
45
|
});
|
|
45
|
-
|
|
46
|
-
const rep = JSON.parse(res?.body);
|
|
47
|
-
console.log(rep);
|
|
48
|
-
assert.ok(rep.status, 409);
|
|
46
|
+
assert.equal(res?.json()?.status || res?.statusCode, 409);
|
|
49
47
|
});
|
|
50
48
|
|
|
51
49
|
await t.test('PUT /update', async () => {
|
|
@@ -54,19 +52,13 @@ test('api crud xss', async (t) => {
|
|
|
54
52
|
url: `${prefix}/table/${editTokens[0]}/${editTokens[0]}`,
|
|
55
53
|
body: { editor_id: '11', dataset_name: '<a onClick="alert("XSS Injection")">xss injection</a>' },
|
|
56
54
|
});
|
|
57
|
-
|
|
58
|
-
const rep = JSON.parse(res?.body);
|
|
59
|
-
console.log(rep);
|
|
60
|
-
assert.equal(rep.status, 409);
|
|
55
|
+
assert.equal(res.json()?.status || res?.statusCode, 409);
|
|
61
56
|
});
|
|
62
57
|
await t.test('DELETE /delete', async () => {
|
|
63
58
|
const res = await app.inject({
|
|
64
59
|
method: 'DELETE',
|
|
65
60
|
url: `${prefix}/table/gis.dataset/5400000`,
|
|
66
61
|
});
|
|
67
|
-
|
|
68
|
-
const rep = JSON.parse(res?.body);
|
|
69
|
-
console.log(rep);
|
|
70
|
-
assert.ok(rep);
|
|
62
|
+
assert.equal(res?.json()?.status || res?.statusCode, 200);
|
|
71
63
|
});
|
|
72
64
|
});
|
package/test/api/table.test.js
CHANGED
|
@@ -11,6 +11,13 @@ const table = 'test.rest_zone.table';
|
|
|
11
11
|
|
|
12
12
|
test('api table', async (t) => {
|
|
13
13
|
const app = await build(t);
|
|
14
|
+
|
|
15
|
+
const session = { passport: { user: { uid: '1', user_type: 'admin' } } };
|
|
16
|
+
app.addHook('onRequest', async (req) => {
|
|
17
|
+
req.session = session;
|
|
18
|
+
req.user = session.passport.user;
|
|
19
|
+
});
|
|
20
|
+
|
|
14
21
|
await init(pgClients.client);
|
|
15
22
|
|
|
16
23
|
const body = await getTemplate('table', table);
|