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