hi-secure 1.0.0

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.
Files changed (210) hide show
  1. package/dist/adapters/ArgonAdapter.d.ts +8 -0
  2. package/dist/adapters/ArgonAdapter.d.ts.map +1 -0
  3. package/dist/adapters/ArgonAdapter.js +45 -0
  4. package/dist/adapters/ArgonAdapter.js.map +1 -0
  5. package/dist/adapters/BcryptAdapter.d.ts +7 -0
  6. package/dist/adapters/BcryptAdapter.d.ts.map +1 -0
  7. package/dist/adapters/BcryptAdapter.js +48 -0
  8. package/dist/adapters/BcryptAdapter.js.map +1 -0
  9. package/dist/adapters/DomPurifyAdapter.d.ts +13 -0
  10. package/dist/adapters/DomPurifyAdapter.d.ts.map +1 -0
  11. package/dist/adapters/DomPurifyAdapter.js +61 -0
  12. package/dist/adapters/DomPurifyAdapter.js.map +1 -0
  13. package/dist/adapters/ExpressRLAdapter.d.ts +13 -0
  14. package/dist/adapters/ExpressRLAdapter.d.ts.map +1 -0
  15. package/dist/adapters/ExpressRLAdapter.js +68 -0
  16. package/dist/adapters/ExpressRLAdapter.js.map +1 -0
  17. package/dist/adapters/ExpressValidatorAdapter.d.ts +6 -0
  18. package/dist/adapters/ExpressValidatorAdapter.d.ts.map +1 -0
  19. package/dist/adapters/ExpressValidatorAdapter.js +78 -0
  20. package/dist/adapters/ExpressValidatorAdapter.js.map +1 -0
  21. package/dist/adapters/GoggleAdapter.d.ts +15 -0
  22. package/dist/adapters/GoggleAdapter.d.ts.map +1 -0
  23. package/dist/adapters/GoggleAdapter.js +91 -0
  24. package/dist/adapters/GoggleAdapter.js.map +1 -0
  25. package/dist/adapters/GoogleAdapter.d.ts +15 -0
  26. package/dist/adapters/GoogleAdapter.d.ts.map +1 -0
  27. package/dist/adapters/GoogleAdapter.js +159 -0
  28. package/dist/adapters/GoogleAdapter.js.map +1 -0
  29. package/dist/adapters/JWTAdapter.d.ts +28 -0
  30. package/dist/adapters/JWTAdapter.d.ts.map +1 -0
  31. package/dist/adapters/JWTAdapter.js +276 -0
  32. package/dist/adapters/JWTAdapter.js.map +1 -0
  33. package/dist/adapters/RLFlexibleAdapter.d.ts +11 -0
  34. package/dist/adapters/RLFlexibleAdapter.d.ts.map +1 -0
  35. package/dist/adapters/RLFlexibleAdapter.js +115 -0
  36. package/dist/adapters/RLFlexibleAdapter.js.map +1 -0
  37. package/dist/adapters/SanitizeHtmlAdapter.d.ts +12 -0
  38. package/dist/adapters/SanitizeHtmlAdapter.d.ts.map +1 -0
  39. package/dist/adapters/SanitizeHtmlAdapter.js +141 -0
  40. package/dist/adapters/SanitizeHtmlAdapter.js.map +1 -0
  41. package/dist/adapters/XSSAdapter.d.ts +33 -0
  42. package/dist/adapters/XSSAdapter.d.ts.map +1 -0
  43. package/dist/adapters/XSSAdapter.js +127 -0
  44. package/dist/adapters/XSSAdapter.js.map +1 -0
  45. package/dist/adapters/ZodAdapter.d.ts +7 -0
  46. package/dist/adapters/ZodAdapter.d.ts.map +1 -0
  47. package/dist/adapters/ZodAdapter.js +39 -0
  48. package/dist/adapters/ZodAdapter.js.map +1 -0
  49. package/dist/core/HiSecure.d.ts +62 -0
  50. package/dist/core/HiSecure.d.ts.map +1 -0
  51. package/dist/core/HiSecure.js +273 -0
  52. package/dist/core/HiSecure.js.map +1 -0
  53. package/dist/core/config.d.ts +3 -0
  54. package/dist/core/config.d.ts.map +1 -0
  55. package/dist/core/config.js +53 -0
  56. package/dist/core/config.js.map +1 -0
  57. package/dist/core/constants.d.ts +37 -0
  58. package/dist/core/constants.d.ts.map +1 -0
  59. package/dist/core/constants.js +67 -0
  60. package/dist/core/constants.js.map +1 -0
  61. package/dist/core/errors/AdapterError.d.ts +5 -0
  62. package/dist/core/errors/AdapterError.d.ts.map +1 -0
  63. package/dist/core/errors/AdapterError.js +15 -0
  64. package/dist/core/errors/AdapterError.js.map +1 -0
  65. package/dist/core/errors/HttpErrror.d.ts +17 -0
  66. package/dist/core/errors/HttpErrror.d.ts.map +1 -0
  67. package/dist/core/errors/HttpErrror.js +36 -0
  68. package/dist/core/errors/HttpErrror.js.map +1 -0
  69. package/dist/core/errors/SanitizerError.d.ts +5 -0
  70. package/dist/core/errors/SanitizerError.d.ts.map +1 -0
  71. package/dist/core/errors/SanitizerError.js +14 -0
  72. package/dist/core/errors/SanitizerError.js.map +1 -0
  73. package/dist/core/errors/SecurityError.d.ts +5 -0
  74. package/dist/core/errors/SecurityError.d.ts.map +1 -0
  75. package/dist/core/errors/SecurityError.js +14 -0
  76. package/dist/core/errors/SecurityError.js.map +1 -0
  77. package/dist/core/errors/ValidationError.d.ts +5 -0
  78. package/dist/core/errors/ValidationError.d.ts.map +1 -0
  79. package/dist/core/errors/ValidationError.js +14 -0
  80. package/dist/core/errors/ValidationError.js.map +1 -0
  81. package/dist/core/types/HiSecureConfig.d.ts +47 -0
  82. package/dist/core/types/HiSecureConfig.d.ts.map +1 -0
  83. package/dist/core/types/HiSecureConfig.js +3 -0
  84. package/dist/core/types/HiSecureConfig.js.map +1 -0
  85. package/dist/core/types/SecureOptions.d.ts +30 -0
  86. package/dist/core/types/SecureOptions.d.ts.map +1 -0
  87. package/dist/core/types/SecureOptions.js +4 -0
  88. package/dist/core/types/SecureOptions.js.map +1 -0
  89. package/dist/core/useSecure.d.ts +10 -0
  90. package/dist/core/useSecure.d.ts.map +1 -0
  91. package/dist/core/useSecure.js +85 -0
  92. package/dist/core/useSecure.js.map +1 -0
  93. package/dist/examples/e1.d.ts +1 -0
  94. package/dist/examples/e1.d.ts.map +1 -0
  95. package/dist/examples/e1.js +3 -0
  96. package/dist/examples/e1.js.map +1 -0
  97. package/dist/index.d.ts +9 -0
  98. package/dist/index.d.ts.map +1 -0
  99. package/dist/index.js +15 -0
  100. package/dist/index.js.map +1 -0
  101. package/dist/logging/index.d.ts +3 -0
  102. package/dist/logging/index.d.ts.map +1 -0
  103. package/dist/logging/index.js +19 -0
  104. package/dist/logging/index.js.map +1 -0
  105. package/dist/logging/morganSetup.d.ts +2 -0
  106. package/dist/logging/morganSetup.d.ts.map +1 -0
  107. package/dist/logging/morganSetup.js +9 -0
  108. package/dist/logging/morganSetup.js.map +1 -0
  109. package/dist/logging/winstonSetup.d.ts +6 -0
  110. package/dist/logging/winstonSetup.d.ts.map +1 -0
  111. package/dist/logging/winstonSetup.js +22 -0
  112. package/dist/logging/winstonSetup.js.map +1 -0
  113. package/dist/managers/AuthManager.d.ts +23 -0
  114. package/dist/managers/AuthManager.d.ts.map +1 -0
  115. package/dist/managers/AuthManager.js +190 -0
  116. package/dist/managers/AuthManager.js.map +1 -0
  117. package/dist/managers/CorsManager.d.ts +9 -0
  118. package/dist/managers/CorsManager.d.ts.map +1 -0
  119. package/dist/managers/CorsManager.js +55 -0
  120. package/dist/managers/CorsManager.js.map +1 -0
  121. package/dist/managers/HashManager.d.ts +22 -0
  122. package/dist/managers/HashManager.d.ts.map +1 -0
  123. package/dist/managers/HashManager.js +319 -0
  124. package/dist/managers/HashManager.js.map +1 -0
  125. package/dist/managers/JsonManager.d.ts +6 -0
  126. package/dist/managers/JsonManager.d.ts.map +1 -0
  127. package/dist/managers/JsonManager.js +142 -0
  128. package/dist/managers/JsonManager.js.map +1 -0
  129. package/dist/managers/RateLimitManager.d.ts +16 -0
  130. package/dist/managers/RateLimitManager.d.ts.map +1 -0
  131. package/dist/managers/RateLimitManager.js +108 -0
  132. package/dist/managers/RateLimitManager.js.map +1 -0
  133. package/dist/managers/SanitizerManager.d.ts +18 -0
  134. package/dist/managers/SanitizerManager.d.ts.map +1 -0
  135. package/dist/managers/SanitizerManager.js +296 -0
  136. package/dist/managers/SanitizerManager.js.map +1 -0
  137. package/dist/managers/ValidatorManager.d.ts +13 -0
  138. package/dist/managers/ValidatorManager.d.ts.map +1 -0
  139. package/dist/managers/ValidatorManager.js +218 -0
  140. package/dist/managers/ValidatorManager.js.map +1 -0
  141. package/dist/middlewares/errorHandler.d.ts +3 -0
  142. package/dist/middlewares/errorHandler.d.ts.map +1 -0
  143. package/dist/middlewares/errorHandler.js +94 -0
  144. package/dist/middlewares/errorHandler.js.map +1 -0
  145. package/dist/middlewares/index.d.ts +3 -0
  146. package/dist/middlewares/index.d.ts.map +1 -0
  147. package/dist/middlewares/index.js +19 -0
  148. package/dist/middlewares/index.js.map +1 -0
  149. package/dist/middlewares/requestLogger.d.ts +2 -0
  150. package/dist/middlewares/requestLogger.d.ts.map +1 -0
  151. package/dist/middlewares/requestLogger.js +8 -0
  152. package/dist/middlewares/requestLogger.js.map +1 -0
  153. package/dist/test/t1.d.ts +1 -0
  154. package/dist/test/t1.d.ts.map +1 -0
  155. package/dist/test/t1.js +3 -0
  156. package/dist/test/t1.js.map +1 -0
  157. package/dist/utils/deepFreeze.d.ts +2 -0
  158. package/dist/utils/deepFreeze.d.ts.map +1 -0
  159. package/dist/utils/deepFreeze.js +69 -0
  160. package/dist/utils/deepFreeze.js.map +1 -0
  161. package/dist/utils/deepMerge.d.ts +5 -0
  162. package/dist/utils/deepMerge.d.ts.map +1 -0
  163. package/dist/utils/deepMerge.js +68 -0
  164. package/dist/utils/deepMerge.js.map +1 -0
  165. package/dist/utils/normalizeOptions.d.ts +38 -0
  166. package/dist/utils/normalizeOptions.d.ts.map +1 -0
  167. package/dist/utils/normalizeOptions.js +119 -0
  168. package/dist/utils/normalizeOptions.js.map +1 -0
  169. package/package.json +50 -0
  170. package/src/adapters/ArgonAdapter.ts +41 -0
  171. package/src/adapters/BcryptAdapter.ts +49 -0
  172. package/src/adapters/ExpressRLAdapter.ts +84 -0
  173. package/src/adapters/ExpressValidatorAdapter.ts +99 -0
  174. package/src/adapters/GoogleAdapter.ts +206 -0
  175. package/src/adapters/JWTAdapter.ts +346 -0
  176. package/src/adapters/RLFlexibleAdapter.ts +139 -0
  177. package/src/adapters/SanitizeHtmlAdapter.ts +162 -0
  178. package/src/adapters/XSSAdapter.ts +153 -0
  179. package/src/adapters/ZodAdapter.ts +91 -0
  180. package/src/core/HiSecure.ts +955 -0
  181. package/src/core/config.ts +156 -0
  182. package/src/core/constants.ts +73 -0
  183. package/src/core/errors/AdapterError.ts +14 -0
  184. package/src/core/errors/HttpErrror.ts +46 -0
  185. package/src/core/errors/SanitizerError.ts +13 -0
  186. package/src/core/errors/SecurityError.ts +13 -0
  187. package/src/core/errors/ValidationError.ts +13 -0
  188. package/src/core/types/HiSecureConfig.ts +62 -0
  189. package/src/core/types/SecureOptions.ts +61 -0
  190. package/src/core/useSecure.ts +111 -0
  191. package/src/examples/e1.ts +1 -0
  192. package/src/index.ts +17 -0
  193. package/src/logging/index.ts +2 -0
  194. package/src/logging/morganSetup.ts +3 -0
  195. package/src/logging/winstonSetup.ts +17 -0
  196. package/src/managers/AuthManager.ts +237 -0
  197. package/src/managers/CorsManager.ts +58 -0
  198. package/src/managers/HashManager.ts +390 -0
  199. package/src/managers/JsonManager.ts +149 -0
  200. package/src/managers/RateLimitManager.ts +368 -0
  201. package/src/managers/SanitizerManager.ts +359 -0
  202. package/src/managers/ValidatorManager.ts +269 -0
  203. package/src/middlewares/errorHandler.ts +265 -0
  204. package/src/middlewares/index.ts +2 -0
  205. package/src/middlewares/requestLogger.ts +5 -0
  206. package/src/test/t1.ts +1 -0
  207. package/src/utils/deepFreeze.ts +76 -0
  208. package/src/utils/deepMerge.ts +87 -0
  209. package/src/utils/normalizeOptions.ts +265 -0
  210. package/tsconfig.json +30 -0
@@ -0,0 +1,237 @@
1
+ // import { JWTAdapter } from "../adapters/JWTAdapter.js";
2
+ // import { GoogleAdapter } from "../adapters/GoggleAdapter.js";
3
+ // import { AdapterError } from "../core/errors/AdapterError.js";
4
+ // import { HttpError } from "../core/errors/HttpErrror.js";
5
+ // import { Request, Response, NextFunction } from "express";
6
+ // import { logError, logWarn, logInfo } from "../logging";
7
+
8
+ // export interface AuthOptions {
9
+ // jwtSecret: string;
10
+ // jwtExpiresIn?: string | number | undefined;
11
+ // googleClientId?: string | undefined;
12
+ // }
13
+
14
+ // export class AuthManager {
15
+ // private jwtAdapter: JWTAdapter;
16
+ // private googleAdapter?: GoogleAdapter;
17
+
18
+ // constructor(opts: AuthOptions) {
19
+ // if (!opts.jwtSecret)
20
+ // throw new AdapterError("jwtSecret required in AuthOptions");
21
+
22
+ // logInfo("AuthManager initialized");
23
+
24
+ // this.jwtAdapter = new JWTAdapter({
25
+ // secret: opts.jwtSecret,
26
+ // expiresIn: opts.jwtExpiresIn ?? undefined,
27
+ // });
28
+
29
+ // if (opts.googleClientId) {
30
+ // this.googleAdapter = new GoogleAdapter(opts.googleClientId);
31
+ // logInfo("GoogleAdapter enabled");
32
+ // }
33
+ // }
34
+
35
+ // sign(payload: object, options?: { expiresIn?: string | number }) {
36
+ // logInfo("JWT Sign called");
37
+ // return this.jwtAdapter.sign(payload, options);
38
+ // }
39
+
40
+ // verify(token: string) {
41
+ // logInfo("JWT Verify called");
42
+ // return this.jwtAdapter.verify(token);
43
+ // }
44
+
45
+ // async verifyGoogleIdToken(idToken: string) {
46
+ // if (!this.googleAdapter)
47
+ // throw new AdapterError("GoogleAdapter not configured.");
48
+
49
+ // logInfo("Google ID Token verify called");
50
+
51
+ // try {
52
+ // return await this.googleAdapter.verifyIdToken(idToken);
53
+ // } catch (err: any) {
54
+ // logError("Google ID Token verification failed", { error: err?.message });
55
+ // throw HttpError.Unauthorized("Invalid Google ID token");
56
+ // }
57
+ // }
58
+
59
+ // protect(options?: { required?: boolean }) {
60
+ // const required = options?.required ?? true;
61
+
62
+ // return (req: Request, res: Response, next: NextFunction) => {
63
+ // const header = req.headers["authorization"] || req.headers["Authorization"];
64
+
65
+ // if (!header) {
66
+ // if (required) {
67
+ // logWarn("Missing Authorization header", {
68
+ // path: req.path,
69
+ // method: req.method
70
+ // });
71
+ // return next(HttpError.Unauthorized("Missing Authorization header"));
72
+ // }
73
+ // return next();
74
+ // }
75
+
76
+ // const [type, token] = String(header).split(" ");
77
+
78
+ // if (type !== "Bearer" || !token) {
79
+ // logWarn("Invalid Authorization header", {
80
+ // path: req.path,
81
+ // method: req.method
82
+ // });
83
+ // return next(HttpError.Unauthorized("Invalid Authorization header"));
84
+ // }
85
+
86
+ // try {
87
+ // const decoded = this.verify(token);
88
+ // (req as any).auth = decoded;
89
+ // return next();
90
+ // } catch (err: any) {
91
+ // logError("JWT verify failed", {
92
+ // error: err?.message,
93
+ // path: req.path,
94
+ // method: req.method
95
+ // });
96
+ // return next(HttpError.Unauthorized("Invalid or expired token"));
97
+ // }
98
+ // };
99
+ // }
100
+ // }
101
+
102
+
103
+
104
+ // src/managers/AuthManager.ts - FIXED
105
+ import { JWTAdapter } from "../adapters/JWTAdapter.js";
106
+ import { GoogleAdapter } from "../adapters/GoogleAdapter.js";
107
+ import { AdapterError } from "../core/errors/AdapterError.js";
108
+ import { HttpError } from "../core/errors/HttpErrror.js";
109
+ import { Request, Response, NextFunction } from "express";
110
+ import { logError, logWarn, logInfo } from "../logging";
111
+
112
+ export interface AuthOptions {
113
+ jwtSecret: string;
114
+ jwtExpiresIn?: string | number;
115
+ googleClientId?: string;
116
+ }
117
+
118
+ export interface ProtectOptions {
119
+ required?: boolean;
120
+ roles?: string[];
121
+ }
122
+
123
+ export class AuthManager {
124
+ private jwtAdapter: JWTAdapter;
125
+ private googleAdapter?: GoogleAdapter;
126
+
127
+ constructor(opts: AuthOptions) {
128
+ if (!opts.jwtSecret) {
129
+ throw new AdapterError("jwtSecret required in AuthOptions");
130
+ }
131
+
132
+ if (opts.jwtSecret.length < 32) {
133
+ logWarn("⚠ JWT secret is less than 32 characters - consider using a stronger secret");
134
+ }
135
+
136
+ logInfo("AuthManager initialized");
137
+
138
+ this.jwtAdapter = new JWTAdapter({
139
+ secret: opts.jwtSecret,
140
+ expiresIn: opts.jwtExpiresIn ?? "1d",
141
+ });
142
+
143
+ if (opts.googleClientId) {
144
+ this.googleAdapter = new GoogleAdapter(opts.googleClientId);
145
+ logInfo("GoogleAdapter enabled");
146
+ }
147
+ }
148
+
149
+ sign(payload: object, options?: { expiresIn?: string | number, jti?: string }) {
150
+ logInfo("JWT Sign called");
151
+ return this.jwtAdapter.sign(payload, options);
152
+ }
153
+
154
+ verify(token: string) {
155
+ logInfo("JWT Verify called");
156
+ return this.jwtAdapter.verify(token);
157
+ }
158
+
159
+ async verifyGoogleIdToken(idToken: string) {
160
+ if (!this.googleAdapter) {
161
+ throw new AdapterError("GoogleAdapter not configured.");
162
+ }
163
+
164
+ logInfo("Google ID Token verify called");
165
+
166
+ try {
167
+ return await this.googleAdapter.verifyIdToken(idToken);
168
+ } catch (err: any) {
169
+ logError("Google ID Token verification failed", { error: err?.message });
170
+ throw HttpError.Unauthorized("Invalid Google ID token");
171
+ }
172
+ }
173
+
174
+ protect(options?: ProtectOptions) {
175
+ const required = options?.required ?? true;
176
+ const roles = options?.roles;
177
+
178
+ return (req: Request, res: Response, next: NextFunction) => {
179
+ const header = req.headers["authorization"];
180
+
181
+ // If auth is not required, skip authentication
182
+ if (!required && !header) {
183
+ return next();
184
+ }
185
+
186
+ // If auth is required but no header
187
+ if (!header) {
188
+ logWarn("Missing Authorization header", {
189
+ path: req.path,
190
+ method: req.method
191
+ });
192
+ return next(HttpError.Unauthorized("Missing Authorization header"));
193
+ }
194
+
195
+ // Parse Bearer token
196
+ const [type, token] = String(header).split(" ");
197
+ if (type !== "Bearer" || !token) {
198
+ logWarn("Invalid Authorization header", {
199
+ path: req.path,
200
+ method: req.method
201
+ });
202
+ return next(HttpError.Unauthorized("Invalid Authorization header"));
203
+ }
204
+
205
+ try {
206
+ // Verify JWT
207
+ const decoded = this.verify(token);
208
+
209
+ // Attach to request
210
+ (req as any).auth = decoded;
211
+ (req as any).user = decoded; // Common pattern
212
+
213
+ // Role-based authorization
214
+ if (roles && roles.length > 0) {
215
+ const userRole = (decoded as any).role || (decoded as any).roles?.[0];
216
+ if (!userRole || !roles.includes(userRole)) {
217
+ logWarn("Insufficient permissions", {
218
+ path: req.path,
219
+ requiredRoles: roles,
220
+ userRole
221
+ });
222
+ return next(HttpError.Forbidden("Insufficient permissions"));
223
+ }
224
+ }
225
+
226
+ return next();
227
+ } catch (err: any) {
228
+ logError("JWT verify failed", {
229
+ error: err?.message,
230
+ path: req.path,
231
+ method: req.method
232
+ });
233
+ return next(HttpError.Unauthorized("Invalid or expired token"));
234
+ }
235
+ };
236
+ }
237
+ }
@@ -0,0 +1,58 @@
1
+ // import cors from "cors";
2
+ // import { logger } from "../logging";
3
+ // import { AdapterError } from "../core/errors/AdapterError.js";
4
+
5
+ // export class CorsManager {
6
+
7
+ // middleware(options?: any) {
8
+ // try {
9
+ // // options = undefined → use default CORS
10
+ // return options ? cors(options) : cors();
11
+
12
+ // } catch (err: any) {
13
+ // logger.error("❌ CORS Manager: failed to create CORS middleware", {
14
+ // error: err?.message || err,
15
+ // options
16
+ // });
17
+ // throw new AdapterError("CORS middleware initialization failed.");
18
+ // }
19
+ // }
20
+ // }
21
+
22
+
23
+
24
+ // src/managers/CorsManager.ts - IMPROVED
25
+ import cors from "cors";
26
+ import { logger } from "../logging";
27
+ import { AdapterError } from "../core/errors/AdapterError.js";
28
+
29
+ export class CorsManager {
30
+
31
+ middleware(options?: any) {
32
+ try {
33
+ const defaultOptions = {
34
+ origin: '*',
35
+ methods: ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'OPTIONS'],
36
+ allowedHeaders: ['Content-Type', 'Authorization'],
37
+ credentials: false,
38
+ maxAge: 86400 // 24 hours
39
+ };
40
+
41
+ const finalOptions = options ? { ...defaultOptions, ...options } : defaultOptions;
42
+
43
+ logger.debug("🔧 CORS configured", {
44
+ origin: finalOptions.origin,
45
+ methods: finalOptions.methods
46
+ });
47
+
48
+ return cors(finalOptions);
49
+
50
+ } catch (err: any) {
51
+ logger.error("❌ CORS Manager: failed to create CORS middleware", {
52
+ error: err?.message || err,
53
+ options
54
+ });
55
+ throw new AdapterError("CORS middleware initialization failed.");
56
+ }
57
+ }
58
+ }
@@ -0,0 +1,390 @@
1
+ // // // import { AdapterError } from "../core/errors/AdapterError";
2
+ // // // import { HiSecureConfig } from "../core/config";
3
+ // // // import { logger } from "../logging";
4
+
5
+ // // // export class HashManager {
6
+ // // // private config: HiSecureConfig["hashing"];
7
+ // // // private primaryAdapter: {
8
+ // // // hash: (value: string) => Promise<string>;
9
+ // // // verify: (value: string, hashed: string) => Promise<boolean>;
10
+ // // // };
11
+ // // // private fallbackAdapter: {
12
+ // // // hash: (value: string) => Promise<string>;
13
+ // // // verify: (value: string, hashed: string) => Promise<boolean>;
14
+ // // // } | null;
15
+
16
+ // // // constructor(
17
+ // // // config: HiSecureConfig["hashing"],
18
+ // // // primaryAdapter: any,
19
+ // // // fallbackAdapter: any
20
+ // // // ) {
21
+ // // // this.config = config;
22
+ // // // this.primaryAdapter = primaryAdapter;
23
+ // // // this.fallbackAdapter = fallbackAdapter;
24
+ // // // }
25
+
26
+ // // // /**
27
+ // // // * Hash a password using primary adapter (Argon2)
28
+ // // // * If it fails → fallback (Bcrypt)
29
+ // // // */
30
+ // // // async hash(value: string): Promise<string> {
31
+ // // // try {
32
+ // // // return await this.primaryAdapter.hash(value);
33
+ // // // } catch (err: any) {
34
+ // // // logger.warn("⚠ Primary hashing failed — switching to fallback", {
35
+ // // // error: err?.message,
36
+ // // // });
37
+
38
+ // // // if (!this.fallbackAdapter) {
39
+ // // // throw new AdapterError(
40
+ // // // "Primary hashing failed and no fallback adapter is configured."
41
+ // // // );
42
+ // // // }
43
+
44
+ // // // try {
45
+ // // // return await this.fallbackAdapter.hash(value);
46
+ // // // } catch (fallbackErr: any) {
47
+ // // // logger.error("❌ Fallback hashing failed", {
48
+ // // // error: fallbackErr?.message,
49
+ // // // });
50
+ // // // throw new AdapterError(
51
+ // // // "Both primary and fallback hashing failed."
52
+ // // // );
53
+ // // // }
54
+ // // // }
55
+ // // // }
56
+
57
+ // // // /**
58
+ // // // * Verify using primary hashing method.
59
+ // // // * If mismatch OR failure → use fallback.
60
+ // // // */
61
+ // // // async verify(value: string, hashed: string): Promise<boolean> {
62
+ // // // try {
63
+ // // // return await this.primaryAdapter.verify(value, hashed);
64
+ // // // } catch (err: any) {
65
+ // // // logger.warn("⚠ Primary verify failed — trying fallback", {
66
+ // // // error: err?.message,
67
+ // // // });
68
+
69
+ // // // if (!this.fallbackAdapter) {
70
+ // // // throw new AdapterError(
71
+ // // // "Primary verify failed and no fallback adapter is configured."
72
+ // // // );
73
+ // // // }
74
+
75
+ // // // try {
76
+ // // // return await this.fallbackAdapter.verify(value, hashed);
77
+ // // // } catch (fallbackErr: any) {
78
+ // // // logger.error("❌ Fallback verify failed", {
79
+ // // // error: fallbackErr?.message,
80
+ // // // });
81
+
82
+ // // // throw new AdapterError(
83
+ // // // "Both primary and fallback verify failed."
84
+ // // // );
85
+ // // // }
86
+ // // // }
87
+ // // // }
88
+ // // // }
89
+
90
+
91
+
92
+
93
+
94
+
95
+
96
+ // // import { AdapterError } from "../core/errors/AdapterError.js";
97
+ // // import { HiSecureConfig } from "../core/config.js";
98
+ // // import { logger } from "../logging";
99
+
100
+ // // interface HashAdapter {
101
+ // // hash(value: string): Promise<string>;
102
+ // // verify(value: string, hashed: string): Promise<boolean>;
103
+ // // }
104
+
105
+ // // export class HashManager {
106
+ // // private config: HiSecureConfig["hashing"];
107
+ // // private primaryAdapter: HashAdapter;
108
+ // // private fallbackAdapter: HashAdapter | null;
109
+
110
+ // // constructor(
111
+ // // config: HiSecureConfig["hashing"],
112
+ // // primaryAdapter: HashAdapter,
113
+ // // fallbackAdapter: HashAdapter | null
114
+ // // ) {
115
+ // // this.config = config;
116
+ // // this.primaryAdapter = primaryAdapter;
117
+ // // this.fallbackAdapter = fallbackAdapter;
118
+ // // }
119
+
120
+ // // async hash(value: string): Promise<string> {
121
+ // // try {
122
+ // // return await this.primaryAdapter.hash(value);
123
+ // // } catch (err: any) {
124
+ // // logger.warn("⚠ Primary hashing failed — trying fallback", {
125
+ // // error: err?.message,
126
+ // // });
127
+
128
+ // // if (!this.fallbackAdapter) {
129
+ // // throw new AdapterError(
130
+ // // "Primary hashing failed and no fallback adapter configured."
131
+ // // );
132
+ // // }
133
+
134
+ // // try {
135
+ // // return await this.fallbackAdapter.hash(value);
136
+ // // } catch (fallbackErr: any) {
137
+ // // logger.error("❌ Fallback hashing failed", {
138
+ // // error: fallbackErr?.message,
139
+ // // });
140
+ // // throw new AdapterError(
141
+ // // "Both primary and fallback hashing failed."
142
+ // // );
143
+ // // }
144
+ // // }
145
+ // // }
146
+
147
+ // // async verify(value: string, hashed: string): Promise<boolean> {
148
+ // // try {
149
+ // // return await this.primaryAdapter.verify(value, hashed);
150
+ // // } catch (err: any) {
151
+ // // logger.warn("⚠ Primary verify failed — trying fallback", {
152
+ // // error: err?.message,
153
+ // // });
154
+
155
+ // // if (!this.fallbackAdapter) {
156
+ // // throw new AdapterError(
157
+ // // "Primary verify failed and no fallback adapter configured."
158
+ // // );
159
+ // // }
160
+
161
+ // // try {
162
+ // // return await this.fallbackAdapter.verify(value, hashed);
163
+ // // } catch (fallbackErr: any) {
164
+ // // logger.error("❌ Fallback verify failed", {
165
+ // // error: fallbackErr?.message,
166
+ // // });
167
+ // // throw new AdapterError(
168
+ // // "Both primary and fallback verify failed."
169
+ // // );
170
+ // // }
171
+ // // }
172
+ // // }
173
+ // // }
174
+
175
+
176
+
177
+ // // src/managers/HashManager.ts - FIXED
178
+ // import { AdapterError } from "../core/errors/AdapterError.js";
179
+ // import { HiSecureConfig } from "../core/types/HiSecureConfig.js";
180
+ // import { logger } from "../logging";
181
+
182
+ // interface HashAdapter {
183
+ // hash(value: string): Promise<string>;
184
+ // verify(value: string, hashed: string): Promise<boolean>;
185
+ // getAlgorithm(): string;
186
+ // }
187
+
188
+ // export interface HashResult {
189
+ // hash: string;
190
+ // algorithm: string;
191
+ // usedFallback: boolean;
192
+ // }
193
+
194
+ // export class HashManager {
195
+ // private config: HiSecureConfig["hashing"];
196
+ // private primaryAdapter: HashAdapter;
197
+ // private fallbackAdapter: HashAdapter | null;
198
+
199
+ // constructor(
200
+ // config: HiSecureConfig["hashing"],
201
+ // primaryAdapter: HashAdapter,
202
+ // fallbackAdapter: HashAdapter | null
203
+ // ) {
204
+ // this.config = config;
205
+ // this.primaryAdapter = primaryAdapter;
206
+ // this.fallbackAdapter = fallbackAdapter;
207
+ // }
208
+
209
+ // async hash(value: string, options?: { allowFallback?: boolean }): Promise<HashResult> {
210
+ // try {
211
+ // const hash = await this.primaryAdapter.hash(value);
212
+ // return {
213
+ // hash,
214
+ // algorithm: this.config.primary,
215
+ // usedFallback: false
216
+ // };
217
+ // } catch (err: any) {
218
+ // logger.warn("⚠ Primary hashing failed", {
219
+ // error: err.message,
220
+ // algorithm: this.config.primary
221
+ // });
222
+
223
+ // if (!options?.allowFallback || !this.fallbackAdapter) {
224
+ // throw new AdapterError(
225
+ // `Primary hashing (${this.config.primary}) failed. Fallback not allowed.`
226
+ // );
227
+ // }
228
+
229
+ // try {
230
+ // const hash = await this.fallbackAdapter.hash(value);
231
+
232
+ // // Log security downgrade warning
233
+ // logger.warn("⚠ SECURITY DOWNGRADE: Using fallback hashing", {
234
+ // from: this.config.primary,
235
+ // to: this.config.fallback
236
+ // });
237
+
238
+ // return {
239
+ // hash,
240
+ // algorithm: this.config.fallback || 'bcrypt',
241
+ // usedFallback: true
242
+ // };
243
+ // } catch (fallbackErr: any) {
244
+ // logger.error("❌ Fallback hashing failed", {
245
+ // error: fallbackErr?.message,
246
+ // });
247
+ // throw new AdapterError(
248
+ // "Both primary and fallback hashing failed."
249
+ // );
250
+ // }
251
+ // }
252
+ // }
253
+
254
+ // async verify(value: string, hashed: string): Promise<boolean> {
255
+ // // Try primary adapter first
256
+ // try {
257
+ // return await this.primaryAdapter.verify(value, hashed);
258
+ // } catch (primaryErr: any) {
259
+ // logger.warn("⚠ Primary verify failed", {
260
+ // error: primaryErr?.message,
261
+ // });
262
+
263
+ // // If fallback exists, try it
264
+ // if (this.fallbackAdapter) {
265
+ // try {
266
+ // return await this.fallbackAdapter.verify(value, hashed);
267
+ // } catch (fallbackErr: any) {
268
+ // logger.error("❌ Fallback verify failed", {
269
+ // error: fallbackErr?.message,
270
+ // });
271
+ // throw new AdapterError(
272
+ // "Both primary and fallback verify failed."
273
+ // );
274
+ // }
275
+ // }
276
+
277
+ // throw new AdapterError(
278
+ // "Primary verify failed and no fallback adapter configured."
279
+ // );
280
+ // }
281
+ // }
282
+ // }
283
+
284
+
285
+ // src/managers/HashManager.ts - COMPLETE FIXED
286
+ import { AdapterError } from "../core/errors/AdapterError.js";
287
+ import { HiSecureConfig } from "../core/types/HiSecureConfig.js";
288
+ import { logger } from "../logging";
289
+
290
+ interface HashAdapter {
291
+ hash(value: string): Promise<string>;
292
+ verify(value: string, hashed: string): Promise<boolean>;
293
+ // ❌ getAlgorithm() REMOVED - Not needed in adapters
294
+ }
295
+
296
+ export interface HashResult {
297
+ hash: string;
298
+ algorithm: string;
299
+ usedFallback: boolean;
300
+ }
301
+
302
+ export class HashManager {
303
+ private config: HiSecureConfig["hashing"];
304
+ private primaryAdapter: HashAdapter;
305
+ private fallbackAdapter: HashAdapter | null;
306
+
307
+ constructor(
308
+ config: HiSecureConfig["hashing"],
309
+ primaryAdapter: HashAdapter,
310
+ fallbackAdapter: HashAdapter | null
311
+ ) {
312
+ this.config = config;
313
+ this.primaryAdapter = primaryAdapter;
314
+ this.fallbackAdapter = fallbackAdapter;
315
+ }
316
+
317
+ async hash(value: string, options?: { allowFallback?: boolean }): Promise<HashResult> {
318
+ try {
319
+ const hash = await this.primaryAdapter.hash(value);
320
+ return {
321
+ hash,
322
+ algorithm: this.config.primary,
323
+ usedFallback: false
324
+ };
325
+ } catch (err: any) {
326
+ logger.warn("⚠ Primary hashing failed", {
327
+ error: err.message,
328
+ algorithm: this.config.primary
329
+ });
330
+
331
+ if (!options?.allowFallback || !this.fallbackAdapter) {
332
+ throw new AdapterError(
333
+ `Primary hashing (${this.config.primary}) failed. Fallback not allowed.`
334
+ );
335
+ }
336
+
337
+ try {
338
+ const hash = await this.fallbackAdapter.hash(value);
339
+
340
+ // Log security downgrade warning
341
+ logger.warn("⚠ SECURITY DOWNGRADE: Using fallback hashing", {
342
+ from: this.config.primary,
343
+ to: this.config.fallback
344
+ });
345
+
346
+ return {
347
+ hash,
348
+ algorithm: this.config.fallback || 'bcrypt',
349
+ usedFallback: true
350
+ };
351
+ } catch (fallbackErr: any) {
352
+ logger.error("❌ Fallback hashing failed", {
353
+ error: fallbackErr?.message,
354
+ });
355
+ throw new AdapterError(
356
+ "Both primary and fallback hashing failed."
357
+ );
358
+ }
359
+ }
360
+ }
361
+
362
+ async verify(value: string, hashed: string): Promise<boolean> {
363
+ // Try primary adapter first
364
+ try {
365
+ return await this.primaryAdapter.verify(value, hashed);
366
+ } catch (primaryErr: any) {
367
+ logger.warn("⚠ Primary verify failed", {
368
+ error: primaryErr?.message,
369
+ });
370
+
371
+ // If fallback exists, try it
372
+ if (this.fallbackAdapter) {
373
+ try {
374
+ return await this.fallbackAdapter.verify(value, hashed);
375
+ } catch (fallbackErr: any) {
376
+ logger.error("❌ Fallback verify failed", {
377
+ error: fallbackErr?.message,
378
+ });
379
+ throw new AdapterError(
380
+ "Both primary and fallback verify failed."
381
+ );
382
+ }
383
+ }
384
+
385
+ throw new AdapterError(
386
+ "Primary verify failed and no fallback adapter configured."
387
+ );
388
+ }
389
+ }
390
+ }