@dax-crafta/auth 2.1.2 → 2.1.4
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/src/models/user.js +2 -2
- package/src/services/auth.service.js +39 -1
- package/src/utils/email.js +4 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dax-crafta/auth",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.4",
|
|
4
4
|
"description": "A powerful, flexible, and secure authentication plugin for the Crafta framework. Supports JWT, social login, 2FA, RBAC, audit logging, and enterprise-grade security features.",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"types": "src/index.d.ts",
|
package/src/models/user.js
CHANGED
|
@@ -89,10 +89,10 @@ userSchema.methods.comparePassword = async function (candidate) {
|
|
|
89
89
|
return bcrypt.compare(candidate, this.password);
|
|
90
90
|
};
|
|
91
91
|
|
|
92
|
-
userSchema.methods.recordPasswordHistory = async function () {
|
|
92
|
+
userSchema.methods.recordPasswordHistory = async function (previousPasswordHash) {
|
|
93
93
|
this.passwordHistory = this.passwordHistory || [];
|
|
94
94
|
this.passwordHistory.push({
|
|
95
|
-
hash: this.password,
|
|
95
|
+
hash: previousPasswordHash || this.password,
|
|
96
96
|
changedAt: new Date()
|
|
97
97
|
});
|
|
98
98
|
|
|
@@ -204,9 +204,10 @@ class AuthService {
|
|
|
204
204
|
throw new ApiError('Cannot reuse previous passwords', 400);
|
|
205
205
|
}
|
|
206
206
|
|
|
207
|
+
const previousPasswordHash = user.password;
|
|
207
208
|
user.password = newPassword;
|
|
208
209
|
|
|
209
|
-
await user.recordPasswordHistory();
|
|
210
|
+
await user.recordPasswordHistory(previousPasswordHash);
|
|
210
211
|
await user.revokeAllRefreshTokens(); // session invalidate
|
|
211
212
|
user.passwordResetToken = undefined;
|
|
212
213
|
user.passwordResetExpires = undefined;
|
|
@@ -341,6 +342,43 @@ class AuthService {
|
|
|
341
342
|
return true;
|
|
342
343
|
}
|
|
343
344
|
|
|
345
|
+
async handleSocialLogin(provider, profile) {
|
|
346
|
+
if (!profile) {
|
|
347
|
+
throw new ApiError('Social profile is required', 400);
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
const primaryEmail = profile.emails?.[0]?.value;
|
|
351
|
+
if (!primaryEmail) {
|
|
352
|
+
throw new ApiError('Social provider did not return an email', 400);
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
let user = await User.findOne({ email: primaryEmail });
|
|
356
|
+
|
|
357
|
+
if (!user) {
|
|
358
|
+
user = new User({
|
|
359
|
+
email: primaryEmail,
|
|
360
|
+
password: this.generateSecureToken(),
|
|
361
|
+
isVerified: true,
|
|
362
|
+
customFields: {
|
|
363
|
+
socialProvider: provider,
|
|
364
|
+
socialId: profile.id,
|
|
365
|
+
name: profile.displayName
|
|
366
|
+
}
|
|
367
|
+
});
|
|
368
|
+
await user.save();
|
|
369
|
+
} else if (profile.displayName) {
|
|
370
|
+
user.customFields = {
|
|
371
|
+
...(user.customFields || {}),
|
|
372
|
+
socialProvider: provider,
|
|
373
|
+
socialId: profile.id,
|
|
374
|
+
name: profile.displayName
|
|
375
|
+
};
|
|
376
|
+
await user.save();
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
return user;
|
|
380
|
+
}
|
|
381
|
+
|
|
344
382
|
|
|
345
383
|
|
|
346
384
|
/* ---------------------------------------------
|
package/src/utils/email.js
CHANGED
|
@@ -57,7 +57,8 @@ class EmailService {
|
|
|
57
57
|
}
|
|
58
58
|
|
|
59
59
|
async sendVerificationEmail(user, token) {
|
|
60
|
-
const
|
|
60
|
+
const verifyPath = this.config.routes?.verify || '/verify';
|
|
61
|
+
const url = `${this.config.baseUrl}${verifyPath}?token=${token}`;
|
|
61
62
|
|
|
62
63
|
const html = this.loadTemplate("email-verification", {
|
|
63
64
|
name: user.name || user.email,
|
|
@@ -73,7 +74,8 @@ class EmailService {
|
|
|
73
74
|
}
|
|
74
75
|
|
|
75
76
|
async sendPasswordResetEmail(user, token) {
|
|
76
|
-
const
|
|
77
|
+
const resetPath = this.config.routes?.resetPassword || '/reset-password';
|
|
78
|
+
const url = `${this.config.baseUrl}${resetPath}?token=${token}`;
|
|
77
79
|
|
|
78
80
|
const html = this.loadTemplate("password-reset", {
|
|
79
81
|
name: user.name || user.email,
|