Merge branch 'release' into develop

This commit is contained in:
Sabe Jones
2019-07-22 16:38:07 -05:00
9 changed files with 31 additions and 101 deletions

View File

@@ -67,12 +67,6 @@
"SLACK_FLAGGING_URL": "https://hooks.slack.com/services/id/id/id",
"SLACK_SUBSCRIPTIONS_URL": "https://hooks.slack.com/services/id/id/id",
"SLACK_URL": "https://hooks.slack.com/services/some-url",
"SMTP_HOST": "example.com",
"SMTP_PASS": "password",
"SMTP_PORT": 587,
"SMTP_SERVICE": "Gmail",
"SMTP_TLS": "true",
"SMTP_USER": "user@example.com",
"STRIPE_API_KEY": "aaaabbbbccccddddeeeeffff00001111",
"STRIPE_PUB_KEY": "22223333444455556666777788889999",
"TEST_DB_URI": "mongodb://localhost/habitrpg_test",

View File

@@ -13,18 +13,19 @@ const questScrolls = shared.content.quests;
const progressCount = 1000;
let count = 0;
let backupUsers;
async function updateGroup (group) {
count++;
if (group && group.quest && group.quest.leader) {
if (group && group.quest && group.quest.key && group.quest.leader) {
const quest = questScrolls[group.quest.key];
const leader = await User.findOne({_id: group.quest.leader}).exec();
if (!leader) return;
await User.update({ _id: leader._id }, {
if (leader && quest) {
await User.update({
_id: leader._id,
migration: {$ne: MIGRATION_NAME},
}, {
$set: {migration: MIGRATION_NAME},
$inc: {
balance: 1,
@@ -37,6 +38,7 @@ async function updateGroup (group) {
sendTxnEmail(leader, 'groups-outage');
}
}
}
if (count % progressCount === 0) console.warn(`${count} ${group._id}`);
}
@@ -66,7 +68,7 @@ module.exports = async function processUsers () {
resolve(foundGroupInBackup);
}).catch(e => {
reject(e);
})
});
});
const groups = await groupsPromise;
@@ -77,7 +79,7 @@ module.exports = async function processUsers () {
break;
} else {
query._id = {
$gt: groups[groups.length - 1],
$gt: groups[groups.length - 1]._id,
};
}

2
package-lock.json generated
View File

@@ -1,6 +1,6 @@
{
"name": "habitica",
"version": "4.104.1",
"version": "4.104.2",
"lockfileVersion": 1,
"requires": true,
"dependencies": {

View File

@@ -1,7 +1,7 @@
{
"name": "habitica",
"description": "A habit tracker app which treats your goals like a Role Playing Game.",
"version": "4.104.1",
"version": "4.104.2",
"main": "./website/server/index.js",
"dependencies": {
"@google-cloud/trace-agent": "^4.0.0",
@@ -69,7 +69,6 @@
"nconf": "^0.10.0",
"node-gcm": "^1.0.2",
"node-sass": "^4.9.0",
"nodemailer": "^6.0.0",
"ora": "^3.2.0",
"pageres": "^5.1.0",
"passport": "^0.4.0",

View File

@@ -1,9 +1,7 @@
/* eslint-disable global-require */
import got from 'got';
import nconf from 'nconf';
import nodemailer from 'nodemailer';
import requireAgain from 'require-again';
import logger from '../../../../website/server/libs/logger';
import { TAVERN_ID } from '../../../../website/server/models/group';
import { defer } from '../../../helpers/api-unit.helper';
@@ -35,42 +33,6 @@ function getUser () {
describe('emails', () => {
let pathToEmailLib = '../../../../website/server/libs/email';
describe('sendEmail', () => {
let sendMailSpy;
beforeEach(() => {
sendMailSpy = sandbox.stub().returns(defer().promise);
sandbox.stub(nodemailer, 'createTransport').returns({
sendMail: sendMailSpy,
});
});
afterEach(() => {
sandbox.restore();
});
it('can send an email using the default transport', () => {
let attachEmail = requireAgain(pathToEmailLib);
attachEmail.send();
expect(sendMailSpy).to.be.calledOnce;
});
it('logs errors', (done) => {
sandbox.stub(logger, 'error');
let attachEmail = requireAgain(pathToEmailLib);
attachEmail.send();
expect(sendMailSpy).to.be.calledOnce;
defer().reject();
// wait for unhandledRejection event to fire
setTimeout(() => {
expect(logger.error).to.be.calledOnce;
done();
}, 20);
});
});
describe('getUserInfo', () => {
it('returns an empty object if no field request', () => {
let attachEmail = requireAgain(pathToEmailLib);
@@ -84,7 +46,7 @@ describe('emails', () => {
let user = getUser();
let data = getUserInfo(user, ['name', 'email', '_id', 'canSend']);
expect(data).to.have.property('name', user.profile.name);
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);
@@ -95,11 +57,11 @@ describe('emails', () => {
let getUserInfo = attachEmail.getUserInfo;
let user = getUser();
delete user.profile.name;
delete user.auth.local;
delete user.auth.local.email;
let data = getUserInfo(user, ['name', 'email', '_id', 'canSend']);
expect(data).to.have.property('name', user.profile.name);
expect(data).to.have.property('name', user.auth.local.username);
expect(data).to.have.property('email', user.auth.facebook.emails[0].value);
expect(data).to.have.property('_id', user._id);
expect(data).to.have.property('canSend', true);
@@ -114,7 +76,7 @@ describe('emails', () => {
let data = getUserInfo(user, ['name', 'email', '_id', 'canSend']);
expect(data).to.have.property('name', user.profile.name);
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);

View File

@@ -16,6 +16,7 @@ describe('payments/index', () => {
beforeEach(async () => {
user = new User();
user.profile.name = 'sender';
user.auth.local.username = 'sender';
await user.save();
group = generateGroup({

View File

@@ -278,9 +278,6 @@
"passwordConfirmationMatch": "Password confirmation doesn't match password.",
"passwordResetPage": "Reset Password",
"passwordReset": "If we have your email on file, instructions for setting a new password have been sent to your email.",
"passwordResetEmailSubject": "Password Reset for Habitica",
"passwordResetEmailText": "If you requested a password reset for <%= username %> on Habitica, head to <%= passwordResetLink %> to set a new one. The link will expire after 24 hours. If you haven't requested a password reset, please ignore this email.",
"passwordResetEmailHtml": "If you requested a password reset for <strong><%= username %></strong> on Habitica, <a href=\"<%= passwordResetLink %>\">click here</a> to set a new one. The link will expire after 24 hours.<br/><br>If you haven't requested a password reset, please ignore this email.",
"invalidLoginCredentialsLong": "Uh-oh - your email address / username or password is incorrect.\n- Make sure they are typed correctly. Your username and password are case-sensitive.\n- You may have signed up with Facebook or Google-sign-in, not email so double-check by trying them.\n- If you forgot your password, click \"Forgot Password\".",
"invalidCredentials": "There is no account that uses those credentials.",
"accountSuspended": "This account, User ID \"<%= userId %>\", has been blocked for breaking the Community Guidelines (https://habitica.com/static/community-guidelines) or Terms of Service (https://habitica.com/static/terms). For details or to ask to be unblocked, please email our Community Manager at <%= communityManagerEmail %> or ask your parent or guardian to email them. Please include your @Username in the email.",

View File

@@ -11,7 +11,7 @@ import {
BadRequest,
} from '../../libs/errors';
import * as passwordUtils from '../../libs/password';
import { send as sendEmail } from '../../libs/email';
import { sendTxn as sendTxnEmail } from '../../libs/email';
import { validatePasswordResetCodeAndFindUser, convertToBcrypt} from '../../libs/password';
import { encrypt } from '../../libs/encryption';
import {
@@ -303,19 +303,9 @@ api.resetPassword = {
user.auth.local.passwordResetCode = passwordResetCode;
sendEmail({
from: 'Habitica <admin@habitica.com>',
to: email,
subject: res.t('passwordResetEmailSubject'),
text: res.t('passwordResetEmailText', {
username: user.auth.local.username,
passwordResetLink: link,
}),
html: res.t('passwordResetEmailHtml', {
username: user.auth.local.username,
passwordResetLink: link,
}),
});
sendTxnEmail(user, 'reset-password', [
{name: 'PASSWORD_RESET_LINK', content: link},
]);
await user.save();
}

View File

@@ -1,4 +1,3 @@
import nodemailer from 'nodemailer';
import nconf from 'nconf';
import { TAVERN_ID } from '../models/group';
import { encrypt } from './encryption';
@@ -16,25 +15,11 @@ const EMAIL_SERVER = {
};
const BASE_URL = nconf.get('BASE_URL');
let smtpTransporter = nodemailer.createTransport({
service: nconf.get('SMTP_SERVICE'),
auth: {
user: nconf.get('SMTP_USER'),
pass: nconf.get('SMTP_PASS'),
},
});
// Send email directly from the server using the smtpTransporter,
// used only to send password reset emails because users unsubscribed on Mandrill wouldn't get them
export function send (mailData) {
return smtpTransporter.sendMail(mailData); // promise
}
export function getUserInfo (user, fields = []) {
let info = {};
if (fields.indexOf('name') !== -1) {
info.name = user.profile && user.profile.name;
info.name = user.auth && user.auth.local.username;
}
if (fields.indexOf('email') !== -1) {