mirror of
https://github.com/HabitRPG/habitica.git
synced 2025-12-17 22:57:21 +01:00
Record local email for social users where possible (#14029)
* fix(auth): record local email for social users where possible * fix(auth): Apple emails are junk, prefer Google * fix(auth): correct placement of logic to save local email * fix(auth): run full function in both workflows to avoid conflicts Co-authored-by: SabreCat <sabe@habitica.com>
This commit is contained in:
@@ -19,6 +19,7 @@ import {
|
||||
hasBackupAuth,
|
||||
loginSocial,
|
||||
registerLocal,
|
||||
socialEmailToLocal,
|
||||
} from '../../libs/auth';
|
||||
import { verifyUsername } from '../../libs/user/validation';
|
||||
|
||||
@@ -478,6 +479,7 @@ api.resetPasswordSetNewOne = {
|
||||
// set new password and make sure it's using bcrypt for hashing
|
||||
await passwordUtils.convertToBcrypt(user, String(newPassword));
|
||||
user.auth.local.passwordResetCode = undefined; // Reset saved password reset code
|
||||
if (!user.auth.local.email) user.auth.local.email = await socialEmailToLocal(user);
|
||||
await user.save();
|
||||
|
||||
return res.respond(200, {}, res.t('passwordChangeSuccess'));
|
||||
|
||||
@@ -12,7 +12,10 @@ import common from '../../../common';
|
||||
import logger from '../logger';
|
||||
import { decrypt } from '../encryption';
|
||||
import { model as Group } from '../../models/group';
|
||||
import { loginSocial } from './social';
|
||||
import {
|
||||
loginSocial,
|
||||
socialEmailToLocal,
|
||||
} from './social';
|
||||
import { loginRes } from './utils';
|
||||
import { verifyUsername } from '../user/validation';
|
||||
|
||||
@@ -227,4 +230,5 @@ export {
|
||||
hasLocalAuth,
|
||||
loginSocial,
|
||||
registerLocal,
|
||||
socialEmailToLocal,
|
||||
};
|
||||
|
||||
@@ -23,6 +23,21 @@ function _passportProfile (network, accessToken) {
|
||||
});
|
||||
}
|
||||
|
||||
export async function socialEmailToLocal (user) {
|
||||
const socialEmail = (user.auth.google && user.auth.google.emails
|
||||
&& user.auth.google.emails[0].value)
|
||||
|| (user.auth.facebook && user.auth.facebook.emails && user.auth.facebook.emails[0].value)
|
||||
|| (user.auth.apple && user.auth.apple.emails && user.auth.apple.emails[0].value);
|
||||
if (socialEmail) {
|
||||
const conflictingUser = await User.findOne(
|
||||
{ 'auth.local.email': socialEmail },
|
||||
{ _id: 1 },
|
||||
).exec();
|
||||
if (!conflictingUser) return socialEmail;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export async function loginSocial (req, res) { // eslint-disable-line import/prefer-default-export
|
||||
let existingUser = res.locals.user;
|
||||
const { network } = req.body;
|
||||
@@ -45,17 +60,23 @@ export async function loginSocial (req, res) { // eslint-disable-line import/pre
|
||||
[`auth.${network}.id`]: profile.id,
|
||||
}, { _id: 1, apiToken: 1, auth: 1 }).exec();
|
||||
|
||||
let email;
|
||||
if (profile.emails && profile.emails[0] && profile.emails[0].value) {
|
||||
email = profile.emails[0].value.toLowerCase();
|
||||
}
|
||||
|
||||
// User already signed up
|
||||
if (user) {
|
||||
if (existingUser) {
|
||||
throw new NotAuthorized(res.t('socialAlreadyExists'));
|
||||
}
|
||||
return loginRes(user, req, res);
|
||||
if (!user.auth.local.email) {
|
||||
user.auth.local.email = await socialEmailToLocal(user);
|
||||
if (user.auth.local.email) {
|
||||
await user.save();
|
||||
}
|
||||
|
||||
let email;
|
||||
if (profile.emails && profile.emails[0] && profile.emails[0].value) {
|
||||
email = profile.emails[0].value.toLowerCase();
|
||||
}
|
||||
return loginRes(user, req, res);
|
||||
}
|
||||
|
||||
if (!existingUser && email) {
|
||||
|
||||
Reference in New Issue
Block a user