Added opt-in option for promotional emails

This commit is contained in:
2021-02-11 16:01:39 +11:00
parent 7759a1cd40
commit 615b686890
19 changed files with 848 additions and 83 deletions
+7 -1
View File
@@ -2,10 +2,16 @@ const express = require('express');
const router = express.Router();
//basic account management
router.get('/', require('./query'));
router.patch('/', require('./update'));
//signup -> login -> logout
router.post('/signup', require('./signup'));
router.get('/validation', require('./validation'));
router.post('/login', require('./login'));
router.post('/logout', require('./logout'));
router.post('/deletion', require('./deletion'));
//account deletion
router.delete('/deletion', require('./deletion'));
module.exports = router;
+1 -1
View File
@@ -37,7 +37,7 @@ const route = async (req, res) => {
}
//save the session and cookie data
req.session.account = account;
req.session.account = JSON.parse(JSON.stringify(account.dataValues));
res.cookie('loggedin', process.env.WEB_ADDRESS);
if (account.privilege == 'administrator') {
+21
View File
@@ -0,0 +1,21 @@
const { accounts } = require('../database/models');
const route = async (req, res) => {
if (!req.session.account || !req.session.account.id) {
res.status(401).send('Unknown account');
}
//update the reference
req.session.account = (await accounts.findOne({
where: {
id: req.session.account.id
}
})).dataValues;
//respond with the private-facing data
res.status(200).json({
contact: req.session.account.contact
});
};
module.exports = route;
+8 -2
View File
@@ -101,6 +101,7 @@ const registerPendingSignup = async (fields, hash, token) => {
email: fields.email,
username: fields.username,
hash: hash,
contact: fields.contact,
token: token
});
@@ -109,7 +110,12 @@ const registerPendingSignup = async (fields, hash, token) => {
const sendValidationEmail = async (email, username, token) => {
const addr = `${process.env.WEB_PROTOCOL}://${process.env.WEB_ADDRESS}/api/accounts/validation?username=${username}&token=${token}`;
const msg = `Hello! Please visit the following address to validate your account: ${addr}`;
const msg = `Hello ${username}!
Please visit the following link to validate your account: ${addr}
You can contact us directly at our physical mailing address here: ${process.env.MAIL_PHYSICAL}
`;
let transporter, info;
@@ -143,7 +149,7 @@ const sendValidationEmail = async (email, username, token) => {
}
if (info.accepted[0] != email) {
return 'validation email failed';
return 'validation email failed to send';
}
return null;
+28
View File
@@ -0,0 +1,28 @@
const { accounts } = require('../database/models');
const route = async (req, res) => {
if (!req.session.account.id) {
return res.status(500).send('missing account data');
}
//update the account
await accounts.update({
contact: req.fields.contact
}, {
where: {
id: req.session.account.id
}
});
//update the reference
req.session.account = (await accounts.findOne({
where: {
id: req.session.account.id
}
})).dataValues;
//respond with an OK
res.status(200).send('Information updated');
};
module.exports = route;
+2 -1
View File
@@ -29,7 +29,8 @@ const route = async (req, res) => {
accounts.create({
email: info.email,
username: info.username,
hash: info.hash
hash: info.hash,
contact: info.contact
});
//finally
+25
View File
@@ -0,0 +1,25 @@
//DOCS: this whole file is just a big bugfix
//DOCS: ensure that there is at least one administration account
const bcrypt = require('bcryptjs');
const { accounts } = require('../database/models');
const defaultAdminAccount = async () => {
const admin = await accounts.findOne({
where: {
privilege: 'administrator'
}
});
if (admin == null) {
await accounts.create({
privilege: 'administrator',
email: `admin@${process.env.WEB_ADDRESS}`,
username: `admin`,
hash: await bcrypt.hash('password', await bcrypt.genSalt(11))
});
console.log(`Created default admin account (email: admin@${process.env.WEB_ADDRESS}; password: password)`);
}
};
module.exports = defaultAdminAccount;
-23
View File
@@ -16,27 +16,4 @@ router.get('/banned', require('./banned'));
router.post('/ban', require('./ban'));
router.post('/unban', require('./unban'));
//DOCS: ensure that there is at least one administration account
const bcrypt = require('bcryptjs');
const { accounts } = require('../database/models');
(async () => {
const admin = await accounts.findOne({
where: {
privilege: 'administrator'
}
});
if (admin == null) {
await accounts.create({
privilege: 'administrator',
email: `admin@${process.env.WEB_ADDRESS}`,
username: `admin`,
hash: await bcrypt.hash('password', await bcrypt.genSalt(11))
});
console.log(`Created default admin account (email: admin@${process.env.WEB_ADDRESS}; password: password)`);
}
})();
module.exports = router;
+6
View File
@@ -28,6 +28,12 @@ module.exports = sequelize.define('accounts', {
hash: 'varchar(100)', //for passwords
contact: {
type: Sequelize.BOOLEAN,
allowNull: false,
defaultValue: false
},
deletion: {
type: 'DATETIME',
allowNull: true,
@@ -14,5 +14,11 @@ module.exports = sequelize.define('pendingSignups', {
hash: 'varchar(100)', //for passwords
contact: {
type: Sequelize.BOOLEAN,
allowNull: false,
defaultValue: false
},
token: Sequelize.INTEGER(11)
});
+14 -4
View File
@@ -11,19 +11,29 @@ const path = require('path');
const formidable = require('express-formidable');
const cookieParser = require('cookie-parser');
const session = require('express-session');
app.use(formidable());
app.use(cookieParser());
app.use(session({ secret: process.env.SESSION_SECRET, resave: true, saveUninitialized: true }));
const SequelizeStore = require("connect-session-sequelize")(session.Store);
//database connection
const database = require('./database');
const models = require('./database/models'); //invoke all models
app.use(formidable());
app.use(cookieParser());
app.use(session({
secret: process.env.SESSION_SECRET,
resave: true,
saveUninitialized: true,
store: new SequelizeStore({
db: database
})
}));
//account management
app.use('/api/accounts', require('./accounts'));
//administration
app.use('/api/admin', require('./admin'));
require('./admin/bookkeeper')(); //BUGFIX
//send static files
app.use('/', express.static(path.resolve(__dirname, '..', 'public')));