Feature: new "report a bug" modal (#13530)
* WIP: report a bug api/ui * fix lint * add USER_USERNAME * extend sendTxn tests / checks + fix bug report email * fix lint * add more checks to sendTxn - fix bug-report variables * fix lint / ci * fix test: reset email config url * fix test stub * fix tests * refactor the variables checks * lint. * move bug-report page as a modal * send user_email to the email * show true/false instead 1/0 * fix issues * fix footer report bug email if not logged in * fix styles/margins * prefill user's email * show facebook email if local email not existing * bugReportSuccessModal.vue * add BROWSER_UA to mail properties * extract bugReportLogic to its own lib file for unit test * test api validators * fix lint
This commit is contained in:
@@ -0,0 +1,53 @@
|
||||
import { authWithHeaders } from '../../middlewares/auth';
|
||||
import { bugReportLogic } from '../../libs/bug-report';
|
||||
|
||||
const api = {};
|
||||
|
||||
/**
|
||||
* @api {post} /api/v4/bug-report Report an issue
|
||||
* @apiName BugReport
|
||||
* @apiGroup BugReport
|
||||
* @apiDescription This POST method is used to send bug reports from the Website.
|
||||
* Since it needs the Users Data, it requires authentication.
|
||||
*
|
||||
* @apiParam (Body) {String} message Bug Report Message to sent
|
||||
* @apiParam (Body) {String} email User Email
|
||||
*
|
||||
* @apiSuccess {Object} data Result of this bug report
|
||||
* @apiSuccess {Boolean} data.ok Status of this report
|
||||
* @apiSuccess {String} data.message Status of this report
|
||||
*
|
||||
* @apiError (400) {BadRequest} emptyReportBugMessage The report message is missing.
|
||||
* @apiUse UserNotFound
|
||||
*/
|
||||
api.bugReport = {
|
||||
method: 'POST',
|
||||
url: '/bug-report',
|
||||
middlewares: [authWithHeaders()],
|
||||
async handler (req, res) {
|
||||
req.checkBody('message', res.t('emptyReportBugMessage')).notEmpty();
|
||||
req.checkBody('email', res.t('missingEmail')).notEmpty();
|
||||
req.checkBody('email', res.t('notAnEmail')).isEmail();
|
||||
|
||||
const validationErrors = req.validationErrors();
|
||||
if (validationErrors) throw validationErrors;
|
||||
|
||||
const { message, email } = req.body;
|
||||
const { user } = res.locals;
|
||||
const BROWSER_UA = req.get('User-Agent');
|
||||
|
||||
const {
|
||||
emailData, sendMailResult,
|
||||
} = bugReportLogic(
|
||||
user, email, message, BROWSER_UA,
|
||||
);
|
||||
|
||||
res.status(200).send({
|
||||
ok: true,
|
||||
emailData,
|
||||
sendMailResult,
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
export default api;
|
||||
@@ -0,0 +1,39 @@
|
||||
import nconf from 'nconf';
|
||||
import { convertVariableObjectToArray, sendTxn } from './email';
|
||||
|
||||
export async function bugReportLogic (
|
||||
user, userEmail, message, BROWSER_UA,
|
||||
) {
|
||||
const emailData = {
|
||||
USER_ID: user._id,
|
||||
USER_EMAIL: userEmail,
|
||||
USER_USERNAME: user.auth.local.username,
|
||||
USER_LEVEL: user.stats.lvl,
|
||||
USER_CLASS: user.stats.class,
|
||||
USER_DAILIES_PAUSED: user.preferences.sleep === 1 ? 'true' : 'false',
|
||||
USER_COSTUME: user.preferences.costume === 1 ? 'true' : 'false',
|
||||
USER_CUSTOM_DAY: user.preferences.dayStart,
|
||||
USER_TIMEZONE_OFFSET: user.preferences.timezoneOffset,
|
||||
USER_SUBSCRIPTION: user.purchased.plan.planId,
|
||||
USER_PAYMENT_PLATFORM: user.purchased.plan.paymentMethod,
|
||||
USER_CUSTOMER_ID: user.purchased.plan.customerId,
|
||||
USER_CONSECUTIVE_MONTHS: user.purchased.plan.consecutive.count,
|
||||
USER_OFFSET_MONTHS: user.purchased.plan.consecutive.offset,
|
||||
USER_HOURGLASSES: user.purchased.plan.consecutive.trinkets,
|
||||
REPORT_MSG: message,
|
||||
BROWSER_UA,
|
||||
};
|
||||
|
||||
const adminMail = { email: nconf.get('ADMIN_EMAIL') };
|
||||
|
||||
const sendMailResult = await sendTxn(
|
||||
adminMail,
|
||||
'report-a-bug',
|
||||
convertVariableObjectToArray(emailData),
|
||||
);
|
||||
|
||||
return {
|
||||
sendMailResult,
|
||||
emailData,
|
||||
};
|
||||
}
|
||||
@@ -67,12 +67,32 @@ export function getGroupUrl (group) {
|
||||
|
||||
// Send a transactional email using Mandrill through the external email server
|
||||
export async function sendTxn (mailingInfoArray, emailType, variables, personalVariables) {
|
||||
mailingInfoArray = Array.isArray(mailingInfoArray) ? mailingInfoArray : [mailingInfoArray]; // eslint-disable-line no-param-reassign, max-len
|
||||
if (!Array.isArray(mailingInfoArray)) {
|
||||
mailingInfoArray = [mailingInfoArray]; // eslint-disable-line no-param-reassign
|
||||
}
|
||||
|
||||
for (const entry of mailingInfoArray) {
|
||||
if (typeof entry === 'string'
|
||||
&& (typeof entry._id === 'undefined' && typeof entry.email === 'undefined')
|
||||
) {
|
||||
throw new Error('Argument Error mailingInfoArray: does not contain email or _id');
|
||||
}
|
||||
}
|
||||
|
||||
if (variables && !Array.isArray(variables)) {
|
||||
throw new Error('Argument Error variables: is not an array');
|
||||
}
|
||||
|
||||
variables = [ // eslint-disable-line no-param-reassign
|
||||
{ name: 'BASE_URL', content: BASE_URL },
|
||||
].concat(variables || []);
|
||||
|
||||
for (const variable of variables) {
|
||||
if (typeof variable.name === 'undefined' && typeof variable.content === 'undefined') {
|
||||
throw new Error('Argument Error variables: does not contain name or content');
|
||||
}
|
||||
}
|
||||
|
||||
// It's important to pass at least a user with its `preferences`
|
||||
// as we need to check if he unsubscribed
|
||||
mailingInfoArray = mailingInfoArray // eslint-disable-line no-param-reassign
|
||||
@@ -157,3 +177,17 @@ export async function sendTxn (mailingInfoArray, emailType, variables, personalV
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
export function convertVariableObjectToArray (variableObject) {
|
||||
const variablesArray = [];
|
||||
|
||||
const objectKeys = Object.keys(variableObject);
|
||||
for (const propName of objectKeys) {
|
||||
variablesArray.push({
|
||||
name: propName,
|
||||
content: variableObject[propName],
|
||||
});
|
||||
}
|
||||
|
||||
return variablesArray;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user