Files
habitica/test/api/unit/libs/email.test.js
Phillip Thelen 24841346dc Purge Facebook (#13696)
* Don't sign in user when trying to connect a social account that was already created

* Log social users into matching local auth accounts

If the social account has an email that already exists as a local user, instead of creating a new account log them into their account and add the social auth to the account

* If possible set local authentication email for social users

* Allow password reset emails to be sent to social login users

* lint fixes

* Fix issues and tests

* fix tests

* Fix lint error.

* purge Facebook.

Only keep it in some select places to allow for some compatablilty.

* Fix error

* fix error

* Let settings handle it when you don't have a password set but an email

* fix error

* Fix boolean logic

* fix json conversion

* .

* fix password reset for old social accounts

* Don't sign in user when trying to connect a social account that was already created

* Log social users into matching local auth accounts

If the social account has an email that already exists as a local user, instead of creating a new account log them into their account and add the social auth to the account

* If possible set local authentication email for social users

* Allow password reset emails to be sent to social login users

* lint fixes

* Fix issues and tests

* fix tests

* Fix lint error.

* purge Facebook.

Only keep it in some select places to allow for some compatablilty.

* Fix error

* fix error

* Let settings handle it when you don't have a password set but an email

* fix error

* Fix boolean logic

* fix json conversion

* fix password reset for old social accounts

* Revert "lint fixes"

This reverts commit c244b1651c.

# Conflicts:
#	website/client/src/components/auth/registerLoginReset.vue
#	website/client/src/components/static/contact.vue

* Revert "fix password reset for old social accounts"

This reverts commit 7e0069a80f.

* fix duplicate code

* chore(misc): remove irrelevant changes

* chore(privacy): update policy page with note about FB

Co-authored-by: SabreCat <sabe@habitica.com>
2022-09-15 18:22:52 -05:00

268 lines
8.2 KiB
JavaScript

/* eslint-disable global-require */
import got from 'got';
import nconf from 'nconf';
import requireAgain from 'require-again';
import { TAVERN_ID } from '../../../../website/server/models/group';
import { defer } from '../../../helpers/api-unit.helper';
function getUser () {
return {
_id: 'random _id',
auth: {
local: {
username: 'username',
email: 'email@email',
},
google: {
emails: [{
value: 'email@google',
}],
},
apple: {
emails: [{
value: 'email@apple',
}],
},
},
profile: {
name: 'profile name',
},
preferences: {
emailNotifications: {
unsubscribeFromAll: false,
},
},
};
}
describe('emails', () => {
const pathToEmailLib = '../../../../website/server/libs/email';
describe('getUserInfo', () => {
it('returns an empty object if no field request', () => {
const attachEmail = requireAgain(pathToEmailLib);
const { getUserInfo } = attachEmail;
expect(getUserInfo({}, [])).to.be.empty;
});
it('returns correct user data', () => {
const attachEmail = requireAgain(pathToEmailLib);
const { getUserInfo } = attachEmail;
const user = getUser();
const data = getUserInfo(user, ['name', 'email', '_id', 'canSend']);
expect(data).to.have.property('name', user.auth.local.username);
expect(data).to.have.property('email', user.auth.local.email);
expect(data).to.have.property('_id', user._id);
expect(data).to.have.property('canSend', true);
});
it('returns correct user data [google users]', () => {
const attachEmail = requireAgain(pathToEmailLib);
const { getUserInfo } = attachEmail;
const user = getUser();
delete user.profile.name;
delete user.auth.local.email;
delete user.auth.apple.emails;
const data = getUserInfo(user, ['name', 'email', '_id', 'canSend']);
expect(data).to.have.property('name', user.auth.local.username);
expect(data).to.have.property('email', user.auth.google.emails[0].value);
expect(data).to.have.property('_id', user._id);
expect(data).to.have.property('canSend', true);
});
it('returns correct user data [apple users]', () => {
const attachEmail = requireAgain(pathToEmailLib);
const { getUserInfo } = attachEmail;
const user = getUser();
delete user.profile.name;
delete user.auth.local.email;
delete user.auth.google.emails;
const data = getUserInfo(user, ['name', 'email', '_id', 'canSend']);
expect(data).to.have.property('name', user.auth.local.username);
expect(data).to.have.property('email', user.auth.apple.emails[0].value);
expect(data).to.have.property('_id', user._id);
expect(data).to.have.property('canSend', true);
});
it('has fallbacks for missing data', () => {
const attachEmail = requireAgain(pathToEmailLib);
const { getUserInfo } = attachEmail;
const user = getUser();
delete user.auth.local.email;
delete user.auth.google;
delete user.auth.apple;
const data = getUserInfo(user, ['name', 'email', '_id', 'canSend']);
expect(data).to.have.property('name', user.auth.local.username);
expect(data).not.to.have.property('email');
expect(data).to.have.property('_id', user._id);
expect(data).to.have.property('canSend', true);
});
});
describe('getGroupUrl', () => {
it('returns correct url if group is the tavern', () => {
const { getGroupUrl } = require(pathToEmailLib); // eslint-disable-line import/no-dynamic-require, max-len
expect(getGroupUrl({ _id: TAVERN_ID, type: 'guild' })).to.eql('/groups/tavern');
});
it('returns correct url if group is a guild', () => {
const { getGroupUrl } = require(pathToEmailLib); // eslint-disable-line import/no-dynamic-require, max-len
expect(getGroupUrl({ _id: 'random _id', type: 'guild' })).to.eql('/groups/guild/random _id');
});
it('returns correct url if group is a party', () => {
const { getGroupUrl } = require(pathToEmailLib); // eslint-disable-line import/no-dynamic-require, max-len
expect(getGroupUrl({ _id: 'random _id', type: 'party' })).to.eql('party');
});
});
describe('sendTxn', () => {
let sendTxn = null;
beforeEach(() => {
sandbox.stub(got, 'post').returns(defer().promise);
const nconfGetStub = sandbox.stub(nconf, 'get');
nconfGetStub.withArgs('IS_PROD').returns(true);
nconfGetStub.withArgs('BASE_URL').returns('BASE_URL');
const attachEmail = requireAgain(pathToEmailLib);
sendTxn = attachEmail.sendTxn;
});
afterEach(() => {
sandbox.restore();
});
it('can send a txn email to one recipient', () => {
const emailType = 'an email type';
const mailingInfo = {
name: 'my name',
email: 'my@email',
};
sendTxn(mailingInfo, emailType);
expect(got.post).to.be.called;
expect(got.post).to.be.calledWith('undefined/job', sinon.match({
json: {
data: {
emailType: sinon.match.same(emailType),
to: sinon.match(value => Array.isArray(value) && value[0].name === mailingInfo.name, 'matches mailing info array'),
},
},
}));
});
it('does not send email if address is missing', () => {
const emailType = 'an email type';
const mailingInfo = {
name: 'my name',
// email: 'my@email',
};
sendTxn(mailingInfo, emailType);
expect(got.post).not.to.be.called;
});
it('throws error when mail target is only a string', () => {
const emailType = 'an email type';
const mailingInfo = 'my email';
expect(sendTxn(mailingInfo, emailType)).to.throw;
});
it('throws error when mail target has no _id or email', () => {
const emailType = 'an email type';
const mailingInfo = {
};
expect(sendTxn(mailingInfo, emailType)).to.throw;
});
it('throws error when variables not an array', () => {
const emailType = 'an email type';
const mailingInfo = {
name: 'my name',
email: 'my@email',
};
const variables = {};
expect(sendTxn(mailingInfo, emailType, variables)).to.throw;
});
it('throws error when variables array not contain name/content', () => {
const emailType = 'an email type';
const mailingInfo = {
name: 'my name',
email: 'my@email',
};
const variables = [
{
},
];
expect(sendTxn(mailingInfo, emailType, variables)).to.throw;
});
it('throws no error when variables array contain name but no content', () => {
const emailType = 'an email type';
const mailingInfo = {
name: 'my name',
email: 'my@email',
};
const variables = [
{
name: 'MY_VAR',
},
];
expect(sendTxn(mailingInfo, emailType, variables)).to.not.throw;
});
it('uses getUserInfo in case of user data', () => {
const emailType = 'an email type';
const mailingInfo = getUser();
sendTxn(mailingInfo, emailType);
expect(got.post).to.be.called;
expect(got.post).to.be.calledWith('undefined/job', sinon.match({
json: {
data: {
emailType: sinon.match.same(emailType),
to: sinon.match(val => val[0]._id === mailingInfo._id),
},
},
}));
});
it('sends email with some default variables', () => {
const emailType = 'an email type';
const mailingInfo = {
name: 'my name',
email: 'my@email',
};
const variables = [];
sendTxn(mailingInfo, emailType, variables);
expect(got.post).to.be.called;
expect(got.post).to.be.calledWith('undefined/job', sinon.match({
json: {
data: {
variables: sinon.match(value => value[0].name === 'BASE_URL', 'matches variables'),
personalVariables: sinon.match(value => value[0].rcpt === mailingInfo.email
&& value[0].vars[0].name === 'RECIPIENT_NAME'
&& value[0].vars[1].name === 'RECIPIENT_UNSUB_URL', 'matches personal variables'),
},
},
}));
});
});
});