Add create and confirm account emails in backend
This commit is contained in:
parent
fd84706104
commit
040b967725
|
@ -1,4 +1,5 @@
|
|||
{
|
||||
"domain": "localhost",
|
||||
"port": 3000,
|
||||
"db_engine": "postgres",
|
||||
"sqlite_location": "./database.sqlite",
|
||||
|
@ -11,6 +12,8 @@
|
|||
"email_port": 465,
|
||||
"email_username": null,
|
||||
"email_password": "password",
|
||||
"email_from_name": "Readlebee Admin",
|
||||
"email_from_address": null,
|
||||
"jwtSecretKey": "SomethingAtLeast32CharactersLong!",
|
||||
"tokenExpireDays": 7,
|
||||
"inventaireDomain": "https://inventaire.io"
|
||||
|
|
|
@ -58,6 +58,19 @@ class Account {
|
|||
}
|
||||
}
|
||||
|
||||
static confirmAccountDataIsValid(createAccountData) {
|
||||
if (typeof createAccountData.id === 'undefined'
|
||||
|| typeof createAccountData.confirm === 'undefined'
|
||||
|| !createAccountData.confirm) {
|
||||
return {
|
||||
error: true,
|
||||
message: 'api.account_confirm_required_data_missing',
|
||||
};
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
async emailExists (email) {
|
||||
const existingUser = await this.model.find({
|
||||
attributes: ['id'],
|
||||
|
@ -109,6 +122,39 @@ class Account {
|
|||
accountConfirm: needsConfirmation ? crypto.randomBytes(32).toString('hex') : null,
|
||||
});
|
||||
}
|
||||
|
||||
async confirmUser (id, accountConfirm) {
|
||||
const userToConfirm = await this.model.findOne({
|
||||
where: {
|
||||
id,
|
||||
accountConfirm,
|
||||
},
|
||||
});
|
||||
|
||||
if (!userToConfirm) {
|
||||
return {
|
||||
error: true,
|
||||
message: 'api.account_confirm_invalid_code',
|
||||
}
|
||||
}
|
||||
|
||||
return await this.model.update({
|
||||
accountConfirm: null,
|
||||
}, {
|
||||
where: {
|
||||
id,
|
||||
accountConfirm,
|
||||
},
|
||||
}).then(success => {
|
||||
if (success[0] < 1) {
|
||||
return {
|
||||
error: true,
|
||||
message: 'api.account_confirm_update_fail',
|
||||
}
|
||||
}
|
||||
return userToConfirm;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@ const sequelizeConfig = {
|
|||
switch (fastify.siteConfig.db_engine) {
|
||||
case 'sqlite': {
|
||||
sequelizeConfig.storage = typeof fastify.siteConfig.sqlite_location !== 'undefined'
|
||||
? path.resolve(fastify.siteConfig.sqlite_location)
|
||||
? path.resolve(__dirname, fastify.siteConfig.sqlite_location)
|
||||
: path.resolve(__dirname, './database.sqlite');
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const Account = require('../controllers/account');
|
||||
|
||||
async function routes(fastify, options) {
|
||||
|
@ -27,20 +29,56 @@ async function routes(fastify, options) {
|
|||
return reply.code(400).send(canCreateUser);
|
||||
}
|
||||
|
||||
const result = await account.createUser(formData.email, formData.username, formData.displayName, formData.password, fastify.canEmail);
|
||||
const newUser = await account.createUser(formData.email, formData.username, formData.displayName, formData.password, fastify.canEmail);
|
||||
|
||||
if (typeof result.error !== 'undefined') {
|
||||
return reply.code(400).send(result);
|
||||
if (typeof newUser.error !== 'undefined') {
|
||||
return reply.code(400).send(newUser);
|
||||
}
|
||||
|
||||
if (fastify.canEmail) {
|
||||
// fastify.nodemailer.sendMail();
|
||||
return reply.send({
|
||||
try {
|
||||
const file = fs.readFileSync(path.resolve(__dirname, '../templates/email.confirm_account.txt'));
|
||||
console.log(file.toString());
|
||||
const text = file.toString()
|
||||
.replace(/\{display_name\}/g, newUser.displayName)
|
||||
.replace(/\{username\}/g, newUser.username)
|
||||
.replace(/\{domain\}/g, fastify.siteConfig.domain)
|
||||
.replace(/\{id\}/g, newUser.id)
|
||||
.replace(/\{code\}/g, newUser.accountConfirm)
|
||||
.replace(/\{sender\}/g, fastify.siteConfig.email_from_name);
|
||||
|
||||
return fastify.nodemailer.sendMail({
|
||||
// Default to email_username if email_from_address is null/falsy
|
||||
from: `"${fastify.siteConfig.email_from_name}" ${!fastify.siteConfig.email_from_address ? fastify.siteConfig.email_username : fastify.siteConfig.email_from_address}`,
|
||||
to: `"${newUser.displayName}" ${newUser.email}`,
|
||||
subject: 'Please Confirm your Account',
|
||||
text,
|
||||
// Definitely gonna have to wait to design the HTML version of the email!
|
||||
// html: '<p>HTML version of the message</p>',
|
||||
}).then(email => {
|
||||
if (email.err) {
|
||||
console.error(email.err);
|
||||
return reply.send({
|
||||
error: true,
|
||||
message: 'api.account_email_send_fail',
|
||||
newUser,
|
||||
});
|
||||
}
|
||||
|
||||
return reply.send({
|
||||
error: false,
|
||||
message: 'api.account_confirm_email',
|
||||
});
|
||||
})
|
||||
} catch (ex) {
|
||||
console.error(ex);
|
||||
return reply.send({
|
||||
error: false,
|
||||
message: 'api.account_create_success',
|
||||
});
|
||||
}
|
||||
} else {
|
||||
const token = fastify.jwt.sign({ id: result.id });
|
||||
const token = fastify.jwt.sign({ id: newUser.id });
|
||||
const expireTime = fastify.siteConfig.tokenExpireDays * (24 * 60 * 60e3); // The section in parentheses is milliseconds in a day
|
||||
|
||||
return reply
|
||||
|
@ -58,6 +96,68 @@ async function routes(fastify, options) {
|
|||
}
|
||||
});
|
||||
|
||||
fastify.post('/api/account/confirm', async (request, reply) => {
|
||||
if (request.isLoggedInUser) {
|
||||
return reply.code(400).send({
|
||||
error: true,
|
||||
message: 'api.account_already_logged_in',
|
||||
});
|
||||
}
|
||||
|
||||
const formDataIsValid = Account.confirmAccountDataIsValid(request.body);
|
||||
if (formDataIsValid !== true) {
|
||||
return reply.code(400).send(formDataIsValid);
|
||||
}
|
||||
|
||||
const account = new Account(fastify.models.User);
|
||||
|
||||
const confirmed = await account.confirmUser(request.body.id, request.body.confirm);
|
||||
|
||||
if (typeof confirmed.error !== 'undefined') {
|
||||
return reply.code(400).send(confirmed);
|
||||
}
|
||||
|
||||
// Expects email to be working, and indeed it should be working because that's how the confirmation code was sent.
|
||||
try {
|
||||
const file = fs.readFileSync(path.resolve(__dirname, '../templates/email.confirm_account_thanks.txt'));
|
||||
console.log(file.toString());
|
||||
const text = file.toString()
|
||||
.replace(/\{display_name\}/g, confirmed.displayName)
|
||||
.replace(/\{username\}/g, confirmed.username)
|
||||
.replace(/\{domain\}/g, fastify.siteConfig.domain)
|
||||
.replace(/\{sender\}/g, fastify.siteConfig.email_from_name);
|
||||
|
||||
return fastify.nodemailer.sendMail({
|
||||
// Default to email_username if email_from_address is null/falsy
|
||||
from: `"${fastify.siteConfig.email_from_name}" ${!fastify.siteConfig.email_from_address ? fastify.siteConfig.email_username : fastify.siteConfig.email_from_address}`,
|
||||
to: `"${confirmed.displayName}" ${confirmed.email}`,
|
||||
subject: 'Account Confirmed Successfully',
|
||||
text,
|
||||
// Definitely gonna have to wait to design the HTML version of the email!
|
||||
// html: '<p>HTML version of the message</p>',
|
||||
}).then(email => {
|
||||
if (email.err) {
|
||||
console.error(email.err);
|
||||
return reply.send({
|
||||
error: true,
|
||||
message: 'api.account_confirm_email_send_fail',
|
||||
});
|
||||
}
|
||||
|
||||
return reply.send({
|
||||
error: false,
|
||||
message: 'api.account_confirm_success_email',
|
||||
});
|
||||
})
|
||||
} catch (ex) {
|
||||
console.error(ex);
|
||||
return reply.send({
|
||||
error: false,
|
||||
message: 'api.account_confirm_success',
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
fastify.get('/api/login', async (request, reply) => {
|
||||
reply.view('login.hbs', { text: request.isLoggedInUser ? JSON.stringify(fastify.jwt.decode(request.cookies.token)) : 'you are NOT logged in' });
|
||||
});
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
Hello {display_name} (username: {username}),
|
||||
|
||||
Someone used this email address to create an account at {domain}.
|
||||
|
||||
If this was you, please confirm your account and log in using the link below:
|
||||
|
||||
{domain}/login?id={id}&confirm={code}
|
||||
|
||||
Thanks!
|
||||
{sender}
|
|
@ -0,0 +1,10 @@
|
|||
Hello {display_name} (username: {username}),
|
||||
|
||||
You have successfully confirmed your account on {domain}.
|
||||
|
||||
You may now log in using your email address and password at the following address:
|
||||
|
||||
{domain}/login
|
||||
|
||||
Thanks!
|
||||
{sender}
|
Loading…
Reference in New Issue