hi-secure 1.0.16 → 1.0.17
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/ArgonAdapter.d.ts.map +1 -1
- package/dist/adapters/ArgonAdapter.js +0 -36
- package/dist/adapters/ArgonAdapter.js.map +1 -1
- package/dist/adapters/BcryptAdapter.d.ts.map +1 -1
- package/dist/adapters/BcryptAdapter.js +0 -36
- package/dist/adapters/BcryptAdapter.js.map +1 -1
- package/dist/adapters/ExpressRLAdapter.d.ts.map +1 -1
- package/dist/adapters/ExpressRLAdapter.js +0 -38
- package/dist/adapters/ExpressRLAdapter.js.map +1 -1
- package/dist/adapters/ExpressValidatorAdapter.d.ts.map +1 -1
- package/dist/adapters/ExpressValidatorAdapter.js +0 -36
- package/dist/adapters/ExpressValidatorAdapter.js.map +1 -1
- package/dist/adapters/GoogleAdapter.d.ts.map +1 -1
- package/dist/adapters/GoogleAdapter.js +0 -63
- package/dist/adapters/GoogleAdapter.js.map +1 -1
- package/dist/adapters/JWTAdapter.d.ts.map +1 -1
- package/dist/adapters/JWTAdapter.js +0 -79
- package/dist/adapters/JWTAdapter.js.map +1 -1
- package/dist/adapters/RLFlexibleAdapter.d.ts.map +1 -1
- package/dist/adapters/RLFlexibleAdapter.js +0 -64
- package/dist/adapters/RLFlexibleAdapter.js.map +1 -1
- package/dist/adapters/SanitizeHtmlAdapter.d.ts.map +1 -1
- package/dist/adapters/SanitizeHtmlAdapter.js +0 -64
- package/dist/adapters/SanitizeHtmlAdapter.js.map +1 -1
- package/dist/adapters/XSSAdapter.d.ts.map +1 -1
- package/dist/adapters/XSSAdapter.js +0 -116
- package/dist/adapters/XSSAdapter.js.map +1 -1
- package/dist/adapters/ZodAdapter.d.ts.map +1 -1
- package/dist/adapters/ZodAdapter.js +0 -3
- package/dist/adapters/ZodAdapter.js.map +1 -1
- package/dist/core/HiSecure.d.ts.map +1 -1
- package/dist/core/HiSecure.js +0 -16
- package/dist/core/HiSecure.js.map +1 -1
- package/dist/logging/index.d.ts.map +1 -1
- package/dist/logging/index.js +0 -2
- package/dist/logging/index.js.map +1 -1
- package/dist/logging/morganSetup.d.ts.map +1 -1
- package/dist/logging/morganSetup.js +0 -14
- package/dist/logging/morganSetup.js.map +1 -1
- package/dist/logging/winstonSetup.d.ts.map +1 -1
- package/dist/logging/winstonSetup.js +2 -46
- package/dist/logging/winstonSetup.js.map +1 -1
- package/dist/managers/AuthManager.d.ts.map +1 -1
- package/dist/managers/AuthManager.js +0 -108
- package/dist/managers/AuthManager.js.map +1 -1
- package/dist/managers/CorsManager.d.ts.map +1 -1
- package/dist/managers/CorsManager.js +0 -28
- package/dist/managers/CorsManager.js.map +1 -1
- package/dist/managers/HashManager.d.ts.map +1 -1
- package/dist/managers/HashManager.js +0 -92
- package/dist/managers/HashManager.js.map +1 -1
- package/dist/managers/JsonManager.d.ts.map +1 -1
- package/dist/managers/JsonManager.js +0 -55
- package/dist/managers/JsonManager.js.map +1 -1
- package/dist/managers/RateLimitManager.d.ts.map +1 -1
- package/dist/managers/RateLimitManager.js +0 -3
- package/dist/managers/RateLimitManager.js.map +1 -1
- package/dist/managers/SanitizerManager.d.ts.map +1 -1
- package/dist/managers/SanitizerManager.js +0 -80
- package/dist/managers/SanitizerManager.js.map +1 -1
- package/dist/managers/ValidatorManager.d.ts.map +1 -1
- package/dist/managers/ValidatorManager.js +0 -59
- package/dist/managers/ValidatorManager.js.map +1 -1
- package/package.json +1 -1
- package/src/adapters/ArgonAdapter.ts +0 -45
- package/src/adapters/BcryptAdapter.ts +0 -49
- package/src/adapters/ExpressRLAdapter.ts +0 -48
- package/src/adapters/ExpressValidatorAdapter.ts +0 -50
- package/src/adapters/GoogleAdapter.ts +0 -82
- package/src/adapters/JWTAdapter.ts +0 -96
- package/src/adapters/RLFlexibleAdapter.ts +0 -82
- package/src/adapters/SanitizeHtmlAdapter.ts +1 -84
- package/src/adapters/XSSAdapter.ts +1 -150
- package/src/adapters/ZodAdapter.ts +0 -46
- package/src/core/HiSecure.ts +1 -369
- package/src/logging/index.ts +0 -6
- package/src/logging/morganSetup.ts +0 -25
- package/src/logging/winstonSetup.ts +2 -64
- package/src/managers/AuthManager.ts +0 -141
- package/src/managers/CorsManager.ts +0 -40
- package/src/managers/HashManager.ts +0 -108
- package/src/managers/JsonManager.ts +0 -62
- package/src/managers/RateLimitManager.ts +0 -113
- package/src/managers/SanitizerManager.ts +0 -103
- package/src/managers/ValidatorManager.ts +0 -75
|
@@ -1,152 +1,3 @@
|
|
|
1
|
-
// import { FilterXSS, getDefaultWhiteList, whiteList } from 'xss';
|
|
2
|
-
// import { AdapterError } from "../core/errors/AdapterError.js";
|
|
3
|
-
// import { logger } from "../logging/index.js";
|
|
4
|
-
|
|
5
|
-
// export interface XSSOptions {
|
|
6
|
-
// whiteList?: typeof whiteList;
|
|
7
|
-
// stripIgnoreTag?: boolean;
|
|
8
|
-
// stripIgnoreTagBody?: string[];
|
|
9
|
-
// allowCommentTag?: boolean;
|
|
10
|
-
// css?: boolean | { [key: string]: boolean };
|
|
11
|
-
// onTag?: (tag: string, html: string, options: any) => string;
|
|
12
|
-
// onTagAttr?: (tag: string, name: string, value: string, isWhiteAttr: boolean) => string;
|
|
13
|
-
// onIgnoreTag?: (tag: string, html: string, options: any) => string;
|
|
14
|
-
// [key: string]: any;
|
|
15
|
-
// }
|
|
16
|
-
|
|
17
|
-
// export class XSSAdapter {
|
|
18
|
-
// private globalOptions: XSSOptions;
|
|
19
|
-
// private defaultFilter: FilterXSS;
|
|
20
|
-
|
|
21
|
-
// constructor(options: XSSOptions = {}) {
|
|
22
|
-
// this.globalOptions = options;
|
|
23
|
-
|
|
24
|
-
// // Default safe configuration
|
|
25
|
-
// const defaultOptions: XSSOptions = {
|
|
26
|
-
// whiteList: getDefaultWhiteList(),
|
|
27
|
-
// stripIgnoreTag: true,
|
|
28
|
-
// stripIgnoreTagBody: ['script', 'style', 'iframe', 'object', 'embed'],
|
|
29
|
-
// allowCommentTag: false,
|
|
30
|
-
// css: false,
|
|
31
|
-
// onTag: (tag, html, options) => {
|
|
32
|
-
|
|
33
|
-
// if (tag === 'a') {
|
|
34
|
-
// return html.replace(/<a /i, '<a target="_blank" rel="noopener noreferrer" ');
|
|
35
|
-
// }
|
|
36
|
-
// return html;
|
|
37
|
-
// }
|
|
38
|
-
// };
|
|
39
|
-
|
|
40
|
-
// const finalOptions = { ...defaultOptions, ...options };
|
|
41
|
-
// this.defaultFilter = new FilterXSS(finalOptions);
|
|
42
|
-
// }
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
// sanitize(input: string, dynamicOptions?: XSSOptions): string {
|
|
46
|
-
// try {
|
|
47
|
-
// if (typeof input !== "string") {
|
|
48
|
-
// return input as any;
|
|
49
|
-
// }
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
// if (!dynamicOptions || Object.keys(dynamicOptions).length === 0) {
|
|
53
|
-
// return this.defaultFilter.process(input);
|
|
54
|
-
// }
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
// const mergedOptions = { ...this.globalOptions, ...dynamicOptions };
|
|
58
|
-
// const customFilter = new FilterXSS(mergedOptions);
|
|
59
|
-
|
|
60
|
-
// return customFilter.process(input);
|
|
61
|
-
|
|
62
|
-
// } catch (err: any) {
|
|
63
|
-
// logger.error("XSS sanitizer failed", {
|
|
64
|
-
// error: err?.message,
|
|
65
|
-
// preview: input?.slice?.(0, 80)
|
|
66
|
-
// });
|
|
67
|
-
// throw new AdapterError("XSS sanitizer failed.");
|
|
68
|
-
// }
|
|
69
|
-
// }
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
// middleware(dynamicOptions?: XSSOptions) {
|
|
73
|
-
// return (req: any, _res: any, next: any) => {
|
|
74
|
-
// try {
|
|
75
|
-
// if (req.body && typeof req.body === "object") {
|
|
76
|
-
// const originalBody = req.body;
|
|
77
|
-
// const sanitizedBody: any = Array.isArray(originalBody) ? [] : {};
|
|
78
|
-
|
|
79
|
-
// for (const key of Object.keys(originalBody)) {
|
|
80
|
-
// const val = originalBody[key];
|
|
81
|
-
|
|
82
|
-
// if (typeof val === "string") {
|
|
83
|
-
// sanitizedBody[key] = this.sanitize(val, dynamicOptions);
|
|
84
|
-
// } else if (Array.isArray(val)) {
|
|
85
|
-
// sanitizedBody[key] = val.map((v) =>
|
|
86
|
-
// typeof v === "string"
|
|
87
|
-
// ? this.sanitize(v, dynamicOptions)
|
|
88
|
-
// : v
|
|
89
|
-
// );
|
|
90
|
-
// } else if (val && typeof val === "object") {
|
|
91
|
-
|
|
92
|
-
// sanitizedBody[key] = this.deepSanitize(val, dynamicOptions);
|
|
93
|
-
// } else {
|
|
94
|
-
// sanitizedBody[key] = val;
|
|
95
|
-
// }
|
|
96
|
-
// }
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
// req.sanitizedBody = sanitizedBody;
|
|
100
|
-
|
|
101
|
-
// logger.debug("XSS sanitizer applied", {
|
|
102
|
-
// originalKeys: Object.keys(originalBody),
|
|
103
|
-
// sanitizedKeys: Object.keys(sanitizedBody)
|
|
104
|
-
// });
|
|
105
|
-
// }
|
|
106
|
-
|
|
107
|
-
// next();
|
|
108
|
-
// } catch (err: any) {
|
|
109
|
-
// logger.error("XSS middleware failed", {
|
|
110
|
-
// error: err?.message || err
|
|
111
|
-
// });
|
|
112
|
-
// next(err);
|
|
113
|
-
// }
|
|
114
|
-
// };
|
|
115
|
-
// }
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
// private deepSanitize(obj: any, options?: XSSOptions, visited = new WeakSet()): any {
|
|
119
|
-
|
|
120
|
-
// if (obj && typeof obj === "object") {
|
|
121
|
-
// if (visited.has(obj)) {
|
|
122
|
-
// return obj;
|
|
123
|
-
// }
|
|
124
|
-
// visited.add(obj);
|
|
125
|
-
// }
|
|
126
|
-
|
|
127
|
-
// if (typeof obj === "string") {
|
|
128
|
-
// return this.sanitize(obj, options);
|
|
129
|
-
// }
|
|
130
|
-
|
|
131
|
-
// if (Array.isArray(obj)) {
|
|
132
|
-
// return obj.map(item => this.deepSanitize(item, options, visited));
|
|
133
|
-
// }
|
|
134
|
-
|
|
135
|
-
// if (obj && typeof obj === "object") {
|
|
136
|
-
// const result: any = {};
|
|
137
|
-
// for (const key of Object.keys(obj)) {
|
|
138
|
-
// result[key] = this.deepSanitize(obj[key], options, visited);
|
|
139
|
-
// }
|
|
140
|
-
// return result;
|
|
141
|
-
// }
|
|
142
|
-
|
|
143
|
-
// return obj;
|
|
144
|
-
// }
|
|
145
|
-
// }
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
1
|
import { FilterXSS, getDefaultWhiteList, whiteList } from "xss";
|
|
151
2
|
import { AdapterError } from "../core/errors/AdapterError";
|
|
152
3
|
import { logger } from "../logging";
|
|
@@ -242,7 +93,7 @@ export class XSSAdapter {
|
|
|
242
93
|
|
|
243
94
|
req.sanitizedBody = sanitizedBody;
|
|
244
95
|
|
|
245
|
-
|
|
96
|
+
|
|
246
97
|
logger.info("XSS sanitization applied", {
|
|
247
98
|
adapter: "xss",
|
|
248
99
|
operation: "middleware",
|
|
@@ -1,49 +1,3 @@
|
|
|
1
|
-
// import { ZodSchema, ZodError } from "zod";
|
|
2
|
-
// import { ValidationError } from "../core/errors/ValidationError.js";
|
|
3
|
-
// import { logger } from "../logging/index.js";
|
|
4
|
-
|
|
5
|
-
// export class ZodAdapter {
|
|
6
|
-
// private globalSchema?: ZodSchema;
|
|
7
|
-
|
|
8
|
-
// constructor(globalSchema?: ZodSchema) {
|
|
9
|
-
// this.globalSchema = globalSchema;
|
|
10
|
-
// }
|
|
11
|
-
|
|
12
|
-
// validate(dynamicSchema?: ZodSchema) {
|
|
13
|
-
// return (req: any, res: any, next: any) => {
|
|
14
|
-
// const schema = dynamicSchema || this.globalSchema;
|
|
15
|
-
|
|
16
|
-
// if (!schema) return next();
|
|
17
|
-
|
|
18
|
-
// const result = schema.safeParse(req.body);
|
|
19
|
-
|
|
20
|
-
// if (result.success) return next();
|
|
21
|
-
|
|
22
|
-
// const zodErr: ZodError = result.error;
|
|
23
|
-
|
|
24
|
-
// const issues = zodErr.issues.map(issue => ({
|
|
25
|
-
// message: issue.message,
|
|
26
|
-
// path: issue.path.join("."),
|
|
27
|
-
// code: issue.code
|
|
28
|
-
// }));
|
|
29
|
-
|
|
30
|
-
// logger.warn("Zod validation failed", {
|
|
31
|
-
// path: req.path,
|
|
32
|
-
// method: req.method,
|
|
33
|
-
// issues,
|
|
34
|
-
// preview: JSON.stringify(req.body).slice(0, 200)
|
|
35
|
-
// });
|
|
36
|
-
|
|
37
|
-
// return next(
|
|
38
|
-
// new ValidationError("Validation failed.", issues as any)
|
|
39
|
-
// );
|
|
40
|
-
// };
|
|
41
|
-
// }
|
|
42
|
-
// }
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
1
|
import { ZodSchema, ZodError } from "zod";
|
|
48
2
|
import { ValidationError } from "../core/errors/ValidationError";
|
|
49
3
|
import { logger } from "../logging";
|
package/src/core/HiSecure.ts
CHANGED
|
@@ -1,362 +1,3 @@
|
|
|
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/index.js";
|
|
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 for singleton
|
|
59
|
-
// private constructor(userConfig: Partial<HiSecureConfig> = {}) {
|
|
60
|
-
// this.config = deepMerge(defaultConfig, userConfig);
|
|
61
|
-
// }
|
|
62
|
-
|
|
63
|
-
// // SINGLETON & INITIALIZATION
|
|
64
|
-
|
|
65
|
-
// static getInstance(config?: Partial<HiSecureConfig>): HiSecure {
|
|
66
|
-
// if (!HiSecure.instance) {
|
|
67
|
-
// HiSecure.instance = new HiSecure(config);
|
|
68
|
-
// HiSecure.instance.init();
|
|
69
|
-
// }
|
|
70
|
-
// return HiSecure.instance;
|
|
71
|
-
// }
|
|
72
|
-
|
|
73
|
-
// static resetInstance(): void {
|
|
74
|
-
// HiSecure.instance = null;
|
|
75
|
-
// }
|
|
76
|
-
|
|
77
|
-
// init(): void {
|
|
78
|
-
// if (this.initialized) {
|
|
79
|
-
// logger.warn(" HiSecure already initialized");
|
|
80
|
-
// return;
|
|
81
|
-
// }
|
|
82
|
-
|
|
83
|
-
// logger.info(` ${LIB_NAME} v${LIB_VERSION} initializing...`);
|
|
84
|
-
|
|
85
|
-
// this.setupAdapters();
|
|
86
|
-
// this.setupManagers();
|
|
87
|
-
// this.setupDynamicManagers();
|
|
88
|
-
|
|
89
|
-
// deepFreeze(this.config);
|
|
90
|
-
// // deep Freeze - for now we remove from manager it needs to manage the adapters
|
|
91
|
-
// // deepFreeze(this.hashManager);
|
|
92
|
-
// // deepFreeze(this.rateLimitManager);
|
|
93
|
-
// // deepFreeze(this.validatorManager);
|
|
94
|
-
// // deepFreeze(this.sanitizerManager);
|
|
95
|
-
// // deepFreeze(this.jsonManager);
|
|
96
|
-
// // deepFreeze(this.corsManager);
|
|
97
|
-
// // if (this.authManager) deepFreeze(this.authManager);
|
|
98
|
-
|
|
99
|
-
// this.initialized = true;
|
|
100
|
-
// logger.info("HiSecure initialized successfully");
|
|
101
|
-
// }
|
|
102
|
-
|
|
103
|
-
// isInitialized(): boolean {
|
|
104
|
-
// return this.initialized;
|
|
105
|
-
// }
|
|
106
|
-
|
|
107
|
-
// // FLUENT API METHODS (Route-level security)
|
|
108
|
-
|
|
109
|
-
// static auth(options?: { required?: boolean; roles?: string[] }) {
|
|
110
|
-
// const instance = this.getInstance();
|
|
111
|
-
// if (!instance.authManager) {
|
|
112
|
-
// throw new Error("Auth not enabled. Set auth.enabled=true in config.");
|
|
113
|
-
// }
|
|
114
|
-
// return instance.authManager.protect(options);
|
|
115
|
-
// }
|
|
116
|
-
|
|
117
|
-
// static validate(schema: ValidationSchema) {
|
|
118
|
-
// return this.getInstance().validatorManager.validate(schema);
|
|
119
|
-
// }
|
|
120
|
-
|
|
121
|
-
// static sanitize(options?: any) {
|
|
122
|
-
// return this.getInstance().sanitizerManager.middleware(options);
|
|
123
|
-
// }
|
|
124
|
-
|
|
125
|
-
// static rateLimit(preset: "strict" | "relaxed" | "api" | object) {
|
|
126
|
-
// const instance = this.getInstance();
|
|
127
|
-
|
|
128
|
-
// if (typeof preset === "string") {
|
|
129
|
-
// const presets: Record<string, { mode?: "strict" | "relaxed" | "api"; options?: any }> = {
|
|
130
|
-
// strict: { mode: "strict" },
|
|
131
|
-
// relaxed: { mode: "relaxed" },
|
|
132
|
-
// api: { mode: "api", options: { max: 100, windowMs: 60000 } }
|
|
133
|
-
// };
|
|
134
|
-
// return instance.rateLimitManager.middleware(presets[preset] || {});
|
|
135
|
-
// }
|
|
136
|
-
|
|
137
|
-
// return instance.rateLimitManager.middleware({ options: preset });
|
|
138
|
-
// }
|
|
139
|
-
|
|
140
|
-
// static cors(options?: any) {
|
|
141
|
-
// return this.getInstance().corsManager.middleware(options);
|
|
142
|
-
// }
|
|
143
|
-
|
|
144
|
-
// static json(options?: any) {
|
|
145
|
-
// const instance = this.getInstance();
|
|
146
|
-
// const chain = [];
|
|
147
|
-
// chain.push(instance.jsonManager.middleware(options));
|
|
148
|
-
// chain.push(instance.jsonManager.urlencoded());
|
|
149
|
-
// return chain;
|
|
150
|
-
// }
|
|
151
|
-
|
|
152
|
-
// // UTILITY METHODS - For direct use
|
|
153
|
-
|
|
154
|
-
// static async hash(password: string): Promise<string> {
|
|
155
|
-
// const instance = this.getInstance();
|
|
156
|
-
// const result = await instance.hashManager.hash(password, { allowFallback: true });
|
|
157
|
-
// return result.hash;
|
|
158
|
-
// }
|
|
159
|
-
|
|
160
|
-
// static async verify(password: string, hash: string): Promise<boolean> {
|
|
161
|
-
// return this.getInstance().hashManager.verify(password, hash);
|
|
162
|
-
// }
|
|
163
|
-
|
|
164
|
-
// static jwt = {
|
|
165
|
-
// sign: (payload: object, options?: any) => {
|
|
166
|
-
// const instance = HiSecure.getInstance();
|
|
167
|
-
// if (!instance.authManager) {
|
|
168
|
-
// throw new Error("Auth not enabled");
|
|
169
|
-
// }
|
|
170
|
-
// return instance.authManager.sign(payload, options);
|
|
171
|
-
// },
|
|
172
|
-
|
|
173
|
-
// verify: (token: string) => {
|
|
174
|
-
// const instance = HiSecure.getInstance();
|
|
175
|
-
// if (!instance.authManager) {
|
|
176
|
-
// throw new Error("Auth not enabled");
|
|
177
|
-
// }
|
|
178
|
-
// return instance.authManager.verify(token);
|
|
179
|
-
// },
|
|
180
|
-
|
|
181
|
-
// google: {
|
|
182
|
-
// verifyIdToken: (idToken: string) => {
|
|
183
|
-
// const instance = HiSecure.getInstance();
|
|
184
|
-
// if (!instance.authManager) {
|
|
185
|
-
// throw new Error("Auth not enabled");
|
|
186
|
-
// }
|
|
187
|
-
// return instance.authManager.verifyGoogleIdToken(idToken);
|
|
188
|
-
// }
|
|
189
|
-
// }
|
|
190
|
-
// };
|
|
191
|
-
|
|
192
|
-
// // GLOBAL MIDDLEWARE (app.use())
|
|
193
|
-
|
|
194
|
-
// static middleware(options?: SecureOptions | "api" | "strict" | "public") {
|
|
195
|
-
// const instance = this.getInstance();
|
|
196
|
-
|
|
197
|
-
// // Handle preset strings
|
|
198
|
-
// if (typeof options === "string") {
|
|
199
|
-
// const presets: Record<string, SecureOptions> = {
|
|
200
|
-
// api: { cors: true, rateLimit: "relaxed" as any, sanitize: true },
|
|
201
|
-
// strict: { cors: true, rateLimit: "strict" as any, sanitize: true, auth: true },
|
|
202
|
-
// public: { cors: true, rateLimit: true as any, sanitize: false }
|
|
203
|
-
// };
|
|
204
|
-
// const presetOptions = presets[options];
|
|
205
|
-
// if (presetOptions) {
|
|
206
|
-
// return instance.createMiddlewareChain(presetOptions);
|
|
207
|
-
// }
|
|
208
|
-
// return instance.createMiddlewareChain({});
|
|
209
|
-
// }
|
|
210
|
-
|
|
211
|
-
// return instance.createMiddlewareChain(options || {});
|
|
212
|
-
// }
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
// // Internal Methods
|
|
216
|
-
|
|
217
|
-
// private setupAdapters(): void {
|
|
218
|
-
// logger.info(" Setting up adapters...");
|
|
219
|
-
|
|
220
|
-
// // Hashing
|
|
221
|
-
// this.hashingPrimary = this.config.hashing.primary === "argon2"
|
|
222
|
-
// ? new ArgonAdapter()
|
|
223
|
-
// : new BcryptAdapter(this.config.hashing.saltRounds);
|
|
224
|
-
|
|
225
|
-
// this.hashingFallback = this.config.hashing.fallback === "bcrypt"
|
|
226
|
-
// ? new BcryptAdapter(this.config.hashing.saltRounds)
|
|
227
|
-
// : null;
|
|
228
|
-
|
|
229
|
-
// // Rate limiting
|
|
230
|
-
// this.rateLimiterPrimary = this.config.rateLimiter.useAdaptiveMode
|
|
231
|
-
// ? new RLFlexibleAdapter()
|
|
232
|
-
// : new ExpressRLAdapter();
|
|
233
|
-
// this.rateLimiterFallback = new ExpressRLAdapter();
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
// // // Validation - we handle this in d/f way for now
|
|
239
|
-
// // this.validatorPrimary = this.config.validation.mode === "zod"
|
|
240
|
-
// // ? new ZodAdapter()
|
|
241
|
-
// // : new ExpressValidatorAdapter();
|
|
242
|
-
// // this.validatorFallback = this.config.validation.fallback === "express-validator"
|
|
243
|
-
// // ? new ExpressValidatorAdapter()
|
|
244
|
-
// // : null;
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
// // Sanitization
|
|
248
|
-
// this.sanitizerPrimary = new SanitizeHtmlAdapter(this.config.sanitizer);
|
|
249
|
-
// this.sanitizerFallback = new XSSAdapter(this.config.sanitizer);
|
|
250
|
-
|
|
251
|
-
// logger.info("Adapters ready");
|
|
252
|
-
// }
|
|
253
|
-
|
|
254
|
-
// private setupManagers(): void {
|
|
255
|
-
// this.hashManager = new HashManager(
|
|
256
|
-
// this.config.hashing,
|
|
257
|
-
// this.hashingPrimary,
|
|
258
|
-
// this.hashingFallback
|
|
259
|
-
// );
|
|
260
|
-
|
|
261
|
-
// this.rateLimitManager = new RateLimitManager(
|
|
262
|
-
// this.config.rateLimiter,
|
|
263
|
-
// this.rateLimiterPrimary,
|
|
264
|
-
// this.rateLimiterFallback
|
|
265
|
-
// );
|
|
266
|
-
|
|
267
|
-
// this.validatorManager = new ValidatorManager(
|
|
268
|
-
// // this.config.validation,
|
|
269
|
-
// // this.validatorPrimary,
|
|
270
|
-
// // this.validatorFallback
|
|
271
|
-
// new ZodAdapter(),
|
|
272
|
-
// new ExpressValidatorAdapter()
|
|
273
|
-
// );
|
|
274
|
-
|
|
275
|
-
// this.sanitizerManager = new SanitizerManager(
|
|
276
|
-
// this.sanitizerPrimary,
|
|
277
|
-
// this.sanitizerFallback
|
|
278
|
-
// );
|
|
279
|
-
// }
|
|
280
|
-
|
|
281
|
-
// private setupDynamicManagers(): void {
|
|
282
|
-
// this.jsonManager = new JsonManager();
|
|
283
|
-
// this.corsManager = new CorsManager();
|
|
284
|
-
|
|
285
|
-
// // Auth manager (only if enabled)
|
|
286
|
-
// if (this.config.auth.enabled) {
|
|
287
|
-
// const jwtSecret = process.env.JWT_SECRET || this.config.auth.jwtSecret;
|
|
288
|
-
// if (!jwtSecret) {
|
|
289
|
-
// throw new Error("JWT_SECRET environment variable or jwtSecret in config is required when auth.enabled=true");
|
|
290
|
-
// }
|
|
291
|
-
|
|
292
|
-
// this.authManager = new AuthManager({
|
|
293
|
-
// jwtSecret,
|
|
294
|
-
// jwtExpiresIn: this.config.auth.jwtExpiresIn,
|
|
295
|
-
// googleClientId: process.env.GOOGLE_CLIENT_ID || this.config.auth.googleClientId
|
|
296
|
-
// });
|
|
297
|
-
// }
|
|
298
|
-
// }
|
|
299
|
-
|
|
300
|
-
// private createMiddlewareChain(options: SecureOptions): any[] {
|
|
301
|
-
// const chain: any[] = [];
|
|
302
|
-
|
|
303
|
-
// // JSON parsing
|
|
304
|
-
// chain.push(this.jsonManager.middleware(this.config.json));
|
|
305
|
-
// chain.push(this.jsonManager.urlencoded(this.config.urlencoded));
|
|
306
|
-
|
|
307
|
-
// // Security headers
|
|
308
|
-
// if (this.config.enableHelmet) chain.push(helmet());
|
|
309
|
-
// if (this.config.enableHPP) chain.push(hpp());
|
|
310
|
-
|
|
311
|
-
// // Compression (check if compression config exists)
|
|
312
|
-
// if (this.config.enableCompression && this.config.compression) {
|
|
313
|
-
// chain.push(compression(this.config.compression));
|
|
314
|
-
// } else if (this.config.enableCompression) {
|
|
315
|
-
// chain.push(compression()); // Use defaults
|
|
316
|
-
// }
|
|
317
|
-
|
|
318
|
-
// // CORS
|
|
319
|
-
// if (this.config.enableCORS || options.cors) {
|
|
320
|
-
// const corsOptions = options.cors === true ? this.config.cors :
|
|
321
|
-
// (typeof options.cors === 'object' ? options.cors : this.config.cors);
|
|
322
|
-
// chain.push(this.corsManager.middleware(corsOptions));
|
|
323
|
-
// }
|
|
324
|
-
|
|
325
|
-
// // Sanitization
|
|
326
|
-
// if (this.config.enableSanitizer || options.sanitize) {
|
|
327
|
-
// const sanitizeOptions = options.sanitize === true ? undefined :
|
|
328
|
-
// (typeof options.sanitize === 'object' ? options.sanitize : undefined);
|
|
329
|
-
// chain.push(this.sanitizerManager.middleware(sanitizeOptions));
|
|
330
|
-
// }
|
|
331
|
-
|
|
332
|
-
// // Rate limiting
|
|
333
|
-
// if (this.config.enableRateLimiter || options.rateLimit) {
|
|
334
|
-
// const rateLimitOpts = typeof options.rateLimit === 'object' ?
|
|
335
|
-
// { options: options.rateLimit } : {};
|
|
336
|
-
// chain.push(this.rateLimitManager.middleware(rateLimitOpts));
|
|
337
|
-
// }
|
|
338
|
-
|
|
339
|
-
// // Authentication
|
|
340
|
-
// if (options.auth && this.authManager) {
|
|
341
|
-
// const authOpts = options.auth === true ? undefined :
|
|
342
|
-
// (typeof options.auth === 'object' ? options.auth : undefined);
|
|
343
|
-
// chain.push(this.authManager.protect(authOpts));
|
|
344
|
-
// }
|
|
345
|
-
|
|
346
|
-
// // Error handler - at last usage
|
|
347
|
-
// chain.push(errorHandler);
|
|
348
|
-
|
|
349
|
-
// return chain;
|
|
350
|
-
// }
|
|
351
|
-
// }
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
1
|
import { HiSecureConfig } from "./types/HiSecureConfig.js";
|
|
361
2
|
import { defaultConfig } from "./config.js";
|
|
362
3
|
import { LIB_NAME, LIB_VERSION } from "./constants.js";
|
|
@@ -418,9 +59,7 @@ export class HiSecure {
|
|
|
418
59
|
this.config = deepMerge(defaultConfig, userConfig);
|
|
419
60
|
}
|
|
420
61
|
|
|
421
|
-
// =========================
|
|
422
62
|
// Singleton & Init
|
|
423
|
-
// =========================
|
|
424
63
|
|
|
425
64
|
static getInstance(config?: Partial<HiSecureConfig>): HiSecure {
|
|
426
65
|
if (!HiSecure.instance) {
|
|
@@ -463,9 +102,8 @@ export class HiSecure {
|
|
|
463
102
|
});
|
|
464
103
|
}
|
|
465
104
|
|
|
466
|
-
// =========================
|
|
467
105
|
// Public Fluent APIs
|
|
468
|
-
|
|
106
|
+
|
|
469
107
|
|
|
470
108
|
static auth(options?: { required?: boolean; roles?: string[] }) {
|
|
471
109
|
const instance = this.getInstance();
|
|
@@ -515,9 +153,7 @@ export class HiSecure {
|
|
|
515
153
|
];
|
|
516
154
|
}
|
|
517
155
|
|
|
518
|
-
// =========================
|
|
519
156
|
// Utilities
|
|
520
|
-
// =========================
|
|
521
157
|
|
|
522
158
|
static async hash(value: string): Promise<string> {
|
|
523
159
|
const instance = this.getInstance();
|
|
@@ -542,9 +178,7 @@ export class HiSecure {
|
|
|
542
178
|
}
|
|
543
179
|
};
|
|
544
180
|
|
|
545
|
-
// =========================
|
|
546
181
|
// Global Middleware
|
|
547
|
-
// =========================
|
|
548
182
|
|
|
549
183
|
static middleware(options?: SecureOptions | "api" | "strict" | "public") {
|
|
550
184
|
const instance = this.getInstance();
|
|
@@ -567,9 +201,7 @@ export class HiSecure {
|
|
|
567
201
|
return instance.createMiddlewareChain(options || {});
|
|
568
202
|
}
|
|
569
203
|
|
|
570
|
-
// =========================
|
|
571
204
|
// Internal Setup
|
|
572
|
-
// =========================
|
|
573
205
|
|
|
574
206
|
private setupAdapters() {
|
|
575
207
|
logger.info("Adapters setup started", {
|
package/src/logging/index.ts
CHANGED
|
@@ -1,28 +1,3 @@
|
|
|
1
|
-
// // import morgan from "morgan";
|
|
2
|
-
|
|
3
|
-
// // export const requestLogger = morgan("combined");
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
// import morgan from "morgan";
|
|
9
|
-
// import { logger } from "./winstonSetup";
|
|
10
|
-
|
|
11
|
-
// export const requestLogger = morgan(
|
|
12
|
-
// ":method :url :status :response-time ms",
|
|
13
|
-
// {
|
|
14
|
-
// stream: {
|
|
15
|
-
// write: (message) => {
|
|
16
|
-
// logger.http(message.trim());
|
|
17
|
-
// }
|
|
18
|
-
// }
|
|
19
|
-
// }
|
|
20
|
-
// );
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
1
|
import morgan from "morgan";
|
|
27
2
|
import { logger } from "./winstonSetup";
|
|
28
3
|
|