hi-secure 1.0.10 β 1.0.12
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/package.json +1 -1
- package/readme.md +484 -113
package/package.json
CHANGED
package/readme.md
CHANGED
|
@@ -1,195 +1,566 @@
|
|
|
1
1
|
<h1 align="center">π HiSecure</h1>
|
|
2
|
-
<p align="center"><strong>One-line security for Express.js
|
|
2
|
+
<p align="center"><strong>One-line security for Express.js</strong></p>
|
|
3
3
|
|
|
4
4
|
<p align="center">
|
|
5
|
-
HiSecure
|
|
6
|
-
It
|
|
7
|
-
all
|
|
5
|
+
HiSecure replaces <strong>10+ common Express security libraries</strong> with one unified API.<br/>
|
|
6
|
+
It provides hashing, authentication, validation, sanitization, rate-limiting, CORS,<br/>
|
|
7
|
+
security headers, compression, JSON parsing, query parsing and logging β all in a single layer.
|
|
8
8
|
</p>
|
|
9
9
|
|
|
10
10
|
<br/>
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
<div style="border-left:5px solid #6366F1; padding:20px; border-radius:8px; background:#fafafa;">
|
|
12
|
+
<hr style="border:0; border-top:2px solid #e5e7eb; margin:32px 0"/>
|
|
14
13
|
|
|
15
|
-
<h2
|
|
14
|
+
<h2>π Overview</h2>
|
|
16
15
|
|
|
17
|
-
<
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
16
|
+
<p>
|
|
17
|
+
Most Express applications require multiple security packages: hashing, CORS, headers, sanitization,
|
|
18
|
+
validation, rate-limits, compression, JSON parsing, query parsing, and authentication.
|
|
19
|
+
Managing all of these separately leads to duplication, bugs, and misconfiguration.
|
|
20
|
+
</p>
|
|
21
|
+
|
|
22
|
+
<p><strong>HiSecure handles all of them for you β with one middleware call.</strong></p>
|
|
23
23
|
|
|
24
|
-
<h3 style="color:#3B82F6;">π Authentication</h3>
|
|
25
24
|
<ul>
|
|
26
|
-
<li><
|
|
27
|
-
<li><
|
|
28
|
-
<li><
|
|
25
|
+
<li><code>argon2</code> / <code>bcrypt</code> β hashing</li>
|
|
26
|
+
<li><code>sanitize-html</code> / <code>xss</code> β sanitization</li>
|
|
27
|
+
<li><code>express-validator</code> / <code>zod</code> β validation</li>
|
|
28
|
+
<li><code>helmet</code> / <code>hpp</code> β headers + HPP</li>
|
|
29
|
+
<li><code>cors</code> β CORS control</li>
|
|
30
|
+
<li><code>express-rate-limit</code> + <code>rate-limiter-flexible</code> β rate limiting</li>
|
|
31
|
+
<li><code>compression</code> β gzip</li>
|
|
32
|
+
<li><code>json/urlencoded</code> β parsers</li>
|
|
33
|
+
<li><code>qs</code> β secure deep query parsing</li>
|
|
29
34
|
</ul>
|
|
30
35
|
|
|
31
|
-
<
|
|
36
|
+
<p><strong>HiSecure bundles all of these features out-of-the-box.</strong></p>
|
|
37
|
+
|
|
38
|
+
<br/>
|
|
39
|
+
<hr style="border:0; border-top:2px solid #e5e7eb; margin:32px 0"/>
|
|
40
|
+
|
|
41
|
+
<h2>β¨ Feature Matrix</h2>
|
|
42
|
+
|
|
43
|
+
<p>
|
|
44
|
+
A complete list of what HiSecure does.
|
|
45
|
+
Everything is built to work together without configuration.
|
|
46
|
+
</p>
|
|
47
|
+
|
|
48
|
+
<table width="100%">
|
|
49
|
+
<tr>
|
|
50
|
+
<th align="left">Capability</th>
|
|
51
|
+
<th align="left">Status</th>
|
|
52
|
+
<th align="left">Details</th>
|
|
53
|
+
</tr>
|
|
54
|
+
|
|
55
|
+
<tr>
|
|
56
|
+
<td>π JWT Authentication</td>
|
|
57
|
+
<td>β
Stable</td>
|
|
58
|
+
<td>Built-in issuer, audience, expiry and subject support. Google ID-token adapter included.</td>
|
|
59
|
+
</tr>
|
|
60
|
+
|
|
61
|
+
<tr>
|
|
62
|
+
<td>π Password Hashing (Argon2 + bcrypt fallback)</td>
|
|
63
|
+
<td>β
Stable</td>
|
|
64
|
+
<td>Argon2-first approach with bcrypt fallback. No salt configuration required.</td>
|
|
65
|
+
</tr>
|
|
66
|
+
|
|
67
|
+
<tr>
|
|
68
|
+
<td>π‘ Route Protection</td>
|
|
69
|
+
<td>β
Stable</td>
|
|
70
|
+
<td>Authentication guard with support for roles (RBAC).</td>
|
|
71
|
+
</tr>
|
|
72
|
+
|
|
73
|
+
<tr>
|
|
74
|
+
<td>π Validation (Zod + express-validator)</td>
|
|
75
|
+
<td>β
Stable</td>
|
|
76
|
+
<td>Automatically detects schema type. Provides a clean error format.</td>
|
|
77
|
+
</tr>
|
|
78
|
+
|
|
79
|
+
<tr>
|
|
80
|
+
<td>π§Ό Sanitization</td>
|
|
81
|
+
<td>β
Stable</td>
|
|
82
|
+
<td>Protects against HTML injection & XSS using sanitize-html + xss fallback.</td>
|
|
83
|
+
</tr>
|
|
84
|
+
|
|
85
|
+
<tr>
|
|
86
|
+
<td>β± Rate Limiting</td>
|
|
87
|
+
<td>β
Stable</td>
|
|
88
|
+
<td>Presets (strict/relaxed/api) + custom per-route limits. Fallback engine included.</td>
|
|
89
|
+
</tr>
|
|
90
|
+
|
|
91
|
+
<tr>
|
|
92
|
+
<td>π CORS</td>
|
|
93
|
+
<td>β
Stable</td>
|
|
94
|
+
<td>Dynamic origins + full configuration support.</td>
|
|
95
|
+
</tr>
|
|
96
|
+
|
|
97
|
+
<tr>
|
|
98
|
+
<td>π§± Security Headers</td>
|
|
99
|
+
<td>β
Stable</td>
|
|
100
|
+
<td>Automatic helmet + HPP integration.</td>
|
|
101
|
+
</tr>
|
|
102
|
+
|
|
103
|
+
<tr>
|
|
104
|
+
<td>π¦ JSON & URL Parsing</td>
|
|
105
|
+
<td>β
Stable</td>
|
|
106
|
+
<td>Togglable express.json + urlencoded, simple and safe.</td>
|
|
107
|
+
</tr>
|
|
108
|
+
|
|
109
|
+
<tr>
|
|
110
|
+
<td>π Query Parsing</td>
|
|
111
|
+
<td>β
Stable</td>
|
|
112
|
+
<td>Secure <code>qs</code>-based deep parsing out of the box.</td>
|
|
113
|
+
</tr>
|
|
114
|
+
|
|
115
|
+
<tr>
|
|
116
|
+
<td>π Compression</td>
|
|
117
|
+
<td>β
Stable</td>
|
|
118
|
+
<td>gzip enabled via a single flag.</td>
|
|
119
|
+
</tr>
|
|
120
|
+
|
|
121
|
+
<tr>
|
|
122
|
+
<td>π Structured Logging</td>
|
|
123
|
+
<td>β οΈ Beta</td>
|
|
124
|
+
<td>Unified log output for debugging & monitoring.</td>
|
|
125
|
+
</tr>
|
|
126
|
+
|
|
127
|
+
<tr>
|
|
128
|
+
<td>π§ Adapter System</td>
|
|
129
|
+
<td>β
Stable</td>
|
|
130
|
+
<td>Swap hashing/validation/sanitization engines easily.</td>
|
|
131
|
+
</tr>
|
|
132
|
+
</table>
|
|
133
|
+
|
|
134
|
+
<br/>
|
|
135
|
+
<hr style="border:0; border-top:2px solid #e5e7eb; margin:32px 0"/>
|
|
136
|
+
|
|
137
|
+
<h2>β‘ Developer Experience Highlights</h2>
|
|
138
|
+
|
|
139
|
+
<p>
|
|
140
|
+
HiSecure is designed so even a beginner can set up security in minutes.
|
|
141
|
+
Hereβs what makes it simple:
|
|
142
|
+
</p>
|
|
143
|
+
|
|
32
144
|
<ul>
|
|
33
|
-
<li><strong>
|
|
34
|
-
|
|
35
|
-
<li>
|
|
36
|
-
<
|
|
37
|
-
|
|
38
|
-
<li>π‘ <strong>Relaxed</strong>: 100 req / 15 min</li>
|
|
39
|
-
<li>βοΈ <strong>API</strong>: Custom config</li>
|
|
40
|
-
</ul>
|
|
145
|
+
<li><strong>One-line global security</strong> using <code>HiSecure.middleware()</code></li>
|
|
146
|
+
|
|
147
|
+
<li><strong>Password utilities</strong>
|
|
148
|
+
<br/>β’ <code>HiSecure.hash()</code> β secure Argon2 hashing
|
|
149
|
+
<br/>β’ <code>HiSecure.verify()</code> β easy password comparison
|
|
41
150
|
</li>
|
|
42
|
-
</ul>
|
|
43
151
|
|
|
44
|
-
<
|
|
45
|
-
<
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
152
|
+
<li><strong>JWT utilities</strong>
|
|
153
|
+
<br/>β’ <code>HiSecure.jwt.sign()</code> β create tokens
|
|
154
|
+
<br/>β’ <code>HiSecure.jwt.verify()</code> β verify tokens
|
|
155
|
+
</li>
|
|
156
|
+
|
|
157
|
+
<li>Automatic sanitization β no extra middleware needed</li>
|
|
158
|
+
|
|
159
|
+
<li>Auto-detected validation (Zod or express-validator)</li>
|
|
160
|
+
|
|
161
|
+
<li>Clean route protection with <code>HiSecure.auth()</code></li>
|
|
162
|
+
|
|
163
|
+
<li>Flexible rate limits for login routes and APIs</li>
|
|
164
|
+
|
|
165
|
+
<li>Zero configuration for headers, parsing, gzip, CORS, etc.</li>
|
|
166
|
+
|
|
167
|
+
<li>Perfect for beginners and production-grade APIs</li>
|
|
49
168
|
</ul>
|
|
50
169
|
|
|
51
|
-
<
|
|
170
|
+
<br/>
|
|
171
|
+
<hr style="border:0; border-top:2px solid #e5e7eb; margin:32px 0"/>
|
|
172
|
+
|
|
173
|
+
<h2>π Summary</h2>
|
|
174
|
+
|
|
175
|
+
<p>
|
|
176
|
+
HiSecure provides a powerful but easy security layer:
|
|
177
|
+
</p>
|
|
178
|
+
|
|
52
179
|
<ul>
|
|
53
|
-
<li>
|
|
54
|
-
<li>
|
|
55
|
-
<li>
|
|
56
|
-
<li>
|
|
57
|
-
<li>
|
|
180
|
+
<li><strong>JWT Authentication</strong></li>
|
|
181
|
+
<li><strong>Password Hashing</strong></li>
|
|
182
|
+
<li><strong>Route Protection</strong></li>
|
|
183
|
+
<li><strong>Validation + Sanitization</strong></li>
|
|
184
|
+
<li><strong>Rate Limiting</strong> (primary + fallback)</li>
|
|
185
|
+
<li><strong>CORS + Security Headers + Compression</strong></li>
|
|
186
|
+
<li><strong>JSON + Query Parsing</strong></li>
|
|
58
187
|
</ul>
|
|
59
188
|
|
|
60
|
-
|
|
189
|
+
<p align="center"><strong>
|
|
190
|
+
Security without complexity.<br/>
|
|
191
|
+
One dependency β complete Express protection.
|
|
192
|
+
</strong></p>
|
|
61
193
|
|
|
62
|
-
<br/>
|
|
194
|
+
<br/><br/>
|
|
63
195
|
|
|
64
|
-
<!--
|
|
65
|
-
<
|
|
196
|
+
<!-- βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ -->
|
|
197
|
+
<h2 align="center">π Documentation Sections</h2>
|
|
198
|
+
<!-- βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ -->
|
|
66
199
|
|
|
67
|
-
<
|
|
200
|
+
<hr style="border:0; border-top:2px dashed #d4d4d8; margin:32px 0"/>
|
|
68
201
|
|
|
69
|
-
<
|
|
202
|
+
<h2>π Part 1 β Quick Start</h2>
|
|
70
203
|
|
|
71
|
-
|
|
72
|
-
npm install hi-secure
|
|
73
|
-
```
|
|
204
|
+
<p>This section is designed for beginners to get started within seconds.</p>
|
|
74
205
|
|
|
75
|
-
<
|
|
206
|
+
<strong>Install</strong>
|
|
207
|
+
<pre><code>npm install hi-secure</code></pre>
|
|
76
208
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
209
|
+
<strong>Basic Usage</strong>
|
|
210
|
+
<pre><code>const express = require('express');
|
|
211
|
+
const { HiSecure } = require('hi-secure');
|
|
80
212
|
|
|
81
213
|
const app = express();
|
|
82
214
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
215
|
+
// One-line complete security preset
|
|
216
|
+
app.use(HiSecure.middleware('api'));
|
|
217
|
+
|
|
218
|
+
app.listen(3000);
|
|
219
|
+
</code></pre>
|
|
220
|
+
|
|
221
|
+
<p><small>The "api" preset includes CORS, Relaxed Rate Limit, Sanitization and basic headers.</small></p>
|
|
222
|
+
|
|
223
|
+
<br/>
|
|
224
|
+
<hr style="border:0; border-top:2px dashed #d4d4d8; margin:32px 0"/>
|
|
225
|
+
|
|
226
|
+
<h2>π Part 2 β Using Built-In Helpers</h2>
|
|
227
|
+
|
|
228
|
+
<h3>2.1 Hashing + Verifying Passwords</h3>
|
|
229
|
+
|
|
230
|
+
<p>Perfect for controllers like register/login.</p>
|
|
231
|
+
|
|
232
|
+
<pre><code>const hashed = await HiSecure.hash(password);
|
|
233
|
+
const valid = await HiSecure.verify(password, user.password);
|
|
234
|
+
</code></pre>
|
|
235
|
+
|
|
236
|
+
<h3>2.2 Validating Inputs in Routes</h3>
|
|
237
|
+
|
|
238
|
+
<p>HiSecure automatically detects whether you're providing Zod or express-validator rules.</p>
|
|
239
|
+
|
|
240
|
+
<pre><code>router.post(
|
|
241
|
+
'/register',
|
|
242
|
+
HiSecure.validate([
|
|
243
|
+
body("name").notEmpty().isLength({ min: 3 }),
|
|
244
|
+
body("email").notEmpty().isEmail(),
|
|
245
|
+
body("password").notEmpty().isLength({ min: 6 })
|
|
246
|
+
]),
|
|
247
|
+
registerUser
|
|
86
248
|
);
|
|
249
|
+
</code></pre>
|
|
87
250
|
|
|
88
|
-
|
|
89
|
-
```
|
|
251
|
+
<h3>2.3 Login Route with Rate Limiting</h3>
|
|
90
252
|
|
|
91
|
-
<
|
|
253
|
+
<pre><code>router.post(
|
|
254
|
+
'/login',
|
|
255
|
+
HiSecure.validate([...]),
|
|
256
|
+
HiSecure.rateLimit({ max: 5, windowMs: 15 * 60 * 1000 }),
|
|
257
|
+
loginUser
|
|
258
|
+
);
|
|
259
|
+
</code></pre>
|
|
92
260
|
|
|
93
|
-
|
|
261
|
+
<h3>2.4 Protecting Routes with Auth Middleware</h3>
|
|
94
262
|
|
|
95
|
-
router.
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
validate: z.object({
|
|
100
|
-
message: z.string().min(5),
|
|
101
|
-
rating: z.number().min(1).max(5)
|
|
102
|
-
}),
|
|
103
|
-
}),
|
|
104
|
-
handleFeedback
|
|
263
|
+
<pre><code>router.get(
|
|
264
|
+
'/profile',
|
|
265
|
+
HiSecure.auth({ required: true }),
|
|
266
|
+
getProfile
|
|
105
267
|
);
|
|
268
|
+
</code></pre>
|
|
106
269
|
|
|
107
|
-
|
|
270
|
+
<br/>
|
|
271
|
+
<hr style="border:0; border-top:2px dashed #d4d4d8; margin:32px 0"/>
|
|
108
272
|
|
|
273
|
+
<h2>π Part 3 β JWT Mode (Advanced)</h2>
|
|
109
274
|
|
|
110
|
-
|
|
275
|
+
<p>Enable this mode only if you want full control over JWT signing options.</p>
|
|
111
276
|
|
|
277
|
+
<h3>3.1 Configure JWT Engine</h3>
|
|
112
278
|
|
|
113
|
-
|
|
114
|
-
export const registerUser = async (req, res) => {
|
|
115
|
-
const { name, email, password } = req.body;
|
|
279
|
+
<pre><code>HiSecure.resetInstance();
|
|
116
280
|
|
|
117
|
-
|
|
281
|
+
HiSecure.getInstance({
|
|
282
|
+
auth: {
|
|
283
|
+
enabled: true,
|
|
284
|
+
jwtSecret: process.env.JWT_SECRET,
|
|
285
|
+
jwtExpiresIn: "1d"
|
|
286
|
+
}
|
|
287
|
+
});
|
|
288
|
+
</code></pre>
|
|
118
289
|
|
|
119
|
-
|
|
290
|
+
<h3>3.2 Global Security Middleware</h3>
|
|
120
291
|
|
|
121
|
-
|
|
292
|
+
<pre><code>app.use(HiSecure.middleware({
|
|
293
|
+
cors: true,
|
|
294
|
+
rateLimit: "strict",
|
|
295
|
+
sanitize: true,
|
|
296
|
+
headers: true,
|
|
297
|
+
compression: true,
|
|
298
|
+
json: true
|
|
299
|
+
}));
|
|
300
|
+
</code></pre>
|
|
122
301
|
|
|
123
|
-
|
|
124
|
-
|
|
302
|
+
<br/>
|
|
303
|
+
<hr style="border:0; border-top:2px dashed #d4d4d8; margin:32px 0"/>
|
|
125
304
|
|
|
126
|
-
|
|
305
|
+
<h2>π Part 4 β Full Example Snapshot</h2>
|
|
127
306
|
|
|
307
|
+
<p>This gives developers a quick glance at how the entire system fits together.</p>
|
|
128
308
|
|
|
129
|
-
<
|
|
309
|
+
<pre><code>// server.js
|
|
310
|
+
require("dotenv").config();
|
|
311
|
+
const express = require("express");
|
|
312
|
+
const dbConnect = require("./config/db");
|
|
313
|
+
const { HiSecure } = require("hi-secure");
|
|
130
314
|
|
|
315
|
+
const app = express();
|
|
316
|
+
const PORT = process.env.PORT || 3000;
|
|
317
|
+
|
|
318
|
+
dbConnect();
|
|
131
319
|
|
|
132
|
-
|
|
320
|
+
// β FORCE NEW INSTANCE WITH CORRECT CONFIG - if use HiSecure.jwt()
|
|
321
|
+
HiSecure.resetInstance();
|
|
133
322
|
|
|
134
|
-
|
|
135
|
-
|
|
323
|
+
HiSecure.getInstance({
|
|
324
|
+
auth: {
|
|
325
|
+
enabled: true,
|
|
326
|
+
jwtSecret: process.env.JWT_SECRET || "supersecret123",
|
|
327
|
+
jwtExpiresIn: "1d",
|
|
328
|
+
}
|
|
329
|
+
});
|
|
136
330
|
|
|
137
|
-
|
|
331
|
+
// if u don't use our jwt config
|
|
332
|
+
app.use(HiSecure.middleware('api')); // one line setup - along with this u use the HiSecure.validat() and HiSecure.hash() | HiSecure.verify()
|
|
138
333
|
|
|
139
|
-
|
|
140
|
-
|
|
334
|
+
// Global middleware WITHOUT auth override
|
|
335
|
+
app.use(
|
|
336
|
+
HiSecure.middleware({
|
|
337
|
+
cors: true,
|
|
338
|
+
rateLimit: "strict",
|
|
339
|
+
sanitize: true,
|
|
340
|
+
headers: true,
|
|
341
|
+
compression: true,
|
|
342
|
+
json: true
|
|
343
|
+
})
|
|
344
|
+
);
|
|
141
345
|
|
|
142
|
-
|
|
346
|
+
// ROUTES (call builder)
|
|
347
|
+
const userRoutes = require("./routes/UserRoutes");
|
|
348
|
+
app.use("/api/auth", userRoutes());
|
|
143
349
|
|
|
144
|
-
|
|
350
|
+
app.listen(PORT, () => {
|
|
351
|
+
console.log(`π Server running port ${PORT}`);
|
|
352
|
+
});
|
|
353
|
+
|
|
354
|
+
</code></pre>
|
|
355
|
+
|
|
356
|
+
|
|
357
|
+
<pre><code>// controller
|
|
358
|
+
const { HiSecure } = require('hi-secure');
|
|
359
|
+
const User = require("../models/User");
|
|
360
|
+
|
|
361
|
+
const JWT_OPTIONS = {
|
|
362
|
+
issuer: 'hi-secure-backend',
|
|
363
|
+
audience: ['web-app', 'mobile-app'], // Array format
|
|
364
|
+
expiresIn: '7d',
|
|
365
|
+
subject: 'user-authentication'
|
|
145
366
|
};
|
|
146
367
|
|
|
368
|
+
exports.registerUser = async(req, res) => {
|
|
369
|
+
try {
|
|
370
|
+
const { name, email, password } = req.body;
|
|
371
|
+
|
|
372
|
+
// Check if user exists
|
|
373
|
+
const existingUser = await User.findOne({ email });
|
|
374
|
+
if (existingUser) {
|
|
375
|
+
return res.status(400).json({
|
|
376
|
+
error: 'User already exists'
|
|
377
|
+
});
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
// Hash password
|
|
381
|
+
const hashedPassword = await HiSecure.hash(password);
|
|
382
|
+
|
|
383
|
+
// Create user
|
|
384
|
+
const user = await User.create({
|
|
385
|
+
name,
|
|
386
|
+
email,
|
|
387
|
+
password: hashedPassword
|
|
388
|
+
});
|
|
389
|
+
|
|
390
|
+
// FIXED: JWT sign with ALL required options
|
|
391
|
+
const token = HiSecure.jwt.sign({
|
|
392
|
+
userId: user._id.toString(),
|
|
393
|
+
email: user.email,
|
|
394
|
+
name: user.name,
|
|
395
|
+
role: 'user'
|
|
396
|
+
},
|
|
397
|
+
JWT_OPTIONS
|
|
398
|
+
);
|
|
399
|
+
|
|
400
|
+
res.status(201).json({
|
|
401
|
+
message: 'User registered successfully',
|
|
402
|
+
token,
|
|
403
|
+
user: {
|
|
404
|
+
id: user._id,
|
|
405
|
+
name: user.name,
|
|
406
|
+
email: user.email
|
|
407
|
+
}
|
|
408
|
+
});
|
|
409
|
+
|
|
410
|
+
} catch (error) {
|
|
411
|
+
console.error('Registration error:', error);
|
|
412
|
+
res.status(500).json({
|
|
413
|
+
error: 'Registration failed',
|
|
414
|
+
details: error.message
|
|
415
|
+
});
|
|
416
|
+
}
|
|
417
|
+
};
|
|
147
418
|
|
|
148
|
-
|
|
419
|
+
exports.loginUser = async(req, res) => {
|
|
420
|
+
try {
|
|
421
|
+
const { email, password } = req.body;
|
|
422
|
+
|
|
423
|
+
// Find user
|
|
424
|
+
const user = await User.findOne({ email });
|
|
425
|
+
if (!user) {
|
|
426
|
+
return res.status(401).json({
|
|
427
|
+
error: 'Invalid credentials'
|
|
428
|
+
});
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
// Verify password
|
|
432
|
+
const isValid = await HiSecure.verify(password, user.password);
|
|
433
|
+
if (!isValid) {
|
|
434
|
+
return res.status(401).json({
|
|
435
|
+
error: 'Invalid credentials'
|
|
436
|
+
});
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
// FIXED: Same JWT options
|
|
440
|
+
const token = HiSecure.jwt.sign({
|
|
441
|
+
userId: user._id.toString(),
|
|
442
|
+
email: user.email,
|
|
443
|
+
name: user.name,
|
|
444
|
+
role: 'user'
|
|
445
|
+
},
|
|
446
|
+
JWT_OPTIONS
|
|
447
|
+
);
|
|
448
|
+
|
|
449
|
+
res.json({
|
|
450
|
+
message: 'Login successful',
|
|
451
|
+
token,
|
|
452
|
+
user: {
|
|
453
|
+
id: user._id,
|
|
454
|
+
name: user.name,
|
|
455
|
+
email: user.email
|
|
456
|
+
}
|
|
457
|
+
});
|
|
458
|
+
|
|
459
|
+
} catch (error) {
|
|
460
|
+
console.error('Login error:', error);
|
|
461
|
+
res.status(500).json({
|
|
462
|
+
error: 'Login failed',
|
|
463
|
+
details: error.message
|
|
464
|
+
});
|
|
465
|
+
}
|
|
466
|
+
};
|
|
149
467
|
|
|
150
|
-
|
|
468
|
+
exports.getProfile = async(req, res) => {
|
|
469
|
+
try {
|
|
470
|
+
// req.user is set by HiSecure.auth() middleware
|
|
471
|
+
const user = await User.findById(req.user.userId).select('-password');
|
|
472
|
+
|
|
473
|
+
if (!user) {
|
|
474
|
+
return res.status(404).json({
|
|
475
|
+
error: 'User not found'
|
|
476
|
+
});
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
res.json({
|
|
480
|
+
message: 'Profile data',
|
|
481
|
+
user
|
|
482
|
+
});
|
|
483
|
+
} catch (error) {
|
|
484
|
+
console.error('Profile error:', error);
|
|
485
|
+
res.status(500).json({
|
|
486
|
+
error: 'Failed to fetch profile',
|
|
487
|
+
details: error.message
|
|
488
|
+
});
|
|
489
|
+
}
|
|
490
|
+
};
|
|
491
|
+
</code></pre>
|
|
151
492
|
|
|
152
|
-
```bash
|
|
153
493
|
|
|
154
|
-
|
|
494
|
+
<pre><code>// routes
|
|
495
|
+
const express = require('express');
|
|
496
|
+
const { body } = require('express-validator');
|
|
497
|
+
const { HiSecure } = require('hi-secure');
|
|
498
|
+
const { registerUser, loginUser, getProfile } = require('../controllers/UserControllers');
|
|
155
499
|
|
|
156
|
-
```
|
|
157
500
|
|
|
158
501
|
|
|
159
502
|
|
|
160
|
-
|
|
503
|
+
module.exports = function buildRoutes() {
|
|
504
|
+
const router = express.Router();
|
|
161
505
|
|
|
506
|
+
router.post(
|
|
507
|
+
'/register',
|
|
162
508
|
|
|
163
|
-
|
|
509
|
+
HiSecure.validate([
|
|
510
|
+
body("name")
|
|
511
|
+
.notEmpty().withMessage("Name is required")
|
|
512
|
+
.isLength({ min: 3 }).withMessage("Name must be at least 3 characters"),
|
|
164
513
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
);
|
|
514
|
+
body("email")
|
|
515
|
+
.notEmpty().withMessage("Email is required")
|
|
516
|
+
.isEmail().withMessage("Invalid email format"),
|
|
169
517
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
loginUser
|
|
175
|
-
);
|
|
518
|
+
body("password")
|
|
519
|
+
.notEmpty().withMessage("Password is required")
|
|
520
|
+
.isLength({ min: 6 }).withMessage("Password must be at least 6 characters"),
|
|
521
|
+
]),
|
|
176
522
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
HiSecure.auth({ required: true }),
|
|
180
|
-
getProfile
|
|
181
|
-
);
|
|
523
|
+
registerUser
|
|
524
|
+
);
|
|
182
525
|
|
|
526
|
+
|
|
527
|
+
router.post(
|
|
528
|
+
'/login',
|
|
183
529
|
|
|
184
|
-
|
|
530
|
+
HiSecure.validate([
|
|
531
|
+
body("email")
|
|
532
|
+
.notEmpty().withMessage("Email is required")
|
|
533
|
+
.isEmail().withMessage("Invalid email format"),
|
|
185
534
|
|
|
535
|
+
body("password")
|
|
536
|
+
.notEmpty().withMessage("Password is required")
|
|
537
|
+
]),
|
|
186
538
|
|
|
187
|
-
|
|
188
|
-
|
|
539
|
+
// Apply rate limiter also
|
|
540
|
+
HiSecure.rateLimit({ max: 5, windowMs: 15 * 60 * 1000 }),
|
|
189
541
|
|
|
542
|
+
loginUser
|
|
543
|
+
);
|
|
190
544
|
|
|
191
545
|
|
|
546
|
+
router.get(
|
|
547
|
+
'/profile',
|
|
548
|
+
HiSecure.auth({ required: true }),
|
|
549
|
+
getProfile
|
|
550
|
+
);
|
|
192
551
|
|
|
552
|
+
return router;
|
|
553
|
+
};
|
|
554
|
+
</code></pre>
|
|
193
555
|
|
|
556
|
+
<br/>
|
|
557
|
+
<hr style="border:0; border-top:2px dashed #d4d4d8; margin:32px 0"/>
|
|
558
|
+
|
|
559
|
+
<h2 align="center">π Additional Documentation</h2>
|
|
194
560
|
|
|
561
|
+
<p align="center">
|
|
562
|
+
We are actively working on extended documentation:<br/>
|
|
563
|
+
<strong>Advanced patterns, RBAC examples, custom adapters, deployment setups & best practices.</strong>
|
|
564
|
+
</p>
|
|
195
565
|
|
|
566
|
+
<p align="center"><i>Updates coming soon.</i></p>
|