Files
talk/plugins/talk-plugin-profile-data/server/connect.js
T
2018-06-05 04:28:54 +02:00

149 lines
4.3 KiB
JavaScript

const path = require('path');
const moment = require('moment');
const { CronJob } = require('cron');
const { get } = require('lodash');
const { ErrMissingEmail } = require('errors');
module.exports = connectors => {
const {
services: { Mailer, I18n },
models: { User },
graph: { Context },
} = connectors;
// Setup the mail templates.
['txt', 'html'].forEach(format => {
Mailer.templates.register(
path.join(__dirname, 'emails', `download.${format}.ejs`),
'download',
format
);
});
// Setup the cron job that will scan for accounts to delete every 30 minutes.
new CronJob({
cronTime: '0,30 * * * *',
timeZone: 'America/New_York',
start: true,
runOnInit: true,
onTick: async () => {
// Create the context we'll use to perform user deletions.
const ctx = Context.forSystem();
try {
// Grab some settings.
const {
loaders: { Settings },
} = ctx;
const {
organizationName,
organizationContactEmail,
} = await Settings.select(
'organizationName',
'organizationContactEmail'
);
// rescheduledDeletionDate is the date in the future that we'll set the
// user's account to be deleted on if this delete fails.
const rescheduledDeletionDate = moment()
.add(1, 'hours')
.toDate();
// Keep running for each user we can pull.
while (true) {
// We'll find any user that has an account deletion date before now
// and update the user such that their deletion time is 1 hour from
// now. This will ensure that only one instance can pull the same
// user at a time, and if the delete fails, it will be retried an
// hour from now. If the deletion was successful, well, it can't be
// retried because the reference to the scheduledDeletionDate will
// get deleted along with the user.
const user = await User.findOneAndUpdate(
{
'metadata.scheduledDeletionDate': { $lte: new Date() },
},
{
$set: {
'metadata.scheduledDeletionDate': rescheduledDeletionDate,
},
}
);
if (!user) {
// There are no more users that meet the search criteria! We're
// done!
ctx.log.info('no more users are scheduled for deletion');
break;
}
// Get the user's email address.
const reply = await ctx.graphql(
`
query GetUserEmailAddress($user_id: ID!) {
user(id: $user_id) {
email
}
}
`,
{ user_id: user.id }
);
if (reply.errors) {
throw reply.errors;
}
const email = get(reply, 'data.user.email');
if (!email) {
throw new ErrMissingEmail();
}
ctx.log.info(
{
userID: user.id,
scheduledDeletionDate: user.metadata.scheduledDeletionDate,
},
'starting user delete'
);
// Delete the user using the existing graph call.
const { data, errors } = await ctx.graphql(
`
mutation DeleteUser($user_id: ID!) {
delUser(id: $user_id) {
errors {
translation_key
}
}
}
`,
{ user_id: user.id }
);
if (errors) {
throw errors;
}
if (data.errors) {
throw data.errors;
}
ctx.log.info({ userID: user.id }, 'user was deleted successfully');
// Send the download link via the user's attached email account.
await Mailer.send({
template: 'plain',
locals: {
body: I18n.t(
'email.deleted.body',
organizationName,
organizationContactEmail
),
},
subject: I18n.t('email.deleted.subject', organizationName),
email,
});
}
} catch (err) {
ctx.log.error({ err }, 'could not handle user deletions');
}
},
});
};