Update routes to use new DB api

This commit is contained in:
Nihanth Subramanya 2018-04-18 16:30:59 +02:00
Родитель 4353ec66cd
Коммит e78b3e2e12
5 изменённых файлов: 54 добавлений и 30 удалений

Просмотреть файл

@ -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.",
});

7
tests/fixtures/make-breach-with-emails.js поставляемый
Просмотреть файл

@ -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