[#1317] Update email consolidation script
- Update the emailConsolidation script so that it will de-duplicate the first duplicated user - Sends email to user alerting them that the consolidation has taken place.
This commit is contained in:
parent
f19f52683b
commit
cd5c000d6d
4 changed files with 173 additions and 16 deletions
|
@ -124,6 +124,7 @@ export function moveObjectToUserInS3(url, userId) {
|
||||||
const objectKey = getObjectKey(url);
|
const objectKey = getObjectKey(url);
|
||||||
const fileExtension = getExtension(objectKey);
|
const fileExtension = getExtension(objectKey);
|
||||||
const newFilename = uuid.v4() + fileExtension;
|
const newFilename = uuid.v4() + fileExtension;
|
||||||
|
console.log(`${process.env.S3_BUCKET}/${objectKey}`);
|
||||||
const params = {
|
const params = {
|
||||||
Bucket: `${process.env.S3_BUCKET}`,
|
Bucket: `${process.env.S3_BUCKET}`,
|
||||||
CopySource: `${process.env.S3_BUCKET}/${objectKey}`,
|
CopySource: `${process.env.S3_BUCKET}/${objectKey}`,
|
||||||
|
|
|
@ -3,6 +3,8 @@ import User from '../models/user';
|
||||||
import Project from '../models/project';
|
import Project from '../models/project';
|
||||||
import Collection from '../models/collection';
|
import Collection from '../models/collection';
|
||||||
import { moveObjectToUserInS3 } from '../controllers/aws.controller';
|
import { moveObjectToUserInS3 } from '../controllers/aws.controller';
|
||||||
|
import mail from '../utils/mail';
|
||||||
|
import { renderAccountConsolidation } from '../views/mail';
|
||||||
|
|
||||||
|
|
||||||
const mongoConnectionString = process.env.MONGO_URL;
|
const mongoConnectionString = process.env.MONGO_URL;
|
||||||
|
@ -50,16 +52,31 @@ const agg = [
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
||||||
|
// steps to make this work
|
||||||
|
// iterate through the results
|
||||||
|
// check if any files are on AWS
|
||||||
|
// if so, move them to the right user bucket
|
||||||
|
// then, update the user to currentUser
|
||||||
|
// then, after updating all of the projects
|
||||||
|
// also update the collections
|
||||||
|
// delete other users
|
||||||
|
// update user email so it is all lowercase
|
||||||
|
// then, send the email
|
||||||
|
// then, figure out how to iterate through all of the users.
|
||||||
|
|
||||||
let currentUser = null;
|
let currentUser = null;
|
||||||
let duplicates = null;
|
let duplicates = null;
|
||||||
User.aggregate(agg).then((result) => {
|
User.aggregate(agg).then((result) => {
|
||||||
|
console.log(result);
|
||||||
const email = result[0]._id;
|
const email = result[0]._id;
|
||||||
return User.find({ email }).collation({ locale: 'en', strength: 2 })
|
return User.find({ email }).collation({ locale: 'en', strength: 2 })
|
||||||
.sort({ createdAt: 1 }).exec();
|
.sort({ createdAt: 1 }).exec();
|
||||||
}).then((result) => {
|
}).then((result) => {
|
||||||
[currentUser, ...duplicates] = result;
|
[currentUser, ...duplicates] = result;
|
||||||
|
console.log('Current User: ', currentUser._id, ' ', currentUser.email);
|
||||||
duplicates = duplicates.map(dup => dup._id);
|
duplicates = duplicates.map(dup => dup._id);
|
||||||
console.log(duplicates);
|
console.log('Duplicates: ', duplicates);
|
||||||
return Project.find({
|
return Project.find({
|
||||||
user: { $in: duplicates }
|
user: { $in: duplicates }
|
||||||
}).exec();
|
}).exec();
|
||||||
|
@ -68,7 +85,7 @@ User.aggregate(agg).then((result) => {
|
||||||
sketches.forEach((sketch) => {
|
sketches.forEach((sketch) => {
|
||||||
const moveSketchFilesPromises = [];
|
const moveSketchFilesPromises = [];
|
||||||
sketch.files.forEach((file) => {
|
sketch.files.forEach((file) => {
|
||||||
if (file.url.includes('assets.editor.p5js.org')) {
|
if (file.url && file.url.includes(process.env.S3_BUCKET_URL_BASE)) {
|
||||||
const fileSavePromise = moveObjectToUserInS3(file.url, currentUser._id)
|
const fileSavePromise = moveObjectToUserInS3(file.url, currentUser._id)
|
||||||
.then((newUrl) => {
|
.then((newUrl) => {
|
||||||
file.url = newUrl;
|
file.url = newUrl;
|
||||||
|
@ -83,19 +100,38 @@ User.aggregate(agg).then((result) => {
|
||||||
saveSketchPromises.push(sketchSavePromise);
|
saveSketchPromises.push(sketchSavePromise);
|
||||||
});
|
});
|
||||||
return Promise.all(saveSketchPromises);
|
return Promise.all(saveSketchPromises);
|
||||||
// iterate through the results
|
}).then(() => {
|
||||||
// check if any files are on AWS
|
console.log('Moved and updated all sketches.');
|
||||||
// if so, move them to the right user bucket
|
return Collection.updateMany(
|
||||||
// then, update the user to currentUser
|
{ owner: { $in: duplicates } },
|
||||||
// then, after updating all of the projects
|
{ $set: { owner: ObjectId(currentUser.id) } }
|
||||||
// also update the collections
|
);
|
||||||
// delete other users
|
}).then(() => {
|
||||||
// update user email so it is all lowercase
|
console.log('Moved and updated all collections.');
|
||||||
// then, send the email
|
return User.deleteMany({ _id: { $in: duplicates } });
|
||||||
}).then(() => Collection.updateMany(
|
}).then(() => {
|
||||||
{ owner: { $in: duplicates } },
|
console.log('Deleted other user accounts.');
|
||||||
{ $set: { owner: ObjectId(currentUser.id) } }
|
currentUser.email = currentUser.email.toLowerCase();
|
||||||
)).then(() => User.deleteMany({ _id: { $in: duplicates } })).catch((err) => {
|
return currentUser.save();
|
||||||
console.log(err);
|
}).then(() => {
|
||||||
|
console.log('Migrated email to lowercase.');
|
||||||
|
// const protocol = process.env.NODE_ENV === 'production' ? 'https' : 'http';
|
||||||
|
const mailOptions = renderAccountConsolidation({
|
||||||
|
body: {
|
||||||
|
domain: 'https://editor.p5js.org',
|
||||||
|
username: currentUser.username,
|
||||||
|
email: currentUser.email
|
||||||
|
},
|
||||||
|
to: currentUser.email,
|
||||||
|
});
|
||||||
|
|
||||||
|
mail.send(mailOptions, (mailErr, result) => {
|
||||||
|
console.log('Sent email.');
|
||||||
|
process.exit(0);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// ).then((result) => {
|
||||||
|
// console.log(result);
|
||||||
|
// });
|
||||||
|
|
||||||
|
|
78
server/views/consolidationMailLayout.js
Normal file
78
server/views/consolidationMailLayout.js
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
export default ({
|
||||||
|
domain,
|
||||||
|
headingText,
|
||||||
|
greetingText,
|
||||||
|
messageText,
|
||||||
|
username,
|
||||||
|
email,
|
||||||
|
message2Text,
|
||||||
|
resetPasswordLink,
|
||||||
|
directLinkText,
|
||||||
|
resetPasswordText,
|
||||||
|
noteText,
|
||||||
|
meta
|
||||||
|
}) => (
|
||||||
|
`
|
||||||
|
<mjml>
|
||||||
|
<mj-head>
|
||||||
|
<mj-raw>
|
||||||
|
<meta name="keywords" content="${meta.keywords}" />
|
||||||
|
<meta name="description" content="${meta.description}" />
|
||||||
|
</mj-raw>
|
||||||
|
</mj-head>
|
||||||
|
<mj-body>
|
||||||
|
<mj-container>
|
||||||
|
<mj-section>
|
||||||
|
<mj-column>
|
||||||
|
<mj-image width="192" src="${domain}/images/p5js-square-logo.png" alt="p5.js" />
|
||||||
|
<mj-divider border-color="#ed225d"></mj-divider>
|
||||||
|
</mj-column>
|
||||||
|
</mj-section>
|
||||||
|
|
||||||
|
<mj-section>
|
||||||
|
<mj-column>
|
||||||
|
<mj-text font-size="20px" color="#333333" font-family="sans-serif">
|
||||||
|
${headingText}
|
||||||
|
</mj-text>
|
||||||
|
</mj-column>
|
||||||
|
</mj-section>
|
||||||
|
|
||||||
|
<mj-section>
|
||||||
|
<mj-column>
|
||||||
|
<mj-text color="#333333">
|
||||||
|
${greetingText}
|
||||||
|
</mj-text>
|
||||||
|
<mj-text color="#333333">
|
||||||
|
${messageText}
|
||||||
|
</mj-text>
|
||||||
|
<mj-text color="#333333">
|
||||||
|
<span style="font-weight:bold;">Username:</span> ${username}
|
||||||
|
</mj-text>
|
||||||
|
<mj-text color="#333333">
|
||||||
|
<span style="font-weight:bold;">Email:</span> ${email}
|
||||||
|
</mj-text>
|
||||||
|
<mj-text color="#333333">
|
||||||
|
${message2Text}
|
||||||
|
</mj-text>
|
||||||
|
<mj-button background-color="#ed225d" href="${domain}/${resetPasswordLink}">
|
||||||
|
${resetPasswordText}
|
||||||
|
</mj-button>
|
||||||
|
</mj-column>
|
||||||
|
</mj-section>
|
||||||
|
|
||||||
|
<mj-section>
|
||||||
|
<mj-column>
|
||||||
|
<mj-text color="#333333">
|
||||||
|
${directLinkText}
|
||||||
|
</mj-text>
|
||||||
|
<mj-text align="center" color="#333333"><a href="${domain}/${resetPasswordLink}">${domain}/${resetPasswordLink}</a></mj-text>
|
||||||
|
<mj-text color="#333333">
|
||||||
|
${noteText}
|
||||||
|
</mj-text>
|
||||||
|
</mj-column>
|
||||||
|
</mj-section>
|
||||||
|
</mj-container>
|
||||||
|
</mj-body>
|
||||||
|
</mjml>
|
||||||
|
`
|
||||||
|
);
|
|
@ -1,5 +1,47 @@
|
||||||
import renderMjml from '../utils/renderMjml';
|
import renderMjml from '../utils/renderMjml';
|
||||||
import mailLayout from './mailLayout';
|
import mailLayout from './mailLayout';
|
||||||
|
import consolidationMailLayout from './consolidationMailLayout';
|
||||||
|
|
||||||
|
export const renderAccountConsolidation = (data) => {
|
||||||
|
const subject = 'p5.js Web Editor Account Consolidation';
|
||||||
|
const templateOptions = {
|
||||||
|
domain: data.body.domain,
|
||||||
|
headingText: 'Account Consolidation',
|
||||||
|
greetingText: 'Hello,',
|
||||||
|
messageText: `You're receiving this message because you previous registered for the
|
||||||
|
<a href="https://editor.p5js.org">p5.js Web Editor</a>
|
||||||
|
using the same email address multiple times. In order to fix bugs and prevent future bugs,
|
||||||
|
your accounts have been consolidated to the first account you created. You can login with
|
||||||
|
the following email and username:`,
|
||||||
|
username: data.body.username,
|
||||||
|
email: data.body.email,
|
||||||
|
message2Text: `All of your sketches and collections have been preserved and have not been modified.
|
||||||
|
If you have forgotten your password you can reset it:`,
|
||||||
|
resetPasswordLink: 'reset-password',
|
||||||
|
resetPasswordText: 'Reset Password',
|
||||||
|
directLinkText: 'Or copy and paste the following URL into your browser:',
|
||||||
|
noteText: `We are grateful for your patience and understanding. Thank you for supporting p5.js and the
|
||||||
|
p5.js Web Editor!`,
|
||||||
|
meta: {
|
||||||
|
keywords: 'p5.js, p5.js web editor, web editor, processing, code editor',
|
||||||
|
description: 'A web editor for p5.js, a JavaScript library with the goal'
|
||||||
|
+ ' of making coding accessible to artists, designers, educators, and beginners.'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Return MJML string
|
||||||
|
const template = consolidationMailLayout(templateOptions);
|
||||||
|
|
||||||
|
// Render MJML to HTML string
|
||||||
|
const html = renderMjml(template);
|
||||||
|
|
||||||
|
// Return options to send mail
|
||||||
|
return Object.assign(
|
||||||
|
{},
|
||||||
|
data,
|
||||||
|
{ html, subject },
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
export const renderResetPassword = (data) => {
|
export const renderResetPassword = (data) => {
|
||||||
const subject = 'p5.js Web Editor Password Reset';
|
const subject = 'p5.js Web Editor Password Reset';
|
||||||
|
|
Loading…
Reference in a new issue