hi-secure 1.0.26 → 1.0.27
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/adapters/JWTAdapter.js.map +1 -1
- package/dist/core/HiSecure.d.ts +15 -36
- package/dist/core/HiSecure.d.ts.map +1 -1
- package/dist/core/HiSecure.js +78 -138
- package/dist/core/HiSecure.js.map +1 -1
- package/dist/core/useSecure.d.ts +4 -1
- package/dist/core/useSecure.d.ts.map +1 -1
- package/dist/core/useSecure.js +58 -13
- package/dist/core/useSecure.js.map +1 -1
- package/dist/index.d.ts +1 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +13 -4
- package/dist/index.js.map +1 -1
- package/dist/managers/AuthManager.js.map +1 -1
- package/package.json +1 -1
- package/src/core/HiSecure.ts +490 -258
- package/src/core/useSecure.ts +94 -37
- package/src/index.ts +25 -11
package/src/core/HiSecure.ts
CHANGED
|
@@ -1,3 +1,331 @@
|
|
|
1
|
+
// import { HiSecureConfig } from "./types/HiSecureConfig.js";
|
|
2
|
+
// import { defaultConfig } from "./config.js";
|
|
3
|
+
// import { LIB_NAME, LIB_VERSION } from "./constants.js";
|
|
4
|
+
// import { deepMerge } from "../utils/deepMerge.js";
|
|
5
|
+
// import { deepFreeze } from "../utils/deepFreeze.js";
|
|
6
|
+
// import { logger } from "../logging";
|
|
7
|
+
|
|
8
|
+
// // Adapters
|
|
9
|
+
// import { ArgonAdapter } from "../adapters/ArgonAdapter.js";
|
|
10
|
+
// import { BcryptAdapter } from "../adapters/BcryptAdapter.js";
|
|
11
|
+
// import { RLFlexibleAdapter } from "../adapters/RLFlexibleAdapter.js";
|
|
12
|
+
// import { ExpressRLAdapter } from "../adapters/ExpressRLAdapter.js";
|
|
13
|
+
// import { ZodAdapter } from "../adapters/ZodAdapter.js";
|
|
14
|
+
// import { ExpressValidatorAdapter } from "../adapters/ExpressValidatorAdapter.js";
|
|
15
|
+
// import { SanitizeHtmlAdapter } from "../adapters/SanitizeHtmlAdapter.js";
|
|
16
|
+
// import { XSSAdapter } from "../adapters/XSSAdapter.js";
|
|
17
|
+
|
|
18
|
+
// // Managers
|
|
19
|
+
// import { HashManager } from "../managers/HashManager.js";
|
|
20
|
+
// import { RateLimitManager } from "../managers/RateLimitManager.js";
|
|
21
|
+
// import { ValidatorManager } from "../managers/ValidatorManager.js";
|
|
22
|
+
// import { SanitizerManager } from "../managers/SanitizerManager.js";
|
|
23
|
+
// import { JsonManager } from "../managers/JsonManager.js";
|
|
24
|
+
// import { CorsManager } from "../managers/CorsManager.js";
|
|
25
|
+
// import { AuthManager } from "../managers/AuthManager.js";
|
|
26
|
+
|
|
27
|
+
// // Middlewares
|
|
28
|
+
// import helmet from "helmet";
|
|
29
|
+
// import hpp from "hpp";
|
|
30
|
+
// import compression from "compression";
|
|
31
|
+
// import { errorHandler } from "../middlewares/errorHandler.js";
|
|
32
|
+
|
|
33
|
+
// // Types
|
|
34
|
+
// import { SecureOptions, ValidationSchema } from "./types/SecureOptions.js";
|
|
35
|
+
|
|
36
|
+
// export class HiSecure {
|
|
37
|
+
// private static instance: HiSecure | null = null;
|
|
38
|
+
// private config: HiSecureConfig;
|
|
39
|
+
// private initialized = false;
|
|
40
|
+
|
|
41
|
+
// // Managers
|
|
42
|
+
// public hashManager!: HashManager;
|
|
43
|
+
// public rateLimitManager!: RateLimitManager;
|
|
44
|
+
// public validatorManager!: ValidatorManager;
|
|
45
|
+
// public sanitizerManager!: SanitizerManager;
|
|
46
|
+
// public jsonManager!: JsonManager;
|
|
47
|
+
// public corsManager!: CorsManager;
|
|
48
|
+
// public authManager?: AuthManager;
|
|
49
|
+
|
|
50
|
+
// // Internal adapters
|
|
51
|
+
// private hashingPrimary: any;
|
|
52
|
+
// private hashingFallback: any;
|
|
53
|
+
// private rateLimiterPrimary: any;
|
|
54
|
+
// private rateLimiterFallback: any;
|
|
55
|
+
// private sanitizerPrimary: any;
|
|
56
|
+
// private sanitizerFallback: any;
|
|
57
|
+
|
|
58
|
+
// private constructor(userConfig: Partial<HiSecureConfig> = {}) {
|
|
59
|
+
// this.config = deepMerge(defaultConfig, userConfig);
|
|
60
|
+
// }
|
|
61
|
+
|
|
62
|
+
// // Singleton & Init
|
|
63
|
+
|
|
64
|
+
// static getInstance(config?: Partial<HiSecureConfig>): HiSecure {
|
|
65
|
+
// if (!HiSecure.instance) {
|
|
66
|
+
// logger.info("Creating HiSecure singleton", {
|
|
67
|
+
// layer: "hisecure-core"
|
|
68
|
+
// });
|
|
69
|
+
// HiSecure.instance = new HiSecure(config);
|
|
70
|
+
// HiSecure.instance.init();
|
|
71
|
+
// }
|
|
72
|
+
// return HiSecure.instance;
|
|
73
|
+
// }
|
|
74
|
+
|
|
75
|
+
// static resetInstance(): void {
|
|
76
|
+
// HiSecure.instance = null;
|
|
77
|
+
// }
|
|
78
|
+
|
|
79
|
+
// init(): void {
|
|
80
|
+
// if (this.initialized) {
|
|
81
|
+
// logger.warn("Initialization skipped (already initialized)", {
|
|
82
|
+
// layer: "hisecure-core"
|
|
83
|
+
// });
|
|
84
|
+
// return;
|
|
85
|
+
// }
|
|
86
|
+
|
|
87
|
+
// logger.info("Framework initialization started", {
|
|
88
|
+
// layer: "hisecure-core",
|
|
89
|
+
// lib: LIB_NAME,
|
|
90
|
+
// version: LIB_VERSION
|
|
91
|
+
// });
|
|
92
|
+
|
|
93
|
+
// this.setupAdapters();
|
|
94
|
+
// this.setupManagers();
|
|
95
|
+
// this.setupDynamicManagers();
|
|
96
|
+
|
|
97
|
+
// deepFreeze(this.config);
|
|
98
|
+
// this.initialized = true;
|
|
99
|
+
|
|
100
|
+
// logger.info("Framework initialized successfully", {
|
|
101
|
+
// layer: "hisecure-core"
|
|
102
|
+
// });
|
|
103
|
+
// }
|
|
104
|
+
|
|
105
|
+
// // Public Fluent API
|
|
106
|
+
// static auth(options?: { required?: boolean; roles?: string[] }) {
|
|
107
|
+
// const instance = this.getInstance();
|
|
108
|
+
// if (!instance.authManager) {
|
|
109
|
+
// throw new Error("Auth not enabled. Set auth.enabled=true in config.");
|
|
110
|
+
// }
|
|
111
|
+
// return instance.authManager.protect(options);
|
|
112
|
+
// }
|
|
113
|
+
|
|
114
|
+
// static validate(schema: ValidationSchema) {
|
|
115
|
+
// return this.getInstance().validatorManager.validate(schema);
|
|
116
|
+
// }
|
|
117
|
+
|
|
118
|
+
// static sanitize(options?: any) {
|
|
119
|
+
// return this.getInstance().sanitizerManager.middleware(options);
|
|
120
|
+
// }
|
|
121
|
+
|
|
122
|
+
// static rateLimit(preset: "strict" | "relaxed" | "api" | object) {
|
|
123
|
+
// const instance = this.getInstance();
|
|
124
|
+
|
|
125
|
+
// if (typeof preset === "string") {
|
|
126
|
+
// logger.info("Rate limit preset applied", {
|
|
127
|
+
// layer: "hisecure-core",
|
|
128
|
+
// preset
|
|
129
|
+
// });
|
|
130
|
+
|
|
131
|
+
// const presets: any = {
|
|
132
|
+
// strict: { mode: "strict" },
|
|
133
|
+
// relaxed: { mode: "relaxed" },
|
|
134
|
+
// api: { mode: "api" }
|
|
135
|
+
// };
|
|
136
|
+
// return instance.rateLimitManager.middleware(presets[preset]);
|
|
137
|
+
// }
|
|
138
|
+
|
|
139
|
+
// return instance.rateLimitManager.middleware({ options: preset });
|
|
140
|
+
// }
|
|
141
|
+
|
|
142
|
+
// static cors(options?: any) {
|
|
143
|
+
// return this.getInstance().corsManager.middleware(options);
|
|
144
|
+
// }
|
|
145
|
+
|
|
146
|
+
// static json(options?: any) {
|
|
147
|
+
// const instance = this.getInstance();
|
|
148
|
+
// return [
|
|
149
|
+
// instance.jsonManager.middleware(options),
|
|
150
|
+
// instance.jsonManager.urlencoded()
|
|
151
|
+
// ];
|
|
152
|
+
// }
|
|
153
|
+
|
|
154
|
+
// // Utilities
|
|
155
|
+
|
|
156
|
+
// static async hash(value: string): Promise<string> {
|
|
157
|
+
// const instance = this.getInstance();
|
|
158
|
+
// const result = await instance.hashManager.hash(value, { allowFallback: true });
|
|
159
|
+
// return result.hash;
|
|
160
|
+
// }
|
|
161
|
+
|
|
162
|
+
// static async verify(value: string, hash: string): Promise<boolean> {
|
|
163
|
+
// return this.getInstance().hashManager.verify(value, hash);
|
|
164
|
+
// }
|
|
165
|
+
|
|
166
|
+
// static jwt = {
|
|
167
|
+
// sign: (payload: object, options?: any) =>
|
|
168
|
+
// HiSecure.getInstance().authManager!.sign(payload, options),
|
|
169
|
+
|
|
170
|
+
// verify: (token: string) =>
|
|
171
|
+
// HiSecure.getInstance().authManager!.verify(token),
|
|
172
|
+
|
|
173
|
+
// google: {
|
|
174
|
+
// verifyIdToken: (idToken: string) =>
|
|
175
|
+
// HiSecure.getInstance().authManager!.verifyGoogleIdToken(idToken)
|
|
176
|
+
// }
|
|
177
|
+
// };
|
|
178
|
+
|
|
179
|
+
// // Global Middleware - globalLevel
|
|
180
|
+
// static middleware(options?: SecureOptions | "api" | "strict" | "public") {
|
|
181
|
+
// const instance = this.getInstance();
|
|
182
|
+
|
|
183
|
+
// if (typeof options === "string") {
|
|
184
|
+
// logger.info("Global middleware preset applied", {
|
|
185
|
+
// layer: "hisecure-core",
|
|
186
|
+
// preset: options
|
|
187
|
+
// });
|
|
188
|
+
|
|
189
|
+
// const presets: any = {
|
|
190
|
+
// api: { cors: true, rateLimit: "relaxed", sanitize: true },
|
|
191
|
+
// strict: { cors: true, rateLimit: "strict", sanitize: true, auth: true },
|
|
192
|
+
// public: { cors: true, rateLimit: true, sanitize: false }
|
|
193
|
+
// };
|
|
194
|
+
|
|
195
|
+
// return instance.createMiddlewareChain(presets[options] || {});
|
|
196
|
+
// }
|
|
197
|
+
|
|
198
|
+
// return instance.createMiddlewareChain(options || {});
|
|
199
|
+
// }
|
|
200
|
+
|
|
201
|
+
// // Internal Setup
|
|
202
|
+
|
|
203
|
+
// private setupAdapters() {
|
|
204
|
+
// logger.info("Adapters setup started", {
|
|
205
|
+
// layer: "hisecure-core"
|
|
206
|
+
// });
|
|
207
|
+
|
|
208
|
+
// this.hashingPrimary =
|
|
209
|
+
// this.config.hashing.primary === "argon2"
|
|
210
|
+
// ? new ArgonAdapter()
|
|
211
|
+
// : new BcryptAdapter(this.config.hashing.saltRounds);
|
|
212
|
+
|
|
213
|
+
// this.hashingFallback =
|
|
214
|
+
// this.config.hashing.fallback === "bcrypt"
|
|
215
|
+
// ? new BcryptAdapter(this.config.hashing.saltRounds)
|
|
216
|
+
// : null;
|
|
217
|
+
|
|
218
|
+
// logger.info("Hashing adapters configured", {
|
|
219
|
+
// layer: "hisecure-core",
|
|
220
|
+
// primary: this.config.hashing.primary,
|
|
221
|
+
// fallback: this.config.hashing.fallback ?? null
|
|
222
|
+
// });
|
|
223
|
+
|
|
224
|
+
// this.rateLimiterPrimary = this.config.rateLimiter.useAdaptiveMode
|
|
225
|
+
// ? new RLFlexibleAdapter()
|
|
226
|
+
// : new ExpressRLAdapter();
|
|
227
|
+
|
|
228
|
+
// this.rateLimiterFallback = new ExpressRLAdapter();
|
|
229
|
+
|
|
230
|
+
// logger.info("Rate limiter adapters configured", {
|
|
231
|
+
// layer: "hisecure-core",
|
|
232
|
+
// adaptive: this.config.rateLimiter.useAdaptiveMode
|
|
233
|
+
// });
|
|
234
|
+
|
|
235
|
+
// this.sanitizerPrimary = new SanitizeHtmlAdapter(this.config.sanitizer);
|
|
236
|
+
// this.sanitizerFallback = new XSSAdapter(this.config.sanitizer);
|
|
237
|
+
|
|
238
|
+
// logger.info("Sanitizer adapters configured", {
|
|
239
|
+
// layer: "hisecure-core",
|
|
240
|
+
// primary: "sanitize-html",
|
|
241
|
+
// fallback: "xss"
|
|
242
|
+
// });
|
|
243
|
+
// }
|
|
244
|
+
|
|
245
|
+
// private setupManagers() {
|
|
246
|
+
// this.hashManager = new HashManager(
|
|
247
|
+
// this.config.hashing,
|
|
248
|
+
// this.hashingPrimary,
|
|
249
|
+
// this.hashingFallback
|
|
250
|
+
// );
|
|
251
|
+
|
|
252
|
+
// this.rateLimitManager = new RateLimitManager(
|
|
253
|
+
// this.config.rateLimiter,
|
|
254
|
+
// this.rateLimiterPrimary,
|
|
255
|
+
// this.rateLimiterFallback
|
|
256
|
+
// );
|
|
257
|
+
|
|
258
|
+
// this.validatorManager = new ValidatorManager(
|
|
259
|
+
// new ZodAdapter(),
|
|
260
|
+
// new ExpressValidatorAdapter()
|
|
261
|
+
// );
|
|
262
|
+
|
|
263
|
+
// this.sanitizerManager = new SanitizerManager(
|
|
264
|
+
// this.sanitizerPrimary,
|
|
265
|
+
// this.sanitizerFallback
|
|
266
|
+
// );
|
|
267
|
+
|
|
268
|
+
// logger.info("Core managers initialized", {
|
|
269
|
+
// layer: "hisecure-core",
|
|
270
|
+
// managers: ["hash", "rate-limit", "validator", "sanitizer"]
|
|
271
|
+
// });
|
|
272
|
+
// }
|
|
273
|
+
|
|
274
|
+
// private setupDynamicManagers() {
|
|
275
|
+
// this.jsonManager = new JsonManager();
|
|
276
|
+
// this.corsManager = new CorsManager();
|
|
277
|
+
|
|
278
|
+
// if (this.config.auth.enabled) {
|
|
279
|
+
// this.authManager = new AuthManager({
|
|
280
|
+
// jwtSecret: process.env.JWT_SECRET || this.config.auth.jwtSecret!,
|
|
281
|
+
// jwtExpiresIn: this.config.auth.jwtExpiresIn,
|
|
282
|
+
// googleClientId:
|
|
283
|
+
// process.env.GOOGLE_CLIENT_ID || this.config.auth.googleClientId
|
|
284
|
+
// });
|
|
285
|
+
|
|
286
|
+
// logger.info("Authentication enabled", {
|
|
287
|
+
// layer: "hisecure-core",
|
|
288
|
+
// google: !!this.config.auth.googleClientId
|
|
289
|
+
// });
|
|
290
|
+
// } else {
|
|
291
|
+
// logger.info("Authentication disabled", {
|
|
292
|
+
// layer: "hisecure-core"
|
|
293
|
+
// });
|
|
294
|
+
// }
|
|
295
|
+
// }
|
|
296
|
+
|
|
297
|
+
// private createMiddlewareChain(options: SecureOptions): any[] {
|
|
298
|
+
// const chain: any[] = [];
|
|
299
|
+
|
|
300
|
+
// chain.push(this.jsonManager.middleware(this.config.json));
|
|
301
|
+
// chain.push(this.jsonManager.urlencoded(this.config.urlencoded));
|
|
302
|
+
|
|
303
|
+
// if (this.config.enableHelmet) chain.push(helmet());
|
|
304
|
+
// if (this.config.enableHPP) chain.push(hpp());
|
|
305
|
+
|
|
306
|
+
// if (this.config.enableCompression)
|
|
307
|
+
// chain.push(compression(this.config.compression));
|
|
308
|
+
|
|
309
|
+
// if (options.cors) chain.push(this.corsManager.middleware(this.config.cors));
|
|
310
|
+
// if (options.sanitize)
|
|
311
|
+
// chain.push(this.sanitizerManager.middleware());
|
|
312
|
+
|
|
313
|
+
// if (options.rateLimit)
|
|
314
|
+
// chain.push(this.rateLimitManager.middleware({}));
|
|
315
|
+
|
|
316
|
+
// if (options.auth && this.authManager)
|
|
317
|
+
// chain.push(this.authManager.protect());
|
|
318
|
+
|
|
319
|
+
// chain.push(errorHandler);
|
|
320
|
+
// return chain;
|
|
321
|
+
// }
|
|
322
|
+
// }
|
|
323
|
+
|
|
324
|
+
|
|
325
|
+
|
|
326
|
+
|
|
327
|
+
|
|
328
|
+
|
|
1
329
|
import { HiSecureConfig } from "./types/HiSecureConfig.js";
|
|
2
330
|
import { defaultConfig } from "./config.js";
|
|
3
331
|
import { LIB_NAME, LIB_VERSION } from "./constants.js";
|
|
@@ -33,290 +361,194 @@ import { errorHandler } from "../middlewares/errorHandler.js";
|
|
|
33
361
|
// Types
|
|
34
362
|
import { SecureOptions, ValidationSchema } from "./types/SecureOptions.js";
|
|
35
363
|
|
|
364
|
+
type MiddlewarePreset = "strict" | "api" | "public";
|
|
365
|
+
|
|
36
366
|
export class HiSecure {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
367
|
+
private static instance: HiSecure | null = null;
|
|
368
|
+
|
|
369
|
+
private readonly config: HiSecureConfig;
|
|
370
|
+
private initialized = false;
|
|
371
|
+
|
|
372
|
+
private hashManager!: HashManager;
|
|
373
|
+
private rateLimitManager!: RateLimitManager;
|
|
374
|
+
private validatorManager!: ValidatorManager;
|
|
375
|
+
private sanitizerManager!: SanitizerManager;
|
|
376
|
+
private jsonManager!: JsonManager;
|
|
377
|
+
private corsManager!: CorsManager;
|
|
378
|
+
private authManager?: AuthManager;
|
|
379
|
+
|
|
380
|
+
private constructor(config: HiSecureConfig) {
|
|
381
|
+
this.config = config;
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
// ===== INIT (ONLY ONCE) =====
|
|
385
|
+
static init(userConfig?: Partial<HiSecureConfig>): HiSecure {
|
|
386
|
+
if (HiSecure.instance) return HiSecure.instance;
|
|
387
|
+
|
|
388
|
+
const finalConfig = deepMerge(defaultConfig, userConfig ?? {});
|
|
389
|
+
const instance = new HiSecure(finalConfig);
|
|
390
|
+
HiSecure.instance = instance;
|
|
391
|
+
instance.bootstrap();
|
|
392
|
+
return instance;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
private static get(): HiSecure {
|
|
396
|
+
if (!HiSecure.instance) {
|
|
397
|
+
throw new Error("HiSecure not initialized. Call HiSecure.init() first.");
|
|
60
398
|
}
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
399
|
+
return HiSecure.instance;
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
private bootstrap(): void {
|
|
403
|
+
if (this.initialized) return;
|
|
404
|
+
|
|
405
|
+
logger.info("Framework initialization started", {
|
|
406
|
+
layer: "hisecure-core",
|
|
407
|
+
lib: LIB_NAME,
|
|
408
|
+
version: LIB_VERSION
|
|
409
|
+
});
|
|
410
|
+
|
|
411
|
+
// Core managers
|
|
412
|
+
this.hashManager = new HashManager(
|
|
413
|
+
this.config.hashing,
|
|
414
|
+
this.config.hashing.primary === "argon2"
|
|
415
|
+
? new ArgonAdapter()
|
|
416
|
+
: new BcryptAdapter(this.config.hashing.saltRounds),
|
|
417
|
+
this.config.hashing.fallback
|
|
418
|
+
? new BcryptAdapter(this.config.hashing.saltRounds)
|
|
419
|
+
: null
|
|
420
|
+
);
|
|
421
|
+
|
|
422
|
+
this.rateLimitManager = new RateLimitManager(
|
|
423
|
+
this.config.rateLimiter,
|
|
424
|
+
this.config.rateLimiter.useAdaptiveMode
|
|
425
|
+
? new RLFlexibleAdapter()
|
|
426
|
+
: new ExpressRLAdapter(),
|
|
427
|
+
new ExpressRLAdapter()
|
|
428
|
+
);
|
|
429
|
+
|
|
430
|
+
this.validatorManager = new ValidatorManager(
|
|
431
|
+
new ZodAdapter(),
|
|
432
|
+
new ExpressValidatorAdapter()
|
|
433
|
+
);
|
|
434
|
+
|
|
435
|
+
this.sanitizerManager = new SanitizerManager(
|
|
436
|
+
new SanitizeHtmlAdapter(this.config.sanitizer),
|
|
437
|
+
new XSSAdapter(this.config.sanitizer)
|
|
438
|
+
);
|
|
439
|
+
|
|
440
|
+
this.jsonManager = new JsonManager();
|
|
441
|
+
this.corsManager = new CorsManager();
|
|
442
|
+
|
|
443
|
+
// Auth (optional)
|
|
444
|
+
if (this.config.auth?.enabled) {
|
|
445
|
+
this.authManager = new AuthManager({
|
|
446
|
+
jwtSecret: process.env.JWT_SECRET || this.config.auth.jwtSecret!,
|
|
447
|
+
jwtExpiresIn: this.config.auth.jwtExpiresIn,
|
|
448
|
+
googleClientId:
|
|
449
|
+
process.env.GOOGLE_CLIENT_ID || this.config.auth.googleClientId
|
|
450
|
+
});
|
|
451
|
+
|
|
452
|
+
logger.info("Authentication enabled", { layer: "hisecure-core" });
|
|
453
|
+
} else {
|
|
454
|
+
logger.info("Authentication disabled", { layer: "hisecure-core" });
|
|
73
455
|
}
|
|
74
456
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
}
|
|
457
|
+
deepFreeze(this.config);
|
|
458
|
+
this.initialized = true;
|
|
78
459
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
});
|
|
84
|
-
return;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
logger.info("Framework initialization started", {
|
|
88
|
-
layer: "hisecure-core",
|
|
89
|
-
lib: LIB_NAME,
|
|
90
|
-
version: LIB_VERSION
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
this.setupAdapters();
|
|
94
|
-
this.setupManagers();
|
|
95
|
-
this.setupDynamicManagers();
|
|
96
|
-
|
|
97
|
-
deepFreeze(this.config);
|
|
98
|
-
this.initialized = true;
|
|
99
|
-
|
|
100
|
-
logger.info("Framework initialized successfully", {
|
|
101
|
-
layer: "hisecure-core"
|
|
102
|
-
});
|
|
103
|
-
}
|
|
460
|
+
logger.info("Framework initialized successfully", {
|
|
461
|
+
layer: "hisecure-core"
|
|
462
|
+
});
|
|
463
|
+
}
|
|
104
464
|
|
|
105
|
-
|
|
106
|
-
static auth(options?: { required?: boolean; roles?: string[] }) {
|
|
107
|
-
const instance = this.getInstance();
|
|
108
|
-
if (!instance.authManager) {
|
|
109
|
-
throw new Error("Auth not enabled. Set auth.enabled=true in config.");
|
|
110
|
-
}
|
|
111
|
-
return instance.authManager.protect(options);
|
|
112
|
-
}
|
|
465
|
+
// ===== PUBLIC STATIC API =====
|
|
113
466
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
467
|
+
static auth(options?: { required?: boolean; roles?: string[] }) {
|
|
468
|
+
const i = HiSecure.get();
|
|
469
|
+
if (!i.authManager) throw new Error("Auth not enabled");
|
|
470
|
+
return i.authManager.protect(options);
|
|
471
|
+
}
|
|
117
472
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
473
|
+
static validate(schema: ValidationSchema) {
|
|
474
|
+
return HiSecure.get().validatorManager.validate(schema);
|
|
475
|
+
}
|
|
121
476
|
|
|
122
|
-
|
|
123
|
-
|
|
477
|
+
static sanitize(options?: any) {
|
|
478
|
+
return HiSecure.get().sanitizerManager.middleware(options);
|
|
479
|
+
}
|
|
124
480
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
layer: "hisecure-core",
|
|
128
|
-
preset
|
|
129
|
-
});
|
|
481
|
+
static rateLimit(preset: "strict" | "relaxed" | "api" | object) {
|
|
482
|
+
const i = HiSecure.get();
|
|
130
483
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
}
|
|
484
|
+
if (typeof preset === "string") {
|
|
485
|
+
const presets = {
|
|
486
|
+
strict: { mode: "strict" },
|
|
487
|
+
relaxed: { mode: "relaxed" },
|
|
488
|
+
api: { mode: "api" }
|
|
489
|
+
} as const;
|
|
138
490
|
|
|
139
|
-
|
|
140
|
-
|
|
491
|
+
return i.rateLimitManager.middleware(presets[preset]);
|
|
492
|
+
}
|
|
141
493
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
}
|
|
494
|
+
return i.rateLimitManager.middleware({ options: preset });
|
|
495
|
+
}
|
|
145
496
|
|
|
146
|
-
static json(options?: any) {
|
|
147
|
-
const instance = this.getInstance();
|
|
148
|
-
return [
|
|
149
|
-
instance.jsonManager.middleware(options),
|
|
150
|
-
instance.jsonManager.urlencoded()
|
|
151
|
-
];
|
|
152
|
-
}
|
|
153
497
|
|
|
154
|
-
|
|
498
|
+
static cors(options?: any) {
|
|
499
|
+
return HiSecure.get().corsManager.middleware(options);
|
|
500
|
+
}
|
|
155
501
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
}
|
|
502
|
+
static json(options?: any) {
|
|
503
|
+
const i = HiSecure.get();
|
|
504
|
+
return [i.jsonManager.middleware(options), i.jsonManager.urlencoded()];
|
|
505
|
+
}
|
|
161
506
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
507
|
+
static async hash(value: string): Promise<string> {
|
|
508
|
+
const { hash } = await HiSecure.get().hashManager.hash(value, {
|
|
509
|
+
allowFallback: true
|
|
510
|
+
});
|
|
511
|
+
return hash;
|
|
512
|
+
}
|
|
165
513
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
514
|
+
static verify(value: string, hash: string): Promise<boolean> {
|
|
515
|
+
return HiSecure.get().hashManager.verify(value, hash);
|
|
516
|
+
}
|
|
169
517
|
|
|
170
|
-
|
|
171
|
-
|
|
518
|
+
static middleware(options?: SecureOptions | MiddlewarePreset) {
|
|
519
|
+
const i = HiSecure.get();
|
|
172
520
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
521
|
+
const presets: Record<MiddlewarePreset, SecureOptions> = {
|
|
522
|
+
strict: { cors: true, rateLimit: "strict", sanitize: true, auth: true },
|
|
523
|
+
api: { cors: true, rateLimit: "relaxed", sanitize: true },
|
|
524
|
+
public: { cors: true, rateLimit: true }
|
|
177
525
|
};
|
|
178
526
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
const instance = this.getInstance();
|
|
182
|
-
|
|
183
|
-
if (typeof options === "string") {
|
|
184
|
-
logger.info("Global middleware preset applied", {
|
|
185
|
-
layer: "hisecure-core",
|
|
186
|
-
preset: options
|
|
187
|
-
});
|
|
188
|
-
|
|
189
|
-
const presets: any = {
|
|
190
|
-
api: { cors: true, rateLimit: "relaxed", sanitize: true },
|
|
191
|
-
strict: { cors: true, rateLimit: "strict", sanitize: true, auth: true },
|
|
192
|
-
public: { cors: true, rateLimit: true, sanitize: false }
|
|
193
|
-
};
|
|
194
|
-
|
|
195
|
-
return instance.createMiddlewareChain(presets[options] || {});
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
return instance.createMiddlewareChain(options || {});
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
// Internal Setup
|
|
202
|
-
|
|
203
|
-
private setupAdapters() {
|
|
204
|
-
logger.info("Adapters setup started", {
|
|
205
|
-
layer: "hisecure-core"
|
|
206
|
-
});
|
|
207
|
-
|
|
208
|
-
this.hashingPrimary =
|
|
209
|
-
this.config.hashing.primary === "argon2"
|
|
210
|
-
? new ArgonAdapter()
|
|
211
|
-
: new BcryptAdapter(this.config.hashing.saltRounds);
|
|
212
|
-
|
|
213
|
-
this.hashingFallback =
|
|
214
|
-
this.config.hashing.fallback === "bcrypt"
|
|
215
|
-
? new BcryptAdapter(this.config.hashing.saltRounds)
|
|
216
|
-
: null;
|
|
217
|
-
|
|
218
|
-
logger.info("Hashing adapters configured", {
|
|
219
|
-
layer: "hisecure-core",
|
|
220
|
-
primary: this.config.hashing.primary,
|
|
221
|
-
fallback: this.config.hashing.fallback ?? null
|
|
222
|
-
});
|
|
223
|
-
|
|
224
|
-
this.rateLimiterPrimary = this.config.rateLimiter.useAdaptiveMode
|
|
225
|
-
? new RLFlexibleAdapter()
|
|
226
|
-
: new ExpressRLAdapter();
|
|
527
|
+
const finalOptions =
|
|
528
|
+
typeof options === "string" ? presets[options] : options ?? {};
|
|
227
529
|
|
|
228
|
-
|
|
530
|
+
return i.createChain(finalOptions);
|
|
531
|
+
}
|
|
229
532
|
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
adaptive: this.config.rateLimiter.useAdaptiveMode
|
|
233
|
-
});
|
|
533
|
+
private createChain(options: SecureOptions): any[] {
|
|
534
|
+
const chain: any[] = [];
|
|
234
535
|
|
|
235
|
-
|
|
236
|
-
|
|
536
|
+
chain.push(this.jsonManager.middleware(this.config.json));
|
|
537
|
+
chain.push(this.jsonManager.urlencoded(this.config.urlencoded));
|
|
237
538
|
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
});
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
private setupManagers() {
|
|
246
|
-
this.hashManager = new HashManager(
|
|
247
|
-
this.config.hashing,
|
|
248
|
-
this.hashingPrimary,
|
|
249
|
-
this.hashingFallback
|
|
250
|
-
);
|
|
251
|
-
|
|
252
|
-
this.rateLimitManager = new RateLimitManager(
|
|
253
|
-
this.config.rateLimiter,
|
|
254
|
-
this.rateLimiterPrimary,
|
|
255
|
-
this.rateLimiterFallback
|
|
256
|
-
);
|
|
257
|
-
|
|
258
|
-
this.validatorManager = new ValidatorManager(
|
|
259
|
-
new ZodAdapter(),
|
|
260
|
-
new ExpressValidatorAdapter()
|
|
261
|
-
);
|
|
262
|
-
|
|
263
|
-
this.sanitizerManager = new SanitizerManager(
|
|
264
|
-
this.sanitizerPrimary,
|
|
265
|
-
this.sanitizerFallback
|
|
266
|
-
);
|
|
267
|
-
|
|
268
|
-
logger.info("Core managers initialized", {
|
|
269
|
-
layer: "hisecure-core",
|
|
270
|
-
managers: ["hash", "rate-limit", "validator", "sanitizer"]
|
|
271
|
-
});
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
private setupDynamicManagers() {
|
|
275
|
-
this.jsonManager = new JsonManager();
|
|
276
|
-
this.corsManager = new CorsManager();
|
|
277
|
-
|
|
278
|
-
if (this.config.auth.enabled) {
|
|
279
|
-
this.authManager = new AuthManager({
|
|
280
|
-
jwtSecret: process.env.JWT_SECRET || this.config.auth.jwtSecret!,
|
|
281
|
-
jwtExpiresIn: this.config.auth.jwtExpiresIn,
|
|
282
|
-
googleClientId:
|
|
283
|
-
process.env.GOOGLE_CLIENT_ID || this.config.auth.googleClientId
|
|
284
|
-
});
|
|
285
|
-
|
|
286
|
-
logger.info("Authentication enabled", {
|
|
287
|
-
layer: "hisecure-core",
|
|
288
|
-
google: !!this.config.auth.googleClientId
|
|
289
|
-
});
|
|
290
|
-
} else {
|
|
291
|
-
logger.info("Authentication disabled", {
|
|
292
|
-
layer: "hisecure-core"
|
|
293
|
-
});
|
|
294
|
-
}
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
private createMiddlewareChain(options: SecureOptions): any[] {
|
|
298
|
-
const chain: any[] = [];
|
|
539
|
+
if (this.config.enableHelmet) chain.push(helmet());
|
|
540
|
+
if (this.config.enableHPP) chain.push(hpp());
|
|
541
|
+
if (this.config.enableCompression)
|
|
542
|
+
chain.push(compression(this.config.compression));
|
|
299
543
|
|
|
300
|
-
|
|
301
|
-
|
|
544
|
+
if (options.cors) chain.push(this.corsManager.middleware());
|
|
545
|
+
if (options.sanitize) chain.push(this.sanitizerManager.middleware());
|
|
546
|
+
if (options.rateLimit)
|
|
547
|
+
chain.push(this.rateLimitManager.middleware({}));
|
|
548
|
+
if (options.auth && this.authManager)
|
|
549
|
+
chain.push(this.authManager.protect());
|
|
302
550
|
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
if (this.config.enableCompression)
|
|
307
|
-
chain.push(compression(this.config.compression));
|
|
308
|
-
|
|
309
|
-
if (options.cors) chain.push(this.corsManager.middleware(this.config.cors));
|
|
310
|
-
if (options.sanitize)
|
|
311
|
-
chain.push(this.sanitizerManager.middleware());
|
|
312
|
-
|
|
313
|
-
if (options.rateLimit)
|
|
314
|
-
chain.push(this.rateLimitManager.middleware({}));
|
|
315
|
-
|
|
316
|
-
if (options.auth && this.authManager)
|
|
317
|
-
chain.push(this.authManager.protect());
|
|
318
|
-
|
|
319
|
-
chain.push(errorHandler);
|
|
320
|
-
return chain;
|
|
321
|
-
}
|
|
551
|
+
chain.push(errorHandler);
|
|
552
|
+
return chain;
|
|
553
|
+
}
|
|
322
554
|
}
|