@opengis/fastify-table 1.4.6 → 1.4.7
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/config.js +25 -3
- package/index.js +1 -0
- package/package.json +5 -2
- package/server/plugins/crud/funcs/dataDelete.js +1 -1
- package/server/plugins/extra/extraDataGet.js +6 -5
- package/server/plugins/util/funcs/flattenObject.js +11 -0
- package/server/plugins/util/funcs/unflattenObject.js +14 -0
- package/server/routes/crud/controllers/deleteCrud.js +15 -5
- package/server/routes/crud/controllers/insert.js +10 -4
- package/server/routes/crud/controllers/table.js +7 -3
- package/server/routes/crud/controllers/update.js +8 -4
- package/server/routes/menu/controllers/getMenu.js +2 -2
- package/server/routes/table/controllers/cardData.js +8 -8
- package/server/routes/table/functions/getData.js +3 -3
- package/utils.js +6 -0
package/config.js
CHANGED
|
@@ -1,11 +1,33 @@
|
|
|
1
|
-
import
|
|
1
|
+
import dotenv from 'dotenv';
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
const config = fileName ? JSON.parse(fs.readFileSync(fileName)) : {};
|
|
3
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
5
4
|
|
|
5
|
+
import unflattenObject from './server/plugins/util/funcs/unflattenObject.js';
|
|
6
|
+
|
|
7
|
+
const fileName = ['config.json', '/data/local/config.json'].find(el => (existsSync(el) ? el : null));
|
|
8
|
+
const config = fileName ? JSON.parse(readFileSync(fileName)) : {};
|
|
9
|
+
|
|
10
|
+
// npm run dev === cross-env NODE_ENV=development
|
|
11
|
+
// alt: node --env=development
|
|
6
12
|
Object.assign(config, {
|
|
7
13
|
allTemplates: config?.allTemplates || {},
|
|
8
14
|
skipCheckPolicyRoutes: [],
|
|
15
|
+
env: process.env?.NODE_ENV || process.argv[2]?.split?.('=')?.pop?.(),
|
|
9
16
|
});
|
|
10
17
|
|
|
18
|
+
if (config.env && existsSync(`.env.${config.env}`)) {
|
|
19
|
+
const { parsed } = dotenv.config({ path: `.env.${config.env}` });
|
|
20
|
+
console.log('start with env:', config.env);
|
|
21
|
+
|
|
22
|
+
const obj = unflattenObject(parsed);
|
|
23
|
+
|
|
24
|
+
Object.keys(obj)
|
|
25
|
+
.filter(key => typeof obj[key] === 'string'
|
|
26
|
+
&& (obj[key].startsWith('[') || ['true', 'false'].includes(obj[key]))) // json array / boolean
|
|
27
|
+
.forEach(key => {
|
|
28
|
+
obj[key] = JSON.parse(obj[key]);
|
|
29
|
+
});
|
|
30
|
+
Object.assign(config, { ...obj });
|
|
31
|
+
}
|
|
32
|
+
|
|
11
33
|
export default config;
|
package/index.js
CHANGED
|
@@ -113,5 +113,6 @@ async function plugin(fastify, opt) {
|
|
|
113
113
|
templatesRoutes(fastify, opt);
|
|
114
114
|
|
|
115
115
|
fastify.get('/api/test-proxy', {}, (req) => ({ ...req.headers || {}, sessionId: req.session?.sessionId }));
|
|
116
|
+
fastify.get('/api/config', { config: { policy: ['admin', 'site'] } }, () => config);
|
|
116
117
|
}
|
|
117
118
|
export default fp(plugin);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@opengis/fastify-table",
|
|
3
|
-
"version": "1.4.
|
|
3
|
+
"version": "1.4.7",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "core-plugins",
|
|
6
6
|
"keywords": [
|
|
@@ -25,10 +25,12 @@
|
|
|
25
25
|
"test:helpers": "node --test .\\test\\helpers",
|
|
26
26
|
"test:routes": "node --test .\\test\\routes",
|
|
27
27
|
"test:functions": "node --test .\\test\\functions",
|
|
28
|
-
"compress": "node compress.js"
|
|
28
|
+
"compress": "node compress.js",
|
|
29
|
+
"dev": "cross-env NODE_ENV=development node server.js"
|
|
29
30
|
},
|
|
30
31
|
"dependencies": {
|
|
31
32
|
"@fastify/http-proxy": "11.1.2",
|
|
33
|
+
"dotenv": "16.5.0",
|
|
32
34
|
"fastify": "5.3.3",
|
|
33
35
|
"fastify-plugin": "5.0.1",
|
|
34
36
|
"handlebars": "4.7.8",
|
|
@@ -43,6 +45,7 @@
|
|
|
43
45
|
"uglify-js": "3.19.3"
|
|
44
46
|
},
|
|
45
47
|
"devDependencies": {
|
|
48
|
+
"cross-env": "7.0.3",
|
|
46
49
|
"eslint": "8.49.0",
|
|
47
50
|
"eslint-config-airbnb": "19.0.4"
|
|
48
51
|
},
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { config, getTemplate, pgClients } from
|
|
1
|
+
import { config, getTemplate, pgClients } from '../../../utils.js';
|
|
2
2
|
|
|
3
3
|
const defaultTable = 'crm.extra_data';
|
|
4
4
|
|
|
@@ -24,7 +24,7 @@ export default async function extraDataGet({
|
|
|
24
24
|
|
|
25
25
|
const extraDataTable = config.extraData?.[table]
|
|
26
26
|
|| config.extraData?.[table.split('.').shift()]
|
|
27
|
-
|| config.extraData?.
|
|
27
|
+
|| config.extraData?.default
|
|
28
28
|
|| config.extraData
|
|
29
29
|
|| defaultTable;
|
|
30
30
|
|
|
@@ -44,9 +44,10 @@ export default async function extraDataGet({
|
|
|
44
44
|
...extraRows
|
|
45
45
|
.filter(el => el.object_id === row.id)
|
|
46
46
|
.reduce((acc, curr) => Object.assign(acc, {
|
|
47
|
-
[curr.property_key]: format(curr.property_key, curr.value_text, loadTemplate?.schema)
|
|
48
|
-
}), {})
|
|
47
|
+
[curr.property_key]: format(curr.property_key, curr.value_text, loadTemplate?.schema),
|
|
48
|
+
}), {}),
|
|
49
49
|
});
|
|
50
50
|
});
|
|
51
51
|
}
|
|
52
|
-
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export default function flattenObject(obj = {}, keys, parent = '') {
|
|
2
|
+
return Object.keys(obj).reduce((acc, key) => {
|
|
3
|
+
const newKey = parent ? `${parent}.${key}` : key;
|
|
4
|
+
if (typeof obj[key] === 'object' && obj[key] !== null && !Array.isArray(obj[key])) {
|
|
5
|
+
Object.assign(acc, flattenObject(obj[key], keys, newKey));
|
|
6
|
+
} else if (keys ? keys.includes(newKey) : true) {
|
|
7
|
+
acc[newKey] = obj[key];
|
|
8
|
+
}
|
|
9
|
+
return acc;
|
|
10
|
+
}, {});
|
|
11
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export default function unflattenObject(flatObj) {
|
|
2
|
+
return Object.keys(flatObj).reduce((acc, key) => {
|
|
3
|
+
const keys = key.split('.');
|
|
4
|
+
keys.reduce((nestedObj, part, index) => {
|
|
5
|
+
if (index === keys.length - 1) {
|
|
6
|
+
nestedObj[part] = flatObj[key];
|
|
7
|
+
} else {
|
|
8
|
+
nestedObj[part] = nestedObj[part] || {};
|
|
9
|
+
}
|
|
10
|
+
return nestedObj[part];
|
|
11
|
+
}, acc);
|
|
12
|
+
return acc;
|
|
13
|
+
}, {});
|
|
14
|
+
}
|
|
@@ -17,21 +17,31 @@ export default async function deleteCrud(req, reply) {
|
|
|
17
17
|
|
|
18
18
|
const { referer } = headers;
|
|
19
19
|
const tokenData = await getToken({
|
|
20
|
-
uid: user.uid, token: params.table, json: 1,
|
|
20
|
+
uid: user.uid, token: params.id || params.table, json: 1,
|
|
21
21
|
});
|
|
22
22
|
|
|
23
|
-
const { table: del, id } = hookData || tokenData || (config.auth?.disable ? req.params : {});
|
|
23
|
+
const { table: del, id } = hookData || tokenData || (config.security?.disableToken || config.local || config.auth?.disable ? req.params : {});
|
|
24
24
|
const { actions = [] } = await getAccess({ table: del, id, user }, pg) || {};
|
|
25
25
|
|
|
26
|
-
if (!
|
|
26
|
+
if (!tokenData && !config?.local && !config.security?.disableToken && !config.auth?.disable) {
|
|
27
|
+
return reply.status(400).send('invalid token');
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
if (!actions.includes('del') && !config?.local) {
|
|
27
31
|
return reply.status(403).send('access restricted');
|
|
28
32
|
}
|
|
33
|
+
|
|
29
34
|
const loadTemplate = await getTemplate('table', del);
|
|
30
35
|
|
|
31
36
|
const { table } = loadTemplate || hookData || tokenData || req.params || {};
|
|
32
37
|
|
|
33
|
-
if (!table)
|
|
34
|
-
|
|
38
|
+
if (!table) {
|
|
39
|
+
return reply.status(404).send('table is required');
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if (!id) {
|
|
43
|
+
return reply.status(404).send('id is required');
|
|
44
|
+
}
|
|
35
45
|
|
|
36
46
|
const data = await dataDelete({
|
|
37
47
|
pg, table, id, uid: user?.uid, tokenData, referer,
|
|
@@ -19,15 +19,20 @@ export default async function insert(req, reply) {
|
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
const { referer } = headers;
|
|
22
|
+
|
|
22
23
|
const tokenData = await getToken({
|
|
23
24
|
uid: user?.uid, token: params.table, mode: 'a', json: 1,
|
|
24
25
|
});
|
|
25
26
|
|
|
26
|
-
const { form, table: add } = hookData || tokenData || (config.auth?.disable ? req.params : {});
|
|
27
|
+
const { form, table: add } = hookData || tokenData || (config.security?.disableToken || config.local || config.auth?.disable ? req.params : {});
|
|
27
28
|
|
|
28
29
|
const { actions = [] } = await getAccess({ table: add, user }, pg) || {};
|
|
29
30
|
|
|
30
|
-
if (!
|
|
31
|
+
if (!tokenData && !config.local && !config.security?.disableToken && !config.auth?.disable) {
|
|
32
|
+
return reply.status(400).send('invalid token');
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
if (!actions.includes('add') && !config.local) {
|
|
31
36
|
return reply.status(403).send('access restricted');
|
|
32
37
|
}
|
|
33
38
|
|
|
@@ -37,8 +42,9 @@ export default async function insert(req, reply) {
|
|
|
37
42
|
|
|
38
43
|
const loadTemplate = await getTemplate('table', add);
|
|
39
44
|
const { table } = loadTemplate || hookData || tokenData || req.params || {};
|
|
45
|
+
|
|
40
46
|
if (!table) {
|
|
41
|
-
return
|
|
47
|
+
return reply.status(404).send('table not found');
|
|
42
48
|
}
|
|
43
49
|
|
|
44
50
|
const formData = form || loadTemplate?.form ? (await getTemplate('form', form || loadTemplate?.form) || {}) : {};
|
|
@@ -110,5 +116,5 @@ export default async function insert(req, reply) {
|
|
|
110
116
|
}
|
|
111
117
|
|
|
112
118
|
const pk = pg.pk?.[loadTemplate?.table || table];
|
|
113
|
-
return { id: res?.rows?.[0]?.[pk], rows: res.rows, extra: res.extra };
|
|
119
|
+
return reply.status(200).send({ id: res?.rows?.[0]?.[pk], rows: res.rows, extra: res.extra });
|
|
114
120
|
}
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
|
|
5
5
|
import extraDataGet from '../../../plugins/extra/extraDataGet.js';
|
|
6
6
|
|
|
7
|
-
export default async function tableAPI(req) {
|
|
7
|
+
export default async function tableAPI(req, reply) {
|
|
8
8
|
const {
|
|
9
9
|
pg = pgClients.client, params, user = {}, query = {},
|
|
10
10
|
} = req;
|
|
@@ -38,7 +38,11 @@ export default async function tableAPI(req) {
|
|
|
38
38
|
|
|
39
39
|
const { actions = [], query: accessQuery } = await getAccess({ table: templateName, id, user }, pg) || {};
|
|
40
40
|
|
|
41
|
-
if (!
|
|
41
|
+
if (!tokenData && !config?.local && !config.security?.disableToken) {
|
|
42
|
+
return reply.status(400).send('invalid token');
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (!actions.includes('edit') && !config?.local) {
|
|
42
46
|
return reply.status(403).send('access restricted');
|
|
43
47
|
}
|
|
44
48
|
|
|
@@ -94,7 +98,7 @@ export default async function tableAPI(req) {
|
|
|
94
98
|
Object.assign(data, { [key]: extraRows });
|
|
95
99
|
}));
|
|
96
100
|
}
|
|
97
|
-
if (user?.uid && actions
|
|
101
|
+
if (user?.uid && !config.security?.disableToken && actions.includes('edit')) {
|
|
98
102
|
data.token = tokenData?.table ? params.table : setToken({
|
|
99
103
|
ids: [JSON.stringify({ id, table: tableName, form: loadTable.form })],
|
|
100
104
|
uid: user.uid,
|
|
@@ -23,14 +23,18 @@ export default async function update(req, reply) {
|
|
|
23
23
|
|
|
24
24
|
const { referer } = headers;
|
|
25
25
|
const tokenData = await getToken({
|
|
26
|
-
uid: user.uid, token: body.token || params.table, mode: 'w', json: 1,
|
|
26
|
+
uid: user.uid, token: body.token || params.id || params.table, mode: 'w', json: 1,
|
|
27
27
|
});
|
|
28
28
|
|
|
29
|
-
const { form, table: edit, id } = hookData || tokenData || (config.auth?.disable ? params : {});
|
|
29
|
+
const { form, table: edit, id } = hookData || tokenData || (config.security?.disableToken || config.local || config.auth?.disable ? params : {});
|
|
30
30
|
|
|
31
31
|
const { actions = [] } = await getAccess({ table: edit, id, user }, pg) || {};
|
|
32
32
|
|
|
33
|
-
if (!
|
|
33
|
+
if (!tokenData && !config.local && !config.security?.disableToken && !config.auth?.disable) {
|
|
34
|
+
return reply.status(400).send('invalid token');
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if (!actions.includes('edit') && !config.local) {
|
|
34
38
|
return reply.status(403).send('access restricted');
|
|
35
39
|
}
|
|
36
40
|
|
|
@@ -114,5 +118,5 @@ export default async function update(req, reply) {
|
|
|
114
118
|
}));
|
|
115
119
|
}
|
|
116
120
|
|
|
117
|
-
return res;
|
|
121
|
+
return reply.status(200).send(res);
|
|
118
122
|
}
|
|
@@ -5,7 +5,7 @@ import { join } from 'node:path';
|
|
|
5
5
|
import { existsSync, readdirSync, readFileSync } from 'node:fs';
|
|
6
6
|
|
|
7
7
|
import {
|
|
8
|
-
|
|
8
|
+
menuDirs, pgClients, applyHook, config,
|
|
9
9
|
} from '../../../../utils.js';
|
|
10
10
|
|
|
11
11
|
const menuCache = [];
|
|
@@ -63,7 +63,7 @@ export default async function adminMenu({
|
|
|
63
63
|
};
|
|
64
64
|
await applyHook('userMenu', result);
|
|
65
65
|
|
|
66
|
-
if (session && user?.uid && !user.user_type?.includes?.('admin') && !user.type?.includes?.('admin') && pg.pk['admin.role_access']) {
|
|
66
|
+
if (session && user?.uid && !user.user_type?.includes?.('admin') && !user.type?.includes?.('admin') && pg.pk?.['admin.role_access']) {
|
|
67
67
|
const { type, gl = [], routes = [] } = await pg.query(`select user_type as type, b.gl,routes from admin.users a
|
|
68
68
|
left join lateral (
|
|
69
69
|
select array_agg(role_id) as gl from admin.user_roles
|
|
@@ -2,10 +2,9 @@
|
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
|
|
4
4
|
import {
|
|
5
|
-
getAccess, handlebars, setOpt, setToken, getTemplate, handlebarsSync, applyHook,
|
|
5
|
+
config, getAccess, handlebars, setOpt, setToken, getTemplate, handlebarsSync, applyHook, getData,
|
|
6
6
|
} from '../../../../utils.js';
|
|
7
7
|
|
|
8
|
-
import getTableData from './tableData.js';
|
|
9
8
|
import conditions from './utils/conditions.js';
|
|
10
9
|
|
|
11
10
|
const components = {
|
|
@@ -15,8 +14,9 @@ const components = {
|
|
|
15
14
|
|
|
16
15
|
export default async function getCardData(req, reply) {
|
|
17
16
|
const {
|
|
18
|
-
pg, params = {},
|
|
17
|
+
pg, params = {}, user = {},
|
|
19
18
|
} = req;
|
|
19
|
+
|
|
20
20
|
const { table, id } = params;
|
|
21
21
|
const { uid } = user;
|
|
22
22
|
|
|
@@ -40,11 +40,11 @@ export default async function getCardData(req, reply) {
|
|
|
40
40
|
? await pg.query(
|
|
41
41
|
`select * from ${index.table} where ${handlebarsSync.compile(index.query)({ uid, user })}`,
|
|
42
42
|
)
|
|
43
|
-
: await
|
|
44
|
-
pg,
|
|
45
|
-
});
|
|
43
|
+
: await getData({
|
|
44
|
+
pg, table, id, user,
|
|
45
|
+
}, reply);
|
|
46
46
|
|
|
47
|
-
if (message) return
|
|
47
|
+
if (message) return message;
|
|
48
48
|
|
|
49
49
|
// conditions
|
|
50
50
|
index.panels?.filter(el => el.items).forEach(el1 => {
|
|
@@ -72,7 +72,7 @@ export default async function getCardData(req, reply) {
|
|
|
72
72
|
|
|
73
73
|
// tokens result
|
|
74
74
|
const tokens = {};
|
|
75
|
-
if (index?.tokens && typeof index?.tokens === 'object' && !Array.isArray(index?.tokens)) {
|
|
75
|
+
if (!config.security?.disableToken && index?.tokens && typeof index?.tokens === 'object' && !Array.isArray(index?.tokens)) {
|
|
76
76
|
Object.keys(index.tokens || {})
|
|
77
77
|
.filter(key => index?.tokens[key]?.public
|
|
78
78
|
|| access.actions?.includes?.('edit')
|
|
@@ -188,7 +188,7 @@ export default async function dataAPI(req, reply, called) {
|
|
|
188
188
|
|
|
189
189
|
timeArr.push(Date.now());
|
|
190
190
|
|
|
191
|
-
if (uid && rows.length && editable) {
|
|
191
|
+
if (uid && rows.length && !config.security?.disableToken && (editable || actions.includes('edit') || actions.includes('del'))) {
|
|
192
192
|
rows.forEach(row => {
|
|
193
193
|
row.token = setToken({
|
|
194
194
|
ids: [JSON.stringify({ id: row.id, table: tokenData?.table || hookData?.table || params.table, form: loadTable?.form })],
|
|
@@ -245,7 +245,7 @@ export default async function dataAPI(req, reply, called) {
|
|
|
245
245
|
const tokens = {};
|
|
246
246
|
if (template && objectId) {
|
|
247
247
|
// tokens result
|
|
248
|
-
if (index?.tokens && typeof index?.tokens === 'object' && !Array.isArray(index?.tokens)) {
|
|
248
|
+
if (!config.security?.disableToken && index?.tokens && typeof index?.tokens === 'object' && !Array.isArray(index?.tokens)) {
|
|
249
249
|
Object.keys(index.tokens || {})
|
|
250
250
|
.filter(key => index?.tokens[key]?.public
|
|
251
251
|
|| actions?.includes?.('edit')
|
|
@@ -347,7 +347,7 @@ export default async function dataAPI(req, reply, called) {
|
|
|
347
347
|
}
|
|
348
348
|
|
|
349
349
|
// console.log({ add: loadTable.table, form: loadTable.form });
|
|
350
|
-
if (uid && actions.includes('add')) {
|
|
350
|
+
if (uid && !config.security?.disableToken && actions.includes('add')) {
|
|
351
351
|
const addTokens = setToken({
|
|
352
352
|
ids: [
|
|
353
353
|
JSON.stringify({
|
package/utils.js
CHANGED
|
@@ -83,6 +83,9 @@ import json2yml from './server/plugins/yml/funcs/json2yml.js';
|
|
|
83
83
|
import formatMdoc from './server/plugins/md/funcs/formatMdoc.js';
|
|
84
84
|
import mdToHTML from './server/plugins/md/funcs/mdToHTML.js';
|
|
85
85
|
|
|
86
|
+
import flattenObject from './server/plugins/util/funcs/flattenObject.js';
|
|
87
|
+
import unflattenObject from './server/plugins/util/funcs/unflattenObject.js';
|
|
88
|
+
|
|
86
89
|
export default null;
|
|
87
90
|
export {
|
|
88
91
|
config,
|
|
@@ -160,4 +163,7 @@ export {
|
|
|
160
163
|
|
|
161
164
|
formatMdoc,
|
|
162
165
|
mdToHTML,
|
|
166
|
+
|
|
167
|
+
flattenObject,
|
|
168
|
+
unflattenObject,
|
|
163
169
|
};
|