mirror of
https://github.com/HabitRPG/habitica.git
synced 2025-12-18 15:17:25 +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,
|
hasBackupAuth,
|
||||||
loginSocial,
|
loginSocial,
|
||||||
registerLocal,
|
registerLocal,
|
||||||
|
socialEmailToLocal,
|
||||||
} from '../../libs/auth';
|
} from '../../libs/auth';
|
||||||
import { verifyUsername } from '../../libs/user/validation';
|
import { verifyUsername } from '../../libs/user/validation';
|
||||||
|
|
||||||
@@ -478,6 +479,7 @@ api.resetPasswordSetNewOne = {
|
|||||||
// set new password and make sure it's using bcrypt for hashing
|
// set new password and make sure it's using bcrypt for hashing
|
||||||
await passwordUtils.convertToBcrypt(user, String(newPassword));
|
await passwordUtils.convertToBcrypt(user, String(newPassword));
|
||||||
user.auth.local.passwordResetCode = undefined; // Reset saved password reset code
|
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();
|
await user.save();
|
||||||
|
|
||||||
return res.respond(200, {}, res.t('passwordChangeSuccess'));
|
return res.respond(200, {}, res.t('passwordChangeSuccess'));
|
||||||
|
|||||||
@@ -12,7 +12,10 @@ import common from '../../../common';
|
|||||||
import logger from '../logger';
|
import logger from '../logger';
|
||||||
import { decrypt } from '../encryption';
|
import { decrypt } from '../encryption';
|
||||||
import { model as Group } from '../../models/group';
|
import { model as Group } from '../../models/group';
|
||||||
import { loginSocial } from './social';
|
import {
|
||||||
|
loginSocial,
|
||||||
|
socialEmailToLocal,
|
||||||
|
} from './social';
|
||||||
import { loginRes } from './utils';
|
import { loginRes } from './utils';
|
||||||
import { verifyUsername } from '../user/validation';
|
import { verifyUsername } from '../user/validation';
|
||||||
|
|
||||||
@@ -227,4 +230,5 @@ export {
|
|||||||
hasLocalAuth,
|
hasLocalAuth,
|
||||||
loginSocial,
|
loginSocial,
|
||||||
registerLocal,
|
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
|
export async function loginSocial (req, res) { // eslint-disable-line import/prefer-default-export
|
||||||
let existingUser = res.locals.user;
|
let existingUser = res.locals.user;
|
||||||
const { network } = req.body;
|
const { network } = req.body;
|
||||||
@@ -45,19 +60,25 @@ export async function loginSocial (req, res) { // eslint-disable-line import/pre
|
|||||||
[`auth.${network}.id`]: profile.id,
|
[`auth.${network}.id`]: profile.id,
|
||||||
}, { _id: 1, apiToken: 1, auth: 1 }).exec();
|
}, { _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
|
// User already signed up
|
||||||
if (user) {
|
if (user) {
|
||||||
if (existingUser) {
|
if (existingUser) {
|
||||||
throw new NotAuthorized(res.t('socialAlreadyExists'));
|
throw new NotAuthorized(res.t('socialAlreadyExists'));
|
||||||
}
|
}
|
||||||
|
if (!user.auth.local.email) {
|
||||||
|
user.auth.local.email = await socialEmailToLocal(user);
|
||||||
|
if (user.auth.local.email) {
|
||||||
|
await user.save();
|
||||||
|
}
|
||||||
|
}
|
||||||
return loginRes(user, req, res);
|
return loginRes(user, req, res);
|
||||||
}
|
}
|
||||||
|
|
||||||
let email;
|
|
||||||
if (profile.emails && profile.emails[0] && profile.emails[0].value) {
|
|
||||||
email = profile.emails[0].value.toLowerCase();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!existingUser && email) {
|
if (!existingUser && email) {
|
||||||
existingUser = await User.findOne({ 'auth.local.email': email }).exec();
|
existingUser = await User.findOne({ 'auth.local.email': email }).exec();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user