mvc-common-toolkit 1.43.9 → 1.43.11
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/src/constants.d.ts +42 -0
- package/dist/src/constants.js +50 -0
- package/dist/src/constants.js.map +1 -0
- package/dist/src/gateways/alibaba-cloud-gateway.d.ts +30 -0
- package/dist/src/gateways/alibaba-cloud-gateway.js +120 -0
- package/dist/src/gateways/alibaba-cloud-gateway.js.map +1 -0
- package/dist/src/gateways/http-audit-gateway.d.ts +20 -0
- package/dist/src/gateways/http-audit-gateway.js +76 -0
- package/dist/src/gateways/http-audit-gateway.js.map +1 -0
- package/dist/src/gateways/index.d.ts +5 -0
- package/dist/src/gateways/index.js +22 -0
- package/dist/src/gateways/index.js.map +1 -0
- package/dist/src/gateways/internal-auth-gateway.d.ts +8 -0
- package/dist/src/gateways/internal-auth-gateway.js +40 -0
- package/dist/src/gateways/internal-auth-gateway.js.map +1 -0
- package/dist/src/gateways/stdout-audit-gateway.d.ts +7 -0
- package/dist/src/gateways/stdout-audit-gateway.js +25 -0
- package/dist/src/gateways/stdout-audit-gateway.js.map +1 -0
- package/dist/src/gateways/webhook-audit-gateway.d.ts +14 -0
- package/dist/src/gateways/webhook-audit-gateway.js +27 -0
- package/dist/src/gateways/webhook-audit-gateway.js.map +1 -0
- package/dist/src/interfaces.d.ts +218 -0
- package/dist/src/interfaces.js +3 -0
- package/dist/src/interfaces.js.map +1 -0
- package/dist/src/models/audit-log.d.ts +77 -0
- package/dist/src/models/audit-log.js +92 -0
- package/dist/src/models/audit-log.js.map +1 -0
- package/dist/src/models/index.d.ts +1 -0
- package/dist/src/models/index.js +18 -0
- package/dist/src/models/index.js.map +1 -0
- package/dist/src/pkg/array-helper.d.ts +1 -0
- package/dist/src/pkg/array-helper.js +12 -0
- package/dist/src/pkg/array-helper.js.map +1 -0
- package/dist/src/pkg/bcrypt-helper.d.ts +2 -0
- package/dist/src/pkg/bcrypt-helper.js +36 -0
- package/dist/src/pkg/bcrypt-helper.js.map +1 -0
- package/dist/src/pkg/crypto-helper.d.ts +2 -0
- package/dist/src/pkg/crypto-helper.js +16 -0
- package/dist/src/pkg/crypto-helper.js.map +1 -0
- package/dist/src/pkg/encryption-helper.d.ts +18 -0
- package/dist/src/pkg/encryption-helper.js +89 -0
- package/dist/src/pkg/encryption-helper.js.map +1 -0
- package/dist/src/pkg/encryption-helper.spec.d.ts +1 -0
- package/dist/src/pkg/encryption-helper.spec.js +238 -0
- package/dist/src/pkg/encryption-helper.spec.js.map +1 -0
- package/dist/src/pkg/filter-helper.d.ts +2 -0
- package/dist/src/pkg/filter-helper.js +102 -0
- package/dist/src/pkg/filter-helper.js.map +1 -0
- package/dist/src/pkg/filter-helper.spec.d.ts +1 -0
- package/dist/src/pkg/filter-helper.spec.js +94 -0
- package/dist/src/pkg/filter-helper.spec.js.map +1 -0
- package/dist/src/pkg/geoip-helper.d.ts +2 -0
- package/dist/src/pkg/geoip-helper.js +32 -0
- package/dist/src/pkg/geoip-helper.js.map +1 -0
- package/dist/src/pkg/hash-helper.d.ts +1 -0
- package/dist/src/pkg/hash-helper.js +37 -0
- package/dist/src/pkg/hash-helper.js.map +1 -0
- package/dist/src/pkg/http-request-utils.d.ts +4 -0
- package/dist/src/pkg/http-request-utils.js +55 -0
- package/dist/src/pkg/http-request-utils.js.map +1 -0
- package/dist/src/pkg/index.d.ts +18 -0
- package/dist/src/pkg/index.js +45 -0
- package/dist/src/pkg/index.js.map +1 -0
- package/dist/src/pkg/key-helper.d.ts +2 -0
- package/dist/src/pkg/key-helper.js +20 -0
- package/dist/src/pkg/key-helper.js.map +1 -0
- package/dist/src/pkg/logger.d.ts +9 -0
- package/dist/src/pkg/logger.js +23 -0
- package/dist/src/pkg/logger.js.map +1 -0
- package/dist/src/pkg/object-helper.d.ts +2 -0
- package/dist/src/pkg/object-helper.js +37 -0
- package/dist/src/pkg/object-helper.js.map +1 -0
- package/dist/src/pkg/paginated-cache-registry.d.ts +8 -0
- package/dist/src/pkg/paginated-cache-registry.js +23 -0
- package/dist/src/pkg/paginated-cache-registry.js.map +1 -0
- package/dist/src/pkg/query-helper.d.ts +3 -0
- package/dist/src/pkg/query-helper.js +60 -0
- package/dist/src/pkg/query-helper.js.map +1 -0
- package/dist/src/pkg/referral-tree-utils.d.ts +33 -0
- package/dist/src/pkg/referral-tree-utils.js +71 -0
- package/dist/src/pkg/referral-tree-utils.js.map +1 -0
- package/dist/src/pkg/scripts/index.d.ts +1 -0
- package/dist/src/pkg/scripts/index.js +28 -0
- package/dist/src/pkg/scripts/index.js.map +1 -0
- package/dist/src/pkg/scripts/lua.d.ts +10 -0
- package/dist/src/pkg/scripts/lua.js +109 -0
- package/dist/src/pkg/scripts/lua.js.map +1 -0
- package/dist/src/pkg/sort-helper.d.ts +3 -0
- package/dist/src/pkg/sort-helper.js +18 -0
- package/dist/src/pkg/sort-helper.js.map +1 -0
- package/dist/src/pkg/string-utils.d.ts +10 -0
- package/dist/src/pkg/string-utils.js +79 -0
- package/dist/src/pkg/string-utils.js.map +1 -0
- package/dist/src/pkg/task-helper.d.ts +2 -0
- package/dist/src/pkg/task-helper.js +30 -0
- package/dist/src/pkg/task-helper.js.map +1 -0
- package/dist/src/pkg/workflow/delayed-task-registry.d.ts +10 -0
- package/dist/src/pkg/workflow/delayed-task-registry.js +67 -0
- package/dist/src/pkg/workflow/delayed-task-registry.js.map +1 -0
- package/dist/src/pkg/workflow/delayed-task.d.ts +18 -0
- package/dist/src/pkg/workflow/delayed-task.js +95 -0
- package/dist/src/pkg/workflow/delayed-task.js.map +1 -0
- package/dist/src/pkg/workflow/index.d.ts +5 -0
- package/dist/src/pkg/workflow/index.js +22 -0
- package/dist/src/pkg/workflow/index.js.map +1 -0
- package/dist/src/pkg/workflow/processing-milestone.d.ts +18 -0
- package/dist/src/pkg/workflow/processing-milestone.js +39 -0
- package/dist/src/pkg/workflow/processing-milestone.js.map +1 -0
- package/dist/src/pkg/workflow/retry-task.d.ts +24 -0
- package/dist/src/pkg/workflow/retry-task.js +89 -0
- package/dist/src/pkg/workflow/retry-task.js.map +1 -0
- package/dist/src/pkg/workflow/retry-task.spec.d.ts +1 -0
- package/dist/src/pkg/workflow/retry-task.spec.js +145 -0
- package/dist/src/pkg/workflow/retry-task.spec.js.map +1 -0
- package/dist/src/pkg/workflow/sync-taskqueue.d.ts +32 -0
- package/dist/src/pkg/workflow/sync-taskqueue.js +108 -0
- package/dist/src/pkg/workflow/sync-taskqueue.js.map +1 -0
- package/dist/src/pkg/worksheet.utils.d.ts +27 -0
- package/dist/src/pkg/worksheet.utils.js +116 -0
- package/dist/src/pkg/worksheet.utils.js.map +1 -0
- package/dist/src/services/audit-service.d.ts +7 -0
- package/dist/src/services/audit-service.js +32 -0
- package/dist/src/services/audit-service.js.map +1 -0
- package/dist/src/services/excel.service.d.ts +25 -0
- package/dist/src/services/excel.service.js +95 -0
- package/dist/src/services/excel.service.js.map +1 -0
- package/dist/src/services/http-service.d.ts +7 -0
- package/dist/src/services/http-service.js +67 -0
- package/dist/src/services/http-service.js.map +1 -0
- package/dist/src/services/index.d.ts +8 -0
- package/dist/src/services/index.js +25 -0
- package/dist/src/services/index.js.map +1 -0
- package/dist/src/services/kafka-service.d.ts +15 -0
- package/dist/src/services/kafka-service.js +68 -0
- package/dist/src/services/kafka-service.js.map +1 -0
- package/dist/src/services/mailer-service.d.ts +15 -0
- package/dist/src/services/mailer-service.js +44 -0
- package/dist/src/services/mailer-service.js.map +1 -0
- package/dist/src/services/paginated-cache.d.ts +16 -0
- package/dist/src/services/paginated-cache.js +115 -0
- package/dist/src/services/paginated-cache.js.map +1 -0
- package/dist/src/services/paginated-cache.spec.d.ts +1 -0
- package/dist/src/services/paginated-cache.spec.js +284 -0
- package/dist/src/services/paginated-cache.spec.js.map +1 -0
- package/dist/src/services/redis-service.d.ts +33 -0
- package/dist/src/services/redis-service.js +230 -0
- package/dist/src/services/redis-service.js.map +1 -0
- package/dist/src/services/security-service.d.ts +11 -0
- package/dist/src/services/security-service.js +68 -0
- package/dist/src/services/security-service.js.map +1 -0
- package/package.json +1 -1
- package/src/constants.ts +47 -0
- package/src/gateways/alibaba-cloud-gateway.ts +127 -0
- package/src/gateways/http-audit-gateway.ts +104 -0
- package/src/gateways/index.ts +5 -0
- package/src/gateways/internal-auth-gateway.ts +42 -0
- package/src/gateways/stdout-audit-gateway.ts +23 -0
- package/src/gateways/webhook-audit-gateway.ts +33 -0
- package/src/interfaces.ts +304 -0
- package/src/models/audit-log.ts +126 -0
- package/src/models/index.ts +1 -0
- package/src/pkg/array-helper.ts +7 -0
- package/src/pkg/bcrypt-helper.ts +9 -0
- package/src/pkg/crypto-helper.ts +18 -0
- package/src/pkg/encryption-helper.spec.ts +423 -0
- package/src/pkg/encryption-helper.ts +155 -0
- package/src/pkg/filter-helper.spec.ts +105 -0
- package/src/pkg/filter-helper.ts +139 -0
- package/src/pkg/geoip-helper.ts +5 -0
- package/src/pkg/hash-helper.ts +12 -0
- package/src/pkg/http-request-utils.ts +75 -0
- package/src/pkg/index.ts +18 -0
- package/src/pkg/key-helper.ts +20 -0
- package/src/pkg/logger.ts +23 -0
- package/src/pkg/object-helper.ts +42 -0
- package/src/pkg/paginated-cache-registry.ts +25 -0
- package/src/pkg/query-helper.ts +79 -0
- package/src/pkg/referral-tree-utils.ts +165 -0
- package/src/pkg/scripts/index.ts +1 -0
- package/src/pkg/scripts/lua.ts +112 -0
- package/src/pkg/sort-helper.ts +19 -0
- package/src/pkg/string-utils.ts +104 -0
- package/src/pkg/task-helper.ts +25 -0
- package/src/pkg/workflow/delayed-task-registry.ts +54 -0
- package/src/pkg/workflow/delayed-task.ts +106 -0
- package/src/pkg/workflow/index.ts +5 -0
- package/src/pkg/workflow/processing-milestone.ts +54 -0
- package/src/pkg/workflow/retry-task.spec.ts +194 -0
- package/src/pkg/workflow/retry-task.ts +119 -0
- package/src/pkg/workflow/sync-taskqueue.ts +118 -0
- package/src/pkg/worksheet.utils.ts +178 -0
- package/src/services/audit-service.ts +22 -0
- package/src/services/excel.service.ts +103 -0
- package/src/services/http-service.ts +71 -0
- package/src/services/index.ts +8 -0
- package/src/services/kafka-service.ts +81 -0
- package/src/services/mailer-service.ts +43 -0
- package/src/services/paginated-cache.spec.ts +519 -0
- package/src/services/paginated-cache.ts +122 -0
- package/src/services/redis-service.ts +238 -0
- package/src/services/security-service.ts +80 -0
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
import * as ioredis from "ioredis";
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
CacheScriptEvaluator,
|
|
5
|
+
CacheService,
|
|
6
|
+
DeleteByPatternOptions,
|
|
7
|
+
HashCacheService,
|
|
8
|
+
ListCacheService,
|
|
9
|
+
LuaCall,
|
|
10
|
+
SetCacheOption,
|
|
11
|
+
} from "../interfaces";
|
|
12
|
+
import { SET_CACHE_POLICY } from "../constants";
|
|
13
|
+
|
|
14
|
+
export class RedisService
|
|
15
|
+
implements
|
|
16
|
+
CacheService,
|
|
17
|
+
HashCacheService,
|
|
18
|
+
ListCacheService,
|
|
19
|
+
CacheScriptEvaluator
|
|
20
|
+
{
|
|
21
|
+
protected _redis: ioredis.Redis;
|
|
22
|
+
|
|
23
|
+
constructor(config: ioredis.RedisOptions) {
|
|
24
|
+
this._redis = new ioredis.Redis(config);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
public get(key: string): Promise<any> {
|
|
28
|
+
return this._redis.get(key);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
public async getNumber(key: string): Promise<number | null> {
|
|
32
|
+
const result = await this._redis.get(key);
|
|
33
|
+
if (result === null) {
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return this.convertToNumber(result);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
public async deleteByPattern(
|
|
41
|
+
deletePattern: string,
|
|
42
|
+
options?: DeleteByPatternOptions
|
|
43
|
+
): Promise<void> {
|
|
44
|
+
let cursor = "0";
|
|
45
|
+
const prefix = this._redis.options.keyPrefix;
|
|
46
|
+
|
|
47
|
+
let scanPattern = deletePattern;
|
|
48
|
+
|
|
49
|
+
if (options?.includePrefixInScanPattern ?? true) {
|
|
50
|
+
scanPattern = prefix + deletePattern;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
do {
|
|
54
|
+
// TODO: ScanStream for multiple-node Redis cluster
|
|
55
|
+
const [nextCursor, keys] = await this._redis.scan(
|
|
56
|
+
cursor,
|
|
57
|
+
"MATCH",
|
|
58
|
+
scanPattern,
|
|
59
|
+
"COUNT",
|
|
60
|
+
100 // adjust batch size as needed
|
|
61
|
+
);
|
|
62
|
+
|
|
63
|
+
cursor = nextCursor;
|
|
64
|
+
|
|
65
|
+
if (keys.length > 0) {
|
|
66
|
+
const dupPrefixRemovedKeys = prefix
|
|
67
|
+
? keys.map((k) => (k.startsWith(prefix) ? k.slice(prefix.length) : k))
|
|
68
|
+
: keys;
|
|
69
|
+
|
|
70
|
+
// TODO: Chunk this for better load
|
|
71
|
+
if (typeof (this._redis as any).unlink === "function") {
|
|
72
|
+
await (this._redis as any).unlink(...dupPrefixRemovedKeys);
|
|
73
|
+
} else {
|
|
74
|
+
await this._redis.del(...dupPrefixRemovedKeys);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
} while (cursor !== "0");
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
public async del(...keys: string[]): Promise<void> {
|
|
81
|
+
await this._redis.del(...keys);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
public async multiEval(calls: LuaCall[]): Promise<any[]> {
|
|
85
|
+
const multi = this._redis.multi();
|
|
86
|
+
|
|
87
|
+
for (const [script, numberOfKeys, ...params] of calls) {
|
|
88
|
+
if (numberOfKeys !== params.slice(0, numberOfKeys).length) {
|
|
89
|
+
throw new Error(
|
|
90
|
+
`numberOfKeys (${numberOfKeys}) does not match key count in params`
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
multi.eval(script, numberOfKeys, ...params);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const execResult = await multi.exec();
|
|
97
|
+
|
|
98
|
+
// bubble up the first Redis-side error, if any
|
|
99
|
+
for (const [err] of execResult) {
|
|
100
|
+
if (err) throw err;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// unwrap the values
|
|
104
|
+
return execResult.map(([, value]) => value);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
public async eval(script: string, numberOfKeys: number, ...args: any[]) {
|
|
108
|
+
return this._redis.eval(script, numberOfKeys, ...args);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
public async hset(key: string, field: string, value: any): Promise<void> {
|
|
112
|
+
await this._redis.hset(key, {
|
|
113
|
+
[field]: value,
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
public async lpush(key: string, value: any): Promise<void> {
|
|
118
|
+
await this._redis.lpush(key, value);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
public async lrem(
|
|
122
|
+
key: string,
|
|
123
|
+
count: string | number,
|
|
124
|
+
element: string | Buffer | number
|
|
125
|
+
): Promise<number> {
|
|
126
|
+
return this._redis.lrem(key, count, element);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
public async rpush(key: string, value: any): Promise<void> {
|
|
130
|
+
await this._redis.rpush(key, value);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
public async lset(key: string, index: number, value: any): Promise<void> {
|
|
134
|
+
await this._redis.lset(key, index, value);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
public async lrange(
|
|
138
|
+
key: string,
|
|
139
|
+
start: number,
|
|
140
|
+
end: number
|
|
141
|
+
): Promise<string[]> {
|
|
142
|
+
return this._redis.lrange(key, start, end);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
public async lindex(key: string, index: number): Promise<string> {
|
|
146
|
+
return this._redis.lindex(key, index);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
public async llen(key: string): Promise<number> {
|
|
150
|
+
return this._redis.llen(key);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
public async hget(key: string, field: string): Promise<string> {
|
|
154
|
+
return this._redis.hget(key, field);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
public async hincrby(key: string, field: string, value = 1): Promise<number> {
|
|
158
|
+
return this._redis.hincrby(key, field, value);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
public async hincrbyfloat(
|
|
162
|
+
key: string,
|
|
163
|
+
field: string,
|
|
164
|
+
value = 1
|
|
165
|
+
): Promise<string> {
|
|
166
|
+
return this._redis.hincrbyfloat(key, field, value);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
public async hkeys(key: string): Promise<string[]> {
|
|
170
|
+
return this._redis.hkeys(key);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
public async ttl(key: string): Promise<number> {
|
|
174
|
+
return this._redis.ttl(key);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
public async hlen(key: string): Promise<number> {
|
|
178
|
+
return this._redis.hlen(key);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
public set(key: string, value: any, option?: SetCacheOption): Promise<any> {
|
|
182
|
+
if (!option) {
|
|
183
|
+
return this._redis.set(key, value);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
switch (option.policy) {
|
|
187
|
+
case SET_CACHE_POLICY.WITH_TTL:
|
|
188
|
+
return this._redis.set(key, value, "EX", option.value); // TTL in seconds
|
|
189
|
+
|
|
190
|
+
case SET_CACHE_POLICY.KEEP_TTL:
|
|
191
|
+
return this._redis.set(key, value, "KEEPTTL");
|
|
192
|
+
|
|
193
|
+
case SET_CACHE_POLICY.IF_EXISTS:
|
|
194
|
+
// Set only if exists, with optional TTL
|
|
195
|
+
return option.value
|
|
196
|
+
? this._redis.set(key, value, "EX", option.value, "XX")
|
|
197
|
+
: this._redis.set(key, value, "XX");
|
|
198
|
+
|
|
199
|
+
case SET_CACHE_POLICY.IF_NOT_EXISTS:
|
|
200
|
+
return option.value
|
|
201
|
+
? this._redis.set(key, value, "EX", option.value, "NX")
|
|
202
|
+
: this._redis.set(key, value, "NX");
|
|
203
|
+
|
|
204
|
+
default:
|
|
205
|
+
throw new Error("policy not supported");
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
public async incrBy(key: string, value = 1): Promise<number> {
|
|
210
|
+
const result = await this._redis.incrby(key, value);
|
|
211
|
+
|
|
212
|
+
return this.convertToNumber(result);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
protected convertToNumber(value: any): number {
|
|
216
|
+
const number = parseFloat(value);
|
|
217
|
+
if (isNaN(number)) {
|
|
218
|
+
throw new Error(`Value "${value}" is not a valid number.`);
|
|
219
|
+
}
|
|
220
|
+
return number;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
public expire(key: string, ttl: number): Promise<number> {
|
|
224
|
+
return this._redis.expire(key, ttl);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
public async incrByFloat(key: string, value: number): Promise<number> {
|
|
228
|
+
const result = await this._redis.incrbyfloat(key, value);
|
|
229
|
+
|
|
230
|
+
return this.convertToNumber(result);
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
public async decrBy(key: string, value = 1): Promise<any> {
|
|
234
|
+
const result = await this._redis.decrby(key, value);
|
|
235
|
+
|
|
236
|
+
return this.convertToNumber(result);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import {
|
|
2
|
+
CRUDService,
|
|
3
|
+
CacheService,
|
|
4
|
+
LockResult,
|
|
5
|
+
OperationResult,
|
|
6
|
+
} from "../interfaces";
|
|
7
|
+
|
|
8
|
+
export class SecurityService {
|
|
9
|
+
constructor(
|
|
10
|
+
protected cacheService: CacheService,
|
|
11
|
+
protected userService: CRUDService
|
|
12
|
+
) {}
|
|
13
|
+
|
|
14
|
+
public static LIMIT_TO_LOCK_USER = 5;
|
|
15
|
+
|
|
16
|
+
public static genLockUserCacheKey(userId: number): string {
|
|
17
|
+
return `user:${userId}:lock`;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
public async addFailureCount(
|
|
21
|
+
userId: number,
|
|
22
|
+
cacheKey?: string
|
|
23
|
+
): Promise<number> {
|
|
24
|
+
const finalCacheKey =
|
|
25
|
+
cacheKey || SecurityService.genLockUserCacheKey(userId);
|
|
26
|
+
|
|
27
|
+
await this.cacheService.incrBy(finalCacheKey);
|
|
28
|
+
|
|
29
|
+
return this.cacheService.get(finalCacheKey);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
public async clearFailureCount(userId: number, cacheKey?: string) {
|
|
33
|
+
const finalCacheKey =
|
|
34
|
+
cacheKey || SecurityService.genLockUserCacheKey(userId);
|
|
35
|
+
|
|
36
|
+
await this.cacheService.del(finalCacheKey);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
async shouldLockUser(
|
|
40
|
+
userId: number,
|
|
41
|
+
cacheKey?: string
|
|
42
|
+
): Promise<OperationResult<LockResult>> {
|
|
43
|
+
try {
|
|
44
|
+
const incrementedAttemptsCount = await this.addFailureCount(
|
|
45
|
+
userId,
|
|
46
|
+
cacheKey
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
// lock user
|
|
50
|
+
if (incrementedAttemptsCount >= SecurityService.LIMIT_TO_LOCK_USER) {
|
|
51
|
+
await this.clearFailureCount(userId);
|
|
52
|
+
|
|
53
|
+
return {
|
|
54
|
+
success: true,
|
|
55
|
+
data: {
|
|
56
|
+
isLocked: true,
|
|
57
|
+
attemptsLeft: 0,
|
|
58
|
+
},
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return {
|
|
63
|
+
success: true,
|
|
64
|
+
data: {
|
|
65
|
+
isLocked: false,
|
|
66
|
+
attemptsLeft: Math.max(
|
|
67
|
+
0,
|
|
68
|
+
SecurityService.LIMIT_TO_LOCK_USER - incrementedAttemptsCount
|
|
69
|
+
),
|
|
70
|
+
},
|
|
71
|
+
};
|
|
72
|
+
} catch (error: any) {
|
|
73
|
+
return {
|
|
74
|
+
success: false,
|
|
75
|
+
message: error.message,
|
|
76
|
+
metadata: error.stack,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|