hi-secure 1.0.5 → 1.0.7
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 +17 -2
- package/dist/core/HiSecure.d.ts.map +1 -1
- package/dist/core/HiSecure.js +135 -30
- package/dist/core/HiSecure.js.map +1 -1
- package/dist/core/useSecure.d.ts +7 -0
- package/dist/core/useSecure.d.ts.map +1 -1
- package/dist/core/useSecure.js +23 -114
- package/dist/core/useSecure.js.map +1 -1
- package/dist/index.d.ts +6 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -19
- package/dist/index.js.map +1 -1
- package/dist/utils/normalizeOptions.d.ts.map +1 -1
- package/dist/utils/normalizeOptions.js +8 -8
- package/dist/utils/normalizeOptions.js.map +1 -1
- package/package.json +1 -1
- package/src/core/HiSecure.ts +0 -837
- package/src/core/useSecure.ts +0 -112
- package/src/index.ts +0 -16
- package/src/utils/normalizeOptions.ts +13 -12
package/src/core/HiSecure.ts
CHANGED
|
@@ -1,606 +1,3 @@
|
|
|
1
|
-
/* The `HiSecure` class is a security library in TypeScript that provides various security features
|
|
2
|
-
such as hashing, rate limiting, validation, sanitization, and authentication through a fluent API
|
|
3
|
-
and global middleware setup. */
|
|
4
|
-
// // // src/core/HiSecure.ts
|
|
5
|
-
|
|
6
|
-
// // import { HiSecureConfig } from "./types/HiSecureConfig.js";
|
|
7
|
-
// // import { defaultConfig } from "./config.js";
|
|
8
|
-
// // import { LIB_NAME, LIB_VERSION } from "./constants.js";
|
|
9
|
-
// // import { deepMerge } from "../utils/deepMerge.js";
|
|
10
|
-
// // import { deepFreeze } from "../utils/deepFreeze.js";
|
|
11
|
-
|
|
12
|
-
// // import { logger } from "../logging";
|
|
13
|
-
|
|
14
|
-
// // // Adapters
|
|
15
|
-
// // import { ArgonAdapter } from "../adapters/ArgonAdapter.js";
|
|
16
|
-
// // import { BcryptAdapter } from "../adapters/BcryptAdapter.js";
|
|
17
|
-
// // import { RLFlexibleAdapter } from "../adapters/RLFlexibleAdapter.js";
|
|
18
|
-
// // import { ExpressRLAdapter } from "../adapters/ExpressRLAdapter.js";
|
|
19
|
-
// // import { ZodAdapter } from "../adapters/ZodAdapter.js";
|
|
20
|
-
// // import { ExpressValidatorAdapter } from "../adapters/ExpressValidatorAdapter.js";
|
|
21
|
-
// // import { SanitizeHtmlAdapter } from "../adapters/SanitizeHtmlAdapter.js";
|
|
22
|
-
// // import { DomPurifyAdapter } from "../adapters/DomPurifyAdapter.js";
|
|
23
|
-
|
|
24
|
-
// // // Managers
|
|
25
|
-
// // import { HashManager } from "../managers/HashManager.js";
|
|
26
|
-
// // import { RateLimitManager } from "../managers/RateLimitManager.js";
|
|
27
|
-
// // import { ValidatorManager } from "../managers/ValidatorManager.js";
|
|
28
|
-
// // import { SanitizerManager } from "../managers/SanitizerManager.js";
|
|
29
|
-
// // import { JsonManager } from "../managers/JsonManager.js";
|
|
30
|
-
// // import { CorsManager } from "../managers/CorsManager.js";
|
|
31
|
-
// // import { AuthManager } from "../managers/AuthManager.js";
|
|
32
|
-
|
|
33
|
-
// // // 3rd-party express middlewares
|
|
34
|
-
// // import helmet from "helmet";
|
|
35
|
-
// // import hpp from "hpp";
|
|
36
|
-
|
|
37
|
-
// // // Shared error handler
|
|
38
|
-
// // import { errorHandler } from "../middlewares/errorHandler.js";
|
|
39
|
-
|
|
40
|
-
// // export class HiSecure {
|
|
41
|
-
// // private config: HiSecureConfig;
|
|
42
|
-
// // private initialized = false;
|
|
43
|
-
|
|
44
|
-
// // // Managers exposed for user
|
|
45
|
-
// // public hashManager!: HashManager;
|
|
46
|
-
// // public rateLimitManager!: RateLimitManager;
|
|
47
|
-
// // public validatorManager!: ValidatorManager;
|
|
48
|
-
// // public sanitizerManager!: SanitizerManager;
|
|
49
|
-
// // public jsonManager!: JsonManager;
|
|
50
|
-
// // public corsManager!: CorsManager;
|
|
51
|
-
// // public authManager?: AuthManager;
|
|
52
|
-
|
|
53
|
-
// // // Internal adapters
|
|
54
|
-
// // private hashingPrimary: any;
|
|
55
|
-
// // private hashingFallback: any;
|
|
56
|
-
// // private rateLimiterPrimary: any;
|
|
57
|
-
// // private rateLimiterFallback: any;
|
|
58
|
-
// // private validatorPrimary: any;
|
|
59
|
-
// // private validatorFallback: any;
|
|
60
|
-
// // private sanitizerPrimary: any;
|
|
61
|
-
// // private sanitizerFallback: any;
|
|
62
|
-
|
|
63
|
-
// // constructor(userConfig: Partial<HiSecureConfig> = {}) {
|
|
64
|
-
// // this.config = deepMerge(defaultConfig, userConfig);
|
|
65
|
-
// // }
|
|
66
|
-
|
|
67
|
-
// // // ---------------------------------------------------------
|
|
68
|
-
// // // INIT
|
|
69
|
-
// // // ---------------------------------------------------------
|
|
70
|
-
// // init() {
|
|
71
|
-
// // if (this.initialized) {
|
|
72
|
-
// // logger.warn("⚠ HiSecure.init() called twice → ignored.");
|
|
73
|
-
// // return;
|
|
74
|
-
// // }
|
|
75
|
-
|
|
76
|
-
// // logger.info(`🔐 ${LIB_NAME} v${LIB_VERSION} initialized`);
|
|
77
|
-
// // logger.info("⚙ Loaded configuration:", this.config);
|
|
78
|
-
|
|
79
|
-
// // this.setupAdapters();
|
|
80
|
-
// // this.setupManagers();
|
|
81
|
-
// // this.setupDynamicManagers();
|
|
82
|
-
|
|
83
|
-
// // // IMMUTABLE — library cannot be modified at runtime
|
|
84
|
-
// // deepFreeze(this.config);
|
|
85
|
-
// // deepFreeze(this.hashManager);
|
|
86
|
-
// // deepFreeze(this.rateLimitManager);
|
|
87
|
-
// // deepFreeze(this.validatorManager);
|
|
88
|
-
// // deepFreeze(this.sanitizerManager);
|
|
89
|
-
// // deepFreeze(this.jsonManager);
|
|
90
|
-
// // deepFreeze(this.corsManager);
|
|
91
|
-
// // if (this.authManager) deepFreeze(this.authManager);
|
|
92
|
-
|
|
93
|
-
// // this.initialized = true;
|
|
94
|
-
|
|
95
|
-
// // logger.info("🔒 HiSecure locked — production-ready");
|
|
96
|
-
// // }
|
|
97
|
-
|
|
98
|
-
// // isInitialized() {
|
|
99
|
-
// // return this.initialized;
|
|
100
|
-
// // }
|
|
101
|
-
|
|
102
|
-
// // // ---------------------------------------------------------
|
|
103
|
-
// // // ADAPTER SETUP
|
|
104
|
-
// // // ---------------------------------------------------------
|
|
105
|
-
// // private setupAdapters() {
|
|
106
|
-
// // logger.info("🧩 Setting up adapters...");
|
|
107
|
-
|
|
108
|
-
// // // Hashing
|
|
109
|
-
// // this.hashingPrimary =
|
|
110
|
-
// // this.config.hashing.primary === "argon2"
|
|
111
|
-
// // ? new ArgonAdapter()
|
|
112
|
-
// // : new BcryptAdapter(this.config.hashing.saltRounds);
|
|
113
|
-
|
|
114
|
-
// // this.hashingFallback =
|
|
115
|
-
// // this.config.hashing.fallback === "bcrypt"
|
|
116
|
-
// // ? new BcryptAdapter(this.config.hashing.saltRounds)
|
|
117
|
-
// // : null;
|
|
118
|
-
|
|
119
|
-
// // // Rate limiter
|
|
120
|
-
// // this.rateLimiterPrimary =
|
|
121
|
-
// // this.config.rateLimiter.useAdaptiveMode
|
|
122
|
-
// // ? new RLFlexibleAdapter()
|
|
123
|
-
// // : new ExpressRLAdapter();
|
|
124
|
-
|
|
125
|
-
// // this.rateLimiterFallback = new ExpressRLAdapter();
|
|
126
|
-
|
|
127
|
-
// // // Validator
|
|
128
|
-
// // this.validatorPrimary =
|
|
129
|
-
// // this.config.validation.mode === "zod"
|
|
130
|
-
// // ? new ZodAdapter()
|
|
131
|
-
// // : new ExpressValidatorAdapter();
|
|
132
|
-
|
|
133
|
-
// // this.validatorFallback =
|
|
134
|
-
// // this.config.validation.fallback === "express-validator"
|
|
135
|
-
// // ? new ExpressValidatorAdapter()
|
|
136
|
-
// // : null;
|
|
137
|
-
|
|
138
|
-
// // // Sanitizer
|
|
139
|
-
// // this.sanitizerPrimary = new SanitizeHtmlAdapter(this.config.sanitizer);
|
|
140
|
-
// // this.sanitizerFallback = new DomPurifyAdapter();
|
|
141
|
-
|
|
142
|
-
// // logger.info("✔ Adapters ready");
|
|
143
|
-
// // }
|
|
144
|
-
|
|
145
|
-
// // // ---------------------------------------------------------
|
|
146
|
-
// // // MANAGER SETUP
|
|
147
|
-
// // // ---------------------------------------------------------
|
|
148
|
-
// // private setupManagers() {
|
|
149
|
-
// // this.hashManager = new HashManager(
|
|
150
|
-
// // this.config.hashing,
|
|
151
|
-
// // this.hashingPrimary,
|
|
152
|
-
// // this.hashingFallback
|
|
153
|
-
// // );
|
|
154
|
-
|
|
155
|
-
// // this.rateLimitManager = new RateLimitManager(
|
|
156
|
-
// // this.config.rateLimiter,
|
|
157
|
-
// // this.rateLimiterPrimary,
|
|
158
|
-
// // this.rateLimiterFallback
|
|
159
|
-
// // );
|
|
160
|
-
|
|
161
|
-
// // this.validatorManager = new ValidatorManager(
|
|
162
|
-
// // this.config.validation,
|
|
163
|
-
// // this.validatorPrimary,
|
|
164
|
-
// // this.validatorFallback
|
|
165
|
-
// // );
|
|
166
|
-
|
|
167
|
-
// // this.sanitizerManager = new SanitizerManager(
|
|
168
|
-
// // this.sanitizerPrimary,
|
|
169
|
-
// // this.sanitizerFallback
|
|
170
|
-
// // );
|
|
171
|
-
// // }
|
|
172
|
-
|
|
173
|
-
// // // ---------------------------------------------------------
|
|
174
|
-
// // // DYNAMIC MANAGERS (JSON, CORS, AUTH)
|
|
175
|
-
// // // ---------------------------------------------------------
|
|
176
|
-
// // private setupDynamicManagers() {
|
|
177
|
-
// // this.jsonManager = new JsonManager();
|
|
178
|
-
// // this.corsManager = new CorsManager();
|
|
179
|
-
|
|
180
|
-
// // // AUTH SUPPORT
|
|
181
|
-
// // if (this.config.auth?.enabled) {
|
|
182
|
-
// // this.authManager = new AuthManager({
|
|
183
|
-
// // jwtSecret: process.env.JWT_SECRET!,
|
|
184
|
-
// // jwtExpiresIn: this.config.auth.jwtExpiresIn,
|
|
185
|
-
// // googleClientId: process.env.GOOGLE_CLIENT_ID
|
|
186
|
-
// // });
|
|
187
|
-
// // }
|
|
188
|
-
// // }
|
|
189
|
-
|
|
190
|
-
// // // ---------------------------------------------------------
|
|
191
|
-
// // // PUBLIC API METHODS
|
|
192
|
-
// // // ---------------------------------------------------------
|
|
193
|
-
// // hash(value: string) {
|
|
194
|
-
// // return this.hashManager.hash(value);
|
|
195
|
-
// // }
|
|
196
|
-
|
|
197
|
-
// // verify(value: string, hashed: string) {
|
|
198
|
-
// // return this.hashManager.verify(value, hashed);
|
|
199
|
-
// // }
|
|
200
|
-
|
|
201
|
-
// // sanitize(value: string) {
|
|
202
|
-
// // return this.sanitizerManager.sanitize(value);
|
|
203
|
-
// // }
|
|
204
|
-
|
|
205
|
-
// // validate(schema: any) {
|
|
206
|
-
// // return this.validatorManager.validate(schema);
|
|
207
|
-
// // }
|
|
208
|
-
|
|
209
|
-
// // // ---------------------------------------------------------
|
|
210
|
-
// // // EXPRESS GLOBAL PIPELINE
|
|
211
|
-
// // // ---------------------------------------------------------
|
|
212
|
-
// // middleware() {
|
|
213
|
-
// // const chain: any[] = [];
|
|
214
|
-
|
|
215
|
-
// // // JSON + URL encoded
|
|
216
|
-
// // chain.push(this.jsonManager.middleware(this.config.json));
|
|
217
|
-
// // chain.push(this.jsonManager.urlencoded(this.config.urlencoded));
|
|
218
|
-
|
|
219
|
-
// // // add qs
|
|
220
|
-
// // chain.push(this.jsonManager.queryParser());
|
|
221
|
-
|
|
222
|
-
// // // Core security
|
|
223
|
-
// // if (this.config.enableHelmet) chain.push(helmet());
|
|
224
|
-
// // if (this.config.enableHPP) chain.push(hpp());
|
|
225
|
-
|
|
226
|
-
// // if (this.config.enableCORS)
|
|
227
|
-
// // chain.push(this.corsManager.middleware(this.config.cors));
|
|
228
|
-
|
|
229
|
-
// // if (this.config.enableSanitizer)
|
|
230
|
-
// // chain.push(this.sanitizerManager.middleware());
|
|
231
|
-
|
|
232
|
-
// // if (this.config.enableRateLimiter)
|
|
233
|
-
// // chain.push(this.rateLimitManager.middleware());
|
|
234
|
-
|
|
235
|
-
// // // Centralized error handling
|
|
236
|
-
// // chain.push(errorHandler);
|
|
237
|
-
|
|
238
|
-
// // return chain;
|
|
239
|
-
// // }
|
|
240
|
-
// // }
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
// src/core/HiSecure.ts - COMPLETE FIXED
|
|
245
|
-
// import { HiSecureConfig } from "./types/HiSecureConfig.js";
|
|
246
|
-
// import { defaultConfig } from "./config.js";
|
|
247
|
-
// import { LIB_NAME, LIB_VERSION } from "./constants.js";
|
|
248
|
-
// import { deepMerge } from "../utils/deepMerge.js";
|
|
249
|
-
// import { deepFreeze } from "../utils/deepFreeze.js";
|
|
250
|
-
// import { logger } from "../logging/index.js";
|
|
251
|
-
|
|
252
|
-
// // Adapters
|
|
253
|
-
// import { ArgonAdapter } from "../adapters/ArgonAdapter.js";
|
|
254
|
-
// import { BcryptAdapter } from "../adapters/BcryptAdapter.js";
|
|
255
|
-
// import { RLFlexibleAdapter } from "../adapters/RLFlexibleAdapter.js";
|
|
256
|
-
// import { ExpressRLAdapter } from "../adapters/ExpressRLAdapter.js";
|
|
257
|
-
// import { ZodAdapter } from "../adapters/ZodAdapter.js";
|
|
258
|
-
// import { ExpressValidatorAdapter } from "../adapters/ExpressValidatorAdapter.js";
|
|
259
|
-
// import { SanitizeHtmlAdapter } from "../adapters/SanitizeHtmlAdapter.js";
|
|
260
|
-
// import { XSSAdapter } from "../adapters/XSSAdapter.js"; // ✅ FIXED IMPORT
|
|
261
|
-
|
|
262
|
-
// // Managers
|
|
263
|
-
// import { HashManager } from "../managers/HashManager.js";
|
|
264
|
-
// import { RateLimitManager } from "../managers/RateLimitManager.js";
|
|
265
|
-
// import { ValidatorManager } from "../managers/ValidatorManager.js";
|
|
266
|
-
// import { SanitizerManager } from "../managers/SanitizerManager.js";
|
|
267
|
-
// import { JsonManager } from "../managers/JsonManager.js";
|
|
268
|
-
// import { CorsManager } from "../managers/CorsManager.js";
|
|
269
|
-
// import { AuthManager } from "../managers/AuthManager.js";
|
|
270
|
-
|
|
271
|
-
// // Middlewares
|
|
272
|
-
// import helmet from "helmet";
|
|
273
|
-
// import hpp from "hpp";
|
|
274
|
-
// import compression from "compression";
|
|
275
|
-
// import { errorHandler } from "../middlewares/errorHandler.js";
|
|
276
|
-
|
|
277
|
-
// // Types
|
|
278
|
-
// import { SecureOptions, ValidationSchema } from "./types/SecureOptions.js";
|
|
279
|
-
|
|
280
|
-
// export class HiSecure {
|
|
281
|
-
// private static instance: HiSecure | null = null;
|
|
282
|
-
// private config: HiSecureConfig;
|
|
283
|
-
// private initialized = false;
|
|
284
|
-
|
|
285
|
-
// // Managers
|
|
286
|
-
// public hashManager!: HashManager;
|
|
287
|
-
// public rateLimitManager!: RateLimitManager;
|
|
288
|
-
// public validatorManager!: ValidatorManager;
|
|
289
|
-
// public sanitizerManager!: SanitizerManager;
|
|
290
|
-
// public jsonManager!: JsonManager;
|
|
291
|
-
// public corsManager!: CorsManager;
|
|
292
|
-
// public authManager?: AuthManager;
|
|
293
|
-
|
|
294
|
-
// // Internal adapters
|
|
295
|
-
// private hashingPrimary: any;
|
|
296
|
-
// private hashingFallback: any;
|
|
297
|
-
// private rateLimiterPrimary: any;
|
|
298
|
-
// private rateLimiterFallback: any;
|
|
299
|
-
// private validatorPrimary: any;
|
|
300
|
-
// private validatorFallback: any;
|
|
301
|
-
// private sanitizerPrimary: any;
|
|
302
|
-
// private sanitizerFallback: any;
|
|
303
|
-
|
|
304
|
-
// // Private constructor for singleton
|
|
305
|
-
// private constructor(userConfig: Partial<HiSecureConfig> = {}) {
|
|
306
|
-
// this.config = deepMerge(defaultConfig, userConfig);
|
|
307
|
-
// }
|
|
308
|
-
|
|
309
|
-
// // =====================================================
|
|
310
|
-
// // SINGLETON & INITIALIZATION
|
|
311
|
-
// // =====================================================
|
|
312
|
-
|
|
313
|
-
// static getInstance(config?: Partial<HiSecureConfig>): HiSecure {
|
|
314
|
-
// if (!HiSecure.instance) {
|
|
315
|
-
// HiSecure.instance = new HiSecure(config);
|
|
316
|
-
// HiSecure.instance.init();
|
|
317
|
-
// }
|
|
318
|
-
// return HiSecure.instance;
|
|
319
|
-
// }
|
|
320
|
-
|
|
321
|
-
// static resetInstance(): void {
|
|
322
|
-
// HiSecure.instance = null;
|
|
323
|
-
// }
|
|
324
|
-
|
|
325
|
-
// init(): void {
|
|
326
|
-
// if (this.initialized) {
|
|
327
|
-
// logger.warn("⚠ HiSecure already initialized");
|
|
328
|
-
// return;
|
|
329
|
-
// }
|
|
330
|
-
|
|
331
|
-
// logger.info(`🔐 ${LIB_NAME} v${LIB_VERSION} initializing...`);
|
|
332
|
-
|
|
333
|
-
// this.setupAdapters();
|
|
334
|
-
// this.setupManagers();
|
|
335
|
-
// this.setupDynamicManagers();
|
|
336
|
-
|
|
337
|
-
// // Make everything immutable
|
|
338
|
-
// deepFreeze(this.config);
|
|
339
|
-
// deepFreeze(this.hashManager);
|
|
340
|
-
// deepFreeze(this.rateLimitManager);
|
|
341
|
-
// deepFreeze(this.validatorManager);
|
|
342
|
-
// deepFreeze(this.sanitizerManager);
|
|
343
|
-
// deepFreeze(this.jsonManager);
|
|
344
|
-
// deepFreeze(this.corsManager);
|
|
345
|
-
// if (this.authManager) deepFreeze(this.authManager);
|
|
346
|
-
|
|
347
|
-
// this.initialized = true;
|
|
348
|
-
// logger.info("✅ HiSecure initialized successfully");
|
|
349
|
-
// }
|
|
350
|
-
|
|
351
|
-
// isInitialized(): boolean {
|
|
352
|
-
// return this.initialized;
|
|
353
|
-
// }
|
|
354
|
-
|
|
355
|
-
// // =====================================================
|
|
356
|
-
// // FLUENT API METHODS (Route-level security)
|
|
357
|
-
// // =====================================================
|
|
358
|
-
|
|
359
|
-
// static auth(options?: { required?: boolean; roles?: string[] }) {
|
|
360
|
-
// const instance = this.getInstance();
|
|
361
|
-
// if (!instance.authManager) {
|
|
362
|
-
// throw new Error("Auth not enabled. Set auth.enabled=true in config.");
|
|
363
|
-
// }
|
|
364
|
-
// return instance.authManager.protect(options);
|
|
365
|
-
// }
|
|
366
|
-
|
|
367
|
-
// static validate(schema: ValidationSchema) {
|
|
368
|
-
// return this.getInstance().validatorManager.validate(schema);
|
|
369
|
-
// }
|
|
370
|
-
|
|
371
|
-
// static sanitize(options?: any) {
|
|
372
|
-
// return this.getInstance().sanitizerManager.middleware(options);
|
|
373
|
-
// }
|
|
374
|
-
|
|
375
|
-
// static rateLimit(preset: "strict" | "relaxed" | "api" | object) {
|
|
376
|
-
// const instance = this.getInstance();
|
|
377
|
-
|
|
378
|
-
// if (typeof preset === "string") {
|
|
379
|
-
// const presets = {
|
|
380
|
-
// strict: { mode: "strict" as const },
|
|
381
|
-
// relaxed: { mode: "relaxed" as const },
|
|
382
|
-
// api: { max: 100, windowMs: 60000 }
|
|
383
|
-
// };
|
|
384
|
-
// return instance.rateLimitManager.middleware(presets[preset] || {});
|
|
385
|
-
// }
|
|
386
|
-
|
|
387
|
-
// return instance.rateLimitManager.middleware({ options: preset });
|
|
388
|
-
// }
|
|
389
|
-
|
|
390
|
-
// static cors(options?: any) {
|
|
391
|
-
// return this.getInstance().corsManager.middleware(options);
|
|
392
|
-
// }
|
|
393
|
-
|
|
394
|
-
// static json(options?: any) {
|
|
395
|
-
// const instance = this.getInstance();
|
|
396
|
-
// const chain = [];
|
|
397
|
-
// chain.push(instance.jsonManager.middleware(options));
|
|
398
|
-
// chain.push(instance.jsonManager.urlencoded());
|
|
399
|
-
// return chain;
|
|
400
|
-
// }
|
|
401
|
-
|
|
402
|
-
// // =====================================================
|
|
403
|
-
// // UTILITY METHODS (Direct usage)
|
|
404
|
-
// // =====================================================
|
|
405
|
-
|
|
406
|
-
// static async hash(password: string): Promise<string> {
|
|
407
|
-
// const instance = this.getInstance();
|
|
408
|
-
// const result = await instance.hashManager.hash(password, { allowFallback: true });
|
|
409
|
-
// return result.hash;
|
|
410
|
-
// }
|
|
411
|
-
|
|
412
|
-
// static async verify(password: string, hash: string): Promise<boolean> {
|
|
413
|
-
// return this.getInstance().hashManager.verify(password, hash);
|
|
414
|
-
// }
|
|
415
|
-
|
|
416
|
-
// static jwt = {
|
|
417
|
-
// sign: (payload: object, options?: any) => {
|
|
418
|
-
// const instance = HiSecure.getInstance();
|
|
419
|
-
// if (!instance.authManager) {
|
|
420
|
-
// throw new Error("Auth not enabled");
|
|
421
|
-
// }
|
|
422
|
-
// return instance.authManager.sign(payload, options);
|
|
423
|
-
// },
|
|
424
|
-
|
|
425
|
-
// verify: (token: string) => {
|
|
426
|
-
// const instance = HiSecure.getInstance();
|
|
427
|
-
// if (!instance.authManager) {
|
|
428
|
-
// throw new Error("Auth not enabled");
|
|
429
|
-
// }
|
|
430
|
-
// return instance.authManager.verify(token);
|
|
431
|
-
// },
|
|
432
|
-
|
|
433
|
-
// google: {
|
|
434
|
-
// verifyIdToken: (idToken: string) => {
|
|
435
|
-
// const instance = HiSecure.getInstance();
|
|
436
|
-
// if (!instance.authManager) {
|
|
437
|
-
// throw new Error("Auth not enabled");
|
|
438
|
-
// }
|
|
439
|
-
// return instance.authManager.verifyGoogleIdToken(idToken);
|
|
440
|
-
// }
|
|
441
|
-
// }
|
|
442
|
-
// };
|
|
443
|
-
|
|
444
|
-
// // =====================================================
|
|
445
|
-
// // GLOBAL MIDDLEWARE (app.use())
|
|
446
|
-
// // =====================================================
|
|
447
|
-
|
|
448
|
-
// static middleware(options?: SecureOptions | "api" | "strict" | "public") {
|
|
449
|
-
// const instance = this.getInstance();
|
|
450
|
-
|
|
451
|
-
// // Handle preset strings
|
|
452
|
-
// if (typeof options === "string") {
|
|
453
|
-
// const presets = {
|
|
454
|
-
// api: { cors: true, rateLimit: "relaxed", sanitize: true },
|
|
455
|
-
// strict: { cors: true, rateLimit: "strict", sanitize: true, auth: true },
|
|
456
|
-
// public: { cors: true, rateLimit: true }
|
|
457
|
-
// };
|
|
458
|
-
// options = presets[options] || {};
|
|
459
|
-
// }
|
|
460
|
-
|
|
461
|
-
// return instance.createMiddlewareChain(options || {});
|
|
462
|
-
// }
|
|
463
|
-
|
|
464
|
-
// // =====================================================
|
|
465
|
-
// // INTERNAL METHODS
|
|
466
|
-
// // =====================================================
|
|
467
|
-
|
|
468
|
-
// private setupAdapters(): void {
|
|
469
|
-
// logger.info("🧩 Setting up adapters...");
|
|
470
|
-
|
|
471
|
-
// // Hashing
|
|
472
|
-
// this.hashingPrimary = this.config.hashing.primary === "argon2"
|
|
473
|
-
// ? new ArgonAdapter()
|
|
474
|
-
// : new BcryptAdapter(this.config.hashing.saltRounds);
|
|
475
|
-
|
|
476
|
-
// this.hashingFallback = this.config.hashing.fallback === "bcrypt"
|
|
477
|
-
// ? new BcryptAdapter(this.config.hashing.saltRounds)
|
|
478
|
-
// : null;
|
|
479
|
-
|
|
480
|
-
// // Rate limiting
|
|
481
|
-
// this.rateLimiterPrimary = this.config.rateLimiter.useAdaptiveMode
|
|
482
|
-
// ? new RLFlexibleAdapter()
|
|
483
|
-
// : new ExpressRLAdapter();
|
|
484
|
-
// this.rateLimiterFallback = new ExpressRLAdapter();
|
|
485
|
-
|
|
486
|
-
// // Validation
|
|
487
|
-
// this.validatorPrimary = this.config.validation.mode === "zod"
|
|
488
|
-
// ? new ZodAdapter()
|
|
489
|
-
// : new ExpressValidatorAdapter();
|
|
490
|
-
// this.validatorFallback = this.config.validation.fallback === "express-validator"
|
|
491
|
-
// ? new ExpressValidatorAdapter()
|
|
492
|
-
// : null;
|
|
493
|
-
|
|
494
|
-
// // Sanitization
|
|
495
|
-
// this.sanitizerPrimary = new SanitizeHtmlAdapter(this.config.sanitizer);
|
|
496
|
-
// this.sanitizerFallback = new XSSAdapter(this.config.sanitizer); // ✅ XSSAdapter, NOT DomPurifyAdapter
|
|
497
|
-
|
|
498
|
-
// logger.info("✅ Adapters ready");
|
|
499
|
-
// }
|
|
500
|
-
|
|
501
|
-
// private setupManagers(): void {
|
|
502
|
-
// this.hashManager = new HashManager(
|
|
503
|
-
// this.config.hashing,
|
|
504
|
-
// this.hashingPrimary,
|
|
505
|
-
// this.hashingFallback
|
|
506
|
-
// );
|
|
507
|
-
|
|
508
|
-
// this.rateLimitManager = new RateLimitManager(
|
|
509
|
-
// this.config.rateLimiter,
|
|
510
|
-
// this.rateLimiterPrimary,
|
|
511
|
-
// this.rateLimiterFallback
|
|
512
|
-
// );
|
|
513
|
-
|
|
514
|
-
// this.validatorManager = new ValidatorManager(
|
|
515
|
-
// this.config.validation,
|
|
516
|
-
// this.validatorPrimary,
|
|
517
|
-
// this.validatorFallback
|
|
518
|
-
// );
|
|
519
|
-
|
|
520
|
-
// this.sanitizerManager = new SanitizerManager(
|
|
521
|
-
// this.sanitizerPrimary,
|
|
522
|
-
// this.sanitizerFallback
|
|
523
|
-
// );
|
|
524
|
-
// }
|
|
525
|
-
|
|
526
|
-
// private setupDynamicManagers(): void {
|
|
527
|
-
// this.jsonManager = new JsonManager();
|
|
528
|
-
// this.corsManager = new CorsManager();
|
|
529
|
-
|
|
530
|
-
// // Auth manager (only if enabled)
|
|
531
|
-
// if (this.config.auth.enabled) {
|
|
532
|
-
// const jwtSecret = process.env.JWT_SECRET || this.config.auth.jwtSecret;
|
|
533
|
-
// if (!jwtSecret) {
|
|
534
|
-
// throw new Error("JWT_SECRET environment variable or jwtSecret in config is required when auth.enabled=true");
|
|
535
|
-
// }
|
|
536
|
-
|
|
537
|
-
// this.authManager = new AuthManager({
|
|
538
|
-
// jwtSecret,
|
|
539
|
-
// jwtExpiresIn: this.config.auth.jwtExpiresIn,
|
|
540
|
-
// googleClientId: process.env.GOOGLE_CLIENT_ID || this.config.auth.googleClientId,
|
|
541
|
-
// // ✅ Add algorithm option for JWT security
|
|
542
|
-
// algorithm: 'HS256'
|
|
543
|
-
// });
|
|
544
|
-
// }
|
|
545
|
-
// }
|
|
546
|
-
|
|
547
|
-
// private createMiddlewareChain(options: SecureOptions): any[] {
|
|
548
|
-
// const chain: any[] = [];
|
|
549
|
-
|
|
550
|
-
// // JSON parsing
|
|
551
|
-
// chain.push(this.jsonManager.middleware(this.config.json));
|
|
552
|
-
// chain.push(this.jsonManager.urlencoded(this.config.urlencoded));
|
|
553
|
-
|
|
554
|
-
// // Security headers
|
|
555
|
-
// if (this.config.enableHelmet) chain.push(helmet());
|
|
556
|
-
// if (this.config.enableHPP) chain.push(hpp());
|
|
557
|
-
|
|
558
|
-
// // Compression (check if compression config exists)
|
|
559
|
-
// if (this.config.enableCompression && this.config.compression) {
|
|
560
|
-
// chain.push(compression(this.config.compression));
|
|
561
|
-
// } else if (this.config.enableCompression) {
|
|
562
|
-
// chain.push(compression()); // Use defaults
|
|
563
|
-
// }
|
|
564
|
-
|
|
565
|
-
// // CORS
|
|
566
|
-
// if (this.config.enableCORS || options.cors) {
|
|
567
|
-
// const corsOptions = options.cors === true ? this.config.cors :
|
|
568
|
-
// (typeof options.cors === 'object' ? options.cors : this.config.cors);
|
|
569
|
-
// chain.push(this.corsManager.middleware(corsOptions));
|
|
570
|
-
// }
|
|
571
|
-
|
|
572
|
-
// // Sanitization
|
|
573
|
-
// if (this.config.enableSanitizer || options.sanitize) {
|
|
574
|
-
// const sanitizeOptions = options.sanitize === true ? undefined :
|
|
575
|
-
// (typeof options.sanitize === 'object' ? options.sanitize : undefined);
|
|
576
|
-
// chain.push(this.sanitizerManager.middleware(sanitizeOptions));
|
|
577
|
-
// }
|
|
578
|
-
|
|
579
|
-
// // Rate limiting
|
|
580
|
-
// if (this.config.enableRateLimiter || options.rateLimit) {
|
|
581
|
-
// const rateLimitOpts = typeof options.rateLimit === 'object' ?
|
|
582
|
-
// { options: options.rateLimit } : {};
|
|
583
|
-
// chain.push(this.rateLimitManager.middleware(rateLimitOpts));
|
|
584
|
-
// }
|
|
585
|
-
|
|
586
|
-
// // Authentication
|
|
587
|
-
// if (options.auth && this.authManager) {
|
|
588
|
-
// const authOpts = options.auth === true ? undefined :
|
|
589
|
-
// (typeof options.auth === 'object' ? options.auth : undefined);
|
|
590
|
-
// chain.push(this.authManager.protect(authOpts));
|
|
591
|
-
// }
|
|
592
|
-
|
|
593
|
-
// // Error handler (always last)
|
|
594
|
-
// chain.push(errorHandler);
|
|
595
|
-
|
|
596
|
-
// return chain;
|
|
597
|
-
// }
|
|
598
|
-
// }
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
// =================
|
|
603
|
-
|
|
604
1
|
// src/core/HiSecure.ts - COMPLETELY FIXED
|
|
605
2
|
import { HiSecureConfig } from "./types/HiSecureConfig.js";
|
|
606
3
|
import { defaultConfig } from "./config.js";
|
|
@@ -963,241 +360,7 @@ export class HiSecure {
|
|
|
963
360
|
}
|
|
964
361
|
|
|
965
362
|
|
|
966
|
-
// ===================
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
// // src/core/HiSecure.ts - FINAL VERSION
|
|
971
|
-
// import { HiSecureConfig } from "./types/HiSecureConfig.js";
|
|
972
|
-
// import { defaultConfig } from "./config.js";
|
|
973
|
-
// import { LIB_NAME, LIB_VERSION } from "./constants.js";
|
|
974
|
-
// import { deepMerge } from "../utils/deepMerge.js";
|
|
975
|
-
// import { deepFreeze } from "../utils/deepFreeze.js";
|
|
976
|
-
// import { logger } from "../logging/index.js";
|
|
977
|
-
|
|
978
|
-
// // Adapters
|
|
979
|
-
// import { ArgonAdapter } from "../adapters/ArgonAdapter.js";
|
|
980
|
-
// import { BcryptAdapter } from "../adapters/BcryptAdapter.js";
|
|
981
|
-
// import { RLFlexibleAdapter } from "../adapters/RLFlexibleAdapter.js";
|
|
982
|
-
// import { ExpressRLAdapter } from "../adapters/ExpressRLAdapter.js";
|
|
983
|
-
// import { ZodAdapter } from "../adapters/ZodAdapter.js";
|
|
984
|
-
// import { ExpressValidatorAdapter } from "../adapters/ExpressValidatorAdapter.js";
|
|
985
|
-
// import { SanitizeHtmlAdapter } from "../adapters/SanitizeHtmlAdapter.js";
|
|
986
|
-
// import { XSSAdapter } from "../adapters/XSSAdapter.js";
|
|
987
|
-
|
|
988
|
-
// // Managers
|
|
989
|
-
// import { HashManager } from "../managers/HashManager.js";
|
|
990
|
-
// import { RateLimitManager } from "../managers/RateLimitManager.js";
|
|
991
|
-
// import { ValidatorManager } from "../managers/ValidatorManager.js";
|
|
992
|
-
// import { SanitizerManager } from "../managers/SanitizerManager.js";
|
|
993
|
-
// import { JsonManager } from "../managers/JsonManager.js";
|
|
994
|
-
// import { CorsManager } from "../managers/CorsManager.js";
|
|
995
|
-
// import { AuthManager } from "../managers/AuthManager.js";
|
|
996
|
-
|
|
997
|
-
// // Middlewares
|
|
998
|
-
// import helmet from "helmet";
|
|
999
|
-
// import hpp from "hpp";
|
|
1000
|
-
// import compression from "compression";
|
|
1001
|
-
// import { errorHandler } from "../middlewares/errorHandler.js";
|
|
1002
|
-
|
|
1003
|
-
// // Types
|
|
1004
|
-
// import { SecureOptions, ValidationSchema } from "./types/SecureOptions.js";
|
|
1005
|
-
|
|
1006
|
-
// export class HiSecure {
|
|
1007
|
-
// private static instance: HiSecure | null = null;
|
|
1008
|
-
// private config: HiSecureConfig;
|
|
1009
|
-
// private initialized = false;
|
|
1010
|
-
|
|
1011
|
-
// // Managers
|
|
1012
|
-
// public hashManager!: HashManager;
|
|
1013
|
-
// public rateLimitManager!: RateLimitManager;
|
|
1014
|
-
// public validatorManager!: ValidatorManager;
|
|
1015
|
-
// public sanitizerManager!: SanitizerManager;
|
|
1016
|
-
// public jsonManager!: JsonManager;
|
|
1017
|
-
// public corsManager!: CorsManager;
|
|
1018
|
-
// public authManager?: AuthManager;
|
|
1019
|
-
|
|
1020
|
-
// // Internal adapters
|
|
1021
|
-
// private hashingPrimary: any;
|
|
1022
|
-
// private hashingFallback: any;
|
|
1023
|
-
// private rateLimiterPrimary: any;
|
|
1024
|
-
// private rateLimiterFallback: any;
|
|
1025
|
-
|
|
1026
|
-
// private constructor(userConfig: Partial<HiSecureConfig> = {}) {
|
|
1027
|
-
// this.config = deepMerge(defaultConfig, userConfig);
|
|
1028
|
-
// }
|
|
1029
|
-
|
|
1030
|
-
// // =====================================================
|
|
1031
|
-
// // SINGLETON
|
|
1032
|
-
// // =====================================================
|
|
1033
|
-
// static getInstance(config?: Partial<HiSecureConfig>): HiSecure {
|
|
1034
|
-
// if (!HiSecure.instance) {
|
|
1035
|
-
// HiSecure.instance = new HiSecure(config);
|
|
1036
|
-
// HiSecure.instance.init();
|
|
1037
|
-
// }
|
|
1038
|
-
// return HiSecure.instance;
|
|
1039
|
-
// }
|
|
1040
|
-
|
|
1041
|
-
// static resetInstance(): void {
|
|
1042
|
-
// HiSecure.instance = null;
|
|
1043
|
-
// }
|
|
1044
|
-
|
|
1045
|
-
// init(): void {
|
|
1046
|
-
// if (this.initialized) return;
|
|
1047
|
-
|
|
1048
|
-
// logger.info(`🔐 ${LIB_NAME} v${LIB_VERSION} initializing...`);
|
|
1049
|
-
|
|
1050
|
-
// this.setupAdapters();
|
|
1051
|
-
// this.setupManagers();
|
|
1052
|
-
// this.setupDynamicManagers();
|
|
1053
|
-
|
|
1054
|
-
// // ❌ DO NOT FREEZE MANAGERS
|
|
1055
|
-
// // ✔ Only freeze config
|
|
1056
|
-
// deepFreeze(this.config);
|
|
1057
|
-
|
|
1058
|
-
// this.initialized = true;
|
|
1059
|
-
// logger.info("✅ HiSecure initialized successfully");
|
|
1060
|
-
// }
|
|
1061
|
-
|
|
1062
|
-
// // =====================================================
|
|
1063
|
-
// // FLUENT API (Route-level)
|
|
1064
|
-
// // =====================================================
|
|
1065
|
-
|
|
1066
|
-
// static auth(options?: { required?: boolean; roles?: string[] }) {
|
|
1067
|
-
// return this.getInstance().authManager!.protect(options);
|
|
1068
|
-
// }
|
|
1069
|
-
|
|
1070
|
-
// static validate(schema: ValidationSchema) {
|
|
1071
|
-
// return this.getInstance().validatorManager.validate(schema);
|
|
1072
|
-
// }
|
|
1073
|
-
|
|
1074
|
-
// static sanitize(options?: any) {
|
|
1075
|
-
// return this.getInstance().sanitizerManager.middleware(options);
|
|
1076
|
-
// }
|
|
1077
|
-
|
|
1078
|
-
// static cors(options?: any) {
|
|
1079
|
-
// return this.getInstance().corsManager.middleware(options);
|
|
1080
|
-
// }
|
|
1081
|
-
|
|
1082
|
-
// static rateLimit(preset: "strict" | "relaxed" | "api" | object) {
|
|
1083
|
-
// const instance = this.getInstance();
|
|
1084
|
-
|
|
1085
|
-
// if (typeof preset === "string") {
|
|
1086
|
-
// const presets: any = {
|
|
1087
|
-
// strict: { mode: "strict" },
|
|
1088
|
-
// relaxed: { mode: "relaxed" },
|
|
1089
|
-
// api: { mode: "api", options: { max: 100, windowMs: 60000 } }
|
|
1090
|
-
// };
|
|
1091
|
-
// return instance.rateLimitManager.middleware(presets[preset] || {});
|
|
1092
|
-
// }
|
|
1093
|
-
// return instance.rateLimitManager.middleware({ options: preset });
|
|
1094
|
-
// }
|
|
1095
|
-
|
|
1096
|
-
// static json(options?: any) {
|
|
1097
|
-
// const instance = this.getInstance();
|
|
1098
|
-
// return [
|
|
1099
|
-
// instance.jsonManager.middleware(options),
|
|
1100
|
-
// instance.jsonManager.urlencoded()
|
|
1101
|
-
// ];
|
|
1102
|
-
// }
|
|
1103
|
-
|
|
1104
|
-
// // =====================================================
|
|
1105
|
-
// // INTERNAL SETUP
|
|
1106
|
-
// // =====================================================
|
|
1107
|
-
|
|
1108
|
-
// private setupAdapters(): void {
|
|
1109
|
-
// logger.info("🧩 Setting up adapters...");
|
|
1110
|
-
|
|
1111
|
-
// this.hashingPrimary = this.config.hashing.primary === "argon2"
|
|
1112
|
-
// ? new ArgonAdapter()
|
|
1113
|
-
// : new BcryptAdapter(this.config.hashing.saltRounds);
|
|
1114
|
-
|
|
1115
|
-
// this.hashingFallback = this.config.hashing.fallback === "bcrypt"
|
|
1116
|
-
// ? new BcryptAdapter(this.config.hashing.saltRounds)
|
|
1117
|
-
// : null;
|
|
1118
|
-
|
|
1119
|
-
// this.rateLimiterPrimary = this.config.rateLimiter.useAdaptiveMode
|
|
1120
|
-
// ? new RLFlexibleAdapter()
|
|
1121
|
-
// : new ExpressRLAdapter();
|
|
1122
|
-
|
|
1123
|
-
// this.rateLimiterFallback = new ExpressRLAdapter();
|
|
1124
|
-
|
|
1125
|
-
// logger.info("✅ Adapters ready");
|
|
1126
|
-
// }
|
|
1127
|
-
|
|
1128
|
-
// private setupManagers(): void {
|
|
1129
|
-
// this.hashManager = new HashManager(this.config.hashing, this.hashingPrimary, this.hashingFallback);
|
|
1130
|
-
|
|
1131
|
-
// this.rateLimitManager = new RateLimitManager(
|
|
1132
|
-
// this.config.rateLimiter,
|
|
1133
|
-
// this.rateLimiterPrimary,
|
|
1134
|
-
// this.rateLimiterFallback
|
|
1135
|
-
// );
|
|
1136
|
-
|
|
1137
|
-
// // ✔ AUTO-DETECT VALIDATION (ZOD + EXPRESS-VALIDATOR)
|
|
1138
|
-
// this.validatorManager = new ValidatorManager(
|
|
1139
|
-
// new ZodAdapter(),
|
|
1140
|
-
// new ExpressValidatorAdapter()
|
|
1141
|
-
// );
|
|
1142
|
-
|
|
1143
|
-
// this.sanitizerManager = new SanitizerManager(
|
|
1144
|
-
// new SanitizeHtmlAdapter(this.config.sanitizer),
|
|
1145
|
-
// new XSSAdapter(this.config.sanitizer)
|
|
1146
|
-
// );
|
|
1147
|
-
// }
|
|
1148
|
-
|
|
1149
|
-
// private setupDynamicManagers(): void {
|
|
1150
|
-
// this.jsonManager = new JsonManager();
|
|
1151
|
-
// this.corsManager = new CorsManager();
|
|
1152
|
-
|
|
1153
|
-
// if (this.config.auth.enabled) {
|
|
1154
|
-
// const jwtSecret = process.env.JWT_SECRET || this.config.auth.jwtSecret;
|
|
1155
|
-
// if (!jwtSecret) throw new Error("JWT_SECRET is required when auth.enabled=true");
|
|
1156
|
-
|
|
1157
|
-
// this.authManager = new AuthManager({
|
|
1158
|
-
// jwtSecret,
|
|
1159
|
-
// jwtExpiresIn: this.config.auth.jwtExpiresIn,
|
|
1160
|
-
// googleClientId: this.config.auth.googleClientId
|
|
1161
|
-
// });
|
|
1162
|
-
// }
|
|
1163
|
-
// }
|
|
1164
|
-
|
|
1165
|
-
// private createMiddlewareChain(options: SecureOptions): any[] {
|
|
1166
|
-
// const chain: any[] = [];
|
|
1167
|
-
|
|
1168
|
-
// chain.push(this.jsonManager.middleware(this.config.json));
|
|
1169
|
-
// chain.push(this.jsonManager.urlencoded(this.config.urlencoded));
|
|
1170
|
-
|
|
1171
|
-
// if (this.config.enableHelmet) chain.push(helmet());
|
|
1172
|
-
// if (this.config.enableHPP) chain.push(hpp());
|
|
1173
|
-
|
|
1174
|
-
// if (this.config.enableCompression) chain.push(compression(this.config.compression));
|
|
1175
|
-
|
|
1176
|
-
// if (this.config.enableCORS || options.cors) {
|
|
1177
|
-
// const opts = typeof options.cors === "object" ? options.cors : this.config.cors;
|
|
1178
|
-
// chain.push(this.corsManager.middleware(opts));
|
|
1179
|
-
// }
|
|
1180
|
-
|
|
1181
|
-
// if (this.config.enableSanitizer || options.sanitize) {
|
|
1182
|
-
// const opts = typeof options.sanitize === "object" ? options.sanitize : undefined;
|
|
1183
|
-
// chain.push(this.sanitizerManager.middleware(opts));
|
|
1184
|
-
// }
|
|
1185
|
-
|
|
1186
|
-
// if (this.config.enableRateLimiter || options.rateLimit) {
|
|
1187
|
-
// const opts = typeof options.rateLimit === "object" ? { options: options.rateLimit } : {};
|
|
1188
|
-
// chain.push(this.rateLimitManager.middleware(opts));
|
|
1189
|
-
// }
|
|
1190
|
-
|
|
1191
|
-
// if (options.auth && this.authManager) {
|
|
1192
|
-
// const opts = typeof options.auth === "object" ? options.auth : undefined;
|
|
1193
|
-
// chain.push(this.authManager.protect(opts));
|
|
1194
|
-
// }
|
|
1195
|
-
|
|
1196
|
-
// chain.push(errorHandler);
|
|
1197
363
|
|
|
1198
|
-
// return chain;
|
|
1199
|
-
// }
|
|
1200
|
-
// }
|
|
1201
364
|
|
|
1202
365
|
|
|
1203
366
|
|