@opengis/fastify-table 1.1.30 → 1.1.32
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 +1 -1
- package/README.md +26 -26
- package/config.js +10 -10
- package/cron/controllers/cronApi.js +22 -22
- package/cron/controllers/utils/cronList.js +1 -1
- package/cron/funcs/addCron.js +131 -131
- package/cron/index.js +10 -10
- package/crud/controllers/insert.js +1 -1
- package/crud/controllers/update.js +1 -1
- package/crud/controllers/utils/checkXSS.js +45 -45
- package/crud/controllers/utils/xssInjection.js +72 -72
- package/crud/funcs/getToken.js +27 -27
- package/crud/funcs/isFileExists.js +13 -13
- package/crud/funcs/setToken.js +53 -53
- package/index.js +18 -2
- package/logger/createFileStream.js +58 -0
- package/logger/getHooks.js +15 -0
- package/logger/getLogger.js +29 -0
- package/logger/labels.js +11 -0
- package/logger/logger.test.api.js +41 -0
- package/logger/serializers.js +24 -0
- package/notification/controllers/testEmail.js +49 -49
- package/notification/funcs/utils/sendEmail.js +39 -39
- package/package.json +3 -1
- package/pg/funcs/getPG.js +30 -30
- package/redis/funcs/getRedis.js +23 -23
- package/server/migrations/log.sql +80 -80
- package/server/migrations/properties.sql +90 -72
- package/server/migrations/roles.sql +2 -0
- package/server.js +18 -14
- package/table/controllers/card.js +44 -44
- package/table/controllers/form.js +28 -28
- package/test/api/crud.xss.test.js +72 -72
- package/test/config.example +18 -18
- package/test/funcs/pg.test.js +34 -34
- package/test/funcs/redis.test.js +19 -19
- package/test/templates/cls/test.json +9 -9
- package/test/templates/form/cp_building.form.json +32 -32
- package/test/templates/select/account_id.json +3 -3
- package/test/templates/select/storage.data.json +2 -2
- package/test/templates/table/gis.dataset.table.json +20 -20
- package/util/controllers/logger.file.js +91 -90
- package/util/controllers/next.id.js +4 -4
- package/util/controllers/properties.get.js +19 -19
- package/util/controllers/utils/checkUserAccess.js +17 -19
- package/util/controllers/utils/getRootDir.js +22 -21
- package/util/index.js +23 -23
- package/utils.js +2 -0
|
@@ -1,72 +1,72 @@
|
|
|
1
|
-
const xssInjection = [
|
|
2
|
-
'onkeypress=',
|
|
3
|
-
'onkeyup=',
|
|
4
|
-
'ondblclick=',
|
|
5
|
-
'onerror=',
|
|
6
|
-
'onmouseover=',
|
|
7
|
-
'<meta',
|
|
8
|
-
'<script',
|
|
9
|
-
'vascript:',
|
|
10
|
-
'onkeydown=',
|
|
11
|
-
'onmousedown=',
|
|
12
|
-
'onmouseenter=',
|
|
13
|
-
'onmouseleave=',
|
|
14
|
-
'onmousemove=',
|
|
15
|
-
'onmouseout=',
|
|
16
|
-
'onmouseup=',
|
|
17
|
-
'onmousewheel=',
|
|
18
|
-
'onpaste=',
|
|
19
|
-
'onscroll=',
|
|
20
|
-
'onwheel=',
|
|
21
|
-
'javascript:',
|
|
22
|
-
'\\x',
|
|
23
|
-
'eval(',
|
|
24
|
-
'onmouseover=',
|
|
25
|
-
'action=',
|
|
26
|
-
'xlink:',
|
|
27
|
-
'allowscriptaccess',
|
|
28
|
-
'href=',
|
|
29
|
-
'behavior:',
|
|
30
|
-
'onreadystatechange=',
|
|
31
|
-
'onstart=',
|
|
32
|
-
'offline=',
|
|
33
|
-
'onabort=',
|
|
34
|
-
'onafterprint=',
|
|
35
|
-
'onbeforeonload=',
|
|
36
|
-
'onbeforeprint=',
|
|
37
|
-
'onblur=',
|
|
38
|
-
'oncanplay=',
|
|
39
|
-
'oncanplaythrough=',
|
|
40
|
-
'onchange=',
|
|
41
|
-
'onclick=',
|
|
42
|
-
'oncontextmenu=',
|
|
43
|
-
'ondblclick=',
|
|
44
|
-
'ondrag=',
|
|
45
|
-
'ondragend=',
|
|
46
|
-
'ondragenter=',
|
|
47
|
-
'ondragleave=',
|
|
48
|
-
'ondragover=',
|
|
49
|
-
'ondragstart=',
|
|
50
|
-
'ondrop=',
|
|
51
|
-
'ondurationchange=',
|
|
52
|
-
'onemptied=',
|
|
53
|
-
'onended=',
|
|
54
|
-
'onerror=',
|
|
55
|
-
'onfocus=',
|
|
56
|
-
'onformchange=',
|
|
57
|
-
'onforminput=',
|
|
58
|
-
'onhaschange=',
|
|
59
|
-
'oninput=',
|
|
60
|
-
'oninvalid=',
|
|
61
|
-
'onkeydown=',
|
|
62
|
-
'onkeypress=',
|
|
63
|
-
'onkeyup=',
|
|
64
|
-
'onload=',
|
|
65
|
-
'onloadeddata=',
|
|
66
|
-
'onloadedmetadata=',
|
|
67
|
-
'onloadstart=',
|
|
68
|
-
'alert(',
|
|
69
|
-
'script:',
|
|
70
|
-
];
|
|
71
|
-
|
|
72
|
-
export default xssInjection;
|
|
1
|
+
const xssInjection = [
|
|
2
|
+
'onkeypress=',
|
|
3
|
+
'onkeyup=',
|
|
4
|
+
'ondblclick=',
|
|
5
|
+
'onerror=',
|
|
6
|
+
'onmouseover=',
|
|
7
|
+
'<meta',
|
|
8
|
+
'<script',
|
|
9
|
+
'vascript:',
|
|
10
|
+
'onkeydown=',
|
|
11
|
+
'onmousedown=',
|
|
12
|
+
'onmouseenter=',
|
|
13
|
+
'onmouseleave=',
|
|
14
|
+
'onmousemove=',
|
|
15
|
+
'onmouseout=',
|
|
16
|
+
'onmouseup=',
|
|
17
|
+
'onmousewheel=',
|
|
18
|
+
'onpaste=',
|
|
19
|
+
'onscroll=',
|
|
20
|
+
'onwheel=',
|
|
21
|
+
'javascript:',
|
|
22
|
+
'\\x',
|
|
23
|
+
'eval(',
|
|
24
|
+
'onmouseover=',
|
|
25
|
+
'action=',
|
|
26
|
+
'xlink:',
|
|
27
|
+
'allowscriptaccess',
|
|
28
|
+
'href=',
|
|
29
|
+
'behavior:',
|
|
30
|
+
'onreadystatechange=',
|
|
31
|
+
'onstart=',
|
|
32
|
+
'offline=',
|
|
33
|
+
'onabort=',
|
|
34
|
+
'onafterprint=',
|
|
35
|
+
'onbeforeonload=',
|
|
36
|
+
'onbeforeprint=',
|
|
37
|
+
'onblur=',
|
|
38
|
+
'oncanplay=',
|
|
39
|
+
'oncanplaythrough=',
|
|
40
|
+
'onchange=',
|
|
41
|
+
'onclick=',
|
|
42
|
+
'oncontextmenu=',
|
|
43
|
+
'ondblclick=',
|
|
44
|
+
'ondrag=',
|
|
45
|
+
'ondragend=',
|
|
46
|
+
'ondragenter=',
|
|
47
|
+
'ondragleave=',
|
|
48
|
+
'ondragover=',
|
|
49
|
+
'ondragstart=',
|
|
50
|
+
'ondrop=',
|
|
51
|
+
'ondurationchange=',
|
|
52
|
+
'onemptied=',
|
|
53
|
+
'onended=',
|
|
54
|
+
'onerror=',
|
|
55
|
+
'onfocus=',
|
|
56
|
+
'onformchange=',
|
|
57
|
+
'onforminput=',
|
|
58
|
+
'onhaschange=',
|
|
59
|
+
'oninput=',
|
|
60
|
+
'oninvalid=',
|
|
61
|
+
'onkeydown=',
|
|
62
|
+
'onkeypress=',
|
|
63
|
+
'onkeyup=',
|
|
64
|
+
'onload=',
|
|
65
|
+
'onloadeddata=',
|
|
66
|
+
'onloadedmetadata=',
|
|
67
|
+
'onloadstart=',
|
|
68
|
+
'alert(',
|
|
69
|
+
'script:',
|
|
70
|
+
];
|
|
71
|
+
|
|
72
|
+
export default xssInjection;
|
package/crud/funcs/getToken.js
CHANGED
|
@@ -1,27 +1,27 @@
|
|
|
1
|
-
import getRedis from '../../redis/funcs/getRedis.js';
|
|
2
|
-
import config from '../../config.js';
|
|
3
|
-
|
|
4
|
-
function sprintf(str, ...args) {
|
|
5
|
-
return str.replace(/%s/g, () => args.shift());
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
const keys = {
|
|
9
|
-
r: '%s:token:view:%s',
|
|
10
|
-
a: '%s:token:add:%s',
|
|
11
|
-
w: '%s:token:edit:%s',
|
|
12
|
-
e: '%s:token:exec:%s',
|
|
13
|
-
};
|
|
14
|
-
|
|
15
|
-
async function getToken({
|
|
16
|
-
uid, token, mode = 'r', json,
|
|
17
|
-
}) {
|
|
18
|
-
if (mode === 'r') return token;
|
|
19
|
-
|
|
20
|
-
const rclient = getRedis({ db: 0 });
|
|
21
|
-
|
|
22
|
-
const key = sprintf(keys[mode], config?.pg?.database, uid?.toString());
|
|
23
|
-
const id = await rclient.hget(key, token);
|
|
24
|
-
return json && id?.[0] === '{' ? JSON.parse(id) : id;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export default getToken;
|
|
1
|
+
import getRedis from '../../redis/funcs/getRedis.js';
|
|
2
|
+
import config from '../../config.js';
|
|
3
|
+
|
|
4
|
+
function sprintf(str, ...args) {
|
|
5
|
+
return str.replace(/%s/g, () => args.shift());
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
const keys = {
|
|
9
|
+
r: '%s:token:view:%s',
|
|
10
|
+
a: '%s:token:add:%s',
|
|
11
|
+
w: '%s:token:edit:%s',
|
|
12
|
+
e: '%s:token:exec:%s',
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
async function getToken({
|
|
16
|
+
uid, token, mode = 'r', json,
|
|
17
|
+
}) {
|
|
18
|
+
if (mode === 'r') return token;
|
|
19
|
+
|
|
20
|
+
const rclient = getRedis({ db: 0 });
|
|
21
|
+
|
|
22
|
+
const key = sprintf(keys[mode], config?.pg?.database, uid?.toString());
|
|
23
|
+
const id = await rclient.hget(key, token);
|
|
24
|
+
return json && id?.[0] === '{' ? JSON.parse(id) : id;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export default getToken;
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import { access } from 'fs/promises';
|
|
2
|
-
|
|
3
|
-
const isFileExists = async (filepath) => {
|
|
4
|
-
try {
|
|
5
|
-
await access(filepath);
|
|
6
|
-
return true;
|
|
7
|
-
}
|
|
8
|
-
catch (err) {
|
|
9
|
-
return false;
|
|
10
|
-
}
|
|
11
|
-
};
|
|
12
|
-
|
|
13
|
-
export default isFileExists;
|
|
1
|
+
import { access } from 'fs/promises';
|
|
2
|
+
|
|
3
|
+
const isFileExists = async (filepath) => {
|
|
4
|
+
try {
|
|
5
|
+
await access(filepath);
|
|
6
|
+
return true;
|
|
7
|
+
}
|
|
8
|
+
catch (err) {
|
|
9
|
+
return false;
|
|
10
|
+
}
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export default isFileExists;
|
package/crud/funcs/setToken.js
CHANGED
|
@@ -1,53 +1,53 @@
|
|
|
1
|
-
import { createHash, randomUUID } from 'crypto';
|
|
2
|
-
|
|
3
|
-
import config from '../../config.js';
|
|
4
|
-
import getRedis from '../../redis/funcs/getRedis.js';
|
|
5
|
-
|
|
6
|
-
const generateCodes = (ids, userToken) => {
|
|
7
|
-
const token = userToken || randomUUID();
|
|
8
|
-
const notNullIds = ids.filter((el) => el);
|
|
9
|
-
const obj = {};
|
|
10
|
-
const codes = notNullIds.reduce((acc, id) => {
|
|
11
|
-
const newToken = createHash('sha1').update(token + id).digest('base64url').replace(/-/g, '');
|
|
12
|
-
acc[newToken] = id; obj[id] = newToken;
|
|
13
|
-
return acc;
|
|
14
|
-
}, {});
|
|
15
|
-
return { codes, obj };
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
function setToken({
|
|
19
|
-
ids: idsOrigin, mode = 'r', uid, referer, array,
|
|
20
|
-
}) {
|
|
21
|
-
const rclient2 = getRedis({ db: 0 });
|
|
22
|
-
// const rclient5 = getRedis({ db: 0, funcs });
|
|
23
|
-
|
|
24
|
-
if (!uid) return { user: 'empty' };
|
|
25
|
-
if (!Object.keys(idsOrigin).length) return { ids: 'empty' };
|
|
26
|
-
|
|
27
|
-
const ids = idsOrigin.map((el) => (typeof el === 'object' ? JSON.stringify(el) : el));
|
|
28
|
-
// update/delete
|
|
29
|
-
|
|
30
|
-
if (mode === 'r') return null;
|
|
31
|
-
|
|
32
|
-
// TODO generate salt
|
|
33
|
-
const { codes, obj } = generateCodes(ids, uid);
|
|
34
|
-
|
|
35
|
-
if (!Object.keys(codes).length) return { ids: 'empty' };
|
|
36
|
-
|
|
37
|
-
rclient2.hmset(`${config.pg.database}:token:${{
|
|
38
|
-
e: 'exec', r: 'view', w: 'edit', a: 'add',
|
|
39
|
-
}[mode]}:${uid}`, codes);
|
|
40
|
-
|
|
41
|
-
// log token for debug. add extra data - uid, mode, date
|
|
42
|
-
/* const dt = new Date().toISOString();
|
|
43
|
-
const codesLog = Object.keys(codes).reduce((acc, key) => {
|
|
44
|
-
acc[key] = `{"referer": "${referer}" ,"uid":"${uid}","mode":"${mode}","date":"${dt}",${codes[key].substr(1)}`;
|
|
45
|
-
return acc;
|
|
46
|
-
}, {});
|
|
47
|
-
rclient5.hmset(`${config.pg.database}:token:edit`, codesLog); // 'EX', 64800 */
|
|
48
|
-
|
|
49
|
-
// TODO дополнительно писать в hset token -> uid
|
|
50
|
-
return array ? Object.values(obj) : obj;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
export default setToken;
|
|
1
|
+
import { createHash, randomUUID } from 'crypto';
|
|
2
|
+
|
|
3
|
+
import config from '../../config.js';
|
|
4
|
+
import getRedis from '../../redis/funcs/getRedis.js';
|
|
5
|
+
|
|
6
|
+
const generateCodes = (ids, userToken) => {
|
|
7
|
+
const token = userToken || randomUUID();
|
|
8
|
+
const notNullIds = ids.filter((el) => el);
|
|
9
|
+
const obj = {};
|
|
10
|
+
const codes = notNullIds.reduce((acc, id) => {
|
|
11
|
+
const newToken = createHash('sha1').update(token + id).digest('base64url').replace(/-/g, '');
|
|
12
|
+
acc[newToken] = id; obj[id] = newToken;
|
|
13
|
+
return acc;
|
|
14
|
+
}, {});
|
|
15
|
+
return { codes, obj };
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
function setToken({
|
|
19
|
+
ids: idsOrigin, mode = 'r', uid, referer, array,
|
|
20
|
+
}) {
|
|
21
|
+
const rclient2 = getRedis({ db: 0 });
|
|
22
|
+
// const rclient5 = getRedis({ db: 0, funcs });
|
|
23
|
+
|
|
24
|
+
if (!uid) return { user: 'empty' };
|
|
25
|
+
if (!Object.keys(idsOrigin).length) return { ids: 'empty' };
|
|
26
|
+
|
|
27
|
+
const ids = idsOrigin.map((el) => (typeof el === 'object' ? JSON.stringify(el) : el));
|
|
28
|
+
// update/delete
|
|
29
|
+
|
|
30
|
+
if (mode === 'r') return null;
|
|
31
|
+
|
|
32
|
+
// TODO generate salt
|
|
33
|
+
const { codes, obj } = generateCodes(ids, uid);
|
|
34
|
+
|
|
35
|
+
if (!Object.keys(codes).length) return { ids: 'empty' };
|
|
36
|
+
|
|
37
|
+
rclient2.hmset(`${config.pg.database}:token:${{
|
|
38
|
+
e: 'exec', r: 'view', w: 'edit', a: 'add',
|
|
39
|
+
}[mode]}:${uid}`, codes);
|
|
40
|
+
|
|
41
|
+
// log token for debug. add extra data - uid, mode, date
|
|
42
|
+
/* const dt = new Date().toISOString();
|
|
43
|
+
const codesLog = Object.keys(codes).reduce((acc, key) => {
|
|
44
|
+
acc[key] = `{"referer": "${referer}" ,"uid":"${uid}","mode":"${mode}","date":"${dt}",${codes[key].substr(1)}`;
|
|
45
|
+
return acc;
|
|
46
|
+
}, {});
|
|
47
|
+
rclient5.hmset(`${config.pg.database}:token:edit`, codesLog); // 'EX', 64800 */
|
|
48
|
+
|
|
49
|
+
// TODO дополнительно писать в hset token -> uid
|
|
50
|
+
return array ? Object.values(obj) : obj;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export default setToken;
|
package/index.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
|
-
import { existsSync, readdirSync, readFileSync } from 'node:fs';
|
|
2
|
+
// import { existsSync, readdirSync, readFileSync } from 'node:fs';
|
|
3
3
|
import { fileURLToPath } from 'node:url';
|
|
4
4
|
|
|
5
5
|
import fp from 'fastify-plugin';
|
|
6
|
+
|
|
6
7
|
import config from './config.js';
|
|
7
8
|
// import rclient from './redis/client.js';
|
|
8
9
|
|
|
@@ -17,7 +18,7 @@ import utilPlugin from './util/index.js';
|
|
|
17
18
|
import cronPlugin from './cron/index.js';
|
|
18
19
|
import userPlugin from './user/index.js';
|
|
19
20
|
|
|
20
|
-
import pgClients from './pg/pgClients.js';
|
|
21
|
+
// import pgClients from './pg/pgClients.js';
|
|
21
22
|
|
|
22
23
|
import { addTemplateDir, execMigrations } from './utils.js';
|
|
23
24
|
|
|
@@ -49,6 +50,21 @@ async function plugin(fastify, opt) {
|
|
|
49
50
|
return filepath;
|
|
50
51
|
});
|
|
51
52
|
|
|
53
|
+
fastify.setErrorHandler((error, request, reply) => {
|
|
54
|
+
// console.log(error)
|
|
55
|
+
debugger;
|
|
56
|
+
if (error.validation) {
|
|
57
|
+
// request.log.warn(request, { code: error?.code, status: 422, error: error.toString() });
|
|
58
|
+
const { params, instancePath } = error.validation?.[0] || {};
|
|
59
|
+
return reply.status(422).send(`invalid params: ${instancePath?.substring(1)} (${params?.pattern})`);
|
|
60
|
+
}
|
|
61
|
+
if (error.stack?.startsWith('Error: unhandled exception')) {
|
|
62
|
+
return reply.status(500).send('ServerError');
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return reply.status(error.statusCode || 500).send(error);
|
|
66
|
+
});
|
|
67
|
+
|
|
52
68
|
// core migrations
|
|
53
69
|
await execMigrations();
|
|
54
70
|
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
const streams = {}
|
|
3
|
+
|
|
4
|
+
import { createStream } from 'rotating-file-stream';
|
|
5
|
+
import labels from './labels.js';
|
|
6
|
+
|
|
7
|
+
import config from '../config.js';
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
const generator = (opt) => () => {
|
|
11
|
+
|
|
12
|
+
const date = new Date();
|
|
13
|
+
const tzOffset = date.getTimezoneOffset();
|
|
14
|
+
const currentTimeWithTimezome = date - tzOffset * 60 * 1000;
|
|
15
|
+
|
|
16
|
+
if (opt.interval === '1h') {
|
|
17
|
+
return `${new Date(currentTimeWithTimezome).toISOString().substring(0, 13).replace(/:/g, '_')}.log`;
|
|
18
|
+
}
|
|
19
|
+
if (opt.interval === '1m') {
|
|
20
|
+
return `${new Date(currentTimeWithTimezome).toISOString().substring(0, 16).replace(/:/g, '_')}.log`;
|
|
21
|
+
}
|
|
22
|
+
if (!opt.interval || opt.interval === '1d') {
|
|
23
|
+
return `${new Date(currentTimeWithTimezome).toISOString().split('T')[0].replace(/:/g, '_')}.log`;
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
const { dir = 'log', interval = '1d', compress = 'gzip', maxFiles = 90, local: teeToStdout } = config?.log || {};
|
|
28
|
+
function createFileStream({ level }) {
|
|
29
|
+
console.log(dir, level, generator({ interval })(), interval, compress);
|
|
30
|
+
const params = {
|
|
31
|
+
maxFiles, // logs to save limit
|
|
32
|
+
history: 'history', // history file name
|
|
33
|
+
interval, // rotate daily
|
|
34
|
+
compress, // compress rotated files
|
|
35
|
+
teeToStdout, // debug / logs to stdout
|
|
36
|
+
path: `${dir}/${level}`, // absolute path (root directory)
|
|
37
|
+
intervalBoundary: true, // true - log name with lower boundary of rotation interval
|
|
38
|
+
initialRotation: true, // true - log rotation check on init
|
|
39
|
+
// intervalUTC: true, // local tz -> utc
|
|
40
|
+
};
|
|
41
|
+
return createStream(generator({ interval }), params);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
import build from 'pino-abstract-transport'
|
|
46
|
+
|
|
47
|
+
export default function () {
|
|
48
|
+
return build(function (source) {
|
|
49
|
+
source.on('data', function (obj) {
|
|
50
|
+
// console.log(obj)
|
|
51
|
+
const lvl = obj.msg?.file || obj.file || labels[obj.level];
|
|
52
|
+
streams[lvl] = streams[lvl] || createFileStream({ level: lvl })
|
|
53
|
+
streams[lvl].write(JSON.stringify(obj) + '\n');
|
|
54
|
+
})
|
|
55
|
+
}, {
|
|
56
|
+
parseLine: (line) => JSON.parse(line)
|
|
57
|
+
})
|
|
58
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
function getHooks() {
|
|
2
|
+
return {
|
|
3
|
+
logMethod(inputArgs, method) {
|
|
4
|
+
|
|
5
|
+
// string name param to object
|
|
6
|
+
|
|
7
|
+
if (inputArgs?.length === 2 && inputArgs[1].originalUrl) {
|
|
8
|
+
return method.apply(this, [inputArgs[1], inputArgs[0]]);
|
|
9
|
+
}
|
|
10
|
+
return method.apply(this, inputArgs);
|
|
11
|
+
}
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export default getHooks;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import pino from 'pino';
|
|
2
|
+
// import path from 'node:path';
|
|
3
|
+
|
|
4
|
+
import config from '../config.js';
|
|
5
|
+
|
|
6
|
+
if (!config.log) config.log = {};
|
|
7
|
+
|
|
8
|
+
// utils
|
|
9
|
+
import getHooks from './getHooks.js';
|
|
10
|
+
import serializers from './serializers.js';
|
|
11
|
+
|
|
12
|
+
const level = config.log?.level || process.env.PINO_LOG_LEVEL || 'info';
|
|
13
|
+
|
|
14
|
+
const options = {
|
|
15
|
+
level, // minimal log level to write
|
|
16
|
+
timestamp: pino.stdTimeFunctions.isoTime, // timestamp as isostring
|
|
17
|
+
hooks: getHooks(),
|
|
18
|
+
serializers, // custom log params
|
|
19
|
+
transport: {
|
|
20
|
+
targets: [{
|
|
21
|
+
target: './createFileStream.js', // path.resolve('utils/createFileStream.js')
|
|
22
|
+
}],
|
|
23
|
+
},
|
|
24
|
+
};
|
|
25
|
+
const logger = pino(options);
|
|
26
|
+
logger.file = function userFile(file, msg, req) {
|
|
27
|
+
logger.info({ file, ...(typeof msg === 'string' ? { msg } : msg) }, req);
|
|
28
|
+
};
|
|
29
|
+
export default logger;
|
package/logger/labels.js
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { rename } from 'fs/promises';
|
|
2
|
+
|
|
3
|
+
export default async function testLog(request) {
|
|
4
|
+
// error handler
|
|
5
|
+
if (request.query?.rejection) {
|
|
6
|
+
rename('/data/local/test', '/data/local/test.txt');
|
|
7
|
+
}
|
|
8
|
+
if (request.query?.awaitRejection) {
|
|
9
|
+
await rename('/data/local/test', '/data/local/test.txt');
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
// default pino log
|
|
13
|
+
// request.log.info({ name: 'custom', test: 'param name and object log - info', status: 200 });
|
|
14
|
+
/* request.log.info('string info log');
|
|
15
|
+
//request.log.warn({ name: 'custom', test: 'param name and object log - warn', status: 400 });
|
|
16
|
+
request.log.warn('string warn log');
|
|
17
|
+
//request.log.debug({ name: 'custom', test: 'param name and object log - debug', status: 200 });
|
|
18
|
+
request.log.debug('string debug log');
|
|
19
|
+
//request.log.error({ name: 'custom', test: 'param name and object log - error', status: 200 });
|
|
20
|
+
//request.log.error('string error log');
|
|
21
|
+
request.log.fatal({ name: 'custom', test: 'param name and object log - fatal', status: 200 });
|
|
22
|
+
//request.log.fatal('string fatal log'); */
|
|
23
|
+
// custom params
|
|
24
|
+
|
|
25
|
+
request.log.info(request, { file: 'test', msg: 'string debug log' });
|
|
26
|
+
request.log.info({ file: 'test', msg: 'string debug log1' }, request);
|
|
27
|
+
|
|
28
|
+
request.log.file('test1', 'my message', request);
|
|
29
|
+
/* request.log.error('policy and string log1');
|
|
30
|
+
request.log.error({ test: 'policy and string log1' });
|
|
31
|
+
request.log.error(request, { test: 'string name and object log', status: 502 });
|
|
32
|
+
request.log.error(request, 'policy and string log1'); */
|
|
33
|
+
|
|
34
|
+
// request.log.error(request, { test: 'policy and object error log', status: 500 });
|
|
35
|
+
// request.log.error(request, 'policy and string log2');
|
|
36
|
+
|
|
37
|
+
/// throw new Error('222');
|
|
38
|
+
d / 0;
|
|
39
|
+
// throw new Error('unhandled exception');
|
|
40
|
+
return { root: true };
|
|
41
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
const serializers = {
|
|
2
|
+
req(request) {
|
|
3
|
+
|
|
4
|
+
const { method, url, referer, params, query, body, session } = request;
|
|
5
|
+
const { uid = undefined, user_name = undefined } = session?.passport?.user || {};
|
|
6
|
+
return {
|
|
7
|
+
method,
|
|
8
|
+
url,
|
|
9
|
+
referer,
|
|
10
|
+
ip: request.headers?.['x-real-ip']
|
|
11
|
+
|| request.headers?.['x-forwarded-for']
|
|
12
|
+
|| request.ip
|
|
13
|
+
|| request.connection?.remoteAddress,
|
|
14
|
+
uid,
|
|
15
|
+
dbName: request.pg?.options?.database,
|
|
16
|
+
user_name,
|
|
17
|
+
params,
|
|
18
|
+
query,
|
|
19
|
+
body,
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export default serializers;
|
|
@@ -1,49 +1,49 @@
|
|
|
1
|
-
import path from 'path';
|
|
2
|
-
import { existsSync } from 'fs';
|
|
3
|
-
import { fileURLToPath } from 'url';
|
|
4
|
-
|
|
5
|
-
const fileName = fileURLToPath(import.meta.url);
|
|
6
|
-
const dirName = path.dirname(fileName);
|
|
7
|
-
|
|
8
|
-
import notification from '../funcs/sendNotification.js';
|
|
9
|
-
|
|
10
|
-
export default async function testNotification({
|
|
11
|
-
pg, funcs = {}, log, query = {}, session = {},
|
|
12
|
-
}) {
|
|
13
|
-
const { local } = funcs.config || {};
|
|
14
|
-
if (!session?.passport?.user?.user_type?.includes('admin') && !local) {
|
|
15
|
-
return { message: 'Forbidden', status: 403 };
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
const date = new Date().toISOString().split('T')[0];
|
|
19
|
-
if (!query.to) {
|
|
20
|
-
return { message: 'param to is required', status: 400 };
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
try {
|
|
24
|
-
const {
|
|
25
|
-
to, template, table, id, nocache,
|
|
26
|
-
} = query;
|
|
27
|
-
const file = [path.join(dirName, '../../', 'changelog.md'), path.join(dirName, 'utils', 'pin-m-ty-media-record-outline+303070.png')].filter((el) => existsSync(el));
|
|
28
|
-
const data = await notification({
|
|
29
|
-
pg,
|
|
30
|
-
funcs,
|
|
31
|
-
log,
|
|
32
|
-
to,
|
|
33
|
-
template,
|
|
34
|
-
title: `Test Softpro ${date}`,
|
|
35
|
-
table,
|
|
36
|
-
nocache,
|
|
37
|
-
file,
|
|
38
|
-
id,
|
|
39
|
-
message: `Test mail Softpro ${date} Lorem Ipsum Lorem Ipsum`,
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
return {
|
|
43
|
-
message: data || 'ok',
|
|
44
|
-
};
|
|
45
|
-
}
|
|
46
|
-
catch (err) {
|
|
47
|
-
return { error: err.toString(), status: 500 };
|
|
48
|
-
}
|
|
49
|
-
}
|
|
1
|
+
import path from 'path';
|
|
2
|
+
import { existsSync } from 'fs';
|
|
3
|
+
import { fileURLToPath } from 'url';
|
|
4
|
+
|
|
5
|
+
const fileName = fileURLToPath(import.meta.url);
|
|
6
|
+
const dirName = path.dirname(fileName);
|
|
7
|
+
|
|
8
|
+
import notification from '../funcs/sendNotification.js';
|
|
9
|
+
|
|
10
|
+
export default async function testNotification({
|
|
11
|
+
pg, funcs = {}, log, query = {}, session = {},
|
|
12
|
+
}) {
|
|
13
|
+
const { local } = funcs.config || {};
|
|
14
|
+
if (!session?.passport?.user?.user_type?.includes('admin') && !local) {
|
|
15
|
+
return { message: 'Forbidden', status: 403 };
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const date = new Date().toISOString().split('T')[0];
|
|
19
|
+
if (!query.to) {
|
|
20
|
+
return { message: 'param to is required', status: 400 };
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
try {
|
|
24
|
+
const {
|
|
25
|
+
to, template, table, id, nocache,
|
|
26
|
+
} = query;
|
|
27
|
+
const file = [path.join(dirName, '../../', 'changelog.md'), path.join(dirName, 'utils', 'pin-m-ty-media-record-outline+303070.png')].filter((el) => existsSync(el));
|
|
28
|
+
const data = await notification({
|
|
29
|
+
pg,
|
|
30
|
+
funcs,
|
|
31
|
+
log,
|
|
32
|
+
to,
|
|
33
|
+
template,
|
|
34
|
+
title: `Test Softpro ${date}`,
|
|
35
|
+
table,
|
|
36
|
+
nocache,
|
|
37
|
+
file,
|
|
38
|
+
id,
|
|
39
|
+
message: `Test mail Softpro ${date} Lorem Ipsum Lorem Ipsum`,
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
return {
|
|
43
|
+
message: data || 'ok',
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
catch (err) {
|
|
47
|
+
return { error: err.toString(), status: 500 };
|
|
48
|
+
}
|
|
49
|
+
}
|