hi-secure 1.0.35 → 1.0.36
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 +192 -230
package/package.json
CHANGED
package/readme.md
CHANGED
|
@@ -460,21 +460,24 @@ Execution order is deterministic and isolated to the route.
|
|
|
460
460
|
JWT support is optional. Enable it only if you want authentication features.
|
|
461
461
|
</p>
|
|
462
462
|
|
|
463
|
-
<pre><code>
|
|
464
|
-
|
|
465
|
-
HiSecure.
|
|
463
|
+
<pre><code>
|
|
464
|
+
|
|
465
|
+
HiSecure.init({
|
|
466
466
|
auth: {
|
|
467
467
|
enabled: true,
|
|
468
|
-
jwtSecret:
|
|
469
|
-
|
|
470
|
-
|
|
468
|
+
jwtSecret:
|
|
469
|
+
process.env.JWT_SECRET , // "at least 32 - if not it shows warning in logs"
|
|
470
|
+
jwtExpiresIn: "1d",
|
|
471
|
+
},
|
|
471
472
|
});
|
|
473
|
+
|
|
474
|
+
|
|
472
475
|
</code></pre>
|
|
473
476
|
|
|
474
477
|
<hr/>
|
|
475
478
|
|
|
476
479
|
|
|
477
|
-
<h2
|
|
480
|
+
<h2>Final Authentication Setup</h2>
|
|
478
481
|
|
|
479
482
|
<p>
|
|
480
483
|
This section demonstrates a complete, production-ready authentication setup using HiSecure.
|
|
@@ -493,42 +496,84 @@ It covers signup, JWT login, Google login, role-based access control, and proper
|
|
|
493
496
|
|
|
494
497
|
<hr/>
|
|
495
498
|
|
|
496
|
-
<h3>Application Bootstrap (
|
|
499
|
+
<h3>Application Bootstrap (app.ts / app.js)</h3>
|
|
497
500
|
|
|
498
|
-
<pre><code>
|
|
499
|
-
|
|
501
|
+
<pre><code>
|
|
502
|
+
|
|
503
|
+
import express from "express";
|
|
500
504
|
import { HiSecure } from "hi-secure";
|
|
501
|
-
import
|
|
505
|
+
import dotenv from "dotenv";
|
|
502
506
|
|
|
503
507
|
dotenv.config();
|
|
504
508
|
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
HiSecure.resetInstance();
|
|
508
|
-
|
|
509
|
-
HiSecure.getInstance({
|
|
509
|
+
HiSecure.init({
|
|
510
510
|
auth: {
|
|
511
511
|
enabled: true,
|
|
512
|
-
jwtSecret:
|
|
512
|
+
jwtSecret:
|
|
513
|
+
process.env.JWT_SECRET ,
|
|
513
514
|
jwtExpiresIn: "1d",
|
|
514
|
-
|
|
515
|
-
}
|
|
515
|
+
},
|
|
516
516
|
});
|
|
517
517
|
|
|
518
|
+
const app = express();
|
|
519
|
+
|
|
518
520
|
app.use(HiSecure.middleware("api"));
|
|
519
521
|
|
|
520
|
-
app.use("/auth", authRoutes);
|
|
521
522
|
|
|
522
|
-
|
|
523
|
+
// When u use the Frontend [Because - Cors is the browser's security]
|
|
524
|
+
// HiSecure.cors({
|
|
525
|
+
// origin:"*" , // We can add our custome end points as well
|
|
526
|
+
// credentials:true
|
|
527
|
+
// })
|
|
528
|
+
|
|
529
|
+
|
|
530
|
+
import authRoutes from "./routes/auth.route";
|
|
531
|
+
import issueRoutes from "./routes/issue.route";
|
|
532
|
+
import notificationRoutes from "./routes/notification.route";
|
|
533
|
+
import communityRoutes from "./routes/community.route";
|
|
534
|
+
|
|
535
|
+
app.use("/api/auth", authRoutes);
|
|
536
|
+
app.use("/api/issues", issueRoutes);
|
|
537
|
+
app.use("/api/notifications", notificationRoutes);
|
|
538
|
+
app.use("/api/community", communityRoutes);
|
|
539
|
+
|
|
540
|
+
app.get("/", (_req, res) => {
|
|
541
|
+
res.json({ success: true, message: "Backend running" });
|
|
542
|
+
});
|
|
543
|
+
|
|
544
|
+
export default app;
|
|
545
|
+
|
|
523
546
|
</code></pre>
|
|
524
547
|
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
</
|
|
548
|
+
|
|
549
|
+
|
|
550
|
+
|
|
551
|
+
<h3>Application Bootstrap (server.ts / server.js)</h3>
|
|
552
|
+
|
|
553
|
+
<pre><code>
|
|
554
|
+
|
|
555
|
+
import app from "./app";
|
|
556
|
+
import dotenv from "dotenv";
|
|
557
|
+
import { connectDB } from "./config/db";
|
|
558
|
+
|
|
559
|
+
dotenv.config();
|
|
560
|
+
|
|
561
|
+
connectDB();
|
|
562
|
+
|
|
563
|
+
const PORT = process.env.PORT;
|
|
564
|
+
|
|
565
|
+
app.listen(PORT, () => {
|
|
566
|
+
console.log(`Server running on port ${PORT}`);
|
|
567
|
+
});
|
|
568
|
+
|
|
569
|
+
</code></pre>
|
|
570
|
+
|
|
571
|
+
|
|
572
|
+
|
|
529
573
|
|
|
530
574
|
<hr/>
|
|
531
575
|
|
|
576
|
+
|
|
532
577
|
<h3>Authentication Routes</h3>
|
|
533
578
|
|
|
534
579
|
<pre><code>import { Router } from "express";
|
|
@@ -552,75 +597,63 @@ router.get(
|
|
|
552
597
|
);
|
|
553
598
|
|
|
554
599
|
export default router;
|
|
600
|
+
|
|
555
601
|
</code></pre>
|
|
556
602
|
|
|
557
603
|
<hr/>
|
|
558
604
|
|
|
559
605
|
<h3>Authentication Controllers</h3>
|
|
560
606
|
|
|
607
|
+
|
|
561
608
|
<h4>Signup (Email and Password)</h4>
|
|
562
609
|
|
|
563
610
|
<pre><code>
|
|
564
|
-
import { HiSecure } from "hi-secure";
|
|
565
|
-
import { HttpError } from "../core/errors/HttpError.js";
|
|
566
|
-
import User from "../models/User.js";
|
|
567
|
-
|
|
568
611
|
|
|
569
|
-
const JWT_OPTIONS = {
|
|
570
|
-
issuer: 'hi-secure-backend',
|
|
571
|
-
audience: ['web-app', 'mobile-app'],
|
|
572
|
-
expiresIn: '7d',
|
|
573
|
-
subject: 'user-authentication'
|
|
574
|
-
};
|
|
575
612
|
|
|
613
|
+
export const register = async (req: Request, res: Response) => {
|
|
614
|
+
try {
|
|
615
|
+
const { name, email, password, role, hostel, block, room } = req.body;
|
|
576
616
|
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
return res.status(400).json({
|
|
584
|
-
error: 'User already exists'
|
|
585
|
-
});
|
|
586
|
-
}
|
|
587
|
-
|
|
588
|
-
const hashedPassword = await HiSecure.hash(password);
|
|
589
|
-
|
|
590
|
-
const user = await User.create({
|
|
591
|
-
name,
|
|
592
|
-
email,
|
|
593
|
-
password: hashedPassword
|
|
594
|
-
});
|
|
595
|
-
|
|
596
|
-
const token = HiSecure.jwt.sign({
|
|
597
|
-
userId: user._id.toString(),
|
|
598
|
-
email: user.email,
|
|
599
|
-
name: user.name,
|
|
600
|
-
role: 'user'
|
|
601
|
-
},
|
|
602
|
-
JWT_OPTIONS
|
|
603
|
-
);
|
|
604
|
-
|
|
605
|
-
res.status(201).json({
|
|
606
|
-
message: 'User registered successfully',
|
|
607
|
-
token,
|
|
608
|
-
user: {
|
|
609
|
-
id: user._id,
|
|
610
|
-
name: user.name,
|
|
611
|
-
email: user.email
|
|
612
|
-
}
|
|
613
|
-
});
|
|
614
|
-
|
|
615
|
-
} catch (error) {
|
|
616
|
-
console.error('Registration error:', error);
|
|
617
|
-
res.status(500).json({
|
|
618
|
-
error: 'Registration failed',
|
|
619
|
-
details: error.message
|
|
620
|
-
});
|
|
617
|
+
const existingUser = await User.findOne({ email });
|
|
618
|
+
if (existingUser) {
|
|
619
|
+
return res.status(400).json({
|
|
620
|
+
success: false,
|
|
621
|
+
message: 'User already exists'
|
|
622
|
+
});
|
|
621
623
|
}
|
|
624
|
+
|
|
625
|
+
const hashedPassword = await HiSecure.hash(password);
|
|
626
|
+
|
|
627
|
+
const user = await User.create({
|
|
628
|
+
name,
|
|
629
|
+
email,
|
|
630
|
+
password: hashedPassword,
|
|
631
|
+
role: role || 'student',
|
|
632
|
+
hostel,
|
|
633
|
+
block,
|
|
634
|
+
room
|
|
635
|
+
});
|
|
636
|
+
|
|
637
|
+
return res.status(201).json({
|
|
638
|
+
success: true,
|
|
639
|
+
message: 'User registered successfully',
|
|
640
|
+
user: {
|
|
641
|
+
id: user._id,
|
|
642
|
+
name: user.name,
|
|
643
|
+
email: user.email,
|
|
644
|
+
role: user.role
|
|
645
|
+
}
|
|
646
|
+
});
|
|
647
|
+
} catch (error: any) {
|
|
648
|
+
return res.status(500).json({
|
|
649
|
+
success: false,
|
|
650
|
+
message: 'Registration failed',
|
|
651
|
+
error: error.message
|
|
652
|
+
});
|
|
653
|
+
}
|
|
622
654
|
};
|
|
623
655
|
|
|
656
|
+
|
|
624
657
|
</code></pre>
|
|
625
658
|
|
|
626
659
|
<hr/>
|
|
@@ -629,175 +662,104 @@ exports.registerUser = async(req, res) => {
|
|
|
629
662
|
|
|
630
663
|
<pre><code>
|
|
631
664
|
|
|
632
|
-
exports.loginUser = async(req, res) => {
|
|
633
|
-
try {
|
|
634
|
-
const { email, password } = req.body;
|
|
635
|
-
|
|
636
|
-
const user = await User.findOne({ email });
|
|
637
|
-
if (!user) {
|
|
638
|
-
return res.status(401).json({
|
|
639
|
-
error: 'Invalid credentials'
|
|
640
|
-
});
|
|
641
|
-
}
|
|
642
|
-
|
|
643
|
-
const isValid = await HiSecure.verify(password, user.password);
|
|
644
|
-
if (!isValid) {
|
|
645
|
-
return res.status(401).json({
|
|
646
|
-
error: 'Invalid credentials'
|
|
647
|
-
});
|
|
648
|
-
}
|
|
649
|
-
|
|
650
|
-
const token = HiSecure.jwt.sign({
|
|
651
|
-
userId: user._id.toString(),
|
|
652
|
-
email: user.email,
|
|
653
|
-
name: user.name,
|
|
654
|
-
role: 'user'
|
|
655
|
-
},
|
|
656
|
-
JWT_OPTIONS
|
|
657
|
-
);
|
|
658
|
-
|
|
659
|
-
res.json({
|
|
660
|
-
message: 'Login successful',
|
|
661
|
-
token,
|
|
662
|
-
user: {
|
|
663
|
-
id: user._id,
|
|
664
|
-
name: user.name,
|
|
665
|
-
email: user.email
|
|
666
|
-
}
|
|
667
|
-
});
|
|
668
|
-
|
|
669
|
-
} catch (error) {
|
|
670
|
-
console.error('Login error:', error);
|
|
671
|
-
res.status(500).json({
|
|
672
|
-
error: 'Login failed',
|
|
673
|
-
details: error.message
|
|
674
|
-
});
|
|
675
|
-
}
|
|
676
|
-
};
|
|
677
665
|
|
|
678
|
-
|
|
666
|
+
export const login = async (req: Request, res: Response) => {
|
|
667
|
+
try {
|
|
668
|
+
const { email, password } = req.body;
|
|
679
669
|
|
|
680
|
-
|
|
670
|
+
const user = await User.findOne({ email });
|
|
671
|
+
if (!user) {
|
|
672
|
+
return res.status(401).json({
|
|
673
|
+
success: false,
|
|
674
|
+
message: 'Invalid credentials'
|
|
675
|
+
});
|
|
676
|
+
}
|
|
681
677
|
|
|
682
|
-
|
|
678
|
+
const isPasswordValid = await HiSecure.verify(password, user.password);
|
|
679
|
+
if (!isPasswordValid) {
|
|
680
|
+
return res.status(401).json({
|
|
681
|
+
success: false,
|
|
682
|
+
message: 'Invalid credentials'
|
|
683
|
+
});
|
|
684
|
+
}
|
|
683
685
|
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
686
|
+
const token = HiSecure.jwt.sign({
|
|
687
|
+
userId: user._id.toString(),
|
|
688
|
+
email: user.email,
|
|
689
|
+
role: user.role
|
|
690
|
+
});
|
|
691
|
+
|
|
692
|
+
return res.status(200).json({
|
|
693
|
+
success: true,
|
|
694
|
+
message: 'Login successful',
|
|
695
|
+
token,
|
|
696
|
+
user: {
|
|
697
|
+
id: user._id,
|
|
698
|
+
name: user.name,
|
|
699
|
+
email: user.email,
|
|
700
|
+
role: user.role
|
|
701
|
+
}
|
|
702
|
+
});
|
|
703
|
+
} catch (error: any) {
|
|
704
|
+
return res.status(500).json({
|
|
705
|
+
success: false,
|
|
706
|
+
message: 'Login failed',
|
|
707
|
+
error: error.message
|
|
708
|
+
});
|
|
689
709
|
}
|
|
690
|
-
|
|
691
|
-
</code></pre>
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
<pre>
|
|
695
|
-
<code>
|
|
696
|
-
const router = express.Router();
|
|
697
|
-
router.post(
|
|
698
|
-
'/register',
|
|
699
|
-
|
|
700
|
-
HiSecure.validate([
|
|
701
|
-
body("name")
|
|
702
|
-
.notEmpty().withMessage("Name is required")
|
|
703
|
-
.isLength({ min: 3 }).withMessage("Name must be at least 3 characters"),
|
|
704
|
-
|
|
705
|
-
body("email")
|
|
706
|
-
.notEmpty().withMessage("Email is required")
|
|
707
|
-
.isEmail().withMessage("Invalid email format"),
|
|
708
|
-
|
|
709
|
-
body("password")
|
|
710
|
-
.notEmpty().withMessage("Password is required")
|
|
711
|
-
.isLength({ min: 6 }).withMessage("Password must be at least 6 characters"),
|
|
712
|
-
]),
|
|
713
|
-
|
|
714
|
-
registerUser
|
|
715
|
-
);
|
|
716
|
-
|
|
717
|
-
router.post(
|
|
718
|
-
'/login',
|
|
719
|
-
|
|
720
|
-
HiSecure.validate([
|
|
721
|
-
body("email")
|
|
722
|
-
.notEmpty().withMessage("Email is required")
|
|
723
|
-
.isEmail().withMessage("Invalid email format"),
|
|
724
|
-
|
|
725
|
-
body("password")
|
|
726
|
-
.notEmpty().withMessage("Password is required")
|
|
727
|
-
]),
|
|
728
|
-
|
|
729
|
-
HiSecure.rateLimit({ max: 5, windowMs: 15 * 60 * 1000 }),
|
|
730
|
-
|
|
731
|
-
loginUser
|
|
732
|
-
);
|
|
733
|
-
|
|
734
|
-
router.get(
|
|
735
|
-
'/profile',
|
|
736
|
-
HiSecure.auth({ required: true }),
|
|
737
|
-
getProfile
|
|
738
|
-
);
|
|
710
|
+
};
|
|
739
711
|
|
|
740
|
-
|
|
741
|
-
router.post('/create', HiSecure.auth({ required: true }), createTask)
|
|
742
|
-
router.get('/get', HiSecure.auth({ required: true }), getTask)
|
|
743
|
-
router.put('/:id', HiSecure.auth({ required: true }), updateTask)
|
|
744
|
-
router.psot('/health',heatlh);
|
|
745
|
-
</code>
|
|
746
|
-
</pre>
|
|
712
|
+
</code></pre>
|
|
747
713
|
|
|
748
714
|
<hr/>
|
|
749
715
|
|
|
750
|
-
<h3>JWT Options (Optional)</h3>
|
|
751
716
|
|
|
752
|
-
<p>
|
|
753
|
-
HiSecure does not require JWT options for most use cases.
|
|
754
|
-
Default configuration provided during initialization is sufficient.
|
|
755
|
-
</p>
|
|
756
717
|
|
|
757
|
-
<
|
|
758
|
-
auth: {
|
|
759
|
-
enabled: true,
|
|
760
|
-
jwtSecret: process.env.JWT_SECRET,
|
|
761
|
-
jwtExpiresIn: "1d"
|
|
762
|
-
}
|
|
763
|
-
});
|
|
764
|
-
</code></pre>
|
|
718
|
+
<h3>Role-Based Protected Routes</h3>
|
|
765
719
|
|
|
766
|
-
<
|
|
767
|
-
|
|
768
|
-
|
|
720
|
+
<pre><code>
|
|
721
|
+
|
|
722
|
+
const router = Router();
|
|
769
723
|
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
expiresIn: "7d"
|
|
780
|
-
}
|
|
724
|
+
router.post(
|
|
725
|
+
"/",
|
|
726
|
+
HiSecure.auth({ roles: ["student", "admin"] }),
|
|
727
|
+
HiSecure.validate([
|
|
728
|
+
body("title").notEmpty(),
|
|
729
|
+
body("description").notEmpty(),
|
|
730
|
+
body("category").notEmpty()
|
|
731
|
+
]),
|
|
732
|
+
createIssue
|
|
781
733
|
);
|
|
782
|
-
</code></pre>
|
|
783
734
|
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
735
|
+
router.get(
|
|
736
|
+
"/my",
|
|
737
|
+
HiSecure.auth({ required: true }),
|
|
738
|
+
getMyIssues
|
|
739
|
+
);
|
|
787
740
|
|
|
788
|
-
|
|
741
|
+
router.post(
|
|
742
|
+
"/assign",
|
|
743
|
+
HiSecure.auth({ roles: ["admin"] }),
|
|
744
|
+
assignIssue
|
|
745
|
+
);
|
|
789
746
|
|
|
790
|
-
|
|
747
|
+
router.put(
|
|
748
|
+
"/status",
|
|
749
|
+
HiSecure.auth({ roles: ["staff", "admin"] }),
|
|
750
|
+
updateIssueStatus
|
|
751
|
+
);
|
|
791
752
|
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
<li>Authorization is enforced using JWT payload and roles</li>
|
|
798
|
-
</ul>
|
|
753
|
+
router.put(
|
|
754
|
+
"/close",
|
|
755
|
+
HiSecure.auth({ required: true }),
|
|
756
|
+
closeIssue
|
|
757
|
+
);
|
|
799
758
|
|
|
800
|
-
|
|
759
|
+
export default router;
|
|
760
|
+
|
|
761
|
+
|
|
762
|
+
</code></pre>
|
|
801
763
|
|
|
802
764
|
|
|
803
765
|
<h2>Summary</h2>
|
|
@@ -818,4 +780,4 @@ It focuses on correctness, safety and developer productivity.
|
|
|
818
780
|
<p align="center">
|
|
819
781
|
Advanced patterns, RBAC strategies, adapter extensions and deployment guides
|
|
820
782
|
will be added over time.
|
|
821
|
-
</p>
|
|
783
|
+
</p>
|