hi-secure 1.0.25 → 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/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/package.json +1 -1
- package/readme.md +155 -93
- package/src/core/HiSecure.ts +490 -261
- 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,293 +361,194 @@ import { errorHandler } from "../middlewares/errorHandler.js";
|
|
|
33
361
|
// Types
|
|
34
362
|
import { SecureOptions, ValidationSchema } from "./types/SecureOptions.js";
|
|
35
363
|
|
|
36
|
-
|
|
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
|
-
}
|
|
364
|
+
type MiddlewarePreset = "strict" | "api" | "public";
|
|
61
365
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
366
|
+
export class HiSecure {
|
|
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.");
|
|
73
398
|
}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
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" });
|
|
77
455
|
}
|
|
78
456
|
|
|
79
|
-
|
|
80
|
-
|
|
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
|
-
}
|
|
457
|
+
deepFreeze(this.config);
|
|
458
|
+
this.initialized = true;
|
|
104
459
|
|
|
105
|
-
|
|
106
|
-
|
|
460
|
+
logger.info("Framework initialized successfully", {
|
|
461
|
+
layer: "hisecure-core"
|
|
462
|
+
});
|
|
463
|
+
}
|
|
107
464
|
|
|
108
|
-
|
|
109
|
-
const instance = this.getInstance();
|
|
110
|
-
if (!instance.authManager) {
|
|
111
|
-
throw new Error("Auth not enabled. Set auth.enabled=true in config.");
|
|
112
|
-
}
|
|
113
|
-
return instance.authManager.protect(options);
|
|
114
|
-
}
|
|
465
|
+
// ===== PUBLIC STATIC API =====
|
|
115
466
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
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
|
+
}
|
|
119
472
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
473
|
+
static validate(schema: ValidationSchema) {
|
|
474
|
+
return HiSecure.get().validatorManager.validate(schema);
|
|
475
|
+
}
|
|
123
476
|
|
|
124
|
-
|
|
125
|
-
|
|
477
|
+
static sanitize(options?: any) {
|
|
478
|
+
return HiSecure.get().sanitizerManager.middleware(options);
|
|
479
|
+
}
|
|
126
480
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
layer: "hisecure-core",
|
|
130
|
-
preset
|
|
131
|
-
});
|
|
481
|
+
static rateLimit(preset: "strict" | "relaxed" | "api" | object) {
|
|
482
|
+
const i = HiSecure.get();
|
|
132
483
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
}
|
|
484
|
+
if (typeof preset === "string") {
|
|
485
|
+
const presets = {
|
|
486
|
+
strict: { mode: "strict" },
|
|
487
|
+
relaxed: { mode: "relaxed" },
|
|
488
|
+
api: { mode: "api" }
|
|
489
|
+
} as const;
|
|
140
490
|
|
|
141
|
-
|
|
142
|
-
|
|
491
|
+
return i.rateLimitManager.middleware(presets[preset]);
|
|
492
|
+
}
|
|
143
493
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
}
|
|
494
|
+
return i.rateLimitManager.middleware({ options: preset });
|
|
495
|
+
}
|
|
147
496
|
|
|
148
|
-
static json(options?: any) {
|
|
149
|
-
const instance = this.getInstance();
|
|
150
|
-
return [
|
|
151
|
-
instance.jsonManager.middleware(options),
|
|
152
|
-
instance.jsonManager.urlencoded()
|
|
153
|
-
];
|
|
154
|
-
}
|
|
155
497
|
|
|
156
|
-
|
|
498
|
+
static cors(options?: any) {
|
|
499
|
+
return HiSecure.get().corsManager.middleware(options);
|
|
500
|
+
}
|
|
157
501
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
}
|
|
502
|
+
static json(options?: any) {
|
|
503
|
+
const i = HiSecure.get();
|
|
504
|
+
return [i.jsonManager.middleware(options), i.jsonManager.urlencoded()];
|
|
505
|
+
}
|
|
163
506
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
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
|
+
}
|
|
167
513
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
514
|
+
static verify(value: string, hash: string): Promise<boolean> {
|
|
515
|
+
return HiSecure.get().hashManager.verify(value, hash);
|
|
516
|
+
}
|
|
171
517
|
|
|
172
|
-
|
|
173
|
-
|
|
518
|
+
static middleware(options?: SecureOptions | MiddlewarePreset) {
|
|
519
|
+
const i = HiSecure.get();
|
|
174
520
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
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 }
|
|
179
525
|
};
|
|
180
526
|
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
static middleware(options?: SecureOptions | "api" | "strict" | "public") {
|
|
184
|
-
const instance = this.getInstance();
|
|
185
|
-
|
|
186
|
-
if (typeof options === "string") {
|
|
187
|
-
logger.info("Global middleware preset applied", {
|
|
188
|
-
layer: "hisecure-core",
|
|
189
|
-
preset: options
|
|
190
|
-
});
|
|
191
|
-
|
|
192
|
-
const presets: any = {
|
|
193
|
-
api: { cors: true, rateLimit: "relaxed", sanitize: true },
|
|
194
|
-
strict: { cors: true, rateLimit: "strict", sanitize: true, auth: true },
|
|
195
|
-
public: { cors: true, rateLimit: true, sanitize: false }
|
|
196
|
-
};
|
|
197
|
-
|
|
198
|
-
return instance.createMiddlewareChain(presets[options] || {});
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
return instance.createMiddlewareChain(options || {});
|
|
202
|
-
}
|
|
527
|
+
const finalOptions =
|
|
528
|
+
typeof options === "string" ? presets[options] : options ?? {};
|
|
203
529
|
|
|
204
|
-
|
|
530
|
+
return i.createChain(finalOptions);
|
|
531
|
+
}
|
|
205
532
|
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
layer: "hisecure-core"
|
|
209
|
-
});
|
|
533
|
+
private createChain(options: SecureOptions): any[] {
|
|
534
|
+
const chain: any[] = [];
|
|
210
535
|
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
? new ArgonAdapter()
|
|
214
|
-
: new BcryptAdapter(this.config.hashing.saltRounds);
|
|
536
|
+
chain.push(this.jsonManager.middleware(this.config.json));
|
|
537
|
+
chain.push(this.jsonManager.urlencoded(this.config.urlencoded));
|
|
215
538
|
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
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));
|
|
220
543
|
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
this.rateLimiterPrimary = this.config.rateLimiter.useAdaptiveMode
|
|
228
|
-
? new RLFlexibleAdapter()
|
|
229
|
-
: new ExpressRLAdapter();
|
|
230
|
-
|
|
231
|
-
this.rateLimiterFallback = new ExpressRLAdapter();
|
|
232
|
-
|
|
233
|
-
logger.info("Rate limiter adapters configured", {
|
|
234
|
-
layer: "hisecure-core",
|
|
235
|
-
adaptive: this.config.rateLimiter.useAdaptiveMode
|
|
236
|
-
});
|
|
237
|
-
|
|
238
|
-
this.sanitizerPrimary = new SanitizeHtmlAdapter(this.config.sanitizer);
|
|
239
|
-
this.sanitizerFallback = new XSSAdapter(this.config.sanitizer);
|
|
240
|
-
|
|
241
|
-
logger.info("Sanitizer adapters configured", {
|
|
242
|
-
layer: "hisecure-core",
|
|
243
|
-
primary: "sanitize-html",
|
|
244
|
-
fallback: "xss"
|
|
245
|
-
});
|
|
246
|
-
}
|
|
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());
|
|
247
550
|
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
this.hashingPrimary,
|
|
252
|
-
this.hashingFallback
|
|
253
|
-
);
|
|
254
|
-
|
|
255
|
-
this.rateLimitManager = new RateLimitManager(
|
|
256
|
-
this.config.rateLimiter,
|
|
257
|
-
this.rateLimiterPrimary,
|
|
258
|
-
this.rateLimiterFallback
|
|
259
|
-
);
|
|
260
|
-
|
|
261
|
-
this.validatorManager = new ValidatorManager(
|
|
262
|
-
new ZodAdapter(),
|
|
263
|
-
new ExpressValidatorAdapter()
|
|
264
|
-
);
|
|
265
|
-
|
|
266
|
-
this.sanitizerManager = new SanitizerManager(
|
|
267
|
-
this.sanitizerPrimary,
|
|
268
|
-
this.sanitizerFallback
|
|
269
|
-
);
|
|
270
|
-
|
|
271
|
-
logger.info("Core managers initialized", {
|
|
272
|
-
layer: "hisecure-core",
|
|
273
|
-
managers: ["hash", "rate-limit", "validator", "sanitizer"]
|
|
274
|
-
});
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
private setupDynamicManagers() {
|
|
278
|
-
this.jsonManager = new JsonManager();
|
|
279
|
-
this.corsManager = new CorsManager();
|
|
280
|
-
|
|
281
|
-
if (this.config.auth.enabled) {
|
|
282
|
-
this.authManager = new AuthManager({
|
|
283
|
-
jwtSecret: process.env.JWT_SECRET || this.config.auth.jwtSecret!,
|
|
284
|
-
jwtExpiresIn: this.config.auth.jwtExpiresIn,
|
|
285
|
-
googleClientId:
|
|
286
|
-
process.env.GOOGLE_CLIENT_ID || this.config.auth.googleClientId
|
|
287
|
-
});
|
|
288
|
-
|
|
289
|
-
logger.info("Authentication enabled", {
|
|
290
|
-
layer: "hisecure-core",
|
|
291
|
-
google: !!this.config.auth.googleClientId
|
|
292
|
-
});
|
|
293
|
-
} else {
|
|
294
|
-
logger.info("Authentication disabled", {
|
|
295
|
-
layer: "hisecure-core"
|
|
296
|
-
});
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
private createMiddlewareChain(options: SecureOptions): any[] {
|
|
301
|
-
const chain: any[] = [];
|
|
302
|
-
|
|
303
|
-
chain.push(this.jsonManager.middleware(this.config.json));
|
|
304
|
-
chain.push(this.jsonManager.urlencoded(this.config.urlencoded));
|
|
305
|
-
|
|
306
|
-
if (this.config.enableHelmet) chain.push(helmet());
|
|
307
|
-
if (this.config.enableHPP) chain.push(hpp());
|
|
308
|
-
|
|
309
|
-
if (this.config.enableCompression)
|
|
310
|
-
chain.push(compression(this.config.compression));
|
|
311
|
-
|
|
312
|
-
if (options.cors) chain.push(this.corsManager.middleware(this.config.cors));
|
|
313
|
-
if (options.sanitize)
|
|
314
|
-
chain.push(this.sanitizerManager.middleware());
|
|
315
|
-
|
|
316
|
-
if (options.rateLimit)
|
|
317
|
-
chain.push(this.rateLimitManager.middleware({}));
|
|
318
|
-
|
|
319
|
-
if (options.auth && this.authManager)
|
|
320
|
-
chain.push(this.authManager.protect());
|
|
321
|
-
|
|
322
|
-
chain.push(errorHandler);
|
|
323
|
-
return chain;
|
|
324
|
-
}
|
|
551
|
+
chain.push(errorHandler);
|
|
552
|
+
return chain;
|
|
553
|
+
}
|
|
325
554
|
}
|