Add initial version of querying by hash prefix

This commit is contained in:
Martijn van der Ven
2020-05-23 16:54:21 +02:00
parent ca46f4c9ac
commit 803b1fa505
4 changed files with 103 additions and 0 deletions

View File

@@ -0,0 +1,26 @@
BEGIN TRANSACTION;
/* Add hash field */
CREATE TABLE "sqlb_temp_table_1" (
"videoID" TEXT NOT NULL,
"startTime" REAL NOT NULL,
"endTime" REAL NOT NULL,
"votes" INTEGER NOT NULL,
"incorrectVotes" INTEGER NOT NULL default '1',
"UUID" TEXT NOT NULL UNIQUE,
"userID" TEXT NOT NULL,
"timeSubmitted" INTEGER NOT NULL,
"views" INTEGER NOT NULL,
"category" TEXT NOT NULL DEFAULT "sponsor",
"shadowHidden" INTEGER NOT NULL,
"hashedVideoID" TEXT NOT NULL
);
INSERT INTO sqlb_temp_table_1 SELECT *, sha256(videoID) FROM sponsorTimes;
DROP TABLE sponsorTimes;
ALTER TABLE sqlb_temp_table_1 RENAME TO "sponsorTimes";
/* Bump version in config */
UPDATE config SET value = 2 WHERE key = "version";
COMMIT;

View File

@@ -10,6 +10,7 @@ var loggerMiddleware = require('./middleware/logger.js');
// Routes
var getSkipSegments = require('./routes/getSkipSegments.js').endpoint;
var postSkipSegments = require('./routes/postSkipSegments.js');
var getSkipSegmentsByHash = require('./routes/getSkipSegmentsByHash.js');
var voteOnSponsorTime = require('./routes/voteOnSponsorTime.js');
var viewedVideoSponsorTime = require('./routes/viewedVideoSponsorTime.js');
var setUsername = require('./routes/setUsername.js');
@@ -48,6 +49,9 @@ app.post('/api/postVideoSponsorTimes', oldSubmitSponsorTimes);
app.get('/api/skipSegments', getSkipSegments);
app.post('/api/skipSegments', postSkipSegments);
// add the privacy protecting skip segments functions
app.get('/api/skipSegments/:prefix', getSkipSegmentsByHash);
//voting endpoint
app.get('/api/voteOnSponsorTime', voteOnSponsorTime);
app.post('/api/voteOnSponsorTime', voteOnSponsorTime);

View File

@@ -26,6 +26,10 @@ if (config.createDatabaseIfNotExist && !config.readOnly) {
// Upgrade database if required
if (!config.readOnly) {
// Register hashing function needed for running database upgrade
db.function("sha256", function (string) {
return require('crypto').createHash("sha256").update(string).digest("hex");
});
ugradeDB(db, "sponsorTimes");
ugradeDB(privateDB, "private")
}

View File

@@ -0,0 +1,69 @@
const config = require('../config.js');
const { db, privateDB } = require('../databases/databases.js');
const getHash = require('../utils/getHash.js');
const getIP = require('../utils/getIP.js');
/**
* @typedef {Object} Segment
* @property {string} videoID YouTube video ID the segment is meant for
* @property {number[]} segment Tuple of start and end times in seconds
* @property {string} category Category of content to skip
* @property {string} UUID Unique identifier for the specific segment
*/
/**
* @param {string} prefix Lowercased hexadecimal hash prefix
* @param {string} hashedIP Custom hash of the visitors IP address
* @returns {Segment[]}
*/
function getSkipSegmentsByHash(prefix, hashedIP) {
/**
* @constant
* @type {Segment[]}
* @default
*/
const segments = [];
const rows = db.prepare('SELECT videoID, startTime, endTime, UUID, category, shadowHidden FROM sponsorTimes WHERE votes >= -1 AND hashedVideoID LIKE ? ORDER BY startTime')
.all(prefix + '%');
const onlyForCurrentUser = privateDB.prepare('SELECT videoID FROM sponsorTimes WHERE hashedIP = ?').all(hashedIP).map(row => row.videoID);
for (const row of rows) {
/** @TODO check if this logic does what is expected. */
if (row.shadowHidden === 1 && onlyForCurrentUser.indexOf(row.videoID) === -1) {
// The current visitors IP did not submit for the current video.
// Do not send shadowHidden segments to them.
continue;
}
segments.push({
videoID: row.videoID,
segment: [row.startTime, row.endTime],
category: row.category,
UUID: row.UUID
});
}
return segments;
}
const minimumPrefix = config.minimumPrefix || '3';
const maximumPrefix = config.maximumPrefix || '32'; // Half the hash.
const prefixChecker = new RegExp('^[\\dA-F]{' + minimumPrefix + ',' + maximumPrefix + '}$', 'i');
module.exports = async function (req, res) {
if (!prefixChecker.test(req.params.prefix)) {
res.sendStatus(400).end(); // Exit early on faulty prefix
}
const segments = getSkipSegmentsByHash(
req.params.prefix.toLowerCase(),
getHash(getIP(req) + config.globalSalt)
);
if (segments) {
res.send(segments)
}
}