aaspai-authx 0.1.3 → 0.1.5
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/express/index.cjs +425 -30
- package/dist/express/index.cjs.map +1 -1
- package/dist/express/index.js +425 -30
- package/dist/express/index.js.map +1 -1
- package/dist/index.cjs +425 -30
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +425 -30
- package/dist/index.js.map +1 -1
- package/dist/nest/index.cjs +425 -30
- package/dist/nest/index.cjs.map +1 -1
- package/dist/nest/index.js +425 -30
- package/dist/nest/index.js.map +1 -1
- package/package.json +1 -1
package/dist/nest/index.js
CHANGED
|
@@ -524,7 +524,7 @@ var AuthAdminService = class {
|
|
|
524
524
|
}
|
|
525
525
|
async updateUserPassword(userId, newPassword) {
|
|
526
526
|
const hashed = await bcrypt.hash(newPassword, 10);
|
|
527
|
-
await OrgUser.findOneAndUpdate({ id: userId }, {
|
|
527
|
+
await OrgUser.findOneAndUpdate({ id: userId }, { passwordHash: hashed });
|
|
528
528
|
}
|
|
529
529
|
// -------------------------------------------------------------------
|
|
530
530
|
// ADMIN TOKEN (self-issued JWT)
|
|
@@ -577,7 +577,6 @@ var EmailService = class {
|
|
|
577
577
|
return jwt3.verify(token, process.env.EMAIL_JWT_SECRET);
|
|
578
578
|
}
|
|
579
579
|
async send(to, subject, html) {
|
|
580
|
-
console.log("[EmailService] Attempting to send:", { to, subject });
|
|
581
580
|
try {
|
|
582
581
|
const info = await this.transporter.sendMail({
|
|
583
582
|
from: process.env.EMAIL_FROM,
|
|
@@ -605,18 +604,6 @@ var EmailService = class {
|
|
|
605
604
|
}
|
|
606
605
|
}
|
|
607
606
|
canSend(lastEmailSent) {
|
|
608
|
-
console.log(
|
|
609
|
-
process.env.EMAIL_PASSWORD,
|
|
610
|
-
"pssword",
|
|
611
|
-
process.env.EMAIL_USER,
|
|
612
|
-
"user",
|
|
613
|
-
process.env.EMAIL_SECURE,
|
|
614
|
-
"secure",
|
|
615
|
-
process.env.EMAIL_PORT,
|
|
616
|
-
"porat",
|
|
617
|
-
process.env.EMAIL_HOST,
|
|
618
|
-
"hosat"
|
|
619
|
-
);
|
|
620
607
|
const now = Date.now();
|
|
621
608
|
const windowStart = now - this.WINDOW_MINUTES * 60 * 1e3;
|
|
622
609
|
const emailsInWindow = (lastEmailSent || []).map((d) => new Date(d)).filter((d) => d.getTime() >= windowStart);
|
|
@@ -630,6 +617,386 @@ var EmailService = class {
|
|
|
630
617
|
}
|
|
631
618
|
};
|
|
632
619
|
|
|
620
|
+
// src/templates/email.templates.ts
|
|
621
|
+
var colors = {
|
|
622
|
+
background: "#0a0a0a",
|
|
623
|
+
cardBackground: "#111111",
|
|
624
|
+
cardBorder: "#1a1a1a",
|
|
625
|
+
accent: "#ffffff",
|
|
626
|
+
accentMuted: "rgba(255, 255, 255, 0.9)",
|
|
627
|
+
textPrimary: "#ffffff",
|
|
628
|
+
textSecondary: "rgba(255, 255, 255, 0.7)",
|
|
629
|
+
textMuted: "rgba(255, 255, 255, 0.5)",
|
|
630
|
+
divider: "rgba(255, 255, 255, 0.1)",
|
|
631
|
+
subtle: "#161616",
|
|
632
|
+
highlight: "rgba(255, 255, 255, 0.05)"
|
|
633
|
+
};
|
|
634
|
+
var styles = {
|
|
635
|
+
wrapper: `
|
|
636
|
+
margin: 0;
|
|
637
|
+
padding: 40px 20px;
|
|
638
|
+
background-color: ${colors.background};
|
|
639
|
+
background-image:
|
|
640
|
+
radial-gradient(ellipse at top, rgba(255,255,255,0.03) 0%, transparent 50%),
|
|
641
|
+
radial-gradient(ellipse at bottom, rgba(255,255,255,0.02) 0%, transparent 50%);
|
|
642
|
+
min-height: 100vh;
|
|
643
|
+
`,
|
|
644
|
+
container: `
|
|
645
|
+
max-width: 520px;
|
|
646
|
+
margin: 0 auto;
|
|
647
|
+
font-family: -apple-system, BlinkMacSystemFont, 'SF Pro Display', 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
|
|
648
|
+
color: ${colors.textPrimary};
|
|
649
|
+
line-height: 1.7;
|
|
650
|
+
`,
|
|
651
|
+
card: `
|
|
652
|
+
background-color: ${colors.cardBackground};
|
|
653
|
+
border: 1px solid ${colors.cardBorder};
|
|
654
|
+
border-radius: 16px;
|
|
655
|
+
overflow: hidden;
|
|
656
|
+
box-shadow:
|
|
657
|
+
0 0 0 1px rgba(255,255,255,0.05),
|
|
658
|
+
0 20px 50px -20px rgba(0,0,0,0.5),
|
|
659
|
+
0 30px 60px -30px rgba(0,0,0,0.3);
|
|
660
|
+
`,
|
|
661
|
+
header: `
|
|
662
|
+
padding: 48px 40px 32px;
|
|
663
|
+
text-align: center;
|
|
664
|
+
border-bottom: 1px solid ${colors.divider};
|
|
665
|
+
`,
|
|
666
|
+
iconWrapper: `
|
|
667
|
+
width: 64px;
|
|
668
|
+
height: 64px;
|
|
669
|
+
margin: 0 auto 24px;
|
|
670
|
+
background: linear-gradient(135deg, rgba(255,255,255,0.1) 0%, rgba(255,255,255,0.05) 100%);
|
|
671
|
+
border: 1px solid rgba(255,255,255,0.1);
|
|
672
|
+
border-radius: 16px;
|
|
673
|
+
display: flex;
|
|
674
|
+
align-items: center;
|
|
675
|
+
justify-content: center;
|
|
676
|
+
font-size: 28px;
|
|
677
|
+
`,
|
|
678
|
+
headerTitle: `
|
|
679
|
+
color: ${colors.textPrimary};
|
|
680
|
+
margin: 0;
|
|
681
|
+
font-size: 24px;
|
|
682
|
+
font-weight: 600;
|
|
683
|
+
letter-spacing: -0.5px;
|
|
684
|
+
`,
|
|
685
|
+
headerSubtitle: `
|
|
686
|
+
color: ${colors.textMuted};
|
|
687
|
+
margin: 8px 0 0;
|
|
688
|
+
font-size: 14px;
|
|
689
|
+
font-weight: 400;
|
|
690
|
+
`,
|
|
691
|
+
body: `
|
|
692
|
+
padding: 40px;
|
|
693
|
+
`,
|
|
694
|
+
greeting: `
|
|
695
|
+
margin: 0 0 24px;
|
|
696
|
+
color: ${colors.textPrimary};
|
|
697
|
+
font-size: 18px;
|
|
698
|
+
font-weight: 500;
|
|
699
|
+
`,
|
|
700
|
+
paragraph: `
|
|
701
|
+
margin: 0 0 20px;
|
|
702
|
+
color: ${colors.textSecondary};
|
|
703
|
+
font-size: 15px;
|
|
704
|
+
line-height: 1.7;
|
|
705
|
+
`,
|
|
706
|
+
buttonWrapper: `
|
|
707
|
+
text-align: center;
|
|
708
|
+
margin: 32px 0;
|
|
709
|
+
`,
|
|
710
|
+
button: `
|
|
711
|
+
display: inline-block;
|
|
712
|
+
background-color: ${colors.accent};
|
|
713
|
+
color: #000000 !important;
|
|
714
|
+
text-decoration: none;
|
|
715
|
+
padding: 14px 36px;
|
|
716
|
+
border-radius: 8px;
|
|
717
|
+
font-weight: 600;
|
|
718
|
+
font-size: 14px;
|
|
719
|
+
letter-spacing: 0.3px;
|
|
720
|
+
transition: all 0.2s ease;
|
|
721
|
+
`,
|
|
722
|
+
secondaryButton: `
|
|
723
|
+
display: inline-block;
|
|
724
|
+
background-color: transparent;
|
|
725
|
+
color: ${colors.textPrimary} !important;
|
|
726
|
+
text-decoration: none;
|
|
727
|
+
padding: 12px 28px;
|
|
728
|
+
border-radius: 8px;
|
|
729
|
+
font-weight: 500;
|
|
730
|
+
font-size: 14px;
|
|
731
|
+
border: 1px solid ${colors.divider};
|
|
732
|
+
`,
|
|
733
|
+
infoCard: `
|
|
734
|
+
background-color: ${colors.subtle};
|
|
735
|
+
border: 1px solid ${colors.divider};
|
|
736
|
+
border-radius: 12px;
|
|
737
|
+
padding: 20px 24px;
|
|
738
|
+
margin: 28px 0;
|
|
739
|
+
`,
|
|
740
|
+
infoCardTitle: `
|
|
741
|
+
margin: 0 0 12px;
|
|
742
|
+
color: ${colors.textPrimary};
|
|
743
|
+
font-size: 13px;
|
|
744
|
+
font-weight: 600;
|
|
745
|
+
text-transform: uppercase;
|
|
746
|
+
letter-spacing: 0.5px;
|
|
747
|
+
`,
|
|
748
|
+
infoCardText: `
|
|
749
|
+
margin: 0;
|
|
750
|
+
color: ${colors.textSecondary};
|
|
751
|
+
font-size: 14px;
|
|
752
|
+
line-height: 1.6;
|
|
753
|
+
`,
|
|
754
|
+
warningCard: `
|
|
755
|
+
background: linear-gradient(135deg, rgba(255,180,0,0.1) 0%, rgba(255,140,0,0.05) 100%);
|
|
756
|
+
border: 1px solid rgba(255,180,0,0.2);
|
|
757
|
+
border-radius: 12px;
|
|
758
|
+
padding: 20px 24px;
|
|
759
|
+
margin: 28px 0;
|
|
760
|
+
`,
|
|
761
|
+
warningCardTitle: `
|
|
762
|
+
margin: 0 0 12px;
|
|
763
|
+
color: #ffc107;
|
|
764
|
+
font-size: 13px;
|
|
765
|
+
font-weight: 600;
|
|
766
|
+
text-transform: uppercase;
|
|
767
|
+
letter-spacing: 0.5px;
|
|
768
|
+
`,
|
|
769
|
+
warningCardText: `
|
|
770
|
+
margin: 0;
|
|
771
|
+
color: rgba(255,255,255,0.7);
|
|
772
|
+
font-size: 14px;
|
|
773
|
+
line-height: 1.6;
|
|
774
|
+
`,
|
|
775
|
+
successCard: `
|
|
776
|
+
background: linear-gradient(135deg, rgba(0,255,150,0.1) 0%, rgba(0,200,100,0.05) 100%);
|
|
777
|
+
border: 1px solid rgba(0,255,150,0.2);
|
|
778
|
+
border-radius: 12px;
|
|
779
|
+
padding: 20px 24px;
|
|
780
|
+
margin: 28px 0;
|
|
781
|
+
`,
|
|
782
|
+
successCardTitle: `
|
|
783
|
+
margin: 0 0 12px;
|
|
784
|
+
color: #00ff96;
|
|
785
|
+
font-size: 13px;
|
|
786
|
+
font-weight: 600;
|
|
787
|
+
text-transform: uppercase;
|
|
788
|
+
letter-spacing: 0.5px;
|
|
789
|
+
`,
|
|
790
|
+
linkSection: `
|
|
791
|
+
margin: 32px 0;
|
|
792
|
+
padding: 20px;
|
|
793
|
+
background-color: ${colors.subtle};
|
|
794
|
+
border-radius: 8px;
|
|
795
|
+
border: 1px solid ${colors.divider};
|
|
796
|
+
`,
|
|
797
|
+
linkLabel: `
|
|
798
|
+
margin: 0 0 8px;
|
|
799
|
+
color: ${colors.textMuted};
|
|
800
|
+
font-size: 12px;
|
|
801
|
+
text-transform: uppercase;
|
|
802
|
+
letter-spacing: 0.5px;
|
|
803
|
+
`,
|
|
804
|
+
linkText: `
|
|
805
|
+
word-break: break-all;
|
|
806
|
+
color: ${colors.textSecondary};
|
|
807
|
+
font-size: 13px;
|
|
808
|
+
font-family: 'SF Mono', 'Monaco', 'Inconsolata', 'Roboto Mono', monospace;
|
|
809
|
+
margin: 0;
|
|
810
|
+
`,
|
|
811
|
+
divider: `
|
|
812
|
+
border: none;
|
|
813
|
+
border-top: 1px solid ${colors.divider};
|
|
814
|
+
margin: 32px 0;
|
|
815
|
+
`,
|
|
816
|
+
footer: `
|
|
817
|
+
padding: 24px 40px 32px;
|
|
818
|
+
text-align: center;
|
|
819
|
+
border-top: 1px solid ${colors.divider};
|
|
820
|
+
`,
|
|
821
|
+
footerText: `
|
|
822
|
+
margin: 0;
|
|
823
|
+
color: ${colors.textMuted};
|
|
824
|
+
font-size: 12px;
|
|
825
|
+
line-height: 1.8;
|
|
826
|
+
`,
|
|
827
|
+
footerLink: `
|
|
828
|
+
color: ${colors.textSecondary};
|
|
829
|
+
text-decoration: none;
|
|
830
|
+
`,
|
|
831
|
+
badge: `
|
|
832
|
+
display: inline-block;
|
|
833
|
+
background-color: rgba(255,255,255,0.1);
|
|
834
|
+
color: ${colors.textSecondary};
|
|
835
|
+
padding: 4px 12px;
|
|
836
|
+
border-radius: 20px;
|
|
837
|
+
font-size: 12px;
|
|
838
|
+
font-weight: 500;
|
|
839
|
+
letter-spacing: 0.3px;
|
|
840
|
+
`,
|
|
841
|
+
listItem: `
|
|
842
|
+
color: ${colors.textSecondary};
|
|
843
|
+
font-size: 14px;
|
|
844
|
+
margin: 8px 0;
|
|
845
|
+
padding-left: 8px;
|
|
846
|
+
`,
|
|
847
|
+
metaRow: `
|
|
848
|
+
display: flex;
|
|
849
|
+
justify-content: space-between;
|
|
850
|
+
padding: 12px 0;
|
|
851
|
+
border-bottom: 1px solid ${colors.divider};
|
|
852
|
+
`,
|
|
853
|
+
metaLabel: `
|
|
854
|
+
color: ${colors.textMuted};
|
|
855
|
+
font-size: 13px;
|
|
856
|
+
`,
|
|
857
|
+
metaValue: `
|
|
858
|
+
color: ${colors.textPrimary};
|
|
859
|
+
font-size: 13px;
|
|
860
|
+
font-weight: 500;
|
|
861
|
+
`
|
|
862
|
+
};
|
|
863
|
+
function buildVerificationEmailTemplate(data) {
|
|
864
|
+
const { firstName, verificationUrl, expiresIn } = data;
|
|
865
|
+
return `
|
|
866
|
+
<!DOCTYPE html>
|
|
867
|
+
<html lang="en">
|
|
868
|
+
<head>
|
|
869
|
+
<meta charset="UTF-8">
|
|
870
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
871
|
+
<meta name="color-scheme" content="dark">
|
|
872
|
+
<meta name="supported-color-schemes" content="dark">
|
|
873
|
+
<title>Verify Your Email</title>
|
|
874
|
+
<!--[if mso]>
|
|
875
|
+
<style type="text/css">
|
|
876
|
+
body, table, td {font-family: Arial, Helvetica, sans-serif !important;}
|
|
877
|
+
</style>
|
|
878
|
+
<![endif]-->
|
|
879
|
+
</head>
|
|
880
|
+
<body style="${styles.wrapper}">
|
|
881
|
+
<div style="${styles.container}">
|
|
882
|
+
<div style="${styles.card}">
|
|
883
|
+
<!-- Header -->
|
|
884
|
+
<div style="${styles.header}">
|
|
885
|
+
<div style="${styles.iconWrapper}">
|
|
886
|
+
\u2709\uFE0F
|
|
887
|
+
</div>
|
|
888
|
+
<h1 style="${styles.headerTitle}">Verify your email</h1>
|
|
889
|
+
<p style="${styles.headerSubtitle}">One quick step to get started</p>
|
|
890
|
+
</div>
|
|
891
|
+
|
|
892
|
+
<!-- Body -->
|
|
893
|
+
<div style="${styles.body}">
|
|
894
|
+
<p style="${styles.greeting}">Hi ${firstName},</p>
|
|
895
|
+
|
|
896
|
+
<p style="${styles.paragraph}">
|
|
897
|
+
Thanks for signing up. To complete your registration and unlock all features,
|
|
898
|
+
please verify your email address by clicking the button below.
|
|
899
|
+
</p>
|
|
900
|
+
|
|
901
|
+
<div style="${styles.buttonWrapper}">
|
|
902
|
+
<a href="${verificationUrl}" style="${styles.button}" target="_blank">
|
|
903
|
+
Verify Email Address
|
|
904
|
+
</a>
|
|
905
|
+
</div>
|
|
906
|
+
|
|
907
|
+
<div style="${styles.infoCard}">
|
|
908
|
+
<p style="${styles.infoCardTitle}">\u23F1 Time Sensitive</p>
|
|
909
|
+
<p style="${styles.infoCardText}">
|
|
910
|
+
This verification link will expire in <strong>${expiresIn}</strong>.
|
|
911
|
+
If you didn't create an account, you can safely ignore this email.
|
|
912
|
+
</p>
|
|
913
|
+
</div>
|
|
914
|
+
</div>
|
|
915
|
+
|
|
916
|
+
<!-- Footer -->
|
|
917
|
+
<div style="${styles.footer}">
|
|
918
|
+
<p style="${styles.footerText}">
|
|
919
|
+
This is an automated message \u2014 please do not reply.<br>
|
|
920
|
+
\xA9 ${(/* @__PURE__ */ new Date()).getFullYear()} All rights reserved.
|
|
921
|
+
</p>
|
|
922
|
+
</div>
|
|
923
|
+
</div>
|
|
924
|
+
</div>
|
|
925
|
+
</body>
|
|
926
|
+
</html>
|
|
927
|
+
`;
|
|
928
|
+
}
|
|
929
|
+
function buildResetPasswordEmailTemplate(data) {
|
|
930
|
+
const { firstName, resetUrl, expiresIn } = data;
|
|
931
|
+
return `
|
|
932
|
+
<!DOCTYPE html>
|
|
933
|
+
<html lang="en">
|
|
934
|
+
<head>
|
|
935
|
+
<meta charset="UTF-8">
|
|
936
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
937
|
+
<meta name="color-scheme" content="dark">
|
|
938
|
+
<meta name="supported-color-schemes" content="dark">
|
|
939
|
+
<title>Reset Your Password</title>
|
|
940
|
+
</head>
|
|
941
|
+
<body style="${styles.wrapper}">
|
|
942
|
+
<div style="${styles.container}">
|
|
943
|
+
<div style="${styles.card}">
|
|
944
|
+
<!-- Header -->
|
|
945
|
+
<div style="${styles.header}">
|
|
946
|
+
<div style="${styles.iconWrapper}">
|
|
947
|
+
\u{1F510}
|
|
948
|
+
</div>
|
|
949
|
+
<h1 style="${styles.headerTitle}">Reset your password</h1>
|
|
950
|
+
<p style="${styles.headerSubtitle}">We received a reset request</p>
|
|
951
|
+
</div>
|
|
952
|
+
|
|
953
|
+
<!-- Body -->
|
|
954
|
+
<div style="${styles.body}">
|
|
955
|
+
<p style="${styles.greeting}">Hi ${firstName},</p>
|
|
956
|
+
|
|
957
|
+
<p style="${styles.paragraph}">
|
|
958
|
+
We received a request to reset the password for your account.
|
|
959
|
+
Click the button below to create a new password.
|
|
960
|
+
</p>
|
|
961
|
+
|
|
962
|
+
<div style="${styles.buttonWrapper}">
|
|
963
|
+
<a href="${resetUrl}" style="${styles.button}" target="_blank">
|
|
964
|
+
Reset Password
|
|
965
|
+
</a>
|
|
966
|
+
</div>
|
|
967
|
+
|
|
968
|
+
<div style="${styles.warningCard}">
|
|
969
|
+
<p style="${styles.warningCardTitle}">\u26A0\uFE0F Security Notice</p>
|
|
970
|
+
<p style="${styles.warningCardText}">
|
|
971
|
+
\u2022 This link expires in <strong>${expiresIn}</strong><br>
|
|
972
|
+
\u2022 This link can only be used once<br>
|
|
973
|
+
\u2022 If you didn't request this, ignore this email
|
|
974
|
+
</p>
|
|
975
|
+
</div>
|
|
976
|
+
|
|
977
|
+
<hr style="${styles.divider}" />
|
|
978
|
+
|
|
979
|
+
<p style="${styles.paragraph}; font-size: 13px; color: ${colors.textMuted};">
|
|
980
|
+
<strong>Didn't request this?</strong><br>
|
|
981
|
+
Your password remains unchanged. If you're concerned about your account
|
|
982
|
+
security, please contact our support team immediately.
|
|
983
|
+
</p>
|
|
984
|
+
</div>
|
|
985
|
+
|
|
986
|
+
<!-- Footer -->
|
|
987
|
+
<div style="${styles.footer}">
|
|
988
|
+
<p style="${styles.footerText}">
|
|
989
|
+
This is an automated message \u2014 please do not reply.<br>
|
|
990
|
+
\xA9 ${(/* @__PURE__ */ new Date()).getFullYear()} All rights reserved.
|
|
991
|
+
</p>
|
|
992
|
+
</div>
|
|
993
|
+
</div>
|
|
994
|
+
</div>
|
|
995
|
+
</body>
|
|
996
|
+
</html>
|
|
997
|
+
`;
|
|
998
|
+
}
|
|
999
|
+
|
|
633
1000
|
// src/express/auth.routes.ts
|
|
634
1001
|
function createAuthRouter(options = {}) {
|
|
635
1002
|
const googleClientId = process.env.GOOGLE_CLIENT_ID;
|
|
@@ -661,10 +1028,8 @@ function createAuthRouter(options = {}) {
|
|
|
661
1028
|
);
|
|
662
1029
|
r.post("/login", validateLogin, async (req, res) => {
|
|
663
1030
|
const { email: emailAddress, password } = req.body || {};
|
|
664
|
-
console.log(emailAddress, password, "body");
|
|
665
1031
|
try {
|
|
666
1032
|
const user = await OrgUser.findOne({ email: emailAddress }).select("+password").lean();
|
|
667
|
-
console.log(user, "user");
|
|
668
1033
|
if (!user) {
|
|
669
1034
|
return res.status(400).json({
|
|
670
1035
|
error: "Invalid email or password",
|
|
@@ -738,10 +1103,20 @@ function createAuthRouter(options = {}) {
|
|
|
738
1103
|
emailService: email,
|
|
739
1104
|
user,
|
|
740
1105
|
subject: "Verify your email",
|
|
741
|
-
html: buildVerificationTemplate(
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
)
|
|
1106
|
+
// html: buildVerificationTemplate(
|
|
1107
|
+
// email.sign({ userId: kcUser.id, email: kcUser.email }),
|
|
1108
|
+
// options,
|
|
1109
|
+
// ),
|
|
1110
|
+
html: buildVerificationEmailTemplate({
|
|
1111
|
+
firstName: user.firstName,
|
|
1112
|
+
verificationUrl: `${getFrontendBaseUrl(options)}/verify-email?token=${email.sign(
|
|
1113
|
+
{
|
|
1114
|
+
userId: user.id,
|
|
1115
|
+
email: user.email
|
|
1116
|
+
}
|
|
1117
|
+
)}`,
|
|
1118
|
+
expiresIn: "1 hour"
|
|
1119
|
+
})
|
|
745
1120
|
});
|
|
746
1121
|
if (emailResult.rateLimited) {
|
|
747
1122
|
return res.status(429).json({
|
|
@@ -821,7 +1196,17 @@ function createAuthRouter(options = {}) {
|
|
|
821
1196
|
emailService: email,
|
|
822
1197
|
user,
|
|
823
1198
|
subject: "Verify your email",
|
|
824
|
-
html: buildVerificationTemplate(token, options)
|
|
1199
|
+
// html: buildVerificationTemplate(token, options),
|
|
1200
|
+
html: buildVerificationEmailTemplate({
|
|
1201
|
+
firstName: user.firstName,
|
|
1202
|
+
verificationUrl: `${getFrontendBaseUrl(options)}/verify-email?token=${email.sign(
|
|
1203
|
+
{
|
|
1204
|
+
userId: user.id,
|
|
1205
|
+
email: user.email
|
|
1206
|
+
}
|
|
1207
|
+
)}`,
|
|
1208
|
+
expiresIn: "1 hour"
|
|
1209
|
+
})
|
|
825
1210
|
});
|
|
826
1211
|
if (resendResult.rateLimited) {
|
|
827
1212
|
return res.status(429).json({
|
|
@@ -850,7 +1235,17 @@ function createAuthRouter(options = {}) {
|
|
|
850
1235
|
emailService: email,
|
|
851
1236
|
user,
|
|
852
1237
|
subject: "Reset password",
|
|
853
|
-
html: buildResetTemplate(resetToken, options)
|
|
1238
|
+
// html: buildResetTemplate(resetToken, options),
|
|
1239
|
+
html: buildResetPasswordEmailTemplate({
|
|
1240
|
+
firstName: user.firstName,
|
|
1241
|
+
resetUrl: `${getFrontendBaseUrl(options)}/reset-password?token=${email.sign(
|
|
1242
|
+
{
|
|
1243
|
+
userId: user.id,
|
|
1244
|
+
email: user.email
|
|
1245
|
+
}
|
|
1246
|
+
)}`,
|
|
1247
|
+
expiresIn: "1 hour"
|
|
1248
|
+
})
|
|
854
1249
|
});
|
|
855
1250
|
if (resetResult.rateLimited) {
|
|
856
1251
|
return res.status(429).json({
|
|
@@ -863,9 +1258,16 @@ function createAuthRouter(options = {}) {
|
|
|
863
1258
|
});
|
|
864
1259
|
r.post("/reset-password", validateResetPassword, async (req, res) => {
|
|
865
1260
|
const { token, newPassword } = req.body || {};
|
|
1261
|
+
if (!token || !newPassword) {
|
|
1262
|
+
return res.status(400).json({
|
|
1263
|
+
ok: false,
|
|
1264
|
+
error: "Token and new password are required",
|
|
1265
|
+
code: "MISSING_FIELDS"
|
|
1266
|
+
});
|
|
1267
|
+
}
|
|
866
1268
|
try {
|
|
867
1269
|
const payload = email.verify(token);
|
|
868
|
-
const user = await OrgUser.findOne({
|
|
1270
|
+
const user = await OrgUser.findOne({ id: payload.userId });
|
|
869
1271
|
if (!user) {
|
|
870
1272
|
return res.status(404).json({ ok: false, error: "User not found" });
|
|
871
1273
|
}
|
|
@@ -1256,12 +1658,6 @@ function respondWithKeycloakError(res, err, fallback, status = 400) {
|
|
|
1256
1658
|
const description = err?.response?.data?.error_description || err?.response?.data?.errorMessage || err?.message || fallback;
|
|
1257
1659
|
return res.status(status).json({ ok: false, error: description });
|
|
1258
1660
|
}
|
|
1259
|
-
function buildVerificationTemplate(token, options) {
|
|
1260
|
-
return `<a href="${getFrontendBaseUrl(options)}/auth/verify-email?token=${token}">Verify</a>`;
|
|
1261
|
-
}
|
|
1262
|
-
function buildResetTemplate(token, options) {
|
|
1263
|
-
return `<a href="${getFrontendBaseUrl(options)}/auth/reset-password?token=${token}">Reset</a>`;
|
|
1264
|
-
}
|
|
1265
1661
|
function getFrontendBaseUrl(options) {
|
|
1266
1662
|
if (options.frontendBaseUrl)
|
|
1267
1663
|
return options.frontendBaseUrl.replace(/\/$/, "");
|
|
@@ -1279,7 +1675,6 @@ async function sendRateLimitedEmail({
|
|
|
1279
1675
|
if (!can.ok) {
|
|
1280
1676
|
return { rateLimited: true, waitMs: can.waitMs };
|
|
1281
1677
|
}
|
|
1282
|
-
console.log(can, "can");
|
|
1283
1678
|
await emailService.send(user.email, subject, html);
|
|
1284
1679
|
user.lastEmailSent = [...user.lastEmailSent || [], /* @__PURE__ */ new Date()];
|
|
1285
1680
|
await user.save();
|