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/index.cjs
CHANGED
|
@@ -642,7 +642,7 @@ var AuthAdminService = class {
|
|
|
642
642
|
}
|
|
643
643
|
async updateUserPassword(userId, newPassword) {
|
|
644
644
|
const hashed = await import_bcrypt.default.hash(newPassword, 10);
|
|
645
|
-
await OrgUser.findOneAndUpdate({ id: userId }, {
|
|
645
|
+
await OrgUser.findOneAndUpdate({ id: userId }, { passwordHash: hashed });
|
|
646
646
|
}
|
|
647
647
|
// -------------------------------------------------------------------
|
|
648
648
|
// ADMIN TOKEN (self-issued JWT)
|
|
@@ -695,7 +695,6 @@ var EmailService = class {
|
|
|
695
695
|
return import_jsonwebtoken3.default.verify(token, process.env.EMAIL_JWT_SECRET);
|
|
696
696
|
}
|
|
697
697
|
async send(to, subject, html) {
|
|
698
|
-
console.log("[EmailService] Attempting to send:", { to, subject });
|
|
699
698
|
try {
|
|
700
699
|
const info = await this.transporter.sendMail({
|
|
701
700
|
from: process.env.EMAIL_FROM,
|
|
@@ -723,18 +722,6 @@ var EmailService = class {
|
|
|
723
722
|
}
|
|
724
723
|
}
|
|
725
724
|
canSend(lastEmailSent) {
|
|
726
|
-
console.log(
|
|
727
|
-
process.env.EMAIL_PASSWORD,
|
|
728
|
-
"pssword",
|
|
729
|
-
process.env.EMAIL_USER,
|
|
730
|
-
"user",
|
|
731
|
-
process.env.EMAIL_SECURE,
|
|
732
|
-
"secure",
|
|
733
|
-
process.env.EMAIL_PORT,
|
|
734
|
-
"porat",
|
|
735
|
-
process.env.EMAIL_HOST,
|
|
736
|
-
"hosat"
|
|
737
|
-
);
|
|
738
725
|
const now = Date.now();
|
|
739
726
|
const windowStart = now - this.WINDOW_MINUTES * 60 * 1e3;
|
|
740
727
|
const emailsInWindow = (lastEmailSent || []).map((d) => new Date(d)).filter((d) => d.getTime() >= windowStart);
|
|
@@ -748,6 +735,386 @@ var EmailService = class {
|
|
|
748
735
|
}
|
|
749
736
|
};
|
|
750
737
|
|
|
738
|
+
// src/templates/email.templates.ts
|
|
739
|
+
var colors = {
|
|
740
|
+
background: "#0a0a0a",
|
|
741
|
+
cardBackground: "#111111",
|
|
742
|
+
cardBorder: "#1a1a1a",
|
|
743
|
+
accent: "#ffffff",
|
|
744
|
+
accentMuted: "rgba(255, 255, 255, 0.9)",
|
|
745
|
+
textPrimary: "#ffffff",
|
|
746
|
+
textSecondary: "rgba(255, 255, 255, 0.7)",
|
|
747
|
+
textMuted: "rgba(255, 255, 255, 0.5)",
|
|
748
|
+
divider: "rgba(255, 255, 255, 0.1)",
|
|
749
|
+
subtle: "#161616",
|
|
750
|
+
highlight: "rgba(255, 255, 255, 0.05)"
|
|
751
|
+
};
|
|
752
|
+
var styles = {
|
|
753
|
+
wrapper: `
|
|
754
|
+
margin: 0;
|
|
755
|
+
padding: 40px 20px;
|
|
756
|
+
background-color: ${colors.background};
|
|
757
|
+
background-image:
|
|
758
|
+
radial-gradient(ellipse at top, rgba(255,255,255,0.03) 0%, transparent 50%),
|
|
759
|
+
radial-gradient(ellipse at bottom, rgba(255,255,255,0.02) 0%, transparent 50%);
|
|
760
|
+
min-height: 100vh;
|
|
761
|
+
`,
|
|
762
|
+
container: `
|
|
763
|
+
max-width: 520px;
|
|
764
|
+
margin: 0 auto;
|
|
765
|
+
font-family: -apple-system, BlinkMacSystemFont, 'SF Pro Display', 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
|
|
766
|
+
color: ${colors.textPrimary};
|
|
767
|
+
line-height: 1.7;
|
|
768
|
+
`,
|
|
769
|
+
card: `
|
|
770
|
+
background-color: ${colors.cardBackground};
|
|
771
|
+
border: 1px solid ${colors.cardBorder};
|
|
772
|
+
border-radius: 16px;
|
|
773
|
+
overflow: hidden;
|
|
774
|
+
box-shadow:
|
|
775
|
+
0 0 0 1px rgba(255,255,255,0.05),
|
|
776
|
+
0 20px 50px -20px rgba(0,0,0,0.5),
|
|
777
|
+
0 30px 60px -30px rgba(0,0,0,0.3);
|
|
778
|
+
`,
|
|
779
|
+
header: `
|
|
780
|
+
padding: 48px 40px 32px;
|
|
781
|
+
text-align: center;
|
|
782
|
+
border-bottom: 1px solid ${colors.divider};
|
|
783
|
+
`,
|
|
784
|
+
iconWrapper: `
|
|
785
|
+
width: 64px;
|
|
786
|
+
height: 64px;
|
|
787
|
+
margin: 0 auto 24px;
|
|
788
|
+
background: linear-gradient(135deg, rgba(255,255,255,0.1) 0%, rgba(255,255,255,0.05) 100%);
|
|
789
|
+
border: 1px solid rgba(255,255,255,0.1);
|
|
790
|
+
border-radius: 16px;
|
|
791
|
+
display: flex;
|
|
792
|
+
align-items: center;
|
|
793
|
+
justify-content: center;
|
|
794
|
+
font-size: 28px;
|
|
795
|
+
`,
|
|
796
|
+
headerTitle: `
|
|
797
|
+
color: ${colors.textPrimary};
|
|
798
|
+
margin: 0;
|
|
799
|
+
font-size: 24px;
|
|
800
|
+
font-weight: 600;
|
|
801
|
+
letter-spacing: -0.5px;
|
|
802
|
+
`,
|
|
803
|
+
headerSubtitle: `
|
|
804
|
+
color: ${colors.textMuted};
|
|
805
|
+
margin: 8px 0 0;
|
|
806
|
+
font-size: 14px;
|
|
807
|
+
font-weight: 400;
|
|
808
|
+
`,
|
|
809
|
+
body: `
|
|
810
|
+
padding: 40px;
|
|
811
|
+
`,
|
|
812
|
+
greeting: `
|
|
813
|
+
margin: 0 0 24px;
|
|
814
|
+
color: ${colors.textPrimary};
|
|
815
|
+
font-size: 18px;
|
|
816
|
+
font-weight: 500;
|
|
817
|
+
`,
|
|
818
|
+
paragraph: `
|
|
819
|
+
margin: 0 0 20px;
|
|
820
|
+
color: ${colors.textSecondary};
|
|
821
|
+
font-size: 15px;
|
|
822
|
+
line-height: 1.7;
|
|
823
|
+
`,
|
|
824
|
+
buttonWrapper: `
|
|
825
|
+
text-align: center;
|
|
826
|
+
margin: 32px 0;
|
|
827
|
+
`,
|
|
828
|
+
button: `
|
|
829
|
+
display: inline-block;
|
|
830
|
+
background-color: ${colors.accent};
|
|
831
|
+
color: #000000 !important;
|
|
832
|
+
text-decoration: none;
|
|
833
|
+
padding: 14px 36px;
|
|
834
|
+
border-radius: 8px;
|
|
835
|
+
font-weight: 600;
|
|
836
|
+
font-size: 14px;
|
|
837
|
+
letter-spacing: 0.3px;
|
|
838
|
+
transition: all 0.2s ease;
|
|
839
|
+
`,
|
|
840
|
+
secondaryButton: `
|
|
841
|
+
display: inline-block;
|
|
842
|
+
background-color: transparent;
|
|
843
|
+
color: ${colors.textPrimary} !important;
|
|
844
|
+
text-decoration: none;
|
|
845
|
+
padding: 12px 28px;
|
|
846
|
+
border-radius: 8px;
|
|
847
|
+
font-weight: 500;
|
|
848
|
+
font-size: 14px;
|
|
849
|
+
border: 1px solid ${colors.divider};
|
|
850
|
+
`,
|
|
851
|
+
infoCard: `
|
|
852
|
+
background-color: ${colors.subtle};
|
|
853
|
+
border: 1px solid ${colors.divider};
|
|
854
|
+
border-radius: 12px;
|
|
855
|
+
padding: 20px 24px;
|
|
856
|
+
margin: 28px 0;
|
|
857
|
+
`,
|
|
858
|
+
infoCardTitle: `
|
|
859
|
+
margin: 0 0 12px;
|
|
860
|
+
color: ${colors.textPrimary};
|
|
861
|
+
font-size: 13px;
|
|
862
|
+
font-weight: 600;
|
|
863
|
+
text-transform: uppercase;
|
|
864
|
+
letter-spacing: 0.5px;
|
|
865
|
+
`,
|
|
866
|
+
infoCardText: `
|
|
867
|
+
margin: 0;
|
|
868
|
+
color: ${colors.textSecondary};
|
|
869
|
+
font-size: 14px;
|
|
870
|
+
line-height: 1.6;
|
|
871
|
+
`,
|
|
872
|
+
warningCard: `
|
|
873
|
+
background: linear-gradient(135deg, rgba(255,180,0,0.1) 0%, rgba(255,140,0,0.05) 100%);
|
|
874
|
+
border: 1px solid rgba(255,180,0,0.2);
|
|
875
|
+
border-radius: 12px;
|
|
876
|
+
padding: 20px 24px;
|
|
877
|
+
margin: 28px 0;
|
|
878
|
+
`,
|
|
879
|
+
warningCardTitle: `
|
|
880
|
+
margin: 0 0 12px;
|
|
881
|
+
color: #ffc107;
|
|
882
|
+
font-size: 13px;
|
|
883
|
+
font-weight: 600;
|
|
884
|
+
text-transform: uppercase;
|
|
885
|
+
letter-spacing: 0.5px;
|
|
886
|
+
`,
|
|
887
|
+
warningCardText: `
|
|
888
|
+
margin: 0;
|
|
889
|
+
color: rgba(255,255,255,0.7);
|
|
890
|
+
font-size: 14px;
|
|
891
|
+
line-height: 1.6;
|
|
892
|
+
`,
|
|
893
|
+
successCard: `
|
|
894
|
+
background: linear-gradient(135deg, rgba(0,255,150,0.1) 0%, rgba(0,200,100,0.05) 100%);
|
|
895
|
+
border: 1px solid rgba(0,255,150,0.2);
|
|
896
|
+
border-radius: 12px;
|
|
897
|
+
padding: 20px 24px;
|
|
898
|
+
margin: 28px 0;
|
|
899
|
+
`,
|
|
900
|
+
successCardTitle: `
|
|
901
|
+
margin: 0 0 12px;
|
|
902
|
+
color: #00ff96;
|
|
903
|
+
font-size: 13px;
|
|
904
|
+
font-weight: 600;
|
|
905
|
+
text-transform: uppercase;
|
|
906
|
+
letter-spacing: 0.5px;
|
|
907
|
+
`,
|
|
908
|
+
linkSection: `
|
|
909
|
+
margin: 32px 0;
|
|
910
|
+
padding: 20px;
|
|
911
|
+
background-color: ${colors.subtle};
|
|
912
|
+
border-radius: 8px;
|
|
913
|
+
border: 1px solid ${colors.divider};
|
|
914
|
+
`,
|
|
915
|
+
linkLabel: `
|
|
916
|
+
margin: 0 0 8px;
|
|
917
|
+
color: ${colors.textMuted};
|
|
918
|
+
font-size: 12px;
|
|
919
|
+
text-transform: uppercase;
|
|
920
|
+
letter-spacing: 0.5px;
|
|
921
|
+
`,
|
|
922
|
+
linkText: `
|
|
923
|
+
word-break: break-all;
|
|
924
|
+
color: ${colors.textSecondary};
|
|
925
|
+
font-size: 13px;
|
|
926
|
+
font-family: 'SF Mono', 'Monaco', 'Inconsolata', 'Roboto Mono', monospace;
|
|
927
|
+
margin: 0;
|
|
928
|
+
`,
|
|
929
|
+
divider: `
|
|
930
|
+
border: none;
|
|
931
|
+
border-top: 1px solid ${colors.divider};
|
|
932
|
+
margin: 32px 0;
|
|
933
|
+
`,
|
|
934
|
+
footer: `
|
|
935
|
+
padding: 24px 40px 32px;
|
|
936
|
+
text-align: center;
|
|
937
|
+
border-top: 1px solid ${colors.divider};
|
|
938
|
+
`,
|
|
939
|
+
footerText: `
|
|
940
|
+
margin: 0;
|
|
941
|
+
color: ${colors.textMuted};
|
|
942
|
+
font-size: 12px;
|
|
943
|
+
line-height: 1.8;
|
|
944
|
+
`,
|
|
945
|
+
footerLink: `
|
|
946
|
+
color: ${colors.textSecondary};
|
|
947
|
+
text-decoration: none;
|
|
948
|
+
`,
|
|
949
|
+
badge: `
|
|
950
|
+
display: inline-block;
|
|
951
|
+
background-color: rgba(255,255,255,0.1);
|
|
952
|
+
color: ${colors.textSecondary};
|
|
953
|
+
padding: 4px 12px;
|
|
954
|
+
border-radius: 20px;
|
|
955
|
+
font-size: 12px;
|
|
956
|
+
font-weight: 500;
|
|
957
|
+
letter-spacing: 0.3px;
|
|
958
|
+
`,
|
|
959
|
+
listItem: `
|
|
960
|
+
color: ${colors.textSecondary};
|
|
961
|
+
font-size: 14px;
|
|
962
|
+
margin: 8px 0;
|
|
963
|
+
padding-left: 8px;
|
|
964
|
+
`,
|
|
965
|
+
metaRow: `
|
|
966
|
+
display: flex;
|
|
967
|
+
justify-content: space-between;
|
|
968
|
+
padding: 12px 0;
|
|
969
|
+
border-bottom: 1px solid ${colors.divider};
|
|
970
|
+
`,
|
|
971
|
+
metaLabel: `
|
|
972
|
+
color: ${colors.textMuted};
|
|
973
|
+
font-size: 13px;
|
|
974
|
+
`,
|
|
975
|
+
metaValue: `
|
|
976
|
+
color: ${colors.textPrimary};
|
|
977
|
+
font-size: 13px;
|
|
978
|
+
font-weight: 500;
|
|
979
|
+
`
|
|
980
|
+
};
|
|
981
|
+
function buildVerificationEmailTemplate(data) {
|
|
982
|
+
const { firstName, verificationUrl, expiresIn } = data;
|
|
983
|
+
return `
|
|
984
|
+
<!DOCTYPE html>
|
|
985
|
+
<html lang="en">
|
|
986
|
+
<head>
|
|
987
|
+
<meta charset="UTF-8">
|
|
988
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
989
|
+
<meta name="color-scheme" content="dark">
|
|
990
|
+
<meta name="supported-color-schemes" content="dark">
|
|
991
|
+
<title>Verify Your Email</title>
|
|
992
|
+
<!--[if mso]>
|
|
993
|
+
<style type="text/css">
|
|
994
|
+
body, table, td {font-family: Arial, Helvetica, sans-serif !important;}
|
|
995
|
+
</style>
|
|
996
|
+
<![endif]-->
|
|
997
|
+
</head>
|
|
998
|
+
<body style="${styles.wrapper}">
|
|
999
|
+
<div style="${styles.container}">
|
|
1000
|
+
<div style="${styles.card}">
|
|
1001
|
+
<!-- Header -->
|
|
1002
|
+
<div style="${styles.header}">
|
|
1003
|
+
<div style="${styles.iconWrapper}">
|
|
1004
|
+
\u2709\uFE0F
|
|
1005
|
+
</div>
|
|
1006
|
+
<h1 style="${styles.headerTitle}">Verify your email</h1>
|
|
1007
|
+
<p style="${styles.headerSubtitle}">One quick step to get started</p>
|
|
1008
|
+
</div>
|
|
1009
|
+
|
|
1010
|
+
<!-- Body -->
|
|
1011
|
+
<div style="${styles.body}">
|
|
1012
|
+
<p style="${styles.greeting}">Hi ${firstName},</p>
|
|
1013
|
+
|
|
1014
|
+
<p style="${styles.paragraph}">
|
|
1015
|
+
Thanks for signing up. To complete your registration and unlock all features,
|
|
1016
|
+
please verify your email address by clicking the button below.
|
|
1017
|
+
</p>
|
|
1018
|
+
|
|
1019
|
+
<div style="${styles.buttonWrapper}">
|
|
1020
|
+
<a href="${verificationUrl}" style="${styles.button}" target="_blank">
|
|
1021
|
+
Verify Email Address
|
|
1022
|
+
</a>
|
|
1023
|
+
</div>
|
|
1024
|
+
|
|
1025
|
+
<div style="${styles.infoCard}">
|
|
1026
|
+
<p style="${styles.infoCardTitle}">\u23F1 Time Sensitive</p>
|
|
1027
|
+
<p style="${styles.infoCardText}">
|
|
1028
|
+
This verification link will expire in <strong>${expiresIn}</strong>.
|
|
1029
|
+
If you didn't create an account, you can safely ignore this email.
|
|
1030
|
+
</p>
|
|
1031
|
+
</div>
|
|
1032
|
+
</div>
|
|
1033
|
+
|
|
1034
|
+
<!-- Footer -->
|
|
1035
|
+
<div style="${styles.footer}">
|
|
1036
|
+
<p style="${styles.footerText}">
|
|
1037
|
+
This is an automated message \u2014 please do not reply.<br>
|
|
1038
|
+
\xA9 ${(/* @__PURE__ */ new Date()).getFullYear()} All rights reserved.
|
|
1039
|
+
</p>
|
|
1040
|
+
</div>
|
|
1041
|
+
</div>
|
|
1042
|
+
</div>
|
|
1043
|
+
</body>
|
|
1044
|
+
</html>
|
|
1045
|
+
`;
|
|
1046
|
+
}
|
|
1047
|
+
function buildResetPasswordEmailTemplate(data) {
|
|
1048
|
+
const { firstName, resetUrl, expiresIn } = data;
|
|
1049
|
+
return `
|
|
1050
|
+
<!DOCTYPE html>
|
|
1051
|
+
<html lang="en">
|
|
1052
|
+
<head>
|
|
1053
|
+
<meta charset="UTF-8">
|
|
1054
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
1055
|
+
<meta name="color-scheme" content="dark">
|
|
1056
|
+
<meta name="supported-color-schemes" content="dark">
|
|
1057
|
+
<title>Reset Your Password</title>
|
|
1058
|
+
</head>
|
|
1059
|
+
<body style="${styles.wrapper}">
|
|
1060
|
+
<div style="${styles.container}">
|
|
1061
|
+
<div style="${styles.card}">
|
|
1062
|
+
<!-- Header -->
|
|
1063
|
+
<div style="${styles.header}">
|
|
1064
|
+
<div style="${styles.iconWrapper}">
|
|
1065
|
+
\u{1F510}
|
|
1066
|
+
</div>
|
|
1067
|
+
<h1 style="${styles.headerTitle}">Reset your password</h1>
|
|
1068
|
+
<p style="${styles.headerSubtitle}">We received a reset request</p>
|
|
1069
|
+
</div>
|
|
1070
|
+
|
|
1071
|
+
<!-- Body -->
|
|
1072
|
+
<div style="${styles.body}">
|
|
1073
|
+
<p style="${styles.greeting}">Hi ${firstName},</p>
|
|
1074
|
+
|
|
1075
|
+
<p style="${styles.paragraph}">
|
|
1076
|
+
We received a request to reset the password for your account.
|
|
1077
|
+
Click the button below to create a new password.
|
|
1078
|
+
</p>
|
|
1079
|
+
|
|
1080
|
+
<div style="${styles.buttonWrapper}">
|
|
1081
|
+
<a href="${resetUrl}" style="${styles.button}" target="_blank">
|
|
1082
|
+
Reset Password
|
|
1083
|
+
</a>
|
|
1084
|
+
</div>
|
|
1085
|
+
|
|
1086
|
+
<div style="${styles.warningCard}">
|
|
1087
|
+
<p style="${styles.warningCardTitle}">\u26A0\uFE0F Security Notice</p>
|
|
1088
|
+
<p style="${styles.warningCardText}">
|
|
1089
|
+
\u2022 This link expires in <strong>${expiresIn}</strong><br>
|
|
1090
|
+
\u2022 This link can only be used once<br>
|
|
1091
|
+
\u2022 If you didn't request this, ignore this email
|
|
1092
|
+
</p>
|
|
1093
|
+
</div>
|
|
1094
|
+
|
|
1095
|
+
<hr style="${styles.divider}" />
|
|
1096
|
+
|
|
1097
|
+
<p style="${styles.paragraph}; font-size: 13px; color: ${colors.textMuted};">
|
|
1098
|
+
<strong>Didn't request this?</strong><br>
|
|
1099
|
+
Your password remains unchanged. If you're concerned about your account
|
|
1100
|
+
security, please contact our support team immediately.
|
|
1101
|
+
</p>
|
|
1102
|
+
</div>
|
|
1103
|
+
|
|
1104
|
+
<!-- Footer -->
|
|
1105
|
+
<div style="${styles.footer}">
|
|
1106
|
+
<p style="${styles.footerText}">
|
|
1107
|
+
This is an automated message \u2014 please do not reply.<br>
|
|
1108
|
+
\xA9 ${(/* @__PURE__ */ new Date()).getFullYear()} All rights reserved.
|
|
1109
|
+
</p>
|
|
1110
|
+
</div>
|
|
1111
|
+
</div>
|
|
1112
|
+
</div>
|
|
1113
|
+
</body>
|
|
1114
|
+
</html>
|
|
1115
|
+
`;
|
|
1116
|
+
}
|
|
1117
|
+
|
|
751
1118
|
// src/express/auth.routes.ts
|
|
752
1119
|
function createAuthRouter(options = {}) {
|
|
753
1120
|
const googleClientId = process.env.GOOGLE_CLIENT_ID;
|
|
@@ -779,10 +1146,8 @@ function createAuthRouter(options = {}) {
|
|
|
779
1146
|
);
|
|
780
1147
|
r.post("/login", validateLogin, async (req, res) => {
|
|
781
1148
|
const { email: emailAddress, password } = req.body || {};
|
|
782
|
-
console.log(emailAddress, password, "body");
|
|
783
1149
|
try {
|
|
784
1150
|
const user = await OrgUser.findOne({ email: emailAddress }).select("+password").lean();
|
|
785
|
-
console.log(user, "user");
|
|
786
1151
|
if (!user) {
|
|
787
1152
|
return res.status(400).json({
|
|
788
1153
|
error: "Invalid email or password",
|
|
@@ -856,10 +1221,20 @@ function createAuthRouter(options = {}) {
|
|
|
856
1221
|
emailService: email,
|
|
857
1222
|
user,
|
|
858
1223
|
subject: "Verify your email",
|
|
859
|
-
html: buildVerificationTemplate(
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
)
|
|
1224
|
+
// html: buildVerificationTemplate(
|
|
1225
|
+
// email.sign({ userId: kcUser.id, email: kcUser.email }),
|
|
1226
|
+
// options,
|
|
1227
|
+
// ),
|
|
1228
|
+
html: buildVerificationEmailTemplate({
|
|
1229
|
+
firstName: user.firstName,
|
|
1230
|
+
verificationUrl: `${getFrontendBaseUrl(options)}/verify-email?token=${email.sign(
|
|
1231
|
+
{
|
|
1232
|
+
userId: user.id,
|
|
1233
|
+
email: user.email
|
|
1234
|
+
}
|
|
1235
|
+
)}`,
|
|
1236
|
+
expiresIn: "1 hour"
|
|
1237
|
+
})
|
|
863
1238
|
});
|
|
864
1239
|
if (emailResult.rateLimited) {
|
|
865
1240
|
return res.status(429).json({
|
|
@@ -939,7 +1314,17 @@ function createAuthRouter(options = {}) {
|
|
|
939
1314
|
emailService: email,
|
|
940
1315
|
user,
|
|
941
1316
|
subject: "Verify your email",
|
|
942
|
-
html: buildVerificationTemplate(token, options)
|
|
1317
|
+
// html: buildVerificationTemplate(token, options),
|
|
1318
|
+
html: buildVerificationEmailTemplate({
|
|
1319
|
+
firstName: user.firstName,
|
|
1320
|
+
verificationUrl: `${getFrontendBaseUrl(options)}/verify-email?token=${email.sign(
|
|
1321
|
+
{
|
|
1322
|
+
userId: user.id,
|
|
1323
|
+
email: user.email
|
|
1324
|
+
}
|
|
1325
|
+
)}`,
|
|
1326
|
+
expiresIn: "1 hour"
|
|
1327
|
+
})
|
|
943
1328
|
});
|
|
944
1329
|
if (resendResult.rateLimited) {
|
|
945
1330
|
return res.status(429).json({
|
|
@@ -968,7 +1353,17 @@ function createAuthRouter(options = {}) {
|
|
|
968
1353
|
emailService: email,
|
|
969
1354
|
user,
|
|
970
1355
|
subject: "Reset password",
|
|
971
|
-
html: buildResetTemplate(resetToken, options)
|
|
1356
|
+
// html: buildResetTemplate(resetToken, options),
|
|
1357
|
+
html: buildResetPasswordEmailTemplate({
|
|
1358
|
+
firstName: user.firstName,
|
|
1359
|
+
resetUrl: `${getFrontendBaseUrl(options)}/reset-password?token=${email.sign(
|
|
1360
|
+
{
|
|
1361
|
+
userId: user.id,
|
|
1362
|
+
email: user.email
|
|
1363
|
+
}
|
|
1364
|
+
)}`,
|
|
1365
|
+
expiresIn: "1 hour"
|
|
1366
|
+
})
|
|
972
1367
|
});
|
|
973
1368
|
if (resetResult.rateLimited) {
|
|
974
1369
|
return res.status(429).json({
|
|
@@ -981,9 +1376,16 @@ function createAuthRouter(options = {}) {
|
|
|
981
1376
|
});
|
|
982
1377
|
r.post("/reset-password", validateResetPassword, async (req, res) => {
|
|
983
1378
|
const { token, newPassword } = req.body || {};
|
|
1379
|
+
if (!token || !newPassword) {
|
|
1380
|
+
return res.status(400).json({
|
|
1381
|
+
ok: false,
|
|
1382
|
+
error: "Token and new password are required",
|
|
1383
|
+
code: "MISSING_FIELDS"
|
|
1384
|
+
});
|
|
1385
|
+
}
|
|
984
1386
|
try {
|
|
985
1387
|
const payload = email.verify(token);
|
|
986
|
-
const user = await OrgUser.findOne({
|
|
1388
|
+
const user = await OrgUser.findOne({ id: payload.userId });
|
|
987
1389
|
if (!user) {
|
|
988
1390
|
return res.status(404).json({ ok: false, error: "User not found" });
|
|
989
1391
|
}
|
|
@@ -1374,12 +1776,6 @@ function respondWithKeycloakError(res, err, fallback, status = 400) {
|
|
|
1374
1776
|
const description = err?.response?.data?.error_description || err?.response?.data?.errorMessage || err?.message || fallback;
|
|
1375
1777
|
return res.status(status).json({ ok: false, error: description });
|
|
1376
1778
|
}
|
|
1377
|
-
function buildVerificationTemplate(token, options) {
|
|
1378
|
-
return `<a href="${getFrontendBaseUrl(options)}/auth/verify-email?token=${token}">Verify</a>`;
|
|
1379
|
-
}
|
|
1380
|
-
function buildResetTemplate(token, options) {
|
|
1381
|
-
return `<a href="${getFrontendBaseUrl(options)}/auth/reset-password?token=${token}">Reset</a>`;
|
|
1382
|
-
}
|
|
1383
1779
|
function getFrontendBaseUrl(options) {
|
|
1384
1780
|
if (options.frontendBaseUrl)
|
|
1385
1781
|
return options.frontendBaseUrl.replace(/\/$/, "");
|
|
@@ -1397,7 +1793,6 @@ async function sendRateLimitedEmail({
|
|
|
1397
1793
|
if (!can.ok) {
|
|
1398
1794
|
return { rateLimited: true, waitMs: can.waitMs };
|
|
1399
1795
|
}
|
|
1400
|
-
console.log(can, "can");
|
|
1401
1796
|
await emailService.send(user.email, subject, html);
|
|
1402
1797
|
user.lastEmailSent = [...user.lastEmailSent || [], /* @__PURE__ */ new Date()];
|
|
1403
1798
|
await user.save();
|