@kewacode/guard 1.0.3 → 1.0.4
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/constants.d.ts +2 -0
- package/constants.d.ts.map +1 -0
- package/constants.js +5 -0
- package/constants.js.map +1 -0
- package/decorators/kewa-rate-limit.decorator.d.ts +7 -0
- package/decorators/kewa-rate-limit.decorator.d.ts.map +1 -0
- package/decorators/kewa-rate-limit.decorator.js +8 -0
- package/decorators/kewa-rate-limit.decorator.js.map +1 -0
- package/guards/kewa-rate-limit.guard.d.ts +10 -0
- package/guards/kewa-rate-limit.guard.d.ts.map +1 -0
- package/guards/kewa-rate-limit.guard.js +54 -0
- package/guards/kewa-rate-limit.guard.js.map +1 -0
- package/{src/index.ts → index.d.ts} +6 -5
- package/index.d.ts.map +1 -0
- package/index.js +22 -0
- package/index.js.map +1 -0
- package/interfaces/kewa-options.interface.d.ts +6 -0
- package/interfaces/kewa-options.interface.d.ts.map +1 -0
- package/interfaces/kewa-options.interface.js +3 -0
- package/interfaces/kewa-options.interface.js.map +1 -0
- package/kewa-guard.module.d.ts +6 -0
- package/kewa-guard.module.d.ts.map +1 -0
- package/kewa-guard.module.js +44 -0
- package/kewa-guard.module.js.map +1 -0
- package/kewa-guard.service.d.ts +17 -0
- package/kewa-guard.service.d.ts.map +1 -0
- package/kewa-guard.service.js +81 -0
- package/kewa-guard.service.js.map +1 -0
- package/package.json +3 -2
- package/tsconfig.lib.tsbuildinfo +1 -0
- package/Readme.md +0 -29
- package/src/constants.ts +0 -1
- package/src/decorators/kewa-rate-limit.decorator.ts +0 -11
- package/src/guards/kewa-rate-limit.guard.ts +0 -62
- package/src/interfaces/kewa-options.interface.ts +0 -5
- package/src/kewa-guard.module.ts +0 -29
- package/src/kewa-guard.service.ts +0 -80
- package/tsconfig.lib.json +0 -10
package/constants.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../../libs/kewa-guard/src/constants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,iBAAiB,iBAAiB,CAAC"}
|
package/constants.js
ADDED
package/constants.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../../libs/kewa-guard/src/constants.ts"],"names":[],"mappings":";;;AAAa,QAAA,iBAAiB,GAAG,cAAc,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export declare const KEWA_RATE_LIMIT_KEY = "kewa_rate_limit_key";
|
|
2
|
+
export interface KewaRateLimitOptions {
|
|
3
|
+
limit: number;
|
|
4
|
+
ttl: number;
|
|
5
|
+
}
|
|
6
|
+
export declare const KewaRateLimit: (options: KewaRateLimitOptions) => import("@nestjs/common").CustomDecorator<string>;
|
|
7
|
+
//# sourceMappingURL=kewa-rate-limit.decorator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kewa-rate-limit.decorator.d.ts","sourceRoot":"","sources":["../../../../libs/kewa-guard/src/decorators/kewa-rate-limit.decorator.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,mBAAmB,wBAAwB,CAAC;AAEzD,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;CACb;AAED,eAAO,MAAM,aAAa,GAAI,SAAS,oBAAoB,qDAChB,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.KewaRateLimit = exports.KEWA_RATE_LIMIT_KEY = void 0;
|
|
4
|
+
const common_1 = require("@nestjs/common");
|
|
5
|
+
exports.KEWA_RATE_LIMIT_KEY = 'kewa_rate_limit_key';
|
|
6
|
+
const KewaRateLimit = (options) => (0, common_1.SetMetadata)(exports.KEWA_RATE_LIMIT_KEY, options);
|
|
7
|
+
exports.KewaRateLimit = KewaRateLimit;
|
|
8
|
+
//# sourceMappingURL=kewa-rate-limit.decorator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kewa-rate-limit.decorator.js","sourceRoot":"","sources":["../../../../libs/kewa-guard/src/decorators/kewa-rate-limit.decorator.ts"],"names":[],"mappings":";;;AAAA,2CAA6C;AAEhC,QAAA,mBAAmB,GAAG,qBAAqB,CAAC;AAOlD,MAAM,aAAa,GAAG,CAAC,OAA6B,EAAE,EAAE,CAC7D,IAAA,oBAAW,EAAC,2BAAmB,EAAE,OAAO,CAAC,CAAC;AAD/B,QAAA,aAAa,iBACkB"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { CanActivate, ExecutionContext } from '@nestjs/common';
|
|
2
|
+
import { Reflector } from '@nestjs/core';
|
|
3
|
+
import { KewaGuardService } from '../kewa-guard.service';
|
|
4
|
+
export declare class KewaRateLimitGuard implements CanActivate {
|
|
5
|
+
private reflector;
|
|
6
|
+
private kewaGuardService;
|
|
7
|
+
constructor(reflector: Reflector, kewaGuardService: KewaGuardService);
|
|
8
|
+
canActivate(context: ExecutionContext): Promise<boolean>;
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=kewa-rate-limit.guard.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kewa-rate-limit.guard.d.ts","sourceRoot":"","sources":["../../../../libs/kewa-guard/src/guards/kewa-rate-limit.guard.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,WAAW,EACX,gBAAgB,EAIjB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAMzC,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAEzD,qBACa,kBAAmB,YAAW,WAAW;IAElD,OAAO,CAAC,SAAS;IACjB,OAAO,CAAC,gBAAgB;gBADhB,SAAS,EAAE,SAAS,EACpB,gBAAgB,EAAE,gBAAgB;IAGtC,WAAW,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,OAAO,CAAC;CAuC/D"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.KewaRateLimitGuard = void 0;
|
|
13
|
+
const common_1 = require("@nestjs/common");
|
|
14
|
+
const core_1 = require("@nestjs/core");
|
|
15
|
+
const kewa_rate_limit_decorator_1 = require("../decorators/kewa-rate-limit.decorator");
|
|
16
|
+
const kewa_guard_service_1 = require("../kewa-guard.service");
|
|
17
|
+
let KewaRateLimitGuard = class KewaRateLimitGuard {
|
|
18
|
+
reflector;
|
|
19
|
+
kewaGuardService;
|
|
20
|
+
constructor(reflector, kewaGuardService) {
|
|
21
|
+
this.reflector = reflector;
|
|
22
|
+
this.kewaGuardService = kewaGuardService;
|
|
23
|
+
}
|
|
24
|
+
async canActivate(context) {
|
|
25
|
+
const options = this.reflector.get(kewa_rate_limit_decorator_1.KEWA_RATE_LIMIT_KEY, context.getHandler());
|
|
26
|
+
if (!options) {
|
|
27
|
+
return true;
|
|
28
|
+
}
|
|
29
|
+
const { limit, ttl } = options;
|
|
30
|
+
const request = context.switchToHttp().getRequest();
|
|
31
|
+
const response = context.switchToHttp().getResponse();
|
|
32
|
+
const ip = request.ip || request.connection.remoteAddress;
|
|
33
|
+
const key = `rate_limit:${ip}:${context.getClass().name}.${context.getHandler().name}`;
|
|
34
|
+
const { allowed, remaining, resetAt } = await this.kewaGuardService.checkLimit(key, limit, ttl);
|
|
35
|
+
response.header('X-RateLimit-Limit', limit.toString());
|
|
36
|
+
response.header('X-RateLimit-Remaining', remaining.toString());
|
|
37
|
+
response.header('X-RateLimit-Reset', resetAt.toString());
|
|
38
|
+
if (!allowed) {
|
|
39
|
+
throw new common_1.HttpException({
|
|
40
|
+
statusCode: common_1.HttpStatus.TOO_MANY_REQUESTS,
|
|
41
|
+
error: 'Too Many Requests',
|
|
42
|
+
message: `Você excedeu o limite de ${limit} requisições em ${ttl} segundos.`,
|
|
43
|
+
}, common_1.HttpStatus.TOO_MANY_REQUESTS);
|
|
44
|
+
}
|
|
45
|
+
return true;
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
exports.KewaRateLimitGuard = KewaRateLimitGuard;
|
|
49
|
+
exports.KewaRateLimitGuard = KewaRateLimitGuard = __decorate([
|
|
50
|
+
(0, common_1.Injectable)(),
|
|
51
|
+
__metadata("design:paramtypes", [core_1.Reflector,
|
|
52
|
+
kewa_guard_service_1.KewaGuardService])
|
|
53
|
+
], KewaRateLimitGuard);
|
|
54
|
+
//# sourceMappingURL=kewa-rate-limit.guard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kewa-rate-limit.guard.js","sourceRoot":"","sources":["../../../../libs/kewa-guard/src/guards/kewa-rate-limit.guard.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,2CAMwB;AACxB,uCAAyC;AAEzC,uFAGiD;AACjD,8DAAyD;AAGlD,IAAM,kBAAkB,GAAxB,MAAM,kBAAkB;IAEnB;IACA;IAFV,YACU,SAAoB,EACpB,gBAAkC;QADlC,cAAS,GAAT,SAAS,CAAW;QACpB,qBAAgB,GAAhB,gBAAgB,CAAkB;IACzC,CAAC;IAEJ,KAAK,CAAC,WAAW,CAAC,OAAyB;QACzC,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAChC,+CAAmB,EACnB,OAAO,CAAC,UAAU,EAAE,CACrB,CAAC;QAEF,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,OAAO,IAAI,CAAC;QACd,CAAC;QAED,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC;QAE/B,MAAM,OAAO,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,UAAU,EAAW,CAAC;QAC7D,MAAM,QAAQ,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,WAAW,EAAY,CAAC;QAEhE,MAAM,EAAE,GAAG,OAAO,CAAC,EAAE,IAAI,OAAO,CAAC,UAAU,CAAC,aAAa,CAAC;QAE1D,MAAM,GAAG,GAAG,cAAc,EAAE,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC,IAAI,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC,IAAI,EAAE,CAAC;QAEvF,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,GACnC,MAAM,IAAI,CAAC,gBAAgB,CAAC,UAAU,CAAC,GAAG,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC;QAE1D,QAAQ,CAAC,MAAM,CAAC,mBAAmB,EAAE,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC;QACvD,QAAQ,CAAC,MAAM,CAAC,uBAAuB,EAAE,SAAS,CAAC,QAAQ,EAAE,CAAC,CAAC;QAC/D,QAAQ,CAAC,MAAM,CAAC,mBAAmB,EAAE,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC;QAEzD,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,IAAI,sBAAa,CACrB;gBACE,UAAU,EAAE,mBAAU,CAAC,iBAAiB;gBACxC,KAAK,EAAE,mBAAmB;gBAC1B,OAAO,EAAE,4BAA4B,KAAK,mBAAmB,GAAG,YAAY;aAC7E,EACD,mBAAU,CAAC,iBAAiB,CAC7B,CAAC;QACJ,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC;CACF,CAAA;AA7CY,gDAAkB;6BAAlB,kBAAkB;IAD9B,IAAA,mBAAU,GAAE;qCAGU,gBAAS;QACF,qCAAgB;GAHjC,kBAAkB,CA6C9B"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
export * from './kewa-guard.module';
|
|
2
|
-
export * from './kewa-guard.service';
|
|
3
|
-
export * from './interfaces/kewa-options.interface';
|
|
4
|
-
export * from './guards/kewa-rate-limit.guard';
|
|
5
|
-
export * from './decorators/kewa-rate-limit.decorator';
|
|
1
|
+
export * from './kewa-guard.module';
|
|
2
|
+
export * from './kewa-guard.service';
|
|
3
|
+
export * from './interfaces/kewa-options.interface';
|
|
4
|
+
export * from './guards/kewa-rate-limit.guard';
|
|
5
|
+
export * from './decorators/kewa-rate-limit.decorator';
|
|
6
|
+
//# sourceMappingURL=index.d.ts.map
|
package/index.d.ts.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../libs/kewa-guard/src/index.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAC;AACpC,cAAc,sBAAsB,CAAC;AACrC,cAAc,qCAAqC,CAAC;AACpD,cAAc,gCAAgC,CAAC;AAC/C,cAAc,wCAAwC,CAAC"}
|
package/index.js
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./kewa-guard.module"), exports);
|
|
18
|
+
__exportStar(require("./kewa-guard.service"), exports);
|
|
19
|
+
__exportStar(require("./interfaces/kewa-options.interface"), exports);
|
|
20
|
+
__exportStar(require("./guards/kewa-rate-limit.guard"), exports);
|
|
21
|
+
__exportStar(require("./decorators/kewa-rate-limit.decorator"), exports);
|
|
22
|
+
//# sourceMappingURL=index.js.map
|
package/index.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../libs/kewa-guard/src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,sDAAoC;AACpC,uDAAqC;AACrC,sEAAoD;AACpD,iEAA+C;AAC/C,yEAAuD"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kewa-options.interface.d.ts","sourceRoot":"","sources":["../../../../libs/kewa-guard/src/interfaces/kewa-options.interface.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kewa-options.interface.js","sourceRoot":"","sources":["../../../../libs/kewa-guard/src/interfaces/kewa-options.interface.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { DynamicModule } from '@nestjs/common';
|
|
2
|
+
import { KewaGuardOptions } from './interfaces/kewa-options.interface';
|
|
3
|
+
export declare class KewaGuardModule {
|
|
4
|
+
static register(options: KewaGuardOptions): DynamicModule;
|
|
5
|
+
}
|
|
6
|
+
//# sourceMappingURL=kewa-guard.module.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kewa-guard.module.d.ts","sourceRoot":"","sources":["../../../libs/kewa-guard/src/kewa-guard.module.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAkB,MAAM,gBAAgB,CAAC;AAI/D,OAAO,EAAE,gBAAgB,EAAE,MAAM,qCAAqC,CAAC;AAEvE,qBAEa,eAAe;IAC1B,MAAM,CAAC,QAAQ,CAAC,OAAO,EAAE,gBAAgB,GAAG,aAAa;CAmB1D"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
9
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
10
|
+
};
|
|
11
|
+
var KewaGuardModule_1;
|
|
12
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
+
exports.KewaGuardModule = void 0;
|
|
14
|
+
const common_1 = require("@nestjs/common");
|
|
15
|
+
const ioredis_1 = __importDefault(require("ioredis"));
|
|
16
|
+
const constants_1 = require("./constants");
|
|
17
|
+
const kewa_guard_service_1 = require("./kewa-guard.service");
|
|
18
|
+
let KewaGuardModule = KewaGuardModule_1 = class KewaGuardModule {
|
|
19
|
+
static register(options) {
|
|
20
|
+
return {
|
|
21
|
+
module: KewaGuardModule_1,
|
|
22
|
+
providers: [
|
|
23
|
+
{
|
|
24
|
+
provide: constants_1.KEWA_REDIS_CLIENT,
|
|
25
|
+
useFactory: () => {
|
|
26
|
+
return new ioredis_1.default({
|
|
27
|
+
host: options.host,
|
|
28
|
+
port: options.port,
|
|
29
|
+
password: options.password,
|
|
30
|
+
});
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
kewa_guard_service_1.KewaGuardService,
|
|
34
|
+
],
|
|
35
|
+
exports: [kewa_guard_service_1.KewaGuardService],
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
exports.KewaGuardModule = KewaGuardModule;
|
|
40
|
+
exports.KewaGuardModule = KewaGuardModule = KewaGuardModule_1 = __decorate([
|
|
41
|
+
(0, common_1.Global)(),
|
|
42
|
+
(0, common_1.Module)({})
|
|
43
|
+
], KewaGuardModule);
|
|
44
|
+
//# sourceMappingURL=kewa-guard.module.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kewa-guard.module.js","sourceRoot":"","sources":["../../../libs/kewa-guard/src/kewa-guard.module.ts"],"names":[],"mappings":";;;;;;;;;;;;;AAAA,2CAA+D;AAC/D,sDAA4B;AAC5B,2CAAgD;AAChD,6DAAwD;AAKjD,IAAM,eAAe,uBAArB,MAAM,eAAe;IAC1B,MAAM,CAAC,QAAQ,CAAC,OAAyB;QACvC,OAAO;YACL,MAAM,EAAE,iBAAe;YACvB,SAAS,EAAE;gBACT;oBACE,OAAO,EAAE,6BAAiB;oBAC1B,UAAU,EAAE,GAAG,EAAE;wBACf,OAAO,IAAI,iBAAK,CAAC;4BACf,IAAI,EAAE,OAAO,CAAC,IAAI;4BAClB,IAAI,EAAE,OAAO,CAAC,IAAI;4BAClB,QAAQ,EAAE,OAAO,CAAC,QAAQ;yBAC3B,CAAC,CAAC;oBACL,CAAC;iBACF;gBACD,qCAAgB;aACjB;YACD,OAAO,EAAE,CAAC,qCAAgB,CAAC;SAC5B,CAAC;IACJ,CAAC;CACF,CAAA;AApBY,0CAAe;0BAAf,eAAe;IAF3B,IAAA,eAAM,GAAE;IACR,IAAA,eAAM,EAAC,EAAE,CAAC;GACE,eAAe,CAoB3B"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { OnModuleDestroy } from '@nestjs/common';
|
|
2
|
+
import Redis from 'ioredis';
|
|
3
|
+
interface RateLimitResult {
|
|
4
|
+
allowed: boolean;
|
|
5
|
+
remaining: number;
|
|
6
|
+
resetAt: number;
|
|
7
|
+
}
|
|
8
|
+
export declare class KewaGuardService implements OnModuleDestroy {
|
|
9
|
+
private readonly redis;
|
|
10
|
+
constructor(redis: Redis);
|
|
11
|
+
onModuleDestroy(): void;
|
|
12
|
+
checkLimit(key: string, limit: number, ttlSeconds: number): Promise<RateLimitResult>;
|
|
13
|
+
ping(): Promise<"PONG">;
|
|
14
|
+
getClient(): Redis;
|
|
15
|
+
}
|
|
16
|
+
export {};
|
|
17
|
+
//# sourceMappingURL=kewa-guard.service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kewa-guard.service.d.ts","sourceRoot":"","sources":["../../../libs/kewa-guard/src/kewa-guard.service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsB,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACrE,OAAO,KAAK,MAAM,SAAS,CAAC;AAG5B,UAAU,eAAe;IACvB,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,qBACa,gBAAiB,YAAW,eAAe;IACf,OAAO,CAAC,QAAQ,CAAC,KAAK;gBAAL,KAAK,EAAE,KAAK;IAEpE,eAAe;IAIT,UAAU,CACd,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,MAAM,EACb,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,eAAe,CAAC;IAkDrB,IAAI;IAIV,SAAS;CAGV"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
12
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
13
|
+
};
|
|
14
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
15
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
16
|
+
};
|
|
17
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
+
exports.KewaGuardService = void 0;
|
|
19
|
+
const common_1 = require("@nestjs/common");
|
|
20
|
+
const ioredis_1 = __importDefault(require("ioredis"));
|
|
21
|
+
const constants_1 = require("./constants");
|
|
22
|
+
let KewaGuardService = class KewaGuardService {
|
|
23
|
+
redis;
|
|
24
|
+
constructor(redis) {
|
|
25
|
+
this.redis = redis;
|
|
26
|
+
}
|
|
27
|
+
onModuleDestroy() {
|
|
28
|
+
this.redis.disconnect();
|
|
29
|
+
}
|
|
30
|
+
async checkLimit(key, limit, ttlSeconds) {
|
|
31
|
+
const now = Date.now();
|
|
32
|
+
const windowStart = now - ttlSeconds * 1000;
|
|
33
|
+
const luaScript = `
|
|
34
|
+
local key = KEYS[1]
|
|
35
|
+
local limit = tonumber(ARGV[1])
|
|
36
|
+
local now = tonumber(ARGV[2])
|
|
37
|
+
local windowStart = tonumber(ARGV[3])
|
|
38
|
+
local ttl = tonumber(ARGV[4])
|
|
39
|
+
|
|
40
|
+
redis.call('ZREMRANGEBYSCORE', key, 0, windowStart)
|
|
41
|
+
|
|
42
|
+
local currentCount = redis.call('ZCARD', key)
|
|
43
|
+
|
|
44
|
+
local allowed = 1
|
|
45
|
+
local remaining = 0
|
|
46
|
+
|
|
47
|
+
if currentCount >= limit then
|
|
48
|
+
allowed = 0
|
|
49
|
+
remaining = 0
|
|
50
|
+
else
|
|
51
|
+
redis.call('ZADD', key, now, now)
|
|
52
|
+
redis.call('EXPIRE', key, ttl)
|
|
53
|
+
allowed = 1
|
|
54
|
+
remaining = limit - (currentCount + 1)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
local resetAt = math.floor((now + (ttl * 1000)) / 1000)
|
|
58
|
+
|
|
59
|
+
return { allowed, remaining, resetAt }
|
|
60
|
+
`;
|
|
61
|
+
const result = (await this.redis.eval(luaScript, 1, key, limit, now, windowStart, ttlSeconds));
|
|
62
|
+
return {
|
|
63
|
+
allowed: result[0] === 1,
|
|
64
|
+
remaining: result[1],
|
|
65
|
+
resetAt: result[2],
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
async ping() {
|
|
69
|
+
return await this.redis.ping();
|
|
70
|
+
}
|
|
71
|
+
getClient() {
|
|
72
|
+
return this.redis;
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
exports.KewaGuardService = KewaGuardService;
|
|
76
|
+
exports.KewaGuardService = KewaGuardService = __decorate([
|
|
77
|
+
(0, common_1.Injectable)(),
|
|
78
|
+
__param(0, (0, common_1.Inject)(constants_1.KEWA_REDIS_CLIENT)),
|
|
79
|
+
__metadata("design:paramtypes", [ioredis_1.default])
|
|
80
|
+
], KewaGuardService);
|
|
81
|
+
//# sourceMappingURL=kewa-guard.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kewa-guard.service.js","sourceRoot":"","sources":["../../../libs/kewa-guard/src/kewa-guard.service.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;AAAA,2CAAqE;AACrE,sDAA4B;AAC5B,2CAAgD;AASzC,IAAM,gBAAgB,GAAtB,MAAM,gBAAgB;IAC6B;IAAxD,YAAwD,KAAY;QAAZ,UAAK,GAAL,KAAK,CAAO;IAAG,CAAC;IAExE,eAAe;QACb,IAAI,CAAC,KAAK,CAAC,UAAU,EAAE,CAAC;IAC1B,CAAC;IAED,KAAK,CAAC,UAAU,CACd,GAAW,EACX,KAAa,EACb,UAAkB;QAElB,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,MAAM,WAAW,GAAG,GAAG,GAAG,UAAU,GAAG,IAAI,CAAC;QAE5C,MAAM,SAAS,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;KA2BjB,CAAC;QAEF,MAAM,MAAM,GAAG,CAAC,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,CACnC,SAAS,EACT,CAAC,EACD,GAAG,EACH,KAAK,EACL,GAAG,EACH,WAAW,EACX,UAAU,CACX,CAA6B,CAAC;QAE/B,OAAO;YACL,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC;YACxB,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC;YACpB,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC;SACnB,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,IAAI;QACR,OAAO,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;IACjC,CAAC;IAED,SAAS;QACP,OAAO,IAAI,CAAC,KAAK,CAAC;IACpB,CAAC;CACF,CAAA;AApEY,4CAAgB;2BAAhB,gBAAgB;IAD5B,IAAA,mBAAU,GAAE;IAEE,WAAA,IAAA,eAAM,EAAC,6BAAiB,CAAC,CAAA;qCAAyB,iBAAK;GADzD,gBAAgB,CAoE5B"}
|
package/package.json
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kewacode/guard",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.4",
|
|
4
4
|
"description": "Distributed Rate Limiter for NestJS using Redis",
|
|
5
5
|
"author": "João Bertan",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"types": "./index.d.ts",
|
|
8
|
+
"main": "./index.js",
|
|
8
9
|
"peerDependencies": {
|
|
9
10
|
"@nestjs/common": "^10.0.0 || ^11.0.0",
|
|
10
11
|
"@nestjs/core": "^10.0.0 || ^11.0.0",
|
|
11
|
-
"ioredis": "5.0.0",
|
|
12
|
+
"ioredis": "^5.0.0",
|
|
12
13
|
"rxjs": "^7.0.0"
|
|
13
14
|
},
|
|
14
15
|
"repository": {
|