From 7acb19756b30d8b269b798b898a68d2f350629e9 Mon Sep 17 00:00:00 2001 From: Joe Dowd Date: Thu, 13 Feb 2020 00:03:09 +0000 Subject: [PATCH 01/11] Create DB form schema on start if config option is set --- config.json.example | 5 ++++- index.js | 7 ++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/config.json.example b/config.json.example index d771410..b90e11e 100644 --- a/config.json.example +++ b/config.json.example @@ -8,6 +8,9 @@ "behindProxy": true, "db": "./databases/sponsorTimes.db", "privateDB": "./databases/private.db", + "createDatabaseIfNotExist": true, //depends on mode='development' //This will run on startup every time - so ensure "create table if not exists" is used in the schema + "dbSchema": "./databases/_sponsorTimes.db.sql", + "privateDBSchema": "./databases/_private.db.sql", "mode": "development", "readOnly": false -} \ No newline at end of file +} diff --git a/index.js b/index.js index e0c993f..73727ba 100644 --- a/index.js +++ b/index.js @@ -29,6 +29,11 @@ var db = new Sqlite3(config.db, options); //where the more sensitive data such as IP addresses are stored var privateDB = new Sqlite3(config.privateDB, options); +if (config.createDatabaseIfNotExist && (config.mode === "development")) { + db.exec(fs.readFileSync(config.dbSchema).toString()); + privateDB.exec(fs.readFileSync(config.privateDBSchema).toString()); +} + // Create an HTTP service. http.createServer(app).listen(config.port); @@ -1049,4 +1054,4 @@ function getFormattedTime(seconds) { let formatted = minutes+ ":" + secondsDisplay; return formatted; -} \ No newline at end of file +} From 1900d1ae52c02bf551653f331230d5948d6e8185 Mon Sep 17 00:00:00 2001 From: Joe Dowd Date: Sat, 15 Feb 2020 20:52:33 +0000 Subject: [PATCH 02/11] Check config.readonly instead of config.mode as condition to creading tables from schema files --- index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.js b/index.js index 73727ba..5ecce38 100644 --- a/index.js +++ b/index.js @@ -29,7 +29,7 @@ var db = new Sqlite3(config.db, options); //where the more sensitive data such as IP addresses are stored var privateDB = new Sqlite3(config.privateDB, options); -if (config.createDatabaseIfNotExist && (config.mode === "development")) { +if (config.createDatabaseIfNotExist && !config.readOnly) { db.exec(fs.readFileSync(config.dbSchema).toString()); privateDB.exec(fs.readFileSync(config.privateDBSchema).toString()); } From 97b2d2d56147b434622a3c8a7916e9fa5300b919 Mon Sep 17 00:00:00 2001 From: Joe Dowd Date: Sat, 15 Feb 2020 21:02:56 +0000 Subject: [PATCH 03/11] Updated config comment to match changed condition for running schema script --- config.json.example | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.json.example b/config.json.example index b90e11e..0d76f8b 100644 --- a/config.json.example +++ b/config.json.example @@ -8,7 +8,7 @@ "behindProxy": true, "db": "./databases/sponsorTimes.db", "privateDB": "./databases/private.db", - "createDatabaseIfNotExist": true, //depends on mode='development' //This will run on startup every time - so ensure "create table if not exists" is used in the schema + "createDatabaseIfNotExist": true, //This will run on startup every time (unless readOnly is true) - so ensure "create table if not exists" is used in the schema "dbSchema": "./databases/_sponsorTimes.db.sql", "privateDBSchema": "./databases/_private.db.sql", "mode": "development", From a8cbc4fbdb8c5af8bb792a979bd9001bd94284ba Mon Sep 17 00:00:00 2001 From: Joe Dowd Date: Tue, 10 Mar 2020 02:10:53 +0000 Subject: [PATCH 04/11] Stopped initial DB from being created when missing if config option set to false. Checked for existence of schema files before executing the schema. --- index.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/index.js b/index.js index 5ecce38..c867049 100644 --- a/index.js +++ b/index.js @@ -21,7 +21,8 @@ YouTubeAPI.authenticate({ var Sqlite3 = require('better-sqlite3'); let options = { - readonly: config.readOnly + readonly: config.readOnly, + fileMustExist: !config.createDatabaseIfNotExist }; //load database @@ -30,8 +31,8 @@ var db = new Sqlite3(config.db, options); var privateDB = new Sqlite3(config.privateDB, options); if (config.createDatabaseIfNotExist && !config.readOnly) { - db.exec(fs.readFileSync(config.dbSchema).toString()); - privateDB.exec(fs.readFileSync(config.privateDBSchema).toString()); + if (fs.existsSync(config.dbSchema)) db.exec(fs.readFileSync(config.dbSchema).toString()); + if (fs.existsSync(config.privateDBSchema)) privateDB.exec(fs.readFileSync(config.privateDBSchema).toString()); } // Create an HTTP service. From da47098ccd47b008dd87a56313b5950fe260a38a Mon Sep 17 00:00:00 2001 From: Ajay Ramachandran Date: Thu, 26 Mar 2020 21:58:21 -0400 Subject: [PATCH 05/11] Added info to config example --- config.json.example | 2 ++ 1 file changed, 2 insertions(+) diff --git a/config.json.example b/config.json.example index 0d76f8b..b8a9d79 100644 --- a/config.json.example +++ b/config.json.example @@ -1,4 +1,6 @@ { + // Remove all comments from the config when using it! + "port": 80, "globalSalt": "[global salt (pepper) that is added to every ip before hashing to make it even harder for someone to decode the ip]", "adminUserID": "[the hashed id of the user who can perform admin actions]", From 3087e05212745f7dfde0a187296c3cd6e6457399 Mon Sep 17 00:00:00 2001 From: Joe-Dowd Date: Wed, 1 Apr 2020 23:29:37 +0100 Subject: [PATCH 06/11] added getHash import for getSavedTimeForUser --- src/routes/getSavedTimeForUser.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/routes/getSavedTimeForUser.js b/src/routes/getSavedTimeForUser.js index 0b874ce..ea23dc6 100644 --- a/src/routes/getSavedTimeForUser.js +++ b/src/routes/getSavedTimeForUser.js @@ -1,4 +1,5 @@ var db = require('../databases/databases.js').db; +var getHash = require('../utils/getHash.js'); module.exports = function getSavedTimeForUser (req, res) { let userID = req.query.userID; From af149b09a99ca96a5e22c8aafc725d3dbede7166 Mon Sep 17 00:00:00 2001 From: Joe-Dowd Date: Wed, 1 Apr 2020 23:39:56 +0100 Subject: [PATCH 07/11] added getSavedTimeForUser test --- test/cases/getSavedTimeForUser.js | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 test/cases/getSavedTimeForUser.js diff --git a/test/cases/getSavedTimeForUser.js b/test/cases/getSavedTimeForUser.js new file mode 100644 index 0000000..3e52590 --- /dev/null +++ b/test/cases/getSavedTimeForUser.js @@ -0,0 +1,21 @@ +var request = require('request'); +var utils = require('../utils.js'); +var db = require('../../src/databases/databases.js').db; +var getHash = require('../../src/utils/getHash.js'); + +describe('getSavedTimeForUser', () => { + before(() => { + db.exec("INSERT INTO sponsorTimes VALUES ('testtesttest', 1, 11, 2, 'abc1239999', '"+getHash("testman")+"', 0, 50, 0)"); + }); + + it('Should be able to get a 200', (done) => { + request.get(utils.getbaseURL() + + "/api/getSavedTimeForUser?userID=testman", null, + (err, res, body) => { + console.log(res.statusCode); + if (err) done(false); + else if (res.statusCode !== 200) done("non 200"); + else done(); + }); + }); +}); \ No newline at end of file From 393c131104911f83ebdfcf63fd511adb003135fe Mon Sep 17 00:00:00 2001 From: Joe-Dowd Date: Wed, 1 Apr 2020 23:42:58 +0100 Subject: [PATCH 08/11] remove duplicate videoID in test cases --- test/cases/getSavedTimeForUser.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/cases/getSavedTimeForUser.js b/test/cases/getSavedTimeForUser.js index 3e52590..5488c67 100644 --- a/test/cases/getSavedTimeForUser.js +++ b/test/cases/getSavedTimeForUser.js @@ -5,14 +5,13 @@ var getHash = require('../../src/utils/getHash.js'); describe('getSavedTimeForUser', () => { before(() => { - db.exec("INSERT INTO sponsorTimes VALUES ('testtesttest', 1, 11, 2, 'abc1239999', '"+getHash("testman")+"', 0, 50, 0)"); + db.exec("INSERT INTO sponsorTimes VALUES ('getSavedTimeForUser', 1, 11, 2, 'abc1239999', '"+getHash("testman")+"', 0, 50, 0)"); }); it('Should be able to get a 200', (done) => { request.get(utils.getbaseURL() + "/api/getSavedTimeForUser?userID=testman", null, (err, res, body) => { - console.log(res.statusCode); if (err) done(false); else if (res.statusCode !== 200) done("non 200"); else done(); From 5d2d5819cff6e0090d246308c51d2414b57b5ec5 Mon Sep 17 00:00:00 2001 From: Joe-Dowd Date: Thu, 2 Apr 2020 18:38:00 +0100 Subject: [PATCH 09/11] added db files to .gitignore --- .gitignore | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.gitignore b/.gitignore index 8fa7201..e329b30 100644 --- a/.gitignore +++ b/.gitignore @@ -89,9 +89,13 @@ typings/ # Databases databases/sponsorTimes.db +databases/sponsorTimes.db-shm +databases/sponsorTimes.db-wal databases/private.db databases/sponsorTimesReal.db test/databases/sponsorTimes.db +test/databases/sponsorTimes.db-shm +test/databases/sponsorTimes.db-wal test/databases/private.db # Config files From 819f338c6840260baa935b27116eecfe298ba3de Mon Sep 17 00:00:00 2001 From: Joe-Dowd Date: Thu, 2 Apr 2020 18:53:02 +0100 Subject: [PATCH 10/11] Ensured anything in master is implemented --- config.json.example | 2 ++ src/databases/databases.js | 3 ++- src/routes/submitSponsorTimes.js | 10 ++++++++++ src/routes/voteOnSponsorTime.js | 10 ++++++++++ test/mocks.js | 2 ++ 5 files changed, 26 insertions(+), 1 deletion(-) diff --git a/config.json.example b/config.json.example index d771410..49f827b 100644 --- a/config.json.example +++ b/config.json.example @@ -1,4 +1,6 @@ { + // Remove all comments from the config when using it! + "port": 80, "globalSalt": "[global salt (pepper) that is added to every ip before hashing to make it even harder for someone to decode the ip]", "adminUserID": "[the hashed id of the user who can perform admin actions]", diff --git a/src/databases/databases.js b/src/databases/databases.js index 8676292..d01d01f 100644 --- a/src/databases/databases.js +++ b/src/databases/databases.js @@ -3,7 +3,8 @@ var Sqlite3 = require('better-sqlite3'); var fs = require('fs'); let options = { - readonly: config.readOnly + readonly: config.readOnly, + fileMustExist: !config.createDatabaseIfNotExist }; var db = new Sqlite3(config.db, options); diff --git a/src/routes/submitSponsorTimes.js b/src/routes/submitSponsorTimes.js index 30b1f0f..a550f00 100644 --- a/src/routes/submitSponsorTimes.js +++ b/src/routes/submitSponsorTimes.js @@ -168,6 +168,16 @@ module.exports = async function submitSponsorTimes(req, res) { } }] } + }, (err, res) => { + if (err) { + console.log("Failed to send first time submission Discord hook."); + console.log(JSON.stringify(err)); + console.log("\n"); + } else if (res && res.statusCode >= 400) { + console.log("Error sending first time submission Discord hook"); + console.log(JSON.stringify(res)); + console.log("\n"); + } }); }); } diff --git a/src/routes/voteOnSponsorTime.js b/src/routes/voteOnSponsorTime.js index 79c73d6..bc9a326 100644 --- a/src/routes/voteOnSponsorTime.js +++ b/src/routes/voteOnSponsorTime.js @@ -119,6 +119,16 @@ module.exports = async function voteOnSponsorTime(req, res) { } }] } + }, (err, res) => { + if (err) { + console.log("Failed to send reported submission Discord hook."); + console.log(JSON.stringify(err)); + console.log("\n"); + } else if (res && res.statusCode >= 400) { + console.log("Error sending reported submission Discord hook"); + console.log(JSON.stringify(res)); + console.log("\n"); + } }); }); } diff --git a/test/mocks.js b/test/mocks.js index a124646..df19c8a 100644 --- a/test/mocks.js +++ b/test/mocks.js @@ -4,10 +4,12 @@ var app = express(); var config = require('../src/config.js'); app.post('/ReportChannelWebhook', (req, res) => { + console.log("report mock hit"); res.status(200); }); app.post('/FirstTimeSubmissionsWebhook', (req, res) => { + console.log("first time submisson mock hit"); res.status(200); }); From cc0bfef0add00e5f939cd1c7e4531855872c0ddc Mon Sep 17 00:00:00 2001 From: Joe-Dowd Date: Fri, 3 Apr 2020 21:45:06 +0100 Subject: [PATCH 11/11] added more tests (categories prep) --- test/cases/getSponsorTime.js | 36 ++++++++++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/test/cases/getSponsorTime.js b/test/cases/getSponsorTime.js index d0fc21e..0565d28 100644 --- a/test/cases/getSponsorTime.js +++ b/test/cases/getSponsorTime.js @@ -19,7 +19,8 @@ var utils = require('../utils.js'); describe('getVideoSponsorTime', () => { before(() => { - db.exec("INSERT INTO sponsorTimes VALUES ('testtesttest', 1, 11, 2, 'abc123', 'testman', 0, 50, 0)"); + db.exec("INSERT INTO sponsorTimes VALUES ('testtesttest', 1, 11, 2, 'uuid-0', 'testman', 0, 50, 0)"); + db.exec("INSERT INTO sponsorTimes VALUES ('testtesttest,test', 1, 11, 2, 'uuid-1', 'testman', 0, 50, 0)"); }); it('Should be able to get a time', (done) => { @@ -32,6 +33,37 @@ describe('getVideoSponsorTime', () => { }); }); + it('Should return 404 if no segment found', (done) => { + request.get(utils.getbaseURL() + + "/api/getVideoSponsorTimes?videoID=notarealvideo", null, + (err, res, body) => { + if (err) done(false); + else if (res.statusCode !== 404) done("non 404 respone code: " + res.statusCode); + else done(); + }); + }); + + + it('Should be possible to send unexpected query parameters', (done) => { + request.get(utils.getbaseURL() + + "/api/getVideoSponsorTimes?videoID=testtesttest&fakeparam=hello", null, + (err, res, body) => { + if (err) done(false); + else if (res.statusCode !== 200) done("non 200"); + else done(); + }); + }); + + it('Should be able send a comma in a query param', (done) => { + request.get(utils.getbaseURL() + + "/api/getVideoSponsorTimes?videoID=testtesttest,test", null, + (err, res, body) => { + if (err) done(false); + else if (res.statusCode !== 200) done("non 200 response: " + res.statusCode); + else (JSON.parse(body).UUIDs[0] === 'uuid-1') && done(); + }); + }); + it('Should be able to get the correct time', (done) => { request.get(utils.getbaseURL() + "/api/getVideoSponsorTimes?videoID=testtesttest", null, @@ -42,7 +74,7 @@ describe('getVideoSponsorTime', () => { let parsedBody = JSON.parse(body); if (parsedBody.sponsorTimes[0][0] === 1 && parsedBody.sponsorTimes[0][1] === 11 - && parsedBody.UUIDs[0] === 'abc123') { + && parsedBody.UUIDs[0] === 'uuid-0') { done(); } else { done("Wrong data was returned + " + parsedBody);