fiberx-backend-toolkit 0.0.54 → 0.0.57
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/config/constants.d.ts +2 -0
- package/dist/config/constants.js +3 -1
- package/dist/middle_ware/cors_middle_ware.js +1 -1
- package/dist/middle_ware/rate_limiter_middle_ware.js +1 -1
- package/dist/rbac/main.d.ts +2 -0
- package/dist/rbac/main.js +8 -0
- package/dist/rbac/rbac_loader_util.d.ts +37 -0
- package/dist/rbac/rbac_loader_util.js +138 -0
- package/dist/types/main.d.ts +1 -0
- package/dist/types/main.js +1 -0
- package/dist/types/rbac_type.d.ts +28 -0
- package/dist/types/rbac_type.js +2 -0
- package/dist/utils/cache_util.d.ts +2 -2
- package/dist/utils/cache_util.js +2 -2
- package/dist/utils/main.d.ts +2 -2
- package/dist/utils/main.js +2 -2
- package/package.json +1 -1
|
@@ -28,3 +28,5 @@ export declare const ALPHABET_CORPUS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
|
|
|
28
28
|
export declare const DEFAULT_TOTP_STEP = 30;
|
|
29
29
|
export declare const DEFAULT_TOTP_DIGITS = 6;
|
|
30
30
|
export declare const DEFAULT_TOTP_WINDOW = 1;
|
|
31
|
+
export declare const DEFAULT_RBAC_CACHE_KEY = "RBAC_SNAPSHOT";
|
|
32
|
+
export declare const DEFAULT_RBAC_CACHE_TTL: number;
|
package/dist/config/constants.js
CHANGED
|
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.DEFAULT_TOTP_WINDOW = exports.DEFAULT_TOTP_DIGITS = exports.DEFAULT_TOTP_STEP = exports.ALPHABET_CORPUS = exports.CHARACTER_CORPUS = exports.REQUEST_RATE_LIMITTER_OPTIONS = exports.CORS_MAX_AGE_IN_MICRO_SECONDS = exports.CORS_MAX_AGE_IN_SECONDS = exports.CORS_ALLOWED_HEADERS = exports.CORS_ALLOWED_METHODS = exports.DEVICE_ID_HEADERS_NAME = exports.DEVICE_ID_COOKIE_NAME = exports.DEVICE_ID_COOKIE_MAX_AGE = exports.REQUEST_ID_HEADERS_NAME = exports.REQUEST_ID_COOKIE_NAME = exports.REQUEST_ID_COOKIE_MAX_AGE = exports.SEQUELIZE_SEEDER_META_TABLE_NAME = exports.SEQUELIZE_META_TABLE_NAME = exports.SEEDERS_DIR = exports.MIGRATIONS_DIR = exports.MODELS_DIR = exports.SCHEMA_SNAPSHOTS_DIR = exports.SCHEMAS_DIR = exports.ENV_VAR_DIR = exports.LOG_DIR = exports.BASE_DIR = void 0;
|
|
6
|
+
exports.DEFAULT_RBAC_CACHE_TTL = exports.DEFAULT_RBAC_CACHE_KEY = exports.DEFAULT_TOTP_WINDOW = exports.DEFAULT_TOTP_DIGITS = exports.DEFAULT_TOTP_STEP = exports.ALPHABET_CORPUS = exports.CHARACTER_CORPUS = exports.REQUEST_RATE_LIMITTER_OPTIONS = exports.CORS_MAX_AGE_IN_MICRO_SECONDS = exports.CORS_MAX_AGE_IN_SECONDS = exports.CORS_ALLOWED_HEADERS = exports.CORS_ALLOWED_METHODS = exports.DEVICE_ID_HEADERS_NAME = exports.DEVICE_ID_COOKIE_NAME = exports.DEVICE_ID_COOKIE_MAX_AGE = exports.REQUEST_ID_HEADERS_NAME = exports.REQUEST_ID_COOKIE_NAME = exports.REQUEST_ID_COOKIE_MAX_AGE = exports.SEQUELIZE_SEEDER_META_TABLE_NAME = exports.SEQUELIZE_META_TABLE_NAME = exports.SEEDERS_DIR = exports.MIGRATIONS_DIR = exports.MODELS_DIR = exports.SCHEMA_SNAPSHOTS_DIR = exports.SCHEMAS_DIR = exports.ENV_VAR_DIR = exports.LOG_DIR = exports.BASE_DIR = void 0;
|
|
7
7
|
const path_1 = __importDefault(require("path"));
|
|
8
8
|
// Database constants
|
|
9
9
|
exports.BASE_DIR = process.cwd();
|
|
@@ -38,3 +38,5 @@ exports.ALPHABET_CORPUS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
|
|
|
38
38
|
exports.DEFAULT_TOTP_STEP = 30;
|
|
39
39
|
exports.DEFAULT_TOTP_DIGITS = 6;
|
|
40
40
|
exports.DEFAULT_TOTP_WINDOW = 1;
|
|
41
|
+
exports.DEFAULT_RBAC_CACHE_KEY = "RBAC_SNAPSHOT";
|
|
42
|
+
exports.DEFAULT_RBAC_CACHE_TTL = (1000 * 60 * 60 * 24); // 24 hours
|
|
@@ -14,7 +14,7 @@ const main_1 = require("../utils/main");
|
|
|
14
14
|
class CorsMiddleWare {
|
|
15
15
|
name = "cors_middle_ware";
|
|
16
16
|
logger = new main_1.LoggerUtil(this.name);
|
|
17
|
-
origin_cache = new main_1.
|
|
17
|
+
origin_cache = new main_1.InMemoryCacheUtil();
|
|
18
18
|
origins;
|
|
19
19
|
methods;
|
|
20
20
|
headers;
|
|
@@ -24,7 +24,7 @@ class RateLimiterMiddleWare {
|
|
|
24
24
|
this.max_requests = options?.max_requests ?? constants_1.REQUEST_RATE_LIMITTER_OPTIONS.max_requests;
|
|
25
25
|
this.message = options.message ?? constants_1.REQUEST_RATE_LIMITTER_OPTIONS.message;
|
|
26
26
|
this.key_generator = options?.key_generator || this.generateRequestIdentitfier;
|
|
27
|
-
this.cache = new main_1.
|
|
27
|
+
this.cache = new main_1.InMemoryCacheUtil();
|
|
28
28
|
this.logger = new main_1.LoggerUtil(this.name);
|
|
29
29
|
main_1.SafeExecuteUtil.setNamedInstance(this.name, this);
|
|
30
30
|
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.RBACLoaderUtil = void 0;
|
|
7
|
+
const rbac_loader_util_1 = __importDefault(require("../rbac/rbac_loader_util"));
|
|
8
|
+
exports.RBACLoaderUtil = rbac_loader_util_1.default;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { RBACDataProvider, RBACOptionsInterface } from "../types/rbac_type";
|
|
2
|
+
declare class RBACLoaderUtil<TSafeRole> {
|
|
3
|
+
private readonly provider;
|
|
4
|
+
private static instance;
|
|
5
|
+
private readonly logger;
|
|
6
|
+
private readonly cache;
|
|
7
|
+
private readonly RBAC_CACHE_KEY;
|
|
8
|
+
private readonly DEFAULT_TTL;
|
|
9
|
+
private loading_promise;
|
|
10
|
+
private constructor();
|
|
11
|
+
static initialize<TSafeRole>(provider: RBACDataProvider<TSafeRole>, options?: RBACOptionsInterface): RBACLoaderUtil<TSafeRole>;
|
|
12
|
+
static getInstance<TSafeRole>(): RBACLoaderUtil<TSafeRole>;
|
|
13
|
+
/**
|
|
14
|
+
* ===============================
|
|
15
|
+
* LOAD RBAC
|
|
16
|
+
* ===============================
|
|
17
|
+
*/
|
|
18
|
+
load(force_refresh?: boolean): Promise<void>;
|
|
19
|
+
/**
|
|
20
|
+
* ===============================
|
|
21
|
+
* BUILD SNAPSHOT
|
|
22
|
+
* ===============================
|
|
23
|
+
*/
|
|
24
|
+
private buildSnapshot;
|
|
25
|
+
/**
|
|
26
|
+
* ===============================
|
|
27
|
+
* ACCESSORS
|
|
28
|
+
* ===============================
|
|
29
|
+
*/
|
|
30
|
+
private getSnapshot;
|
|
31
|
+
getRoleById(role_id: number): TSafeRole | undefined;
|
|
32
|
+
getRoleBySymbol(symbol: string): TSafeRole | undefined;
|
|
33
|
+
getPermissionsForRole(role_id: number): string[];
|
|
34
|
+
roleHasPermission(role_id: number, permission_key: string): boolean;
|
|
35
|
+
refresh(): Promise<void>;
|
|
36
|
+
}
|
|
37
|
+
export default RBACLoaderUtil;
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const main_1 = require("../utils/main");
|
|
4
|
+
const constants_1 = require("../config/constants");
|
|
5
|
+
class RBACLoaderUtil {
|
|
6
|
+
provider;
|
|
7
|
+
static instance = null;
|
|
8
|
+
logger = new main_1.LoggerUtil("rbac_loader_util");
|
|
9
|
+
cache = new main_1.InMemoryCacheUtil();
|
|
10
|
+
RBAC_CACHE_KEY;
|
|
11
|
+
DEFAULT_TTL;
|
|
12
|
+
loading_promise = null;
|
|
13
|
+
constructor(provider, options) {
|
|
14
|
+
this.provider = provider;
|
|
15
|
+
this.RBAC_CACHE_KEY = options?.rbac_cache_key ?? constants_1.DEFAULT_RBAC_CACHE_KEY;
|
|
16
|
+
this.DEFAULT_TTL = options?.cache_ttl ?? constants_1.DEFAULT_RBAC_CACHE_TTL;
|
|
17
|
+
}
|
|
18
|
+
//Method to Initialize singleton (MUST be called once)
|
|
19
|
+
static initialize(provider, options) {
|
|
20
|
+
if (this.instance) {
|
|
21
|
+
throw new Error("RBACLoaderUtil already initialized.");
|
|
22
|
+
}
|
|
23
|
+
this.instance = new RBACLoaderUtil(provider, options);
|
|
24
|
+
return this.instance;
|
|
25
|
+
}
|
|
26
|
+
// Method to Get singleton instance
|
|
27
|
+
static getInstance() {
|
|
28
|
+
if (!this.instance) {
|
|
29
|
+
throw new Error("RBACLoaderUtil not initialized.");
|
|
30
|
+
}
|
|
31
|
+
return this.instance;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* ===============================
|
|
35
|
+
* LOAD RBAC
|
|
36
|
+
* ===============================
|
|
37
|
+
*/
|
|
38
|
+
async load(force_refresh = false) {
|
|
39
|
+
if (!force_refresh && this.cache.has(this.RBAC_CACHE_KEY)) {
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
if (this.loading_promise) {
|
|
43
|
+
return this.loading_promise;
|
|
44
|
+
}
|
|
45
|
+
this.loading_promise = (async () => {
|
|
46
|
+
try {
|
|
47
|
+
const snapshot = await this.buildSnapshot();
|
|
48
|
+
this.cache.set(this.RBAC_CACHE_KEY, snapshot, this.DEFAULT_TTL);
|
|
49
|
+
}
|
|
50
|
+
catch (error) {
|
|
51
|
+
this.logger.error("Failed to load RBAC snapshot", { error });
|
|
52
|
+
throw error;
|
|
53
|
+
}
|
|
54
|
+
finally {
|
|
55
|
+
this.loading_promise = null;
|
|
56
|
+
}
|
|
57
|
+
})();
|
|
58
|
+
return this.loading_promise;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* ===============================
|
|
62
|
+
* BUILD SNAPSHOT
|
|
63
|
+
* ===============================
|
|
64
|
+
*/
|
|
65
|
+
async buildSnapshot() {
|
|
66
|
+
const roles = await this.provider.fetchRoles();
|
|
67
|
+
const permissions = await this.provider.fetchPermissions();
|
|
68
|
+
const role_permissions = await this.provider.fetchRolePermissions();
|
|
69
|
+
const role_by_id = new Map();
|
|
70
|
+
const role_by_symbol = new Map();
|
|
71
|
+
const permission_by_id = new Map();
|
|
72
|
+
const permissions_by_role_id = new Map();
|
|
73
|
+
// Roles
|
|
74
|
+
for (const role of roles) {
|
|
75
|
+
const safe = this.provider.mapRoleToSafe(role);
|
|
76
|
+
const id = this.provider.getRoleId(role);
|
|
77
|
+
const symbol = this.provider.getRoleSymbol(role);
|
|
78
|
+
role_by_id.set(id, safe);
|
|
79
|
+
role_by_symbol.set(symbol, safe);
|
|
80
|
+
}
|
|
81
|
+
// Permissions
|
|
82
|
+
for (const permission of permissions) {
|
|
83
|
+
const id = this.provider.getPermissionId(permission);
|
|
84
|
+
const key = this.provider.getPermissionKey(permission);
|
|
85
|
+
permission_by_id.set(id, key);
|
|
86
|
+
}
|
|
87
|
+
// RolePermissions
|
|
88
|
+
for (const rp of role_permissions) {
|
|
89
|
+
const role_id = this.provider.getRolePermissionRoleId(rp);
|
|
90
|
+
const permission_id = this.provider.getRolePermissionPermissionId(rp);
|
|
91
|
+
const permission_key = permission_by_id.get(permission_id);
|
|
92
|
+
if (!permission_key) {
|
|
93
|
+
continue;
|
|
94
|
+
}
|
|
95
|
+
if (!permissions_by_role_id.has(role_id)) {
|
|
96
|
+
permissions_by_role_id.set(role_id, new Set());
|
|
97
|
+
}
|
|
98
|
+
permissions_by_role_id.get(role_id).add(permission_key);
|
|
99
|
+
}
|
|
100
|
+
return {
|
|
101
|
+
role_by_id,
|
|
102
|
+
role_by_symbol,
|
|
103
|
+
permission_by_id,
|
|
104
|
+
permissions_by_role_id
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* ===============================
|
|
109
|
+
* ACCESSORS
|
|
110
|
+
* ===============================
|
|
111
|
+
*/
|
|
112
|
+
getSnapshot() {
|
|
113
|
+
const snapshot = this.cache.get(this.RBAC_CACHE_KEY);
|
|
114
|
+
if (!snapshot) {
|
|
115
|
+
throw new Error("RBAC snapshot not loaded. Call load() first.");
|
|
116
|
+
}
|
|
117
|
+
return snapshot;
|
|
118
|
+
}
|
|
119
|
+
getRoleById(role_id) {
|
|
120
|
+
return this.getSnapshot().role_by_id.get(role_id);
|
|
121
|
+
}
|
|
122
|
+
getRoleBySymbol(symbol) {
|
|
123
|
+
return this.getSnapshot().role_by_symbol.get(symbol);
|
|
124
|
+
}
|
|
125
|
+
getPermissionsForRole(role_id) {
|
|
126
|
+
return Array.from(this.getSnapshot().permissions_by_role_id.get(role_id) ?? []);
|
|
127
|
+
}
|
|
128
|
+
roleHasPermission(role_id, permission_key) {
|
|
129
|
+
return (this.getSnapshot()
|
|
130
|
+
.permissions_by_role_id
|
|
131
|
+
.get(role_id)
|
|
132
|
+
?.has(permission_key) ?? false);
|
|
133
|
+
}
|
|
134
|
+
async refresh() {
|
|
135
|
+
await this.load(true);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
exports.default = RBACLoaderUtil;
|
package/dist/types/main.d.ts
CHANGED
package/dist/types/main.js
CHANGED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export interface RBACOptionsInterface {
|
|
2
|
+
rbac_cache_key?: string;
|
|
3
|
+
cache_ttl?: number;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Generic RBAC snapshot
|
|
7
|
+
*/
|
|
8
|
+
export type RBACSnapshot<TSafeRole> = {
|
|
9
|
+
role_by_id: Map<number, TSafeRole>;
|
|
10
|
+
role_by_symbol: Map<string, TSafeRole>;
|
|
11
|
+
permission_by_id: Map<number, string>;
|
|
12
|
+
permissions_by_role_id: Map<number, Set<string>>;
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* Provider contract (each app implements this)
|
|
16
|
+
*/
|
|
17
|
+
export interface RBACDataProvider<TSafeRole> {
|
|
18
|
+
fetchRoles(): Promise<any[]>;
|
|
19
|
+
fetchPermissions(): Promise<any[]>;
|
|
20
|
+
fetchRolePermissions(): Promise<any[]>;
|
|
21
|
+
mapRoleToSafe(role: any): TSafeRole;
|
|
22
|
+
getRoleId(role: any): number;
|
|
23
|
+
getRoleSymbol(role: any): string;
|
|
24
|
+
getPermissionId(permission: any): number;
|
|
25
|
+
getPermissionKey(permission: any): string;
|
|
26
|
+
getRolePermissionRoleId(rp: any): number;
|
|
27
|
+
getRolePermissionPermissionId(rp: any): number;
|
|
28
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
declare class
|
|
1
|
+
declare class InMemoryCacheUtil<T = unknown> {
|
|
2
2
|
private store;
|
|
3
3
|
/**
|
|
4
4
|
* Set a cache value with TTL (ms)
|
|
@@ -37,4 +37,4 @@ declare class InMemoryCache<T = unknown> {
|
|
|
37
37
|
*/
|
|
38
38
|
size(): number;
|
|
39
39
|
}
|
|
40
|
-
export default
|
|
40
|
+
export default InMemoryCacheUtil;
|
package/dist/utils/cache_util.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
class
|
|
3
|
+
class InMemoryCacheUtil {
|
|
4
4
|
store = new Map();
|
|
5
5
|
/**
|
|
6
6
|
* Set a cache value with TTL (ms)
|
|
@@ -80,4 +80,4 @@ class InMemoryCache {
|
|
|
80
80
|
return this.store.size;
|
|
81
81
|
}
|
|
82
82
|
}
|
|
83
|
-
exports.default =
|
|
83
|
+
exports.default = InMemoryCacheUtil;
|
package/dist/utils/main.d.ts
CHANGED
|
@@ -5,8 +5,8 @@ import EnvManagerUtil from "./env_manager_util";
|
|
|
5
5
|
import SqlFormatterUtil from "./sql_formatter_util";
|
|
6
6
|
import ServerUtil from "./server_util";
|
|
7
7
|
import SafeExecuteUtil from "./safe_execute_util";
|
|
8
|
-
import
|
|
8
|
+
import InMemoryCacheUtil from "./cache_util";
|
|
9
9
|
import UUIDGeneratorUtil from "./uuid_gen_util";
|
|
10
10
|
import EncryptorDecryptorUtil from "./encryptor_decryptor_util";
|
|
11
11
|
import TOTPServiceUtil from "./totp_service_util";
|
|
12
|
-
export { LoggerUtil, InputTransformerUtil, InputValidatorUtil, EnvManagerUtil, SqlFormatterUtil, ServerUtil, SafeExecuteUtil,
|
|
12
|
+
export { LoggerUtil, InputTransformerUtil, InputValidatorUtil, EnvManagerUtil, SqlFormatterUtil, ServerUtil, SafeExecuteUtil, InMemoryCacheUtil, UUIDGeneratorUtil, EncryptorDecryptorUtil, TOTPServiceUtil };
|
package/dist/utils/main.js
CHANGED
|
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.TOTPServiceUtil = exports.EncryptorDecryptorUtil = exports.UUIDGeneratorUtil = exports.
|
|
6
|
+
exports.TOTPServiceUtil = exports.EncryptorDecryptorUtil = exports.UUIDGeneratorUtil = exports.InMemoryCacheUtil = exports.SafeExecuteUtil = exports.ServerUtil = exports.SqlFormatterUtil = exports.EnvManagerUtil = exports.InputValidatorUtil = exports.InputTransformerUtil = exports.LoggerUtil = void 0;
|
|
7
7
|
const logger_util_1 = __importDefault(require("./logger_util"));
|
|
8
8
|
exports.LoggerUtil = logger_util_1.default;
|
|
9
9
|
const input_transformer_util_1 = __importDefault(require("./input_transformer_util"));
|
|
@@ -19,7 +19,7 @@ exports.ServerUtil = server_util_1.default;
|
|
|
19
19
|
const safe_execute_util_1 = __importDefault(require("./safe_execute_util"));
|
|
20
20
|
exports.SafeExecuteUtil = safe_execute_util_1.default;
|
|
21
21
|
const cache_util_1 = __importDefault(require("./cache_util"));
|
|
22
|
-
exports.
|
|
22
|
+
exports.InMemoryCacheUtil = cache_util_1.default;
|
|
23
23
|
const uuid_gen_util_1 = __importDefault(require("./uuid_gen_util"));
|
|
24
24
|
exports.UUIDGeneratorUtil = uuid_gen_util_1.default;
|
|
25
25
|
const encryptor_decryptor_util_1 = __importDefault(require("./encryptor_decryptor_util"));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fiberx-backend-toolkit",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.57",
|
|
4
4
|
"description": "A TypeScript backend toolkit providing shared domain logic, infrastructure helpers, and utilities for FiberX server-side applications and services.",
|
|
5
5
|
"type": "commonjs",
|
|
6
6
|
"main": "./dist/index.js",
|