@adaptivestone/framework 5.0.0-beta.4 → 5.0.0-beta.40
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 +1107 -528
- package/LICENCE +1 -1
- package/dist/Cli.d.ts +7 -0
- package/dist/Cli.js +19 -0
- package/dist/Cli.js.map +1 -0
- package/dist/cluster.d.ts +1 -0
- package/dist/cluster.js +18 -0
- package/dist/cluster.js.map +1 -0
- package/dist/commands/CreateUser.d.ts +32 -0
- package/dist/commands/CreateUser.js +83 -0
- package/dist/commands/CreateUser.js.map +1 -0
- package/dist/commands/Documentation.d.ts +5 -0
- package/dist/commands/Documentation.js +15 -0
- package/dist/commands/Documentation.js.map +1 -0
- package/dist/commands/DropIndex.d.ts +16 -0
- package/dist/commands/DropIndex.js +30 -0
- package/dist/commands/DropIndex.js.map +1 -0
- package/dist/commands/GenerateRandomBytes.d.ts +7 -0
- package/dist/commands/GenerateRandomBytes.js +18 -0
- package/dist/commands/GenerateRandomBytes.js.map +1 -0
- package/dist/commands/GenerateTypes.d.ts +11 -0
- package/dist/commands/GenerateTypes.js +52 -0
- package/dist/commands/GenerateTypes.js.map +1 -0
- package/dist/commands/GetOpenApiJson.d.ts +17 -0
- package/dist/commands/GetOpenApiJson.js +272 -0
- package/dist/commands/GetOpenApiJson.js.map +1 -0
- package/dist/commands/SyncIndexes.d.ts +6 -0
- package/dist/commands/SyncIndexes.js +31 -0
- package/dist/commands/SyncIndexes.js.map +1 -0
- package/dist/commands/migration/Create.d.ts +18 -0
- package/dist/commands/migration/Create.js +57 -0
- package/dist/commands/migration/Create.js.map +1 -0
- package/dist/commands/migration/Migrate.d.ts +6 -0
- package/dist/commands/migration/Migrate.js +43 -0
- package/dist/commands/migration/Migrate.js.map +1 -0
- package/dist/config/auth.d.ts +6 -0
- package/dist/config/auth.js +7 -0
- package/dist/config/auth.js.map +1 -0
- package/dist/config/http.d.ts +8 -0
- package/dist/config/http.js +10 -0
- package/dist/config/http.js.map +1 -0
- package/dist/config/i18n.d.ts +13 -0
- package/dist/config/i18n.js +13 -0
- package/dist/config/i18n.js.map +1 -0
- package/dist/config/ipDetector.d.ts +5 -0
- package/dist/config/ipDetector.js +15 -0
- package/dist/config/ipDetector.js.map +1 -0
- package/dist/config/log.d.ts +11 -0
- package/dist/config/log.js +20 -0
- package/dist/config/log.js.map +1 -0
- package/dist/config/mongo.d.ts +4 -0
- package/dist/config/mongo.js +4 -0
- package/dist/config/mongo.js.map +1 -0
- package/dist/config/rateLimiter.d.ts +13 -0
- package/dist/config/rateLimiter.js +17 -0
- package/dist/config/rateLimiter.js.map +1 -0
- package/dist/config/redis.d.ts +5 -0
- package/dist/config/redis.js +5 -0
- package/dist/config/redis.js.map +1 -0
- package/dist/config/validate.d.ts +4 -0
- package/dist/config/validate.js +4 -0
- package/dist/config/validate.js.map +1 -0
- package/dist/controllers/Auth.d.ts +131 -0
- package/dist/controllers/Auth.js +186 -0
- package/dist/controllers/Auth.js.map +1 -0
- package/dist/controllers/Home.d.ts +15 -0
- package/dist/controllers/Home.js +22 -0
- package/dist/controllers/Home.js.map +1 -0
- package/dist/controllers/index.d.ts +16 -0
- package/dist/controllers/index.js +59 -0
- package/dist/controllers/index.js.map +1 -0
- package/dist/folderConfig.d.ts +34 -0
- package/dist/folderConfig.js +14 -0
- package/dist/folderConfig.js.map +1 -0
- package/dist/helpers/appInstance.d.ts +3 -0
- package/dist/helpers/appInstance.js +8 -0
- package/dist/helpers/appInstance.js.map +1 -0
- package/dist/helpers/crypto.d.ts +3 -0
- package/dist/helpers/crypto.js +17 -0
- package/dist/helpers/crypto.js.map +1 -0
- package/dist/helpers/files.d.ts +16 -0
- package/dist/helpers/files.js +76 -0
- package/dist/helpers/files.js.map +1 -0
- package/dist/helpers/logger.d.ts +4 -0
- package/dist/helpers/logger.js +20 -0
- package/dist/helpers/logger.js.map +1 -0
- package/dist/helpers/redis/clearNamespace.d.ts +2 -0
- package/dist/helpers/redis/clearNamespace.js +14 -0
- package/dist/helpers/redis/clearNamespace.js.map +1 -0
- package/dist/helpers/yup.d.ts +13 -0
- package/dist/helpers/yup.js +21 -0
- package/dist/helpers/yup.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -0
- package/dist/models/Lock.d.ts +90 -0
- package/dist/models/Lock.js +97 -0
- package/dist/models/Lock.js.map +1 -0
- package/dist/models/Migration.d.ts +13 -0
- package/dist/models/Migration.js +14 -0
- package/dist/models/Migration.js.map +1 -0
- package/dist/models/Sequence.d.ts +28 -0
- package/dist/models/Sequence.js +19 -0
- package/dist/models/Sequence.js.map +1 -0
- package/dist/models/User.d.ts +656 -0
- package/dist/models/User.js +291 -0
- package/dist/models/User.js.map +1 -0
- package/dist/models/UserOld.d.ts +179 -0
- package/dist/models/UserOld.js +230 -0
- package/dist/models/UserOld.js.map +1 -0
- package/dist/modules/AbstractCommand.d.ts +51 -0
- package/dist/modules/AbstractCommand.js +60 -0
- package/dist/modules/AbstractCommand.js.map +1 -0
- package/dist/modules/AbstractConnector.d.ts +5 -0
- package/dist/modules/AbstractConnector.js +8 -0
- package/dist/modules/AbstractConnector.js.map +1 -0
- package/dist/modules/AbstractController.d.ts +94 -0
- package/dist/modules/AbstractController.js +323 -0
- package/dist/modules/AbstractController.js.map +1 -0
- package/dist/modules/AbstractModel.d.ts +29 -0
- package/dist/modules/AbstractModel.js +42 -0
- package/dist/modules/AbstractModel.js.map +1 -0
- package/dist/modules/Base.d.ts +29 -0
- package/dist/modules/Base.js +58 -0
- package/dist/modules/Base.js.map +1 -0
- package/dist/modules/BaseCli.d.ts +25 -0
- package/dist/modules/BaseCli.js +147 -0
- package/dist/modules/BaseCli.js.map +1 -0
- package/dist/modules/BaseModel.d.ts +55 -0
- package/dist/modules/BaseModel.js +37 -0
- package/dist/modules/BaseModel.js.map +1 -0
- package/dist/server.d.ts +123 -0
- package/dist/server.js +468 -0
- package/dist/server.js.map +1 -0
- package/dist/services/cache/Cache.d.ts +31 -0
- package/dist/services/cache/Cache.js +113 -0
- package/dist/services/cache/Cache.js.map +1 -0
- package/dist/services/documentation/DocumentationGenerator.d.ts +11 -0
- package/dist/services/documentation/DocumentationGenerator.js +130 -0
- package/dist/services/documentation/DocumentationGenerator.js.map +1 -0
- package/dist/services/http/HttpServer.d.ts +35 -0
- package/dist/services/http/HttpServer.js +70 -0
- package/dist/services/http/HttpServer.js.map +1 -0
- package/dist/services/http/middleware/AbstractMiddleware.d.ts +25 -0
- package/dist/services/http/middleware/AbstractMiddleware.js +41 -0
- package/dist/services/http/middleware/AbstractMiddleware.js.map +1 -0
- package/dist/services/http/middleware/Auth.d.ts +9 -0
- package/dist/services/http/middleware/Auth.js +18 -0
- package/dist/services/http/middleware/Auth.js.map +1 -0
- package/dist/services/http/middleware/Cors.d.ts +12 -0
- package/dist/services/http/middleware/Cors.js +36 -0
- package/dist/services/http/middleware/Cors.js.map +1 -0
- package/dist/services/http/middleware/GetUserByToken.d.ts +20 -0
- package/dist/services/http/middleware/GetUserByToken.js +39 -0
- package/dist/services/http/middleware/GetUserByToken.js.map +1 -0
- package/dist/services/http/middleware/I18n.d.ts +23 -0
- package/dist/services/http/middleware/I18n.js +61 -0
- package/dist/services/http/middleware/I18n.js.map +1 -0
- package/dist/services/http/middleware/IpDetector.d.ts +14 -0
- package/dist/services/http/middleware/IpDetector.js +55 -0
- package/dist/services/http/middleware/IpDetector.js.map +1 -0
- package/dist/services/http/middleware/Pagination.d.ts +27 -0
- package/dist/services/http/middleware/Pagination.js +46 -0
- package/dist/services/http/middleware/Pagination.js.map +1 -0
- package/dist/services/http/middleware/PrepareAppInfo.d.ts +8 -0
- package/dist/services/http/middleware/PrepareAppInfo.js +17 -0
- package/dist/services/http/middleware/PrepareAppInfo.js.map +1 -0
- package/dist/services/http/middleware/RateLimiter.d.ts +26 -0
- package/dist/services/http/middleware/RateLimiter.js +118 -0
- package/dist/services/http/middleware/RateLimiter.js.map +1 -0
- package/dist/services/http/middleware/RequestLogger.d.ts +8 -0
- package/dist/services/http/middleware/RequestLogger.js +18 -0
- package/dist/services/http/middleware/RequestLogger.js.map +1 -0
- package/dist/services/http/middleware/RequestParser.d.ts +8 -0
- package/dist/services/http/middleware/RequestParser.js +35 -0
- package/dist/services/http/middleware/RequestParser.js.map +1 -0
- package/dist/services/http/middleware/Role.d.ts +12 -0
- package/dist/services/http/middleware/Role.js +24 -0
- package/dist/services/http/middleware/Role.js.map +1 -0
- package/dist/services/i18n/I18n.d.ts +15 -0
- package/dist/services/i18n/I18n.js +58 -0
- package/dist/services/i18n/I18n.js.map +1 -0
- package/dist/services/logging/SentryTransport.d.ts +14 -0
- package/dist/services/logging/SentryTransport.js +57 -0
- package/dist/services/logging/SentryTransport.js.map +1 -0
- package/dist/services/validate/ValidateService.d.ts +31 -0
- package/dist/services/validate/ValidateService.js +95 -0
- package/dist/services/validate/ValidateService.js.map +1 -0
- package/dist/services/validate/drivers/AbstractValidator.d.ts +14 -0
- package/dist/services/validate/drivers/AbstractValidator.js +29 -0
- package/dist/services/validate/drivers/AbstractValidator.js.map +1 -0
- package/dist/services/validate/drivers/CustomValidator.d.ts +14 -0
- package/dist/services/validate/drivers/CustomValidator.js +48 -0
- package/dist/services/validate/drivers/CustomValidator.js.map +1 -0
- package/dist/services/validate/drivers/YupValidator.d.ts +13 -0
- package/dist/services/validate/drivers/YupValidator.js +86 -0
- package/dist/services/validate/drivers/YupValidator.js.map +1 -0
- package/dist/tests/frameworkVitestSetup.d.ts +1 -0
- package/dist/tests/frameworkVitestSetup.js +9 -0
- package/dist/tests/frameworkVitestSetup.js.map +1 -0
- package/dist/tests/globalSetupVitest.d.ts +3 -0
- package/dist/tests/globalSetupVitest.js +29 -0
- package/dist/tests/globalSetupVitest.js.map +1 -0
- package/dist/tests/setupVitest.d.ts +1 -0
- package/dist/tests/setupVitest.js +91 -0
- package/dist/tests/setupVitest.js.map +1 -0
- package/dist/tests/testHelpers.d.ts +340 -0
- package/dist/tests/testHelpers.js +48 -0
- package/dist/tests/testHelpers.js.map +1 -0
- package/package.json +45 -39
- package/Cli.js +0 -22
- package/cluster.js +0 -27
- package/commands/CreateUser.js +0 -75
- package/commands/Documentation.js +0 -17
- package/commands/DropIndex.js +0 -29
- package/commands/GenerateRandomBytes.js +0 -21
- package/commands/GetOpenApiJson.js +0 -325
- package/commands/SyncIndexes.js +0 -39
- package/commands/migration/Create.js +0 -61
- package/commands/migration/Migrate.js +0 -55
- package/config/auth.js +0 -9
- package/config/http.js +0 -9
- package/config/i18n.js +0 -12
- package/config/ipDetector.js +0 -14
- package/config/log.js +0 -22
- package/config/mail.js +0 -29
- package/config/mongo.js +0 -3
- package/config/rateLimiter.js +0 -16
- package/config/redis.js +0 -4
- package/config/validate.js +0 -3
- package/controllers/Auth.js +0 -210
- package/controllers/Home.js +0 -28
- package/controllers/index.js +0 -60
- package/folderConfig.js +0 -14
- package/helpers/files.js +0 -79
- package/helpers/logger.js +0 -17
- package/helpers/redis/clearNamespace.js +0 -14
- package/helpers/yup.js +0 -24
- package/index.js +0 -8
- package/jsconfig.json +0 -9
- package/locales/en/translation.json +0 -27
- package/locales/ru/translation.json +0 -27
- package/migrations/.gitkeep +0 -0
- package/models/Migration.js +0 -15
- package/models/Sequence.js +0 -22
- package/models/User.js +0 -263
- package/modules/AbstractCommand.js +0 -43
- package/modules/AbstractConnector.js +0 -9
- package/modules/AbstractController.js +0 -413
- package/modules/AbstractModel.d.ts +0 -48
- package/modules/AbstractModel.js +0 -92
- package/modules/Base.d.ts +0 -37
- package/modules/Base.js +0 -63
- package/modules/BaseCli.js +0 -97
- package/server.d.ts +0 -98
- package/server.js +0 -438
- package/services/cache/Cache.d.ts +0 -35
- package/services/cache/Cache.js +0 -124
- package/services/documentation/DocumentationGenerator.js +0 -169
- package/services/http/HttpServer.js +0 -96
- package/services/http/middleware/AbstractMiddleware.js +0 -51
- package/services/http/middleware/Auth.js +0 -20
- package/services/http/middleware/Cors.js +0 -46
- package/services/http/middleware/GetUserByToken.js +0 -47
- package/services/http/middleware/I18n.js +0 -117
- package/services/http/middleware/IpDetector.js +0 -59
- package/services/http/middleware/Pagination.js +0 -57
- package/services/http/middleware/PrepareAppInfo.js +0 -18
- package/services/http/middleware/RateLimiter.js +0 -134
- package/services/http/middleware/RequestLogger.js +0 -22
- package/services/http/middleware/RequestParser.js +0 -40
- package/services/http/middleware/Role.js +0 -29
- package/services/messaging/email/index.js +0 -217
- package/services/messaging/email/resources/.gitkeep +0 -1
- package/services/messaging/email/templates/emptyTemplate/html.pug +0 -9
- package/services/messaging/email/templates/emptyTemplate/subject.pug +0 -1
- package/services/messaging/email/templates/emptyTemplate/text.pug +0 -1
- package/services/messaging/email/templates/recovery/html.pug +0 -8
- package/services/messaging/email/templates/recovery/subject.pug +0 -2
- package/services/messaging/email/templates/recovery/text.pug +0 -3
- package/services/messaging/email/templates/verification/html.pug +0 -10
- package/services/messaging/email/templates/verification/subject.pug +0 -1
- package/services/messaging/email/templates/verification/text.pug +0 -1
- package/services/messaging/index.js +0 -3
- package/services/validate/ValidateService.js +0 -157
- package/services/validate/drivers/AbstractValidator.js +0 -37
- package/services/validate/drivers/CustomValidator.js +0 -51
- package/services/validate/drivers/YupValidator.js +0 -103
- package/tests/globalSetupVitest.js +0 -35
- package/tests/setup.js +0 -118
- package/tests/setupVitest.js +0 -109
- package/types/Expand.d.ts +0 -11
- package/types/TFoldersConfig.d.ts +0 -17
- package/views/404.pug +0 -3
- package/views/home.pug +0 -3
- package/views/layouts/base.pug +0 -39
- package/vitest.config.js +0 -16
- /package/{commands → dist/migrations}/.gitkeep +0 -0
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
import { BlockList } from 'node:net';
|
|
2
|
-
|
|
3
|
-
import AbstractMiddleware from './AbstractMiddleware.js';
|
|
4
|
-
|
|
5
|
-
class IpDetector extends AbstractMiddleware {
|
|
6
|
-
static get description() {
|
|
7
|
-
return 'Detect real user IP address. Support proxy and load balancer';
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
constructor(app, params) {
|
|
11
|
-
super(app, params);
|
|
12
|
-
const { trustedProxy } = this.app.getConfig('ipDetector');
|
|
13
|
-
|
|
14
|
-
this.blockList = new BlockList();
|
|
15
|
-
|
|
16
|
-
for (const subnet of trustedProxy) {
|
|
17
|
-
const addressType = subnet.includes(':') ? 'ipv6' : 'ipv4';
|
|
18
|
-
if (subnet.includes('/')) {
|
|
19
|
-
// CIDR
|
|
20
|
-
const [realSubnet, prefixLength] = subnet.split('/');
|
|
21
|
-
this.blockList.addSubnet(
|
|
22
|
-
realSubnet,
|
|
23
|
-
parseInt(prefixLength, 10),
|
|
24
|
-
addressType,
|
|
25
|
-
);
|
|
26
|
-
} else if (subnet.includes('-')) {
|
|
27
|
-
// RANGE
|
|
28
|
-
const [start, end] = subnet.split('-');
|
|
29
|
-
this.blockList.addRange(start, end, addressType);
|
|
30
|
-
} else {
|
|
31
|
-
// just an address
|
|
32
|
-
this.blockList.addAddress(subnet, addressType);
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
async middleware(req, res, next) {
|
|
38
|
-
const { headers } = this.app.getConfig('ipDetector');
|
|
39
|
-
const initialIp = req.socket.remoteAddress;
|
|
40
|
-
req.appInfo.ip = initialIp;
|
|
41
|
-
const addressType = initialIp.includes(':') ? 'ipv6' : 'ipv4';
|
|
42
|
-
|
|
43
|
-
if (this.blockList.check(initialIp, addressType)) {
|
|
44
|
-
// we can trust this source
|
|
45
|
-
for (const header of headers) {
|
|
46
|
-
// in a range
|
|
47
|
-
const ipHeader = req.headers[header.toLowerCase()];
|
|
48
|
-
if (ipHeader) {
|
|
49
|
-
const [firstIp] = ipHeader.split(',').map((ip) => ip.trim());
|
|
50
|
-
req.appInfo.ip = firstIp;
|
|
51
|
-
break;
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
next();
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
export default IpDetector;
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
import yup from 'yup';
|
|
2
|
-
import AbstractMiddleware from './AbstractMiddleware.js';
|
|
3
|
-
/**
|
|
4
|
-
* Middleware for reusing pagination
|
|
5
|
-
*/
|
|
6
|
-
class Pagination extends AbstractMiddleware {
|
|
7
|
-
static get description() {
|
|
8
|
-
return 'Pagination middleware. You can use limit=10 and maxLimit=100 parameters';
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
// eslint-disable-next-line class-methods-use-this
|
|
12
|
-
get relatedQueryParameters() {
|
|
13
|
-
return yup.object().shape({
|
|
14
|
-
page: yup.number(),
|
|
15
|
-
limit: yup.number(),
|
|
16
|
-
});
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
async middleware(req, res, next) {
|
|
20
|
-
let { limit, maxLimit } = this.params;
|
|
21
|
-
|
|
22
|
-
limit = (typeof limit !== 'number' ? parseInt(limit, 10) : limit) || 10;
|
|
23
|
-
maxLimit =
|
|
24
|
-
(typeof maxLimit !== 'number' ? parseInt(maxLimit, 10) : maxLimit) || 100;
|
|
25
|
-
|
|
26
|
-
req.appInfo.pagination = {};
|
|
27
|
-
req.appInfo.pagination.page =
|
|
28
|
-
typeof req?.query?.page === 'string'
|
|
29
|
-
? parseInt(req?.query?.page, 10) || 1
|
|
30
|
-
: 1;
|
|
31
|
-
|
|
32
|
-
req.appInfo.pagination.limit =
|
|
33
|
-
typeof req?.query?.limit === 'string'
|
|
34
|
-
? parseInt(req?.query?.limit, 10) || 0
|
|
35
|
-
: limit;
|
|
36
|
-
|
|
37
|
-
if (req.appInfo.pagination.limit > maxLimit) {
|
|
38
|
-
req.appInfo.pagination.limit = maxLimit;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
if (req.appInfo.pagination.page < 1) {
|
|
42
|
-
req.appInfo.pagination.page = 1;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
if (req.appInfo.pagination.limit < 0) {
|
|
46
|
-
req.appInfo.pagination.limit = 0;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
req.appInfo.pagination.skip =
|
|
50
|
-
req.appInfo.pagination.page * req.appInfo.pagination.limit -
|
|
51
|
-
req.appInfo.pagination.limit;
|
|
52
|
-
|
|
53
|
-
return next();
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
export default Pagination;
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import AbstractMiddleware from './AbstractMiddleware.js';
|
|
2
|
-
|
|
3
|
-
class PrepareAppInfo extends AbstractMiddleware {
|
|
4
|
-
static get description() {
|
|
5
|
-
return 'Basic middleware that creates "req.appInfo" object';
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
async middleware(req, res, next) {
|
|
9
|
-
if (!req.appInfo) {
|
|
10
|
-
req.appInfo = {
|
|
11
|
-
app: this.app,
|
|
12
|
-
};
|
|
13
|
-
}
|
|
14
|
-
next();
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export default PrepareAppInfo;
|
|
@@ -1,134 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
RateLimiterMemory,
|
|
3
|
-
RateLimiterRedis,
|
|
4
|
-
RateLimiterMongo,
|
|
5
|
-
} from 'rate-limiter-flexible';
|
|
6
|
-
import merge from 'deepmerge';
|
|
7
|
-
import redis from 'redis';
|
|
8
|
-
import mongoose from 'mongoose';
|
|
9
|
-
import AbstractMiddleware from './AbstractMiddleware.js';
|
|
10
|
-
|
|
11
|
-
class RateLimiter extends AbstractMiddleware {
|
|
12
|
-
static get description() {
|
|
13
|
-
return 'Rate limiter middleware. Limit amount of request. Please refer to documentation';
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
constructor(app, params) {
|
|
17
|
-
super(app, params);
|
|
18
|
-
const limiterOptions = this.app.getConfig('rateLimiter');
|
|
19
|
-
|
|
20
|
-
this.finalOptions = merge(limiterOptions, params);
|
|
21
|
-
this.limiter = null;
|
|
22
|
-
|
|
23
|
-
switch (this.finalOptions.driver) {
|
|
24
|
-
case 'memory':
|
|
25
|
-
this.limiter = new RateLimiterMemory(this.finalOptions.limiterOptions);
|
|
26
|
-
break;
|
|
27
|
-
|
|
28
|
-
case 'redis':
|
|
29
|
-
this.limiter = this.initRedisLimiter();
|
|
30
|
-
break;
|
|
31
|
-
|
|
32
|
-
case 'mongo':
|
|
33
|
-
this.limiter = new RateLimiterMongo({
|
|
34
|
-
storeClient: mongoose.connection,
|
|
35
|
-
...this.finalOptions.limiterOptions,
|
|
36
|
-
});
|
|
37
|
-
break;
|
|
38
|
-
|
|
39
|
-
default:
|
|
40
|
-
this.logger.error(
|
|
41
|
-
`Unknwon option for driver ${this.finalOptions.driver}`,
|
|
42
|
-
);
|
|
43
|
-
break;
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
initRedisLimiter() {
|
|
48
|
-
const redisConfig = this.app.getConfig('redis');
|
|
49
|
-
const redisClient = redis.createClient({
|
|
50
|
-
url: redisConfig.url,
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
// TODO: change it
|
|
54
|
-
(async () => {
|
|
55
|
-
await redisClient.connect();
|
|
56
|
-
})();
|
|
57
|
-
|
|
58
|
-
redisClient.on('error', (error, b, c) => {
|
|
59
|
-
this.logger.error(error, b, c);
|
|
60
|
-
});
|
|
61
|
-
redisClient.on('connect', () => {
|
|
62
|
-
this.logger.info('Redis connection success');
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
this.app.events.on('shutdown', async () => {
|
|
66
|
-
await redisClient.disconnect();
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
return new RateLimiterRedis({
|
|
70
|
-
storeClient: redisClient,
|
|
71
|
-
useRedisPackage: true,
|
|
72
|
-
...this.finalOptions.limiterOptions,
|
|
73
|
-
});
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
gerenateConsumeKey(req) {
|
|
77
|
-
const { ip, route, user, request } = this.finalOptions.consumeKeyComponents;
|
|
78
|
-
|
|
79
|
-
const key = [];
|
|
80
|
-
if (ip) {
|
|
81
|
-
if (!req.appInfo.ip) {
|
|
82
|
-
this.logger.error(
|
|
83
|
-
`RateLimiter: Can't get remote address from request. Please check that you used IpDetecor middleware before RateLimiter`,
|
|
84
|
-
);
|
|
85
|
-
} else {
|
|
86
|
-
key.push(req.appInfo.ip);
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
if (route) {
|
|
90
|
-
key.push(`${req.baseUrl ?? ''}${req.path ?? ''}`); // to avoid quesry params
|
|
91
|
-
}
|
|
92
|
-
if (user && req.appInfo?.user) {
|
|
93
|
-
key.push(req.appInfo?.user.id);
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
if (request && request.length) {
|
|
97
|
-
request.forEach((val) => {
|
|
98
|
-
if (req.body && req.body[val]) {
|
|
99
|
-
key.push(req.body[val]);
|
|
100
|
-
}
|
|
101
|
-
// if (req.appInfo.request && req.appInfo.request[val]) {
|
|
102
|
-
// key.push(req.appInfo.request[val]);
|
|
103
|
-
// }
|
|
104
|
-
});
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
return key.join('_');
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
async middleware(req, res, next) {
|
|
111
|
-
if (!this.limiter) {
|
|
112
|
-
this.logger.info(
|
|
113
|
-
`RateLimiter not inited correclty! Please check init logs `,
|
|
114
|
-
);
|
|
115
|
-
return res.status(500).json({ message: 'RateLimiter error' });
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
const { namespace } = this.app.getConfig('redis');
|
|
119
|
-
|
|
120
|
-
const consumeKey = `${namespace}-${this.gerenateConsumeKey(req)}`;
|
|
121
|
-
|
|
122
|
-
const consumeResult = await this.limiter
|
|
123
|
-
.consume(consumeKey, this.finalOptions.consumePoints)
|
|
124
|
-
.catch(() => {
|
|
125
|
-
this.logger.warn(`Too many requests. Consume key: ${consumeKey}`);
|
|
126
|
-
});
|
|
127
|
-
if (consumeResult) {
|
|
128
|
-
return next();
|
|
129
|
-
}
|
|
130
|
-
return res.status(429).json({ message: 'Too Many Requests' });
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
export default RateLimiter;
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import AbstractMiddleware from './AbstractMiddleware.js';
|
|
2
|
-
|
|
3
|
-
class RequestLogger extends AbstractMiddleware {
|
|
4
|
-
static get description() {
|
|
5
|
-
return 'Log info about the request';
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
async middleware(req, res, next) {
|
|
9
|
-
const startTime = performance.now();
|
|
10
|
-
const text = `Request is [${req.method}] ${req.url}`;
|
|
11
|
-
this.logger.info(text);
|
|
12
|
-
res.on('finish', () => {
|
|
13
|
-
const end = performance.now();
|
|
14
|
-
this.logger.info(
|
|
15
|
-
`Finished ${text}. Status: ${res.statusCode}. [${(end - startTime).toFixed(2)} ms]`,
|
|
16
|
-
);
|
|
17
|
-
});
|
|
18
|
-
next();
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export default RequestLogger;
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import formidable from 'formidable';
|
|
2
|
-
import AbstractMiddleware from './AbstractMiddleware.js';
|
|
3
|
-
|
|
4
|
-
class RequestParser extends AbstractMiddleware {
|
|
5
|
-
static get description() {
|
|
6
|
-
return 'Parses incoming request. Based on Formidable library';
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
async middleware(req, res, next) {
|
|
10
|
-
const time = Date.now();
|
|
11
|
-
this.logger.verbose(`Parsing request`);
|
|
12
|
-
// TODO update this to https://github.com/node-formidable/formidable/issues/412#issuecomment-1367914268 in node v20 (in 2023?)
|
|
13
|
-
|
|
14
|
-
const form = formidable(this.params); // not in construstor as reuse formidable affects performance
|
|
15
|
-
let fields;
|
|
16
|
-
let files;
|
|
17
|
-
try {
|
|
18
|
-
[fields, files] = await form.parse(req);
|
|
19
|
-
} catch (err) {
|
|
20
|
-
this.logger.error(`Parsing failed ${err}`);
|
|
21
|
-
return res.status(400).json({
|
|
22
|
-
message: `Error to parse your request. You provided invalid content type or content-length. Please check your request headers and content type.`,
|
|
23
|
-
});
|
|
24
|
-
// return next(err);
|
|
25
|
-
}
|
|
26
|
-
this.logger.verbose(
|
|
27
|
-
`Parsing multipart/formdata request DONE ${Date.now() - time}ms`,
|
|
28
|
-
);
|
|
29
|
-
|
|
30
|
-
req.body = {
|
|
31
|
-
// todo avoid body in next versions
|
|
32
|
-
...(req.body || {}),
|
|
33
|
-
...fields,
|
|
34
|
-
...files,
|
|
35
|
-
};
|
|
36
|
-
return next();
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
export default RequestParser;
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import AbstractMiddleware from './AbstractMiddleware.js';
|
|
2
|
-
|
|
3
|
-
class RoleMiddleware extends AbstractMiddleware {
|
|
4
|
-
static get description() {
|
|
5
|
-
return 'Check user role (user.roles property). If the user has no role then stop request and return error. OR logic (any role will pass user)';
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
async middleware(req, res, next) {
|
|
9
|
-
const { user } = req.appInfo;
|
|
10
|
-
|
|
11
|
-
if (!user) {
|
|
12
|
-
return res.status(401).json({ message: 'User should be provided' });
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
let hasRole = false;
|
|
16
|
-
user.roles.forEach((role) => {
|
|
17
|
-
if (this.params.roles.includes(role)) {
|
|
18
|
-
hasRole = true;
|
|
19
|
-
}
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
if (!hasRole) {
|
|
23
|
-
return res.status(403).json({ message: 'You do not have access' });
|
|
24
|
-
}
|
|
25
|
-
return next();
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
export default RoleMiddleware;
|
|
@@ -1,217 +0,0 @@
|
|
|
1
|
-
import fs from 'node:fs';
|
|
2
|
-
import path from 'node:path';
|
|
3
|
-
import * as url from 'node:url';
|
|
4
|
-
import { promisify } from 'node:util';
|
|
5
|
-
import nodemailer from 'nodemailer';
|
|
6
|
-
import sendMail from 'nodemailer-sendmail-transport';
|
|
7
|
-
import stub from 'nodemailer-stub-transport';
|
|
8
|
-
import pug from 'pug';
|
|
9
|
-
import juice from 'juice';
|
|
10
|
-
import { convert } from 'html-to-text';
|
|
11
|
-
import Base from '../../../modules/Base.js';
|
|
12
|
-
|
|
13
|
-
const mailTransports = {
|
|
14
|
-
sendMail,
|
|
15
|
-
stub,
|
|
16
|
-
smtp: (data) => data,
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
class Mail extends Base {
|
|
20
|
-
/**
|
|
21
|
-
* Construct mail class
|
|
22
|
-
* @param {object} app
|
|
23
|
-
* @param {string} template template name
|
|
24
|
-
* @param {object} [templateData={}] data to render in template. Object with value that available inside template
|
|
25
|
-
* @param {object} [i18n] data to render in template
|
|
26
|
-
*/
|
|
27
|
-
constructor(app, template, templateData = {}, i18n = null) {
|
|
28
|
-
super(app);
|
|
29
|
-
const dirname = url.fileURLToPath(new URL('.', import.meta.url));
|
|
30
|
-
if (!path.isAbsolute(template)) {
|
|
31
|
-
if (
|
|
32
|
-
fs.existsSync(
|
|
33
|
-
`${this.app.foldersConfig.emails}/${path.basename(template)}`,
|
|
34
|
-
)
|
|
35
|
-
) {
|
|
36
|
-
this.template = `${this.app.foldersConfig.emails}/${path.basename(
|
|
37
|
-
template,
|
|
38
|
-
)}`;
|
|
39
|
-
} else if (
|
|
40
|
-
fs.existsSync(
|
|
41
|
-
path.join(dirname, `/templates/${path.basename(template)}`),
|
|
42
|
-
)
|
|
43
|
-
) {
|
|
44
|
-
this.template = path.join(
|
|
45
|
-
dirname,
|
|
46
|
-
`/templates/${path.basename(template)}`,
|
|
47
|
-
);
|
|
48
|
-
} else {
|
|
49
|
-
this.template = path.join(dirname, `/templates/emptyTemplate`);
|
|
50
|
-
this.logger.error(
|
|
51
|
-
`Template '${template}' not found. Using 'emptyTemplate' as a fallback`,
|
|
52
|
-
);
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
this.templateData = templateData;
|
|
56
|
-
this.i18n = i18n ?? {
|
|
57
|
-
t: (str) => str,
|
|
58
|
-
locale: 'en', // todo change it to config
|
|
59
|
-
};
|
|
60
|
-
this.locale = this.i18n?.language;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
* Render template
|
|
65
|
-
* @param {object} type and fullpath
|
|
66
|
-
* @param {object} templateData
|
|
67
|
-
* @returns string
|
|
68
|
-
*/
|
|
69
|
-
// eslint-disable-next-line class-methods-use-this
|
|
70
|
-
async #renderTemplateFile({ type, fullPath } = {}, templateData = {}) {
|
|
71
|
-
if (!type) {
|
|
72
|
-
return null;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
switch (type) {
|
|
76
|
-
case 'html':
|
|
77
|
-
case 'text':
|
|
78
|
-
case 'css':
|
|
79
|
-
return fs.promises.readFile(fullPath, { encoding: 'utf8' });
|
|
80
|
-
case 'pug': {
|
|
81
|
-
const compiledFunction = pug.compileFile(fullPath);
|
|
82
|
-
return compiledFunction(templateData);
|
|
83
|
-
}
|
|
84
|
-
default:
|
|
85
|
-
throw new Error(`Template type ${type} is not supported`);
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
/**
|
|
90
|
-
* Render template
|
|
91
|
-
* @return {Promise}
|
|
92
|
-
*/
|
|
93
|
-
async renderTemplate() {
|
|
94
|
-
const files = await fs.promises.readdir(this.template);
|
|
95
|
-
const templates = {};
|
|
96
|
-
for (const file of files) {
|
|
97
|
-
const [name, extension] = file.split('.');
|
|
98
|
-
templates[name] = {
|
|
99
|
-
type: extension,
|
|
100
|
-
fullPath: path.join(this.template, file),
|
|
101
|
-
};
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
if (!templates.html || !templates.subject) {
|
|
105
|
-
throw new Error(
|
|
106
|
-
'Template HTML and Subject must be provided. Please follow documentation for details https://framework.adaptivestone.com/docs/email',
|
|
107
|
-
);
|
|
108
|
-
}
|
|
109
|
-
const mailConfig = this.app.getConfig('mail');
|
|
110
|
-
|
|
111
|
-
const templateDataToRender = {
|
|
112
|
-
locale: this.locale,
|
|
113
|
-
t: this.i18n.t.bind(this.i18n),
|
|
114
|
-
...mailConfig.globalVariablesToTemplates,
|
|
115
|
-
...this.templateData,
|
|
116
|
-
};
|
|
117
|
-
|
|
118
|
-
const [htmlRendered, subjectRendered, textRendered, extraCss] =
|
|
119
|
-
await Promise.all([
|
|
120
|
-
this.#renderTemplateFile(templates.html, templateDataToRender),
|
|
121
|
-
this.#renderTemplateFile(templates.subject, templateDataToRender),
|
|
122
|
-
this.#renderTemplateFile(templates.text, templateDataToRender),
|
|
123
|
-
this.#renderTemplateFile(templates.style),
|
|
124
|
-
]);
|
|
125
|
-
|
|
126
|
-
juice.tableElements = ['TABLE'];
|
|
127
|
-
|
|
128
|
-
const juiceResourcesAsync = promisify(juice.juiceResources);
|
|
129
|
-
|
|
130
|
-
const inlinedHTML = await juiceResourcesAsync(htmlRendered, {
|
|
131
|
-
preserveImportant: true,
|
|
132
|
-
webResources: mailConfig.webResources,
|
|
133
|
-
extraCss,
|
|
134
|
-
});
|
|
135
|
-
return {
|
|
136
|
-
htmlRaw: htmlRendered,
|
|
137
|
-
subject: subjectRendered,
|
|
138
|
-
text: textRendered,
|
|
139
|
-
inlinedHTML,
|
|
140
|
-
};
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
/**
|
|
144
|
-
* Send email
|
|
145
|
-
* @param {string} to email send to
|
|
146
|
-
* @param {string} [from = mailConfig.from]
|
|
147
|
-
* @param {object} [aditionalNodemailerOptions = {}] additional option to nodemailer
|
|
148
|
-
* @return {Promise}
|
|
149
|
-
*/
|
|
150
|
-
async send(to, from = null, aditionalNodemailerOptions = {}) {
|
|
151
|
-
const { subject, text, inlinedHTML } = await this.renderTemplate();
|
|
152
|
-
|
|
153
|
-
return this.constructor.sendRaw(
|
|
154
|
-
this.app,
|
|
155
|
-
to,
|
|
156
|
-
subject,
|
|
157
|
-
inlinedHTML,
|
|
158
|
-
text,
|
|
159
|
-
from,
|
|
160
|
-
aditionalNodemailerOptions,
|
|
161
|
-
);
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
/**
|
|
165
|
-
* Send provided text (html) to email. Low level function. All data should be prepared before sending (like inline styles)
|
|
166
|
-
* @param {import('../../../server.js').default['app']} app application
|
|
167
|
-
* @param {string} to send to
|
|
168
|
-
* @param {string} subject email topic
|
|
169
|
-
* @param {string} html hmlt body of emain
|
|
170
|
-
* @param {string} [text] if not provided will be generated from html string
|
|
171
|
-
* @param {string} [from = mailConfig.from] from. If not provided will be grabbed from config
|
|
172
|
-
* @param {object} [additionalNodeMailerOption = {}] any otipns to pass to nodemailer https://nodemailer.com/message/
|
|
173
|
-
*/
|
|
174
|
-
static async sendRaw(
|
|
175
|
-
app,
|
|
176
|
-
to,
|
|
177
|
-
subject,
|
|
178
|
-
html,
|
|
179
|
-
text = null,
|
|
180
|
-
from = null,
|
|
181
|
-
additionalNodeMailerOption = {},
|
|
182
|
-
) {
|
|
183
|
-
if (!app || !to || !subject || !html) {
|
|
184
|
-
throw new Error('App, to, subject and html is required fields.');
|
|
185
|
-
}
|
|
186
|
-
const mailConfig = app.getConfig('mail');
|
|
187
|
-
if (!from) {
|
|
188
|
-
// eslint-disable-next-line no-param-reassign
|
|
189
|
-
from = mailConfig.from;
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
if (!text) {
|
|
193
|
-
// eslint-disable-next-line no-param-reassign
|
|
194
|
-
text = convert(html, {
|
|
195
|
-
selectors: [{ selector: 'img', format: 'skip' }],
|
|
196
|
-
});
|
|
197
|
-
}
|
|
198
|
-
const transportConfig = mailConfig.transports[mailConfig.transport];
|
|
199
|
-
const transport = mailTransports[mailConfig.transport];
|
|
200
|
-
const transporter = nodemailer.createTransport(transport(transportConfig));
|
|
201
|
-
|
|
202
|
-
return transporter.sendMail({
|
|
203
|
-
from,
|
|
204
|
-
to,
|
|
205
|
-
subject,
|
|
206
|
-
text,
|
|
207
|
-
html,
|
|
208
|
-
...additionalNodeMailerOption,
|
|
209
|
-
});
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
static get loggerGroup() {
|
|
213
|
-
return 'email_';
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
export default Mail;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
This folder for you resources to inline
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
= `New message`
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
= `Good day`
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
= `Верификаия емейла`
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
= `Добрый день {{username}} Для верификации емейла перейдите по ссылке ${link}`
|