From 0c1cbbfe29d91c95f9c574b57adf067654b8b5b4 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Thu, 14 Apr 2016 22:06:11 +0200 Subject: [PATCH] Add authentications for routes that need it and adapts the tests --- package.json | 2 +- server/controllers/api/v1/users.js | 7 +- server/controllers/api/v1/videos.js | 11 ++- server/initializers/installer.js | 6 +- server/middlewares/oauth2.js | 26 +++++- server/models/users.js | 2 +- server/models/videos.js | 3 +- server/tests/api/checkParams.js | 68 ++++++++------ server/tests/api/friendsAdvanced.js | 42 +++++---- server/tests/api/friendsBasic.js | 60 ++++++------- server/tests/api/index.js | 1 + server/tests/api/multiplePods.js | 67 ++++++++------ server/tests/api/singlePod.js | 33 ++++--- server/tests/api/users.js | 133 ++++++++++++++++++++++++++++ server/tests/api/utils.js | 99 +++++++++++++++++++-- 15 files changed, 416 insertions(+), 144 deletions(-) create mode 100644 server/tests/api/users.js diff --git a/package.json b/package.json index 076cf6fdb..678804ed2 100644 --- a/package.json +++ b/package.json @@ -48,7 +48,7 @@ "dezalgo": "^1.0.3", "electron-spawn": "https://github.com/Chocobozzz/electron-spawn", "express": "^4.12.4", - "express-oauth-server": "https://github.com/oauthjs/express-oauth-server", + "express-oauth-server": "https://github.com/Chocobozzz/express-oauth-server", "express-validator": "^2.11.0", "js-yaml": "^3.5.4", "lodash-node": "^3.10.2", diff --git a/server/controllers/api/v1/users.js b/server/controllers/api/v1/users.js index acb860c66..f45b47077 100644 --- a/server/controllers/api/v1/users.js +++ b/server/controllers/api/v1/users.js @@ -1,15 +1,14 @@ 'use strict' -var express = require('express') -var oAuth2 = require('../../../middlewares/oauth2') +const express = require('express') +const oAuth2 = require('../../../middlewares/oauth2') const middleware = require('../../../middlewares') const cacheMiddleware = middleware.cache const router = express.Router() -router.post('/token', cacheMiddleware.cache(false), oAuth2.token(), success) -router.get('/authenticate', cacheMiddleware.cache(false), oAuth2.authenticate(), success) +router.post('/token', cacheMiddleware.cache(false), oAuth2.token, success) // --------------------------------------------------------------------------- diff --git a/server/controllers/api/v1/videos.js b/server/controllers/api/v1/videos.js index 97d3e6b5a..d25ca95f7 100644 --- a/server/controllers/api/v1/videos.js +++ b/server/controllers/api/v1/videos.js @@ -8,6 +8,7 @@ const multer = require('multer') const logger = require('../../../helpers/logger') const friends = require('../../../lib/friends') const middleware = require('../../../middlewares') +const oAuth2 = require('../../../middlewares/oauth2') const cacheMiddleware = middleware.cache const reqValidator = middleware.reqValidators.videos const Videos = require('../../../models/videos') // model @@ -38,9 +39,9 @@ const storage = multer.diskStorage({ const reqFiles = multer({ storage: storage }).fields([{ name: 'videofile', maxCount: 1 }]) router.get('/', cacheMiddleware.cache(false), listVideos) -router.post('/', reqFiles, reqValidator.videosAdd, cacheMiddleware.cache(false), addVideo) +router.post('/', oAuth2.authenticate, reqFiles, reqValidator.videosAdd, cacheMiddleware.cache(false), addVideo) router.get('/:id', reqValidator.videosGet, cacheMiddleware.cache(false), getVideos) -router.delete('/:id', reqValidator.videosRemove, cacheMiddleware.cache(false), removeVideo) +router.delete('/:id', oAuth2.authenticate, reqValidator.videosRemove, cacheMiddleware.cache(false), removeVideo) router.get('/search/:name', reqValidator.videosSearch, cacheMiddleware.cache(false), searchVideos) // --------------------------------------------------------------------------- @@ -63,7 +64,8 @@ function addVideo (req, res, next) { name: video_infos.name, namePath: video_file.filename, description: video_infos.description, - magnetUri: torrent.magnetURI + magnetUri: torrent.magnetURI, + author: res.locals.oauth.token.user.username } Videos.add(video_data, function (err) { @@ -141,7 +143,8 @@ function getFormatedVideo (video_obj) { description: video_obj.description, podUrl: video_obj.podUrl, isLocal: videos.getVideoState(video_obj).owned, - magnetUri: video_obj.magnetUri + magnetUri: video_obj.magnetUri, + author: video_obj.author } return formated_video diff --git a/server/initializers/installer.js b/server/initializers/installer.js index 750eb2c59..ec9175f34 100644 --- a/server/initializers/installer.js +++ b/server/initializers/installer.js @@ -57,12 +57,12 @@ function createOAuthClientIfNotExist (callback) { logger.info('Creating a default OAuth Client.') // TODO: generate password - const password = 'megustalabanana' - Users.createClient(password, [ 'password' ], function (err, id) { + const secret = 'megustalabanana' + Users.createClient(secret, [ 'password' ], function (err, id) { if (err) return callback(err) logger.info('Client id: ' + id) - logger.info('Client password: ' + password) + logger.info('Client secret: ' + secret) return callback(null) }) diff --git a/server/middlewares/oauth2.js b/server/middlewares/oauth2.js index a1fa61fbb..1defdc02e 100644 --- a/server/middlewares/oauth2.js +++ b/server/middlewares/oauth2.js @@ -2,10 +2,34 @@ const OAuthServer = require('express-oauth-server') -const oAuth2 = new OAuthServer({ +const logger = require('../helpers/logger') + +const oAuthServer = new OAuthServer({ model: require('../models/users') }) +const oAuth2 = { + authenticate: authenticate, + token: token +} + +function authenticate (req, res, next) { + oAuthServer.authenticate()(req, res, function (err) { + if (err) { + logger.error('Cannot authenticate.', { error: err }) + return res.sendStatus(500) + } + + if (res.statusCode === 401 || res.statusCode === 400) return res.end() + + return next() + }) +} + +function token (req, res, next) { + return oAuthServer.token()(req, res, next) +} + // --------------------------------------------------------------------------- module.exports = oAuth2 diff --git a/server/models/users.js b/server/models/users.js index 367c206ab..046fe462d 100644 --- a/server/models/users.js +++ b/server/models/users.js @@ -104,7 +104,7 @@ function saveToken (token, client, user) { } return OAuthTokensDB.create(token_to_create, function (err, token_created) { - if (err) throw err // node-oauth2-server library use Promise.try + if (err) throw err // node-oauth2-server library uses Promise.try token_created.client = client token_created.user = user diff --git a/server/models/videos.js b/server/models/videos.js index 0141cbb7f..13ef2295a 100644 --- a/server/models/videos.js +++ b/server/models/videos.js @@ -21,7 +21,8 @@ const videosSchema = mongoose.Schema({ namePath: String, description: String, magnetUri: String, - podUrl: String + podUrl: String, + author: String }) const VideosDB = mongoose.model('videos', videosSchema) diff --git a/server/tests/api/checkParams.js b/server/tests/api/checkParams.js index dcc190e97..59ee0bfc3 100644 --- a/server/tests/api/checkParams.js +++ b/server/tests/api/checkParams.js @@ -9,17 +9,18 @@ const request = require('supertest') const utils = require('./utils') describe('Test parameters validator', function () { - let app = null - let url = '' + let server = null - function makePostRequest (path, fields, attach, done, fail) { + function makePostRequest (path, token, fields, attach, done, fail) { let status_code = 400 if (fail !== undefined && fail === false) status_code = 200 - const req = request(url) + const req = request(server.url) .post(path) .set('Accept', 'application/json') + if (token) req.set('Authorization', 'Bearer ' + token) + Object.keys(fields).forEach(function (field) { const value = fields[field] req.field(field, value) @@ -32,7 +33,7 @@ describe('Test parameters validator', function () { let status_code = 400 if (fail !== undefined && fail === false) status_code = 200 - request(url) + request(server.url) .post(path) .set('Accept', 'application/json') .send(fields) @@ -49,9 +50,17 @@ describe('Test parameters validator', function () { utils.flushTests(next) }, function (next) { - utils.runServer(1, function (app1, url1) { - app = app1 - url = url1 + utils.runServer(1, function (server1) { + server = server1 + + next() + }) + }, + function (next) { + utils.loginAndGetAccessToken(server, function (err, token) { + if (err) throw err + server.access_token = token + next() }) } @@ -118,7 +127,7 @@ describe('Test parameters validator', function () { describe('When searching a video', function () { it('Should fail with nothing', function (done) { - request(url) + request(server.url) .get(pathUtils.join(path, 'search')) .set('Accept', 'application/json') .expect(400, done) @@ -129,7 +138,7 @@ describe('Test parameters validator', function () { it('Should fail with nothing', function (done) { const data = {} const attach = {} - makePostRequest(path, data, attach, done) + makePostRequest(path, server.access_token, data, attach, done) }) it('Should fail without name', function (done) { @@ -139,7 +148,7 @@ describe('Test parameters validator', function () { const attach = { 'videofile': pathUtils.join(__dirname, 'fixtures', 'video_short.webm') } - makePostRequest(path, data, attach, done) + makePostRequest(path, server.access_token, data, attach, done) }) it('Should fail with a long name', function (done) { @@ -150,7 +159,7 @@ describe('Test parameters validator', function () { const attach = { 'videofile': pathUtils.join(__dirname, 'fixtures', 'video_short.webm') } - makePostRequest(path, data, attach, done) + makePostRequest(path, server.access_token, data, attach, done) }) it('Should fail without description', function (done) { @@ -160,7 +169,7 @@ describe('Test parameters validator', function () { const attach = { 'videofile': pathUtils.join(__dirname, 'fixtures', 'video_short.webm') } - makePostRequest(path, data, attach, done) + makePostRequest(path, server.access_token, data, attach, done) }) it('Should fail with a long description', function (done) { @@ -173,7 +182,7 @@ describe('Test parameters validator', function () { const attach = { 'videofile': pathUtils.join(__dirname, 'fixtures', 'video_short.webm') } - makePostRequest(path, data, attach, done) + makePostRequest(path, server.access_token, data, attach, done) }) it('Should fail without an input file', function (done) { @@ -182,7 +191,7 @@ describe('Test parameters validator', function () { description: 'my super description' } const attach = {} - makePostRequest(path, data, attach, done) + makePostRequest(path, server.access_token, data, attach, done) }) it('Should fail without an incorrect input file', function (done) { @@ -193,7 +202,7 @@ describe('Test parameters validator', function () { const attach = { 'videofile': pathUtils.join(__dirname, '..', 'fixtures', 'video_short_fake.webm') } - makePostRequest(path, data, attach, done) + makePostRequest(path, server.access_token, data, attach, done) }) it('Should succeed with the correct parameters', function (done) { @@ -204,11 +213,11 @@ describe('Test parameters validator', function () { const attach = { 'videofile': pathUtils.join(__dirname, 'fixtures', 'video_short.webm') } - makePostRequest(path, data, attach, function () { + makePostRequest(path, server.access_token, data, attach, function () { attach.videofile = pathUtils.join(__dirname, 'fixtures', 'video_short.mp4') - makePostRequest(path, data, attach, function () { + makePostRequest(path, server.access_token, data, attach, function () { attach.videofile = pathUtils.join(__dirname, 'fixtures', 'video_short.ogv') - makePostRequest(path, data, attach, done, true) + makePostRequest(path, server.access_token, data, attach, done, true) }, true) }, true) }) @@ -216,7 +225,7 @@ describe('Test parameters validator', function () { describe('When getting a video', function () { it('Should return the list of the videos with nothing', function (done) { - request(url) + request(server.url) .get(path) .set('Accept', 'application/json') .expect(200) @@ -232,14 +241,14 @@ describe('Test parameters validator', function () { }) it('Should fail without a mongodb id', function (done) { - request(url) + request(server.url) .get(path + 'coucou') .set('Accept', 'application/json') .expect(400, done) }) it('Should return 404 with an incorrect video', function (done) { - request(url) + request(server.url) .get(path + '123456789012345678901234') .set('Accept', 'application/json') .expect(404, done) @@ -250,20 +259,23 @@ describe('Test parameters validator', function () { describe('When removing a video', function () { it('Should have 404 with nothing', function (done) { - request(url) - .delete(path) - .expect(400, done) + request(server.url) + .delete(path) + .set('Authorization', 'Bearer ' + server.access_token) + .expect(400, done) }) it('Should fail without a mongodb id', function (done) { - request(url) + request(server.url) .delete(path + 'hello') + .set('Authorization', 'Bearer ' + server.access_token) .expect(400, done) }) it('Should fail with a video which does not exist', function (done) { - request(url) + request(server.url) .delete(path + '123456789012345678901234') + .set('Authorization', 'Bearer ' + server.access_token) .expect(404, done) }) @@ -288,7 +300,7 @@ describe('Test parameters validator', function () { }) after(function (done) { - process.kill(-app.pid) + process.kill(-server.app.pid) // Keep the logs if the test failed if (this.ok) { diff --git a/server/tests/api/friendsAdvanced.js b/server/tests/api/friendsAdvanced.js index 6c4b7567f..6f18648d7 100644 --- a/server/tests/api/friendsAdvanced.js +++ b/server/tests/api/friendsAdvanced.js @@ -7,41 +7,48 @@ const expect = chai.expect const utils = require('./utils') describe('Test advanced friends', function () { - let apps = [] - let urls = [] + let servers = [] function makeFriends (pod_number, callback) { - return utils.makeFriends(urls[pod_number - 1], callback) + return utils.makeFriends(servers[pod_number - 1].url, callback) } function quitFriends (pod_number, callback) { - return utils.quitFriends(urls[pod_number - 1], callback) + return utils.quitFriends(servers[pod_number - 1].url, callback) } function getFriendsList (pod_number, end) { - return utils.getFriendsList(urls[pod_number - 1], end) + return utils.getFriendsList(servers[pod_number - 1].url, end) } function uploadVideo (pod_number, callback) { const name = 'my super video' const description = 'my super description' const fixture = 'video_short.webm' + const server = servers[pod_number - 1] - return utils.uploadVideo(urls[pod_number - 1], name, description, fixture, callback) + return utils.uploadVideo(server.url, server.access_token, name, description, fixture, callback) } function getVideos (pod_number, callback) { - return utils.getVideosList(urls[pod_number - 1], callback) + return utils.getVideosList(servers[pod_number - 1].url, callback) } // --------------------------------------------------------------- before(function (done) { this.timeout(30000) - utils.flushAndRunMultipleServers(6, function (apps_run, urls_run) { - apps = apps_run - urls = urls_run - done() + utils.flushAndRunMultipleServers(6, function (servers_run, urls_run) { + servers = servers_run + + async.each(servers, function (server, callback_each) { + utils.loginAndGetAccessToken(server, function (err, access_token) { + if (err) return callback_each(err) + + server.access_token = access_token + callback_each() + }) + }, done) }) }) @@ -121,7 +128,7 @@ describe('Test advanced friends', function () { }, // Kill pod 4 function (next) { - apps[3].kill() + servers[3].app.kill() next() }, // Expulse pod 4 from pod 1 and 2 @@ -145,8 +152,8 @@ describe('Test advanced friends', function () { }, // Rerun server 4 function (next) { - utils.runServer(4, function (app, url) { - apps[3] = app + utils.runServer(4, function (server) { + servers[3].app = server.app next() }) }, @@ -156,7 +163,6 @@ describe('Test advanced friends', function () { // Pod 4 didn't know pod 1 and 2 removed it expect(res.body.length).to.equal(3) - next() }) }, @@ -174,7 +180,7 @@ describe('Test advanced friends', function () { const result = res.body expect(result.length).to.equal(3) for (const pod of result) { - expect(pod.url).not.equal(urls[3]) + expect(pod.url).not.equal(servers[3].url) } done() @@ -237,8 +243,8 @@ describe('Test advanced friends', function () { }) after(function (done) { - apps.forEach(function (app) { - process.kill(-app.pid) + servers.forEach(function (server) { + process.kill(-server.app.pid) }) if (this.ok) { diff --git a/server/tests/api/friendsBasic.js b/server/tests/api/friendsBasic.js index 62eac51ec..49e51804f 100644 --- a/server/tests/api/friendsBasic.js +++ b/server/tests/api/friendsBasic.js @@ -8,17 +8,16 @@ const request = require('supertest') const utils = require('./utils') describe('Test basic friends', function () { - let apps = [] - let urls = [] + let servers = [] - function testMadeFriends (urls, url_to_test, callback) { + function testMadeFriends (servers, server_to_test, callback) { const friends = [] - for (let i = 0; i < urls.length; i++) { - if (urls[i] === url_to_test) continue - friends.push(urls[i]) + for (let i = 0; i < servers.length; i++) { + if (servers[i].url === server_to_test.url) continue + friends.push(servers[i].url) } - utils.getFriendsList(url_to_test, function (err, res) { + utils.getFriendsList(server_to_test.url, function (err, res) { if (err) throw err const result = res.body @@ -27,7 +26,7 @@ describe('Test basic friends', function () { expect(result.length).to.equal(2) expect(result_urls[0]).to.not.equal(result_urls[1]) - const error_string = 'Friends url do not correspond for ' + url_to_test + const error_string = 'Friends url do not correspond for ' + server_to_test.url expect(friends).to.contain(result_urls[0], error_string) expect(friends).to.contain(result_urls[1], error_string) callback() @@ -38,16 +37,15 @@ describe('Test basic friends', function () { before(function (done) { this.timeout(20000) - utils.flushAndRunMultipleServers(3, function (apps_run, urls_run) { - apps = apps_run - urls = urls_run + utils.flushAndRunMultipleServers(3, function (servers_run, urls_run) { + servers = servers_run done() }) }) it('Should not have friends', function (done) { - async.each(urls, function (url, callback) { - utils.getFriendsList(url, function (err, res) { + async.each(servers, function (server, callback) { + utils.getFriendsList(server.url, function (err, res) { if (err) throw err const result = res.body @@ -66,7 +64,7 @@ describe('Test basic friends', function () { async.series([ // The second pod make friend with the third function (next) { - request(urls[1]) + request(servers[1].url) .get(path) .set('Accept', 'application/json') .expect(204) @@ -78,33 +76,33 @@ describe('Test basic friends', function () { }, // The second pod should have the third as a friend function (next) { - utils.getFriendsList(urls[1], function (err, res) { + utils.getFriendsList(servers[1].url, function (err, res) { if (err) throw err const result = res.body expect(result).to.be.an('array') expect(result.length).to.equal(1) - expect(result[0].url).to.be.equal(urls[2]) + expect(result[0].url).to.be.equal(servers[2].url) next() }) }, // Same here, the third pod should have the second pod as a friend function (next) { - utils.getFriendsList(urls[2], function (err, res) { + utils.getFriendsList(servers[2].url, function (err, res) { if (err) throw err const result = res.body expect(result).to.be.an('array') expect(result.length).to.equal(1) - expect(result[0].url).to.be.equal(urls[1]) + expect(result[0].url).to.be.equal(servers[1].url) next() }) }, // Finally the first pod make friend with the second pod function (next) { - request(urls[0]) + request(servers[0].url) .get(path) .set('Accept', 'application/json') .expect(204) @@ -118,25 +116,25 @@ describe('Test basic friends', function () { // Now each pod should be friend with the other ones function (err) { if (err) throw err - async.each(urls, function (url, callback) { - testMadeFriends(urls, url, callback) + async.each(servers, function (server, callback) { + testMadeFriends(servers, server, callback) }, done) }) }) it('Should not be allowed to make friend again', function (done) { - utils.makeFriends(urls[1], 409, done) + utils.makeFriends(servers[1].url, 409, done) }) it('Should quit friends of pod 2', function (done) { async.series([ // Pod 1 quit friends function (next) { - utils.quitFriends(urls[1], next) + utils.quitFriends(servers[1].url, next) }, // Pod 1 should not have friends anymore function (next) { - utils.getFriendsList(urls[1], function (err, res) { + utils.getFriendsList(servers[1].url, function (err, res) { if (err) throw err const result = res.body @@ -148,14 +146,14 @@ describe('Test basic friends', function () { }, // Other pods shouldn't have pod 1 too function (next) { - async.each([ urls[0], urls[2] ], function (url, callback) { + async.each([ servers[0].url, servers[2].url ], function (url, callback) { utils.getFriendsList(url, function (err, res) { if (err) throw err const result = res.body expect(result).to.be.an('array') expect(result.length).to.equal(1) - expect(result[0].url).not.to.be.equal(urls[1]) + expect(result[0].url).not.to.be.equal(servers[1].url) callback() }) }, next) @@ -164,16 +162,16 @@ describe('Test basic friends', function () { }) it('Should allow pod 2 to make friend again', function (done) { - utils.makeFriends(urls[1], function () { - async.each(urls, function (url, callback) { - testMadeFriends(urls, url, callback) + utils.makeFriends(servers[1].url, function () { + async.each(servers, function (server, callback) { + testMadeFriends(servers, server, callback) }, done) }) }) after(function (done) { - apps.forEach(function (app) { - process.kill(-app.pid) + servers.forEach(function (server) { + process.kill(-server.app.pid) }) if (this.ok) { diff --git a/server/tests/api/index.js b/server/tests/api/index.js index 9c4fdd48a..61c9a7aca 100644 --- a/server/tests/api/index.js +++ b/server/tests/api/index.js @@ -3,6 +3,7 @@ // Order of the tests we want to execute require('./checkParams') require('./friendsBasic') +require('./users') require('./singlePod') require('./multiplePods') require('./friendsAdvanced') diff --git a/server/tests/api/multiplePods.js b/server/tests/api/multiplePods.js index 0e2355a55..b6545ca60 100644 --- a/server/tests/api/multiplePods.js +++ b/server/tests/api/multiplePods.js @@ -10,8 +10,7 @@ const webtorrent = require(pathUtils.join(__dirname, '../../lib/webtorrent')) webtorrent.silent = true describe('Test multiple pods', function () { - let apps = [] - let urls = [] + let servers = [] const to_remove = [] before(function (done) { @@ -20,15 +19,25 @@ describe('Test multiple pods', function () { async.series([ // Run servers function (next) { - utils.flushAndRunMultipleServers(3, function (apps_run, urls_run) { - apps = apps_run - urls = urls_run + utils.flushAndRunMultipleServers(3, function (servers_run) { + servers = servers_run next() }) }, + // Get the access tokens + function (next) { + async.each(servers, function (server, callback_each) { + utils.loginAndGetAccessToken(server, function (err, access_token) { + if (err) return callback_each(err) + + server.access_token = access_token + callback_each() + }) + }, next) + }, // The second pod make friend with the third function (next) { - utils.makeFriends(urls[1], next) + utils.makeFriends(servers[1].url, next) }, // Wait for the request between pods function (next) { @@ -36,7 +45,7 @@ describe('Test multiple pods', function () { }, // Pod 1 make friends too function (next) { - utils.makeFriends(urls[0], next) + utils.makeFriends(servers[0].url, next) }, function (next) { webtorrent.create({ host: 'client', port: '1' }, next) @@ -45,8 +54,8 @@ describe('Test multiple pods', function () { }) it('Should not have videos for all pods', function (done) { - async.each(urls, function (url, callback) { - utils.getVideosList(url, function (err, res) { + async.each(servers, function (server, callback) { + utils.getVideosList(server.url, function (err, res) { if (err) throw err expect(res.body).to.be.an('array') @@ -63,7 +72,7 @@ describe('Test multiple pods', function () { async.series([ function (next) { - utils.uploadVideo(urls[0], 'my super name for pod 1', 'my super description for pod 1', 'video_short1.webm', next) + utils.uploadVideo(servers[0].url, servers[0].access_token, 'my super name for pod 1', 'my super description for pod 1', 'video_short1.webm', next) }, function (next) { setTimeout(next, 11000) @@ -72,10 +81,10 @@ describe('Test multiple pods', function () { function (err) { if (err) throw err - async.each(urls, function (url, callback) { + async.each(servers, function (server, callback) { let base_magnet = null - utils.getVideosList(url, function (err, res) { + utils.getVideosList(server.url, function (err, res) { if (err) throw err const videos = res.body @@ -106,7 +115,7 @@ describe('Test multiple pods', function () { async.series([ function (next) { - utils.uploadVideo(urls[1], 'my super name for pod 2', 'my super description for pod 2', 'video_short2.webm', next) + utils.uploadVideo(servers[1].url, servers[1].access_token, 'my super name for pod 2', 'my super description for pod 2', 'video_short2.webm', next) }, function (next) { setTimeout(next, 11000) @@ -115,10 +124,10 @@ describe('Test multiple pods', function () { function (err) { if (err) throw err - async.each(urls, function (url, callback) { + async.each(servers, function (server, callback) { let base_magnet = null - utils.getVideosList(url, function (err, res) { + utils.getVideosList(server.url, function (err, res) { if (err) throw err const videos = res.body @@ -149,10 +158,10 @@ describe('Test multiple pods', function () { async.series([ function (next) { - utils.uploadVideo(urls[2], 'my super name for pod 3', 'my super description for pod 3', 'video_short3.webm', next) + utils.uploadVideo(servers[2].url, servers[2].access_token, 'my super name for pod 3', 'my super description for pod 3', 'video_short3.webm', next) }, function (next) { - utils.uploadVideo(urls[2], 'my super name for pod 3-2', 'my super description for pod 3-2', 'video_short.webm', next) + utils.uploadVideo(servers[2].url, servers[2].access_token, 'my super name for pod 3-2', 'my super description for pod 3-2', 'video_short.webm', next) }, function (next) { setTimeout(next, 22000) @@ -162,8 +171,8 @@ describe('Test multiple pods', function () { let base_magnet = null // All pods should have this video - async.each(urls, function (url, callback) { - utils.getVideosList(url, function (err, res) { + async.each(servers, function (server, callback) { + utils.getVideosList(server.url, function (err, res) { if (err) throw err const videos = res.body @@ -201,7 +210,7 @@ describe('Test multiple pods', function () { // Yes, this could be long this.timeout(200000) - utils.getVideosList(urls[2], function (err, res) { + utils.getVideosList(servers[2].url, function (err, res) { if (err) throw err const video = res.body[0] @@ -222,7 +231,7 @@ describe('Test multiple pods', function () { // Yes, this could be long this.timeout(200000) - utils.getVideosList(urls[0], function (err, res) { + utils.getVideosList(servers[0].url, function (err, res) { if (err) throw err const video = res.body[1] @@ -241,7 +250,7 @@ describe('Test multiple pods', function () { // Yes, this could be long this.timeout(200000) - utils.getVideosList(urls[1], function (err, res) { + utils.getVideosList(servers[1].url, function (err, res) { if (err) throw err const video = res.body[2] @@ -260,7 +269,7 @@ describe('Test multiple pods', function () { // Yes, this could be long this.timeout(200000) - utils.getVideosList(urls[0], function (err, res) { + utils.getVideosList(servers[0].url, function (err, res) { if (err) throw err const video = res.body[3] @@ -280,10 +289,10 @@ describe('Test multiple pods', function () { async.series([ function (next) { - utils.removeVideo(urls[2], to_remove[0], next) + utils.removeVideo(servers[2].url, servers[2].access_token, to_remove[0], next) }, function (next) { - utils.removeVideo(urls[2], to_remove[1], next) + utils.removeVideo(servers[2].url, servers[2].access_token, to_remove[1], next) }], function (err) { if (err) throw err @@ -293,8 +302,8 @@ describe('Test multiple pods', function () { }) it('Should have videos 1 and 3 on each pod', function (done) { - async.each(urls, function (url, callback) { - utils.getVideosList(url, function (err, res) { + async.each(servers, function (server, callback) { + utils.getVideosList(server.url, function (err, res) { if (err) throw err const videos = res.body @@ -313,8 +322,8 @@ describe('Test multiple pods', function () { }) after(function (done) { - apps.forEach(function (app) { - process.kill(-app.pid) + servers.forEach(function (server) { + process.kill(-server.app.pid) }) process.kill(-webtorrent.app.pid) diff --git a/server/tests/api/singlePod.js b/server/tests/api/singlePod.js index 0b96f221a..64d5475dd 100644 --- a/server/tests/api/singlePod.js +++ b/server/tests/api/singlePod.js @@ -12,8 +12,7 @@ webtorrent.silent = true const utils = require('./utils') describe('Test a single pod', function () { - let app = null - let url = '' + let server = null let video_id = -1 before(function (done) { @@ -24,9 +23,15 @@ describe('Test a single pod', function () { utils.flushTests(next) }, function (next) { - utils.runServer(1, function (app1, url1) { - app = app1 - url = url1 + utils.runServer(1, function (server1) { + server = server1 + next() + }) + }, + function (next) { + utils.loginAndGetAccessToken(server, function (err, token) { + if (err) throw err + server.access_token = token next() }) }, @@ -37,7 +42,7 @@ describe('Test a single pod', function () { }) it('Should not have videos', function (done) { - utils.getVideosList(url, function (err, res) { + utils.getVideosList(server.url, function (err, res) { if (err) throw err expect(res.body).to.be.an('array') @@ -49,14 +54,14 @@ describe('Test a single pod', function () { it('Should upload the video', function (done) { this.timeout(5000) - utils.uploadVideo(url, 'my super name', 'my super description', 'video_short.webm', done) + utils.uploadVideo(server.url, server.access_token, 'my super name', 'my super description', 'video_short.webm', done) }) it('Should seed the uploaded video', function (done) { // Yes, this could be long this.timeout(60000) - utils.getVideosList(url, function (err, res) { + utils.getVideosList(server.url, function (err, res) { if (err) throw err expect(res.body).to.be.an('array') @@ -84,7 +89,7 @@ describe('Test a single pod', function () { // Yes, this could be long this.timeout(60000) - utils.getVideo(url, video_id, function (err, res) { + utils.getVideo(server.url, video_id, function (err, res) { if (err) throw err const video = res.body @@ -104,7 +109,7 @@ describe('Test a single pod', function () { }) it('Should search the video', function (done) { - utils.searchVideo(url, 'my', function (err, res) { + utils.searchVideo(server.url, 'my', function (err, res) { if (err) throw err expect(res.body).to.be.an('array') @@ -120,7 +125,7 @@ describe('Test a single pod', function () { }) it('Should not find a search', function (done) { - utils.searchVideo(url, 'hello', function (err, res) { + utils.searchVideo(server.url, 'hello', function (err, res) { if (err) throw err expect(res.body).to.be.an('array') @@ -131,7 +136,7 @@ describe('Test a single pod', function () { }) it('Should remove the video', function (done) { - utils.removeVideo(url, video_id, function (err) { + utils.removeVideo(server.url, server.access_token, video_id, function (err) { if (err) throw err fs.readdir(pathUtils.join(__dirname, '../../../test1/uploads/'), function (err, files) { @@ -144,7 +149,7 @@ describe('Test a single pod', function () { }) it('Should not have videos', function (done) { - utils.getVideosList(url, function (err, res) { + utils.getVideosList(server.url, function (err, res) { if (err) throw err expect(res.body).to.be.an('array') @@ -155,7 +160,7 @@ describe('Test a single pod', function () { }) after(function (done) { - process.kill(-app.pid) + process.kill(-server.app.pid) process.kill(-webtorrent.app.pid) // Keep the logs if the test failed diff --git a/server/tests/api/users.js b/server/tests/api/users.js new file mode 100644 index 000000000..506b19299 --- /dev/null +++ b/server/tests/api/users.js @@ -0,0 +1,133 @@ +'use strict' + +const async = require('async') +const chai = require('chai') +const expect = chai.expect +const pathUtils = require('path') + +const webtorrent = require(pathUtils.join(__dirname, '../../lib/webtorrent')) +webtorrent.silent = true + +const utils = require('./utils') + +describe('Test users', function () { + let server = null + let access_token = null + let video_id + + before(function (done) { + this.timeout(20000) + + async.series([ + function (next) { + utils.flushTests(next) + }, + function (next) { + utils.runServer(1, function (server1) { + server = server1 + next() + }) + } + ], done) + }) + + it('Should not login with an invalid client id', function (done) { + const client = { id: 'client', password: server.client.secret } + utils.login(server.url, client, server.user, 400, function (err, res) { + if (err) throw err + + expect(res.body.error).to.equal('invalid_client') + done() + }) + }) + + it('Should not login with an invalid client password', function (done) { + const client = { id: server.client.id, password: 'coucou' } + utils.login(server.url, client, server.user, 400, function (err, res) { + if (err) throw err + + expect(res.body.error).to.equal('invalid_client') + done() + }) + }) + + it('Should not login with an invalid username', function (done) { + const user = { username: 'captain crochet', password: server.user.password } + utils.login(server.url, server.client, user, 400, function (err, res) { + if (err) throw err + + expect(res.body.error).to.equal('invalid_grant') + done() + }) + }) + + it('Should not login with an invalid password', function (done) { + const user = { username: server.user.username, password: 'mewthree' } + utils.login(server.url, server.client, user, 400, function (err, res) { + if (err) throw err + + expect(res.body.error).to.equal('invalid_grant') + done() + }) + }) + + it('Should not be able to upload a video', function (done) { + access_token = 'mysupertoken' + utils.uploadVideo(server.url, access_token, 'my super name', 'my super description', 'video_short.webm', 401, done) + }) + + it('Should be able to login', function (done) { + utils.login(server.url, server.client, server.user, 200, function (err, res) { + if (err) throw err + + access_token = res.body.access_token + done() + }) + }) + + it('Should upload the video with the correct token', function (done) { + utils.uploadVideo(server.url, access_token, 'my super name', 'my super description', 'video_short.webm', 204, function (err, res) { + if (err) throw err + + utils.getVideosList(server.url, function (err, res) { + if (err) throw err + + video_id = res.body[0].id + done() + }) + }) + }) + + it('Should upload the video again with the correct token', function (done) { + utils.uploadVideo(server.url, access_token, 'my super name 2', 'my super description 2', 'video_short.webm', 204, done) + }) + + it('Should not be able to remove the video with an incorrect token', function (done) { + utils.removeVideo(server.url, 'bad_token', video_id, 401, done) + }) + + it('Should not be able to remove the video with the token of another account') + + it('Should be able to remove the video with the correct token', function (done) { + utils.removeVideo(server.url, access_token, video_id, done) + }) + + it('Should logout') + + it('Should not be able to upload a video') + + it('Should not be able to remove a video') + + it('Should be able to login again') + + after(function (done) { + process.kill(-server.app.pid) + + // Keep the logs if the test failed + if (this.ok) { + utils.flushTests(done) + } else { + done() + } + }) +}) diff --git a/server/tests/api/utils.js b/server/tests/api/utils.js index 1b2f61059..d37e12cb2 100644 --- a/server/tests/api/utils.js +++ b/server/tests/api/utils.js @@ -11,6 +11,8 @@ const testUtils = { getFriendsList: getFriendsList, getVideo: getVideo, getVideosList: getVideosList, + login: login, + loginAndGetAccessToken: loginAndGetAccessToken, makeFriends: makeFriends, quitFriends: quitFriends, removeVideo: removeVideo, @@ -59,6 +61,40 @@ function getVideosList (url, end) { .end(end) } +function login (url, client, user, expected_status, end) { + if (!end) { + end = expected_status + expected_status = 200 + } + + const path = '/api/v1/users/token' + + const body = { + client_id: client.id, + client_secret: client.secret, + username: user.username, + password: user.password, + response_type: 'code', + grant_type: 'password', + scope: 'upload' + } + + request(url) + .post(path) + .type('form') + .send(body) + .expect(expected_status) + .end(end) +} + +function loginAndGetAccessToken (server, callback) { + login(server.url, server.client, server.user, 200, function (err, res) { + if (err) return callback(err) + + return callback(null, res.body.access_token) + }) +} + function makeFriends (url, expected_status, callback) { if (!callback) { callback = expected_status @@ -96,13 +132,19 @@ function quitFriends (url, callback) { }) } -function removeVideo (url, id, end) { +function removeVideo (url, token, id, expected_status, end) { + if (!end) { + end = expected_status + expected_status = 204 + } + const path = '/api/v1/videos' request(url) .delete(path + '/' + id) .set('Accept', 'application/json') - .expect(204) + .set('Authorization', 'Bearer ' + token) + .expect(expected_status) .end(end) } @@ -133,12 +175,32 @@ function flushAndRunMultipleServers (total_servers, serversRun) { } function runServer (number, callback) { - const port = 9000 + number + const server = { + app: null, + url: `http://localhost:${9000 + number}`, + client: { + id: null, + secret: null + }, + user: { + username: null, + password: null + } + } + + // These actions are async so we need to be sure that they have both been done const server_run_string = { 'Connected to mongodb': false, 'Server listening on port': false } + const regexps = { + client_id: 'Client id: ([a-f0-9]+)', + client_secret: 'Client secret: (.+)', + user_username: 'Username: (.+)', + user_password: 'User password: (.+)' + } + // Share the environment const env = Object.create(process.env) env.NODE_ENV = 'test' @@ -149,9 +211,22 @@ function runServer (number, callback) { detached: true } - const app = fork(pathUtils.join(__dirname, '../../../server.js'), [], options) - app.stdout.on('data', function onStdout (data) { + server.app = fork(pathUtils.join(__dirname, '../../../server.js'), [], options) + server.app.stdout.on('data', function onStdout (data) { let dont_continue = false + + // Capture things if we want to + for (const key of Object.keys(regexps)) { + const regexp = regexps[key] + const matches = data.toString().match(regexp) + if (matches !== null) { + if (key === 'client_id') server.client.id = matches[1] + else if (key === 'client_secret') server.client.secret = matches[1] + else if (key === 'user_username') server.user.username = matches[1] + else if (key === 'user_password') server.user.password = matches[1] + } + } + // Check if all required sentences are here for (const key of Object.keys(server_run_string)) { if (data.toString().indexOf(key) !== -1) server_run_string[key] = true @@ -161,8 +236,8 @@ function runServer (number, callback) { // If no, there is maybe one thing not already initialized (mongodb...) if (dont_continue === true) return - app.stdout.removeListener('data', onStdout) - callback(app, 'http://localhost:' + port) + server.app.stdout.removeListener('data', onStdout) + callback(server) }) } @@ -177,16 +252,22 @@ function searchVideo (url, search, end) { .end(end) } -function uploadVideo (url, name, description, fixture, end) { +function uploadVideo (url, access_token, name, description, fixture, special_status, end) { + if (!end) { + end = special_status + special_status = 204 + } + const path = '/api/v1/videos' request(url) .post(path) .set('Accept', 'application/json') + .set('Authorization', 'Bearer ' + access_token) .field('name', name) .field('description', description) .attach('videofile', pathUtils.join(__dirname, 'fixtures', fixture)) - .expect(204) + .expect(special_status) .end(end) } -- 2.41.0