mielk-api 1.5.4 → 1.5.6
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/middlewares/index.d.ts +0 -12
- package/dist/middlewares/index.js +0 -12
- package/dist/middlewares/rateLimit/checkRateLimit.js +2 -0
- package/dist/middlewares/rateLimit/createRateLimiter.d.ts +7 -3
- package/dist/middlewares/rateLimit/createRateLimiter.js +7 -8
- package/dist/middlewares/rateLimit/index.d.ts +2 -5
- package/dist/middlewares/rateLimit/index.js +1 -3
- package/dist/middlewares/rateLimit/rateLimitConfigFactory.d.ts +24 -6
- package/dist/middlewares/rateLimit/rateLimitConfigFactory.js +24 -23
- package/dist/middlewares/rateLimit/types.d.ts +2 -10
- package/dist/middlewares/redis/index.d.ts +8 -0
- package/dist/middlewares/redis/index.js +12 -0
- package/dist/middlewares/redis/redisKeysFactory.d.ts +18 -13
- package/dist/middlewares/redis/redisKeysFactory.js +17 -5
- package/dist/middlewares/redis/redisLockChecker.d.ts +5 -4
- package/dist/middlewares/redis/redisLockChecker.js +7 -4
- package/dist/middlewares/redis/redisLockCheckerConfigFactory.d.ts +9 -3
- package/dist/middlewares/redis/redisLockCheckerConfigFactory.js +10 -11
- package/dist/middlewares/redis/redisLocker.js +3 -10
- package/dist/middlewares/redis/redisLockerConfigFactory.d.ts +9 -3
- package/dist/middlewares/redis/redisLockerConfigFactory.js +9 -10
- package/dist/middlewares/redis/types.d.ts +2 -10
- package/dist/routing/express.d.ts +2 -2
- package/package.json +7 -2
|
@@ -3,18 +3,6 @@ import { privateCors } from './cors/privateCors.js';
|
|
|
3
3
|
import { publicCors } from './cors/publicCors.js';
|
|
4
4
|
import { apiKeyAuthorization } from './requestAuth/auth.middleware.js';
|
|
5
5
|
import { validateQueryParams, validateBodyJson } from './zod/validate.js';
|
|
6
|
-
import { RedisLockerConfigFactory } from './redis/redisLockerConfigFactory.js';
|
|
7
|
-
import { RedisLockerConfig, RedisLockerConfigParams } from './redis/types.js';
|
|
8
|
-
import { setRedisLock, removeRedisLock } from './redis/redisLocker.js';
|
|
9
|
-
import { RedisLockCheckerConfigFactory } from './redis/redisLockCheckerConfigFactory.js';
|
|
10
|
-
import { RedisLockChecker, RedisLockCheckerConfig, RedisLockCheckerConfigParams } from './redis/types.js';
|
|
11
|
-
import { createRedisLockChecker, checkIfLockedInRedis } from './redis/redisLockChecker.js';
|
|
12
6
|
export { CorsConfig, initCors, privateCors, publicCors };
|
|
13
7
|
export { apiKeyAuthorization };
|
|
14
8
|
export { validateQueryParams, validateBodyJson };
|
|
15
|
-
export { RedisLockerConfigFactory };
|
|
16
|
-
export { RedisLockerConfig, RedisLockerConfigParams };
|
|
17
|
-
export { setRedisLock, removeRedisLock };
|
|
18
|
-
export { createRedisLockChecker, checkIfLockedInRedis };
|
|
19
|
-
export { RedisLockCheckerConfigFactory };
|
|
20
|
-
export { RedisLockChecker, RedisLockCheckerConfig, RedisLockCheckerConfigParams };
|
|
@@ -3,18 +3,6 @@ import { privateCors } from './cors/privateCors.js';
|
|
|
3
3
|
import { publicCors } from './cors/publicCors.js';
|
|
4
4
|
import { apiKeyAuthorization } from './requestAuth/auth.middleware.js';
|
|
5
5
|
import { validateQueryParams, validateBodyJson } from './zod/validate.js';
|
|
6
|
-
// Redis locker
|
|
7
|
-
import { RedisLockerConfigFactory } from './redis/redisLockerConfigFactory.js';
|
|
8
|
-
import { setRedisLock, removeRedisLock } from './redis/redisLocker.js';
|
|
9
|
-
// Redis lock checker
|
|
10
|
-
import { RedisLockCheckerConfigFactory } from './redis/redisLockCheckerConfigFactory.js';
|
|
11
|
-
import { createRedisLockChecker, checkIfLockedInRedis } from './redis/redisLockChecker.js';
|
|
12
6
|
export { initCors, privateCors, publicCors };
|
|
13
7
|
export { apiKeyAuthorization };
|
|
14
8
|
export { validateQueryParams, validateBodyJson };
|
|
15
|
-
// Redis locker
|
|
16
|
-
export { RedisLockerConfigFactory };
|
|
17
|
-
export { setRedisLock, removeRedisLock };
|
|
18
|
-
// Redis lock checker
|
|
19
|
-
export { createRedisLockChecker, checkIfLockedInRedis };
|
|
20
|
-
export { RedisLockCheckerConfigFactory };
|
|
@@ -20,8 +20,10 @@ export const checkRateLimit = (rateLimit) => __awaiter(void 0, void 0, void 0, f
|
|
|
20
20
|
const allowed = currentCounter <= limit;
|
|
21
21
|
if (!allowed && redisLock) {
|
|
22
22
|
const { key, ttlSeconds } = redisLock;
|
|
23
|
+
console.log(`Setting Redis lock for ${key} | ${ttlSeconds} seconds`);
|
|
23
24
|
setRedisLock(key, ttlSeconds);
|
|
24
25
|
}
|
|
26
|
+
console.log('RL key:', key, 'current:', currentCounter, 'ttl:', ttl);
|
|
25
27
|
return {
|
|
26
28
|
currentCounter,
|
|
27
29
|
limit,
|
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
import { Request, Response, NextFunction } from 'express';
|
|
2
|
-
import { RateLimitConfig
|
|
3
|
-
|
|
4
|
-
export declare const
|
|
2
|
+
import { RateLimitConfig } from './types.js';
|
|
3
|
+
import { RateLimitType } from './rateLimitConfigFactory.js';
|
|
4
|
+
export declare const createGlobalRateLimiter: (config?: Partial<RateLimitConfig>) => (req: Request, res: Response, next: NextFunction) => Promise<void | Response<Record<string, any>, Record<string, any>>>;
|
|
5
|
+
export declare const createRateLimiter: (params: {
|
|
6
|
+
type?: RateLimitType;
|
|
7
|
+
customConfig?: Partial<RateLimitConfig>;
|
|
8
|
+
}) => (req: Request, res: Response, next: NextFunction) => Promise<void | Response<Record<string, any>, Record<string, any>>>;
|
|
@@ -9,14 +9,14 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
9
9
|
};
|
|
10
10
|
import { checkRateLimit } from './checkRateLimit.js';
|
|
11
11
|
import { failure, HttpResponseStatus } from '../../http/index.js';
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
12
|
+
import { createRateLimitConfig } from './rateLimitConfigFactory.js';
|
|
13
|
+
import { generateRedisKeyFromRequest } from '../redis/redisKeysFactory.js';
|
|
14
14
|
import { Msg } from '../../internal/messaging/messageTags.js';
|
|
15
|
-
import { generateRedisKey } from '../redis/redisKeysFactory.js';
|
|
16
15
|
export const createGlobalRateLimiter = (config) => {
|
|
17
|
-
return createRateLimiter(
|
|
16
|
+
return createRateLimiter({ type: 'globalIp', customConfig: config });
|
|
18
17
|
};
|
|
19
|
-
export const createRateLimiter = (
|
|
18
|
+
export const createRateLimiter = (params) => {
|
|
19
|
+
const config = createRateLimitConfig(params);
|
|
20
20
|
return (req, res, next) => __awaiter(void 0, void 0, void 0, function* () {
|
|
21
21
|
const { message } = config;
|
|
22
22
|
const rateLimit = createRateLimitFromConfig(config, req);
|
|
@@ -34,12 +34,11 @@ export const createRateLimiter = (config) => {
|
|
|
34
34
|
};
|
|
35
35
|
const createRateLimitFromConfig = (config, req) => {
|
|
36
36
|
const { keyPrefix, keySuffixes, limit, windowSec, message, redisLockerConfig } = config;
|
|
37
|
-
const key =
|
|
37
|
+
const key = generateRedisKeyFromRequest(keyPrefix, keySuffixes, req);
|
|
38
38
|
const rateLimit = { key, limit, windowSec, message };
|
|
39
39
|
if (redisLockerConfig) {
|
|
40
40
|
const { keyPrefix, ttlSeconds } = redisLockerConfig;
|
|
41
|
-
const
|
|
42
|
-
const key = generateRedisLockKey(keyPrefix, keySuffixes, req);
|
|
41
|
+
const key = generateRedisKeyFromRequest(keyPrefix, keySuffixes, req);
|
|
43
42
|
const redisLock = { key, ttlSeconds };
|
|
44
43
|
rateLimit.redisLock = redisLock;
|
|
45
44
|
}
|
|
@@ -1,8 +1,5 @@
|
|
|
1
1
|
import { checkRateLimit } from './checkRateLimit.js';
|
|
2
2
|
import { createRateLimiter } from './createRateLimiter.js';
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
import { type RateLimiter, RateLimitConfig, RateLimit, RateLimitCheck } from './types.js';
|
|
6
|
-
export { checkRateLimit, createRateLimiter, RateLimitConfigFactory, RedisKeyFactory };
|
|
7
|
-
export { RateLimitConfig, RateLimit, RateLimitCheck };
|
|
3
|
+
import { type RateLimiter } from './types.js';
|
|
4
|
+
export { checkRateLimit, createRateLimiter };
|
|
8
5
|
export type { RateLimiter };
|
|
@@ -1,5 +1,3 @@
|
|
|
1
1
|
import { checkRateLimit } from './checkRateLimit.js';
|
|
2
2
|
import { createRateLimiter } from './createRateLimiter.js';
|
|
3
|
-
|
|
4
|
-
import { RedisKeyFactory } from '../redis/redisKeysFactory.js';
|
|
5
|
-
export { checkRateLimit, createRateLimiter, RateLimitConfigFactory, RedisKeyFactory };
|
|
3
|
+
export { checkRateLimit, createRateLimiter };
|
|
@@ -1,7 +1,25 @@
|
|
|
1
|
-
import { RateLimitConfig
|
|
2
|
-
|
|
3
|
-
globalIp:
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
import { RateLimitConfig } from "./types.js";
|
|
2
|
+
declare const configs: {
|
|
3
|
+
readonly globalIp: {
|
|
4
|
+
readonly keyPrefix: "auth.global" | "auth.login" | "auth.lock:email" | "auth.refresh";
|
|
5
|
+
readonly windowSec: 60;
|
|
6
|
+
readonly limit: 2;
|
|
7
|
+
};
|
|
8
|
+
readonly loginIp: {};
|
|
9
|
+
readonly loginIpMail: {
|
|
10
|
+
readonly keySuffixes: ((req: import("express").Request) => string[]) | ((req: import("express").Request) => string[]) | ((req: import("express").Request) => string[]);
|
|
11
|
+
};
|
|
12
|
+
readonly loginMail: {
|
|
13
|
+
readonly keySuffixes: ((req: import("express").Request) => string[]) | ((req: import("express").Request) => string[]) | ((req: import("express").Request) => string[]);
|
|
14
|
+
readonly redisLockerConfig: {
|
|
15
|
+
readonly keyPrefix: "auth.global" | "auth.login" | "auth.lock:email" | "auth.refresh";
|
|
16
|
+
readonly ttlSeconds: number;
|
|
17
|
+
};
|
|
18
|
+
};
|
|
7
19
|
};
|
|
20
|
+
export type RateLimitType = keyof typeof configs;
|
|
21
|
+
export declare const createRateLimitConfig: (params: {
|
|
22
|
+
type?: RateLimitType;
|
|
23
|
+
customConfig?: Partial<RateLimitConfig>;
|
|
24
|
+
}) => RateLimitConfig;
|
|
25
|
+
export {};
|
|
@@ -1,30 +1,31 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { getRedisPrefix, getRedisSuffixCallback } from "../redis/redisKeysFactory.js";
|
|
2
2
|
import { Msg } from "../../internal/messaging/messageTags.js";
|
|
3
|
-
const
|
|
4
|
-
keyPrefix:
|
|
5
|
-
keySuffixes:
|
|
3
|
+
const defaultConfig = {
|
|
4
|
+
keyPrefix: getRedisPrefix("authLogin"),
|
|
5
|
+
keySuffixes: getRedisSuffixCallback("ip"),
|
|
6
6
|
windowSec: 15 * 60,
|
|
7
7
|
limit: 5,
|
|
8
8
|
message: Msg.apiStatus.tooManyRequests,
|
|
9
9
|
};
|
|
10
|
-
const
|
|
11
|
-
|
|
10
|
+
const configs = {
|
|
11
|
+
globalIp: {
|
|
12
|
+
keyPrefix: getRedisPrefix("authGlobal"),
|
|
13
|
+
windowSec: 60,
|
|
14
|
+
limit: 2
|
|
15
|
+
},
|
|
16
|
+
loginIp: {},
|
|
17
|
+
loginIpMail: {
|
|
18
|
+
keySuffixes: getRedisSuffixCallback("ipMail"),
|
|
19
|
+
},
|
|
20
|
+
loginMail: {
|
|
21
|
+
keySuffixes: getRedisSuffixCallback("mail"),
|
|
22
|
+
redisLockerConfig: {
|
|
23
|
+
keyPrefix: getRedisPrefix("authLockEmail"), ttlSeconds: 15 * 60
|
|
24
|
+
}
|
|
25
|
+
}
|
|
12
26
|
};
|
|
13
|
-
const
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
return createRateLimitConfig(Object.assign({}, (params || {})));
|
|
18
|
-
};
|
|
19
|
-
const loginIpMail = (params) => {
|
|
20
|
-
return createRateLimitConfig(Object.assign({ keySuffixes: RedisKeyFactory.suffixes.ipMail }, (params || {})));
|
|
21
|
-
};
|
|
22
|
-
const loginMail = (params) => {
|
|
23
|
-
return createRateLimitConfig(Object.assign({ keySuffixes: RedisKeyFactory.suffixes.mail, redisLockerConfig: { keyPrefix: RedisKeyFactory.prefixes.authLockEmail, ttlSeconds: 15 * 60 } }, (params || {})));
|
|
24
|
-
};
|
|
25
|
-
export const RateLimitConfigFactory = {
|
|
26
|
-
globalIp,
|
|
27
|
-
loginIp,
|
|
28
|
-
loginIpMail,
|
|
29
|
-
loginMail
|
|
27
|
+
export const createRateLimitConfig = (params) => {
|
|
28
|
+
const { type, customConfig } = params;
|
|
29
|
+
const typeConfig = type ? configs[type] : undefined;
|
|
30
|
+
return Object.assign(Object.assign(Object.assign({}, defaultConfig), typeConfig), customConfig);
|
|
30
31
|
};
|
|
@@ -1,17 +1,9 @@
|
|
|
1
1
|
import { NextFunction, Request, Response } from 'express';
|
|
2
|
-
import { RedisLockerConfig } from '../redis/types.js';
|
|
2
|
+
import { RedisLockerConfig, RequestParamsFetcher } from '../redis/types.js';
|
|
3
3
|
export type RateLimiter = (req: Request, res: Response, next: NextFunction) => Promise<void | Response<Record<string, any>, Record<string, any>>>;
|
|
4
|
-
export type RateLimitConfigParams = {
|
|
5
|
-
keyPrefix?: string;
|
|
6
|
-
keySuffixes?: (req: Request) => string[];
|
|
7
|
-
windowSec?: number;
|
|
8
|
-
limit?: number;
|
|
9
|
-
message?: string;
|
|
10
|
-
redisLockerConfig?: RedisLockerConfig | null;
|
|
11
|
-
};
|
|
12
4
|
export interface RateLimitConfig {
|
|
13
5
|
keyPrefix: string;
|
|
14
|
-
keySuffixes:
|
|
6
|
+
keySuffixes: RequestParamsFetcher;
|
|
15
7
|
limit: number;
|
|
16
8
|
windowSec: number;
|
|
17
9
|
message?: string;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { RedisLockChecker, RequestParamsFetcher } from './types.js';
|
|
2
|
+
import { setRedisLock, removeRedisLock } from './redisLocker.js';
|
|
3
|
+
import { createRedisLockChecker } from './redisLockChecker.js';
|
|
4
|
+
import { getRedisPrefix, generateRedisKeyFromValue, generateRedisKeyFromRequest } from './redisKeysFactory.js';
|
|
5
|
+
export { RedisLockChecker, RequestParamsFetcher };
|
|
6
|
+
export { setRedisLock, removeRedisLock };
|
|
7
|
+
export { createRedisLockChecker };
|
|
8
|
+
export { getRedisPrefix, generateRedisKeyFromRequest, generateRedisKeyFromValue };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
// Redis locker
|
|
2
|
+
import { setRedisLock, removeRedisLock } from './redisLocker.js';
|
|
3
|
+
// Redis lock checker
|
|
4
|
+
import { createRedisLockChecker } from './redisLockChecker.js';
|
|
5
|
+
// Redis keys
|
|
6
|
+
import { getRedisPrefix, generateRedisKeyFromValue, generateRedisKeyFromRequest } from './redisKeysFactory.js';
|
|
7
|
+
// Redis locker
|
|
8
|
+
export { setRedisLock, removeRedisLock };
|
|
9
|
+
// Redis lock checker
|
|
10
|
+
export { createRedisLockChecker };
|
|
11
|
+
// Redis keys
|
|
12
|
+
export { getRedisPrefix, generateRedisKeyFromRequest, generateRedisKeyFromValue };
|
|
@@ -1,15 +1,20 @@
|
|
|
1
1
|
import { Request } from 'express';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
};
|
|
9
|
-
suffixes: {
|
|
10
|
-
readonly ip: (req: Request) => string[];
|
|
11
|
-
readonly ipMail: (req: Request) => string[];
|
|
12
|
-
readonly mail: (req: Request) => string[];
|
|
13
|
-
};
|
|
2
|
+
import { RequestParamsFetcher } from './types.js';
|
|
3
|
+
declare const prefixes: {
|
|
4
|
+
readonly authGlobal: "auth.global";
|
|
5
|
+
readonly authLogin: "auth.login";
|
|
6
|
+
readonly authLockEmail: "auth.lock:email";
|
|
7
|
+
readonly authRefresh: "auth.refresh";
|
|
14
8
|
};
|
|
15
|
-
|
|
9
|
+
type RedisKeyPrefix = keyof typeof prefixes;
|
|
10
|
+
declare const suffixCallbacks: {
|
|
11
|
+
readonly ip: (req: Request) => string[];
|
|
12
|
+
readonly ipMail: (req: Request) => string[];
|
|
13
|
+
readonly mail: (req: Request) => string[];
|
|
14
|
+
};
|
|
15
|
+
type RedisKeySuffixCallback = keyof typeof suffixCallbacks;
|
|
16
|
+
export declare const generateRedisKeyFromValue: (prefix: RedisKeyPrefix | string, value: string[]) => string;
|
|
17
|
+
export declare const generateRedisKeyFromRequest: (prefix: RedisKeyPrefix | string, suffixCallback: RedisKeySuffixCallback | RequestParamsFetcher, req: Request) => string;
|
|
18
|
+
export declare const getRedisPrefix: (key: RedisKeyPrefix) => "auth.global" | "auth.login" | "auth.lock:email" | "auth.refresh";
|
|
19
|
+
export declare const getRedisSuffixCallback: (key: RedisKeySuffixCallback) => ((req: Request) => string[]) | ((req: Request) => string[]) | ((req: Request) => string[]);
|
|
20
|
+
export {};
|
|
@@ -1,9 +1,13 @@
|
|
|
1
|
+
// ### PREFIXES
|
|
1
2
|
const prefixes = {
|
|
2
3
|
authGlobal: 'auth.global',
|
|
3
4
|
authLogin: 'auth.login',
|
|
4
5
|
authLockEmail: 'auth.lock:email',
|
|
5
6
|
authRefresh: 'auth.refresh',
|
|
6
7
|
};
|
|
8
|
+
const isKnownPrefix = (value) => value in prefixes;
|
|
9
|
+
// ### SUFFIXES
|
|
10
|
+
const isRequestParamFetcher = (value) => typeof value === 'function';
|
|
7
11
|
const getIpSuffixCallback = (req) => {
|
|
8
12
|
const ip = req.ip || 'undefined';
|
|
9
13
|
return [ip];
|
|
@@ -24,10 +28,18 @@ const suffixCallbacks = {
|
|
|
24
28
|
'ipMail': getIpEmailSuffixCallback,
|
|
25
29
|
'mail': getEmailSuffixCallback,
|
|
26
30
|
};
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
31
|
+
// ### CALCULATING KEYS
|
|
32
|
+
const generateRedisKey = (prefix, suffixes) => {
|
|
33
|
+
const prefixValue = isKnownPrefix(prefix) ? prefixes[prefix] : prefix;
|
|
34
|
+
return `${prefixValue}:${suffixes.join(':')}`;
|
|
30
35
|
};
|
|
31
|
-
export const
|
|
32
|
-
return
|
|
36
|
+
export const generateRedisKeyFromValue = (prefix, value) => {
|
|
37
|
+
return generateRedisKey(prefix, value);
|
|
33
38
|
};
|
|
39
|
+
export const generateRedisKeyFromRequest = (prefix, suffixCallback, req) => {
|
|
40
|
+
const callback = isRequestParamFetcher(suffixCallback) ? suffixCallback : suffixCallbacks[suffixCallback];
|
|
41
|
+
const suffixes = callback(req);
|
|
42
|
+
return generateRedisKey(prefix, suffixes);
|
|
43
|
+
};
|
|
44
|
+
export const getRedisPrefix = (key) => prefixes[key];
|
|
45
|
+
export const getRedisSuffixCallback = (key) => suffixCallbacks[key];
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { RedisLockChecker, RedisLockCheckerConfig } from "./types.js";
|
|
2
|
-
import {
|
|
3
|
-
export declare const createRedisLockChecker: (
|
|
4
|
-
|
|
5
|
-
|
|
2
|
+
import { RedisLockCheckerType } from "./redisLockCheckerConfigFactory.js";
|
|
3
|
+
export declare const createRedisLockChecker: (params: {
|
|
4
|
+
type?: RedisLockCheckerType;
|
|
5
|
+
customConfig?: Partial<RedisLockCheckerConfig>;
|
|
6
|
+
}) => RedisLockChecker;
|
|
@@ -9,8 +9,11 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
9
9
|
};
|
|
10
10
|
import { getRedisClient } from "mielk-fn/redis";
|
|
11
11
|
import { failure, HttpResponseStatus } from "../../http/index.js";
|
|
12
|
+
import { createRedisLockCheckerConfig } from "./redisLockCheckerConfigFactory.js";
|
|
13
|
+
import { generateRedisKeyFromRequest } from "./redisKeysFactory.js";
|
|
12
14
|
import { Msg } from "../../internal/messaging/messageTags.js";
|
|
13
|
-
export const createRedisLockChecker = (
|
|
15
|
+
export const createRedisLockChecker = (params) => {
|
|
16
|
+
const config = createRedisLockCheckerConfig(params);
|
|
14
17
|
return (req, res, next) => __awaiter(void 0, void 0, void 0, function* () {
|
|
15
18
|
const { message, keyPrefix, keySuffixes } = config;
|
|
16
19
|
const key = generateRedisLockKey(keyPrefix, keySuffixes, req);
|
|
@@ -21,10 +24,10 @@ export const createRedisLockChecker = (config) => {
|
|
|
21
24
|
return next();
|
|
22
25
|
});
|
|
23
26
|
};
|
|
24
|
-
|
|
25
|
-
return
|
|
27
|
+
const generateRedisLockKey = (keyPrefix, suffixCallback, req) => {
|
|
28
|
+
return generateRedisKeyFromRequest(keyPrefix, suffixCallback, req);
|
|
26
29
|
};
|
|
27
|
-
|
|
30
|
+
const checkIfLockedInRedis = (key) => __awaiter(void 0, void 0, void 0, function* () {
|
|
28
31
|
const redisClient = yield getRedisClient();
|
|
29
32
|
const value = yield redisClient.get(key);
|
|
30
33
|
return value !== null;
|
|
@@ -1,4 +1,10 @@
|
|
|
1
|
-
import { RedisLockCheckerConfig
|
|
2
|
-
|
|
3
|
-
mail:
|
|
1
|
+
import { RedisLockCheckerConfig } from './types.js';
|
|
2
|
+
declare const configs: {
|
|
3
|
+
readonly mail: {};
|
|
4
4
|
};
|
|
5
|
+
export type RedisLockCheckerType = keyof typeof configs;
|
|
6
|
+
export declare const createRedisLockCheckerConfig: (params: {
|
|
7
|
+
type?: RedisLockCheckerType;
|
|
8
|
+
customConfig?: Partial<RedisLockCheckerConfig>;
|
|
9
|
+
}) => RedisLockCheckerConfig;
|
|
10
|
+
export {};
|
|
@@ -1,16 +1,15 @@
|
|
|
1
|
-
import { RedisKeyFactory } from "./redisKeysFactory.js";
|
|
2
1
|
import { Msg } from "../../internal/messaging/messageTags.js";
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
2
|
+
import { getRedisPrefix, getRedisSuffixCallback } from "./redisKeysFactory.js";
|
|
3
|
+
const defaultConfig = {
|
|
4
|
+
keyPrefix: getRedisPrefix("authLockEmail"),
|
|
5
|
+
keySuffixes: getRedisSuffixCallback("mail"),
|
|
6
6
|
message: Msg.apiStatus.locked,
|
|
7
7
|
};
|
|
8
|
-
const
|
|
9
|
-
|
|
8
|
+
const configs = {
|
|
9
|
+
mail: {}
|
|
10
10
|
};
|
|
11
|
-
const
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
mail,
|
|
11
|
+
export const createRedisLockCheckerConfig = (params) => {
|
|
12
|
+
const { type, customConfig } = params;
|
|
13
|
+
const typeConfig = type ? configs[type] : undefined;
|
|
14
|
+
return Object.assign(Object.assign(Object.assign({}, defaultConfig), typeConfig), customConfig);
|
|
16
15
|
};
|
|
@@ -7,17 +7,10 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
7
7
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
8
|
});
|
|
9
9
|
};
|
|
10
|
-
import {
|
|
10
|
+
import { addRedisKey, removeRedisKey } from 'mielk-fn/redis';
|
|
11
11
|
export const setRedisLock = (key, ttlSeconds) => __awaiter(void 0, void 0, void 0, function* () {
|
|
12
|
-
|
|
13
|
-
yield redisClient.set(key, JSON.stringify({ locked: true }), {
|
|
14
|
-
expiration: {
|
|
15
|
-
type: 'EX',
|
|
16
|
-
value: ttlSeconds
|
|
17
|
-
}
|
|
18
|
-
});
|
|
12
|
+
yield addRedisKey(key, { locked: true }, ttlSeconds);
|
|
19
13
|
});
|
|
20
14
|
export const removeRedisLock = (key) => __awaiter(void 0, void 0, void 0, function* () {
|
|
21
|
-
|
|
22
|
-
yield redisClient.del(key);
|
|
15
|
+
yield removeRedisKey(key);
|
|
23
16
|
});
|
|
@@ -1,4 +1,10 @@
|
|
|
1
|
-
import { RedisLockerConfig
|
|
2
|
-
|
|
3
|
-
mail:
|
|
1
|
+
import { RedisLockerConfig } from "./types.js";
|
|
2
|
+
declare const configs: {
|
|
3
|
+
readonly mail: {};
|
|
4
4
|
};
|
|
5
|
+
export type RedisLockerType = keyof typeof configs;
|
|
6
|
+
export declare const createRedisLockCheckerConfig: (params: {
|
|
7
|
+
type?: RedisLockerType;
|
|
8
|
+
customConfig?: Partial<RedisLockerConfig>;
|
|
9
|
+
}) => RedisLockerConfig;
|
|
10
|
+
export {};
|
|
@@ -1,14 +1,13 @@
|
|
|
1
|
-
import {
|
|
2
|
-
const
|
|
3
|
-
keyPrefix:
|
|
1
|
+
import { getRedisPrefix } from "./redisKeysFactory.js";
|
|
2
|
+
const defaultConfig = {
|
|
3
|
+
keyPrefix: getRedisPrefix("authLockEmail"),
|
|
4
4
|
ttlSeconds: 30 * 60,
|
|
5
5
|
};
|
|
6
|
-
const
|
|
7
|
-
|
|
6
|
+
const configs = {
|
|
7
|
+
mail: {}
|
|
8
8
|
};
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
mail,
|
|
9
|
+
export const createRedisLockCheckerConfig = (params) => {
|
|
10
|
+
const { type, customConfig } = params;
|
|
11
|
+
const typeConfig = type ? configs[type] : undefined;
|
|
12
|
+
return Object.assign(Object.assign(Object.assign({}, defaultConfig), typeConfig), customConfig);
|
|
14
13
|
};
|
|
@@ -1,19 +1,11 @@
|
|
|
1
1
|
import { NextFunction, Request, Response } from "express";
|
|
2
2
|
export type RedisLockChecker = (req: Request, res: Response, next: NextFunction) => Promise<void | Response<Record<string, any>, Record<string, any>>>;
|
|
3
|
-
export
|
|
4
|
-
keyPrefix?: string;
|
|
5
|
-
keySuffixes?: (req: Request) => string[];
|
|
6
|
-
message?: string;
|
|
7
|
-
}
|
|
3
|
+
export type RequestParamsFetcher = (req: Request) => string[];
|
|
8
4
|
export interface RedisLockCheckerConfig {
|
|
9
5
|
keyPrefix: string;
|
|
10
|
-
keySuffixes:
|
|
6
|
+
keySuffixes: RequestParamsFetcher;
|
|
11
7
|
message: string;
|
|
12
8
|
}
|
|
13
|
-
export interface RedisLockerConfigParams {
|
|
14
|
-
keyPrefix?: string;
|
|
15
|
-
ttlSeconds?: number;
|
|
16
|
-
}
|
|
17
9
|
export interface RedisLockerConfig {
|
|
18
10
|
keyPrefix: string;
|
|
19
11
|
ttlSeconds: number;
|
|
@@ -2,9 +2,9 @@ import { PostgreDbConfig } from '../db/pg/index.js';
|
|
|
2
2
|
import { MsSqlDbConfig } from '../db/mssql/index.js';
|
|
3
3
|
import { CorsConfig } from '../middlewares/index.js';
|
|
4
4
|
import { DbProvider } from './DbProvider.js';
|
|
5
|
-
import {
|
|
5
|
+
import { RateLimitConfig } from '../middlewares/rateLimit/types.js';
|
|
6
6
|
import { RedisConfig } from 'mielk-fn/redis';
|
|
7
7
|
export type DbConfig = PostgreDbConfig | MsSqlDbConfig;
|
|
8
|
-
export declare const createExpressApp: (isProd: boolean, dbConfig: DbConfig, corsConfig: CorsConfig, redisConfig: RedisConfig, rateLimitConfig?:
|
|
8
|
+
export declare const createExpressApp: (isProd: boolean, dbConfig: DbConfig, corsConfig: CorsConfig, redisConfig: RedisConfig, rateLimitConfig?: Partial<RateLimitConfig>) => Promise<import("express-serve-static-core").Express>;
|
|
9
9
|
export declare const isProd: () => boolean;
|
|
10
10
|
export declare const getDbProvider: () => DbProvider;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mielk-api",
|
|
3
|
-
"version": "1.5.
|
|
3
|
+
"version": "1.5.6",
|
|
4
4
|
"keywords": [],
|
|
5
5
|
"author": "mielk",
|
|
6
6
|
"description": "Wrapper for API operations",
|
|
@@ -37,6 +37,11 @@
|
|
|
37
37
|
"types": "./dist/middlewares/rateLimit/index.d.ts",
|
|
38
38
|
"import": "./dist/middlewares/rateLimit/index.js",
|
|
39
39
|
"default": "./dist/middlewares/rateLimit/index.js"
|
|
40
|
+
},
|
|
41
|
+
"./redis": {
|
|
42
|
+
"types": "./dist/middlewares/redis/index.d.ts",
|
|
43
|
+
"import": "./dist/middlewares/redis/index.js",
|
|
44
|
+
"default": "./dist/middlewares/redis/index.js"
|
|
40
45
|
}
|
|
41
46
|
},
|
|
42
47
|
"scripts": {
|
|
@@ -84,7 +89,7 @@
|
|
|
84
89
|
"dependencies": {
|
|
85
90
|
"cors": "^2.8.6",
|
|
86
91
|
"express-rate-limit": "^8.3.1",
|
|
87
|
-
"mielk-fn": "^1.2.
|
|
92
|
+
"mielk-fn": "^1.2.3",
|
|
88
93
|
"pg": "^8.20.0",
|
|
89
94
|
"tunnel-ssh": "^5.2.0"
|
|
90
95
|
}
|