Update routes to use new DB api
This commit is contained in:
Родитель
4353ec66cd
Коммит
e78b3e2e12
30
db/utils.js
30
db/utils.js
|
@ -48,6 +48,26 @@ const DBUtils = {
|
|||
return await this._addEmailHash(sha1, email);
|
||||
},
|
||||
|
||||
async removeSubscriber(email) {
|
||||
const sha1 = getSha1(email);
|
||||
|
||||
// Check if an entry exists.
|
||||
const existingEntries = await EmailHash
|
||||
.query()
|
||||
.where("sha1", sha1);
|
||||
|
||||
// If not, nothing to be done, return.
|
||||
if (!existingEntries.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Patch out the email from the entry.
|
||||
await existingEntries[0]
|
||||
.$query()
|
||||
.patch({ email: null })
|
||||
.returning('*'); // Postgres trick to return the updated row as model.
|
||||
},
|
||||
|
||||
async addBreachedHash(breachName, sha1) {
|
||||
console.log(`Adding ${sha1} to ${breachName}`);
|
||||
const addedEmailHash = await this._addEmailHash(sha1);
|
||||
|
@ -61,6 +81,10 @@ const DBUtils = {
|
|||
.relate(addedEmailHash.id);
|
||||
},
|
||||
|
||||
addBreachedEmail(breachName, email) {
|
||||
return this.addBreachedHash(breachName, getSha1(email));
|
||||
},
|
||||
|
||||
async getBreachesForHash(sha1) {
|
||||
console.log(`Finding EmailHash entry for ${sha1}`);
|
||||
const emailHashesBySha1 = await EmailHash
|
||||
|
@ -70,7 +94,11 @@ const DBUtils = {
|
|||
return await emailHashesBySha1[0]
|
||||
.$relatedQuery("breaches")
|
||||
.orderBy("name");
|
||||
}
|
||||
},
|
||||
|
||||
getBreachesForEmail(email) {
|
||||
return this.getBreachesForHash(getSha1(email));
|
||||
},
|
||||
};
|
||||
|
||||
module.exports = DBUtils;
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
"use strict";
|
||||
|
||||
const crypto = require("crypto");
|
||||
const express = require("express");
|
||||
const bodyParser = require("body-parser");
|
||||
|
||||
const models = require("../db/models");
|
||||
const DBUtils = require("../db/utils");
|
||||
|
||||
const router = express.Router();
|
||||
const urlEncodedParser = bodyParser.urlencoded({ extended: false });
|
||||
|
@ -19,11 +18,9 @@ router.post("/scan", urlEncodedParser, async (req, res) => {
|
|||
const email = req.body.email;
|
||||
let foundBreaches;
|
||||
if (email) {
|
||||
const emailHash = await models.EmailHash.findOne({ where: { sha1: getSha1(email) }});
|
||||
if (emailHash) {
|
||||
foundBreaches = (await emailHash.getBreaches()).map(aBreach => aBreach.dataValues);
|
||||
}
|
||||
foundBreaches = await DBUtils.getBreachesForEmail(email);
|
||||
}
|
||||
|
||||
res.render("scan", {
|
||||
title: "Firefox Breach Alerts: Scan Results",
|
||||
email: email,
|
||||
|
@ -31,8 +28,4 @@ router.post("/scan", urlEncodedParser, async (req, res) => {
|
|||
});
|
||||
});
|
||||
|
||||
function getSha1(email) {
|
||||
return crypto.createHash("sha1").update(email).digest("hex");
|
||||
}
|
||||
|
||||
module.exports = router;
|
||||
|
|
|
@ -8,7 +8,7 @@ const express = require("express");
|
|||
const bodyParser = require("body-parser");
|
||||
const popsicle = require("popsicle");
|
||||
|
||||
const models = require("../db/models");
|
||||
const DBUtils = require("../db/utils");
|
||||
|
||||
// This object exists instead of inlining the env vars to make it easy
|
||||
// to abstract fetching API endpoints from the OAuth server (instead
|
||||
|
@ -58,8 +58,7 @@ router.get("/confirmed", jsonParser, async (req, res) => {
|
|||
},
|
||||
});
|
||||
const email = JSON.parse(data.body).email;
|
||||
const user = await models.Subscriber.create({ email: email });
|
||||
user.saveSha1();
|
||||
const user = await DBUtils.addSubscriber(email);
|
||||
|
||||
res.render("confirm", {
|
||||
title: "Firefox Breach Alerts: Subscribed",
|
||||
|
|
|
@ -4,8 +4,9 @@ const AppConstants = require("../app-constants");
|
|||
|
||||
const express = require("express");
|
||||
const bodyParser = require("body-parser");
|
||||
const crypto = require("crypto");
|
||||
|
||||
const models = require("../db/models");
|
||||
const DBUtils = require("../db/utils");
|
||||
const EmailUtils = require("../email-utils");
|
||||
|
||||
const ResponseCodes = Object.freeze({
|
||||
|
@ -19,17 +20,22 @@ const router = express.Router();
|
|||
const jsonParser = bodyParser.json();
|
||||
const urlEncodedParser = bodyParser.urlencoded({ extended: false });
|
||||
|
||||
const tempUserStore = new Map();
|
||||
|
||||
router.post("/add", urlEncodedParser, async (req, res) => {
|
||||
const user = await models.Subscriber.create({ email: req.body.email });
|
||||
const url = `${AppConstants.SERVER_URL}/user/verify?state=${encodeURIComponent(user.verificationToken)}&email=${encodeURIComponent(user.email)}`;
|
||||
const email = req.body.email;
|
||||
const verificationToken = crypto.randomBytes(40).toString("hex");
|
||||
tempUserStore.set(verificationToken, email);
|
||||
const url = `${AppConstants.SERVER_URL}/user/verify?state=${encodeURIComponent(verificationToken)}&email=${encodeURIComponent(email)}`;
|
||||
console.log(url); // Temporary for debugging.
|
||||
|
||||
try {
|
||||
await EmailUtils.sendEmail(user.email, "Firefox Breach Alert",
|
||||
await EmailUtils.sendEmail(email, "Firefox Breach Alert",
|
||||
`Visit this link to subscribe: ${url}`);
|
||||
|
||||
res.render("add", {
|
||||
title: "Verify email",
|
||||
email: user.email,
|
||||
email: email,
|
||||
});
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
|
@ -41,24 +47,23 @@ router.post("/add", urlEncodedParser, async (req, res) => {
|
|||
});
|
||||
|
||||
router.get("/verify", jsonParser, async (req, res) => {
|
||||
const user = await models.Subscriber.findOne({ where: { email: req.query.email, verificationToken: req.query.state } });
|
||||
if (user === null) {
|
||||
const email = tempUserStore.get(req.query.state);
|
||||
if (!email || email !== req.query.email) {
|
||||
res.status(400).json({
|
||||
error_code: ResponseCodes.EmailNotFound,
|
||||
info: "Email not found or verification token does not match.",
|
||||
});
|
||||
return;
|
||||
}
|
||||
// TODO: make a better user "verified" status than implicit presence of
|
||||
// SHA1 hash value
|
||||
user.saveSha1();
|
||||
|
||||
await DBUtils.addSubscriber(email);
|
||||
res.status(201).json({
|
||||
info: `Successfully verified ${user.email}`,
|
||||
info: `Successfully verified ${email}`,
|
||||
});
|
||||
});
|
||||
|
||||
router.post("/remove", jsonParser, async (req, res) => {
|
||||
models.Subscriber.destroy({ where: { email: req.query.email } });
|
||||
await DBUtils.removeSubscriber(req.body.email);
|
||||
res.status(200).json({
|
||||
info: "Deleted user.",
|
||||
});
|
||||
|
|
|
@ -5,8 +5,7 @@ const Knex = require("knex");
|
|||
const knexConfig = require('../../db/knexfile');
|
||||
const { Model } = require("objection");
|
||||
|
||||
const DBUtils = require("../../db/utils.js")
|
||||
const getSha1 = require("../../sha1-utils");
|
||||
const DBUtils = require("../../db/utils")
|
||||
|
||||
const knex = Knex(knexConfig.development);
|
||||
Model.knex(knex);
|
||||
|
@ -33,12 +32,12 @@ const sampleBreaches = [
|
|||
for (const sB of sampleBreaches) {
|
||||
await DBUtils.createBreach(sB.name, sB.meta);
|
||||
for (const e of sB.emails) {
|
||||
await DBUtils.addBreachedHash(sB.name, getSha1(e));
|
||||
await DBUtils.addBreachedEmail(sB.name, e);
|
||||
}
|
||||
}
|
||||
|
||||
const testEmail = "test1@test.com";
|
||||
const foundBreaches = await DBUtils.getBreachesForHash(getSha1(testEmail));
|
||||
const foundBreaches = await DBUtils.getBreachesForEmail(testEmail);
|
||||
console.log(`\n\n${testEmail} was found in the following breaches:\n`);
|
||||
console.log(foundBreaches.map(b => b.name));
|
||||
// eslint-disable-next-line no-process-exit
|
||||
|
|
Загрузка…
Ссылка в новой задаче