hi-secure 1.0.26 → 1.0.29
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 +79 -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 +488 -257
- package/src/core/useSecure.ts +94 -37
- package/src/index.ts +25 -11
package/src/core/HiSecure.ts
CHANGED
|
@@ -1,3 +1,329 @@
|
|
|
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
|
+
|
|
1
327
|
import { HiSecureConfig } from "./types/HiSecureConfig.js";
|
|
2
328
|
import { defaultConfig } from "./config.js";
|
|
3
329
|
import { LIB_NAME, LIB_VERSION } from "./constants.js";
|
|
@@ -33,290 +359,195 @@ import { errorHandler } from "../middlewares/errorHandler.js";
|
|
|
33
359
|
// Types
|
|
34
360
|
import { SecureOptions, ValidationSchema } from "./types/SecureOptions.js";
|
|
35
361
|
|
|
362
|
+
type MiddlewarePreset = "strict" | "api" | "public";
|
|
363
|
+
|
|
36
364
|
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
|
-
|
|
365
|
+
private static instance: HiSecure | null = null;
|
|
366
|
+
|
|
367
|
+
private readonly config: HiSecureConfig;
|
|
368
|
+
private initialized = false;
|
|
369
|
+
|
|
370
|
+
private hashManager!: HashManager;
|
|
371
|
+
private rateLimitManager!: RateLimitManager;
|
|
372
|
+
private validatorManager!: ValidatorManager;
|
|
373
|
+
private sanitizerManager!: SanitizerManager;
|
|
374
|
+
private jsonManager!: JsonManager;
|
|
375
|
+
private corsManager!: CorsManager;
|
|
376
|
+
private authManager?: AuthManager;
|
|
377
|
+
|
|
378
|
+
private constructor(config: HiSecureConfig) {
|
|
379
|
+
this.config = config;
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
// ================= INIT (ONLY ONCE) =================
|
|
383
|
+
static init(userConfig?: Partial<HiSecureConfig>): HiSecure {
|
|
384
|
+
if (HiSecure.instance) return HiSecure.instance;
|
|
385
|
+
|
|
386
|
+
const finalConfig = deepMerge(defaultConfig, userConfig ?? {});
|
|
387
|
+
const instance = new HiSecure(finalConfig);
|
|
388
|
+
HiSecure.instance = instance;
|
|
389
|
+
instance.bootstrap();
|
|
390
|
+
return instance;
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
private static get(): HiSecure {
|
|
394
|
+
if (!HiSecure.instance) {
|
|
395
|
+
throw new Error("HiSecure not initialized. Call HiSecure.init() first.");
|
|
60
396
|
}
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
397
|
+
return HiSecure.instance;
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
private bootstrap(): void {
|
|
401
|
+
if (this.initialized) return;
|
|
402
|
+
|
|
403
|
+
logger.info("Framework initialization started", {
|
|
404
|
+
layer: "hisecure-core",
|
|
405
|
+
lib: LIB_NAME,
|
|
406
|
+
version: LIB_VERSION
|
|
407
|
+
});
|
|
408
|
+
|
|
409
|
+
// ===== Core Managers =====
|
|
410
|
+
this.hashManager = new HashManager(
|
|
411
|
+
this.config.hashing,
|
|
412
|
+
this.config.hashing.primary === "argon2"
|
|
413
|
+
? new ArgonAdapter()
|
|
414
|
+
: new BcryptAdapter(this.config.hashing.saltRounds),
|
|
415
|
+
this.config.hashing.fallback
|
|
416
|
+
? new BcryptAdapter(this.config.hashing.saltRounds)
|
|
417
|
+
: null
|
|
418
|
+
);
|
|
419
|
+
|
|
420
|
+
this.rateLimitManager = new RateLimitManager(
|
|
421
|
+
this.config.rateLimiter,
|
|
422
|
+
this.config.rateLimiter.useAdaptiveMode
|
|
423
|
+
? new RLFlexibleAdapter()
|
|
424
|
+
: new ExpressRLAdapter(),
|
|
425
|
+
new ExpressRLAdapter()
|
|
426
|
+
);
|
|
427
|
+
|
|
428
|
+
this.validatorManager = new ValidatorManager(
|
|
429
|
+
new ZodAdapter(),
|
|
430
|
+
new ExpressValidatorAdapter()
|
|
431
|
+
);
|
|
432
|
+
|
|
433
|
+
this.sanitizerManager = new SanitizerManager(
|
|
434
|
+
new SanitizeHtmlAdapter(this.config.sanitizer),
|
|
435
|
+
new XSSAdapter(this.config.sanitizer)
|
|
436
|
+
);
|
|
437
|
+
|
|
438
|
+
this.jsonManager = new JsonManager();
|
|
439
|
+
this.corsManager = new CorsManager();
|
|
440
|
+
|
|
441
|
+
// ===== Auth (OPTIONAL) =====
|
|
442
|
+
if (this.config.auth?.enabled) {
|
|
443
|
+
this.authManager = new AuthManager({
|
|
444
|
+
jwtSecret: process.env.JWT_SECRET || this.config.auth.jwtSecret!,
|
|
445
|
+
jwtExpiresIn: this.config.auth.jwtExpiresIn,
|
|
446
|
+
googleClientId:
|
|
447
|
+
process.env.GOOGLE_CLIENT_ID || this.config.auth.googleClientId
|
|
448
|
+
});
|
|
449
|
+
|
|
450
|
+
logger.info("Authentication enabled", { layer: "hisecure-core" });
|
|
451
|
+
} else {
|
|
452
|
+
logger.info("Authentication disabled", { layer: "hisecure-core" });
|
|
73
453
|
}
|
|
74
454
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
}
|
|
455
|
+
deepFreeze(this.config);
|
|
456
|
+
this.initialized = true;
|
|
78
457
|
|
|
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
|
-
}
|
|
458
|
+
logger.info("Framework initialized successfully", {
|
|
459
|
+
layer: "hisecure-core"
|
|
460
|
+
});
|
|
461
|
+
}
|
|
104
462
|
|
|
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
|
-
}
|
|
463
|
+
// ================= PUBLIC STATIC API =================
|
|
113
464
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
465
|
+
static auth(options?: { required?: boolean; roles?: string[] }) {
|
|
466
|
+
const i = HiSecure.get();
|
|
467
|
+
if (!i.authManager) throw new Error("Auth not enabled");
|
|
468
|
+
return i.authManager.protect(options);
|
|
469
|
+
}
|
|
117
470
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
471
|
+
static validate(schema: ValidationSchema) {
|
|
472
|
+
return HiSecure.get().validatorManager.validate(schema);
|
|
473
|
+
}
|
|
121
474
|
|
|
122
|
-
|
|
123
|
-
|
|
475
|
+
static sanitize(options?: any) {
|
|
476
|
+
return HiSecure.get().sanitizerManager.middleware(options);
|
|
477
|
+
}
|
|
124
478
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
layer: "hisecure-core",
|
|
128
|
-
preset
|
|
129
|
-
});
|
|
479
|
+
static rateLimit(preset: "strict" | "relaxed" | "api" | object) {
|
|
480
|
+
const i = HiSecure.get();
|
|
130
481
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
}
|
|
482
|
+
if (typeof preset === "string") {
|
|
483
|
+
const presets = {
|
|
484
|
+
strict: { mode: "strict" },
|
|
485
|
+
relaxed: { mode: "relaxed" },
|
|
486
|
+
api: { mode: "api" }
|
|
487
|
+
} as const;
|
|
138
488
|
|
|
139
|
-
|
|
489
|
+
return i.rateLimitManager.middleware(presets[preset]);
|
|
140
490
|
}
|
|
141
491
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
}
|
|
492
|
+
return i.rateLimitManager.middleware({ options: preset });
|
|
493
|
+
}
|
|
145
494
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
instance.jsonManager.middleware(options),
|
|
150
|
-
instance.jsonManager.urlencoded()
|
|
151
|
-
];
|
|
152
|
-
}
|
|
495
|
+
static cors(options?: any) {
|
|
496
|
+
return HiSecure.get().corsManager.middleware(options);
|
|
497
|
+
}
|
|
153
498
|
|
|
154
|
-
|
|
499
|
+
static json(options?: any) {
|
|
500
|
+
const i = HiSecure.get();
|
|
501
|
+
return [i.jsonManager.middleware(options), i.jsonManager.urlencoded()];
|
|
502
|
+
}
|
|
155
503
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
504
|
+
static async hash(value: string): Promise<string> {
|
|
505
|
+
const { hash } = await HiSecure.get().hashManager.hash(value, {
|
|
506
|
+
allowFallback: true
|
|
507
|
+
});
|
|
508
|
+
return hash;
|
|
509
|
+
}
|
|
161
510
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
511
|
+
static verify(value: string, hash: string): Promise<boolean> {
|
|
512
|
+
return HiSecure.get().hashManager.verify(value, hash);
|
|
513
|
+
}
|
|
165
514
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
HiSecure.getInstance().authManager!.sign(payload, options),
|
|
515
|
+
static middleware(options?: SecureOptions | MiddlewarePreset) {
|
|
516
|
+
const i = HiSecure.get();
|
|
169
517
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
verifyIdToken: (idToken: string) =>
|
|
175
|
-
HiSecure.getInstance().authManager!.verifyGoogleIdToken(idToken)
|
|
176
|
-
}
|
|
518
|
+
const presets: Record<MiddlewarePreset, SecureOptions> = {
|
|
519
|
+
strict: { cors: true, rateLimit: "strict", sanitize: true, auth: true },
|
|
520
|
+
api: { cors: true, rateLimit: "relaxed", sanitize: true },
|
|
521
|
+
public: { cors: true, rateLimit: true }
|
|
177
522
|
};
|
|
178
523
|
|
|
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
|
-
}
|
|
524
|
+
const finalOptions =
|
|
525
|
+
typeof options === "string" ? presets[options] : options ?? {};
|
|
197
526
|
|
|
198
|
-
|
|
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;
|
|
527
|
+
return i.createChain(finalOptions);
|
|
528
|
+
}
|
|
217
529
|
|
|
218
|
-
|
|
219
|
-
layer: "hisecure-core",
|
|
220
|
-
primary: this.config.hashing.primary,
|
|
221
|
-
fallback: this.config.hashing.fallback ?? null
|
|
222
|
-
});
|
|
530
|
+
// ================= INTERNAL =================
|
|
223
531
|
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
: new ExpressRLAdapter();
|
|
532
|
+
private createChain(options: SecureOptions): any[] {
|
|
533
|
+
const chain: any[] = [];
|
|
227
534
|
|
|
228
|
-
|
|
535
|
+
chain.push(this.jsonManager.middleware(this.config.json));
|
|
536
|
+
chain.push(this.jsonManager.urlencoded(this.config.urlencoded));
|
|
229
537
|
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
538
|
+
if (this.config.enableHelmet) chain.push(helmet());
|
|
539
|
+
if (this.config.enableHPP) chain.push(hpp());
|
|
540
|
+
if (this.config.enableCompression)
|
|
541
|
+
chain.push(compression(this.config.compression));
|
|
234
542
|
|
|
235
|
-
|
|
236
|
-
|
|
543
|
+
if (options.cors) chain.push(this.corsManager.middleware());
|
|
544
|
+
if (options.sanitize) chain.push(this.sanitizerManager.middleware());
|
|
545
|
+
if (options.rateLimit)
|
|
546
|
+
chain.push(this.rateLimitManager.middleware({}));
|
|
547
|
+
if (options.auth && this.authManager)
|
|
548
|
+
chain.push(this.authManager.protect());
|
|
237
549
|
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
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
|
-
}
|
|
550
|
+
chain.push(errorHandler);
|
|
551
|
+
return chain;
|
|
552
|
+
}
|
|
322
553
|
}
|