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/express/index.cjs
CHANGED
|
@@ -562,7 +562,7 @@ var AuthAdminService = class {
|
|
|
562
562
|
}
|
|
563
563
|
async updateUserPassword(userId, newPassword) {
|
|
564
564
|
const hashed = await import_bcrypt.default.hash(newPassword, 10);
|
|
565
|
-
await OrgUser.findOneAndUpdate({ id: userId }, {
|
|
565
|
+
await OrgUser.findOneAndUpdate({ id: userId }, { passwordHash: hashed });
|
|
566
566
|
}
|
|
567
567
|
// -------------------------------------------------------------------
|
|
568
568
|
// ADMIN TOKEN (self-issued JWT)
|
|
@@ -615,7 +615,6 @@ var EmailService = class {
|
|
|
615
615
|
return import_jsonwebtoken3.default.verify(token, process.env.EMAIL_JWT_SECRET);
|
|
616
616
|
}
|
|
617
617
|
async send(to, subject, html) {
|
|
618
|
-
console.log("[EmailService] Attempting to send:", { to, subject });
|
|
619
618
|
try {
|
|
620
619
|
const info = await this.transporter.sendMail({
|
|
621
620
|
from: process.env.EMAIL_FROM,
|
|
@@ -643,18 +642,6 @@ var EmailService = class {
|
|
|
643
642
|
}
|
|
644
643
|
}
|
|
645
644
|
canSend(lastEmailSent) {
|
|
646
|
-
console.log(
|
|
647
|
-
process.env.EMAIL_PASSWORD,
|
|
648
|
-
"pssword",
|
|
649
|
-
process.env.EMAIL_USER,
|
|
650
|
-
"user",
|
|
651
|
-
process.env.EMAIL_SECURE,
|
|
652
|
-
"secure",
|
|
653
|
-
process.env.EMAIL_PORT,
|
|
654
|
-
"porat",
|
|
655
|
-
process.env.EMAIL_HOST,
|
|
656
|
-
"hosat"
|
|
657
|
-
);
|
|
658
645
|
const now = Date.now();
|
|
659
646
|
const windowStart = now - this.WINDOW_MINUTES * 60 * 1e3;
|
|
660
647
|
const emailsInWindow = (lastEmailSent || []).map((d) => new Date(d)).filter((d) => d.getTime() >= windowStart);
|
|
@@ -668,6 +655,386 @@ var EmailService = class {
|
|
|
668
655
|
}
|
|
669
656
|
};
|
|
670
657
|
|
|
658
|
+
// src/templates/email.templates.ts
|
|
659
|
+
var colors = {
|
|
660
|
+
background: "#0a0a0a",
|
|
661
|
+
cardBackground: "#111111",
|
|
662
|
+
cardBorder: "#1a1a1a",
|
|
663
|
+
accent: "#ffffff",
|
|
664
|
+
accentMuted: "rgba(255, 255, 255, 0.9)",
|
|
665
|
+
textPrimary: "#ffffff",
|
|
666
|
+
textSecondary: "rgba(255, 255, 255, 0.7)",
|
|
667
|
+
textMuted: "rgba(255, 255, 255, 0.5)",
|
|
668
|
+
divider: "rgba(255, 255, 255, 0.1)",
|
|
669
|
+
subtle: "#161616",
|
|
670
|
+
highlight: "rgba(255, 255, 255, 0.05)"
|
|
671
|
+
};
|
|
672
|
+
var styles = {
|
|
673
|
+
wrapper: `
|
|
674
|
+
margin: 0;
|
|
675
|
+
padding: 40px 20px;
|
|
676
|
+
background-color: ${colors.background};
|
|
677
|
+
background-image:
|
|
678
|
+
radial-gradient(ellipse at top, rgba(255,255,255,0.03) 0%, transparent 50%),
|
|
679
|
+
radial-gradient(ellipse at bottom, rgba(255,255,255,0.02) 0%, transparent 50%);
|
|
680
|
+
min-height: 100vh;
|
|
681
|
+
`,
|
|
682
|
+
container: `
|
|
683
|
+
max-width: 520px;
|
|
684
|
+
margin: 0 auto;
|
|
685
|
+
font-family: -apple-system, BlinkMacSystemFont, 'SF Pro Display', 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
|
|
686
|
+
color: ${colors.textPrimary};
|
|
687
|
+
line-height: 1.7;
|
|
688
|
+
`,
|
|
689
|
+
card: `
|
|
690
|
+
background-color: ${colors.cardBackground};
|
|
691
|
+
border: 1px solid ${colors.cardBorder};
|
|
692
|
+
border-radius: 16px;
|
|
693
|
+
overflow: hidden;
|
|
694
|
+
box-shadow:
|
|
695
|
+
0 0 0 1px rgba(255,255,255,0.05),
|
|
696
|
+
0 20px 50px -20px rgba(0,0,0,0.5),
|
|
697
|
+
0 30px 60px -30px rgba(0,0,0,0.3);
|
|
698
|
+
`,
|
|
699
|
+
header: `
|
|
700
|
+
padding: 48px 40px 32px;
|
|
701
|
+
text-align: center;
|
|
702
|
+
border-bottom: 1px solid ${colors.divider};
|
|
703
|
+
`,
|
|
704
|
+
iconWrapper: `
|
|
705
|
+
width: 64px;
|
|
706
|
+
height: 64px;
|
|
707
|
+
margin: 0 auto 24px;
|
|
708
|
+
background: linear-gradient(135deg, rgba(255,255,255,0.1) 0%, rgba(255,255,255,0.05) 100%);
|
|
709
|
+
border: 1px solid rgba(255,255,255,0.1);
|
|
710
|
+
border-radius: 16px;
|
|
711
|
+
display: flex;
|
|
712
|
+
align-items: center;
|
|
713
|
+
justify-content: center;
|
|
714
|
+
font-size: 28px;
|
|
715
|
+
`,
|
|
716
|
+
headerTitle: `
|
|
717
|
+
color: ${colors.textPrimary};
|
|
718
|
+
margin: 0;
|
|
719
|
+
font-size: 24px;
|
|
720
|
+
font-weight: 600;
|
|
721
|
+
letter-spacing: -0.5px;
|
|
722
|
+
`,
|
|
723
|
+
headerSubtitle: `
|
|
724
|
+
color: ${colors.textMuted};
|
|
725
|
+
margin: 8px 0 0;
|
|
726
|
+
font-size: 14px;
|
|
727
|
+
font-weight: 400;
|
|
728
|
+
`,
|
|
729
|
+
body: `
|
|
730
|
+
padding: 40px;
|
|
731
|
+
`,
|
|
732
|
+
greeting: `
|
|
733
|
+
margin: 0 0 24px;
|
|
734
|
+
color: ${colors.textPrimary};
|
|
735
|
+
font-size: 18px;
|
|
736
|
+
font-weight: 500;
|
|
737
|
+
`,
|
|
738
|
+
paragraph: `
|
|
739
|
+
margin: 0 0 20px;
|
|
740
|
+
color: ${colors.textSecondary};
|
|
741
|
+
font-size: 15px;
|
|
742
|
+
line-height: 1.7;
|
|
743
|
+
`,
|
|
744
|
+
buttonWrapper: `
|
|
745
|
+
text-align: center;
|
|
746
|
+
margin: 32px 0;
|
|
747
|
+
`,
|
|
748
|
+
button: `
|
|
749
|
+
display: inline-block;
|
|
750
|
+
background-color: ${colors.accent};
|
|
751
|
+
color: #000000 !important;
|
|
752
|
+
text-decoration: none;
|
|
753
|
+
padding: 14px 36px;
|
|
754
|
+
border-radius: 8px;
|
|
755
|
+
font-weight: 600;
|
|
756
|
+
font-size: 14px;
|
|
757
|
+
letter-spacing: 0.3px;
|
|
758
|
+
transition: all 0.2s ease;
|
|
759
|
+
`,
|
|
760
|
+
secondaryButton: `
|
|
761
|
+
display: inline-block;
|
|
762
|
+
background-color: transparent;
|
|
763
|
+
color: ${colors.textPrimary} !important;
|
|
764
|
+
text-decoration: none;
|
|
765
|
+
padding: 12px 28px;
|
|
766
|
+
border-radius: 8px;
|
|
767
|
+
font-weight: 500;
|
|
768
|
+
font-size: 14px;
|
|
769
|
+
border: 1px solid ${colors.divider};
|
|
770
|
+
`,
|
|
771
|
+
infoCard: `
|
|
772
|
+
background-color: ${colors.subtle};
|
|
773
|
+
border: 1px solid ${colors.divider};
|
|
774
|
+
border-radius: 12px;
|
|
775
|
+
padding: 20px 24px;
|
|
776
|
+
margin: 28px 0;
|
|
777
|
+
`,
|
|
778
|
+
infoCardTitle: `
|
|
779
|
+
margin: 0 0 12px;
|
|
780
|
+
color: ${colors.textPrimary};
|
|
781
|
+
font-size: 13px;
|
|
782
|
+
font-weight: 600;
|
|
783
|
+
text-transform: uppercase;
|
|
784
|
+
letter-spacing: 0.5px;
|
|
785
|
+
`,
|
|
786
|
+
infoCardText: `
|
|
787
|
+
margin: 0;
|
|
788
|
+
color: ${colors.textSecondary};
|
|
789
|
+
font-size: 14px;
|
|
790
|
+
line-height: 1.6;
|
|
791
|
+
`,
|
|
792
|
+
warningCard: `
|
|
793
|
+
background: linear-gradient(135deg, rgba(255,180,0,0.1) 0%, rgba(255,140,0,0.05) 100%);
|
|
794
|
+
border: 1px solid rgba(255,180,0,0.2);
|
|
795
|
+
border-radius: 12px;
|
|
796
|
+
padding: 20px 24px;
|
|
797
|
+
margin: 28px 0;
|
|
798
|
+
`,
|
|
799
|
+
warningCardTitle: `
|
|
800
|
+
margin: 0 0 12px;
|
|
801
|
+
color: #ffc107;
|
|
802
|
+
font-size: 13px;
|
|
803
|
+
font-weight: 600;
|
|
804
|
+
text-transform: uppercase;
|
|
805
|
+
letter-spacing: 0.5px;
|
|
806
|
+
`,
|
|
807
|
+
warningCardText: `
|
|
808
|
+
margin: 0;
|
|
809
|
+
color: rgba(255,255,255,0.7);
|
|
810
|
+
font-size: 14px;
|
|
811
|
+
line-height: 1.6;
|
|
812
|
+
`,
|
|
813
|
+
successCard: `
|
|
814
|
+
background: linear-gradient(135deg, rgba(0,255,150,0.1) 0%, rgba(0,200,100,0.05) 100%);
|
|
815
|
+
border: 1px solid rgba(0,255,150,0.2);
|
|
816
|
+
border-radius: 12px;
|
|
817
|
+
padding: 20px 24px;
|
|
818
|
+
margin: 28px 0;
|
|
819
|
+
`,
|
|
820
|
+
successCardTitle: `
|
|
821
|
+
margin: 0 0 12px;
|
|
822
|
+
color: #00ff96;
|
|
823
|
+
font-size: 13px;
|
|
824
|
+
font-weight: 600;
|
|
825
|
+
text-transform: uppercase;
|
|
826
|
+
letter-spacing: 0.5px;
|
|
827
|
+
`,
|
|
828
|
+
linkSection: `
|
|
829
|
+
margin: 32px 0;
|
|
830
|
+
padding: 20px;
|
|
831
|
+
background-color: ${colors.subtle};
|
|
832
|
+
border-radius: 8px;
|
|
833
|
+
border: 1px solid ${colors.divider};
|
|
834
|
+
`,
|
|
835
|
+
linkLabel: `
|
|
836
|
+
margin: 0 0 8px;
|
|
837
|
+
color: ${colors.textMuted};
|
|
838
|
+
font-size: 12px;
|
|
839
|
+
text-transform: uppercase;
|
|
840
|
+
letter-spacing: 0.5px;
|
|
841
|
+
`,
|
|
842
|
+
linkText: `
|
|
843
|
+
word-break: break-all;
|
|
844
|
+
color: ${colors.textSecondary};
|
|
845
|
+
font-size: 13px;
|
|
846
|
+
font-family: 'SF Mono', 'Monaco', 'Inconsolata', 'Roboto Mono', monospace;
|
|
847
|
+
margin: 0;
|
|
848
|
+
`,
|
|
849
|
+
divider: `
|
|
850
|
+
border: none;
|
|
851
|
+
border-top: 1px solid ${colors.divider};
|
|
852
|
+
margin: 32px 0;
|
|
853
|
+
`,
|
|
854
|
+
footer: `
|
|
855
|
+
padding: 24px 40px 32px;
|
|
856
|
+
text-align: center;
|
|
857
|
+
border-top: 1px solid ${colors.divider};
|
|
858
|
+
`,
|
|
859
|
+
footerText: `
|
|
860
|
+
margin: 0;
|
|
861
|
+
color: ${colors.textMuted};
|
|
862
|
+
font-size: 12px;
|
|
863
|
+
line-height: 1.8;
|
|
864
|
+
`,
|
|
865
|
+
footerLink: `
|
|
866
|
+
color: ${colors.textSecondary};
|
|
867
|
+
text-decoration: none;
|
|
868
|
+
`,
|
|
869
|
+
badge: `
|
|
870
|
+
display: inline-block;
|
|
871
|
+
background-color: rgba(255,255,255,0.1);
|
|
872
|
+
color: ${colors.textSecondary};
|
|
873
|
+
padding: 4px 12px;
|
|
874
|
+
border-radius: 20px;
|
|
875
|
+
font-size: 12px;
|
|
876
|
+
font-weight: 500;
|
|
877
|
+
letter-spacing: 0.3px;
|
|
878
|
+
`,
|
|
879
|
+
listItem: `
|
|
880
|
+
color: ${colors.textSecondary};
|
|
881
|
+
font-size: 14px;
|
|
882
|
+
margin: 8px 0;
|
|
883
|
+
padding-left: 8px;
|
|
884
|
+
`,
|
|
885
|
+
metaRow: `
|
|
886
|
+
display: flex;
|
|
887
|
+
justify-content: space-between;
|
|
888
|
+
padding: 12px 0;
|
|
889
|
+
border-bottom: 1px solid ${colors.divider};
|
|
890
|
+
`,
|
|
891
|
+
metaLabel: `
|
|
892
|
+
color: ${colors.textMuted};
|
|
893
|
+
font-size: 13px;
|
|
894
|
+
`,
|
|
895
|
+
metaValue: `
|
|
896
|
+
color: ${colors.textPrimary};
|
|
897
|
+
font-size: 13px;
|
|
898
|
+
font-weight: 500;
|
|
899
|
+
`
|
|
900
|
+
};
|
|
901
|
+
function buildVerificationEmailTemplate(data) {
|
|
902
|
+
const { firstName, verificationUrl, expiresIn } = data;
|
|
903
|
+
return `
|
|
904
|
+
<!DOCTYPE html>
|
|
905
|
+
<html lang="en">
|
|
906
|
+
<head>
|
|
907
|
+
<meta charset="UTF-8">
|
|
908
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
909
|
+
<meta name="color-scheme" content="dark">
|
|
910
|
+
<meta name="supported-color-schemes" content="dark">
|
|
911
|
+
<title>Verify Your Email</title>
|
|
912
|
+
<!--[if mso]>
|
|
913
|
+
<style type="text/css">
|
|
914
|
+
body, table, td {font-family: Arial, Helvetica, sans-serif !important;}
|
|
915
|
+
</style>
|
|
916
|
+
<![endif]-->
|
|
917
|
+
</head>
|
|
918
|
+
<body style="${styles.wrapper}">
|
|
919
|
+
<div style="${styles.container}">
|
|
920
|
+
<div style="${styles.card}">
|
|
921
|
+
<!-- Header -->
|
|
922
|
+
<div style="${styles.header}">
|
|
923
|
+
<div style="${styles.iconWrapper}">
|
|
924
|
+
\u2709\uFE0F
|
|
925
|
+
</div>
|
|
926
|
+
<h1 style="${styles.headerTitle}">Verify your email</h1>
|
|
927
|
+
<p style="${styles.headerSubtitle}">One quick step to get started</p>
|
|
928
|
+
</div>
|
|
929
|
+
|
|
930
|
+
<!-- Body -->
|
|
931
|
+
<div style="${styles.body}">
|
|
932
|
+
<p style="${styles.greeting}">Hi ${firstName},</p>
|
|
933
|
+
|
|
934
|
+
<p style="${styles.paragraph}">
|
|
935
|
+
Thanks for signing up. To complete your registration and unlock all features,
|
|
936
|
+
please verify your email address by clicking the button below.
|
|
937
|
+
</p>
|
|
938
|
+
|
|
939
|
+
<div style="${styles.buttonWrapper}">
|
|
940
|
+
<a href="${verificationUrl}" style="${styles.button}" target="_blank">
|
|
941
|
+
Verify Email Address
|
|
942
|
+
</a>
|
|
943
|
+
</div>
|
|
944
|
+
|
|
945
|
+
<div style="${styles.infoCard}">
|
|
946
|
+
<p style="${styles.infoCardTitle}">\u23F1 Time Sensitive</p>
|
|
947
|
+
<p style="${styles.infoCardText}">
|
|
948
|
+
This verification link will expire in <strong>${expiresIn}</strong>.
|
|
949
|
+
If you didn't create an account, you can safely ignore this email.
|
|
950
|
+
</p>
|
|
951
|
+
</div>
|
|
952
|
+
</div>
|
|
953
|
+
|
|
954
|
+
<!-- Footer -->
|
|
955
|
+
<div style="${styles.footer}">
|
|
956
|
+
<p style="${styles.footerText}">
|
|
957
|
+
This is an automated message \u2014 please do not reply.<br>
|
|
958
|
+
\xA9 ${(/* @__PURE__ */ new Date()).getFullYear()} All rights reserved.
|
|
959
|
+
</p>
|
|
960
|
+
</div>
|
|
961
|
+
</div>
|
|
962
|
+
</div>
|
|
963
|
+
</body>
|
|
964
|
+
</html>
|
|
965
|
+
`;
|
|
966
|
+
}
|
|
967
|
+
function buildResetPasswordEmailTemplate(data) {
|
|
968
|
+
const { firstName, resetUrl, expiresIn } = data;
|
|
969
|
+
return `
|
|
970
|
+
<!DOCTYPE html>
|
|
971
|
+
<html lang="en">
|
|
972
|
+
<head>
|
|
973
|
+
<meta charset="UTF-8">
|
|
974
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
975
|
+
<meta name="color-scheme" content="dark">
|
|
976
|
+
<meta name="supported-color-schemes" content="dark">
|
|
977
|
+
<title>Reset Your Password</title>
|
|
978
|
+
</head>
|
|
979
|
+
<body style="${styles.wrapper}">
|
|
980
|
+
<div style="${styles.container}">
|
|
981
|
+
<div style="${styles.card}">
|
|
982
|
+
<!-- Header -->
|
|
983
|
+
<div style="${styles.header}">
|
|
984
|
+
<div style="${styles.iconWrapper}">
|
|
985
|
+
\u{1F510}
|
|
986
|
+
</div>
|
|
987
|
+
<h1 style="${styles.headerTitle}">Reset your password</h1>
|
|
988
|
+
<p style="${styles.headerSubtitle}">We received a reset request</p>
|
|
989
|
+
</div>
|
|
990
|
+
|
|
991
|
+
<!-- Body -->
|
|
992
|
+
<div style="${styles.body}">
|
|
993
|
+
<p style="${styles.greeting}">Hi ${firstName},</p>
|
|
994
|
+
|
|
995
|
+
<p style="${styles.paragraph}">
|
|
996
|
+
We received a request to reset the password for your account.
|
|
997
|
+
Click the button below to create a new password.
|
|
998
|
+
</p>
|
|
999
|
+
|
|
1000
|
+
<div style="${styles.buttonWrapper}">
|
|
1001
|
+
<a href="${resetUrl}" style="${styles.button}" target="_blank">
|
|
1002
|
+
Reset Password
|
|
1003
|
+
</a>
|
|
1004
|
+
</div>
|
|
1005
|
+
|
|
1006
|
+
<div style="${styles.warningCard}">
|
|
1007
|
+
<p style="${styles.warningCardTitle}">\u26A0\uFE0F Security Notice</p>
|
|
1008
|
+
<p style="${styles.warningCardText}">
|
|
1009
|
+
\u2022 This link expires in <strong>${expiresIn}</strong><br>
|
|
1010
|
+
\u2022 This link can only be used once<br>
|
|
1011
|
+
\u2022 If you didn't request this, ignore this email
|
|
1012
|
+
</p>
|
|
1013
|
+
</div>
|
|
1014
|
+
|
|
1015
|
+
<hr style="${styles.divider}" />
|
|
1016
|
+
|
|
1017
|
+
<p style="${styles.paragraph}; font-size: 13px; color: ${colors.textMuted};">
|
|
1018
|
+
<strong>Didn't request this?</strong><br>
|
|
1019
|
+
Your password remains unchanged. If you're concerned about your account
|
|
1020
|
+
security, please contact our support team immediately.
|
|
1021
|
+
</p>
|
|
1022
|
+
</div>
|
|
1023
|
+
|
|
1024
|
+
<!-- Footer -->
|
|
1025
|
+
<div style="${styles.footer}">
|
|
1026
|
+
<p style="${styles.footerText}">
|
|
1027
|
+
This is an automated message \u2014 please do not reply.<br>
|
|
1028
|
+
\xA9 ${(/* @__PURE__ */ new Date()).getFullYear()} All rights reserved.
|
|
1029
|
+
</p>
|
|
1030
|
+
</div>
|
|
1031
|
+
</div>
|
|
1032
|
+
</div>
|
|
1033
|
+
</body>
|
|
1034
|
+
</html>
|
|
1035
|
+
`;
|
|
1036
|
+
}
|
|
1037
|
+
|
|
671
1038
|
// src/express/auth.routes.ts
|
|
672
1039
|
function createAuthRouter(options = {}) {
|
|
673
1040
|
const googleClientId = process.env.GOOGLE_CLIENT_ID;
|
|
@@ -699,10 +1066,8 @@ function createAuthRouter(options = {}) {
|
|
|
699
1066
|
);
|
|
700
1067
|
r.post("/login", validateLogin, async (req, res) => {
|
|
701
1068
|
const { email: emailAddress, password } = req.body || {};
|
|
702
|
-
console.log(emailAddress, password, "body");
|
|
703
1069
|
try {
|
|
704
1070
|
const user = await OrgUser.findOne({ email: emailAddress }).select("+password").lean();
|
|
705
|
-
console.log(user, "user");
|
|
706
1071
|
if (!user) {
|
|
707
1072
|
return res.status(400).json({
|
|
708
1073
|
error: "Invalid email or password",
|
|
@@ -776,10 +1141,20 @@ function createAuthRouter(options = {}) {
|
|
|
776
1141
|
emailService: email,
|
|
777
1142
|
user,
|
|
778
1143
|
subject: "Verify your email",
|
|
779
|
-
html: buildVerificationTemplate(
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
)
|
|
1144
|
+
// html: buildVerificationTemplate(
|
|
1145
|
+
// email.sign({ userId: kcUser.id, email: kcUser.email }),
|
|
1146
|
+
// options,
|
|
1147
|
+
// ),
|
|
1148
|
+
html: buildVerificationEmailTemplate({
|
|
1149
|
+
firstName: user.firstName,
|
|
1150
|
+
verificationUrl: `${getFrontendBaseUrl(options)}/verify-email?token=${email.sign(
|
|
1151
|
+
{
|
|
1152
|
+
userId: user.id,
|
|
1153
|
+
email: user.email
|
|
1154
|
+
}
|
|
1155
|
+
)}`,
|
|
1156
|
+
expiresIn: "1 hour"
|
|
1157
|
+
})
|
|
783
1158
|
});
|
|
784
1159
|
if (emailResult.rateLimited) {
|
|
785
1160
|
return res.status(429).json({
|
|
@@ -859,7 +1234,17 @@ function createAuthRouter(options = {}) {
|
|
|
859
1234
|
emailService: email,
|
|
860
1235
|
user,
|
|
861
1236
|
subject: "Verify your email",
|
|
862
|
-
html: buildVerificationTemplate(token, options)
|
|
1237
|
+
// html: buildVerificationTemplate(token, options),
|
|
1238
|
+
html: buildVerificationEmailTemplate({
|
|
1239
|
+
firstName: user.firstName,
|
|
1240
|
+
verificationUrl: `${getFrontendBaseUrl(options)}/verify-email?token=${email.sign(
|
|
1241
|
+
{
|
|
1242
|
+
userId: user.id,
|
|
1243
|
+
email: user.email
|
|
1244
|
+
}
|
|
1245
|
+
)}`,
|
|
1246
|
+
expiresIn: "1 hour"
|
|
1247
|
+
})
|
|
863
1248
|
});
|
|
864
1249
|
if (resendResult.rateLimited) {
|
|
865
1250
|
return res.status(429).json({
|
|
@@ -888,7 +1273,17 @@ function createAuthRouter(options = {}) {
|
|
|
888
1273
|
emailService: email,
|
|
889
1274
|
user,
|
|
890
1275
|
subject: "Reset password",
|
|
891
|
-
html: buildResetTemplate(resetToken, options)
|
|
1276
|
+
// html: buildResetTemplate(resetToken, options),
|
|
1277
|
+
html: buildResetPasswordEmailTemplate({
|
|
1278
|
+
firstName: user.firstName,
|
|
1279
|
+
resetUrl: `${getFrontendBaseUrl(options)}/reset-password?token=${email.sign(
|
|
1280
|
+
{
|
|
1281
|
+
userId: user.id,
|
|
1282
|
+
email: user.email
|
|
1283
|
+
}
|
|
1284
|
+
)}`,
|
|
1285
|
+
expiresIn: "1 hour"
|
|
1286
|
+
})
|
|
892
1287
|
});
|
|
893
1288
|
if (resetResult.rateLimited) {
|
|
894
1289
|
return res.status(429).json({
|
|
@@ -901,9 +1296,16 @@ function createAuthRouter(options = {}) {
|
|
|
901
1296
|
});
|
|
902
1297
|
r.post("/reset-password", validateResetPassword, async (req, res) => {
|
|
903
1298
|
const { token, newPassword } = req.body || {};
|
|
1299
|
+
if (!token || !newPassword) {
|
|
1300
|
+
return res.status(400).json({
|
|
1301
|
+
ok: false,
|
|
1302
|
+
error: "Token and new password are required",
|
|
1303
|
+
code: "MISSING_FIELDS"
|
|
1304
|
+
});
|
|
1305
|
+
}
|
|
904
1306
|
try {
|
|
905
1307
|
const payload = email.verify(token);
|
|
906
|
-
const user = await OrgUser.findOne({
|
|
1308
|
+
const user = await OrgUser.findOne({ id: payload.userId });
|
|
907
1309
|
if (!user) {
|
|
908
1310
|
return res.status(404).json({ ok: false, error: "User not found" });
|
|
909
1311
|
}
|
|
@@ -1294,12 +1696,6 @@ function respondWithKeycloakError(res, err, fallback, status = 400) {
|
|
|
1294
1696
|
const description = err?.response?.data?.error_description || err?.response?.data?.errorMessage || err?.message || fallback;
|
|
1295
1697
|
return res.status(status).json({ ok: false, error: description });
|
|
1296
1698
|
}
|
|
1297
|
-
function buildVerificationTemplate(token, options) {
|
|
1298
|
-
return `<a href="${getFrontendBaseUrl(options)}/auth/verify-email?token=${token}">Verify</a>`;
|
|
1299
|
-
}
|
|
1300
|
-
function buildResetTemplate(token, options) {
|
|
1301
|
-
return `<a href="${getFrontendBaseUrl(options)}/auth/reset-password?token=${token}">Reset</a>`;
|
|
1302
|
-
}
|
|
1303
1699
|
function getFrontendBaseUrl(options) {
|
|
1304
1700
|
if (options.frontendBaseUrl)
|
|
1305
1701
|
return options.frontendBaseUrl.replace(/\/$/, "");
|
|
@@ -1317,7 +1713,6 @@ async function sendRateLimitedEmail({
|
|
|
1317
1713
|
if (!can.ok) {
|
|
1318
1714
|
return { rateLimited: true, waitMs: can.waitMs };
|
|
1319
1715
|
}
|
|
1320
|
-
console.log(can, "can");
|
|
1321
1716
|
await emailService.send(user.email, subject, html);
|
|
1322
1717
|
user.lastEmailSent = [...user.lastEmailSent || [], /* @__PURE__ */ new Date()];
|
|
1323
1718
|
await user.save();
|