Extract controller code
This commit is contained in:
parent
51fe1c24c0
commit
53adf04b16
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"tabWidth": 2,
|
||||
"useTabs": false,
|
||||
"printWidth": 120
|
||||
}
|
|
@ -0,0 +1,144 @@
|
|||
const { validationResult } = require("express-validator");
|
||||
const { isSignatureValid, getToken } = require("./utils");
|
||||
const Subscribers = require("../models/subscribers");
|
||||
const Verifications = require("../models/verifications");
|
||||
|
||||
class Controller {
|
||||
static subscribe(dappConfig, mailer) {
|
||||
return async (req, res) => {
|
||||
const {
|
||||
params: { dappId },
|
||||
body: { address, email, signature }
|
||||
} = req;
|
||||
|
||||
const errors = validationResult(req);
|
||||
if (!errors.isEmpty()) {
|
||||
return res.status(404).json({ errors: errors.array() });
|
||||
}
|
||||
|
||||
if (!dappConfig.isDapp(dappId)) {
|
||||
return res.status(404).send("Invalid dapp");
|
||||
}
|
||||
|
||||
if (!isSignatureValid(address, email, signature)) {
|
||||
return res.status(404).send("Invalid signature");
|
||||
}
|
||||
|
||||
// TODO: handle subscriptions to particular events
|
||||
|
||||
try {
|
||||
const subscriber = await Subscribers.findOne({
|
||||
dappId,
|
||||
address
|
||||
});
|
||||
|
||||
const t = getToken();
|
||||
|
||||
if (!subscriber) {
|
||||
const s = await Subscribers.create({
|
||||
dappId,
|
||||
email,
|
||||
address
|
||||
});
|
||||
|
||||
await Verifications.create({
|
||||
...t,
|
||||
subscriber: s._id
|
||||
});
|
||||
} else if (!subscriber.isVerified) {
|
||||
const d = new Date(subscriber.lastSignUpAttempt);
|
||||
d.setMinutes(d.getMinutes() + 5);
|
||||
if (d > new Date()) {
|
||||
return res.status(400).send("You need to wait at least 5 minutes between sign up attempts");
|
||||
}
|
||||
|
||||
subscriber.lastSignUpAttempt = d;
|
||||
await subscriber.save();
|
||||
|
||||
await Verification.create({
|
||||
...t,
|
||||
subscriber: subscriber._id
|
||||
});
|
||||
}
|
||||
|
||||
if (!subscriber || !subscriber.isVerified) {
|
||||
const template = dappConfig.template(dappId, "sign-up");
|
||||
mailer.send(dappConfig.getEmailTemplate(dappId, template), dappConfig.config(dappId).from, {
|
||||
email,
|
||||
token: t.token
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
// TODO: add global error handler
|
||||
return res.status(400).send(err.message);
|
||||
}
|
||||
|
||||
return res.status(200).send("OK");
|
||||
};
|
||||
}
|
||||
|
||||
static unsubscribe(dappConfig) {
|
||||
return async (req, res) => {
|
||||
// TODO:
|
||||
const {
|
||||
params: { dappId },
|
||||
body: { address, signature }
|
||||
} = req;
|
||||
|
||||
if (!dappConfig.isDapp(dappId)) {
|
||||
return res.status(404).send("Invalid dapp");
|
||||
}
|
||||
|
||||
if (!isSignatureValid(address, dappId, signature)) {
|
||||
return res.status(404).send("Invalid signature");
|
||||
}
|
||||
|
||||
// TODO: handle unsubscribe to particular events
|
||||
|
||||
try {
|
||||
await Subscribers.deleteOne({
|
||||
dappId,
|
||||
address
|
||||
});
|
||||
} catch (err) {
|
||||
// TODO: add global error handler
|
||||
return res.status(400).send(err.message);
|
||||
}
|
||||
|
||||
return res.status(200).send("OK");
|
||||
};
|
||||
}
|
||||
|
||||
static confirm() {
|
||||
return async (req, res) => {
|
||||
const {
|
||||
params: { token }
|
||||
} = req;
|
||||
|
||||
const verification = await Verifications.findOne({
|
||||
token
|
||||
}).populate("subscriber");
|
||||
|
||||
if (verification) {
|
||||
if (verification.expirationTime < new Date()) {
|
||||
return res.status(400).send("Verification token already expired");
|
||||
}
|
||||
|
||||
if (!verification.subscriber.isVerified) {
|
||||
verification.subscriber.isVerified = true;
|
||||
await verification.subscriber.save();
|
||||
}
|
||||
|
||||
await Verifications.deleteMany({
|
||||
subscriber: verification.subscriber._id
|
||||
});
|
||||
} else {
|
||||
return res.status(400).send("Invalid verification token");
|
||||
}
|
||||
|
||||
return res.status(200).send("OK");
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Controller;
|
151
api/index.js
151
api/index.js
|
@ -1,20 +1,17 @@
|
|||
const Events = require("events");
|
||||
const { isSignatureValid, getToken, hexValidator } = require("./utils");
|
||||
const { hexValidator } = require("./utils");
|
||||
const express = require("express");
|
||||
const { check, validationResult } = require("express-validator");
|
||||
const { check } = require("express-validator");
|
||||
const cors = require("cors");
|
||||
const helmet = require("helmet");
|
||||
const rateLimit = require("../middleware/rate-limit");
|
||||
const config = require("../config");
|
||||
const Database = require("../database");
|
||||
const Subscribers = require("../models/subscribers");
|
||||
const Verifications = require("../models/verifications");
|
||||
const Mailer = require("../mail/sendgrid");
|
||||
const DappConfig = require("../config/dapps");
|
||||
|
||||
const Controller = require("./controller");
|
||||
|
||||
const events = new Events();
|
||||
|
||||
const dappConfig = new DappConfig();
|
||||
const mailer = new Mailer(config);
|
||||
const db = new Database(events, config);
|
||||
|
@ -47,84 +44,7 @@ events.on("db:connected", () => {
|
|||
.isEmail(),
|
||||
check("dappId").exists()
|
||||
],
|
||||
async (req, res) => {
|
||||
const {
|
||||
params: { dappId },
|
||||
body: { address, email, signature }
|
||||
} = req;
|
||||
|
||||
const errors = validationResult(req);
|
||||
if (!errors.isEmpty()) {
|
||||
return res.status(404).json({ errors: errors.array() });
|
||||
}
|
||||
|
||||
if (!dappConfig.isDapp(dappId)) {
|
||||
return res.status(404).send("Invalid dapp");
|
||||
}
|
||||
|
||||
if (!isSignatureValid(address, email, signature)) {
|
||||
return res.status(404).send("Invalid signature");
|
||||
}
|
||||
|
||||
// TODO: handle subscriptions to particular events
|
||||
|
||||
try {
|
||||
const subscriber = await Subscribers.findOne({
|
||||
dappId,
|
||||
address
|
||||
});
|
||||
|
||||
const t = getToken();
|
||||
|
||||
if (!subscriber) {
|
||||
const s = await Subscribers.create({
|
||||
dappId,
|
||||
email,
|
||||
address
|
||||
});
|
||||
|
||||
await Verifications.create({
|
||||
...t,
|
||||
subscriber: s._id
|
||||
});
|
||||
} else if (!subscriber.isVerified) {
|
||||
const d = new Date(subscriber.lastSignUpAttempt);
|
||||
d.setMinutes(d.getMinutes() + 5);
|
||||
if (d > new Date()) {
|
||||
return res
|
||||
.status(400)
|
||||
.send(
|
||||
"You need to wait at least 5 minutes between sign up attempts"
|
||||
);
|
||||
}
|
||||
|
||||
subscriber.lastSignUpAttempt = d;
|
||||
await subscriber.save();
|
||||
|
||||
await Verification.create({
|
||||
...t,
|
||||
subscriber: subscriber._id
|
||||
});
|
||||
}
|
||||
|
||||
if (!subscriber || !subscriber.isVerified) {
|
||||
const template = dappConfig.template(dappId, "sign-up");
|
||||
mailer.send(
|
||||
dappConfig.getEmailTemplate(dappId, template),
|
||||
dappConfig.config(dappId).from,
|
||||
{
|
||||
email,
|
||||
token: t.token
|
||||
}
|
||||
);
|
||||
}
|
||||
} catch (err) {
|
||||
// TODO: add global error handler
|
||||
return res.status(400).send(err.message);
|
||||
}
|
||||
|
||||
return res.status(200).send("OK");
|
||||
}
|
||||
Controller.subscribe(dappConfig, mailer)
|
||||
);
|
||||
|
||||
app.post(
|
||||
|
@ -140,71 +60,14 @@ events.on("db:connected", () => {
|
|||
.custom(hexValidator),
|
||||
check("dappId").exists()
|
||||
],
|
||||
async (req, res) => {
|
||||
// TODO:
|
||||
const {
|
||||
params: { dappId },
|
||||
body: { address, signature }
|
||||
} = req;
|
||||
|
||||
if (!dappConfig.isDapp(dappId)) {
|
||||
return res.status(404).send("Invalid dapp");
|
||||
}
|
||||
|
||||
if (!isSignatureValid(address, dappId, signature)) {
|
||||
return res.status(404).send("Invalid signature");
|
||||
}
|
||||
|
||||
// TODO: handle unsubscribe to particular events
|
||||
|
||||
try {
|
||||
await Subscribers.deleteOne({
|
||||
dappId,
|
||||
address
|
||||
});
|
||||
} catch (err) {
|
||||
// TODO: add global error handler
|
||||
return res.status(400).send(err.message);
|
||||
}
|
||||
|
||||
return res.status(200).send("OK");
|
||||
}
|
||||
Controller.unsubscribe(dappConfig)
|
||||
);
|
||||
|
||||
app.get("/confirm/:token", [check("token").exists()], async (req, res) => {
|
||||
const {
|
||||
params: { token }
|
||||
} = req;
|
||||
|
||||
const verification = await Verifications.findOne({
|
||||
token
|
||||
}).populate("subscriber");
|
||||
|
||||
if (verification) {
|
||||
if (verification.expirationTime < new Date()) {
|
||||
return res.status(400).send("Verification token already expired");
|
||||
}
|
||||
|
||||
if (!verification.subscriber.isVerified) {
|
||||
verification.subscriber.isVerified = true;
|
||||
await verification.subscriber.save();
|
||||
}
|
||||
|
||||
await Verifications.deleteMany({
|
||||
subscriber: verification.subscriber._id
|
||||
});
|
||||
} else {
|
||||
return res.status(400).send("Invalid verification token");
|
||||
}
|
||||
|
||||
return res.status(200).send("OK");
|
||||
});
|
||||
app.get("/confirm/:token", [check("token").exists()], Controller.confirm());
|
||||
|
||||
app.get("/", (req, res) => res.status(200).json({ ok: true }));
|
||||
|
||||
app.listen(config.PORT, () =>
|
||||
console.log(`App listening on port ${config.PORT}!`)
|
||||
);
|
||||
app.listen(config.PORT, () => console.log(`App listening on port ${config.PORT}!`));
|
||||
});
|
||||
|
||||
// MVP
|
||||
|
|
|
@ -20,8 +20,8 @@ const config = {
|
|||
/* Email */
|
||||
SENDGRID_API_KEY: secret.SENDGRID_API_KEY,
|
||||
/* WATCHER */
|
||||
BLOCK_DELAY: 5, // ~60-70 secs... this could be helpful to avoid reorgs
|
||||
POLL_SLEEP: 60 // seconds
|
||||
BLOCK_DELAY: 6, // [Recommended 6 ~80 secs...] this could be helpful to avoid reorgs
|
||||
POLL_SLEEP: 30 // seconds
|
||||
};
|
||||
|
||||
module.exports = config;
|
||||
|
|
Loading…
Reference in New Issue