@opengis/fastify-table 1.4.20 → 1.4.22
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 +34 -13
- package/package.json +1 -1
- package/server/plugins/crud/funcs/dataDelete.js +57 -23
- package/server/plugins/crud/funcs/dataInsert.js +25 -10
- package/server/plugins/crud/funcs/dataUpdate.js +27 -5
- package/server/plugins/extra/extraData.js +5 -3
- package/server/plugins/extra/extraDataGet.js +2 -14
- package/server/routes/crud/controllers/insert.js +1 -1
- package/server/routes/crud/controllers/update.js +1 -1
- package/server/routes/logger/controllers/utils/checkUserAccess.js +1 -1
package/config.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import dotenv from 'dotenv';
|
|
2
|
+
import path from 'node:path';
|
|
2
3
|
|
|
3
4
|
import { existsSync, readFileSync } from 'node:fs';
|
|
4
5
|
|
|
@@ -16,19 +17,39 @@ Object.assign(config, {
|
|
|
16
17
|
env: process.env?.NODE_ENV || process.argv[2]?.split?.('=')?.pop?.(),
|
|
17
18
|
});
|
|
18
19
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
20
|
+
function loadEnvConfig() {
|
|
21
|
+
if (config.env && existsSync(`.env.${config.env}`)) {
|
|
22
|
+
const { parsed } = dotenv.config({ path: `.env.${config.env}` });
|
|
23
|
+
if (parsed) {
|
|
24
|
+
console.log('start with env:', config.env);
|
|
25
|
+
|
|
26
|
+
const obj = unflattenObject(parsed);
|
|
27
|
+
|
|
28
|
+
Object.keys(obj || {})
|
|
29
|
+
.filter(key => typeof obj[key] === 'string'
|
|
30
|
+
&& (obj[key].startsWith('[') || ['true', 'false'].includes(obj[key]))) // json array / boolean
|
|
31
|
+
.forEach(key => {
|
|
32
|
+
try {
|
|
33
|
+
obj[key] = JSON.parse(obj[key]);
|
|
34
|
+
}
|
|
35
|
+
catch (err) {
|
|
36
|
+
console.warn(`Invalid JSON for key "${key}": ${obj[key]}`);
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
if (obj) {
|
|
40
|
+
Object.assign(config, obj);
|
|
41
|
+
console.log('env init success', config.env, config.pg?.database);
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
console.log('env init error', config.env, config.pg?.database);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
console.error('env init error: malformed file', config.env);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
32
51
|
}
|
|
33
52
|
|
|
53
|
+
loadEnvConfig();
|
|
54
|
+
|
|
34
55
|
export default config;
|
package/package.json
CHANGED
|
@@ -11,7 +11,7 @@ import logger from '../../logger/getLogger.js';
|
|
|
11
11
|
const rclient = getRedis();
|
|
12
12
|
|
|
13
13
|
export default async function dataDelete({
|
|
14
|
-
table, tokenData, referer, id, pg: pg1, uid,
|
|
14
|
+
table: table1, tokenData, referer, id, pg: pg1, uid,
|
|
15
15
|
}) {
|
|
16
16
|
const pg = pg1 || getPG({ name: 'client' });
|
|
17
17
|
|
|
@@ -24,33 +24,67 @@ export default async function dataDelete({
|
|
|
24
24
|
pg.pk = pgClients.client?.pk;
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
const
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
});
|
|
32
|
-
throw new Error(err);
|
|
33
|
-
});
|
|
34
|
-
const table1 = table.replace(/"/g, '');
|
|
27
|
+
const table = table1.replace(/"/g, '');
|
|
28
|
+
|
|
29
|
+
const { pk } = await getMeta({ pg, table });
|
|
30
|
+
|
|
35
31
|
if (!pg.tlist?.includes(table1)) return 'table not exist';
|
|
32
|
+
|
|
36
33
|
const delQuery = `delete from ${table} WHERE ${pk}::text = $1::text returning *`;
|
|
37
34
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
35
|
+
// for transactions
|
|
36
|
+
const isClient = typeof pg.query === 'function' && typeof pg.release === 'function';
|
|
37
|
+
const client = isClient ? pg : await pg.connect();
|
|
38
|
+
|
|
39
|
+
if (!isClient) {
|
|
40
|
+
client.caller = 'dataDelete';
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (isClient || !client.pk) {
|
|
44
|
+
client.options = pg.options;
|
|
45
|
+
client.tlist = pg.tlist;
|
|
46
|
+
client.pgType = pg.pgType;
|
|
47
|
+
client.relkinds = pg.relkinds;
|
|
48
|
+
client.pk = pg.pk;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
try {
|
|
52
|
+
if (client.caller === 'dataDelete') {
|
|
53
|
+
await client.query('begin;');
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const row = {};
|
|
57
|
+
await extraData({
|
|
58
|
+
table, form: tokenData?.form, id, uid, row,
|
|
59
|
+
}, client);
|
|
60
|
+
|
|
61
|
+
const res = await client.query(delQuery, [id])
|
|
62
|
+
.then(el => (el.rows?.[0] ? { rowCount: 1, ...el.rows[0] } : {}));
|
|
63
|
+
|
|
64
|
+
await logChanges({
|
|
65
|
+
pg: client, table, tokenData, referer, id, uid, type: 'DELETE',
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
if (config.redis) { rclient.incr(`pg:${table}:crud`); }
|
|
69
|
+
|
|
70
|
+
if (client.caller === 'dataDelete') {
|
|
71
|
+
await client.query('commit;');
|
|
72
|
+
}
|
|
41
73
|
|
|
42
|
-
|
|
43
|
-
|
|
74
|
+
return { ...res, ...row };
|
|
75
|
+
}
|
|
76
|
+
catch (err) {
|
|
44
77
|
logger.file('crud/delete', {
|
|
45
|
-
error: err.toString(), stack: err.stack, table, id, referer, uid,
|
|
78
|
+
error: err.toString(), stack: err.stack, table, id, referer, uid, form: tokenData?.form,
|
|
46
79
|
});
|
|
80
|
+
if (client.caller === 'dataDelete') {
|
|
81
|
+
await client.query('rollback;');
|
|
82
|
+
}
|
|
47
83
|
throw err;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
if (config.redis) { rclient.incr(`pg:${table}:crud`); }
|
|
55
|
-
return { ...res, ...extraRes || {} };
|
|
84
|
+
}
|
|
85
|
+
finally {
|
|
86
|
+
if (client.caller === 'dataDelete') {
|
|
87
|
+
await client.query('begin;');
|
|
88
|
+
}
|
|
89
|
+
}
|
|
56
90
|
}
|
|
@@ -15,6 +15,7 @@ export default async function dataInsert({
|
|
|
15
15
|
id, table: table1, referer, data, pg: pg1, uid, tokenData = {},
|
|
16
16
|
}) {
|
|
17
17
|
const pg = pg1 || getPG({ name: 'client' });
|
|
18
|
+
if (!pg) return null;
|
|
18
19
|
|
|
19
20
|
// pg client single transaction support
|
|
20
21
|
if (!pg?.pk && config.pg) {
|
|
@@ -38,16 +39,24 @@ export default async function dataInsert({
|
|
|
38
39
|
if (!insertQuery || !args.length) return null;
|
|
39
40
|
|
|
40
41
|
// for transactions
|
|
41
|
-
const
|
|
42
|
+
const isClient = typeof pg.query === 'function' && typeof pg.release === 'function';
|
|
43
|
+
const client = isClient ? pg : await pg.connect();
|
|
44
|
+
if (!isClient) {
|
|
45
|
+
client.caller = 'dataInsert';
|
|
46
|
+
}
|
|
42
47
|
|
|
43
|
-
client.
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
+
if (isClient || !client.pk) {
|
|
49
|
+
client.options = pg.options;
|
|
50
|
+
client.tlist = pg.tlist;
|
|
51
|
+
client.pgType = pg.pgType;
|
|
52
|
+
client.relkinds = pg.relkinds;
|
|
53
|
+
client.pk = pg.pk;
|
|
54
|
+
}
|
|
48
55
|
|
|
49
56
|
try {
|
|
50
|
-
|
|
57
|
+
if (client.caller === 'dataInsert') {
|
|
58
|
+
await client.query('begin;');
|
|
59
|
+
}
|
|
51
60
|
const res = await client.query(insertQuery, args).then(el => el || {});
|
|
52
61
|
|
|
53
62
|
const id1 = res.rows?.[0]?.[pg.pk[table1]];
|
|
@@ -98,17 +107,23 @@ export default async function dataInsert({
|
|
|
98
107
|
});
|
|
99
108
|
|
|
100
109
|
if (config.redis) { rclient.incr(`pg:${table}:crud`); }
|
|
101
|
-
|
|
110
|
+
if (client.caller === 'dataInsert') {
|
|
111
|
+
await client.query('commit;');
|
|
112
|
+
}
|
|
102
113
|
return res;
|
|
103
114
|
}
|
|
104
115
|
catch (err) {
|
|
105
116
|
logger.file('crud/insert', {
|
|
106
117
|
error: err.toString(), stack: err.stack, table, id, referer, uid, form: tokenData?.form,
|
|
107
118
|
});
|
|
108
|
-
|
|
119
|
+
if (client.caller === 'dataInsert') {
|
|
120
|
+
await client.query('rollback;');
|
|
121
|
+
}
|
|
109
122
|
throw err;
|
|
110
123
|
}
|
|
111
124
|
finally {
|
|
112
|
-
client.
|
|
125
|
+
if (client.caller === 'dataInsert') {
|
|
126
|
+
client.release();
|
|
127
|
+
}
|
|
113
128
|
}
|
|
114
129
|
}
|
|
@@ -29,6 +29,7 @@ export default async function dataUpdate({
|
|
|
29
29
|
if (!data || !table || !id) return null;
|
|
30
30
|
|
|
31
31
|
const pg = pg1 || getPG({ name: 'client' });
|
|
32
|
+
if (!pg) return null;
|
|
32
33
|
|
|
33
34
|
// pg client single transaction support
|
|
34
35
|
if (!pg?.pk && config.pg) {
|
|
@@ -75,10 +76,25 @@ export default async function dataUpdate({
|
|
|
75
76
|
// console.log(updateQuery, filterValue);
|
|
76
77
|
|
|
77
78
|
// for transactions
|
|
78
|
-
const
|
|
79
|
+
const isClient = typeof pg.query === 'function' && typeof pg.release === 'function';
|
|
80
|
+
const client = isClient ? pg : await pg.connect();
|
|
81
|
+
|
|
82
|
+
if (!isClient) {
|
|
83
|
+
client.caller = 'dataUpdate';
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
if (isClient || !client.pk) {
|
|
87
|
+
client.options = pg.options;
|
|
88
|
+
client.tlist = pg.tlist;
|
|
89
|
+
client.pgType = pg.pgType;
|
|
90
|
+
client.relkinds = pg.relkinds;
|
|
91
|
+
client.pk = pg.pk;
|
|
92
|
+
}
|
|
79
93
|
|
|
80
94
|
try {
|
|
81
|
-
|
|
95
|
+
if (client.caller === 'dataUpdate') {
|
|
96
|
+
await client.query('begin;');
|
|
97
|
+
}
|
|
82
98
|
const res = await client.query(updateQuery, [id, ...filterValue])
|
|
83
99
|
.catch(err => {
|
|
84
100
|
logger.file('crud/update', {
|
|
@@ -145,17 +161,23 @@ export default async function dataUpdate({
|
|
|
145
161
|
|
|
146
162
|
if (config.redis) { rclient.incr(`pg:${table}:crud`); }
|
|
147
163
|
|
|
148
|
-
|
|
164
|
+
if (client.caller === 'dataUpdate') {
|
|
165
|
+
await client.query('commit;');
|
|
166
|
+
}
|
|
149
167
|
return res || {};
|
|
150
168
|
}
|
|
151
169
|
catch (err) {
|
|
152
170
|
logger.file('crud/update', {
|
|
153
171
|
error: err.toString(), stack: err.stack, table, id, referer, uid, form: tokenData?.form,
|
|
154
172
|
});
|
|
155
|
-
|
|
173
|
+
if (client.caller === 'dataUpdate') {
|
|
174
|
+
await client.query('rollback;');
|
|
175
|
+
}
|
|
156
176
|
throw err;
|
|
157
177
|
}
|
|
158
178
|
finally {
|
|
159
|
-
client.
|
|
179
|
+
if (client.caller === 'dataUpdate') {
|
|
180
|
+
client.release();
|
|
181
|
+
}
|
|
160
182
|
}
|
|
161
183
|
}
|
|
@@ -9,7 +9,7 @@ const defaultTable = 'crm.extra_data';
|
|
|
9
9
|
function format(key, value, schema) {
|
|
10
10
|
if (!key || !schema?.[key]) return value;
|
|
11
11
|
if (schema?.[key]?.type && ['Number', 'Switcher'].includes(schema?.[key]?.type)) {
|
|
12
|
-
return JSON.parse(value
|
|
12
|
+
return typeof value === 'string' ? JSON.parse(value) : value;
|
|
13
13
|
}
|
|
14
14
|
return value;
|
|
15
15
|
}
|
|
@@ -45,7 +45,9 @@ export default async function extraData({
|
|
|
45
45
|
const deleteRes = await pg.query(`delete from ${extraTable} where object_id=$1 and property_key = any($2::text[]) returning *`, [id, Object.keys(loadTemplate?.schema || {})]);
|
|
46
46
|
|
|
47
47
|
if (!data) {
|
|
48
|
-
|
|
48
|
+
const result = deleteRes?.rows?.reduce?.((acc, curr) => Object.assign(acc, { [curr.property_key]: format(curr.property_key, curr.value_text || curr.value_array, loadTemplate?.schema) }), {}) || {};
|
|
49
|
+
Object.assign(row, result);
|
|
50
|
+
return result;
|
|
49
51
|
}
|
|
50
52
|
|
|
51
53
|
const rows = Object.keys(data || {})
|
|
@@ -70,7 +72,7 @@ export default async function extraData({
|
|
|
70
72
|
}));
|
|
71
73
|
|
|
72
74
|
Object.assign(row, {
|
|
73
|
-
...res.reduce((acc, curr) => Object.assign(acc, { [curr.property_key]: format(curr.property_key, curr.value_text
|
|
75
|
+
...res.reduce((acc, curr) => Object.assign(acc, { [curr.property_key]: format(curr.property_key, curr.value_text || curr.value_array, loadTemplate?.schema) }), {}),
|
|
74
76
|
id: res?.[0]?.object_id,
|
|
75
77
|
});
|
|
76
78
|
return row;
|
|
@@ -44,21 +44,9 @@ export default async function extraDataGet({
|
|
|
44
44
|
rows.forEach(row => {
|
|
45
45
|
Object.assign(row, {
|
|
46
46
|
...extraRows
|
|
47
|
-
.filter(el => el.object_id === row.id)
|
|
47
|
+
.filter(el => el.object_id === row.id && (el.value_text || el.value_array))
|
|
48
48
|
.reduce((acc, curr) => {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
if (curr.value_text !== null) {
|
|
52
|
-
value = curr.value_text;
|
|
53
|
-
}
|
|
54
|
-
else if (curr.value_array !== null) {
|
|
55
|
-
value = curr.value_array;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
if (value !== null) {
|
|
59
|
-
acc[curr.property_key] = format(curr.property_key, value, loadTemplate?.schema);
|
|
60
|
-
}
|
|
61
|
-
|
|
49
|
+
acc[curr.property_key] = format(curr.property_key, curr.value_text || curr.value_array, loadTemplate?.schema);
|
|
62
50
|
return acc;
|
|
63
51
|
}, {}),
|
|
64
52
|
});
|
|
@@ -32,7 +32,7 @@ export default async function insert(req, reply) {
|
|
|
32
32
|
return reply.status(400).send('invalid token');
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
if (!actions.includes('add') && !config.local) {
|
|
35
|
+
if (!actions.includes('add') && !config.local && !tokenData) {
|
|
36
36
|
return reply.status(403).send('access restricted: actions');
|
|
37
37
|
}
|
|
38
38
|
|
|
@@ -36,7 +36,7 @@ export default async function update(req, reply) {
|
|
|
36
36
|
return reply.status(400).send('invalid token');
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
-
if (!actions.includes('edit') && !config.local) {
|
|
39
|
+
if (!actions.includes('edit') && !config.local && !tokenData) {
|
|
40
40
|
return reply.status(403).send('access restricted: actions');
|
|
41
41
|
}
|
|
42
42
|
|
|
@@ -13,7 +13,7 @@ export default function checkUserAccess({ user = {}, token }) {
|
|
|
13
13
|
return { message: 'access granted', status: 200 };
|
|
14
14
|
}
|
|
15
15
|
// console.log(user);
|
|
16
|
-
if (user.user_type
|
|
16
|
+
if (!user.user_type?.includes?.('admin') && !config?.local && !config.auth?.disable) {
|
|
17
17
|
return { message: 'access restricted', status: 403 };
|
|
18
18
|
}
|
|
19
19
|
|