@volcanicminds/backend 2.2.6 → 2.2.8
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/dist/index.d.ts.map +1 -1
- package/dist/index.js +100 -51
- package/dist/index.js.map +1 -1
- package/dist/lib/api/auth/controller/auth.d.ts +10 -0
- package/dist/lib/api/auth/controller/auth.d.ts.map +1 -1
- package/dist/lib/api/auth/controller/auth.js +26 -4
- package/dist/lib/api/auth/controller/auth.js.map +1 -1
- package/dist/lib/api/token/controller/token.d.ts +1 -1
- package/dist/lib/api/token/controller/token.d.ts.map +1 -1
- package/dist/lib/api/token/controller/token.js +7 -5
- package/dist/lib/api/token/controller/token.js.map +1 -1
- package/dist/lib/api/users/controller/user.d.ts +2 -2
- package/dist/lib/api/users/controller/user.d.ts.map +1 -1
- package/dist/lib/api/users/controller/user.js +14 -4
- package/dist/lib/api/users/controller/user.js.map +1 -1
- package/dist/lib/apollo/resolvers.d.ts +1 -1
- package/dist/lib/apollo/resolvers.d.ts.map +1 -1
- package/dist/lib/apollo/resolvers.js +1 -1
- package/dist/lib/apollo/resolvers.js.map +1 -1
- package/dist/lib/hooks/onError.d.ts +1 -1
- package/dist/lib/hooks/onError.d.ts.map +1 -1
- package/dist/lib/hooks/onError.js +5 -3
- package/dist/lib/hooks/onError.js.map +1 -1
- package/dist/lib/hooks/onRequest.d.ts.map +1 -1
- package/dist/lib/hooks/onRequest.js +18 -2
- package/dist/lib/hooks/onRequest.js.map +1 -1
- package/dist/lib/hooks/onResponse.d.ts.map +1 -1
- package/dist/lib/hooks/onResponse.js +9 -1
- package/dist/lib/hooks/onResponse.js.map +1 -1
- package/dist/lib/loader/general.js +4 -2
- package/dist/lib/loader/general.js.map +1 -1
- package/dist/lib/loader/hooks.d.ts.map +1 -1
- package/dist/lib/loader/hooks.js +8 -4
- package/dist/lib/loader/hooks.js.map +1 -1
- package/dist/lib/loader/plugins.d.ts.map +1 -1
- package/dist/lib/loader/plugins.js +6 -3
- package/dist/lib/loader/plugins.js.map +1 -1
- package/dist/lib/loader/roles.js +4 -2
- package/dist/lib/loader/roles.js.map +1 -1
- package/dist/lib/loader/router.d.ts.map +1 -1
- package/dist/lib/loader/router.js +31 -16
- package/dist/lib/loader/router.js.map +1 -1
- package/dist/lib/loader/schedules.d.ts.map +1 -1
- package/dist/lib/loader/schedules.js +19 -10
- package/dist/lib/loader/schedules.js.map +1 -1
- package/dist/lib/loader/schemas.d.ts.map +1 -1
- package/dist/lib/loader/schemas.js +20 -10
- package/dist/lib/loader/schemas.js.map +1 -1
- package/dist/lib/loader/tracking.d.ts.map +1 -1
- package/dist/lib/loader/tracking.js +6 -3
- package/dist/lib/loader/tracking.js.map +1 -1
- package/dist/lib/loader/translation.d.ts.map +1 -1
- package/dist/lib/loader/translation.js.map +1 -1
- package/dist/lib/middleware/isAdmin.d.ts.map +1 -1
- package/dist/lib/middleware/isAdmin.js +2 -1
- package/dist/lib/middleware/isAdmin.js.map +1 -1
- package/dist/lib/middleware/isAuthenticated.d.ts.map +1 -1
- package/dist/lib/middleware/isAuthenticated.js +3 -2
- package/dist/lib/middleware/isAuthenticated.js.map +1 -1
- package/dist/lib/middleware/preAuth.d.ts +1 -1
- package/dist/lib/middleware/preAuth.d.ts.map +1 -1
- package/dist/lib/middleware/preAuth.js +1 -1
- package/dist/lib/middleware/preAuth.js.map +1 -1
- package/dist/lib/middleware/preForgotPasswordHandler.d.ts +1 -1
- package/dist/lib/middleware/preForgotPasswordHandler.d.ts.map +1 -1
- package/dist/lib/middleware/preForgotPasswordHandler.js +1 -1
- package/dist/lib/middleware/preForgotPasswordHandler.js.map +1 -1
- package/dist/lib/schemas/auth.d.ts +3 -0
- package/dist/lib/schemas/auth.d.ts.map +1 -1
- package/dist/lib/schemas/auth.js +1 -0
- package/dist/lib/schemas/auth.js.map +1 -1
- package/dist/lib/util/common.d.ts.map +1 -1
- package/dist/lib/util/common.js.map +1 -1
- package/dist/lib/util/errors.d.ts.map +1 -1
- package/dist/lib/util/errors.js.map +1 -1
- package/dist/lib/util/logger.js +1 -1
- package/dist/lib/util/logger.js.map +1 -1
- package/dist/lib/util/mark.d.ts.map +1 -1
- package/dist/lib/util/mark.js +34 -17
- package/dist/lib/util/mark.js.map +1 -1
- package/dist/lib/util/regexp.d.ts.map +1 -1
- package/dist/lib/util/regexp.js +3 -3
- package/dist/lib/util/regexp.js.map +1 -1
- package/dist/lib/util/tracker.d.ts +2 -2
- package/dist/lib/util/tracker.d.ts.map +1 -1
- package/dist/lib/util/tracker.js +6 -4
- package/dist/lib/util/tracker.js.map +1 -1
- package/dist/lib/util/yn.d.ts.map +1 -1
- package/dist/lib/util/yn.js.map +1 -1
- package/dist/server.js.map +1 -1
- package/lib/api/auth/controller/auth.ts +36 -4
- package/lib/api/token/controller/token.ts +7 -5
- package/lib/api/users/controller/user.ts +17 -4
- package/lib/apollo/resolvers.ts +2 -1
- package/lib/hooks/onError.ts +4 -3
- package/lib/hooks/onRequest.ts +21 -14
- package/lib/hooks/onResponse.ts +10 -4
- package/lib/loader/general.ts +2 -2
- package/lib/loader/hooks.ts +6 -4
- package/lib/loader/plugins.ts +4 -3
- package/lib/loader/roles.ts +2 -2
- package/lib/loader/router.ts +21 -24
- package/lib/loader/schedules.ts +23 -26
- package/lib/loader/schemas.ts +12 -10
- package/lib/loader/tracking.ts +4 -3
- package/lib/loader/translation.ts +2 -0
- package/lib/middleware/isAdmin.ts +2 -1
- package/lib/middleware/isAuthenticated.ts +3 -2
- package/lib/middleware/preAuth.ts +1 -1
- package/lib/middleware/preForgotPasswordHandler.ts +1 -1
- package/lib/schemas/auth.ts +1 -0
- package/lib/util/common.ts +1 -0
- package/lib/util/errors.ts +1 -0
- package/lib/util/logger.ts +1 -1
- package/lib/util/mark.ts +18 -17
- package/lib/util/regexp.ts +3 -3
- package/lib/util/tracker.ts +6 -4
- package/lib/util/yn.ts +1 -0
- package/package.json +11 -2
package/dist/lib/util/tracker.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import dayjs from 'dayjs';
|
|
2
|
-
export async function initialize(req,
|
|
2
|
+
export async function initialize(req, _reply) {
|
|
3
3
|
if (req.server['dataBaseManager'].isImplemented()) {
|
|
4
4
|
const tc = getTrackingConfigIfEnabled(req);
|
|
5
5
|
const allData = { ...req.parameters(), ...req.data() };
|
|
@@ -8,7 +8,8 @@ export async function initialize(req, reply) {
|
|
|
8
8
|
if (allData && tc.entity && tc.primaryKey && tc.primaryKey in allData) {
|
|
9
9
|
const key = allData[tc.primaryKey];
|
|
10
10
|
req.trackingData = await req.server['dataBaseManager'].retrieveBy(tc.entity, key);
|
|
11
|
-
log.
|
|
11
|
+
if (log.t)
|
|
12
|
+
log.trace(`Tracking changes: found id ${req.trackingData ? req.trackingData[tc.primaryKey] : null}`);
|
|
12
13
|
}
|
|
13
14
|
}
|
|
14
15
|
catch (error) {
|
|
@@ -18,7 +19,7 @@ export async function initialize(req, reply) {
|
|
|
18
19
|
}
|
|
19
20
|
}
|
|
20
21
|
}
|
|
21
|
-
export async function track(req,
|
|
22
|
+
export async function track(req, _reply, payload) {
|
|
22
23
|
if (req.server['dataBaseManager'].isImplemented()) {
|
|
23
24
|
const tc = getTrackingConfigIfEnabled(req);
|
|
24
25
|
if (tc) {
|
|
@@ -56,7 +57,8 @@ export async function track(req, reply, payload) {
|
|
|
56
57
|
});
|
|
57
58
|
}
|
|
58
59
|
if (addChange) {
|
|
59
|
-
log.
|
|
60
|
+
if (log.t)
|
|
61
|
+
log.trace(`Tracking changes: add ${changeEntity} for ${entity}, ${id}, ${userId}, ${status}`);
|
|
60
62
|
await req.server['dataBaseManager'].addChange(entity, id, status, userId, contents, changeEntity);
|
|
61
63
|
}
|
|
62
64
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tracker.js","sourceRoot":"","sources":["../../../lib/util/tracker.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"tracker.js","sourceRoot":"","sources":["../../../lib/util/tracker.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,OAAO,CAAA;AAGzB,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,GAAmB,EAAE,MAAoB;IACxE,IAAI,GAAG,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC,aAAa,EAAE,EAAE,CAAC;QAClD,MAAM,EAAE,GAAG,0BAA0B,CAAC,GAAG,CAAC,CAAA;QAC1C,MAAM,OAAO,GAAG,EAAE,GAAG,GAAG,CAAC,UAAU,EAAE,EAAE,GAAG,GAAG,CAAC,IAAI,EAAE,EAAE,CAAA;QAEtD,IAAI,EAAE,EAAE,CAAC;YACP,IAAI,CAAC;gBACH,IAAI,OAAO,IAAI,EAAE,CAAC,MAAM,IAAI,EAAE,CAAC,UAAU,IAAI,EAAE,CAAC,UAAU,IAAI,OAAO,EAAE,CAAC;oBACtE,MAAM,GAAG,GAAG,OAAO,CAAC,EAAE,CAAC,UAAU,CAAC,CAAA;oBAClC,GAAG,CAAC,YAAY,GAAG,MAAM,GAAG,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC,UAAU,CAAC,EAAE,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;oBACjF,IAAI,GAAG,CAAC,CAAC;wBACP,GAAG,CAAC,KAAK,CAAC,8BAA8B,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC,GAAG,CAAC,YAAY,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAA;gBACxG,CAAC;YACH,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,GAAG,CAAC,KAAK,CAAC,8BAA8B,EAAE,CAAC,IAAI,EAAE,CAAC,CAAA;gBAClD,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,CAAA;YAClB,CAAC;QACH,CAAC;IACH,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,KAAK,CAAC,GAAmB,EAAE,MAAoB,EAAE,OAAY;IACjF,IAAI,GAAG,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC,aAAa,EAAE,EAAE,CAAC;QAClD,MAAM,EAAE,GAAG,0BAA0B,CAAC,GAAG,CAAC,CAAA;QAC1C,IAAI,EAAE,EAAE,CAAC;YACP,IAAI,CAAC;gBACH,MAAM,QAAQ,GAAU,EAAE,CAAA;gBAC1B,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,GAAG,EAAE,CAAA;gBACnC,MAAM,MAAM,GAAG,GAAG,CAAC,IAAI,EAAE,KAAK,EAAE,CAAA;gBAChC,MAAM,OAAO,GAAG,GAAG,CAAC,YAAY,CAAA;gBAEhC,MAAM,MAAM,GACV,GAAG,CAAC,MAAM,EAAE,WAAW,EAAE,KAAK,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,EAAE,WAAW,EAAE,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAA;gBAEhH,MAAM,EAAE,GACN,EAAE,CAAC,UAAU,IAAI,OAAO,IAAI,EAAE,CAAC,UAAU,IAAI,OAAO;oBAClD,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,UAAU,CAAC;oBACxB,CAAC,CAAC,EAAE,CAAC,UAAU,IAAI,OAAO,IAAI,EAAE,CAAC,UAAU,IAAI,OAAO;wBACtD,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,UAAU,CAAC;wBACxB,CAAC,CAAC,SAAS,CAAA;gBAEf,IAAI,CAAC,EAAE,EAAE,CAAC;oBACR,GAAG,CAAC,KAAK,CAAC,8CAA8C,CAAC,CAAA;oBACzD,OAAM;gBACR,CAAC;gBAED,IAAI,SAAS,GAAG,KAAK,CAAA;gBACrB,IAAI,MAAM,KAAK,QAAQ,EAAE,CAAC;oBACxB,SAAS,GAAG,IAAI,CAAA;gBAClB,CAAC;qBAAM,CAAC;oBACN,MAAM,MAAM,GAAG,EAAE,CAAC,MAAM,EAAE,QAAQ,IAAI,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAA;oBAChE,MAAM,QAAQ,GAAa,EAAE,CAAC,MAAM,EAAE,QAAQ,IAAI,EAAE,CAAA;oBAEpD,MAAM,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE;wBACvB,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;4BAC9B,MAAM,QAAQ,GAAG,OAAO,IAAI,IAAI,IAAI,KAAK,IAAI,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAA;4BACjF,MAAM,QAAQ,GAAG,OAAO,IAAI,IAAI,IAAI,KAAK,IAAI,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAA;4BACjF,IAAI,QAAQ,KAAK,SAAS,IAAI,cAAc,CAAC,QAAQ,EAAE,QAAQ,CAAC,EAAE,CAAC;gCACjE,QAAQ,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,QAAQ,EAAE,GAAG,EAAE,QAAQ,EAAE,CAAC,CAAA;gCAC3D,SAAS,GAAG,IAAI,CAAA;4BAClB,CAAC;wBACH,CAAC;oBACH,CAAC,CAAC,CAAA;gBACJ,CAAC;gBAED,IAAI,SAAS,EAAE,CAAC;oBACd,IAAI,GAAG,CAAC,CAAC;wBAAE,GAAG,CAAC,KAAK,CAAC,yBAAyB,YAAY,QAAQ,MAAM,KAAK,EAAE,KAAK,MAAM,KAAK,MAAM,EAAE,CAAC,CAAA;oBACxG,MAAM,GAAG,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC,SAAS,CAAC,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,YAAY,CAAC,CAAA;gBACnG,CAAC;YACH,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,GAAG,CAAC,KAAK,CAAC,8BAA8B,EAAE,CAAC,IAAI,EAAE,CAAC,CAAA;gBAClD,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,CAAA;YAClB,CAAC;QACH,CAAC;IACH,CAAC;AACH,CAAC;AAED,SAAS,0BAA0B,CAAC,GAAG;IACrC,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,GAAG,GAAG,CAAC,MAAM,EAAE,WAAW,EAAE,KAAK,GAAG,CAAC,YAAY,EAAE,MAAM,EAAE,GAAG,IAAI,GAAG,CAAC,WAAW,EAAE,GAAG,IAAI,GAAG,CAAC,GAAG,EAAE,CAAA;QAChH,OAAO,IAAI,IAAI,MAAM,CAAC,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,GAAG,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAA;IAC5G,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,CAAA;IAClB,CAAC;AACH,CAAC;AAED,SAAS,cAAc,CAAC,QAAQ,EAAE,QAAQ;IACxC,IAAI,CAAC,QAAQ,YAAY,IAAI,IAAI,QAAQ,YAAY,IAAI,CAAC,IAAI,QAAQ,IAAI,IAAI,IAAI,QAAQ,IAAI,SAAS,EAAE,CAAC;QACxG,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAA;IACjD,CAAC;IAED,IAAI,CAAC,QAAQ,YAAY,MAAM,IAAI,QAAQ,YAAY,MAAM,CAAC,IAAI,QAAQ,IAAI,IAAI,IAAI,QAAQ,IAAI,SAAS,EAAE,CAAC;QAC5G,MAAM,UAAU,GAAG,MAAM,CAAC,cAAc,EAAE,UAAU,CAAA;QACpD,MAAM,KAAK,GACT,QAAQ,IAAI,IAAI,IAAI,UAAU,IAAI,QAAQ;YACxC,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAC;YACtB,CAAC,CAAC,OAAO,QAAQ,KAAK,QAAQ;gBAC9B,CAAC,CAAC,QAAQ;gBACV,CAAC,CAAC,SAAS,CAAA;QACf,MAAM,KAAK,GACT,QAAQ,IAAI,IAAI,IAAI,UAAU,IAAI,QAAQ;YACxC,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAC;YACtB,CAAC,CAAC,OAAO,QAAQ,KAAK,QAAQ;gBAC9B,CAAC,CAAC,QAAQ;gBACV,CAAC,CAAC,SAAS,CAAA;QACf,OAAO,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,KAAK,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,CAAA;IAC5E,CAAC;IAED,OAAO,QAAQ,IAAI,QAAQ,CAAA;AAC7B,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"yn.d.ts","sourceRoot":"","sources":["../../../lib/util/yn.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"yn.d.ts","sourceRoot":"","sources":["../../../lib/util/yn.ts"],"names":[],"mappings":"AAGA,MAAM,CAAC,OAAO,UAAU,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,YAAY,EAAE,OAAO,GAAG,OAAO,CAgBrE"}
|
package/dist/lib/util/yn.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"yn.js","sourceRoot":"","sources":["../../../lib/util/yn.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"yn.js","sourceRoot":"","sources":["../../../lib/util/yn.ts"],"names":[],"mappings":"AACA,YAAY,CAAA;AAEZ,MAAM,CAAC,OAAO,UAAU,EAAE,CAAC,KAAU,EAAE,YAAqB;IAC1D,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QAC1C,OAAO,YAAY,CAAA;IACrB,CAAC;IAED,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,CAAA;IAEhC,IAAI,wBAAwB,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;QACvC,OAAO,IAAI,CAAA;IACb,CAAC;IAED,IAAI,yBAAyB,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;QACxC,OAAO,KAAK,CAAA;IACd,CAAC;IAED,OAAO,YAAY,IAAI,KAAK,CAAA;AAC9B,CAAC"}
|
package/dist/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sourceRoot":"","sources":["../server.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../server.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAGjC;AAAC,MAAc,CAAC,qBAAqB,GAAG,IAAI,CAAA;AAE7C,KAAK,EAAE,CAAA"}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
1
2
|
import { FastifyReply, FastifyRequest } from 'fastify'
|
|
2
3
|
import * as regExp from '../../../util/regexp.js'
|
|
4
|
+
import { MfaPolicy } from '../../../../types/global.js'
|
|
3
5
|
|
|
4
6
|
export async function register(req: FastifyRequest, reply: FastifyReply) {
|
|
5
7
|
const { password1: password, password2, ...data } = req.data()
|
|
@@ -33,6 +35,7 @@ export async function register(req: FastifyRequest, reply: FastifyReply) {
|
|
|
33
35
|
}
|
|
34
36
|
}
|
|
35
37
|
|
|
38
|
+
// public is the default
|
|
36
39
|
const publicRole = global.roles?.public?.code || 'public'
|
|
37
40
|
data.roles = (data.requiredRoles || []).map((r) => global.roles[r]?.code).filter((r) => !!r)
|
|
38
41
|
if (!data.roles.includes(publicRole)) {
|
|
@@ -208,6 +211,7 @@ export async function resetPassword(req: FastifyRequest, reply: FastifyReply) {
|
|
|
208
211
|
|
|
209
212
|
export async function login(req: FastifyRequest, reply: FastifyReply) {
|
|
210
213
|
const { email, password } = req.data()
|
|
214
|
+
const { mfa_policy = MfaPolicy.OPTIONAL } = global.config.options || {}
|
|
211
215
|
|
|
212
216
|
if (!req.server['userManager'].isImplemented()) {
|
|
213
217
|
throw new Error('Not implemented')
|
|
@@ -245,11 +249,15 @@ export async function login(req: FastifyRequest, reply: FastifyReply) {
|
|
|
245
249
|
}
|
|
246
250
|
|
|
247
251
|
// MFA Logic Interception
|
|
248
|
-
|
|
252
|
+
const isMfaEnabled = user.mfaEnabled
|
|
253
|
+
const isMandatory = mfa_policy === MfaPolicy.MANDATORY
|
|
254
|
+
|
|
255
|
+
if (isMfaEnabled || isMandatory) {
|
|
249
256
|
const tempToken = await reply.jwtSign({ sub: user.externalId, role: 'pre-auth-mfa' }, { expiresIn: '5m' })
|
|
250
257
|
// Use 202 Accepted to bypass 200 OK strict schema filtering
|
|
251
258
|
return reply.status(202).send({
|
|
252
|
-
mfaRequired:
|
|
259
|
+
mfaRequired: isMfaEnabled, // If enabled, verify. If not enabled but mandatory, setup.
|
|
260
|
+
mfaSetupRequired: isMandatory && !isMfaEnabled,
|
|
253
261
|
tempToken: tempToken
|
|
254
262
|
})
|
|
255
263
|
}
|
|
@@ -258,6 +266,7 @@ export async function login(req: FastifyRequest, reply: FastifyReply) {
|
|
|
258
266
|
user = await req.server['userManager'].resetExternalId(user.getId())
|
|
259
267
|
}
|
|
260
268
|
|
|
269
|
+
// https://www.iana.org/assignments/jwt/jwt.xhtml
|
|
261
270
|
const token = await reply.jwtSign({ sub: user.externalId })
|
|
262
271
|
const refreshToken = reply.server.jwt['refreshToken']
|
|
263
272
|
? await reply.server.jwt['refreshToken'].sign({ sub: user.externalId })
|
|
@@ -379,7 +388,25 @@ export async function mfaEnable(req: FastifyRequest, reply: FastifyReply) {
|
|
|
379
388
|
await req.server['userManager'].saveMfaSecret(user.getId(), secret)
|
|
380
389
|
await req.server['userManager'].enableMfa(user.getId())
|
|
381
390
|
|
|
382
|
-
|
|
391
|
+
// IMPORTANT: Return full tokens upon enablement if user was in pending state
|
|
392
|
+
// BUT usually user is already logged in via temp token or full token.
|
|
393
|
+
// If user is setting up from "Forced Setup", they need tokens now.
|
|
394
|
+
|
|
395
|
+
const finalToken = await reply.jwtSign({ sub: user.externalId })
|
|
396
|
+
const refreshToken = reply.server.jwt['refreshToken']
|
|
397
|
+
? await reply.server.jwt['refreshToken'].sign({ sub: user.externalId })
|
|
398
|
+
: undefined
|
|
399
|
+
|
|
400
|
+
return {
|
|
401
|
+
ok: true,
|
|
402
|
+
token: finalToken,
|
|
403
|
+
refreshToken: refreshToken,
|
|
404
|
+
user: {
|
|
405
|
+
...user,
|
|
406
|
+
mfaEnabled: true,
|
|
407
|
+
roles: (user.roles || [global.role?.public?.code || 'public']).map((r) => r?.code || r)
|
|
408
|
+
}
|
|
409
|
+
}
|
|
383
410
|
} catch (error: any) {
|
|
384
411
|
req.log.error({ err: error }, 'MFA Enable failed')
|
|
385
412
|
return reply.status(500).send(new Error('Failed to enable MFA'))
|
|
@@ -394,7 +421,7 @@ export async function mfaVerify(req: FastifyRequest, reply: FastifyReply) {
|
|
|
394
421
|
let decoded: any
|
|
395
422
|
try {
|
|
396
423
|
decoded = req.server.jwt.verify(tokenStr)
|
|
397
|
-
} catch (
|
|
424
|
+
} catch (_e) {
|
|
398
425
|
return reply.status(401).send(new Error('Invalid token'))
|
|
399
426
|
}
|
|
400
427
|
|
|
@@ -438,6 +465,11 @@ export async function mfaDisable(req: FastifyRequest, reply: FastifyReply) {
|
|
|
438
465
|
const user = req.user
|
|
439
466
|
if (!user) return reply.status(401).send(new Error('Unauthorized'))
|
|
440
467
|
|
|
468
|
+
const { mfa_policy = MfaPolicy.OPTIONAL } = global.config.options || {}
|
|
469
|
+
if (mfa_policy === MfaPolicy.MANDATORY || mfa_policy === MfaPolicy.ONE_WAY) {
|
|
470
|
+
return reply.status(403).send(new Error('MFA disable is not allowed by security policy'))
|
|
471
|
+
}
|
|
472
|
+
|
|
441
473
|
try {
|
|
442
474
|
await req.server['userManager'].disableMfa(user.getId())
|
|
443
475
|
return { ok: true }
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { FastifyReply, FastifyRequest } from 'fastify'
|
|
2
2
|
|
|
3
|
-
export async function count(req: FastifyRequest,
|
|
3
|
+
export async function count(req: FastifyRequest, _reply: FastifyReply) {
|
|
4
4
|
return await req.server['tokenManager'].countQuery(req.data())
|
|
5
5
|
}
|
|
6
6
|
|
|
@@ -87,8 +87,9 @@ export async function block(req: FastifyRequest, reply: FastifyReply) {
|
|
|
87
87
|
const { id: userId } = req.parameters()
|
|
88
88
|
const { reason } = req.data()
|
|
89
89
|
|
|
90
|
-
|
|
91
|
-
|
|
90
|
+
await req.server['tokenManager'].blockTokenById(userId, reason)
|
|
91
|
+
const token = await req.server['tokenManager'].retrieveTokenById(userId)
|
|
92
|
+
return { ok: !!token.getId() }
|
|
92
93
|
}
|
|
93
94
|
|
|
94
95
|
export async function unblock(req: FastifyRequest, reply: FastifyReply) {
|
|
@@ -99,6 +100,7 @@ export async function unblock(req: FastifyRequest, reply: FastifyReply) {
|
|
|
99
100
|
}
|
|
100
101
|
|
|
101
102
|
const { id: userId } = req.parameters()
|
|
102
|
-
|
|
103
|
-
|
|
103
|
+
await req.server['tokenManager'].unblockTokenById(userId)
|
|
104
|
+
const token = await req.server['tokenManager'].retrieveTokenById(userId)
|
|
105
|
+
return { ok: !!token.getId() }
|
|
104
106
|
}
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { FastifyReply, FastifyRequest } from 'fastify'
|
|
2
2
|
import type { AuthenticatedUser } from '../../../../types/global.js'
|
|
3
|
+
import { MfaPolicy } from '../../../../types/global.js'
|
|
3
4
|
|
|
4
|
-
export async function getRoles(
|
|
5
|
+
export async function getRoles(_req: FastifyRequest, reply: FastifyReply) {
|
|
5
6
|
const allRoles = Object.keys(roles).map((key) => roles[key])
|
|
6
7
|
return reply.send(allRoles)
|
|
7
8
|
}
|
|
8
9
|
|
|
9
|
-
export async function count(req: FastifyRequest,
|
|
10
|
+
export async function count(req: FastifyRequest, _reply: FastifyReply) {
|
|
10
11
|
return req.server['userManager'].countQuery(req.data())
|
|
11
12
|
}
|
|
12
13
|
|
|
@@ -26,7 +27,7 @@ export async function create(req: FastifyRequest, reply: FastifyReply) {
|
|
|
26
27
|
return reply.status(403).send(Error('Only admins can create users'))
|
|
27
28
|
}
|
|
28
29
|
|
|
29
|
-
const { id, ...data } = req.data()
|
|
30
|
+
const { id: _id, ...data } = req.data()
|
|
30
31
|
|
|
31
32
|
if (data.roles && data.roles.includes(roles.admin)) {
|
|
32
33
|
if (!config.enable || config.options?.allow_multiple_admin !== true) {
|
|
@@ -58,7 +59,19 @@ export async function remove(req: FastifyRequest, reply: FastifyReply) {
|
|
|
58
59
|
|
|
59
60
|
export async function getCurrentUser(req: FastifyRequest, reply: FastifyReply) {
|
|
60
61
|
const user: AuthenticatedUser | undefined = req.user
|
|
61
|
-
|
|
62
|
+
const mfaPolicy = global.config.options?.mfa_policy || MfaPolicy.OPTIONAL
|
|
63
|
+
|
|
64
|
+
return reply.send(
|
|
65
|
+
user
|
|
66
|
+
? {
|
|
67
|
+
...user,
|
|
68
|
+
roles: req.roles(),
|
|
69
|
+
securityPolicy: {
|
|
70
|
+
mfaPolicy
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
: {}
|
|
74
|
+
)
|
|
62
75
|
}
|
|
63
76
|
|
|
64
77
|
export async function updateCurrentUser(req: FastifyRequest, reply: FastifyReply) {
|
package/lib/apollo/resolvers.ts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
1
2
|
'use strict'
|
|
2
3
|
|
|
3
4
|
import { MyContext } from './context.js'
|
|
4
5
|
|
|
5
6
|
const resolvers = {
|
|
6
7
|
Query: {
|
|
7
|
-
helloWorld: (
|
|
8
|
+
helloWorld: (_parent: any, _args: any, context: MyContext, _info: any) => context.greeting
|
|
8
9
|
}
|
|
9
10
|
}
|
|
10
11
|
|
package/lib/hooks/onError.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
1
2
|
import { FastifyRequest, FastifyReply } from 'fastify'
|
|
2
3
|
|
|
3
|
-
export default async (
|
|
4
|
-
log.e
|
|
5
|
-
log.t
|
|
4
|
+
export default async (_req: FastifyRequest, reply: FastifyReply, error: any) => {
|
|
5
|
+
if (log.e) log.error(`${error?.message || error}`)
|
|
6
|
+
if (log.t) log.trace(error)
|
|
6
7
|
|
|
7
8
|
if (error.statusCode && error.statusCode >= 400) {
|
|
8
9
|
return reply.code(error.statusCode).send(error)
|
package/lib/hooks/onRequest.ts
CHANGED
|
@@ -1,36 +1,32 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
1
2
|
import { getParams, getData } from '../util/common.js'
|
|
2
3
|
import type { AuthenticatedUser, AuthenticatedToken, Role } from '../../types/global.js'
|
|
3
4
|
|
|
4
5
|
const { embedded_auth = true } = global.config?.options || {}
|
|
5
6
|
|
|
7
|
+
const MFA_SETUP_WHITELIST = ['/auth/mfa/setup', '/auth/mfa/enable', '/auth/mfa/verify', '/auth/logout']
|
|
8
|
+
|
|
6
9
|
const normalizeRoles = (rolesArray: any[] | undefined): string[] => {
|
|
7
10
|
if (!rolesArray || rolesArray.length === 0) {
|
|
8
11
|
return [roles.public.code]
|
|
9
12
|
}
|
|
10
|
-
|
|
11
|
-
// Check the type of the first element to determine the array's structure
|
|
12
13
|
const firstElement = rolesArray[0]
|
|
13
14
|
if (typeof firstElement === 'string') {
|
|
14
15
|
return rolesArray as string[]
|
|
15
16
|
}
|
|
16
|
-
|
|
17
17
|
if (typeof firstElement === 'object' && firstElement !== null && 'code' in firstElement) {
|
|
18
18
|
return rolesArray.map((role: Role) => role.code)
|
|
19
19
|
}
|
|
20
|
-
|
|
21
|
-
// Fallback for unexpected formats
|
|
22
20
|
return [roles.public.code]
|
|
23
21
|
}
|
|
24
22
|
|
|
25
23
|
export default async (req, reply) => {
|
|
26
|
-
log.i
|
|
24
|
+
if (log.i) req.startedAt = new Date()
|
|
27
25
|
|
|
28
|
-
// Request enrichment
|
|
29
26
|
req.data = () => getData(req)
|
|
30
27
|
req.parameters = () => getParams(req)
|
|
31
28
|
|
|
32
29
|
if (embedded_auth) {
|
|
33
|
-
// Initialize role helpers with a default 'public' role
|
|
34
30
|
req.roles = () => [roles.public.code]
|
|
35
31
|
req.hasRole = (r: Role) => req.roles().includes(r?.code)
|
|
36
32
|
|
|
@@ -41,6 +37,22 @@ export default async (req, reply) => {
|
|
|
41
37
|
if (prefix === 'Bearer' && bearerToken != null) {
|
|
42
38
|
try {
|
|
43
39
|
const tokenData = reply.server.jwt.verify(bearerToken)
|
|
40
|
+
|
|
41
|
+
// --- MFA GATEKEEPER ---
|
|
42
|
+
if (tokenData.role === 'pre-auth-mfa') {
|
|
43
|
+
const currentUrl = req.routeOptions.url || req.raw.url
|
|
44
|
+
const isAllowed = MFA_SETUP_WHITELIST.some((url) => currentUrl.endsWith(url))
|
|
45
|
+
|
|
46
|
+
if (!isAllowed) {
|
|
47
|
+
if (log.w) log.warn(`Security Block: User attempted to access ${currentUrl} with pre-auth MFA token`)
|
|
48
|
+
return reply.status(403).send({
|
|
49
|
+
statusCode: 403,
|
|
50
|
+
code: 'MFA_REQUIRED',
|
|
51
|
+
message: 'MFA verification or setup required to access this resource'
|
|
52
|
+
})
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
44
56
|
const subjectId = tokenData?.sub
|
|
45
57
|
|
|
46
58
|
if (!subjectId) {
|
|
@@ -50,7 +62,6 @@ export default async (req, reply) => {
|
|
|
50
62
|
let user: null | AuthenticatedUser = null
|
|
51
63
|
let token: null | AuthenticatedToken = null
|
|
52
64
|
|
|
53
|
-
// Attempt to retrieve user only if userManager is implemented
|
|
54
65
|
if (req.server['userManager']?.isImplemented()) {
|
|
55
66
|
user = await req.server['userManager'].retrieveUserByExternalId(subjectId)
|
|
56
67
|
if (user) {
|
|
@@ -64,7 +75,6 @@ export default async (req, reply) => {
|
|
|
64
75
|
}
|
|
65
76
|
}
|
|
66
77
|
|
|
67
|
-
// Attempt to retrieve token if user was not found and tokenManager is implemented
|
|
68
78
|
if (!user && req.server['tokenManager']?.isImplemented()) {
|
|
69
79
|
token = await req.server['tokenManager'].retrieveTokenByExternalId(subjectId)
|
|
70
80
|
if (token) {
|
|
@@ -82,7 +92,6 @@ export default async (req, reply) => {
|
|
|
82
92
|
return reply.status(404).send({ statusCode: 404, code: 'SUBJECT_NOT_FOUND', message: 'Subject not found' })
|
|
83
93
|
}
|
|
84
94
|
|
|
85
|
-
// Re-normalize roles now that req.user or req.token is populated
|
|
86
95
|
const freshNormalizedRoles = normalizeRoles(req.user?.roles || req.token?.roles)
|
|
87
96
|
req.roles = () => freshNormalizedRoles
|
|
88
97
|
} catch (error) {
|
|
@@ -97,15 +106,13 @@ export default async (req, reply) => {
|
|
|
97
106
|
}
|
|
98
107
|
}
|
|
99
108
|
|
|
100
|
-
// Role-Based Access Control (RBAC) check
|
|
101
109
|
if (cfg.requiredRoles?.length > 0) {
|
|
102
110
|
const { method = '', url = '', requiredRoles } = cfg
|
|
103
111
|
const authorizedRoles: string[] = req.roles()
|
|
104
|
-
|
|
105
112
|
const hasPermission = requiredRoles.some((r) => authorizedRoles.includes(r.code))
|
|
106
113
|
|
|
107
114
|
if (!hasPermission) {
|
|
108
|
-
log.w
|
|
115
|
+
if (log.w) log.warn(`Forbidden: ${req.user?.email || 'anonymous'} cannot call ${method.toUpperCase()} ${url}`)
|
|
109
116
|
return reply.status(403).send({ statusCode: 403, code: 'FORBIDDEN', message: 'Authorization denied' })
|
|
110
117
|
}
|
|
111
118
|
}
|
package/lib/hooks/onResponse.ts
CHANGED
|
@@ -1,15 +1,21 @@
|
|
|
1
1
|
export default async (req, reply) => {
|
|
2
|
-
let extraMessage
|
|
2
|
+
let extraMessage = ''
|
|
3
3
|
if (log.i && req.startedAt) {
|
|
4
4
|
const elapsed: number = new Date().getTime() - req.startedAt.getTime()
|
|
5
5
|
extraMessage = `(${elapsed}ms)`
|
|
6
6
|
}
|
|
7
7
|
if (log.t) {
|
|
8
|
-
const reqSize
|
|
9
|
-
const replySize
|
|
8
|
+
const reqSize = `req ${req.payloadSize || 0}`
|
|
9
|
+
const replySize = reply.payloadSize > 0 ? ` res ${reply.payloadSize}` : ''
|
|
10
10
|
extraMessage += `[${reqSize}${replySize} bytes]`
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
const message = () => `${req.method} ${req.url} ${reply.statusCode} ${extraMessage}`.trim()
|
|
14
|
-
|
|
14
|
+
if (reply.statusCode < 300) {
|
|
15
|
+
log.info(message())
|
|
16
|
+
} else if (reply.statusCode < 400) {
|
|
17
|
+
log.warn(message())
|
|
18
|
+
} else {
|
|
19
|
+
log.error(message())
|
|
20
|
+
}
|
|
15
21
|
}
|
package/lib/loader/general.ts
CHANGED
|
@@ -17,7 +17,7 @@ export async function load() {
|
|
|
17
17
|
const patterns = normalizePatterns(['..', 'config', 'general.{ts,js}'], ['src', 'config', 'general.{ts,js}'])
|
|
18
18
|
|
|
19
19
|
for (const pattern of patterns) {
|
|
20
|
-
log.t
|
|
20
|
+
if (log.t) log.trace('Looking for ' + pattern)
|
|
21
21
|
const files = globSync(pattern, { windowsPathsNoEscape: true })
|
|
22
22
|
|
|
23
23
|
for (const f of files) {
|
|
@@ -34,6 +34,6 @@ export async function load() {
|
|
|
34
34
|
}
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
-
log.d
|
|
37
|
+
if (log.d) log.debug('General configuration loaded')
|
|
38
38
|
return generalConfig
|
|
39
39
|
}
|
package/lib/loader/hooks.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-unsafe-function-type */
|
|
2
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
1
3
|
import { normalizePatterns } from '../util/path.js'
|
|
2
4
|
import { globSync } from 'glob'
|
|
3
5
|
import path from 'path'
|
|
@@ -23,7 +25,7 @@ export async function apply(server: any): Promise<void> {
|
|
|
23
25
|
const allHooks: any = hooks.reduce((acc, v) => ({ ...acc, [v]: [] as Function[] }), {})
|
|
24
26
|
|
|
25
27
|
for (const pattern of patterns) {
|
|
26
|
-
log.t
|
|
28
|
+
if (log.t) log.trace('Looking for ' + pattern)
|
|
27
29
|
const files = globSync(pattern, { windowsPathsNoEscape: true })
|
|
28
30
|
|
|
29
31
|
for (const f of files) {
|
|
@@ -44,9 +46,9 @@ export async function apply(server: any): Promise<void> {
|
|
|
44
46
|
|
|
45
47
|
hooks.map((hookName) => {
|
|
46
48
|
const fns: Function[] = allHooks[hookName]
|
|
47
|
-
log.t
|
|
48
|
-
fns?.length > 0
|
|
49
|
+
if (log.t) log.trace(`* Add ${fns?.length || 0} hooks for ${hookName}`)
|
|
50
|
+
if (fns?.length > 0) fns.map((fn) => server.addHook(hookName, fn as Function))
|
|
49
51
|
})
|
|
50
52
|
|
|
51
|
-
log.d
|
|
53
|
+
if (log.d) log.debug(`Hooks loaded: ${hooks?.length || 0}`)
|
|
52
54
|
}
|
package/lib/loader/plugins.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
1
2
|
import { normalizePatterns } from '../util/path.js'
|
|
2
3
|
import { globSync } from 'glob'
|
|
3
4
|
|
|
@@ -7,7 +8,7 @@ export async function load() {
|
|
|
7
8
|
const patterns = normalizePatterns(['..', 'config', 'plugins.{ts,js}'], ['src', 'config', 'plugins.{ts,js}'])
|
|
8
9
|
|
|
9
10
|
for (const pattern of patterns) {
|
|
10
|
-
log.t
|
|
11
|
+
if (log.t) log.trace('Looking for ' + pattern)
|
|
11
12
|
const files = globSync(pattern, { windowsPathsNoEscape: true })
|
|
12
13
|
|
|
13
14
|
for (const f of files) {
|
|
@@ -16,12 +17,12 @@ export async function load() {
|
|
|
16
17
|
|
|
17
18
|
configPlugins.forEach((plugin) => {
|
|
18
19
|
plugins[plugin.name] = plugin.enable ? plugin.options : false
|
|
19
|
-
log.t
|
|
20
|
+
if (log.t) log.trace(`* Plugin ${plugin.name} ${plugin.enable ? 'enabled' : 'disabled'}`)
|
|
20
21
|
})
|
|
21
22
|
}
|
|
22
23
|
}
|
|
23
24
|
|
|
24
25
|
const enabledPulgins = Object.keys(plugins).filter((p) => !!plugins[p])
|
|
25
|
-
log.d
|
|
26
|
+
if (log.d) log.debug(`Plugins loaded: ${enabledPulgins.length > 0 ? enabledPulgins.join(', ') : 0}`)
|
|
26
27
|
return plugins
|
|
27
28
|
}
|
package/lib/loader/roles.ts
CHANGED
|
@@ -8,7 +8,7 @@ export async function load() {
|
|
|
8
8
|
const patterns = normalizePatterns(['..', 'config', 'roles.{ts,js}'], ['src', 'config', 'roles.{ts,js}'])
|
|
9
9
|
|
|
10
10
|
for (const pattern of patterns) {
|
|
11
|
-
log.t
|
|
11
|
+
if (log.t) log.trace('Looking for ' + pattern)
|
|
12
12
|
const files = globSync(pattern, { windowsPathsNoEscape: true })
|
|
13
13
|
|
|
14
14
|
for (const f of files) {
|
|
@@ -21,6 +21,6 @@ export async function load() {
|
|
|
21
21
|
}
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
log.d
|
|
24
|
+
if (log.d) log.debug('Roles loaded: ' + Object.keys(roles).join(', '))
|
|
25
25
|
return roles
|
|
26
26
|
}
|
package/lib/loader/router.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
1
2
|
import yn from '../util/yn.js'
|
|
2
3
|
import type { Role, Route, ConfiguredRoute, RouteConfig } from '../../types/global.js'
|
|
3
4
|
import { FastifyReply, FastifyRequest } from 'fastify'
|
|
@@ -5,7 +6,6 @@ import { normalizePatterns } from '../util/path.js'
|
|
|
5
6
|
import { globSync } from 'glob'
|
|
6
7
|
import path from 'path'
|
|
7
8
|
import { fileURLToPath } from 'url'
|
|
8
|
-
import require from '../util/require.js'
|
|
9
9
|
|
|
10
10
|
const __filename = fileURLToPath(import.meta.url)
|
|
11
11
|
const __dirname = path.dirname(__filename)
|
|
@@ -16,7 +16,7 @@ async function tryToLoadFile(fileName: string) {
|
|
|
16
16
|
try {
|
|
17
17
|
const module = await import(fileName)
|
|
18
18
|
return module.default || module
|
|
19
|
-
} catch (
|
|
19
|
+
} catch (_err) {
|
|
20
20
|
return null
|
|
21
21
|
}
|
|
22
22
|
}
|
|
@@ -28,25 +28,21 @@ async function loadMiddleware(base: string, middleware: string = '') {
|
|
|
28
28
|
|
|
29
29
|
if (isGlobal) {
|
|
30
30
|
const name = middleware.substring(key.length)
|
|
31
|
-
|
|
32
|
-
const
|
|
33
|
-
const localPathJs = path.resolve(process.cwd() + '/src/middleware/' + name + '.js') // Prova JS (dist)
|
|
31
|
+
const localPath = path.resolve(process.cwd() + '/src/middleware/' + name + '.ts')
|
|
32
|
+
const localPathJs = path.resolve(process.cwd() + '/src/middleware/' + name + '.js')
|
|
34
33
|
|
|
35
34
|
loadedModule = await tryToLoadFile(localPath)
|
|
36
35
|
if (!loadedModule) loadedModule = await tryToLoadFile(localPathJs)
|
|
37
36
|
|
|
38
|
-
// Se non trova locale, prova interno alla lib
|
|
39
37
|
if (!loadedModule) {
|
|
40
38
|
const libPath = path.resolve(__dirname + '/../middleware/' + name + '.js')
|
|
41
39
|
loadedModule = await tryToLoadFile(libPath)
|
|
42
40
|
}
|
|
43
41
|
} else {
|
|
44
|
-
// Middleware locale alla route
|
|
45
42
|
const routeMiddPath = path.resolve(base + '/middleware/' + middleware)
|
|
46
|
-
// Qui è difficile indovinare l'estensione se non fornita, assumiamo che il loader sappia cosa fa o proviamo entrambe
|
|
47
43
|
loadedModule = await tryToLoadFile(routeMiddPath + '.ts')
|
|
48
44
|
if (!loadedModule) loadedModule = await tryToLoadFile(routeMiddPath + '.js')
|
|
49
|
-
if (!loadedModule) loadedModule = await tryToLoadFile(routeMiddPath)
|
|
45
|
+
if (!loadedModule) loadedModule = await tryToLoadFile(routeMiddPath)
|
|
50
46
|
}
|
|
51
47
|
|
|
52
48
|
if (!loadedModule) {
|
|
@@ -60,7 +56,6 @@ async function loadMiddlewares(base: string, middlewares: string[] = []) {
|
|
|
60
56
|
const midds = {}
|
|
61
57
|
for (const m of middlewares) {
|
|
62
58
|
const middleware = await loadMiddleware(base, m)
|
|
63
|
-
// I middleware possono esportare più funzioni (preHandler, preSerialization, ecc.)
|
|
64
59
|
Object.keys(middleware).map((name) => (midds[name] = [...(midds[name] || []), middleware[name]]))
|
|
65
60
|
}
|
|
66
61
|
return midds
|
|
@@ -72,7 +67,7 @@ async function load(): Promise<ConfiguredRoute[]> {
|
|
|
72
67
|
const authMiddlewares = ['global.isAuthenticated', 'global.isAdmin']
|
|
73
68
|
|
|
74
69
|
for (const pattern of patterns) {
|
|
75
|
-
log.t
|
|
70
|
+
if (log.t) log.trace('Looking for ' + pattern)
|
|
76
71
|
const files = globSync(pattern, { windowsPathsNoEscape: true })
|
|
77
72
|
|
|
78
73
|
for (const f of files) {
|
|
@@ -86,7 +81,7 @@ async function load(): Promise<ConfiguredRoute[]> {
|
|
|
86
81
|
const routesjs = module.default || module
|
|
87
82
|
const { routes = [], config: defaultConfig = {} } = routesjs || {}
|
|
88
83
|
|
|
89
|
-
log.t
|
|
84
|
+
if (log.t) log.trace(`* Add ${routes.length} routes from ${file}`)
|
|
90
85
|
|
|
91
86
|
routes.forEach((route: Route, index: number) => {
|
|
92
87
|
const errors: string[] = []
|
|
@@ -106,8 +101,8 @@ async function load(): Promise<ConfiguredRoute[]> {
|
|
|
106
101
|
try {
|
|
107
102
|
requiredRoles = rsp.some((r) => r.code === roles.admin.code) ? rsp : [...rsp, roles.admin]
|
|
108
103
|
} catch (err) {
|
|
109
|
-
log.e
|
|
110
|
-
log.t
|
|
104
|
+
if (log.e) log.error(`Error in loading roles for ${methodCase} ${pathName} (${handler})`)
|
|
105
|
+
if (log.t) log.trace(err)
|
|
111
106
|
config.enable = false
|
|
112
107
|
}
|
|
113
108
|
|
|
@@ -151,19 +146,21 @@ async function load(): Promise<ConfiguredRoute[]> {
|
|
|
151
146
|
}
|
|
152
147
|
|
|
153
148
|
if (errors.length > 0) {
|
|
154
|
-
log.e
|
|
149
|
+
if (log.e) errors.forEach((error) => log.error(error))
|
|
155
150
|
}
|
|
156
151
|
}
|
|
157
152
|
|
|
158
153
|
const toAdd = enable && errors.length === 0
|
|
159
|
-
toAdd
|
|
160
|
-
|
|
154
|
+
if (toAdd) {
|
|
155
|
+
if (log.t)
|
|
161
156
|
log.trace(
|
|
162
157
|
`* Method [${method}] path ${endpoint} handler ${handler} enabled with ${
|
|
163
158
|
middlewares?.length || 0
|
|
164
159
|
} middlewares`
|
|
165
160
|
)
|
|
166
|
-
|
|
161
|
+
} else {
|
|
162
|
+
if (log.w) log.warn(`* Method [${method}] path ${endpoint} handler ${handler} disabled. Skip.`)
|
|
163
|
+
}
|
|
167
164
|
|
|
168
165
|
if (toAdd) {
|
|
169
166
|
const doc = {
|
|
@@ -200,23 +197,23 @@ async function load(): Promise<ConfiguredRoute[]> {
|
|
|
200
197
|
}
|
|
201
198
|
}
|
|
202
199
|
|
|
203
|
-
log.d
|
|
200
|
+
if (log.d) log.debug(`Routes loaded: ${validRoutes.length}`)
|
|
204
201
|
return validRoutes
|
|
205
202
|
}
|
|
206
203
|
|
|
207
204
|
async function applyRoutes(server: any, routes: ConfiguredRoute[]): Promise<void> {
|
|
208
205
|
if (!routes || routes.length === 0) {
|
|
209
|
-
log.w
|
|
206
|
+
if (log.w) log.warn('No routes to apply to server')
|
|
210
207
|
return
|
|
211
208
|
}
|
|
212
209
|
|
|
213
|
-
log.t
|
|
210
|
+
if (log.t) log.trace(`Apply ${routes.length} routes to server with pid ${process.pid}`)
|
|
214
211
|
|
|
215
212
|
for (const route of routes) {
|
|
216
213
|
if (route?.enable) {
|
|
217
214
|
const { handler, method, path, middlewares, roles, rawBody, rateLimit, base, file, func, doc } = route
|
|
218
215
|
|
|
219
|
-
log.t
|
|
216
|
+
if (log.t) log.trace(`* Add path ${method} ${path} on handle ${handler}`)
|
|
220
217
|
const midds = await loadMiddlewares(base, middlewares)
|
|
221
218
|
|
|
222
219
|
server.route({
|
|
@@ -242,12 +239,12 @@ async function applyRoutes(server: any, routes: ConfiguredRoute[]): Promise<void
|
|
|
242
239
|
}
|
|
243
240
|
}
|
|
244
241
|
} catch (err) {
|
|
245
|
-
log.e
|
|
242
|
+
if (log.e) log.error(`Cannot load module ${file}: ${err}`)
|
|
246
243
|
return reply.code(500).send(`Invalid handler module ${handler}`)
|
|
247
244
|
}
|
|
248
245
|
|
|
249
246
|
if (!module || typeof module[func] !== 'function') {
|
|
250
|
-
log.e
|
|
247
|
+
if (log.e) log.error(`Method ${func} not found in ${file}`)
|
|
251
248
|
return reply.code(500).send(`Invalid handler method ${handler}`)
|
|
252
249
|
}
|
|
253
250
|
|