aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--controllers/api/v1/index.js7
-rw-r--r--controllers/api/v1/pods.js46
-rw-r--r--controllers/api/v1/remoteVideos.js30
-rw-r--r--controllers/api/v1/videos.js83
-rw-r--r--controllers/index.js4
-rw-r--r--controllers/views.js29
-rw-r--r--helpers/customValidators.js15
-rw-r--r--helpers/logger.js11
-rw-r--r--helpers/utils.js111
-rw-r--r--initializers/checker.js12
-rw-r--r--initializers/constants.js39
-rw-r--r--initializers/database.js37
-rw-r--r--lib/poolRequests.js211
-rw-r--r--lib/webTorrentNode.js27
-rw-r--r--lib/webtorrent.js6
-rw-r--r--middlewares/index.js10
-rw-r--r--middlewares/misc.js19
-rw-r--r--middlewares/reqValidators/index.js6
-rw-r--r--middlewares/reqValidators/pods.js10
-rw-r--r--middlewares/reqValidators/remote.js34
-rw-r--r--middlewares/reqValidators/utils.js11
-rw-r--r--middlewares/reqValidators/videos.js51
-rw-r--r--models/pods.js120
-rw-r--r--models/videos.js222
-rw-r--r--tests/api/singlePod.js2
-rw-r--r--tests/api/utils.js6
26 files changed, 648 insertions, 511 deletions
diff --git a/controllers/api/v1/index.js b/controllers/api/v1/index.js
index f5504ad85..b16eeb0f6 100644
--- a/controllers/api/v1/index.js
+++ b/controllers/api/v1/index.js
@@ -2,11 +2,14 @@
2 'use strict' 2 'use strict'
3 3
4 var express = require('express') 4 var express = require('express')
5
5 var router = express.Router() 6 var router = express.Router()
6 7
7 router.use('/videos', require('./videos'))
8 router.use('/remotevideos', require('./remoteVideos'))
9 router.use('/pods', require('./pods')) 8 router.use('/pods', require('./pods'))
9 router.use('/remotevideos', require('./remoteVideos'))
10 router.use('/videos', require('./videos'))
11
12 // ---------------------------------------------------------------------------
10 13
11 module.exports = router 14 module.exports = router
12})() 15})()
diff --git a/controllers/api/v1/pods.js b/controllers/api/v1/pods.js
index 30385bd5a..b073e85af 100644
--- a/controllers/api/v1/pods.js
+++ b/controllers/api/v1/pods.js
@@ -2,20 +2,27 @@
2 'use strict' 2 'use strict'
3 3
4 var express = require('express') 4 var express = require('express')
5 var router = express.Router() 5
6 var middleware = require('../../../middlewares') 6 var middleware = require('../../../middlewares')
7 var miscMiddleware = middleware.misc 7 var miscMiddleware = middleware.misc
8 var pods = require('../../../models/pods')
8 var reqValidator = middleware.reqValidators.pods 9 var reqValidator = middleware.reqValidators.pods
9 var secureRequest = middleware.reqValidators.remote.secureRequest 10 var secureRequest = middleware.reqValidators.remote.secureRequest
10 var pods = require('../../../models/pods')
11 11
12 function listPods (req, res, next) { 12 var router = express.Router()
13 pods.list(function (err, pods_list) {
14 if (err) return next(err)
15 13
16 res.json(pods_list) 14 router.get('/', miscMiddleware.cache(false), listPods)
17 }) 15 router.post('/', reqValidator.podsAdd, miscMiddleware.cache(false), addPods)
18 } 16 router.get('/makefriends', miscMiddleware.cache(false), makeFriends)
17 router.get('/quitfriends', miscMiddleware.cache(false), quitFriends)
18 // Post because this is a secured request
19 router.post('/remove', secureRequest, miscMiddleware.decryptBody, removePods)
20
21 // ---------------------------------------------------------------------------
22
23 module.exports = router
24
25 // ---------------------------------------------------------------------------
19 26
20 function addPods (req, res, next) { 27 function addPods (req, res, next) {
21 pods.add(req.body.data, function (err, json) { 28 pods.add(req.body.data, function (err, json) {
@@ -25,11 +32,11 @@
25 }) 32 })
26 } 33 }
27 34
28 function removePods (req, res, next) { 35 function listPods (req, res, next) {
29 pods.remove(req.body.signature.url, function (err) { 36 pods.list(function (err, pods_list) {
30 if (err) return next(err) 37 if (err) return next(err)
31 38
32 res.sendStatus(204) 39 res.json(pods_list)
33 }) 40 })
34 } 41 }
35 42
@@ -50,20 +57,19 @@
50 }) 57 })
51 } 58 }
52 59
53 function quitFriends (req, res, next) { 60 function removePods (req, res, next) {
54 pods.quitFriends(function (err) { 61 pods.remove(req.body.signature.url, function (err) {
55 if (err) return next(err) 62 if (err) return next(err)
56 63
57 res.sendStatus(204) 64 res.sendStatus(204)
58 }) 65 })
59 } 66 }
60 67
61 router.get('/', miscMiddleware.cache(false), listPods) 68 function quitFriends (req, res, next) {
62 router.get('/makefriends', miscMiddleware.cache(false), makeFriends) 69 pods.quitFriends(function (err) {
63 router.get('/quitfriends', miscMiddleware.cache(false), quitFriends) 70 if (err) return next(err)
64 router.post('/', reqValidator.podsAdd, miscMiddleware.cache(false), addPods)
65 // Post because this is a secured request
66 router.post('/remove', secureRequest, miscMiddleware.decryptBody, removePods)
67 71
68 module.exports = router 72 res.sendStatus(204)
73 })
74 }
69})() 75})()
diff --git a/controllers/api/v1/remoteVideos.js b/controllers/api/v1/remoteVideos.js
index d534d6792..2be2fc87e 100644
--- a/controllers/api/v1/remoteVideos.js
+++ b/controllers/api/v1/remoteVideos.js
@@ -2,7 +2,6 @@
2 'use strict' 2 'use strict'
3 3
4 var express = require('express') 4 var express = require('express')
5 var router = express.Router()
6 var pluck = require('lodash-node/compat/collection/pluck') 5 var pluck = require('lodash-node/compat/collection/pluck')
7 6
8 var middleware = require('../../../middlewares') 7 var middleware = require('../../../middlewares')
@@ -10,6 +9,30 @@
10 var reqValidator = middleware.reqValidators.remote 9 var reqValidator = middleware.reqValidators.remote
11 var videos = require('../../../models/videos') 10 var videos = require('../../../models/videos')
12 11
12 var router = express.Router()
13
14 router.post('/add',
15 reqValidator.secureRequest,
16 miscMiddleware.decryptBody,
17 reqValidator.remoteVideosAdd,
18 miscMiddleware.cache(false),
19 addRemoteVideos
20 )
21
22 router.post('/remove',
23 reqValidator.secureRequest,
24 miscMiddleware.decryptBody,
25 reqValidator.remoteVideosRemove,
26 miscMiddleware.cache(false),
27 removeRemoteVideo
28 )
29
30 // ---------------------------------------------------------------------------
31
32 module.exports = router
33
34 // ---------------------------------------------------------------------------
35
13 function addRemoteVideos (req, res, next) { 36 function addRemoteVideos (req, res, next) {
14 videos.addRemotes(req.body.data, function (err, videos) { 37 videos.addRemotes(req.body.data, function (err, videos) {
15 if (err) return next(err) 38 if (err) return next(err)
@@ -25,9 +48,4 @@
25 res.sendStatus(204) 48 res.sendStatus(204)
26 }) 49 })
27 } 50 }
28
29 router.post('/add', reqValidator.secureRequest, miscMiddleware.decryptBody, reqValidator.remoteVideosAdd, miscMiddleware.cache(false), addRemoteVideos)
30 router.post('/remove', reqValidator.secureRequest, miscMiddleware.decryptBody, reqValidator.remoteVideosRemove, miscMiddleware.cache(false), removeRemoteVideo)
31
32 module.exports = router
33})() 51})()
diff --git a/controllers/api/v1/videos.js b/controllers/api/v1/videos.js
index aa8cb466b..64b05e32b 100644
--- a/controllers/api/v1/videos.js
+++ b/controllers/api/v1/videos.js
@@ -1,34 +1,50 @@
1;(function () { 1;(function () {
2 'use strict' 2 'use strict'
3 3
4 var express = require('express')
5 var config = require('config') 4 var config = require('config')
6 var crypto = require('crypto') 5 var crypto = require('crypto')
6 var express = require('express')
7 var multer = require('multer') 7 var multer = require('multer')
8 var router = express.Router()
9 8
10 var middleware = require('../../../middlewares') 9 var middleware = require('../../../middlewares')
11 var miscMiddleware = middleware.misc 10 var miscMiddleware = middleware.misc
12 var reqValidator = middleware.reqValidators.videos 11 var reqValidator = middleware.reqValidators.videos
13 var videos = require('../../../models/videos') 12 var videos = require('../../../models/videos')
14 13
14 var router = express.Router()
15 var uploads = config.get('storage.uploads') 15 var uploads = config.get('storage.uploads')
16 16
17 function listVideos (req, res, next) { 17 // multer configuration
18 videos.list(function (err, videos_list) { 18 var storage = multer.diskStorage({
19 if (err) return next(err) 19 destination: function (req, file, cb) {
20 cb(null, uploads)
21 },
20 22
21 res.json(videos_list) 23 filename: function (req, file, cb) {
22 }) 24 var extension = ''
23 } 25 if (file.mimetype === 'video/webm') extension = 'webm'
26 else if (file.mimetype === 'video/mp4') extension = 'mp4'
27 else if (file.mimetype === 'video/ogg') extension = 'ogv'
28 crypto.pseudoRandomBytes(16, function (err, raw) {
29 var fieldname = err ? undefined : raw.toString('hex')
30 cb(null, fieldname + '.' + extension)
31 })
32 }
33 })
24 34
25 function searchVideos (req, res, next) { 35 var reqFiles = multer({ storage: storage }).fields([{ name: 'input_video', maxCount: 1 }])
26 videos.search(req.params.name, function (err, videos_list) {
27 if (err) return next(err)
28 36
29 res.json(videos_list) 37 router.get('/', miscMiddleware.cache(false), listVideos)
30 }) 38 router.post('/', reqFiles, reqValidator.videosAdd, miscMiddleware.cache(false), addVideos)
31 } 39 router.get('/:id', reqValidator.videosGet, miscMiddleware.cache(false), getVideos)
40 router.delete('/:id', reqValidator.videosRemove, miscMiddleware.cache(false), removeVideo)
41 router.get('/search/:name', reqValidator.videosSearch, miscMiddleware.cache(false), searchVideos)
42
43 // ---------------------------------------------------------------------------
44
45 module.exports = router
46
47 // ---------------------------------------------------------------------------
32 48
33 function addVideos (req, res, next) { 49 function addVideos (req, res, next) {
34 videos.add({ video: req.files.input_video[0], data: req.body }, function (err) { 50 videos.add({ video: req.files.input_video[0], data: req.body }, function (err) {
@@ -51,6 +67,14 @@
51 }) 67 })
52 } 68 }
53 69
70 function listVideos (req, res, next) {
71 videos.list(function (err, videos_list) {
72 if (err) return next(err)
73
74 res.json(videos_list)
75 })
76 }
77
54 function removeVideo (req, res, next) { 78 function removeVideo (req, res, next) {
55 videos.remove(req.params.id, function (err) { 79 videos.remove(req.params.id, function (err) {
56 if (err) return next(err) 80 if (err) return next(err)
@@ -59,30 +83,11 @@
59 }) 83 })
60 } 84 }
61 85
62 // multer configuration 86 function searchVideos (req, res, next) {
63 var storage = multer.diskStorage({ 87 videos.search(req.params.name, function (err, videos_list) {
64 destination: function (req, file, cb) { 88 if (err) return next(err)
65 cb(null, uploads)
66 },
67
68 filename: function (req, file, cb) {
69 var extension = ''
70 if (file.mimetype === 'video/webm') extension = 'webm'
71 else if (file.mimetype === 'video/mp4') extension = 'mp4'
72 else if (file.mimetype === 'video/ogg') extension = 'ogv'
73 crypto.pseudoRandomBytes(16, function (err, raw) {
74 var fieldname = err ? undefined : raw.toString('hex')
75 cb(null, fieldname + '.' + extension)
76 })
77 }
78 })
79 var reqFiles = multer({ storage: storage }).fields([{ name: 'input_video', maxCount: 1 }])
80
81 router.get('/', miscMiddleware.cache(false), listVideos)
82 router.post('/', reqFiles, reqValidator.videosAdd, miscMiddleware.cache(false), addVideos)
83 router.get('/search/:name', reqValidator.videosSearch, miscMiddleware.cache(false), searchVideos)
84 router.get('/:id', reqValidator.videosGet, miscMiddleware.cache(false), getVideos)
85 router.delete('/:id', reqValidator.videosRemove, miscMiddleware.cache(false), removeVideo)
86 89
87 module.exports = router 90 res.json(videos_list)
91 })
92 }
88})() 93})()
diff --git a/controllers/index.js b/controllers/index.js
index 7dca002ff..770d08248 100644
--- a/controllers/index.js
+++ b/controllers/index.js
@@ -3,10 +3,8 @@
3 3
4 var constants = require('../initializers/constants') 4 var constants = require('../initializers/constants')
5 5
6 var routes = { 6 module.exports = {
7 api: require('./api/' + constants.API_VERSION), 7 api: require('./api/' + constants.API_VERSION),
8 views: require('./views') 8 views: require('./views')
9 } 9 }
10
11 module.exports = routes
12})() 10})()
diff --git a/controllers/views.js b/controllers/views.js
index ebd97380e..1bb4ffe70 100644
--- a/controllers/views.js
+++ b/controllers/views.js
@@ -1,24 +1,29 @@
1;(function () { 1;(function () {
2 'use strict' 2 'use strict'
3 3
4 function getPartial (req, res) {
5 var directory = req.params.directory
6 var name = req.params.name
7
8 res.render('partials/' + directory + '/' + name)
9 }
10
11 function getIndex (req, res) {
12 res.render('index')
13 }
14
15 var express = require('express') 4 var express = require('express')
5
16 var middleware = require('../middlewares').misc 6 var middleware = require('../middlewares').misc
17 7
18 var router = express.Router() 8 var router = express.Router()
19 9
20 router.get('/partials/:directory/:name', middleware.cache(), getPartial)
21 router.get(/^\/(index)?$/, middleware.cache(), getIndex) 10 router.get(/^\/(index)?$/, middleware.cache(), getIndex)
11 router.get('/partials/:directory/:name', middleware.cache(), getPartial)
12
13 // ---------------------------------------------------------------------------
22 14
23 module.exports = router 15 module.exports = router
16
17 // ---------------------------------------------------------------------------
18
19 function getIndex (req, res) {
20 res.render('index')
21 }
22
23 function getPartial (req, res) {
24 var directory = req.params.directory
25 var name = req.params.name
26
27 res.render('partials/' + directory + '/' + name)
28 }
24})() 29})()
diff --git a/helpers/customValidators.js b/helpers/customValidators.js
index 73c2f8461..c433e5c5d 100644
--- a/helpers/customValidators.js
+++ b/helpers/customValidators.js
@@ -3,9 +3,13 @@
3 3
4 var validator = require('validator') 4 var validator = require('validator')
5 5
6 var customValidators = {} 6 var customValidators = {
7 eachIsRemoteVideosAddValid: eachIsRemoteVideosAddValid,
8 eachIsRemoteVideosRemoveValid: eachIsRemoteVideosRemoveValid,
9 isArray: isArray
10 }
7 11
8 customValidators.eachIsRemoteVideosAddValid = function (values) { 12 function eachIsRemoteVideosAddValid (values) {
9 return values.every(function (val) { 13 return values.every(function (val) {
10 return validator.isLength(val.name, 1, 50) && 14 return validator.isLength(val.name, 1, 50) &&
11 validator.isLength(val.description, 1, 50) && 15 validator.isLength(val.description, 1, 50) &&
@@ -14,16 +18,17 @@
14 }) 18 })
15 } 19 }
16 20
17 customValidators.eachIsRemoteVideosRemoveValid = function (values) { 21 function eachIsRemoteVideosRemoveValid (values) {
18 return values.every(function (val) { 22 return values.every(function (val) {
19 return validator.isLength(val.magnetUri, 10) 23 return validator.isLength(val.magnetUri, 10)
20 }) 24 })
21 } 25 }
22 26
23 customValidators.isArray = function (value) { 27 function isArray (value) {
24 return Array.isArray(value) 28 return Array.isArray(value)
25 } 29 }
26 30
27 // ----------- Export ----------- 31 // ---------------------------------------------------------------------------
32
28 module.exports = customValidators 33 module.exports = customValidators
29})() 34})()
diff --git a/helpers/logger.js b/helpers/logger.js
index 850af10cb..fa5b53708 100644
--- a/helpers/logger.js
+++ b/helpers/logger.js
@@ -4,11 +4,9 @@
4 4
5 var config = require('config') 5 var config = require('config')
6 var winston = require('winston') 6 var winston = require('winston')
7
8 var logDir = __dirname + '/../' + config.get('storage.logs')
9
10 winston.emitErrs = true 7 winston.emitErrs = true
11 8
9 var logDir = __dirname + '/../' + config.get('storage.logs')
12 var logger = new winston.Logger({ 10 var logger = new winston.Logger({
13 transports: [ 11 transports: [
14 new winston.transports.File({ 12 new winston.transports.File({
@@ -31,10 +29,13 @@
31 exitOnError: true 29 exitOnError: true
32 }) 30 })
33 31
34 module.exports = logger 32 logger.stream = {
35 module.exports.stream = {
36 write: function (message, encoding) { 33 write: function (message, encoding) {
37 logger.info(message) 34 logger.info(message)
38 } 35 }
39 } 36 }
37
38 // ---------------------------------------------------------------------------
39
40 module.exports = logger
40})() 41})()
diff --git a/helpers/utils.js b/helpers/utils.js
index 7cdb2600d..ec46631b1 100644
--- a/helpers/utils.js
+++ b/helpers/utils.js
@@ -13,47 +13,29 @@
13 var constants = require('../initializers/constants') 13 var constants = require('../initializers/constants')
14 var logger = require('./logger') 14 var logger = require('./logger')
15 15
16 var utils = {} 16 var certDir = __dirname + '/../' + config.get('storage.certs')
17
18 var http = config.get('webserver.https') ? 'https' : 'http' 17 var http = config.get('webserver.https') ? 'https' : 'http'
19 var host = config.get('webserver.host') 18 var host = config.get('webserver.host')
20 var port = config.get('webserver.port') 19 var port = config.get('webserver.port')
21 var algorithm = 'aes-256-ctr' 20 var algorithm = 'aes-256-ctr'
22 21
23 // ----------- Private functions ---------- 22 var utils = {
24 23 getCertDir: getCertDir,
25 function makeRetryRequest (params, from_url, to_pod, signature, callbackEach) { 24 certsExist: certsExist,
26 // Append the signature 25 cleanForExit: cleanForExit,
27 if (signature) { 26 createCerts: createCerts,
28 params.json.signature = { 27 createCertsIfNotExist: createCertsIfNotExist,
29 url: from_url, 28 generatePassword: generatePassword,
30 signature: signature 29 makeMultipleRetryRequest: makeMultipleRetryRequest,
31 } 30 symetricEncrypt: symetricEncrypt,
32 } 31 symetricDecrypt: symetricDecrypt
33
34 logger.debug('Make retry requests to %s.', to_pod.url)
35
36 replay(
37 request.post(params, function (err, response, body) {
38 callbackEach(err, response, body, params.url, to_pod)
39 }),
40 {
41 retries: constants.REQUEST_RETRIES,
42 factor: 3,
43 maxTimeout: Infinity,
44 errorCodes: [ 'EADDRINFO', 'ETIMEDOUT', 'ECONNRESET', 'ESOCKETTIMEDOUT', 'ENOTFOUND', 'ECONNREFUSED' ]
45 }
46 ).on('replay', function (replay) {
47 logger.info('Replaying request to %s. Request failed: %d %s. Replay number: #%d. Will retry in: %d ms.',
48 params.url, replay.error.code, replay.error.message, replay.number, replay.delay)
49 })
50 } 32 }
51 33
52 // ----------- Public attributes ---------- 34 function getCertDir () {
53 utils.certDir = __dirname + '/../' + config.get('storage.certs') 35 return certDir
36 }
54 37
55 // { path, data } 38 function makeMultipleRetryRequest (all_data, pods, callbackEach, callback) {
56 utils.makeMultipleRetryRequest = function (all_data, pods, callbackEach, callback) {
57 if (!callback) { 39 if (!callback) {
58 callback = callbackEach 40 callback = callbackEach
59 callbackEach = null 41 callbackEach = null
@@ -64,7 +46,7 @@
64 46
65 // Add signature if it is specified in the params 47 // Add signature if it is specified in the params
66 if (all_data.method === 'POST' && all_data.data && all_data.sign === true) { 48 if (all_data.method === 'POST' && all_data.data && all_data.sign === true) {
67 var myKey = ursa.createPrivateKey(fs.readFileSync(utils.certDir + 'peertube.key.pem')) 49 var myKey = ursa.createPrivateKey(fs.readFileSync(certDir + 'peertube.key.pem'))
68 signature = myKey.hashAndSign('sha256', url, 'utf8', 'hex') 50 signature = myKey.hashAndSign('sha256', url, 'utf8', 'hex')
69 } 51 }
70 52
@@ -93,7 +75,7 @@
93 75
94 // TODO: ES6 with let 76 // TODO: ES6 with let
95 ;(function (crt_copy, copy_params, copy_url, copy_pod, copy_signature) { 77 ;(function (crt_copy, copy_params, copy_url, copy_pod, copy_signature) {
96 utils.symetricEncrypt(JSON.stringify(all_data.data), function (err, dataEncrypted) { 78 symetricEncrypt(JSON.stringify(all_data.data), function (err, dataEncrypted) {
97 if (err) throw err 79 if (err) throw err
98 80
99 var passwordEncrypted = crt_copy.encrypt(dataEncrypted.password, 'utf8', 'hex') 81 var passwordEncrypted = crt_copy.encrypt(dataEncrypted.password, 'utf8', 'hex')
@@ -115,14 +97,14 @@
115 }, callback) 97 }, callback)
116 } 98 }
117 99
118 utils.certsExist = function (callback) { 100 function certsExist (callback) {
119 fs.exists(utils.certDir + 'peertube.key.pem', function (exists) { 101 fs.exists(certDir + 'peertube.key.pem', function (exists) {
120 return callback(exists) 102 return callback(exists)
121 }) 103 })
122 } 104 }
123 105
124 utils.createCerts = function (callback) { 106 function createCerts (callback) {
125 utils.certsExist(function (exist) { 107 certsExist(function (exist) {
126 if (exist === true) { 108 if (exist === true) {
127 var string = 'Certs already exist.' 109 var string = 'Certs already exist.'
128 logger.warning(string) 110 logger.warning(string)
@@ -130,7 +112,7 @@
130 } 112 }
131 113
132 logger.info('Generating a RSA key...') 114 logger.info('Generating a RSA key...')
133 openssl.exec('genrsa', { 'out': utils.certDir + 'peertube.key.pem', '2048': false }, function (err) { 115 openssl.exec('genrsa', { 'out': certDir + 'peertube.key.pem', '2048': false }, function (err) {
134 if (err) { 116 if (err) {
135 logger.error('Cannot create private key on this pod.', { error: err }) 117 logger.error('Cannot create private key on this pod.', { error: err })
136 return callback(err) 118 return callback(err)
@@ -138,7 +120,7 @@
138 logger.info('RSA key generated.') 120 logger.info('RSA key generated.')
139 121
140 logger.info('Manage public key...') 122 logger.info('Manage public key...')
141 openssl.exec('rsa', { 'in': utils.certDir + 'peertube.key.pem', 'pubout': true, 'out': utils.certDir + 'peertube.pub' }, function (err) { 123 openssl.exec('rsa', { 'in': certDir + 'peertube.key.pem', 'pubout': true, 'out': certDir + 'peertube.pub' }, function (err) {
142 if (err) { 124 if (err) {
143 logger.error('Cannot create public key on this pod .', { error: err }) 125 logger.error('Cannot create public key on this pod .', { error: err })
144 return callback(err) 126 return callback(err)
@@ -151,19 +133,19 @@
151 }) 133 })
152 } 134 }
153 135
154 utils.createCertsIfNotExist = function (callback) { 136 function createCertsIfNotExist (callback) {
155 utils.certsExist(function (exist) { 137 certsExist(function (exist) {
156 if (exist === true) { 138 if (exist === true) {
157 return callback(null) 139 return callback(null)
158 } 140 }
159 141
160 utils.createCerts(function (err) { 142 createCerts(function (err) {
161 return callback(err) 143 return callback(err)
162 }) 144 })
163 }) 145 })
164 } 146 }
165 147
166 utils.generatePassword = function (callback) { 148 function generatePassword (callback) {
167 crypto.randomBytes(32, function (err, buf) { 149 crypto.randomBytes(32, function (err, buf) {
168 if (err) { 150 if (err) {
169 return callback(err) 151 return callback(err)
@@ -173,8 +155,8 @@
173 }) 155 })
174 } 156 }
175 157
176 utils.symetricEncrypt = function (text, callback) { 158 function symetricEncrypt (text, callback) {
177 utils.generatePassword(function (err, password) { 159 generatePassword(function (err, password) {
178 if (err) { 160 if (err) {
179 return callback(err) 161 return callback(err)
180 } 162 }
@@ -186,17 +168,48 @@
186 }) 168 })
187 } 169 }
188 170
189 utils.symetricDecrypt = function (text, password) { 171 function symetricDecrypt (text, password) {
190 var decipher = crypto.createDecipher(algorithm, password) 172 var decipher = crypto.createDecipher(algorithm, password)
191 var dec = decipher.update(text, 'hex', 'utf8') 173 var dec = decipher.update(text, 'hex', 'utf8')
192 dec += decipher.final('utf8') 174 dec += decipher.final('utf8')
193 return dec 175 return dec
194 } 176 }
195 177
196 utils.cleanForExit = function (webtorrent_process) { 178 function cleanForExit (webtorrent_process) {
197 logger.info('Gracefully exiting') 179 logger.info('Gracefully exiting')
198 process.kill(-webtorrent_process.pid) 180 process.kill(-webtorrent_process.pid)
199 } 181 }
200 182
183 // ---------------------------------------------------------------------------
184
201 module.exports = utils 185 module.exports = utils
186
187 // ---------------------------------------------------------------------------
188
189 function makeRetryRequest (params, from_url, to_pod, signature, callbackEach) {
190 // Append the signature
191 if (signature) {
192 params.json.signature = {
193 url: from_url,
194 signature: signature
195 }
196 }
197
198 logger.debug('Make retry requests to %s.', to_pod.url)
199
200 replay(
201 request.post(params, function (err, response, body) {
202 callbackEach(err, response, body, params.url, to_pod)
203 }),
204 {
205 retries: constants.REQUEST_RETRIES,
206 factor: 3,
207 maxTimeout: Infinity,
208 errorCodes: [ 'EADDRINFO', 'ETIMEDOUT', 'ECONNRESET', 'ESOCKETTIMEDOUT', 'ENOTFOUND', 'ECONNREFUSED' ]
209 }
210 ).on('replay', function (replay) {
211 logger.info('Replaying request to %s. Request failed: %d %s. Replay number: #%d. Will retry in: %d ms.',
212 params.url, replay.error.code, replay.error.message, replay.number, replay.delay)
213 })
214 }
202})() 215})()
diff --git a/initializers/checker.js b/initializers/checker.js
index 7a3a53616..7a09c02d1 100644
--- a/initializers/checker.js
+++ b/initializers/checker.js
@@ -4,10 +4,13 @@
4 var config = require('config') 4 var config = require('config')
5 var mkdirp = require('mkdirp') 5 var mkdirp = require('mkdirp')
6 6
7 var checker = {} 7 var checker = {
8 checkConfig: checkConfig,
9 createDirectoriesIfNotExist: createDirectoriesIfNotExist
10 }
8 11
9 // Check the config files 12 // Check the config files
10 checker.checkConfig = function () { 13 function checkConfig () {
11 var required = [ 'listen.port', 14 var required = [ 'listen.port',
12 'webserver.https', 'webserver.host', 'webserver.port', 15 'webserver.https', 'webserver.host', 'webserver.port',
13 'database.host', 'database.port', 'database.suffix', 16 'database.host', 'database.port', 'database.suffix',
@@ -25,7 +28,7 @@
25 } 28 }
26 29
27 // Create directories for the storage if it doesn't exist 30 // Create directories for the storage if it doesn't exist
28 checker.createDirectoriesIfNotExist = function () { 31 function createDirectoriesIfNotExist () {
29 var storages = config.get('storage') 32 var storages = config.get('storage')
30 33
31 for (var key of Object.keys(storages)) { 34 for (var key of Object.keys(storages)) {
@@ -40,6 +43,7 @@
40 } 43 }
41 } 44 }
42 45
43 // ----------- Export ----------- 46 // ---------------------------------------------------------------------------
47
44 module.exports = checker 48 module.exports = checker
45})() 49})()
diff --git a/initializers/constants.js b/initializers/constants.js
index 00b713961..1e101a747 100644
--- a/initializers/constants.js
+++ b/initializers/constants.js
@@ -1,37 +1,44 @@
1;(function () { 1;(function () {
2 'use strict' 2 'use strict'
3 3
4 var constants = {}
5
6 function isTestInstance () {
7 return (process.env.NODE_ENV === 'test')
8 }
9
10 // API version of our pod 4 // API version of our pod
11 constants.API_VERSION = 'v1' 5 var API_VERSION = 'v1'
12 6
13 // Score a pod has when we create it as a friend 7 // Score a pod has when we create it as a friend
14 constants.FRIEND_BASE_SCORE = 100 8 var FRIEND_BASE_SCORE = 100
15 9
16 // Time to wait between requests to the friends 10 // Time to wait between requests to the friends
17 constants.INTERVAL = 60000 11 var INTERVAL = 60000
18 12
19 // Number of points we add/remove from a friend after a successful/bad request 13 // Number of points we add/remove from a friend after a successful/bad request
20 constants.PODS_SCORE = { 14 var PODS_SCORE = {
21 MALUS: -10, 15 MALUS: -10,
22 BONUS: 10 16 BONUS: 10
23 } 17 }
24 18
25 // Number of retries we make for the make retry requests (to friends...) 19 // Number of retries we make for the make retry requests (to friends...)
26 constants.REQUEST_RETRIES = 10 20 var REQUEST_RETRIES = 10
27 21
28 // Special constants for a test instance 22 // Special constants for a test instance
29 if (isTestInstance() === true) { 23 if (isTestInstance() === true) {
30 constants.FRIEND_BASE_SCORE = 20 24 FRIEND_BASE_SCORE = 20
31 constants.INTERVAL = 10000 25 INTERVAL = 10000
32 constants.REQUEST_RETRIES = 2 26 REQUEST_RETRIES = 2
27 }
28
29 // ---------------------------------------------------------------------------
30
31 module.exports = {
32 API_VERSION: API_VERSION,
33 FRIEND_BASE_SCORE: FRIEND_BASE_SCORE,
34 INTERVAL: INTERVAL,
35 PODS_SCORE: PODS_SCORE,
36 REQUEST_RETRIES: REQUEST_RETRIES
33 } 37 }
34 38
35 // ----------- Export ----------- 39 // ---------------------------------------------------------------------------
36 module.exports = constants 40
41 function isTestInstance () {
42 return (process.env.NODE_ENV === 'test')
43 }
37})() 44})()
diff --git a/initializers/database.js b/initializers/database.js
index 4570d3739..e041d5c4b 100644
--- a/initializers/database.js
+++ b/initializers/database.js
@@ -11,17 +11,6 @@
11 var host = config.get('database.host') 11 var host = config.get('database.host')
12 var port = config.get('database.port') 12 var port = config.get('database.port')
13 13
14 // ----------- Videos -----------
15 var videosSchema = mongoose.Schema({
16 name: String,
17 namePath: String,
18 description: String,
19 magnetUri: String,
20 podUrl: String
21 })
22
23 var VideosDB = mongoose.model('videos', videosSchema)
24
25 // ----------- Pods ----------- 14 // ----------- Pods -----------
26 var podsSchema = mongoose.Schema({ 15 var podsSchema = mongoose.Schema({
27 url: String, 16 url: String,
@@ -40,6 +29,25 @@
40 29
41 var PoolRequestsDB = mongoose.model('poolRequests', poolRequestsSchema) 30 var PoolRequestsDB = mongoose.model('poolRequests', poolRequestsSchema)
42 31
32 // ----------- Videos -----------
33 var videosSchema = mongoose.Schema({
34 name: String,
35 namePath: String,
36 description: String,
37 magnetUri: String,
38 podUrl: String
39 })
40
41 var VideosDB = mongoose.model('videos', videosSchema)
42
43 // ---------------------------------------------------------------------------
44
45 module.exports = {
46 PodsDB: PodsDB,
47 PoolRequestsDB: PoolRequestsDB,
48 VideosDB: VideosDB
49 }
50
43 // ----------- Connection ----------- 51 // ----------- Connection -----------
44 52
45 mongoose.connect('mongodb://' + host + ':' + port + '/' + dbname) 53 mongoose.connect('mongodb://' + host + ':' + port + '/' + dbname)
@@ -51,11 +59,4 @@
51 mongoose.connection.on('open', function () { 59 mongoose.connection.on('open', function () {
52 logger.info('Connected to mongodb.') 60 logger.info('Connected to mongodb.')
53 }) 61 })
54
55 // ----------- Export -----------
56 module.exports = {
57 VideosDB: VideosDB,
58 PodsDB: PodsDB,
59 PoolRequestsDB: PoolRequestsDB
60 }
61})() 62})()
diff --git a/lib/poolRequests.js b/lib/poolRequests.js
index 9c7f3238b..53f47d629 100644
--- a/lib/poolRequests.js
+++ b/lib/poolRequests.js
@@ -2,29 +2,114 @@
2 'use strict' 2 'use strict'
3 3
4 var async = require('async') 4 var async = require('async')
5 var pluck = require('lodash-node/compat/collection/pluck')
5 6
6 var constants = require('../initializers/constants') 7 var constants = require('../initializers/constants')
7 var logger = require('../helpers/logger')
8 var database = require('../initializers/database') 8 var database = require('../initializers/database')
9 var pluck = require('lodash-node/compat/collection/pluck') 9 var logger = require('../helpers/logger')
10 var PoolRequestsDB = database.PoolRequestsDB
11 var PodsDB = database.PodsDB 10 var PodsDB = database.PodsDB
11 var PoolRequestsDB = database.PoolRequestsDB
12 var utils = require('../helpers/utils') 12 var utils = require('../helpers/utils')
13 var VideosDB = database.VideosDB 13 var VideosDB = database.VideosDB
14 14
15 var poolRequests = {}
16
17 // ----------- Private -----------
18 var timer = null 15 var timer = null
19 16
20 function removePoolRequestsFromDB (ids) { 17 var poolRequests = {
21 PoolRequestsDB.remove({ _id: { $in: ids } }, function (err) { 18 activate: activate,
22 if (err) { 19 addToPoolRequests: addToPoolRequests,
23 logger.error('Cannot remove requests from the pool requests database.', { error: err }) 20 deactivate: deactivate,
24 return 21 forceSend: forceSend
22 }
23
24 function deactivate () {
25 logger.info('Pool requests deactivated.')
26 clearInterval(timer)
27 }
28
29 function forceSend () {
30 logger.info('Force pool requests sending.')
31 makePoolRequests()
32 }
33
34 function activate () {
35 logger.info('Pool requests activated.')
36 timer = setInterval(makePoolRequests, constants.INTERVAL)
37 }
38
39 function addToPoolRequests (id, type, request) {
40 logger.debug('Add request to the pool requests.', { id: id, type: type, request: request })
41
42 PoolRequestsDB.findOne({ id: id }, function (err, entity) {
43 if (err) logger.error(err)
44
45 if (entity) {
46 if (entity.type === type) {
47 logger.error(new Error('Cannot insert two same requests.'))
48 return
49 }
50
51 // Remove the request of the other type
52 PoolRequestsDB.remove({ id: id }, function (err) {
53 if (err) logger.error(err)
54 })
55 } else {
56 PoolRequestsDB.create({ id: id, type: type, request: request }, function (err) {
57 if (err) logger.error(err)
58 })
25 } 59 }
60 })
61 }
26 62
27 logger.info('Pool requests flushed.') 63 // ---------------------------------------------------------------------------
64
65 module.exports = poolRequests
66
67 // ---------------------------------------------------------------------------
68
69 function makePoolRequest (type, requests, callback) {
70 if (!callback) callback = function () {}
71
72 PodsDB.find({}, { _id: 1, url: 1, publicKey: 1 }).exec(function (err, pods) {
73 if (err) throw err
74
75 var params = {
76 encrypt: true,
77 sign: true,
78 method: 'POST',
79 path: null,
80 data: requests
81 }
82
83 if (type === 'add') {
84 params.path = '/api/' + constants.API_VERSION + '/remotevideos/add'
85 } else if (type === 'remove') {
86 params.path = '/api/' + constants.API_VERSION + '/remotevideos/remove'
87 } else {
88 throw new Error('Unkown pool request type.')
89 }
90
91 var bad_pods = []
92 var good_pods = []
93
94 utils.makeMultipleRetryRequest(params, pods, callbackEachPodFinished, callbackAllPodsFinished)
95
96 function callbackEachPodFinished (err, response, body, url, pod, callback_each_pod_finished) {
97 if (err || (response.statusCode !== 200 && response.statusCode !== 204)) {
98 bad_pods.push(pod._id)
99 logger.error('Error sending secure request to %s pod.', url, { error: err || new Error('Status code not 20x') })
100 } else {
101 good_pods.push(pod._id)
102 }
103
104 return callback_each_pod_finished()
105 }
106
107 function callbackAllPodsFinished (err) {
108 if (err) return callback(err)
109
110 updatePodsScore(good_pods, bad_pods)
111 callback(null)
112 }
28 }) 113 })
29 } 114 }
30 115
@@ -81,16 +166,6 @@
81 }) 166 })
82 } 167 }
83 168
84 function updatePodsScore (good_pods, bad_pods) {
85 logger.info('Updating %d good pods and %d bad pods scores.', good_pods.length, bad_pods.length)
86
87 PodsDB.update({ _id: { $in: good_pods } }, { $inc: { score: constants.PODS_SCORE.BONUS } }, { multi: true }).exec()
88 PodsDB.update({ _id: { $in: bad_pods } }, { $inc: { score: constants.PODS_SCORE.MALUS } }, { multi: true }, function (err) {
89 if (err) throw err
90 removeBadPods()
91 })
92 }
93
94 function removeBadPods () { 169 function removeBadPods () {
95 PodsDB.find({ score: 0 }, { _id: 1, url: 1 }, function (err, pods) { 170 PodsDB.find({ score: 0 }, { _id: 1, url: 1 }, function (err, pods) {
96 if (err) throw err 171 if (err) throw err
@@ -115,92 +190,24 @@
115 }) 190 })
116 } 191 }
117 192
118 function makePoolRequest (type, requests, callback) { 193 function removePoolRequestsFromDB (ids) {
119 if (!callback) callback = function () {} 194 PoolRequestsDB.remove({ _id: { $in: ids } }, function (err) {
120 195 if (err) {
121 PodsDB.find({}, { _id: 1, url: 1, publicKey: 1 }).exec(function (err, pods) { 196 logger.error('Cannot remove requests from the pool requests database.', { error: err })
122 if (err) throw err 197 return
123
124 var params = {
125 encrypt: true,
126 sign: true,
127 method: 'POST',
128 path: null,
129 data: requests
130 }
131
132 if (type === 'add') {
133 params.path = '/api/' + constants.API_VERSION + '/remotevideos/add'
134 } else if (type === 'remove') {
135 params.path = '/api/' + constants.API_VERSION + '/remotevideos/remove'
136 } else {
137 throw new Error('Unkown pool request type.')
138 }
139
140 var bad_pods = []
141 var good_pods = []
142
143 utils.makeMultipleRetryRequest(params, pods, callbackEachPodFinished, callbackAllPodsFinished)
144
145 function callbackEachPodFinished (err, response, body, url, pod, callback_each_pod_finished) {
146 if (err || (response.statusCode !== 200 && response.statusCode !== 204)) {
147 bad_pods.push(pod._id)
148 logger.error('Error sending secure request to %s pod.', url, { error: err || new Error('Status code not 20x') })
149 } else {
150 good_pods.push(pod._id)
151 }
152
153 return callback_each_pod_finished()
154 } 198 }
155 199
156 function callbackAllPodsFinished (err) { 200 logger.info('Pool requests flushed.')
157 if (err) return callback(err)
158
159 updatePodsScore(good_pods, bad_pods)
160 callback(null)
161 }
162 }) 201 })
163 } 202 }
164 203
165 // ----------- Public ----------- 204 function updatePodsScore (good_pods, bad_pods) {
166 poolRequests.activate = function () { 205 logger.info('Updating %d good pods and %d bad pods scores.', good_pods.length, bad_pods.length)
167 logger.info('Pool requests activated.')
168 timer = setInterval(makePoolRequests, constants.INTERVAL)
169 }
170
171 poolRequests.addToPoolRequests = function (id, type, request) {
172 logger.debug('Add request to the pool requests.', { id: id, type: type, request: request })
173
174 PoolRequestsDB.findOne({ id: id }, function (err, entity) {
175 if (err) logger.error(err)
176
177 if (entity) {
178 if (entity.type === type) {
179 logger.error(new Error('Cannot insert two same requests.'))
180 return
181 }
182 206
183 // Remove the request of the other type 207 PodsDB.update({ _id: { $in: good_pods } }, { $inc: { score: constants.PODS_SCORE.BONUS } }, { multi: true }).exec()
184 PoolRequestsDB.remove({ id: id }, function (err) { 208 PodsDB.update({ _id: { $in: bad_pods } }, { $inc: { score: constants.PODS_SCORE.MALUS } }, { multi: true }, function (err) {
185 if (err) logger.error(err) 209 if (err) throw err
186 }) 210 removeBadPods()
187 } else {
188 PoolRequestsDB.create({ id: id, type: type, request: request }, function (err) {
189 if (err) logger.error(err)
190 })
191 }
192 }) 211 })
193 } 212 }
194
195 poolRequests.deactivate = function () {
196 logger.info('Pool requests deactivated.')
197 clearInterval(timer)
198 }
199
200 poolRequests.forceSend = function () {
201 logger.info('Force pool requests sending.')
202 makePoolRequests()
203 }
204
205 module.exports = poolRequests
206})() 213})()
diff --git a/lib/webTorrentNode.js b/lib/webTorrentNode.js
index 8827c68c5..69fa6b012 100644
--- a/lib/webTorrentNode.js
+++ b/lib/webTorrentNode.js
@@ -10,22 +10,21 @@
10 10
11 var host = config.get('webserver.host') 11 var host = config.get('webserver.host')
12 var port = config.get('webserver.port') 12 var port = config.get('webserver.port')
13
14 var nodeKey = 'webtorrentnode' + port 13 var nodeKey = 'webtorrentnode' + port
15 var processKey = 'webtorrent' + port 14 var processKey = 'webtorrent' + port
16
17 ipc.config.silent = true 15 ipc.config.silent = true
18 ipc.config.id = nodeKey 16 ipc.config.id = nodeKey
19 17
20 var webtorrentnode = {} 18 var webtorrentnode = {
21 19 add: add,
22 // Useful for beautiful tests 20 app: null, // Pid of the app
23 webtorrentnode.silent = false 21 create: create,
24 22 remove: remove,
25 // Useful to kill it 23 seed: seed,
26 webtorrentnode.app = null 24 silent: false // Useful for beautiful tests
25 }
27 26
28 webtorrentnode.create = function (options, callback) { 27 function create (options, callback) {
29 if (typeof options === 'function') { 28 if (typeof options === 'function') {
30 callback = options 29 callback = options
31 options = {} 30 options = {}
@@ -75,7 +74,7 @@
75 ipc.server.start() 74 ipc.server.start()
76 } 75 }
77 76
78 webtorrentnode.seed = function (path, callback) { 77 function seed (path, callback) {
79 var extension = pathUtils.extname(path) 78 var extension = pathUtils.extname(path)
80 var basename = pathUtils.basename(path, extension) 79 var basename = pathUtils.basename(path, extension)
81 var data = { 80 var data = {
@@ -104,7 +103,7 @@
104 ipc.server.broadcast(processKey + '.seed', data) 103 ipc.server.broadcast(processKey + '.seed', data)
105 } 104 }
106 105
107 webtorrentnode.add = function (magnetUri, callback) { 106 function add (magnetUri, callback) {
108 var data = { 107 var data = {
109 _id: magnetUri, 108 _id: magnetUri,
110 args: { 109 args: {
@@ -131,7 +130,7 @@
131 ipc.server.broadcast(processKey + '.add', data) 130 ipc.server.broadcast(processKey + '.add', data)
132 } 131 }
133 132
134 webtorrentnode.remove = function (magnetUri, callback) { 133 function remove (magnetUri, callback) {
135 var data = { 134 var data = {
136 _id: magnetUri, 135 _id: magnetUri,
137 args: { 136 args: {
@@ -156,5 +155,7 @@
156 ipc.server.broadcast(processKey + '.remove', data) 155 ipc.server.broadcast(processKey + '.remove', data)
157 } 156 }
158 157
158 // ---------------------------------------------------------------------------
159
159 module.exports = webtorrentnode 160 module.exports = webtorrentnode
160})() 161})()
diff --git a/lib/webtorrent.js b/lib/webtorrent.js
index b72bc500d..41e60499f 100644
--- a/lib/webtorrent.js
+++ b/lib/webtorrent.js
@@ -1,7 +1,7 @@
1;(function () { 1;(function () {
2 'use strict' 2 'use strict'
3 3
4 module.exports = function (args) { 4 function webtorrent (args) {
5 var WebTorrent = require('webtorrent') 5 var WebTorrent = require('webtorrent')
6 var ipc = require('node-ipc') 6 var ipc = require('node-ipc')
7 7
@@ -88,4 +88,8 @@
88 ipc.of[nodeKey].emit(processKey + '.exception', { exception: e }) 88 ipc.of[nodeKey].emit(processKey + '.exception', { exception: e })
89 }) 89 })
90 } 90 }
91
92 // ---------------------------------------------------------------------------
93
94 module.exports = webtorrent
91})() 95})()
diff --git a/middlewares/index.js b/middlewares/index.js
index e727202ba..311dfb6d2 100644
--- a/middlewares/index.js
+++ b/middlewares/index.js
@@ -1,10 +1,12 @@
1;(function () { 1;(function () {
2 'use strict' 2 'use strict'
3 3
4 var middleware = { 4 var middlewares = {
5 reqValidators: require('./reqValidators'), 5 misc: require('./misc'),
6 misc: require('./misc') 6 reqValidators: require('./reqValidators')
7 } 7 }
8 8
9 module.exports = middleware 9 // ---------------------------------------------------------------------------
10
11 module.exports = middlewares
10})() 12})()
diff --git a/middlewares/misc.js b/middlewares/misc.js
index f814acd9f..dbb604db3 100644
--- a/middlewares/misc.js
+++ b/middlewares/misc.js
@@ -1,16 +1,19 @@
1;(function () { 1;(function () {
2 'use strict' 2 'use strict'
3 3
4 var ursa = require('ursa')
5 var fs = require('fs') 4 var fs = require('fs')
5 var ursa = require('ursa')
6 6
7 var logger = require('../helpers/logger') 7 var logger = require('../helpers/logger')
8 var utils = require('../helpers/utils')
9 var PodsDB = require('../initializers/database').PodsDB 8 var PodsDB = require('../initializers/database').PodsDB
9 var utils = require('../helpers/utils')
10 10
11 var misc = {} 11 var miscMiddleware = {
12 cache: cache,
13 decryptBody: decryptBody
14 }
12 15
13 misc.cache = function (cache) { 16 function cache (cache) {
14 return function (req, res, next) { 17 return function (req, res, next) {
15 // If we want explicitly a cache 18 // If we want explicitly a cache
16 // Or if we don't specify if we want a cache or no and we are in production 19 // Or if we don't specify if we want a cache or no and we are in production
@@ -24,7 +27,7 @@
24 } 27 }
25 } 28 }
26 29
27 misc.decryptBody = function (req, res, next) { 30 function decryptBody (req, res, next) {
28 PodsDB.findOne({ url: req.body.signature.url }, function (err, pod) { 31 PodsDB.findOne({ url: req.body.signature.url }, function (err, pod) {
29 if (err) { 32 if (err) {
30 logger.error('Cannot get signed url in decryptBody.', { error: err }) 33 logger.error('Cannot get signed url in decryptBody.', { error: err })
@@ -42,7 +45,7 @@
42 var signature_ok = crt.hashAndVerify('sha256', new Buffer(req.body.signature.url).toString('hex'), req.body.signature.signature, 'hex') 45 var signature_ok = crt.hashAndVerify('sha256', new Buffer(req.body.signature.url).toString('hex'), req.body.signature.signature, 'hex')
43 46
44 if (signature_ok === true) { 47 if (signature_ok === true) {
45 var myKey = ursa.createPrivateKey(fs.readFileSync(utils.certDir + 'peertube.key.pem')) 48 var myKey = ursa.createPrivateKey(fs.readFileSync(utils.getCertDir() + 'peertube.key.pem'))
46 var decryptedKey = myKey.decrypt(req.body.key, 'hex', 'utf8') 49 var decryptedKey = myKey.decrypt(req.body.key, 'hex', 'utf8')
47 req.body.data = JSON.parse(utils.symetricDecrypt(req.body.data, decryptedKey)) 50 req.body.data = JSON.parse(utils.symetricDecrypt(req.body.data, decryptedKey))
48 delete req.body.key 51 delete req.body.key
@@ -55,5 +58,7 @@
55 }) 58 })
56 } 59 }
57 60
58 module.exports = misc 61 // ---------------------------------------------------------------------------
62
63 module.exports = miscMiddleware
59})() 64})()
diff --git a/middlewares/reqValidators/index.js b/middlewares/reqValidators/index.js
index 1ea611031..34d34013c 100644
--- a/middlewares/reqValidators/index.js
+++ b/middlewares/reqValidators/index.js
@@ -1,11 +1,13 @@
1;(function () { 1;(function () {
2 'use strict' 2 'use strict'
3 3
4 var reqValidator = { 4 var reqValidators = {
5 videos: require('./videos'), 5 videos: require('./videos'),
6 pods: require('./pods'), 6 pods: require('./pods'),
7 remote: require('./remote') 7 remote: require('./remote')
8 } 8 }
9 9
10 module.exports = reqValidator 10 // ---------------------------------------------------------------------------
11
12 module.exports = reqValidators
11})() 13})()
diff --git a/middlewares/reqValidators/pods.js b/middlewares/reqValidators/pods.js
index 0d023842d..6ccfd7361 100644
--- a/middlewares/reqValidators/pods.js
+++ b/middlewares/reqValidators/pods.js
@@ -4,9 +4,11 @@
4 var checkErrors = require('./utils').checkErrors 4 var checkErrors = require('./utils').checkErrors
5 var logger = require('../../helpers/logger') 5 var logger = require('../../helpers/logger')
6 6
7 var pods = {} 7 var reqValidatorsPod = {
8 podsAdd: podsAdd
9 }
8 10
9 pods.podsAdd = function (req, res, next) { 11 function podsAdd (req, res, next) {
10 req.checkBody('data.url', 'Should have an url').notEmpty().isURL({ require_protocol: true }) 12 req.checkBody('data.url', 'Should have an url').notEmpty().isURL({ require_protocol: true })
11 req.checkBody('data.publicKey', 'Should have a public key').notEmpty() 13 req.checkBody('data.publicKey', 'Should have a public key').notEmpty()
12 14
@@ -15,5 +17,7 @@
15 checkErrors(req, res, next) 17 checkErrors(req, res, next)
16 } 18 }
17 19
18 module.exports = pods 20 // ---------------------------------------------------------------------------
21
22 module.exports = reqValidatorsPod
19})() 23})()
diff --git a/middlewares/reqValidators/remote.js b/middlewares/reqValidators/remote.js
index 4b161e292..9b61481ad 100644
--- a/middlewares/reqValidators/remote.js
+++ b/middlewares/reqValidators/remote.js
@@ -4,20 +4,13 @@
4 var checkErrors = require('./utils').checkErrors 4 var checkErrors = require('./utils').checkErrors
5 var logger = require('../../helpers/logger') 5 var logger = require('../../helpers/logger')
6 6
7 var remote = {} 7 var reqValidatorsRemote = {
8 8 remoteVideosAdd: remoteVideosAdd,
9 remote.secureRequest = function (req, res, next) { 9 remoteVideosRemove: remoteVideosRemove,
10 req.checkBody('signature.url', 'Should have a signature url').isURL() 10 secureRequest: secureRequest
11 req.checkBody('signature.signature', 'Should have a signature').notEmpty()
12 req.checkBody('key', 'Should have a key').notEmpty()
13 req.checkBody('data', 'Should have data').notEmpty()
14
15 logger.debug('Checking secureRequest parameters', { parameters: { data: req.body.data, keyLength: req.body.key.length } })
16
17 checkErrors(req, res, next)
18 } 11 }
19 12
20 remote.remoteVideosAdd = function (req, res, next) { 13 function remoteVideosAdd (req, res, next) {
21 req.checkBody('data').isArray() 14 req.checkBody('data').isArray()
22 req.checkBody('data').eachIsRemoteVideosAddValid() 15 req.checkBody('data').eachIsRemoteVideosAddValid()
23 16
@@ -26,7 +19,7 @@
26 checkErrors(req, res, next) 19 checkErrors(req, res, next)
27 } 20 }
28 21
29 remote.remoteVideosRemove = function (req, res, next) { 22 function remoteVideosRemove (req, res, next) {
30 req.checkBody('data').isArray() 23 req.checkBody('data').isArray()
31 req.checkBody('data').eachIsRemoteVideosRemoveValid() 24 req.checkBody('data').eachIsRemoteVideosRemoveValid()
32 25
@@ -35,5 +28,18 @@
35 checkErrors(req, res, next) 28 checkErrors(req, res, next)
36 } 29 }
37 30
38 module.exports = remote 31 function secureRequest (req, res, next) {
32 req.checkBody('signature.url', 'Should have a signature url').isURL()
33 req.checkBody('signature.signature', 'Should have a signature').notEmpty()
34 req.checkBody('key', 'Should have a key').notEmpty()
35 req.checkBody('data', 'Should have data').notEmpty()
36
37 logger.debug('Checking secureRequest parameters', { parameters: { data: req.body.data, keyLength: req.body.key.length } })
38
39 checkErrors(req, res, next)
40 }
41
42 // ---------------------------------------------------------------------------
43
44 module.exports = reqValidatorsRemote
39})() 45})()
diff --git a/middlewares/reqValidators/utils.js b/middlewares/reqValidators/utils.js
index 5bc9f4f0b..c88f6df2e 100644
--- a/middlewares/reqValidators/utils.js
+++ b/middlewares/reqValidators/utils.js
@@ -2,11 +2,14 @@
2 'use strict' 2 'use strict'
3 3
4 var util = require('util') 4 var util = require('util')
5
5 var logger = require('../../helpers/logger') 6 var logger = require('../../helpers/logger')
6 7
7 var utils = {} 8 var reqValidatorsUtils = {
9 checkErrors: checkErrors
10 }
8 11
9 utils.checkErrors = function (req, res, next, status_code) { 12 function checkErrors (req, res, next, status_code) {
10 if (status_code === undefined) status_code = 400 13 if (status_code === undefined) status_code = 400
11 var errors = req.validationErrors() 14 var errors = req.validationErrors()
12 15
@@ -18,5 +21,7 @@
18 return next() 21 return next()
19 } 22 }
20 23
21 module.exports = utils 24 // ---------------------------------------------------------------------------
25
26 module.exports = reqValidatorsUtils
22})() 27})()
diff --git a/middlewares/reqValidators/videos.js b/middlewares/reqValidators/videos.js
index a34445f7a..3479c47c3 100644
--- a/middlewares/reqValidators/videos.js
+++ b/middlewares/reqValidators/videos.js
@@ -2,28 +2,17 @@
2 'use strict' 2 'use strict'
3 3
4 var checkErrors = require('./utils').checkErrors 4 var checkErrors = require('./utils').checkErrors
5 var VideosDB = require('../../initializers/database').VideosDB
6 var logger = require('../../helpers/logger') 5 var logger = require('../../helpers/logger')
6 var VideosDB = require('../../initializers/database').VideosDB
7 7
8 var videos = {} 8 var reqValidatorsVideos = {
9 9 videosAdd: videosAdd,
10 function findVideoById (id, callback) { 10 videosGet: videosGet,
11 VideosDB.findById(id, { _id: 1, namePath: 1 }).limit(1).exec(function (err, video) { 11 videosRemove: videosRemove,
12 if (err) throw err 12 videosSearch: videosSearch
13
14 callback(video)
15 })
16 }
17
18 videos.videosSearch = function (req, res, next) {
19 req.checkParams('name', 'Should have a name').notEmpty()
20
21 logger.debug('Checking videosSearch parameters', { parameters: req.params })
22
23 checkErrors(req, res, next)
24 } 13 }
25 14
26 videos.videosAdd = function (req, res, next) { 15 function videosAdd (req, res, next) {
27 req.checkFiles('input_video[0].originalname', 'Should have an input video').notEmpty() 16 req.checkFiles('input_video[0].originalname', 'Should have an input video').notEmpty()
28 req.checkFiles('input_video[0].mimetype', 'Should have a correct mime type').matches(/video\/(webm)|(mp4)|(ogg)/i) 17 req.checkFiles('input_video[0].mimetype', 'Should have a correct mime type').matches(/video\/(webm)|(mp4)|(ogg)/i)
29 req.checkBody('name', 'Should have a name').isLength(1, 50) 18 req.checkBody('name', 'Should have a name').isLength(1, 50)
@@ -34,7 +23,7 @@
34 checkErrors(req, res, next) 23 checkErrors(req, res, next)
35 } 24 }
36 25
37 videos.videosGet = function (req, res, next) { 26 function videosGet (req, res, next) {
38 req.checkParams('id', 'Should have a valid id').notEmpty().isMongoId() 27 req.checkParams('id', 'Should have a valid id').notEmpty().isMongoId()
39 28
40 logger.debug('Checking videosGet parameters', { parameters: req.params }) 29 logger.debug('Checking videosGet parameters', { parameters: req.params })
@@ -48,7 +37,7 @@
48 }) 37 })
49 } 38 }
50 39
51 videos.videosRemove = function (req, res, next) { 40 function videosRemove (req, res, next) {
52 req.checkParams('id', 'Should have a valid id').notEmpty().isMongoId() 41 req.checkParams('id', 'Should have a valid id').notEmpty().isMongoId()
53 42
54 logger.debug('Checking videosRemove parameters', { parameters: req.params }) 43 logger.debug('Checking videosRemove parameters', { parameters: req.params })
@@ -63,5 +52,25 @@
63 }) 52 })
64 } 53 }
65 54
66 module.exports = videos 55 function videosSearch (req, res, next) {
56 req.checkParams('name', 'Should have a name').notEmpty()
57
58 logger.debug('Checking videosSearch parameters', { parameters: req.params })
59
60 checkErrors(req, res, next)
61 }
62
63 // ---------------------------------------------------------------------------
64
65 module.exports = reqValidatorsVideos
66
67 // ---------------------------------------------------------------------------
68
69 function findVideoById (id, callback) {
70 VideosDB.findById(id, { _id: 1, namePath: 1 }).limit(1).exec(function (err, video) {
71 if (err) throw err
72
73 callback(video)
74 })
75 }
67})() 76})()
diff --git a/models/pods.js b/models/pods.js
index c8d08b26f..ed2f0d8ee 100644
--- a/models/pods.js
+++ b/models/pods.js
@@ -12,39 +12,23 @@
12 var poolRequests = require('../lib/poolRequests') 12 var poolRequests = require('../lib/poolRequests')
13 var utils = require('../helpers/utils') 13 var utils = require('../helpers/utils')
14 14
15 var pods = {}
16
17 var http = config.get('webserver.https') ? 'https' : 'http' 15 var http = config.get('webserver.https') ? 'https' : 'http'
18 var host = config.get('webserver.host') 16 var host = config.get('webserver.host')
19 var port = config.get('webserver.port') 17 var port = config.get('webserver.port')
20 18
21 // ----------- Private functions ----------- 19 var pods = {
22 20 add: add,
23 function getForeignPodsList (url, callback) { 21 addVideoToFriends: addVideoToFriends,
24 var path = '/api/' + constants.API_VERSION + '/pods' 22 list: list,
25 23 hasFriends: hasFriends,
26 request.get(url + path, function (err, response, body) { 24 makeFriends: makeFriends,
27 if (err) throw err 25 quitFriends: quitFriends,
28 callback(JSON.parse(body)) 26 remove: remove,
29 }) 27 removeVideoToFriends
30 } 28 }
31 29
32 // ----------- Public functions -----------
33
34 pods.list = function (callback) {
35 PodsDB.find(function (err, pods_list) {
36 if (err) {
37 logger.error('Cannot get the list of the pods.', { error: err })
38 return callback(err)
39 }
40
41 return callback(null, pods_list)
42 })
43 }
44
45 // { url }
46 // TODO: check if the pod is not already a friend 30 // TODO: check if the pod is not already a friend
47 pods.add = function (data, callback) { 31 function add (data, callback) {
48 var videos = require('./videos') 32 var videos = require('./videos')
49 logger.info('Adding pod: %s', data.url) 33 logger.info('Adding pod: %s', data.url)
50 34
@@ -62,7 +46,7 @@
62 46
63 videos.addRemotes(data.videos) 47 videos.addRemotes(data.videos)
64 48
65 fs.readFile(utils.certDir + 'peertube.pub', 'utf8', function (err, cert) { 49 fs.readFile(utils.getCertDir() + 'peertube.pub', 'utf8', function (err, cert) {
66 if (err) { 50 if (err) {
67 logger.error('Cannot read cert file.', { error: err }) 51 logger.error('Cannot read cert file.', { error: err })
68 return callback(err) 52 return callback(err)
@@ -80,40 +64,38 @@
80 }) 64 })
81 } 65 }
82 66
83 pods.remove = function (url, callback) { 67 function addVideoToFriends (video) {
84 var videos = require('./videos') 68 // To avoid duplicates
85 logger.info('Removing %s pod.', url) 69 var id = video.name + video.magnetUri
86 70 poolRequests.addToPoolRequests(id, 'add', video)
87 videos.removeAllRemotesOf(url, function (err) { 71 }
88 if (err) logger.error('Cannot remove all remote videos of %s.', url)
89 72
90 PodsDB.remove({ url: url }, function (err) { 73 function list (callback) {
91 if (err) return callback(err) 74 PodsDB.find(function (err, pods_list) {
75 if (err) {
76 logger.error('Cannot get the list of the pods.', { error: err })
77 return callback(err)
78 }
92 79
93 logger.info('%s pod removed.', url) 80 return callback(null, pods_list)
94 callback(null)
95 })
96 }) 81 })
97 } 82 }
98 83
99 pods.addVideoToFriends = function (video) { 84 function hasFriends (callback) {
100 // To avoid duplicates 85 PodsDB.count(function (err, count) {
101 var id = video.name + video.magnetUri 86 if (err) return callback(err)
102 poolRequests.addToPoolRequests(id, 'add', video)
103 }
104 87
105 pods.removeVideoToFriends = function (video) { 88 var has_friends = (count !== 0)
106 // To avoid duplicates 89 callback(null, has_friends)
107 var id = video.name + video.magnetUri 90 })
108 poolRequests.addToPoolRequests(id, 'remove', video)
109 } 91 }
110 92
111 pods.makeFriends = function (callback) { 93 function makeFriends (callback) {
112 var videos = require('./videos') 94 var videos = require('./videos')
113 var pods_score = {} 95 var pods_score = {}
114 96
115 logger.info('Make friends!') 97 logger.info('Make friends!')
116 fs.readFile(utils.certDir + 'peertube.pub', 'utf8', function (err, cert) { 98 fs.readFile(utils.getCertDir() + 'peertube.pub', 'utf8', function (err, cert) {
117 if (err) { 99 if (err) {
118 logger.error('Cannot read public cert.', { error: err }) 100 logger.error('Cannot read public cert.', { error: err })
119 return callback(err) 101 return callback(err)
@@ -188,7 +170,7 @@
188 function eachRequest (err, response, body, url, pod, callback_each_request) { 170 function eachRequest (err, response, body, url, pod, callback_each_request) {
189 // We add the pod if it responded correctly with its public certificate 171 // We add the pod if it responded correctly with its public certificate
190 if (!err && response.statusCode === 200) { 172 if (!err && response.statusCode === 200) {
191 pods.add({ url: pod.url, publicKey: body.cert, score: constants.FRIEND_BASE_SCORE }, function (err) { 173 add({ url: pod.url, publicKey: body.cert, score: constants.FRIEND_BASE_SCORE }, function (err) {
192 if (err) logger.error('Error with adding %s pod.', pod.url, { error: err }) 174 if (err) logger.error('Error with adding %s pod.', pod.url, { error: err })
193 175
194 videos.addRemotes(body.videos, function (err) { 176 videos.addRemotes(body.videos, function (err) {
@@ -221,7 +203,7 @@
221 } 203 }
222 } 204 }
223 205
224 pods.quitFriends = function (callback) { 206 function quitFriends (callback) {
225 // Stop pool requests 207 // Stop pool requests
226 poolRequests.deactivate() 208 poolRequests.deactivate()
227 // Flush pool requests 209 // Flush pool requests
@@ -261,14 +243,40 @@
261 }) 243 })
262 } 244 }
263 245
264 pods.hasFriends = function (callback) { 246 function remove (url, callback) {
265 PodsDB.count(function (err, count) { 247 var videos = require('./videos')
266 if (err) return callback(err) 248 logger.info('Removing %s pod.', url)
267 249
268 var has_friends = (count !== 0) 250 videos.removeAllRemotesOf(url, function (err) {
269 callback(null, has_friends) 251 if (err) logger.error('Cannot remove all remote videos of %s.', url)
252
253 PodsDB.remove({ url: url }, function (err) {
254 if (err) return callback(err)
255
256 logger.info('%s pod removed.', url)
257 callback(null)
258 })
270 }) 259 })
271 } 260 }
272 261
262 function removeVideoToFriends (video) {
263 // To avoid duplicates
264 var id = video.name + video.magnetUri
265 poolRequests.addToPoolRequests(id, 'remove', video)
266 }
267
268 // ---------------------------------------------------------------------------
269
273 module.exports = pods 270 module.exports = pods
271
272 // ---------------------------------------------------------------------------
273
274 function getForeignPodsList (url, callback) {
275 var path = '/api/' + constants.API_VERSION + '/pods'
276
277 request.get(url + path, function (err, response, body) {
278 if (err) throw err
279 callback(JSON.parse(body))
280 })
281 }
274})() 282})()
diff --git a/models/videos.js b/models/videos.js
index 626c55819..5711c5657 100644
--- a/models/videos.js
+++ b/models/videos.js
@@ -11,51 +11,29 @@
11 var pods = require('./pods') 11 var pods = require('./pods')
12 var VideosDB = require('../initializers/database').VideosDB 12 var VideosDB = require('../initializers/database').VideosDB
13 13
14 var videos = {}
15
16 var http = config.get('webserver.https') === true ? 'https' : 'http' 14 var http = config.get('webserver.https') === true ? 'https' : 'http'
17 var host = config.get('webserver.host') 15 var host = config.get('webserver.host')
18 var port = config.get('webserver.port') 16 var port = config.get('webserver.port')
19 17
20 // ----------- Private functions ----------- 18 var videos = {
21 function seedVideo (path, callback) { 19 add: add,
22 logger.info('Seeding %s...', path) 20 addRemotes: addRemotes,
23 21 get: get,
24 webtorrent.seed(path, function (torrent) { 22 list: list,
25 logger.info('%s seeded (%s).', path, torrent.magnetURI) 23 listOwned: listOwned,
26 24 remove: remove,
27 return callback(null, torrent) 25 removeAllRemotes: removeAllRemotes,
28 }) 26 removeAllRemotesOf: removeAllRemotesOf,
27 removeRemotes: removeRemotes,
28 search: search,
29 seedAll: seedAll,
30 uploadDir: uploadDir
29 } 31 }
30 32
31 // ----------- Public attributes ---------- 33 // ----------- Public attributes ----------
32 videos.uploadDir = __dirname + '/../' + config.get('storage.uploads') 34 var uploadDir = __dirname + '/../' + config.get('storage.uploads')
33
34 // ----------- Public functions -----------
35 videos.list = function (callback) {
36 VideosDB.find(function (err, videos_list) {
37 if (err) {
38 logger.error('Cannot get list of the videos.', { error: err })
39 return callback(err)
40 }
41
42 return callback(null, videos_list)
43 })
44 }
45
46 videos.listOwned = function (callback) {
47 // If namePath is not null this is *our* video
48 VideosDB.find({ namePath: { $ne: null } }, function (err, videos_list) {
49 if (err) {
50 logger.error('Cannot get list of the videos.', { error: err })
51 return callback(err)
52 }
53 35
54 return callback(null, videos_list) 36 function add (data, callback) {
55 })
56 }
57
58 videos.add = function (data, callback) {
59 var video_file = data.video 37 var video_file = data.video
60 var video_data = data.data 38 var video_data = data.data
61 39
@@ -89,7 +67,74 @@
89 }) 67 })
90 } 68 }
91 69
92 videos.remove = function (id, callback) { 70 // TODO: avoid doublons
71 function addRemotes (videos, callback) {
72 if (callback === undefined) callback = function () {}
73
74 var to_add = []
75
76 async.each(videos, function (video, callback_each) {
77 callback_each = dz(callback_each)
78 logger.debug('Add remote video from pod: %s', video.podUrl)
79
80 var params = {
81 name: video.name,
82 namePath: null,
83 description: video.description,
84 magnetUri: video.magnetUri,
85 podUrl: video.podUrl
86 }
87
88 to_add.push(params)
89
90 callback_each()
91 }, function () {
92 VideosDB.create(to_add, function (err, videos) {
93 if (err) {
94 logger.error('Cannot insert this remote video.', { error: err })
95 return callback(err)
96 }
97
98 return callback(null, videos)
99 })
100 })
101 }
102
103 function get (id, callback) {
104 VideosDB.findById(id, function (err, video) {
105 if (err) {
106 logger.error('Cannot get this video.', { error: err })
107 return callback(err)
108 }
109
110 return callback(null, video)
111 })
112 }
113
114 function list (callback) {
115 VideosDB.find(function (err, videos_list) {
116 if (err) {
117 logger.error('Cannot get list of the videos.', { error: err })
118 return callback(err)
119 }
120
121 return callback(null, videos_list)
122 })
123 }
124
125 function listOwned (callback) {
126 // If namePath is not null this is *our* video
127 VideosDB.find({ namePath: { $ne: null } }, function (err, videos_list) {
128 if (err) {
129 logger.error('Cannot get list of the videos.', { error: err })
130 return callback(err)
131 }
132
133 return callback(null, videos_list)
134 })
135 }
136
137 function remove (id, callback) {
93 // Maybe the torrent is not seeded, but we catch the error to don't stop the removing process 138 // Maybe the torrent is not seeded, but we catch the error to don't stop the removing process
94 function removeTorrent (magnetUri, callback) { 139 function removeTorrent (magnetUri, callback) {
95 try { 140 try {
@@ -122,7 +167,7 @@
122 return callback(err) 167 return callback(err)
123 } 168 }
124 169
125 fs.unlink(videos.uploadDir + video.namePath, function (err) { 170 fs.unlink(uploadDir + video.namePath, function (err) {
126 if (err) { 171 if (err) {
127 logger.error('Cannot remove this video file.', { error: err }) 172 logger.error('Cannot remove this video file.', { error: err })
128 return callback(err) 173 return callback(err)
@@ -141,8 +186,24 @@
141 }) 186 })
142 } 187 }
143 188
189 function removeAllRemotes (callback) {
190 VideosDB.remove({ namePath: null }, function (err) {
191 if (err) return callback(err)
192
193 callback(null)
194 })
195 }
196
197 function removeAllRemotesOf (fromUrl, callback) {
198 VideosDB.remove({ podUrl: fromUrl }, function (err) {
199 if (err) return callback(err)
200
201 callback(null)
202 })
203 }
204
144 // Use the magnet Uri because the _id field is not the same on different servers 205 // Use the magnet Uri because the _id field is not the same on different servers
145 videos.removeRemotes = function (fromUrl, magnetUris, callback) { 206 function removeRemotes (fromUrl, magnetUris, callback) {
146 if (callback === undefined) callback = function () {} 207 if (callback === undefined) callback = function () {}
147 208
148 VideosDB.find({ magnetUri: { $in: magnetUris } }, function (err, videos) { 209 VideosDB.find({ magnetUri: { $in: magnetUris } }, function (err, videos) {
@@ -176,68 +237,7 @@
176 }) 237 })
177 } 238 }
178 239
179 videos.removeAllRemotes = function (callback) { 240 function search (name, callback) {
180 VideosDB.remove({ namePath: null }, function (err) {
181 if (err) return callback(err)
182
183 callback(null)
184 })
185 }
186
187 videos.removeAllRemotesOf = function (fromUrl, callback) {
188 VideosDB.remove({ podUrl: fromUrl }, function (err) {
189 if (err) return callback(err)
190
191 callback(null)
192 })
193 }
194
195 // { name, magnetUri, podUrl }
196 // TODO: avoid doublons
197 videos.addRemotes = function (videos, callback) {
198 if (callback === undefined) callback = function () {}
199
200 var to_add = []
201
202 async.each(videos, function (video, callback_each) {
203 callback_each = dz(callback_each)
204 logger.debug('Add remote video from pod: %s', video.podUrl)
205
206 var params = {
207 name: video.name,
208 namePath: null,
209 description: video.description,
210 magnetUri: video.magnetUri,
211 podUrl: video.podUrl
212 }
213
214 to_add.push(params)
215
216 callback_each()
217 }, function () {
218 VideosDB.create(to_add, function (err, videos) {
219 if (err) {
220 logger.error('Cannot insert this remote video.', { error: err })
221 return callback(err)
222 }
223
224 return callback(null, videos)
225 })
226 })
227 }
228
229 videos.get = function (id, callback) {
230 VideosDB.findById(id, function (err, video) {
231 if (err) {
232 logger.error('Cannot get this video.', { error: err })
233 return callback(err)
234 }
235
236 return callback(null, video)
237 })
238 }
239
240 videos.search = function (name, callback) {
241 VideosDB.find({ name: new RegExp(name) }, function (err, videos) { 241 VideosDB.find({ name: new RegExp(name) }, function (err, videos) {
242 if (err) { 242 if (err) {
243 logger.error('Cannot search the videos.', { error: err }) 243 logger.error('Cannot search the videos.', { error: err })
@@ -248,7 +248,7 @@
248 }) 248 })
249 } 249 }
250 250
251 videos.seedAll = function (callback) { 251 function seedAll (callback) {
252 VideosDB.find({ namePath: { $ne: null } }, function (err, videos_list) { 252 VideosDB.find({ namePath: { $ne: null } }, function (err, videos_list) {
253 if (err) { 253 if (err) {
254 logger.error('Cannot get list of the videos to seed.', { error: err }) 254 logger.error('Cannot get list of the videos to seed.', { error: err })
@@ -256,7 +256,7 @@
256 } 256 }
257 257
258 async.each(videos_list, function (video, each_callback) { 258 async.each(videos_list, function (video, each_callback) {
259 seedVideo(videos.uploadDir + video.namePath, function (err) { 259 seedVideo(uploadDir + video.namePath, function (err) {
260 if (err) { 260 if (err) {
261 logger.error('Cannot seed this video.', { error: err }) 261 logger.error('Cannot seed this video.', { error: err })
262 return callback(err) 262 return callback(err)
@@ -268,5 +268,19 @@
268 }) 268 })
269 } 269 }
270 270
271 // ---------------------------------------------------------------------------
272
271 module.exports = videos 273 module.exports = videos
274
275 // ---------------------------------------------------------------------------
276
277 function seedVideo (path, callback) {
278 logger.info('Seeding %s...', path)
279
280 webtorrent.seed(path, function (torrent) {
281 logger.info('%s seeded (%s).', path, torrent.magnetURI)
282
283 return callback(null, torrent)
284 })
285 }
272})() 286})()
diff --git a/tests/api/singlePod.js b/tests/api/singlePod.js
index ce3ca80f2..7621d766c 100644
--- a/tests/api/singlePod.js
+++ b/tests/api/singlePod.js
@@ -3,8 +3,8 @@
3 3
4 var async = require('async') 4 var async = require('async')
5 var chai = require('chai') 5 var chai = require('chai')
6 var fs = require('fs')
7 var expect = chai.expect 6 var expect = chai.expect
7 var fs = require('fs')
8 8
9 var webtorrent = require(__dirname + '/../../lib/webTorrentNode') 9 var webtorrent = require(__dirname + '/../../lib/webTorrentNode')
10 webtorrent.silent = true 10 webtorrent.silent = true
diff --git a/tests/api/utils.js b/tests/api/utils.js
index afb0abb33..a1996b4d7 100644
--- a/tests/api/utils.js
+++ b/tests/api/utils.js
@@ -6,7 +6,7 @@
6 var fork = child_process.fork 6 var fork = child_process.fork
7 var request = require('supertest') 7 var request = require('supertest')
8 8
9 module.exports = { 9 var testUtils = {
10 flushTests: flushTests, 10 flushTests: flushTests,
11 getFriendsList: getFriendsList, 11 getFriendsList: getFriendsList,
12 getVideosList: getVideosList, 12 getVideosList: getVideosList,
@@ -179,4 +179,8 @@
179 .expect(201) 179 .expect(201)
180 .end(end) 180 .end(end)
181 } 181 }
182
183 // ---------------------------------------------------------------------------
184
185 module.exports = testUtils
182})() 186})()