aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--package.json2
-rw-r--r--server/controllers/api/clients.ts4
-rw-r--r--server/controllers/api/config.ts2
-rw-r--r--server/controllers/api/index.ts2
-rw-r--r--server/controllers/api/pods.ts17
-rw-r--r--server/controllers/api/remote/pods.ts2
-rw-r--r--server/controllers/api/remote/videos.ts40
-rw-r--r--server/controllers/api/requests.ts5
-rw-r--r--server/controllers/api/users.ts22
-rw-r--r--server/controllers/api/videos/abuse.ts9
-rw-r--r--server/controllers/api/videos/blacklist.ts2
-rw-r--r--server/controllers/api/videos/index.ts29
-rw-r--r--server/controllers/api/videos/rate.ts7
-rw-r--r--server/controllers/client.ts13
-rw-r--r--server/helpers/custom-validators/misc.ts13
-rw-r--r--server/helpers/custom-validators/pods.ts17
-rw-r--r--server/helpers/custom-validators/remote/index.ts2
-rw-r--r--server/helpers/custom-validators/remote/videos.ts32
-rw-r--r--server/helpers/custom-validators/users.ts24
-rw-r--r--server/helpers/custom-validators/videos.ts110
-rw-r--r--server/helpers/database-utils.ts13
-rw-r--r--server/helpers/peertube-crypto.ts26
-rw-r--r--server/helpers/requests.ts19
-rw-r--r--server/helpers/utils.ts16
-rw-r--r--server/initializers/checker.ts8
-rw-r--r--server/initializers/constants.ts2
-rw-r--r--server/initializers/database.ts4
-rw-r--r--server/initializers/installer.ts8
-rw-r--r--server/initializers/migrator.ts9
-rw-r--r--server/lib/friends.ts94
-rw-r--r--server/lib/jobs/handlers/index.ts10
-rw-r--r--server/lib/jobs/handlers/video-transcoder.ts7
-rw-r--r--server/lib/jobs/job-scheduler.ts24
-rw-r--r--server/lib/oauth-model.ts15
-rw-r--r--server/lib/request/base-request-scheduler.ts16
-rw-r--r--server/lib/request/index.ts1
-rw-r--r--server/lib/request/request-scheduler.ts23
-rw-r--r--server/lib/request/request-video-event-scheduler.ts21
-rw-r--r--server/lib/request/request-video-qadu-scheduler.ts21
-rw-r--r--server/middlewares/admin.ts5
-rw-r--r--server/middlewares/index.ts16
-rw-r--r--server/middlewares/oauth.ts6
-rw-r--r--server/middlewares/pagination.ts5
-rw-r--r--server/middlewares/pods.ts9
-rw-r--r--server/middlewares/search.ts5
-rw-r--r--server/middlewares/secure.ts5
-rw-r--r--server/middlewares/sort.ts9
-rw-r--r--server/middlewares/validators/pagination.ts5
-rw-r--r--server/middlewares/validators/pods.ts7
-rw-r--r--server/middlewares/validators/remote/signature.ts5
-rw-r--r--server/middlewares/validators/remote/videos.ts9
-rw-r--r--server/middlewares/validators/sort.ts13
-rw-r--r--server/middlewares/validators/users.ts11
-rw-r--r--server/middlewares/validators/utils.ts5
-rw-r--r--server/middlewares/validators/videos.ts28
-rw-r--r--server/models/application-interface.ts7
-rw-r--r--server/models/application.ts13
-rw-r--r--server/models/author-interface.ts8
-rw-r--r--server/models/author.ts15
-rw-r--r--server/models/job-interface.ts3
-rw-r--r--server/models/job.ts2
-rw-r--r--server/models/oauth-client-interface.ts8
-rw-r--r--server/models/oauth-client.ts6
-rw-r--r--server/models/oauth-token-interface.ts20
-rw-r--r--server/models/oauth-token.ts13
-rw-r--r--server/models/pod-interface.ts41
-rw-r--r--server/models/pod.ts34
-rw-r--r--server/models/request-interface.ts27
-rw-r--r--server/models/request-to-pod-interface.ts5
-rw-r--r--server/models/request-to-pod.ts2
-rw-r--r--server/models/request-video-event-interface.ts32
-rw-r--r--server/models/request-video-event.ts19
-rw-r--r--server/models/request-video-qadu-interface.ts31
-rw-r--r--server/models/request-video-qadu.ts17
-rw-r--r--server/models/request.ts22
-rw-r--r--server/models/tag-interface.ts3
-rw-r--r--server/models/tag.ts9
-rw-r--r--server/models/user-interface.ts36
-rw-r--r--server/models/user-video-rate-interface.ts3
-rw-r--r--server/models/user-video-rate.ts2
-rw-r--r--server/models/user.ts18
-rw-r--r--server/models/utils.ts6
-rw-r--r--server/models/video-abuse-interface.ts10
-rw-r--r--server/models/video-blacklist-interface.ts24
-rw-r--r--server/models/video-blacklist.ts10
-rw-r--r--server/models/video-interface.ts118
-rw-r--r--server/models/video-tag-interface.ts2
-rw-r--r--server/models/video.ts79
-rw-r--r--shared/index.ts1
-rw-r--r--shared/models/index.ts5
-rw-r--r--shared/models/pod.model.ts7
-rw-r--r--shared/models/user.model.ts8
-rw-r--r--shared/models/video-abuse.model.ts8
-rw-r--r--shared/models/video-blacklist.model.ts5
-rw-r--r--shared/models/video.model.ts3
-rw-r--r--yarn.lock12
96 files changed, 987 insertions, 541 deletions
diff --git a/package.json b/package.json
index e7d0c39a4..71cd789ba 100644
--- a/package.json
+++ b/package.json
@@ -82,8 +82,10 @@
82 "@types/config": "^0.0.32", 82 "@types/config": "^0.0.32",
83 "@types/express": "^4.0.35", 83 "@types/express": "^4.0.35",
84 "@types/lodash": "^4.14.64", 84 "@types/lodash": "^4.14.64",
85 "@types/magnet-uri": "^5.1.1",
85 "@types/mkdirp": "^0.3.29", 86 "@types/mkdirp": "^0.3.29",
86 "@types/morgan": "^1.7.32", 87 "@types/morgan": "^1.7.32",
88 "@types/multer": "^0.0.34",
87 "@types/node": "^7.0.18", 89 "@types/node": "^7.0.18",
88 "@types/request": "^0.0.43", 90 "@types/request": "^0.0.43",
89 "@types/sequelize": "^4.0.55", 91 "@types/sequelize": "^4.0.55",
diff --git a/server/controllers/api/clients.ts b/server/controllers/api/clients.ts
index f6499556a..8c460096b 100644
--- a/server/controllers/api/clients.ts
+++ b/server/controllers/api/clients.ts
@@ -1,6 +1,6 @@
1import * as express from 'express' 1import * as express from 'express'
2 2
3import { CONFIG } from '../../initializers'; 3import { CONFIG } from '../../initializers'
4import { logger } from '../../helpers' 4import { logger } from '../../helpers'
5import { database as db } from '../../initializers/database' 5import { database as db } from '../../initializers/database'
6 6
@@ -9,7 +9,7 @@ const clientsRouter = express.Router()
9clientsRouter.get('/local', getLocalClient) 9clientsRouter.get('/local', getLocalClient)
10 10
11// Get the client credentials for the PeerTube front end 11// Get the client credentials for the PeerTube front end
12function getLocalClient (req, res, next) { 12function getLocalClient (req: express.Request, res: express.Response, next: express.NextFunction) {
13 const serverHostname = CONFIG.WEBSERVER.HOSTNAME 13 const serverHostname = CONFIG.WEBSERVER.HOSTNAME
14 const serverPort = CONFIG.WEBSERVER.PORT 14 const serverPort = CONFIG.WEBSERVER.PORT
15 let headerHostShouldBe = serverHostname 15 let headerHostShouldBe = serverHostname
diff --git a/server/controllers/api/config.ts b/server/controllers/api/config.ts
index 57c9398ec..c63981797 100644
--- a/server/controllers/api/config.ts
+++ b/server/controllers/api/config.ts
@@ -7,7 +7,7 @@ const configRouter = express.Router()
7configRouter.get('/', getConfig) 7configRouter.get('/', getConfig)
8 8
9// Get the client credentials for the PeerTube front end 9// Get the client credentials for the PeerTube front end
10function getConfig (req, res, next) { 10function getConfig (req: express.Request, res: express.Response, next: express.NextFunction) {
11 res.json({ 11 res.json({
12 signup: { 12 signup: {
13 enabled: CONFIG.SIGNUP.ENABLED 13 enabled: CONFIG.SIGNUP.ENABLED
diff --git a/server/controllers/api/index.ts b/server/controllers/api/index.ts
index 98004544d..ac3972ac6 100644
--- a/server/controllers/api/index.ts
+++ b/server/controllers/api/index.ts
@@ -28,6 +28,6 @@ export { apiRouter }
28 28
29// --------------------------------------------------------------------------- 29// ---------------------------------------------------------------------------
30 30
31function pong (req, res, next) { 31function pong (req: express.Request, res: express.Response, next: express.NextFunction) {
32 return res.send('pong').status(200).end() 32 return res.send('pong').status(200).end()
33} 33}
diff --git a/server/controllers/api/pods.ts b/server/controllers/api/pods.ts
index a028c4ab9..283105f6c 100644
--- a/server/controllers/api/pods.ts
+++ b/server/controllers/api/pods.ts
@@ -21,6 +21,9 @@ import {
21 setBodyHostPort, 21 setBodyHostPort,
22 setBodyHostsPort 22 setBodyHostsPort
23} from '../../middlewares' 23} from '../../middlewares'
24import {
25 PodInstance
26} from '../../models'
24 27
25const podsRouter = express.Router() 28const podsRouter = express.Router()
26 29
@@ -51,10 +54,10 @@ export {
51 54
52// --------------------------------------------------------------------------- 55// ---------------------------------------------------------------------------
53 56
54function addPods (req, res, next) { 57function addPods (req: express.Request, res: express.Response, next: express.NextFunction) {
55 const informations = req.body 58 const informations = req.body
56 59
57 waterfall([ 60 waterfall<string, Error>([
58 function addPod (callback) { 61 function addPod (callback) {
59 const pod = db.Pod.build(informations) 62 const pod = db.Pod.build(informations)
60 pod.save().asCallback(function (err, podCreated) { 63 pod.save().asCallback(function (err, podCreated) {
@@ -63,7 +66,7 @@ function addPods (req, res, next) {
63 }) 66 })
64 }, 67 },
65 68
66 function sendMyVideos (podCreated, callback) { 69 function sendMyVideos (podCreated: PodInstance, callback) {
67 sendOwnedVideosToPod(podCreated.id) 70 sendOwnedVideosToPod(podCreated.id)
68 71
69 callback(null) 72 callback(null)
@@ -86,7 +89,7 @@ function addPods (req, res, next) {
86 }) 89 })
87} 90}
88 91
89function listPods (req, res, next) { 92function listPods (req: express.Request, res: express.Response, next: express.NextFunction) {
90 db.Pod.list(function (err, podsList) { 93 db.Pod.list(function (err, podsList) {
91 if (err) return next(err) 94 if (err) return next(err)
92 95
@@ -94,8 +97,8 @@ function listPods (req, res, next) {
94 }) 97 })
95} 98}
96 99
97function makeFriendsController (req, res, next) { 100function makeFriendsController (req: express.Request, res: express.Response, next: express.NextFunction) {
98 const hosts = req.body.hosts 101 const hosts = req.body.hosts as string[]
99 102
100 makeFriends(hosts, function (err) { 103 makeFriends(hosts, function (err) {
101 if (err) { 104 if (err) {
@@ -109,7 +112,7 @@ function makeFriendsController (req, res, next) {
109 res.type('json').status(204).end() 112 res.type('json').status(204).end()
110} 113}
111 114
112function quitFriendsController (req, res, next) { 115function quitFriendsController (req: express.Request, res: express.Response, next: express.NextFunction) {
113 quitFriends(function (err) { 116 quitFriends(function (err) {
114 if (err) return next(err) 117 if (err) return next(err)
115 118
diff --git a/server/controllers/api/remote/pods.ts b/server/controllers/api/remote/pods.ts
index 9c9d2164d..b0d6642c1 100644
--- a/server/controllers/api/remote/pods.ts
+++ b/server/controllers/api/remote/pods.ts
@@ -21,7 +21,7 @@ export {
21 21
22// --------------------------------------------------------------------------- 22// ---------------------------------------------------------------------------
23 23
24function removePods (req, res, next) { 24function removePods (req: express.Request, res: express.Response, next: express.NextFunction) {
25 const host = req.body.signature.host 25 const host = req.body.signature.host
26 26
27 waterfall([ 27 waterfall([
diff --git a/server/controllers/api/remote/videos.ts b/server/controllers/api/remote/videos.ts
index d97a3db31..d9cc08fb4 100644
--- a/server/controllers/api/remote/videos.ts
+++ b/server/controllers/api/remote/videos.ts
@@ -1,4 +1,5 @@
1import * as express from 'express' 1import * as express from 'express'
2import * as Sequelize from 'sequelize'
2import { eachSeries, waterfall } from 'async' 3import { eachSeries, waterfall } from 'async'
3 4
4import { database as db } from '../../../initializers/database' 5import { database as db } from '../../../initializers/database'
@@ -23,6 +24,7 @@ import {
23 startSerializableTransaction 24 startSerializableTransaction
24} from '../../../helpers' 25} from '../../../helpers'
25import { quickAndDirtyUpdatesVideoToFriends } from '../../../lib' 26import { quickAndDirtyUpdatesVideoToFriends } from '../../../lib'
27import { PodInstance, VideoInstance } from '../../../models'
26 28
27const ENDPOINT_ACTIONS = REQUEST_ENDPOINT_ACTIONS[REQUEST_ENDPOINTS.VIDEOS] 29const ENDPOINT_ACTIONS = REQUEST_ENDPOINT_ACTIONS[REQUEST_ENDPOINTS.VIDEOS]
28 30
@@ -64,7 +66,7 @@ export {
64 66
65// --------------------------------------------------------------------------- 67// ---------------------------------------------------------------------------
66 68
67function remoteVideos (req, res, next) { 69function remoteVideos (req: express.Request, res: express.Response, next: express.NextFunction) {
68 const requests = req.body.data 70 const requests = req.body.data
69 const fromPod = res.locals.secure.pod 71 const fromPod = res.locals.secure.pod
70 72
@@ -89,7 +91,7 @@ function remoteVideos (req, res, next) {
89 return res.type('json').status(204).end() 91 return res.type('json').status(204).end()
90} 92}
91 93
92function remoteVideosQadu (req, res, next) { 94function remoteVideosQadu (req: express.Request, res: express.Response, next: express.NextFunction) {
93 const requests = req.body.data 95 const requests = req.body.data
94 const fromPod = res.locals.secure.pod 96 const fromPod = res.locals.secure.pod
95 97
@@ -104,7 +106,7 @@ function remoteVideosQadu (req, res, next) {
104 return res.type('json').status(204).end() 106 return res.type('json').status(204).end()
105} 107}
106 108
107function remoteVideosEvents (req, res, next) { 109function remoteVideosEvents (req: express.Request, res: express.Response, next: express.NextFunction) {
108 const requests = req.body.data 110 const requests = req.body.data
109 const fromPod = res.locals.secure.pod 111 const fromPod = res.locals.secure.pod
110 112
@@ -119,7 +121,7 @@ function remoteVideosEvents (req, res, next) {
119 return res.type('json').status(204).end() 121 return res.type('json').status(204).end()
120} 122}
121 123
122function processVideosEventsRetryWrapper (eventData, fromPod, finalCallback) { 124function processVideosEventsRetryWrapper (eventData: any, fromPod: PodInstance, finalCallback: (err: Error) => void) {
123 const options = { 125 const options = {
124 arguments: [ eventData, fromPod ], 126 arguments: [ eventData, fromPod ],
125 errorMessage: 'Cannot process videos events with many retries.' 127 errorMessage: 'Cannot process videos events with many retries.'
@@ -128,7 +130,7 @@ function processVideosEventsRetryWrapper (eventData, fromPod, finalCallback) {
128 retryTransactionWrapper(processVideosEvents, options, finalCallback) 130 retryTransactionWrapper(processVideosEvents, options, finalCallback)
129} 131}
130 132
131function processVideosEvents (eventData, fromPod, finalCallback) { 133function processVideosEvents (eventData: any, fromPod: PodInstance, finalCallback: (err: Error) => void) {
132 waterfall([ 134 waterfall([
133 startSerializableTransaction, 135 startSerializableTransaction,
134 136
@@ -187,7 +189,7 @@ function processVideosEvents (eventData, fromPod, finalCallback) {
187 189
188 commitTransaction 190 commitTransaction
189 191
190 ], function (err, t) { 192 ], function (err: Error, t: Sequelize.Transaction) {
191 if (err) { 193 if (err) {
192 logger.debug('Cannot process a video event.', { error: err }) 194 logger.debug('Cannot process a video event.', { error: err })
193 return rollbackTransaction(err, t, finalCallback) 195 return rollbackTransaction(err, t, finalCallback)
@@ -198,7 +200,7 @@ function processVideosEvents (eventData, fromPod, finalCallback) {
198 }) 200 })
199} 201}
200 202
201function quickAndDirtyUpdateVideoRetryWrapper (videoData, fromPod, finalCallback) { 203function quickAndDirtyUpdateVideoRetryWrapper (videoData: any, fromPod: PodInstance, finalCallback: (err: Error) => void) {
202 const options = { 204 const options = {
203 arguments: [ videoData, fromPod ], 205 arguments: [ videoData, fromPod ],
204 errorMessage: 'Cannot update quick and dirty the remote video with many retries.' 206 errorMessage: 'Cannot update quick and dirty the remote video with many retries.'
@@ -207,7 +209,7 @@ function quickAndDirtyUpdateVideoRetryWrapper (videoData, fromPod, finalCallback
207 retryTransactionWrapper(quickAndDirtyUpdateVideo, options, finalCallback) 209 retryTransactionWrapper(quickAndDirtyUpdateVideo, options, finalCallback)
208} 210}
209 211
210function quickAndDirtyUpdateVideo (videoData, fromPod, finalCallback) { 212function quickAndDirtyUpdateVideo (videoData: any, fromPod: PodInstance, finalCallback: (err: Error) => void) {
211 let videoName 213 let videoName
212 214
213 waterfall([ 215 waterfall([
@@ -243,7 +245,7 @@ function quickAndDirtyUpdateVideo (videoData, fromPod, finalCallback) {
243 245
244 commitTransaction 246 commitTransaction
245 247
246 ], function (err, t) { 248 ], function (err: Error, t: Sequelize.Transaction) {
247 if (err) { 249 if (err) {
248 logger.debug('Cannot quick and dirty update the remote video.', { error: err }) 250 logger.debug('Cannot quick and dirty update the remote video.', { error: err })
249 return rollbackTransaction(err, t, finalCallback) 251 return rollbackTransaction(err, t, finalCallback)
@@ -255,7 +257,7 @@ function quickAndDirtyUpdateVideo (videoData, fromPod, finalCallback) {
255} 257}
256 258
257// Handle retries on fail 259// Handle retries on fail
258function addRemoteVideoRetryWrapper (videoToCreateData, fromPod, finalCallback) { 260function addRemoteVideoRetryWrapper (videoToCreateData: any, fromPod: PodInstance, finalCallback: (err: Error) => void) {
259 const options = { 261 const options = {
260 arguments: [ videoToCreateData, fromPod ], 262 arguments: [ videoToCreateData, fromPod ],
261 errorMessage: 'Cannot insert the remote video with many retries.' 263 errorMessage: 'Cannot insert the remote video with many retries.'
@@ -264,7 +266,7 @@ function addRemoteVideoRetryWrapper (videoToCreateData, fromPod, finalCallback)
264 retryTransactionWrapper(addRemoteVideo, options, finalCallback) 266 retryTransactionWrapper(addRemoteVideo, options, finalCallback)
265} 267}
266 268
267function addRemoteVideo (videoToCreateData, fromPod, finalCallback) { 269function addRemoteVideo (videoToCreateData: any, fromPod: PodInstance, finalCallback: (err: Error) => void) {
268 logger.debug('Adding remote video "%s".', videoToCreateData.remoteId) 270 logger.debug('Adding remote video "%s".', videoToCreateData.remoteId)
269 271
270 waterfall([ 272 waterfall([
@@ -359,7 +361,7 @@ function addRemoteVideo (videoToCreateData, fromPod, finalCallback) {
359 361
360 commitTransaction 362 commitTransaction
361 363
362 ], function (err, t) { 364 ], function (err: Error, t: Sequelize.Transaction) {
363 if (err) { 365 if (err) {
364 // This is just a debug because we will retry the insert 366 // This is just a debug because we will retry the insert
365 logger.debug('Cannot insert the remote video.', { error: err }) 367 logger.debug('Cannot insert the remote video.', { error: err })
@@ -372,7 +374,7 @@ function addRemoteVideo (videoToCreateData, fromPod, finalCallback) {
372} 374}
373 375
374// Handle retries on fail 376// Handle retries on fail
375function updateRemoteVideoRetryWrapper (videoAttributesToUpdate, fromPod, finalCallback) { 377function updateRemoteVideoRetryWrapper (videoAttributesToUpdate: any, fromPod: PodInstance, finalCallback: (err: Error) => void) {
376 const options = { 378 const options = {
377 arguments: [ videoAttributesToUpdate, fromPod ], 379 arguments: [ videoAttributesToUpdate, fromPod ],
378 errorMessage: 'Cannot update the remote video with many retries' 380 errorMessage: 'Cannot update the remote video with many retries'
@@ -381,7 +383,7 @@ function updateRemoteVideoRetryWrapper (videoAttributesToUpdate, fromPod, finalC
381 retryTransactionWrapper(updateRemoteVideo, options, finalCallback) 383 retryTransactionWrapper(updateRemoteVideo, options, finalCallback)
382} 384}
383 385
384function updateRemoteVideo (videoAttributesToUpdate, fromPod, finalCallback) { 386function updateRemoteVideo (videoAttributesToUpdate: any, fromPod: PodInstance, finalCallback: (err: Error) => void) {
385 logger.debug('Updating remote video "%s".', videoAttributesToUpdate.remoteId) 387 logger.debug('Updating remote video "%s".', videoAttributesToUpdate.remoteId)
386 388
387 waterfall([ 389 waterfall([
@@ -435,7 +437,7 @@ function updateRemoteVideo (videoAttributesToUpdate, fromPod, finalCallback) {
435 437
436 commitTransaction 438 commitTransaction
437 439
438 ], function (err, t) { 440 ], function (err: Error, t: Sequelize.Transaction) {
439 if (err) { 441 if (err) {
440 // This is just a debug because we will retry the insert 442 // This is just a debug because we will retry the insert
441 logger.debug('Cannot update the remote video.', { error: err }) 443 logger.debug('Cannot update the remote video.', { error: err })
@@ -447,7 +449,7 @@ function updateRemoteVideo (videoAttributesToUpdate, fromPod, finalCallback) {
447 }) 449 })
448} 450}
449 451
450function removeRemoteVideo (videoToRemoveData, fromPod, callback) { 452function removeRemoteVideo (videoToRemoveData: any, fromPod: PodInstance, callback: (err: Error) => void) {
451 // We need the instance because we have to remove some other stuffs (thumbnail etc) 453 // We need the instance because we have to remove some other stuffs (thumbnail etc)
452 fetchRemoteVideo(fromPod.host, videoToRemoveData.remoteId, function (err, video) { 454 fetchRemoteVideo(fromPod.host, videoToRemoveData.remoteId, function (err, video) {
453 // Do not return the error, continue the process 455 // Do not return the error, continue the process
@@ -465,7 +467,7 @@ function removeRemoteVideo (videoToRemoveData, fromPod, callback) {
465 }) 467 })
466} 468}
467 469
468function reportAbuseRemoteVideo (reportData, fromPod, callback) { 470function reportAbuseRemoteVideo (reportData: any, fromPod: PodInstance, callback: (err: Error) => void) {
469 fetchOwnedVideo(reportData.videoRemoteId, function (err, video) { 471 fetchOwnedVideo(reportData.videoRemoteId, function (err, video) {
470 if (err || !video) { 472 if (err || !video) {
471 if (!err) err = new Error('video not found') 473 if (!err) err = new Error('video not found')
@@ -494,7 +496,7 @@ function reportAbuseRemoteVideo (reportData, fromPod, callback) {
494 }) 496 })
495} 497}
496 498
497function fetchOwnedVideo (id, callback) { 499function fetchOwnedVideo (id: string, callback: (err: Error, video?: VideoInstance) => void) {
498 db.Video.load(id, function (err, video) { 500 db.Video.load(id, function (err, video) {
499 if (err || !video) { 501 if (err || !video) {
500 if (!err) err = new Error('video not found') 502 if (!err) err = new Error('video not found')
@@ -507,7 +509,7 @@ function fetchOwnedVideo (id, callback) {
507 }) 509 })
508} 510}
509 511
510function fetchRemoteVideo (podHost, remoteId, callback) { 512function fetchRemoteVideo (podHost: string, remoteId: string, callback: (err: Error, video?: VideoInstance) => void) {
511 db.Video.loadByHostAndRemoteId(podHost, remoteId, function (err, video) { 513 db.Video.loadByHostAndRemoteId(podHost, remoteId, function (err, video) {
512 if (err || !video) { 514 if (err || !video) {
513 if (!err) err = new Error('video not found') 515 if (!err) err = new Error('video not found')
diff --git a/server/controllers/api/requests.ts b/server/controllers/api/requests.ts
index ff4b4ac1a..2c18fe046 100644
--- a/server/controllers/api/requests.ts
+++ b/server/controllers/api/requests.ts
@@ -2,6 +2,7 @@ import * as express from 'express'
2import { parallel } from 'async' 2import { parallel } from 'async'
3 3
4import { 4import {
5 BaseRequestScheduler,
5 getRequestScheduler, 6 getRequestScheduler,
6 getRequestVideoQaduScheduler, 7 getRequestVideoQaduScheduler,
7 getRequestVideoEventScheduler 8 getRequestVideoEventScheduler
@@ -24,7 +25,7 @@ export {
24 25
25// --------------------------------------------------------------------------- 26// ---------------------------------------------------------------------------
26 27
27function getStatsRequests (req, res, next) { 28function getStatsRequests (req: express.Request, res: express.Response, next: express.NextFunction) {
28 parallel({ 29 parallel({
29 requestScheduler: buildRequestSchedulerFunction(getRequestScheduler()), 30 requestScheduler: buildRequestSchedulerFunction(getRequestScheduler()),
30 requestVideoQaduScheduler: buildRequestSchedulerFunction(getRequestVideoQaduScheduler()), 31 requestVideoQaduScheduler: buildRequestSchedulerFunction(getRequestVideoQaduScheduler()),
@@ -38,7 +39,7 @@ function getStatsRequests (req, res, next) {
38 39
39// --------------------------------------------------------------------------- 40// ---------------------------------------------------------------------------
40 41
41function buildRequestSchedulerFunction (requestScheduler) { 42function buildRequestSchedulerFunction (requestScheduler: BaseRequestScheduler) {
42 return function (callback) { 43 return function (callback) {
43 requestScheduler.remainingRequestsCount(function (err, count) { 44 requestScheduler.remainingRequestsCount(function (err, count) {
44 if (err) return callback(err) 45 if (err) return callback(err)
diff --git a/server/controllers/api/users.ts b/server/controllers/api/users.ts
index 44c5ec13c..ffe5881e5 100644
--- a/server/controllers/api/users.ts
+++ b/server/controllers/api/users.ts
@@ -76,7 +76,7 @@ export {
76 76
77// --------------------------------------------------------------------------- 77// ---------------------------------------------------------------------------
78 78
79function ensureRegistrationEnabled (req, res, next) { 79function ensureRegistrationEnabled (req: express.Request, res: express.Response, next: express.NextFunction) {
80 const registrationEnabled = CONFIG.SIGNUP.ENABLED 80 const registrationEnabled = CONFIG.SIGNUP.ENABLED
81 81
82 if (registrationEnabled === true) { 82 if (registrationEnabled === true) {
@@ -86,7 +86,7 @@ function ensureRegistrationEnabled (req, res, next) {
86 return res.status(400).send('User registration is not enabled.') 86 return res.status(400).send('User registration is not enabled.')
87} 87}
88 88
89function createUser (req, res, next) { 89function createUser (req: express.Request, res: express.Response, next: express.NextFunction) {
90 const user = db.User.build({ 90 const user = db.User.build({
91 username: req.body.username, 91 username: req.body.username,
92 password: req.body.password, 92 password: req.body.password,
@@ -95,14 +95,14 @@ function createUser (req, res, next) {
95 role: USER_ROLES.USER 95 role: USER_ROLES.USER
96 }) 96 })
97 97
98 user.save().asCallback(function (err, createdUser) { 98 user.save().asCallback(function (err) {
99 if (err) return next(err) 99 if (err) return next(err)
100 100
101 return res.type('json').status(204).end() 101 return res.type('json').status(204).end()
102 }) 102 })
103} 103}
104 104
105function getUserInformation (req, res, next) { 105function getUserInformation (req: express.Request, res: express.Response, next: express.NextFunction) {
106 db.User.loadByUsername(res.locals.oauth.token.user.username, function (err, user) { 106 db.User.loadByUsername(res.locals.oauth.token.user.username, function (err, user) {
107 if (err) return next(err) 107 if (err) return next(err)
108 108
@@ -110,9 +110,9 @@ function getUserInformation (req, res, next) {
110 }) 110 })
111} 111}
112 112
113function getUserVideoRating (req, res, next) { 113function getUserVideoRating (req: express.Request, res: express.Response, next: express.NextFunction) {
114 const videoId = req.params.videoId 114 const videoId = '' + req.params.videoId
115 const userId = res.locals.oauth.token.User.id 115 const userId = +res.locals.oauth.token.User.id
116 116
117 db.UserVideoRate.load(userId, videoId, null, function (err, ratingObj) { 117 db.UserVideoRate.load(userId, videoId, null, function (err, ratingObj) {
118 if (err) return next(err) 118 if (err) return next(err)
@@ -126,7 +126,7 @@ function getUserVideoRating (req, res, next) {
126 }) 126 })
127} 127}
128 128
129function listUsers (req, res, next) { 129function listUsers (req: express.Request, res: express.Response, next: express.NextFunction) {
130 db.User.listForApi(req.query.start, req.query.count, req.query.sort, function (err, usersList, usersTotal) { 130 db.User.listForApi(req.query.start, req.query.count, req.query.sort, function (err, usersList, usersTotal) {
131 if (err) return next(err) 131 if (err) return next(err)
132 132
@@ -134,7 +134,7 @@ function listUsers (req, res, next) {
134 }) 134 })
135} 135}
136 136
137function removeUser (req, res, next) { 137function removeUser (req: express.Request, res: express.Response, next: express.NextFunction) {
138 waterfall([ 138 waterfall([
139 function loadUser (callback) { 139 function loadUser (callback) {
140 db.User.loadById(req.params.id, callback) 140 db.User.loadById(req.params.id, callback)
@@ -153,7 +153,7 @@ function removeUser (req, res, next) {
153 }) 153 })
154} 154}
155 155
156function updateUser (req, res, next) { 156function updateUser (req: express.Request, res: express.Response, next: express.NextFunction) {
157 db.User.loadByUsername(res.locals.oauth.token.user.username, function (err, user) { 157 db.User.loadByUsername(res.locals.oauth.token.user.username, function (err, user) {
158 if (err) return next(err) 158 if (err) return next(err)
159 159
@@ -168,6 +168,6 @@ function updateUser (req, res, next) {
168 }) 168 })
169} 169}
170 170
171function success (req, res, next) { 171function success (req: express.Request, res: express.Response, next: express.NextFunction) {
172 res.end() 172 res.end()
173} 173}
diff --git a/server/controllers/api/videos/abuse.ts b/server/controllers/api/videos/abuse.ts
index 68db025b7..78e8e8b3d 100644
--- a/server/controllers/api/videos/abuse.ts
+++ b/server/controllers/api/videos/abuse.ts
@@ -1,4 +1,5 @@
1import * as express from 'express' 1import * as express from 'express'
2import * as Sequelize from 'sequelize'
2import { waterfall } from 'async' 3import { waterfall } from 'async'
3 4
4import { database as db } from '../../../initializers/database' 5import { database as db } from '../../../initializers/database'
@@ -46,7 +47,7 @@ export {
46 47
47// --------------------------------------------------------------------------- 48// ---------------------------------------------------------------------------
48 49
49function listVideoAbuses (req, res, next) { 50function listVideoAbuses (req: express.Request, res: express.Response, next: express.NextFunction) {
50 db.VideoAbuse.listForApi(req.query.start, req.query.count, req.query.sort, function (err, abusesList, abusesTotal) { 51 db.VideoAbuse.listForApi(req.query.start, req.query.count, req.query.sort, function (err, abusesList, abusesTotal) {
51 if (err) return next(err) 52 if (err) return next(err)
52 53
@@ -54,7 +55,7 @@ function listVideoAbuses (req, res, next) {
54 }) 55 })
55} 56}
56 57
57function reportVideoAbuseRetryWrapper (req, res, next) { 58function reportVideoAbuseRetryWrapper (req: express.Request, res: express.Response, next: express.NextFunction) {
58 const options = { 59 const options = {
59 arguments: [ req, res ], 60 arguments: [ req, res ],
60 errorMessage: 'Cannot report abuse to the video with many retries.' 61 errorMessage: 'Cannot report abuse to the video with many retries.'
@@ -67,7 +68,7 @@ function reportVideoAbuseRetryWrapper (req, res, next) {
67 }) 68 })
68} 69}
69 70
70function reportVideoAbuse (req, res, finalCallback) { 71function reportVideoAbuse (req: express.Request, res: express.Response, finalCallback: (err: Error) => void) {
71 const videoInstance = res.locals.video 72 const videoInstance = res.locals.video
72 const reporterUsername = res.locals.oauth.token.User.username 73 const reporterUsername = res.locals.oauth.token.User.username
73 74
@@ -105,7 +106,7 @@ function reportVideoAbuse (req, res, finalCallback) {
105 106
106 commitTransaction 107 commitTransaction
107 108
108 ], function andFinally (err, t) { 109 ], function andFinally (err: Error, t: Sequelize.Transaction) {
109 if (err) { 110 if (err) {
110 logger.debug('Cannot update the video.', { error: err }) 111 logger.debug('Cannot update the video.', { error: err })
111 return rollbackTransaction(err, t, finalCallback) 112 return rollbackTransaction(err, t, finalCallback)
diff --git a/server/controllers/api/videos/blacklist.ts b/server/controllers/api/videos/blacklist.ts
index 58960798b..4b42fc2d7 100644
--- a/server/controllers/api/videos/blacklist.ts
+++ b/server/controllers/api/videos/blacklist.ts
@@ -25,7 +25,7 @@ export {
25 25
26// --------------------------------------------------------------------------- 26// ---------------------------------------------------------------------------
27 27
28function addVideoToBlacklist (req, res, next) { 28function addVideoToBlacklist (req: express.Request, res: express.Response, next: express.NextFunction) {
29 const videoInstance = res.locals.video 29 const videoInstance = res.locals.video
30 30
31 const toCreate = { 31 const toCreate = {
diff --git a/server/controllers/api/videos/index.ts b/server/controllers/api/videos/index.ts
index b82b0936f..bfa018031 100644
--- a/server/controllers/api/videos/index.ts
+++ b/server/controllers/api/videos/index.ts
@@ -1,4 +1,5 @@
1import * as express from 'express' 1import * as express from 'express'
2import * as Sequelize from 'sequelize'
2import * as fs from 'fs' 3import * as fs from 'fs'
3import * as multer from 'multer' 4import * as multer from 'multer'
4import * as path from 'path' 5import * as path from 'path'
@@ -124,21 +125,21 @@ export {
124 125
125// --------------------------------------------------------------------------- 126// ---------------------------------------------------------------------------
126 127
127function listVideoCategories (req, res, next) { 128function listVideoCategories (req: express.Request, res: express.Response, next: express.NextFunction) {
128 res.json(VIDEO_CATEGORIES) 129 res.json(VIDEO_CATEGORIES)
129} 130}
130 131
131function listVideoLicences (req, res, next) { 132function listVideoLicences (req: express.Request, res: express.Response, next: express.NextFunction) {
132 res.json(VIDEO_LICENCES) 133 res.json(VIDEO_LICENCES)
133} 134}
134 135
135function listVideoLanguages (req, res, next) { 136function listVideoLanguages (req: express.Request, res: express.Response, next: express.NextFunction) {
136 res.json(VIDEO_LANGUAGES) 137 res.json(VIDEO_LANGUAGES)
137} 138}
138 139
139// Wrapper to video add that retry the function if there is a database error 140// Wrapper to video add that retry the function if there is a database error
140// We need this because we run the transaction in SERIALIZABLE isolation that can fail 141// We need this because we run the transaction in SERIALIZABLE isolation that can fail
141function addVideoRetryWrapper (req, res, next) { 142function addVideoRetryWrapper (req: express.Request, res: express.Response, next: express.NextFunction) {
142 const options = { 143 const options = {
143 arguments: [ req, res, req.files.videofile[0] ], 144 arguments: [ req, res, req.files.videofile[0] ],
144 errorMessage: 'Cannot insert the video with many retries.' 145 errorMessage: 'Cannot insert the video with many retries.'
@@ -152,7 +153,7 @@ function addVideoRetryWrapper (req, res, next) {
152 }) 153 })
153} 154}
154 155
155function addVideo (req, res, videoFile, finalCallback) { 156function addVideo (req: express.Request, res: express.Response, videoFile: Express.Multer.File, finalCallback: (err: Error) => void) {
156 const videoInfos = req.body 157 const videoInfos = req.body
157 158
158 waterfall([ 159 waterfall([
@@ -190,7 +191,7 @@ function addVideo (req, res, videoFile, finalCallback) {
190 language: videoInfos.language, 191 language: videoInfos.language,
191 nsfw: videoInfos.nsfw, 192 nsfw: videoInfos.nsfw,
192 description: videoInfos.description, 193 description: videoInfos.description,
193 duration: videoFile.duration, 194 duration: videoFile['duration'], // duration was added by a previous middleware
194 authorId: author.id 195 authorId: author.id
195 } 196 }
196 197
@@ -254,7 +255,7 @@ function addVideo (req, res, videoFile, finalCallback) {
254 255
255 commitTransaction 256 commitTransaction
256 257
257 ], function andFinally (err, t) { 258 ], function andFinally (err: Error, t: Sequelize.Transaction) {
258 if (err) { 259 if (err) {
259 // This is just a debug because we will retry the insert 260 // This is just a debug because we will retry the insert
260 logger.debug('Cannot insert the video.', { error: err }) 261 logger.debug('Cannot insert the video.', { error: err })
@@ -266,7 +267,7 @@ function addVideo (req, res, videoFile, finalCallback) {
266 }) 267 })
267} 268}
268 269
269function updateVideoRetryWrapper (req, res, next) { 270function updateVideoRetryWrapper (req: express.Request, res: express.Response, next: express.NextFunction) {
270 const options = { 271 const options = {
271 arguments: [ req, res ], 272 arguments: [ req, res ],
272 errorMessage: 'Cannot update the video with many retries.' 273 errorMessage: 'Cannot update the video with many retries.'
@@ -280,7 +281,7 @@ function updateVideoRetryWrapper (req, res, next) {
280 }) 281 })
281} 282}
282 283
283function updateVideo (req, res, finalCallback) { 284function updateVideo (req: express.Request, res: express.Response, finalCallback: (err: Error) => void) {
284 const videoInstance = res.locals.video 285 const videoInstance = res.locals.video
285 const videoFieldsSave = videoInstance.toJSON() 286 const videoFieldsSave = videoInstance.toJSON()
286 const videoInfosToUpdate = req.body 287 const videoInfosToUpdate = req.body
@@ -341,7 +342,7 @@ function updateVideo (req, res, finalCallback) {
341 342
342 commitTransaction 343 commitTransaction
343 344
344 ], function andFinally (err, t) { 345 ], function andFinally (err: Error, t: Sequelize.Transaction) {
345 if (err) { 346 if (err) {
346 logger.debug('Cannot update the video.', { error: err }) 347 logger.debug('Cannot update the video.', { error: err })
347 348
@@ -361,7 +362,7 @@ function updateVideo (req, res, finalCallback) {
361 }) 362 })
362} 363}
363 364
364function getVideo (req, res, next) { 365function getVideo (req: express.Request, res: express.Response, next: express.NextFunction) {
365 const videoInstance = res.locals.video 366 const videoInstance = res.locals.video
366 367
367 if (videoInstance.isOwned()) { 368 if (videoInstance.isOwned()) {
@@ -393,7 +394,7 @@ function getVideo (req, res, next) {
393 res.json(videoInstance.toFormatedJSON()) 394 res.json(videoInstance.toFormatedJSON())
394} 395}
395 396
396function listVideos (req, res, next) { 397function listVideos (req: express.Request, res: express.Response, next: express.NextFunction) {
397 db.Video.listForApi(req.query.start, req.query.count, req.query.sort, function (err, videosList, videosTotal) { 398 db.Video.listForApi(req.query.start, req.query.count, req.query.sort, function (err, videosList, videosTotal) {
398 if (err) return next(err) 399 if (err) return next(err)
399 400
@@ -401,7 +402,7 @@ function listVideos (req, res, next) {
401 }) 402 })
402} 403}
403 404
404function removeVideo (req, res, next) { 405function removeVideo (req: express.Request, res: express.Response, next: express.NextFunction) {
405 const videoInstance = res.locals.video 406 const videoInstance = res.locals.video
406 407
407 videoInstance.destroy().asCallback(function (err) { 408 videoInstance.destroy().asCallback(function (err) {
@@ -414,7 +415,7 @@ function removeVideo (req, res, next) {
414 }) 415 })
415} 416}
416 417
417function searchVideos (req, res, next) { 418function searchVideos (req: express.Request, res: express.Response, next: express.NextFunction) {
418 db.Video.searchAndPopulateAuthorAndPodAndTags( 419 db.Video.searchAndPopulateAuthorAndPodAndTags(
419 req.params.value, req.query.field, req.query.start, req.query.count, req.query.sort, 420 req.params.value, req.query.field, req.query.start, req.query.count, req.query.sort,
420 function (err, videosList, videosTotal) { 421 function (err, videosList, videosTotal) {
diff --git a/server/controllers/api/videos/rate.ts b/server/controllers/api/videos/rate.ts
index 1bc575675..afdd099f8 100644
--- a/server/controllers/api/videos/rate.ts
+++ b/server/controllers/api/videos/rate.ts
@@ -1,4 +1,5 @@
1import * as express from 'express' 1import * as express from 'express'
2import * as Sequelize from 'sequelize'
2import { waterfall } from 'async' 3import { waterfall } from 'async'
3 4
4import { database as db } from '../../../initializers/database' 5import { database as db } from '../../../initializers/database'
@@ -39,7 +40,7 @@ export {
39 40
40// --------------------------------------------------------------------------- 41// ---------------------------------------------------------------------------
41 42
42function rateVideoRetryWrapper (req, res, next) { 43function rateVideoRetryWrapper (req: express.Request, res: express.Response, next: express.NextFunction) {
43 const options = { 44 const options = {
44 arguments: [ req, res ], 45 arguments: [ req, res ],
45 errorMessage: 'Cannot update the user video rate.' 46 errorMessage: 'Cannot update the user video rate.'
@@ -52,7 +53,7 @@ function rateVideoRetryWrapper (req, res, next) {
52 }) 53 })
53} 54}
54 55
55function rateVideo (req, res, finalCallback) { 56function rateVideo (req: express.Request, res: express.Response, finalCallback: (err: Error) => void) {
56 const rateType = req.body.rating 57 const rateType = req.body.rating
57 const videoInstance = res.locals.video 58 const videoInstance = res.locals.video
58 const userInstance = res.locals.oauth.token.User 59 const userInstance = res.locals.oauth.token.User
@@ -168,7 +169,7 @@ function rateVideo (req, res, finalCallback) {
168 169
169 commitTransaction 170 commitTransaction
170 171
171 ], function (err, t) { 172 ], function (err: Error, t: Sequelize.Transaction) {
172 if (err) { 173 if (err) {
173 // This is just a debug because we will retry the insert 174 // This is just a debug because we will retry the insert
174 logger.debug('Cannot add the user video rate.', { error: err }) 175 logger.debug('Cannot add the user video rate.', { error: err })
diff --git a/server/controllers/client.ts b/server/controllers/client.ts
index c3d28245c..503eff750 100644
--- a/server/controllers/client.ts
+++ b/server/controllers/client.ts
@@ -12,6 +12,7 @@ import {
12 STATIC_MAX_AGE 12 STATIC_MAX_AGE
13} from '../initializers' 13} from '../initializers'
14import { root } from '../helpers' 14import { root } from '../helpers'
15import { VideoInstance } from '../models'
15 16
16const clientsRouter = express.Router() 17const clientsRouter = express.Router()
17 18
@@ -25,7 +26,7 @@ const indexPath = join(distPath, 'index.html')
25// Do not use a template engine for a so little thing 26// Do not use a template engine for a so little thing
26clientsRouter.use('/videos/watch/:id', generateWatchHtmlPage) 27clientsRouter.use('/videos/watch/:id', generateWatchHtmlPage)
27 28
28clientsRouter.use('/videos/embed', function (req, res, next) { 29clientsRouter.use('/videos/embed', function (req: express.Request, res: express.Response, next: express.NextFunction) {
29 res.sendFile(embedPath) 30 res.sendFile(embedPath)
30}) 31})
31 32
@@ -33,7 +34,7 @@ clientsRouter.use('/videos/embed', function (req, res, next) {
33clientsRouter.use('/client', express.static(distPath, { maxAge: STATIC_MAX_AGE })) 34clientsRouter.use('/client', express.static(distPath, { maxAge: STATIC_MAX_AGE }))
34 35
35// 404 for static files not found 36// 404 for static files not found
36clientsRouter.use('/client/*', function (req, res, next) { 37clientsRouter.use('/client/*', function (req: express.Request, res: express.Response, next: express.NextFunction) {
37 res.sendStatus(404) 38 res.sendStatus(404)
38}) 39})
39 40
@@ -45,7 +46,7 @@ export {
45 46
46// --------------------------------------------------------------------------- 47// ---------------------------------------------------------------------------
47 48
48function addOpenGraphTags (htmlStringPage, video) { 49function addOpenGraphTags (htmlStringPage: string, video: VideoInstance) {
49 let basePreviewUrlHttp 50 let basePreviewUrlHttp
50 51
51 if (video.isOwned()) { 52 if (video.isOwned()) {
@@ -88,8 +89,8 @@ function addOpenGraphTags (htmlStringPage, video) {
88 return htmlStringPage.replace(opengraphComment, tagsString) 89 return htmlStringPage.replace(opengraphComment, tagsString)
89} 90}
90 91
91function generateWatchHtmlPage (req, res, next) { 92function generateWatchHtmlPage (req: express.Request, res: express.Response, next: express.NextFunction) {
92 const videoId = req.params.id 93 const videoId = '' + req.params.id
93 94
94 // Let Angular application handle errors 95 // Let Angular application handle errors
95 if (!validator.isUUID(videoId, 4)) return res.sendFile(indexPath) 96 if (!validator.isUUID(videoId, 4)) return res.sendFile(indexPath)
@@ -102,7 +103,7 @@ function generateWatchHtmlPage (req, res, next) {
102 video: function (callback) { 103 video: function (callback) {
103 db.Video.loadAndPopulateAuthorAndPodAndTags(videoId, callback) 104 db.Video.loadAndPopulateAuthorAndPodAndTags(videoId, callback)
104 } 105 }
105 }, function (err, result: any) { 106 }, function (err: Error, result: { file: Buffer, video: VideoInstance }) {
106 if (err) return next(err) 107 if (err) return next(err)
107 108
108 const html = result.file.toString() 109 const html = result.file.toString()
diff --git a/server/helpers/custom-validators/misc.ts b/server/helpers/custom-validators/misc.ts
index 83f50a7fe..b1291ba7a 100644
--- a/server/helpers/custom-validators/misc.ts
+++ b/server/helpers/custom-validators/misc.ts
@@ -1,8 +1,8 @@
1function exists (value) { 1function exists (value: any) {
2 return value !== undefined && value !== null 2 return value !== undefined && value !== null
3} 3}
4 4
5function isArray (value) { 5function isArray (value: any) {
6 return Array.isArray(value) 6 return Array.isArray(value)
7} 7}
8 8
@@ -12,3 +12,12 @@ export {
12 exists, 12 exists,
13 isArray 13 isArray
14} 14}
15
16declare global {
17 namespace ExpressValidator {
18 export interface Validator {
19 exists,
20 isArray
21 }
22 }
23}
diff --git a/server/helpers/custom-validators/pods.ts b/server/helpers/custom-validators/pods.ts
index ee939ad04..ec9f26cc8 100644
--- a/server/helpers/custom-validators/pods.ts
+++ b/server/helpers/custom-validators/pods.ts
@@ -1,12 +1,12 @@
1import * as validator from 'validator' 1import * as validator from 'validator'
2 2
3import { isArray } from './misc' 3import { isArray, exists } from './misc'
4 4
5function isHostValid (host) { 5function isHostValid (host: string) {
6 return validator.isURL(host) && host.split('://').length === 1 6 return exists(host) && validator.isURL(host) && host.split('://').length === 1
7} 7}
8 8
9function isEachUniqueHostValid (hosts) { 9function isEachUniqueHostValid (hosts: string[]) {
10 return isArray(hosts) && 10 return isArray(hosts) &&
11 hosts.length !== 0 && 11 hosts.length !== 0 &&
12 hosts.every(function (host) { 12 hosts.every(function (host) {
@@ -20,3 +20,12 @@ export {
20 isEachUniqueHostValid, 20 isEachUniqueHostValid,
21 isHostValid 21 isHostValid
22} 22}
23
24declare global {
25 namespace ExpressValidator {
26 export interface Validator {
27 isEachUniqueHostValid
28 isHostValid
29 }
30 }
31}
diff --git a/server/helpers/custom-validators/remote/index.ts b/server/helpers/custom-validators/remote/index.ts
index d6f9a7e77..e29a9b767 100644
--- a/server/helpers/custom-validators/remote/index.ts
+++ b/server/helpers/custom-validators/remote/index.ts
@@ -1 +1 @@
export * from './videos'; export * from './videos'
diff --git a/server/helpers/custom-validators/remote/videos.ts b/server/helpers/custom-validators/remote/videos.ts
index 4b904d011..1df7316aa 100644
--- a/server/helpers/custom-validators/remote/videos.ts
+++ b/server/helpers/custom-validators/remote/videos.ts
@@ -31,7 +31,7 @@ import {
31 31
32const ENDPOINT_ACTIONS = REQUEST_ENDPOINT_ACTIONS[REQUEST_ENDPOINTS.VIDEOS] 32const ENDPOINT_ACTIONS = REQUEST_ENDPOINT_ACTIONS[REQUEST_ENDPOINTS.VIDEOS]
33 33
34function isEachRemoteRequestVideosValid (requests) { 34function isEachRemoteRequestVideosValid (requests: any[]) {
35 return isArray(requests) && 35 return isArray(requests) &&
36 requests.every(function (request) { 36 requests.every(function (request) {
37 const video = request.data 37 const video = request.data
@@ -61,7 +61,7 @@ function isEachRemoteRequestVideosValid (requests) {
61 }) 61 })
62} 62}
63 63
64function isEachRemoteRequestVideosQaduValid (requests) { 64function isEachRemoteRequestVideosQaduValid (requests: any[]) {
65 return isArray(requests) && 65 return isArray(requests) &&
66 requests.every(function (request) { 66 requests.every(function (request) {
67 const video = request.data 67 const video = request.data
@@ -70,14 +70,14 @@ function isEachRemoteRequestVideosQaduValid (requests) {
70 70
71 return ( 71 return (
72 isVideoRemoteIdValid(video.remoteId) && 72 isVideoRemoteIdValid(video.remoteId) &&
73 (has(video, 'views') === false || isVideoViewsValid) && 73 (has(video, 'views') === false || isVideoViewsValid(video.views)) &&
74 (has(video, 'likes') === false || isVideoLikesValid) && 74 (has(video, 'likes') === false || isVideoLikesValid(video.likes)) &&
75 (has(video, 'dislikes') === false || isVideoDislikesValid) 75 (has(video, 'dislikes') === false || isVideoDislikesValid(video.dislikes))
76 ) 76 )
77 }) 77 })
78} 78}
79 79
80function isEachRemoteRequestVideosEventsValid (requests) { 80function isEachRemoteRequestVideosEventsValid (requests: any[]) {
81 return isArray(requests) && 81 return isArray(requests) &&
82 requests.every(function (request) { 82 requests.every(function (request) {
83 const eventData = request.data 83 const eventData = request.data
@@ -100,9 +100,19 @@ export {
100 isEachRemoteRequestVideosEventsValid 100 isEachRemoteRequestVideosEventsValid
101} 101}
102 102
103declare global {
104 namespace ExpressValidator {
105 export interface Validator {
106 isEachRemoteRequestVideosValid,
107 isEachRemoteRequestVideosQaduValid,
108 isEachRemoteRequestVideosEventsValid
109 }
110 }
111}
112
103// --------------------------------------------------------------------------- 113// ---------------------------------------------------------------------------
104 114
105function isCommonVideoAttributesValid (video) { 115function isCommonVideoAttributesValid (video: any) {
106 return isVideoDateValid(video.createdAt) && 116 return isVideoDateValid(video.createdAt) &&
107 isVideoDateValid(video.updatedAt) && 117 isVideoDateValid(video.updatedAt) &&
108 isVideoCategoryValid(video.category) && 118 isVideoCategoryValid(video.category) &&
@@ -121,18 +131,18 @@ function isCommonVideoAttributesValid (video) {
121 isVideoDislikesValid(video.dislikes) 131 isVideoDislikesValid(video.dislikes)
122} 132}
123 133
124function isRequestTypeAddValid (value) { 134function isRequestTypeAddValid (value: string) {
125 return value === ENDPOINT_ACTIONS.ADD 135 return value === ENDPOINT_ACTIONS.ADD
126} 136}
127 137
128function isRequestTypeUpdateValid (value) { 138function isRequestTypeUpdateValid (value: string) {
129 return value === ENDPOINT_ACTIONS.UPDATE 139 return value === ENDPOINT_ACTIONS.UPDATE
130} 140}
131 141
132function isRequestTypeRemoveValid (value) { 142function isRequestTypeRemoveValid (value: string) {
133 return value === ENDPOINT_ACTIONS.REMOVE 143 return value === ENDPOINT_ACTIONS.REMOVE
134} 144}
135 145
136function isRequestTypeReportAbuseValid (value) { 146function isRequestTypeReportAbuseValid (value: string) {
137 return value === ENDPOINT_ACTIONS.REPORT_ABUSE 147 return value === ENDPOINT_ACTIONS.REPORT_ABUSE
138} 148}
diff --git a/server/helpers/custom-validators/users.ts b/server/helpers/custom-validators/users.ts
index f303ab8db..7792ffd74 100644
--- a/server/helpers/custom-validators/users.ts
+++ b/server/helpers/custom-validators/users.ts
@@ -1,25 +1,26 @@
1import { values } from 'lodash' 1import { values } from 'lodash'
2import * as validator from 'validator' 2import * as validator from 'validator'
3 3
4import { exists } from './misc'
4import { CONSTRAINTS_FIELDS, USER_ROLES } from '../../initializers' 5import { CONSTRAINTS_FIELDS, USER_ROLES } from '../../initializers'
5const USERS_CONSTRAINTS_FIELDS = CONSTRAINTS_FIELDS.USERS 6const USERS_CONSTRAINTS_FIELDS = CONSTRAINTS_FIELDS.USERS
6 7
7function isUserPasswordValid (value) { 8function isUserPasswordValid (value: string) {
8 return validator.isLength(value, USERS_CONSTRAINTS_FIELDS.PASSWORD) 9 return validator.isLength(value, USERS_CONSTRAINTS_FIELDS.PASSWORD)
9} 10}
10 11
11function isUserRoleValid (value) { 12function isUserRoleValid (value: string) {
12 return values(USER_ROLES).indexOf(value) !== -1 13 return values(USER_ROLES).indexOf(value) !== -1
13} 14}
14 15
15function isUserUsernameValid (value) { 16function isUserUsernameValid (value: string) {
16 const max = USERS_CONSTRAINTS_FIELDS.USERNAME.max 17 const max = USERS_CONSTRAINTS_FIELDS.USERNAME.max
17 const min = USERS_CONSTRAINTS_FIELDS.USERNAME.min 18 const min = USERS_CONSTRAINTS_FIELDS.USERNAME.min
18 return validator.matches(value, new RegExp(`^[a-zA-Z0-9._]{${min},${max}}$`)) 19 return exists(value) && validator.matches(value, new RegExp(`^[a-zA-Z0-9._]{${min},${max}}$`))
19} 20}
20 21
21function isUserDisplayNSFWValid (value) { 22function isUserDisplayNSFWValid (value: any) {
22 return validator.isBoolean(value) 23 return typeof value === 'boolean' || (typeof value === 'string' && validator.isBoolean(value))
23} 24}
24 25
25// --------------------------------------------------------------------------- 26// ---------------------------------------------------------------------------
@@ -30,3 +31,14 @@ export {
30 isUserUsernameValid, 31 isUserUsernameValid,
31 isUserDisplayNSFWValid 32 isUserDisplayNSFWValid
32} 33}
34
35declare global {
36 namespace ExpressValidator {
37 export interface Validator {
38 isUserPasswordValid,
39 isUserRoleValid,
40 isUserUsernameValid,
41 isUserDisplayNSFWValid
42 }
43 }
44}
diff --git a/server/helpers/custom-validators/videos.ts b/server/helpers/custom-validators/videos.ts
index 6389998e1..c5ef4cb5f 100644
--- a/server/helpers/custom-validators/videos.ts
+++ b/server/helpers/custom-validators/videos.ts
@@ -9,105 +9,105 @@ import {
9 VIDEO_RATE_TYPES 9 VIDEO_RATE_TYPES
10} from '../../initializers' 10} from '../../initializers'
11import { isUserUsernameValid } from './users' 11import { isUserUsernameValid } from './users'
12import { isArray } from './misc' 12import { isArray, exists } from './misc'
13 13
14const VIDEOS_CONSTRAINTS_FIELDS = CONSTRAINTS_FIELDS.VIDEOS 14const VIDEOS_CONSTRAINTS_FIELDS = CONSTRAINTS_FIELDS.VIDEOS
15const VIDEO_ABUSES_CONSTRAINTS_FIELDS = CONSTRAINTS_FIELDS.VIDEO_ABUSES 15const VIDEO_ABUSES_CONSTRAINTS_FIELDS = CONSTRAINTS_FIELDS.VIDEO_ABUSES
16const VIDEO_EVENTS_CONSTRAINTS_FIELDS = CONSTRAINTS_FIELDS.VIDEO_EVENTS 16const VIDEO_EVENTS_CONSTRAINTS_FIELDS = CONSTRAINTS_FIELDS.VIDEO_EVENTS
17 17
18function isVideoAuthorValid (value) { 18function isVideoAuthorValid (value: string) {
19 return isUserUsernameValid(value) 19 return isUserUsernameValid(value)
20} 20}
21 21
22function isVideoDateValid (value) { 22function isVideoDateValid (value: string) {
23 return validator.isDate(value) 23 return exists(value) && validator.isISO8601(value)
24} 24}
25 25
26function isVideoCategoryValid (value) { 26function isVideoCategoryValid (value: number) {
27 return VIDEO_CATEGORIES[value] !== undefined 27 return VIDEO_CATEGORIES[value] !== undefined
28} 28}
29 29
30function isVideoLicenceValid (value) { 30function isVideoLicenceValid (value: number) {
31 return VIDEO_LICENCES[value] !== undefined 31 return VIDEO_LICENCES[value] !== undefined
32} 32}
33 33
34function isVideoLanguageValid (value) { 34function isVideoLanguageValid (value: number) {
35 return value === null || VIDEO_LANGUAGES[value] !== undefined 35 return value === null || VIDEO_LANGUAGES[value] !== undefined
36} 36}
37 37
38function isVideoNSFWValid (value) { 38function isVideoNSFWValid (value: any) {
39 return validator.isBoolean(value) 39 return typeof value === 'boolean' || (typeof value === 'string' && validator.isBoolean(value))
40} 40}
41 41
42function isVideoDescriptionValid (value) { 42function isVideoDescriptionValid (value: string) {
43 return validator.isLength(value, VIDEOS_CONSTRAINTS_FIELDS.DESCRIPTION) 43 return exists(value) && validator.isLength(value, VIDEOS_CONSTRAINTS_FIELDS.DESCRIPTION)
44} 44}
45 45
46function isVideoDurationValid (value) { 46function isVideoDurationValid (value: string) {
47 return validator.isInt(value + '', VIDEOS_CONSTRAINTS_FIELDS.DURATION) 47 return exists(value) && validator.isInt(value + '', VIDEOS_CONSTRAINTS_FIELDS.DURATION)
48} 48}
49 49
50function isVideoExtnameValid (value) { 50function isVideoExtnameValid (value: string) {
51 return VIDEOS_CONSTRAINTS_FIELDS.EXTNAME.indexOf(value) !== -1 51 return VIDEOS_CONSTRAINTS_FIELDS.EXTNAME.indexOf(value) !== -1
52} 52}
53 53
54function isVideoInfoHashValid (value) { 54function isVideoInfoHashValid (value: string) {
55 return validator.isLength(value, VIDEOS_CONSTRAINTS_FIELDS.INFO_HASH) 55 return exists(value) && validator.isLength(value, VIDEOS_CONSTRAINTS_FIELDS.INFO_HASH)
56} 56}
57 57
58function isVideoNameValid (value) { 58function isVideoNameValid (value: string) {
59 return validator.isLength(value, VIDEOS_CONSTRAINTS_FIELDS.NAME) 59 return exists(value) && validator.isLength(value, VIDEOS_CONSTRAINTS_FIELDS.NAME)
60} 60}
61 61
62function isVideoTagsValid (tags) { 62function isVideoTagsValid (tags: string[]) {
63 return isArray(tags) && 63 return isArray(tags) &&
64 validator.isInt(tags.length, VIDEOS_CONSTRAINTS_FIELDS.TAGS) && 64 validator.isInt(tags.length.toString(), VIDEOS_CONSTRAINTS_FIELDS.TAGS) &&
65 tags.every(function (tag) { 65 tags.every(function (tag) {
66 return validator.isLength(tag, VIDEOS_CONSTRAINTS_FIELDS.TAG) 66 return exists(tag) && validator.isLength(tag, VIDEOS_CONSTRAINTS_FIELDS.TAG)
67 }) 67 })
68} 68}
69 69
70function isVideoThumbnailValid (value) { 70function isVideoThumbnailValid (value: string) {
71 return validator.isLength(value, VIDEOS_CONSTRAINTS_FIELDS.THUMBNAIL) 71 return exists(value) && validator.isLength(value, VIDEOS_CONSTRAINTS_FIELDS.THUMBNAIL)
72} 72}
73 73
74function isVideoThumbnailDataValid (value) { 74function isVideoThumbnailDataValid (value: string) {
75 return validator.isByteLength(value, VIDEOS_CONSTRAINTS_FIELDS.THUMBNAIL_DATA) 75 return exists(value) && validator.isByteLength(value, VIDEOS_CONSTRAINTS_FIELDS.THUMBNAIL_DATA)
76} 76}
77 77
78function isVideoRemoteIdValid (value) { 78function isVideoRemoteIdValid (value: string) {
79 return validator.isUUID(value, 4) 79 return exists(value) && validator.isUUID(value, 4)
80} 80}
81 81
82function isVideoAbuseReasonValid (value) { 82function isVideoAbuseReasonValid (value: string) {
83 return validator.isLength(value, VIDEO_ABUSES_CONSTRAINTS_FIELDS.REASON) 83 return exists(value) && validator.isLength(value, VIDEO_ABUSES_CONSTRAINTS_FIELDS.REASON)
84} 84}
85 85
86function isVideoAbuseReporterUsernameValid (value) { 86function isVideoAbuseReporterUsernameValid (value: string) {
87 return isUserUsernameValid(value) 87 return isUserUsernameValid(value)
88} 88}
89 89
90function isVideoViewsValid (value) { 90function isVideoViewsValid (value: string) {
91 return validator.isInt(value + '', VIDEOS_CONSTRAINTS_FIELDS.VIEWS) 91 return exists(value) && validator.isInt(value + '', VIDEOS_CONSTRAINTS_FIELDS.VIEWS)
92} 92}
93 93
94function isVideoLikesValid (value) { 94function isVideoLikesValid (value: string) {
95 return validator.isInt(value + '', VIDEOS_CONSTRAINTS_FIELDS.LIKES) 95 return exists(value) && validator.isInt(value + '', VIDEOS_CONSTRAINTS_FIELDS.LIKES)
96} 96}
97 97
98function isVideoDislikesValid (value) { 98function isVideoDislikesValid (value: string) {
99 return validator.isInt(value + '', VIDEOS_CONSTRAINTS_FIELDS.DISLIKES) 99 return exists(value) && validator.isInt(value + '', VIDEOS_CONSTRAINTS_FIELDS.DISLIKES)
100} 100}
101 101
102function isVideoEventCountValid (value) { 102function isVideoEventCountValid (value: string) {
103 return validator.isInt(value + '', VIDEO_EVENTS_CONSTRAINTS_FIELDS.COUNT) 103 return exists(value) && validator.isInt(value + '', VIDEO_EVENTS_CONSTRAINTS_FIELDS.COUNT)
104} 104}
105 105
106function isVideoRatingTypeValid (value) { 106function isVideoRatingTypeValid (value: string) {
107 return values(VIDEO_RATE_TYPES).indexOf(value) !== -1 107 return values(VIDEO_RATE_TYPES).indexOf(value) !== -1
108} 108}
109 109
110function isVideoFile (value, files) { 110function isVideoFile (value: string, files: { [ fieldname: string ]: Express.Multer.File[] }) {
111 // Should have files 111 // Should have files
112 if (!files) return false 112 if (!files) return false
113 113
@@ -149,3 +149,33 @@ export {
149 isVideoDislikesValid, 149 isVideoDislikesValid,
150 isVideoEventCountValid 150 isVideoEventCountValid
151} 151}
152
153declare global {
154 namespace ExpressValidator {
155 export interface Validator {
156 isVideoAuthorValid,
157 isVideoDateValid,
158 isVideoCategoryValid,
159 isVideoLicenceValid,
160 isVideoLanguageValid,
161 isVideoNSFWValid,
162 isVideoDescriptionValid,
163 isVideoDurationValid,
164 isVideoInfoHashValid,
165 isVideoNameValid,
166 isVideoTagsValid,
167 isVideoThumbnailValid,
168 isVideoThumbnailDataValid,
169 isVideoExtnameValid,
170 isVideoRemoteIdValid,
171 isVideoAbuseReasonValid,
172 isVideoAbuseReporterUsernameValid,
173 isVideoFile,
174 isVideoViewsValid,
175 isVideoLikesValid,
176 isVideoRatingTypeValid,
177 isVideoDislikesValid,
178 isVideoEventCountValid
179 }
180 }
181}
diff --git a/server/helpers/database-utils.ts b/server/helpers/database-utils.ts
index 4f49c5825..f8ee9a454 100644
--- a/server/helpers/database-utils.ts
+++ b/server/helpers/database-utils.ts
@@ -1,14 +1,15 @@
1import * as Sequelize from 'sequelize'
1// TODO: import from ES6 when retry typing file will include errorFilter function 2// TODO: import from ES6 when retry typing file will include errorFilter function
2import * as retry from 'async/retry' 3import * as retry from 'async/retry'
3 4
4import { database as db } from '../initializers/database' 5import { database as db } from '../initializers/database'
5import { logger } from './logger' 6import { logger } from './logger'
6 7
7function commitTransaction (t, callback) { 8function commitTransaction (t: Sequelize.Transaction, callback: (err: Error) => void) {
8 return t.commit().asCallback(callback) 9 return t.commit().asCallback(callback)
9} 10}
10 11
11function rollbackTransaction (err, t, callback) { 12function rollbackTransaction (err: Error, t: Sequelize.Transaction, callback: (err: Error) => void) {
12 // Try to rollback transaction 13 // Try to rollback transaction
13 if (t) { 14 if (t) {
14 // Do not catch err, report the original one 15 // Do not catch err, report the original one
@@ -20,8 +21,8 @@ function rollbackTransaction (err, t, callback) {
20 } 21 }
21} 22}
22 23
23// { arguments, errorMessage } 24type RetryTransactionWrapperOptions = { errorMessage: string, arguments?: any[] }
24function retryTransactionWrapper (functionToRetry, options, finalCallback) { 25function retryTransactionWrapper (functionToRetry: Function, options: RetryTransactionWrapperOptions, finalCallback: Function) {
25 const args = options.arguments ? options.arguments : [] 26 const args = options.arguments ? options.arguments : []
26 27
27 transactionRetryer( 28 transactionRetryer(
@@ -39,7 +40,7 @@ function retryTransactionWrapper (functionToRetry, options, finalCallback) {
39 ) 40 )
40} 41}
41 42
42function transactionRetryer (func, callback) { 43function transactionRetryer (func: Function, callback: (err: Error) => void) {
43 retry({ 44 retry({
44 times: 5, 45 times: 5,
45 46
@@ -51,7 +52,7 @@ function transactionRetryer (func, callback) {
51 }, func, callback) 52 }, func, callback)
52} 53}
53 54
54function startSerializableTransaction (callback) { 55function startSerializableTransaction (callback: (err: Error, t: Sequelize.Transaction) => void) {
55 db.sequelize.transaction(/* { isolationLevel: 'SERIALIZABLE' } */).asCallback(function (err, t) { 56 db.sequelize.transaction(/* { isolationLevel: 'SERIALIZABLE' } */).asCallback(function (err, t) {
56 // We force to return only two parameters 57 // We force to return only two parameters
57 return callback(err, t) 58 return callback(err, t)
diff --git a/server/helpers/peertube-crypto.ts b/server/helpers/peertube-crypto.ts
index feb32a4cd..0ac875127 100644
--- a/server/helpers/peertube-crypto.ts
+++ b/server/helpers/peertube-crypto.ts
@@ -14,7 +14,7 @@ import {
14} from '../initializers' 14} from '../initializers'
15import { logger } from './logger' 15import { logger } from './logger'
16 16
17function checkSignature (publicKey, data, hexSignature) { 17function checkSignature (publicKey: string, data: string, hexSignature: string) {
18 const verify = crypto.createVerify(SIGNATURE_ALGORITHM) 18 const verify = crypto.createVerify(SIGNATURE_ALGORITHM)
19 19
20 let dataString 20 let dataString
@@ -35,10 +35,10 @@ function checkSignature (publicKey, data, hexSignature) {
35 return isValid 35 return isValid
36} 36}
37 37
38function sign (data) { 38function sign (data: string|Object) {
39 const sign = crypto.createSign(SIGNATURE_ALGORITHM) 39 const sign = crypto.createSign(SIGNATURE_ALGORITHM)
40 40
41 let dataString 41 let dataString: string
42 if (typeof data === 'string') { 42 if (typeof data === 'string') {
43 dataString = data 43 dataString = data
44 } else { 44 } else {
@@ -60,7 +60,7 @@ function sign (data) {
60 return signature 60 return signature
61} 61}
62 62
63function comparePassword (plainPassword, hashPassword, callback) { 63function comparePassword (plainPassword: string, hashPassword: string, callback: (err: Error, match?: boolean) => void) {
64 bcrypt.compare(plainPassword, hashPassword, function (err, isPasswordMatch) { 64 bcrypt.compare(plainPassword, hashPassword, function (err, isPasswordMatch) {
65 if (err) return callback(err) 65 if (err) return callback(err)
66 66
@@ -68,7 +68,7 @@ function comparePassword (plainPassword, hashPassword, callback) {
68 }) 68 })
69} 69}
70 70
71function createCertsIfNotExist (callback) { 71function createCertsIfNotExist (callback: (err: Error) => void) {
72 certsExist(function (err, exist) { 72 certsExist(function (err, exist) {
73 if (err) return callback(err) 73 if (err) return callback(err)
74 74
@@ -82,7 +82,7 @@ function createCertsIfNotExist (callback) {
82 }) 82 })
83} 83}
84 84
85function cryptPassword (password, callback) { 85function cryptPassword (password: string, callback: (err: Error, hash?: string) => void) {
86 bcrypt.genSalt(BCRYPT_SALT_SIZE, function (err, salt) { 86 bcrypt.genSalt(BCRYPT_SALT_SIZE, function (err, salt) {
87 if (err) return callback(err) 87 if (err) return callback(err)
88 88
@@ -92,12 +92,12 @@ function cryptPassword (password, callback) {
92 }) 92 })
93} 93}
94 94
95function getMyPrivateCert (callback) { 95function getMyPrivateCert (callback: (err: Error, privateCert: string) => void) {
96 const certPath = join(CONFIG.STORAGE.CERT_DIR, PRIVATE_CERT_NAME) 96 const certPath = join(CONFIG.STORAGE.CERT_DIR, PRIVATE_CERT_NAME)
97 fs.readFile(certPath, 'utf8', callback) 97 fs.readFile(certPath, 'utf8', callback)
98} 98}
99 99
100function getMyPublicCert (callback) { 100function getMyPublicCert (callback: (err: Error, publicCert: string) => void) {
101 const certPath = join(CONFIG.STORAGE.CERT_DIR, PUBLIC_CERT_NAME) 101 const certPath = join(CONFIG.STORAGE.CERT_DIR, PUBLIC_CERT_NAME)
102 fs.readFile(certPath, 'utf8', callback) 102 fs.readFile(certPath, 'utf8', callback)
103} 103}
@@ -116,7 +116,7 @@ export {
116 116
117// --------------------------------------------------------------------------- 117// ---------------------------------------------------------------------------
118 118
119function certsExist (callback) { 119function certsExist (callback: (err: Error, certsExist: boolean) => void) {
120 const certPath = join(CONFIG.STORAGE.CERT_DIR, PRIVATE_CERT_NAME) 120 const certPath = join(CONFIG.STORAGE.CERT_DIR, PRIVATE_CERT_NAME)
121 fs.access(certPath, function (err) { 121 fs.access(certPath, function (err) {
122 // If there is an error the certificates do not exist 122 // If there is an error the certificates do not exist
@@ -125,14 +125,14 @@ function certsExist (callback) {
125 }) 125 })
126} 126}
127 127
128function createCerts (callback) { 128function createCerts (callback: (err: Error) => void) {
129 certsExist(function (err, exist) { 129 certsExist(function (err, exist) {
130 if (err) return callback(err) 130 if (err) return callback(err)
131 131
132 if (exist === true) { 132 if (exist === true) {
133 const string = 'Certs already exist.' 133 const errorMessage = 'Certs already exist.'
134 logger.warning(string) 134 logger.warning(errorMessage)
135 return callback(new Error(string)) 135 return callback(new Error(errorMessage))
136 } 136 }
137 137
138 logger.info('Generating a RSA key...') 138 logger.info('Generating a RSA key...')
diff --git a/server/helpers/requests.ts b/server/helpers/requests.ts
index 48b1fd703..b40fc8e39 100644
--- a/server/helpers/requests.ts
+++ b/server/helpers/requests.ts
@@ -6,9 +6,15 @@ import {
6 REMOTE_SCHEME, 6 REMOTE_SCHEME,
7 CONFIG 7 CONFIG
8} from '../initializers' 8} from '../initializers'
9import { PodInstance } from '../models'
9import { sign } from './peertube-crypto' 10import { sign } from './peertube-crypto'
10 11
11function makeRetryRequest (params, callback) { 12type MakeRetryRequestParams = {
13 url: string,
14 method: 'GET'|'POST',
15 json: Object
16}
17function makeRetryRequest (params: MakeRetryRequestParams, callback: request.RequestCallback) {
12 replay( 18 replay(
13 request(params, callback), 19 request(params, callback),
14 { 20 {
@@ -20,14 +26,21 @@ function makeRetryRequest (params, callback) {
20 ) 26 )
21} 27}
22 28
23function makeSecureRequest (params, callback) { 29type MakeSecureRequestParams = {
30 method: 'GET'|'POST'
31 toPod: PodInstance
32 path: string
33 sign: boolean
34 data?: Object
35}
36function makeSecureRequest (params: MakeSecureRequestParams, callback: request.RequestCallback) {
24 const requestParams = { 37 const requestParams = {
25 url: REMOTE_SCHEME.HTTP + '://' + params.toPod.host + params.path, 38 url: REMOTE_SCHEME.HTTP + '://' + params.toPod.host + params.path,
26 json: {} 39 json: {}
27 } 40 }
28 41
29 if (params.method !== 'POST') { 42 if (params.method !== 'POST') {
30 return callback(new Error('Cannot make a secure request with a non POST method.')) 43 return callback(new Error('Cannot make a secure request with a non POST method.'), null, null)
31 } 44 }
32 45
33 // Add signature if it is specified in the params 46 // Add signature if it is specified in the params
diff --git a/server/helpers/utils.ts b/server/helpers/utils.ts
index bc76cfb26..1dcbd31c4 100644
--- a/server/helpers/utils.ts
+++ b/server/helpers/utils.ts
@@ -1,13 +1,15 @@
1import * as express from 'express'
2
1import { pseudoRandomBytes } from 'crypto' 3import { pseudoRandomBytes } from 'crypto'
2import { join } from 'path' 4import { join } from 'path'
3 5
4import { logger } from './logger' 6import { logger } from './logger'
5 7
6function badRequest (req, res, next) { 8function badRequest (req: express.Request, res: express.Response, next: express.NextFunction) {
7 res.type('json').status(400).end() 9 res.type('json').status(400).end()
8} 10}
9 11
10function generateRandomString (size, callback) { 12function generateRandomString (size: number, callback: (err: Error, randomString?: string) => void) {
11 pseudoRandomBytes(size, function (err, raw) { 13 pseudoRandomBytes(size, function (err, raw) {
12 if (err) return callback(err) 14 if (err) return callback(err)
13 15
@@ -15,11 +17,6 @@ function generateRandomString (size, callback) {
15 }) 17 })
16} 18}
17 19
18function cleanForExit (webtorrentProcess) {
19 logger.info('Gracefully exiting.')
20 process.kill(-webtorrentProcess.pid)
21}
22
23function createEmptyCallback () { 20function createEmptyCallback () {
24 return function (err) { 21 return function (err) {
25 if (err) logger.error('Error in empty callback.', { error: err }) 22 if (err) logger.error('Error in empty callback.', { error: err })
@@ -27,10 +24,10 @@ function createEmptyCallback () {
27} 24}
28 25
29function isTestInstance () { 26function isTestInstance () {
30 return (process.env.NODE_ENV === 'test') 27 return process.env.NODE_ENV === 'test'
31} 28}
32 29
33function getFormatedObjects (objects, objectsTotal) { 30function getFormatedObjects (objects: any[], objectsTotal: number) {
34 const formatedObjects = [] 31 const formatedObjects = []
35 32
36 objects.forEach(function (object) { 33 objects.forEach(function (object) {
@@ -53,7 +50,6 @@ function root () {
53export { 50export {
54 badRequest, 51 badRequest,
55 createEmptyCallback, 52 createEmptyCallback,
56 cleanForExit,
57 generateRandomString, 53 generateRandomString,
58 isTestInstance, 54 isTestInstance,
59 getFormatedObjects, 55 getFormatedObjects,
diff --git a/server/initializers/checker.ts b/server/initializers/checker.ts
index 8c3d64b60..7007f2c0b 100644
--- a/server/initializers/checker.ts
+++ b/server/initializers/checker.ts
@@ -23,7 +23,7 @@ function checkMissedConfig () {
23 'storage.certs', 'storage.videos', 'storage.logs', 'storage.thumbnails', 'storage.previews', 23 'storage.certs', 'storage.videos', 'storage.logs', 'storage.thumbnails', 'storage.previews',
24 'admin.email', 'signup.enabled', 'transcoding.enabled', 'transcoding.threads' 24 'admin.email', 'signup.enabled', 'transcoding.enabled', 'transcoding.threads'
25 ] 25 ]
26 const miss = [] 26 const miss: string[] = []
27 27
28 for (const key of required) { 28 for (const key of required) {
29 if (!config.has(key)) { 29 if (!config.has(key)) {
@@ -35,7 +35,7 @@ function checkMissedConfig () {
35} 35}
36 36
37// Check the available codecs 37// Check the available codecs
38function checkFFmpeg (callback) { 38function checkFFmpeg (callback: (err: Error) => void) {
39 const Ffmpeg = require('fluent-ffmpeg') 39 const Ffmpeg = require('fluent-ffmpeg')
40 40
41 Ffmpeg.getAvailableCodecs(function (err, codecs) { 41 Ffmpeg.getAvailableCodecs(function (err, codecs) {
@@ -57,7 +57,7 @@ function checkFFmpeg (callback) {
57 }) 57 })
58} 58}
59 59
60function clientsExist (callback) { 60function clientsExist (callback: (err: Error, clientsExist?: boolean) => void) {
61 db.OAuthClient.countTotal(function (err, totalClients) { 61 db.OAuthClient.countTotal(function (err, totalClients) {
62 if (err) return callback(err) 62 if (err) return callback(err)
63 63
@@ -65,7 +65,7 @@ function clientsExist (callback) {
65 }) 65 })
66} 66}
67 67
68function usersExist (callback) { 68function usersExist (callback: (err: Error, usersExist?: boolean) => void) {
69 db.User.countTotal(function (err, totalUsers) { 69 db.User.countTotal(function (err, totalUsers) {
70 if (err) return callback(err) 70 if (err) return callback(err)
71 71
diff --git a/server/initializers/constants.ts b/server/initializers/constants.ts
index 7ab019f44..6dcb4bb91 100644
--- a/server/initializers/constants.ts
+++ b/server/initializers/constants.ts
@@ -202,7 +202,7 @@ const REQUEST_ENDPOINTS = {
202 VIDEOS: 'videos' 202 VIDEOS: 'videos'
203} 203}
204 204
205const REQUEST_ENDPOINT_ACTIONS = {} 205const REQUEST_ENDPOINT_ACTIONS: { [ id: string ]: any } = {}
206REQUEST_ENDPOINT_ACTIONS[REQUEST_ENDPOINTS.VIDEOS] = { 206REQUEST_ENDPOINT_ACTIONS[REQUEST_ENDPOINTS.VIDEOS] = {
207 ADD: 'add', 207 ADD: 'add',
208 UPDATE: 'update', 208 UPDATE: 'update',
diff --git a/server/initializers/database.ts b/server/initializers/database.ts
index b0f47876e..78ca5ab84 100644
--- a/server/initializers/database.ts
+++ b/server/initializers/database.ts
@@ -59,7 +59,7 @@ const sequelize = new Sequelize(dbname, username, password, {
59 port: CONFIG.DATABASE.PORT, 59 port: CONFIG.DATABASE.PORT,
60 benchmark: isTestInstance(), 60 benchmark: isTestInstance(),
61 61
62 logging: function (message, benchmark) { 62 logging: function (message: string, benchmark: number) {
63 let newMessage = message 63 let newMessage = message
64 if (benchmark !== undefined) { 64 if (benchmark !== undefined) {
65 newMessage += ' | ' + benchmark + 'ms' 65 newMessage += ' | ' + benchmark + 'ms'
@@ -71,7 +71,7 @@ const sequelize = new Sequelize(dbname, username, password, {
71 71
72database.sequelize = sequelize 72database.sequelize = sequelize
73 73
74database.init = function (silent, callback) { 74database.init = function (silent: boolean, callback: (err: Error) => void) {
75 75
76 const modelDirectory = join(__dirname, '..', 'models') 76 const modelDirectory = join(__dirname, '..', 'models')
77 fs.readdir(modelDirectory, function (err, files) { 77 fs.readdir(modelDirectory, function (err, files) {
diff --git a/server/initializers/installer.ts b/server/initializers/installer.ts
index 2f9b58991..f105c8292 100644
--- a/server/initializers/installer.ts
+++ b/server/initializers/installer.ts
@@ -9,7 +9,7 @@ import { USER_ROLES, CONFIG, LAST_MIGRATION_VERSION } from './constants'
9import { clientsExist, usersExist } from './checker' 9import { clientsExist, usersExist } from './checker'
10import { logger, createCertsIfNotExist, root } from '../helpers' 10import { logger, createCertsIfNotExist, root } from '../helpers'
11 11
12function installApplication (callback) { 12function installApplication (callback: (err: Error) => void) {
13 series([ 13 series([
14 function createDatabase (callbackAsync) { 14 function createDatabase (callbackAsync) {
15 db.sequelize.sync().asCallback(callbackAsync) 15 db.sequelize.sync().asCallback(callbackAsync)
@@ -42,7 +42,7 @@ export {
42 42
43// --------------------------------------------------------------------------- 43// ---------------------------------------------------------------------------
44 44
45function createDirectoriesIfNotExist (callback) { 45function createDirectoriesIfNotExist (callback: (err: Error) => void) {
46 const storages = config.get('storage') 46 const storages = config.get('storage')
47 47
48 each(Object.keys(storages), function (key, callbackEach) { 48 each(Object.keys(storages), function (key, callbackEach) {
@@ -51,7 +51,7 @@ function createDirectoriesIfNotExist (callback) {
51 }, callback) 51 }, callback)
52} 52}
53 53
54function createOAuthClientIfNotExist (callback) { 54function createOAuthClientIfNotExist (callback: (err: Error) => void) {
55 clientsExist(function (err, exist) { 55 clientsExist(function (err, exist) {
56 if (err) return callback(err) 56 if (err) return callback(err)
57 57
@@ -80,7 +80,7 @@ function createOAuthClientIfNotExist (callback) {
80 }) 80 })
81} 81}
82 82
83function createOAuthAdminIfNotExist (callback) { 83function createOAuthAdminIfNotExist (callback: (err: Error) => void) {
84 usersExist(function (err, exist) { 84 usersExist(function (err, exist) {
85 if (err) return callback(err) 85 if (err) return callback(err)
86 86
diff --git a/server/initializers/migrator.ts b/server/initializers/migrator.ts
index 379d43af5..d72c60638 100644
--- a/server/initializers/migrator.ts
+++ b/server/initializers/migrator.ts
@@ -8,7 +8,7 @@ import { LAST_MIGRATION_VERSION } from './constants'
8import { logger } from '../helpers' 8import { logger } from '../helpers'
9import { ApplicationInstance } from '../models' 9import { ApplicationInstance } from '../models'
10 10
11function migrate (finalCallback) { 11function migrate (finalCallback: (err: Error) => void) {
12 waterfall([ 12 waterfall([
13 13
14 function checkApplicationTableExists (callback) { 14 function checkApplicationTableExists (callback) {
@@ -56,7 +56,7 @@ function migrate (finalCallback) {
56 }, 56 },
57 57
58 function doMigrations (actualVersion, migrationScripts, callback) { 58 function doMigrations (actualVersion, migrationScripts, callback) {
59 eachSeries(migrationScripts, function (entity, callbackEach) { 59 eachSeries(migrationScripts, function (entity: any, callbackEach) {
60 executeMigration(actualVersion, entity, callbackEach) 60 executeMigration(actualVersion, entity, callbackEach)
61 }, function (err) { 61 }, function (err) {
62 if (err) return callback(err) 62 if (err) return callback(err)
@@ -76,7 +76,8 @@ export {
76 76
77// --------------------------------------------------------------------------- 77// ---------------------------------------------------------------------------
78 78
79function getMigrationScripts (callback) { 79type GetMigrationScriptsCallback = (err: Error, filesToMigrate?: { version: string, script: string }[]) => void
80function getMigrationScripts (callback: GetMigrationScriptsCallback) {
80 fs.readdir(path.join(__dirname, 'migrations'), function (err, files) { 81 fs.readdir(path.join(__dirname, 'migrations'), function (err, files) {
81 if (err) return callback(err) 82 if (err) return callback(err)
82 83
@@ -95,7 +96,7 @@ function getMigrationScripts (callback) {
95 }) 96 })
96} 97}
97 98
98function executeMigration (actualVersion, entity, callback) { 99function executeMigration (actualVersion: number, entity: { version: string, script: string }, callback: (err: Error) => void) {
99 const versionScript = parseInt(entity.version, 10) 100 const versionScript = parseInt(entity.version, 10)
100 101
101 // Do not execute old migration scripts 102 // Do not execute old migration scripts
diff --git a/server/lib/friends.ts b/server/lib/friends.ts
index 6b0fbd2bf..e097f9254 100644
--- a/server/lib/friends.ts
+++ b/server/lib/friends.ts
@@ -1,5 +1,6 @@
1import { each, eachLimit, eachSeries, series, waterfall } from 'async' 1import { each, eachLimit, eachSeries, series, waterfall } from 'async'
2import * as request from 'request' 2import * as request from 'request'
3import * as Sequelize from 'sequelize'
3 4
4import { database as db } from '../initializers/database' 5import { database as db } from '../initializers/database'
5import { 6import {
@@ -19,9 +20,18 @@ import {
19} from '../helpers' 20} from '../helpers'
20import { 21import {
21 RequestScheduler, 22 RequestScheduler,
23 RequestSchedulerOptions,
24
22 RequestVideoQaduScheduler, 25 RequestVideoQaduScheduler,
23 RequestVideoEventScheduler 26 RequestVideoQaduSchedulerOptions,
27
28 RequestVideoEventScheduler,
29 RequestVideoEventSchedulerOptions
24} from './request' 30} from './request'
31import { PodInstance, VideoInstance } from '../models'
32
33type QaduParam = { videoId: string, type: string }
34type EventParam = { videoId: string, type: string }
25 35
26const ENDPOINT_ACTIONS = REQUEST_ENDPOINT_ACTIONS[REQUEST_ENDPOINTS.VIDEOS] 36const ENDPOINT_ACTIONS = REQUEST_ENDPOINT_ACTIONS[REQUEST_ENDPOINTS.VIDEOS]
27 37
@@ -35,7 +45,7 @@ function activateSchedulers () {
35 requestVideoEventScheduler.activate() 45 requestVideoEventScheduler.activate()
36} 46}
37 47
38function addVideoToFriends (videoData, transaction, callback) { 48function addVideoToFriends (videoData: Object, transaction: Sequelize.Transaction, callback: (err: Error) => void) {
39 const options = { 49 const options = {
40 type: ENDPOINT_ACTIONS.ADD, 50 type: ENDPOINT_ACTIONS.ADD,
41 endpoint: REQUEST_ENDPOINTS.VIDEOS, 51 endpoint: REQUEST_ENDPOINTS.VIDEOS,
@@ -45,7 +55,7 @@ function addVideoToFriends (videoData, transaction, callback) {
45 createRequest(options, callback) 55 createRequest(options, callback)
46} 56}
47 57
48function updateVideoToFriends (videoData, transaction, callback) { 58function updateVideoToFriends (videoData: Object, transaction: Sequelize.Transaction, callback: (err: Error) => void) {
49 const options = { 59 const options = {
50 type: ENDPOINT_ACTIONS.UPDATE, 60 type: ENDPOINT_ACTIONS.UPDATE,
51 endpoint: REQUEST_ENDPOINTS.VIDEOS, 61 endpoint: REQUEST_ENDPOINTS.VIDEOS,
@@ -55,35 +65,37 @@ function updateVideoToFriends (videoData, transaction, callback) {
55 createRequest(options, callback) 65 createRequest(options, callback)
56} 66}
57 67
58function removeVideoToFriends (videoParams) { 68function removeVideoToFriends (videoParams: Object) {
59 const options = { 69 const options = {
60 type: ENDPOINT_ACTIONS.REMOVE, 70 type: ENDPOINT_ACTIONS.REMOVE,
61 endpoint: REQUEST_ENDPOINTS.VIDEOS, 71 endpoint: REQUEST_ENDPOINTS.VIDEOS,
62 data: videoParams 72 data: videoParams,
73 transaction: null
63 } 74 }
64 createRequest(options) 75 createRequest(options)
65} 76}
66 77
67function reportAbuseVideoToFriend (reportData, video) { 78function reportAbuseVideoToFriend (reportData: Object, video: VideoInstance) {
68 const options = { 79 const options = {
69 type: ENDPOINT_ACTIONS.REPORT_ABUSE, 80 type: ENDPOINT_ACTIONS.REPORT_ABUSE,
70 endpoint: REQUEST_ENDPOINTS.VIDEOS, 81 endpoint: REQUEST_ENDPOINTS.VIDEOS,
71 data: reportData, 82 data: reportData,
72 toIds: [ video.Author.podId ] 83 toIds: [ video.Author.podId ],
84 transaction: null
73 } 85 }
74 createRequest(options) 86 createRequest(options)
75} 87}
76 88
77function quickAndDirtyUpdateVideoToFriends (qaduParams, transaction?, callback?) { 89function quickAndDirtyUpdateVideoToFriends (qaduParam: QaduParam, transaction?: Sequelize.Transaction, callback?: (err: Error) => void) {
78 const options = { 90 const options = {
79 videoId: qaduParams.videoId, 91 videoId: qaduParam.videoId,
80 type: qaduParams.type, 92 type: qaduParam.type,
81 transaction 93 transaction
82 } 94 }
83 return createVideoQaduRequest(options, callback) 95 return createVideoQaduRequest(options, callback)
84} 96}
85 97
86function quickAndDirtyUpdatesVideoToFriends (qadusParams, transaction, finalCallback) { 98function quickAndDirtyUpdatesVideoToFriends (qadusParams: QaduParam[], transaction: Sequelize.Transaction, finalCallback: (err: Error) => void) {
87 const tasks = [] 99 const tasks = []
88 100
89 qadusParams.forEach(function (qaduParams) { 101 qadusParams.forEach(function (qaduParams) {
@@ -97,16 +109,16 @@ function quickAndDirtyUpdatesVideoToFriends (qadusParams, transaction, finalCall
97 series(tasks, finalCallback) 109 series(tasks, finalCallback)
98} 110}
99 111
100function addEventToRemoteVideo (eventParams, transaction?, callback?) { 112function addEventToRemoteVideo (eventParam: EventParam, transaction?: Sequelize.Transaction, callback?: (err: Error) => void) {
101 const options = { 113 const options = {
102 videoId: eventParams.videoId, 114 videoId: eventParam.videoId,
103 type: eventParams.type, 115 type: eventParam.type,
104 transaction 116 transaction
105 } 117 }
106 createVideoEventRequest(options, callback) 118 createVideoEventRequest(options, callback)
107} 119}
108 120
109function addEventsToRemoteVideo (eventsParams, transaction, finalCallback) { 121function addEventsToRemoteVideo (eventsParams: EventParam[], transaction: Sequelize.Transaction, finalCallback: (err: Error) => void) {
110 const tasks = [] 122 const tasks = []
111 123
112 eventsParams.forEach(function (eventParams) { 124 eventsParams.forEach(function (eventParams) {
@@ -120,7 +132,7 @@ function addEventsToRemoteVideo (eventsParams, transaction, finalCallback) {
120 series(tasks, finalCallback) 132 series(tasks, finalCallback)
121} 133}
122 134
123function hasFriends (callback) { 135function hasFriends (callback: (err: Error, hasFriends?: boolean) => void) {
124 db.Pod.countAll(function (err, count) { 136 db.Pod.countAll(function (err, count) {
125 if (err) return callback(err) 137 if (err) return callback(err)
126 138
@@ -129,7 +141,7 @@ function hasFriends (callback) {
129 }) 141 })
130} 142}
131 143
132function makeFriends (hosts, callback) { 144function makeFriends (hosts: string[], callback: (err: Error) => void) {
133 const podsScore = {} 145 const podsScore = {}
134 146
135 logger.info('Make friends!') 147 logger.info('Make friends!')
@@ -141,7 +153,7 @@ function makeFriends (hosts, callback) {
141 153
142 eachSeries(hosts, function (host, callbackEach) { 154 eachSeries(hosts, function (host, callbackEach) {
143 computeForeignPodsList(host, podsScore, callbackEach) 155 computeForeignPodsList(host, podsScore, callbackEach)
144 }, function (err) { 156 }, function (err: Error) {
145 if (err) return callback(err) 157 if (err) return callback(err)
146 158
147 logger.debug('Pods scores computed.', { podsScore: podsScore }) 159 logger.debug('Pods scores computed.', { podsScore: podsScore })
@@ -153,7 +165,7 @@ function makeFriends (hosts, callback) {
153 }) 165 })
154} 166}
155 167
156function quitFriends (callback) { 168function quitFriends (callback: (err: Error) => void) {
157 // Stop pool requests 169 // Stop pool requests
158 requestScheduler.deactivate() 170 requestScheduler.deactivate()
159 171
@@ -172,7 +184,7 @@ function quitFriends (callback) {
172 184
173 function announceIQuitMyFriends (pods, callbackAsync) { 185 function announceIQuitMyFriends (pods, callbackAsync) {
174 const requestParams = { 186 const requestParams = {
175 method: 'POST', 187 method: 'POST' as 'POST',
176 path: '/api/' + API_VERSION + '/remote/pods/remove', 188 path: '/api/' + API_VERSION + '/remote/pods/remove',
177 sign: true, 189 sign: true,
178 toPod: null 190 toPod: null
@@ -199,7 +211,7 @@ function quitFriends (callback) {
199 pod.destroy().asCallback(callbackEach) 211 pod.destroy().asCallback(callbackEach)
200 }, callbackAsync) 212 }, callbackAsync)
201 } 213 }
202 ], function (err) { 214 ], function (err: Error) {
203 // Don't forget to re activate the scheduler, even if there was an error 215 // Don't forget to re activate the scheduler, even if there was an error
204 requestScheduler.activate() 216 requestScheduler.activate()
205 217
@@ -210,7 +222,7 @@ function quitFriends (callback) {
210 }) 222 })
211} 223}
212 224
213function sendOwnedVideosToPod (podId) { 225function sendOwnedVideosToPod (podId: number) {
214 db.Video.listOwnedAndPopulateAuthorAndTags(function (err, videosList) { 226 db.Video.listOwnedAndPopulateAuthorAndTags(function (err, videosList) {
215 if (err) { 227 if (err) {
216 logger.error('Cannot get the list of videos we own.') 228 logger.error('Cannot get the list of videos we own.')
@@ -229,7 +241,8 @@ function sendOwnedVideosToPod (podId) {
229 type: 'add', 241 type: 'add',
230 endpoint: REQUEST_ENDPOINTS.VIDEOS, 242 endpoint: REQUEST_ENDPOINTS.VIDEOS,
231 data: remoteVideo, 243 data: remoteVideo,
232 toIds: [ podId ] 244 toIds: [ podId ],
245 transaction: null
233 } 246 }
234 createRequest(options) 247 createRequest(options)
235 }) 248 })
@@ -272,7 +285,7 @@ export {
272 285
273// --------------------------------------------------------------------------- 286// ---------------------------------------------------------------------------
274 287
275function computeForeignPodsList (host, podsScore, callback) { 288function computeForeignPodsList (host: string, podsScore: { [ host: string ]: number }, callback: (err: Error) => void) {
276 getForeignPodsList(host, function (err, res) { 289 getForeignPodsList(host, function (err, res) {
277 if (err) return callback(err) 290 if (err) return callback(err)
278 291
@@ -288,11 +301,11 @@ function computeForeignPodsList (host, podsScore, callback) {
288 else podsScore[foreignPodHost] = 1 301 else podsScore[foreignPodHost] = 1
289 }) 302 })
290 303
291 return callback() 304 return callback(null)
292 }) 305 })
293} 306}
294 307
295function computeWinningPods (hosts, podsScore) { 308function computeWinningPods (hosts: string[], podsScore: { [ host: string ]: number }) {
296 // Build the list of pods to add 309 // Build the list of pods to add
297 // Only add a pod if it exists in more than a half base pods 310 // Only add a pod if it exists in more than a half base pods
298 const podsList = [] 311 const podsList = []
@@ -308,7 +321,7 @@ function computeWinningPods (hosts, podsScore) {
308 return podsList 321 return podsList
309} 322}
310 323
311function getForeignPodsList (host, callback) { 324function getForeignPodsList (host: string, callback: (err: Error, foreignPodsList?: any) => void) {
312 const path = '/api/' + API_VERSION + '/pods' 325 const path = '/api/' + API_VERSION + '/pods'
313 326
314 request.get(REMOTE_SCHEME.HTTP + '://' + host + path, function (err, response, body) { 327 request.get(REMOTE_SCHEME.HTTP + '://' + host + path, function (err, response, body) {
@@ -323,16 +336,16 @@ function getForeignPodsList (host, callback) {
323 }) 336 })
324} 337}
325 338
326function makeRequestsToWinningPods (cert, podsList, callback) { 339function makeRequestsToWinningPods (cert: string, podsList: PodInstance[], callback: (err: Error) => void) {
327 // Stop pool requests 340 // Stop pool requests
328 requestScheduler.deactivate() 341 requestScheduler.deactivate()
329 // Flush pool requests 342 // Flush pool requests
330 requestScheduler.forceSend() 343 requestScheduler.forceSend()
331 344
332 eachLimit(podsList, REQUESTS_IN_PARALLEL, function (pod: { host: string }, callbackEach) { 345 eachLimit(podsList, REQUESTS_IN_PARALLEL, function (pod: PodInstance, callbackEach) {
333 const params = { 346 const params = {
334 url: REMOTE_SCHEME.HTTP + '://' + pod.host + '/api/' + API_VERSION + '/pods/', 347 url: REMOTE_SCHEME.HTTP + '://' + pod.host + '/api/' + API_VERSION + '/pods/',
335 method: 'POST', 348 method: 'POST' as 'POST',
336 json: { 349 json: {
337 host: CONFIG.WEBSERVER.HOST, 350 host: CONFIG.WEBSERVER.HOST,
338 email: CONFIG.ADMIN.EMAIL, 351 email: CONFIG.ADMIN.EMAIL,
@@ -371,15 +384,22 @@ function makeRequestsToWinningPods (cert, podsList, callback) {
371 requestScheduler.activate() 384 requestScheduler.activate()
372 385
373 logger.debug('makeRequestsToWinningPods finished.') 386 logger.debug('makeRequestsToWinningPods finished.')
374 return callback() 387 return callback(null)
375 }) 388 })
376} 389}
377 390
378// Wrapper that populate "toIds" argument with all our friends if it is not specified 391// Wrapper that populate "toIds" argument with all our friends if it is not specified
379// { type, endpoint, data, toIds, transaction } 392type CreateRequestOptions = {
380function createRequest (options, callback?) { 393 type: string
394 endpoint: string
395 data: Object
396 toIds?: number[]
397 transaction: Sequelize.Transaction
398}
399function createRequest (options: CreateRequestOptions, callback?: (err: Error) => void) {
381 if (!callback) callback = function () { /* empty */ } 400 if (!callback) callback = function () { /* empty */ }
382 if (options.toIds) return requestScheduler.createRequest(options, callback) 401
402 if (options.toIds !== undefined) return requestScheduler.createRequest(options as RequestSchedulerOptions, callback)
383 403
384 // If the "toIds" pods is not specified, we send the request to all our friends 404 // If the "toIds" pods is not specified, we send the request to all our friends
385 db.Pod.listAllIds(options.transaction, function (err, podIds) { 405 db.Pod.listAllIds(options.transaction, function (err, podIds) {
@@ -393,18 +413,18 @@ function createRequest (options, callback?) {
393 }) 413 })
394} 414}
395 415
396function createVideoQaduRequest (options, callback) { 416function createVideoQaduRequest (options: RequestVideoQaduSchedulerOptions, callback: (err: Error) => void) {
397 if (!callback) callback = createEmptyCallback() 417 if (!callback) callback = createEmptyCallback()
398 418
399 requestVideoQaduScheduler.createRequest(options, callback) 419 requestVideoQaduScheduler.createRequest(options, callback)
400} 420}
401 421
402function createVideoEventRequest (options, callback) { 422function createVideoEventRequest (options: RequestVideoEventSchedulerOptions, callback: (err: Error) => void) {
403 if (!callback) callback = createEmptyCallback() 423 if (!callback) callback = createEmptyCallback()
404 424
405 requestVideoEventScheduler.createRequest(options, callback) 425 requestVideoEventScheduler.createRequest(options, callback)
406} 426}
407 427
408function isMe (host) { 428function isMe (host: string) {
409 return host === CONFIG.WEBSERVER.HOST 429 return host === CONFIG.WEBSERVER.HOST
410} 430}
diff --git a/server/lib/jobs/handlers/index.ts b/server/lib/jobs/handlers/index.ts
index ae5440031..7d0263b15 100644
--- a/server/lib/jobs/handlers/index.ts
+++ b/server/lib/jobs/handlers/index.ts
@@ -1,6 +1,14 @@
1import * as videoTranscoder from './video-transcoder' 1import * as videoTranscoder from './video-transcoder'
2 2
3const jobHandlers = { 3import { VideoInstance } from '../../../models'
4
5export interface JobHandler<T> {
6 process (data: object, callback: (err: Error, videoInstance?: T) => void)
7 onError (err: Error, jobId: number, video: T, callback: (err: Error) => void)
8 onSuccess (data: any, jobId: number, video: T, callback: (err: Error) => void)
9}
10
11const jobHandlers: { [ handlerName: string ]: JobHandler<any> } = {
4 videoTranscoder 12 videoTranscoder
5} 13}
6 14
diff --git a/server/lib/jobs/handlers/video-transcoder.ts b/server/lib/jobs/handlers/video-transcoder.ts
index 43599356a..efa18ef2d 100644
--- a/server/lib/jobs/handlers/video-transcoder.ts
+++ b/server/lib/jobs/handlers/video-transcoder.ts
@@ -1,8 +1,9 @@
1import { database as db } from '../../../initializers/database' 1import { database as db } from '../../../initializers/database'
2import { logger } from '../../../helpers' 2import { logger } from '../../../helpers'
3import { addVideoToFriends } from '../../../lib' 3import { addVideoToFriends } from '../../../lib'
4import { VideoInstance } from '../../../models'
4 5
5function process (data, callback) { 6function process (data: { id: string }, callback: (err: Error, videoInstance?: VideoInstance) => void) {
6 db.Video.loadAndPopulateAuthorAndPodAndTags(data.id, function (err, video) { 7 db.Video.loadAndPopulateAuthorAndPodAndTags(data.id, function (err, video) {
7 if (err) return callback(err) 8 if (err) return callback(err)
8 9
@@ -12,12 +13,12 @@ function process (data, callback) {
12 }) 13 })
13} 14}
14 15
15function onError (err, jobId, video, callback) { 16function onError (err: Error, jobId: number, video: VideoInstance, callback: () => void) {
16 logger.error('Error when transcoding video file in job %d.', jobId, { error: err }) 17 logger.error('Error when transcoding video file in job %d.', jobId, { error: err })
17 return callback() 18 return callback()
18} 19}
19 20
20function onSuccess (data, jobId, video, callback) { 21function onSuccess (data: any, jobId: number, video: VideoInstance, callback: (err: Error) => void) {
21 logger.info('Job %d is a success.', jobId) 22 logger.info('Job %d is a success.', jobId)
22 23
23 video.toAddRemoteJSON(function (err, remoteVideo) { 24 video.toAddRemoteJSON(function (err, remoteVideo) {
diff --git a/server/lib/jobs/job-scheduler.ts b/server/lib/jobs/job-scheduler.ts
index ad5f7f6d9..2f01387e7 100644
--- a/server/lib/jobs/job-scheduler.ts
+++ b/server/lib/jobs/job-scheduler.ts
@@ -1,4 +1,5 @@
1import { forever, queue } from 'async' 1import { forever, queue } from 'async'
2import * as Sequelize from 'sequelize'
2 3
3import { database as db } from '../../initializers/database' 4import { database as db } from '../../initializers/database'
4import { 5import {
@@ -7,7 +8,10 @@ import {
7 JOB_STATES 8 JOB_STATES
8} from '../../initializers' 9} from '../../initializers'
9import { logger } from '../../helpers' 10import { logger } from '../../helpers'
10import { jobHandlers } from './handlers' 11import { JobInstance } from '../../models'
12import { JobHandler, jobHandlers } from './handlers'
13
14type JobQueueCallback = (err: Error) => void
11 15
12class JobScheduler { 16class JobScheduler {
13 17
@@ -24,7 +28,7 @@ class JobScheduler {
24 28
25 logger.info('Jobs scheduler activated.') 29 logger.info('Jobs scheduler activated.')
26 30
27 const jobsQueue = queue(this.processJob.bind(this)) 31 const jobsQueue = queue<JobInstance, JobQueueCallback>(this.processJob.bind(this))
28 32
29 // Finish processing jobs from a previous start 33 // Finish processing jobs from a previous start
30 const state = JOB_STATES.PROCESSING 34 const state = JOB_STATES.PROCESSING
@@ -58,7 +62,7 @@ class JobScheduler {
58 }) 62 })
59 } 63 }
60 64
61 createJob (transaction, handlerName: string, handlerInputData: object, callback) { 65 createJob (transaction: Sequelize.Transaction, handlerName: string, handlerInputData: object, callback: (err: Error) => void) {
62 const createQuery = { 66 const createQuery = {
63 state: JOB_STATES.PENDING, 67 state: JOB_STATES.PENDING,
64 handlerName, 68 handlerName,
@@ -69,7 +73,7 @@ class JobScheduler {
69 db.Job.create(createQuery, options).asCallback(callback) 73 db.Job.create(createQuery, options).asCallback(callback)
70 } 74 }
71 75
72 private enqueueJobs (err, jobsQueue, jobs) { 76 private enqueueJobs (err: Error, jobsQueue: AsyncQueue<JobInstance>, jobs: JobInstance[]) {
73 if (err) { 77 if (err) {
74 logger.error('Cannot list pending jobs.', { error: err }) 78 logger.error('Cannot list pending jobs.', { error: err })
75 } else { 79 } else {
@@ -79,7 +83,7 @@ class JobScheduler {
79 } 83 }
80 } 84 }
81 85
82 private processJob (job, callback) { 86 private processJob (job: JobInstance, callback: (err: Error) => void) {
83 const jobHandler = jobHandlers[job.handlerName] 87 const jobHandler = jobHandlers[job.handlerName]
84 88
85 logger.info('Processing job %d with handler %s.', job.id, job.handlerName) 89 logger.info('Processing job %d with handler %s.', job.id, job.handlerName)
@@ -89,8 +93,8 @@ class JobScheduler {
89 if (err) return this.cannotSaveJobError(err, callback) 93 if (err) return this.cannotSaveJobError(err, callback)
90 94
91 if (jobHandler === undefined) { 95 if (jobHandler === undefined) {
92 logger.error('Unknown job handler for job %s.', jobHandler.handlerName) 96 logger.error('Unknown job handler for job %s.', job.handlerName)
93 return callback() 97 return callback(null)
94 } 98 }
95 99
96 return jobHandler.process(job.handlerInputData, (err, result) => { 100 return jobHandler.process(job.handlerInputData, (err, result) => {
@@ -104,7 +108,7 @@ class JobScheduler {
104 }) 108 })
105 } 109 }
106 110
107 private onJobError (jobHandler, job, jobResult, callback) { 111 private onJobError (jobHandler: JobHandler<any>, job: JobInstance, jobResult: any, callback: (err: Error) => void) {
108 job.state = JOB_STATES.ERROR 112 job.state = JOB_STATES.ERROR
109 113
110 job.save().asCallback(err => { 114 job.save().asCallback(err => {
@@ -114,7 +118,7 @@ class JobScheduler {
114 }) 118 })
115 } 119 }
116 120
117 private onJobSuccess (jobHandler, job, jobResult, callback) { 121 private onJobSuccess (jobHandler: JobHandler<any>, job: JobInstance, jobResult: any, callback: (err: Error) => void) {
118 job.state = JOB_STATES.SUCCESS 122 job.state = JOB_STATES.SUCCESS
119 123
120 job.save().asCallback(err => { 124 job.save().asCallback(err => {
@@ -124,7 +128,7 @@ class JobScheduler {
124 }) 128 })
125 } 129 }
126 130
127 private cannotSaveJobError (err, callback) { 131 private cannotSaveJobError (err: Error, callback: (err: Error) => void) {
128 logger.error('Cannot save new job state.', { error: err }) 132 logger.error('Cannot save new job state.', { error: err })
129 return callback(err) 133 return callback(err)
130 } 134 }
diff --git a/server/lib/oauth-model.ts b/server/lib/oauth-model.ts
index 3bdf0f478..7cf42e94c 100644
--- a/server/lib/oauth-model.ts
+++ b/server/lib/oauth-model.ts
@@ -1,27 +1,30 @@
1import { OAuthClientInstance, UserInstance } from '../models'
1import { database as db } from '../initializers/database' 2import { database as db } from '../initializers/database'
2import { logger } from '../helpers' 3import { logger } from '../helpers'
3 4
5type TokenInfo = { accessToken: string, refreshToken: string, accessTokenExpiresAt: Date, refreshTokenExpiresAt: Date }
6
4// --------------------------------------------------------------------------- 7// ---------------------------------------------------------------------------
5 8
6function getAccessToken (bearerToken) { 9function getAccessToken (bearerToken: string) {
7 logger.debug('Getting access token (bearerToken: ' + bearerToken + ').') 10 logger.debug('Getting access token (bearerToken: ' + bearerToken + ').')
8 11
9 return db.OAuthToken.getByTokenAndPopulateUser(bearerToken) 12 return db.OAuthToken.getByTokenAndPopulateUser(bearerToken)
10} 13}
11 14
12function getClient (clientId, clientSecret) { 15function getClient (clientId: string, clientSecret: string) {
13 logger.debug('Getting Client (clientId: ' + clientId + ', clientSecret: ' + clientSecret + ').') 16 logger.debug('Getting Client (clientId: ' + clientId + ', clientSecret: ' + clientSecret + ').')
14 17
15 return db.OAuthClient.getByIdAndSecret(clientId, clientSecret) 18 return db.OAuthClient.getByIdAndSecret(clientId, clientSecret)
16} 19}
17 20
18function getRefreshToken (refreshToken) { 21function getRefreshToken (refreshToken: string) {
19 logger.debug('Getting RefreshToken (refreshToken: ' + refreshToken + ').') 22 logger.debug('Getting RefreshToken (refreshToken: ' + refreshToken + ').')
20 23
21 return db.OAuthToken.getByRefreshTokenAndPopulateClient(refreshToken) 24 return db.OAuthToken.getByRefreshTokenAndPopulateClient(refreshToken)
22} 25}
23 26
24function getUser (username, password) { 27function getUser (username: string, password: string) {
25 logger.debug('Getting User (username: ' + username + ', password: ' + password + ').') 28 logger.debug('Getting User (username: ' + username + ', password: ' + password + ').')
26 29
27 return db.User.getByUsername(username).then(function (user) { 30 return db.User.getByUsername(username).then(function (user) {
@@ -42,7 +45,7 @@ function getUser (username, password) {
42 }) 45 })
43} 46}
44 47
45function revokeToken (token) { 48function revokeToken (token: TokenInfo) {
46 return db.OAuthToken.getByRefreshTokenAndPopulateUser(token.refreshToken).then(function (tokenDB) { 49 return db.OAuthToken.getByRefreshTokenAndPopulateUser(token.refreshToken).then(function (tokenDB) {
47 if (tokenDB) tokenDB.destroy() 50 if (tokenDB) tokenDB.destroy()
48 51
@@ -60,7 +63,7 @@ function revokeToken (token) {
60 }) 63 })
61} 64}
62 65
63function saveToken (token, client, user) { 66function saveToken (token: TokenInfo, client: OAuthClientInstance, user: UserInstance) {
64 logger.debug('Saving token ' + token.accessToken + ' for client ' + client.id + ' and user ' + user.id + '.') 67 logger.debug('Saving token ' + token.accessToken + ' for client ' + client.id + ' and user ' + user.id + '.')
65 68
66 const tokenToCreate = { 69 const tokenToCreate = {
diff --git a/server/lib/request/base-request-scheduler.ts b/server/lib/request/base-request-scheduler.ts
index b7ef6abf9..26bdc2bff 100644
--- a/server/lib/request/base-request-scheduler.ts
+++ b/server/lib/request/base-request-scheduler.ts
@@ -2,6 +2,7 @@ import * as eachLimit from 'async/eachLimit'
2 2
3import { database as db } from '../../initializers/database' 3import { database as db } from '../../initializers/database'
4import { logger, makeSecureRequest } from '../../helpers' 4import { logger, makeSecureRequest } from '../../helpers'
5import { PodInstance } from '../../models'
5import { 6import {
6 API_VERSION, 7 API_VERSION,
7 REQUESTS_IN_PARALLEL, 8 REQUESTS_IN_PARALLEL,
@@ -9,11 +10,12 @@ import {
9} from '../../initializers' 10} from '../../initializers'
10 11
11abstract class BaseRequestScheduler { 12abstract class BaseRequestScheduler {
13 requestInterval: number
14 limitPods: number
15 limitPerPod: number
16
12 protected lastRequestTimestamp: number 17 protected lastRequestTimestamp: number
13 protected timer: NodeJS.Timer 18 protected timer: NodeJS.Timer
14 protected requestInterval: number
15 protected limitPods: number
16 protected limitPerPod: number
17 protected description: string 19 protected description: string
18 20
19 constructor () { 21 constructor () {
@@ -53,24 +55,24 @@ abstract class BaseRequestScheduler {
53 return REQUESTS_INTERVAL - (Date.now() - this.lastRequestTimestamp) 55 return REQUESTS_INTERVAL - (Date.now() - this.lastRequestTimestamp)
54 } 56 }
55 57
56 remainingRequestsCount (callback) { 58 remainingRequestsCount (callback: (err: Error, total: number) => void) {
57 return this.getRequestModel().countTotalRequests(callback) 59 return this.getRequestModel().countTotalRequests(callback)
58 } 60 }
59 61
60 flush (callback) { 62 flush (callback: (err: Error) => void) {
61 this.getRequestModel().removeAll(callback) 63 this.getRequestModel().removeAll(callback)
62 } 64 }
63 65
64 // --------------------------------------------------------------------------- 66 // ---------------------------------------------------------------------------
65 67
66 // Make a requests to friends of a certain type 68 // Make a requests to friends of a certain type
67 protected makeRequest (toPod, requestEndpoint, requestsToMake, callback) { 69 protected makeRequest (toPod: PodInstance, requestEndpoint: string, requestsToMake: Object, callback) {
68 if (!callback) callback = function () { /* empty */ } 70 if (!callback) callback = function () { /* empty */ }
69 71
70 const params = { 72 const params = {
71 toPod: toPod, 73 toPod: toPod,
72 sign: true, // Prove our identity 74 sign: true, // Prove our identity
73 method: 'POST', 75 method: 'POST' as 'POST',
74 path: '/api/' + API_VERSION + '/remote/' + requestEndpoint, 76 path: '/api/' + API_VERSION + '/remote/' + requestEndpoint,
75 data: requestsToMake // Requests we need to make 77 data: requestsToMake // Requests we need to make
76 } 78 }
diff --git a/server/lib/request/index.ts b/server/lib/request/index.ts
index c98f956db..110d0ed78 100644
--- a/server/lib/request/index.ts
+++ b/server/lib/request/index.ts
@@ -1,3 +1,4 @@
1export * from './base-request-scheduler'
1export * from './request-scheduler' 2export * from './request-scheduler'
2export * from './request-video-event-scheduler' 3export * from './request-video-event-scheduler'
3export * from './request-video-qadu-scheduler' 4export * from './request-video-qadu-scheduler'
diff --git a/server/lib/request/request-scheduler.ts b/server/lib/request/request-scheduler.ts
index 26ffbfb86..69d840eeb 100644
--- a/server/lib/request/request-scheduler.ts
+++ b/server/lib/request/request-scheduler.ts
@@ -1,3 +1,5 @@
1import * as Sequelize from 'sequelize'
2
1import { database as db } from '../../initializers/database' 3import { database as db } from '../../initializers/database'
2import { BaseRequestScheduler } from './base-request-scheduler' 4import { BaseRequestScheduler } from './base-request-scheduler'
3import { logger } from '../../helpers' 5import { logger } from '../../helpers'
@@ -6,6 +8,14 @@ import {
6 REQUESTS_LIMIT_PER_POD 8 REQUESTS_LIMIT_PER_POD
7} from '../../initializers' 9} from '../../initializers'
8 10
11export type RequestSchedulerOptions = {
12 type: string
13 endpoint: string
14 data: Object
15 toIds: number[]
16 transaction: Sequelize.Transaction
17}
18
9class RequestScheduler extends BaseRequestScheduler { 19class RequestScheduler extends BaseRequestScheduler {
10 constructor () { 20 constructor () {
11 super() 21 super()
@@ -25,7 +35,7 @@ class RequestScheduler extends BaseRequestScheduler {
25 return db.RequestToPod 35 return db.RequestToPod
26 } 36 }
27 37
28 buildRequestObjects (requests) { 38 buildRequestObjects (requests: { [ toPodId: number ]: any }) {
29 const requestsToMakeGrouped = {} 39 const requestsToMakeGrouped = {}
30 40
31 Object.keys(requests).forEach(toPodId => { 41 Object.keys(requests).forEach(toPodId => {
@@ -51,14 +61,7 @@ class RequestScheduler extends BaseRequestScheduler {
51 return requestsToMakeGrouped 61 return requestsToMakeGrouped
52 } 62 }
53 63
54 // { type, endpoint, data, toIds, transaction } 64 createRequest ({ type, endpoint, data, toIds, transaction }: RequestSchedulerOptions, callback: (err: Error) => void) {
55 createRequest (options, callback) {
56 const type = options.type
57 const endpoint = options.endpoint
58 const data = options.data
59 const toIds = options.toIds
60 const transaction = options.transaction
61
62 // TODO: check the setPods works 65 // TODO: check the setPods works
63 const podIds = [] 66 const podIds = []
64 67
@@ -77,7 +80,7 @@ class RequestScheduler extends BaseRequestScheduler {
77 } 80 }
78 } 81 }
79 82
80 const dbRequestOptions = { 83 const dbRequestOptions: Sequelize.CreateOptions = {
81 transaction 84 transaction
82 } 85 }
83 86
diff --git a/server/lib/request/request-video-event-scheduler.ts b/server/lib/request/request-video-event-scheduler.ts
index bde50b1d3..9da82585e 100644
--- a/server/lib/request/request-video-event-scheduler.ts
+++ b/server/lib/request/request-video-event-scheduler.ts
@@ -1,3 +1,5 @@
1import * as Sequelize from 'sequelize'
2
1import { database as db } from '../../initializers/database' 3import { database as db } from '../../initializers/database'
2import { BaseRequestScheduler } from './base-request-scheduler' 4import { BaseRequestScheduler } from './base-request-scheduler'
3import { 5import {
@@ -6,6 +8,13 @@ import {
6 REQUEST_VIDEO_EVENT_ENDPOINT 8 REQUEST_VIDEO_EVENT_ENDPOINT
7} from '../../initializers' 9} from '../../initializers'
8 10
11export type RequestVideoEventSchedulerOptions = {
12 type: string
13 videoId: string
14 count?: number
15 transaction?: Sequelize.Transaction
16}
17
9class RequestVideoEventScheduler extends BaseRequestScheduler { 18class RequestVideoEventScheduler extends BaseRequestScheduler {
10 constructor () { 19 constructor () {
11 super() 20 super()
@@ -25,7 +34,7 @@ class RequestVideoEventScheduler extends BaseRequestScheduler {
25 return db.RequestVideoEvent 34 return db.RequestVideoEvent
26 } 35 }
27 36
28 buildRequestObjects (eventsToProcess) { 37 buildRequestObjects (eventsToProcess: { [ toPodId: number ]: any }[]) {
29 const requestsToMakeGrouped = {} 38 const requestsToMakeGrouped = {}
30 39
31 /* Example: 40 /* Example:
@@ -87,16 +96,10 @@ class RequestVideoEventScheduler extends BaseRequestScheduler {
87 return requestsToMakeGrouped 96 return requestsToMakeGrouped
88 } 97 }
89 98
90 // { type, videoId, count?, transaction? } 99 createRequest ({ type, videoId, count, transaction }: RequestVideoEventSchedulerOptions, callback: (err: Error) => void) {
91 createRequest (options, callback) {
92 const type = options.type
93 const videoId = options.videoId
94 const transaction = options.transaction
95 let count = options.count
96
97 if (count === undefined) count = 1 100 if (count === undefined) count = 1
98 101
99 const dbRequestOptions: { transaction?: any } = {} 102 const dbRequestOptions: Sequelize.CreateOptions = {}
100 if (transaction) dbRequestOptions.transaction = transaction 103 if (transaction) dbRequestOptions.transaction = transaction
101 104
102 const createQuery = { 105 const createQuery = {
diff --git a/server/lib/request/request-video-qadu-scheduler.ts b/server/lib/request/request-video-qadu-scheduler.ts
index dab526088..436fd8e50 100644
--- a/server/lib/request/request-video-qadu-scheduler.ts
+++ b/server/lib/request/request-video-qadu-scheduler.ts
@@ -1,3 +1,5 @@
1import * as Sequelize from 'sequelize'
2
1import { database as db } from '../../initializers/database' 3import { database as db } from '../../initializers/database'
2import { BaseRequestScheduler } from './base-request-scheduler' 4import { BaseRequestScheduler } from './base-request-scheduler'
3import { logger } from '../../helpers' 5import { logger } from '../../helpers'
@@ -8,6 +10,12 @@ import {
8 REQUEST_VIDEO_QADU_TYPES 10 REQUEST_VIDEO_QADU_TYPES
9} from '../../initializers' 11} from '../../initializers'
10 12
13export type RequestVideoQaduSchedulerOptions = {
14 type: string
15 videoId: string
16 transaction?: Sequelize.Transaction
17}
18
11class RequestVideoQaduScheduler extends BaseRequestScheduler { 19class RequestVideoQaduScheduler extends BaseRequestScheduler {
12 constructor () { 20 constructor () {
13 super() 21 super()
@@ -27,7 +35,7 @@ class RequestVideoQaduScheduler extends BaseRequestScheduler {
27 return db.RequestVideoQadu 35 return db.RequestVideoQadu
28 } 36 }
29 37
30 buildRequestObjects (requests) { 38 buildRequestObjects (requests: { [ toPodId: number ]: any }[]) {
31 const requestsToMakeGrouped = {} 39 const requestsToMakeGrouped = {}
32 40
33 Object.keys(requests).forEach(toPodId => { 41 Object.keys(requests).forEach(toPodId => {
@@ -96,17 +104,12 @@ class RequestVideoQaduScheduler extends BaseRequestScheduler {
96 return requestsToMakeGrouped 104 return requestsToMakeGrouped
97 } 105 }
98 106
99 // { type, videoId, transaction? } 107 createRequest ({ type, videoId, transaction }: RequestVideoQaduSchedulerOptions, callback: (err: Error) => void) {
100 createRequest (options, callback) { 108 const dbRequestOptions: Sequelize.BulkCreateOptions = {}
101 const type = options.type
102 const videoId = options.videoId
103 const transaction = options.transaction
104
105 const dbRequestOptions: { transaction?: any } = {}
106 if (transaction) dbRequestOptions.transaction = transaction 109 if (transaction) dbRequestOptions.transaction = transaction
107 110
108 // Send the update to all our friends 111 // Send the update to all our friends
109 db.Pod.listAllIds(options.transaction, function (err, podIds) { 112 db.Pod.listAllIds(transaction, function (err, podIds) {
110 if (err) return callback(err) 113 if (err) return callback(err)
111 114
112 const queries = [] 115 const queries = []
diff --git a/server/middlewares/admin.ts b/server/middlewares/admin.ts
index 28b6a9a12..812397352 100644
--- a/server/middlewares/admin.ts
+++ b/server/middlewares/admin.ts
@@ -1,6 +1,9 @@
1import 'express-validator'
2import * as express from 'express'
3
1import { logger } from '../helpers' 4import { logger } from '../helpers'
2 5
3function ensureIsAdmin (req, res, next) { 6function ensureIsAdmin (req: express.Request, res: express.Response, next: express.NextFunction) {
4 const user = res.locals.oauth.token.user 7 const user = res.locals.oauth.token.user
5 if (user.isAdmin() === false) { 8 if (user.isAdmin() === false) {
6 logger.info('A non admin user is trying to access to an admin content.') 9 logger.info('A non admin user is trying to access to an admin content.')
diff --git a/server/middlewares/index.ts b/server/middlewares/index.ts
index 2c1c5fa53..d71dd2452 100644
--- a/server/middlewares/index.ts
+++ b/server/middlewares/index.ts
@@ -1,8 +1,8 @@
1export * from './validators'; 1export * from './validators'
2export * from './admin'; 2export * from './admin'
3export * from './oauth'; 3export * from './oauth'
4export * from './pagination'; 4export * from './pagination'
5export * from './pods'; 5export * from './pods'
6export * from './search'; 6export * from './search'
7export * from './secure'; 7export * from './secure'
8export * from './sort'; 8export * from './sort'
diff --git a/server/middlewares/oauth.ts b/server/middlewares/oauth.ts
index 468e41810..d545b3e58 100644
--- a/server/middlewares/oauth.ts
+++ b/server/middlewares/oauth.ts
@@ -1,3 +1,5 @@
1import 'express-validator'
2import * as express from 'express'
1import * as OAuthServer from 'express-oauth-server' 3import * as OAuthServer from 'express-oauth-server'
2 4
3import { OAUTH_LIFETIME } from '../initializers' 5import { OAUTH_LIFETIME } from '../initializers'
@@ -9,7 +11,7 @@ const oAuthServer = new OAuthServer({
9 model: require('../lib/oauth-model') 11 model: require('../lib/oauth-model')
10}) 12})
11 13
12function authenticate (req, res, next) { 14function authenticate (req: express.Request, res: express.Response, next: express.NextFunction) {
13 oAuthServer.authenticate()(req, res, function (err) { 15 oAuthServer.authenticate()(req, res, function (err) {
14 if (err) { 16 if (err) {
15 logger.error('Cannot authenticate.', { error: err }) 17 logger.error('Cannot authenticate.', { error: err })
@@ -22,7 +24,7 @@ function authenticate (req, res, next) {
22 }) 24 })
23} 25}
24 26
25function token (req, res, next) { 27function token (req: express.Request, res: express.Response, next: express.NextFunction) {
26 return oAuthServer.token()(req, res, next) 28 return oAuthServer.token()(req, res, next)
27} 29}
28 30
diff --git a/server/middlewares/pagination.ts b/server/middlewares/pagination.ts
index cadd76980..26a8cacf0 100644
--- a/server/middlewares/pagination.ts
+++ b/server/middlewares/pagination.ts
@@ -1,6 +1,9 @@
1import 'express-validator'
2import * as express from 'express'
3
1import { PAGINATION_COUNT_DEFAULT } from '../initializers' 4import { PAGINATION_COUNT_DEFAULT } from '../initializers'
2 5
3function setPagination (req, res, next) { 6function setPagination (req: express.Request, res: express.Response, next: express.NextFunction) {
4 if (!req.query.start) req.query.start = 0 7 if (!req.query.start) req.query.start = 0
5 else req.query.start = parseInt(req.query.start, 10) 8 else req.query.start = parseInt(req.query.start, 10)
6 9
diff --git a/server/middlewares/pods.ts b/server/middlewares/pods.ts
index c255be899..eaf9aa144 100644
--- a/server/middlewares/pods.ts
+++ b/server/middlewares/pods.ts
@@ -1,6 +1,9 @@
1import 'express-validator'
2import * as express from 'express'
3
1import { REMOTE_SCHEME } from '../initializers' 4import { REMOTE_SCHEME } from '../initializers'
2 5
3function setBodyHostsPort (req, res, next) { 6function setBodyHostsPort (req: express.Request, res: express.Response, next: express.NextFunction) {
4 if (!req.body.hosts) return next() 7 if (!req.body.hosts) return next()
5 8
6 for (let i = 0; i < req.body.hosts.length; i++) { 9 for (let i = 0; i < req.body.hosts.length; i++) {
@@ -17,7 +20,7 @@ function setBodyHostsPort (req, res, next) {
17 return next() 20 return next()
18} 21}
19 22
20function setBodyHostPort (req, res, next) { 23function setBodyHostPort (req: express.Request, res: express.Response, next: express.NextFunction) {
21 if (!req.body.host) return next() 24 if (!req.body.host) return next()
22 25
23 const hostWithPort = getHostWithPort(req.body.host) 26 const hostWithPort = getHostWithPort(req.body.host)
@@ -41,7 +44,7 @@ export {
41 44
42// --------------------------------------------------------------------------- 45// ---------------------------------------------------------------------------
43 46
44function getHostWithPort (host) { 47function getHostWithPort (host: string) {
45 const splitted = host.split(':') 48 const splitted = host.split(':')
46 49
47 // The port was not specified 50 // The port was not specified
diff --git a/server/middlewares/search.ts b/server/middlewares/search.ts
index 05a2e7442..6fe83d25b 100644
--- a/server/middlewares/search.ts
+++ b/server/middlewares/search.ts
@@ -1,4 +1,7 @@
1function setVideosSearch (req, res, next) { 1import 'express-validator'
2import * as express from 'express'
3
4function setVideosSearch (req: express.Request, res: express.Response, next: express.NextFunction) {
2 if (!req.query.field) req.query.field = 'name' 5 if (!req.query.field) req.query.field = 'name'
3 6
4 return next() 7 return next()
diff --git a/server/middlewares/secure.ts b/server/middlewares/secure.ts
index bd7cfa918..fbfd08c7b 100644
--- a/server/middlewares/secure.ts
+++ b/server/middlewares/secure.ts
@@ -1,10 +1,13 @@
1import 'express-validator'
2import * as express from 'express'
3
1import { database as db } from '../initializers' 4import { database as db } from '../initializers'
2import { 5import {
3 logger, 6 logger,
4 checkSignature as peertubeCryptoCheckSignature 7 checkSignature as peertubeCryptoCheckSignature
5} from '../helpers' 8} from '../helpers'
6 9
7function checkSignature (req, res, next) { 10function checkSignature (req: express.Request, res: express.Response, next: express.NextFunction) {
8 const host = req.body.signature.host 11 const host = req.body.signature.host
9 db.Pod.loadByHost(host, function (err, pod) { 12 db.Pod.loadByHost(host, function (err, pod) {
10 if (err) { 13 if (err) {
diff --git a/server/middlewares/sort.ts b/server/middlewares/sort.ts
index ab9ccf524..632b2fae4 100644
--- a/server/middlewares/sort.ts
+++ b/server/middlewares/sort.ts
@@ -1,16 +1,19 @@
1function setUsersSort (req, res, next) { 1import 'express-validator'
2import * as express from 'express'
3
4function setUsersSort (req: express.Request, res: express.Response, next: express.NextFunction) {
2 if (!req.query.sort) req.query.sort = '-createdAt' 5 if (!req.query.sort) req.query.sort = '-createdAt'
3 6
4 return next() 7 return next()
5} 8}
6 9
7function setVideoAbusesSort (req, res, next) { 10function setVideoAbusesSort (req: express.Request, res: express.Response, next: express.NextFunction) {
8 if (!req.query.sort) req.query.sort = '-createdAt' 11 if (!req.query.sort) req.query.sort = '-createdAt'
9 12
10 return next() 13 return next()
11} 14}
12 15
13function setVideosSort (req, res, next) { 16function setVideosSort (req: express.Request, res: express.Response, next: express.NextFunction) {
14 if (!req.query.sort) req.query.sort = '-createdAt' 17 if (!req.query.sort) req.query.sort = '-createdAt'
15 18
16 return next() 19 return next()
diff --git a/server/middlewares/validators/pagination.ts b/server/middlewares/validators/pagination.ts
index de719c05b..cca8295ff 100644
--- a/server/middlewares/validators/pagination.ts
+++ b/server/middlewares/validators/pagination.ts
@@ -1,7 +1,10 @@
1import 'express-validator'
2import * as express from 'express'
3
1import { checkErrors } from './utils' 4import { checkErrors } from './utils'
2import { logger } from '../../helpers' 5import { logger } from '../../helpers'
3 6
4function paginationValidator (req, res, next) { 7function paginationValidator (req: express.Request, res: express.Response, next: express.NextFunction) {
5 req.checkQuery('start', 'Should have a number start').optional().isInt() 8 req.checkQuery('start', 'Should have a number start').optional().isInt()
6 req.checkQuery('count', 'Should have a number count').optional().isInt() 9 req.checkQuery('count', 'Should have a number count').optional().isInt()
7 10
diff --git a/server/middlewares/validators/pods.ts b/server/middlewares/validators/pods.ts
index c55a88b85..d8eb90168 100644
--- a/server/middlewares/validators/pods.ts
+++ b/server/middlewares/validators/pods.ts
@@ -1,3 +1,6 @@
1import 'express-validator'
2import * as express from 'express'
3
1import { database as db } from '../../initializers/database' 4import { database as db } from '../../initializers/database'
2import { checkErrors } from './utils' 5import { checkErrors } from './utils'
3import { logger } from '../../helpers' 6import { logger } from '../../helpers'
@@ -5,7 +8,7 @@ import { CONFIG } from '../../initializers'
5import { hasFriends } from '../../lib' 8import { hasFriends } from '../../lib'
6import { isTestInstance } from '../../helpers' 9import { isTestInstance } from '../../helpers'
7 10
8function makeFriendsValidator (req, res, next) { 11function makeFriendsValidator (req: express.Request, res: express.Response, next: express.NextFunction) {
9 // Force https if the administrator wants to make friends 12 // Force https if the administrator wants to make friends
10 if (isTestInstance() === false && CONFIG.WEBSERVER.SCHEME === 'http') { 13 if (isTestInstance() === false && CONFIG.WEBSERVER.SCHEME === 'http') {
11 return res.status(400).send('Cannot make friends with a non HTTPS webserver.') 14 return res.status(400).send('Cannot make friends with a non HTTPS webserver.')
@@ -32,7 +35,7 @@ function makeFriendsValidator (req, res, next) {
32 }) 35 })
33} 36}
34 37
35function podsAddValidator (req, res, next) { 38function podsAddValidator (req: express.Request, res: express.Response, next: express.NextFunction) {
36 req.checkBody('host', 'Should have a host').isHostValid() 39 req.checkBody('host', 'Should have a host').isHostValid()
37 req.checkBody('email', 'Should have an email').isEmail() 40 req.checkBody('email', 'Should have an email').isEmail()
38 req.checkBody('publicKey', 'Should have a public key').notEmpty() 41 req.checkBody('publicKey', 'Should have a public key').notEmpty()
diff --git a/server/middlewares/validators/remote/signature.ts b/server/middlewares/validators/remote/signature.ts
index 6e3ebe7db..eb5c196eb 100644
--- a/server/middlewares/validators/remote/signature.ts
+++ b/server/middlewares/validators/remote/signature.ts
@@ -1,7 +1,10 @@
1import 'express-validator'
2import * as express from 'express'
3
1import { logger } from '../../../helpers' 4import { logger } from '../../../helpers'
2import { checkErrors } from '../utils' 5import { checkErrors } from '../utils'
3 6
4function signatureValidator (req, res, next) { 7function signatureValidator (req: express.Request, res: express.Response, next: express.NextFunction) {
5 req.checkBody('signature.host', 'Should have a signature host').isURL() 8 req.checkBody('signature.host', 'Should have a signature host').isURL()
6 req.checkBody('signature.signature', 'Should have a signature').notEmpty() 9 req.checkBody('signature.signature', 'Should have a signature').notEmpty()
7 10
diff --git a/server/middlewares/validators/remote/videos.ts b/server/middlewares/validators/remote/videos.ts
index 3380c29e2..2037c0085 100644
--- a/server/middlewares/validators/remote/videos.ts
+++ b/server/middlewares/validators/remote/videos.ts
@@ -1,7 +1,10 @@
1import 'express-validator'
2import * as express from 'express'
3
1import { logger } from '../../../helpers' 4import { logger } from '../../../helpers'
2import { checkErrors } from '../utils' 5import { checkErrors } from '../utils'
3 6
4function remoteVideosValidator (req, res, next) { 7function remoteVideosValidator (req: express.Request, res: express.Response, next: express.NextFunction) {
5 req.checkBody('data').isEachRemoteRequestVideosValid() 8 req.checkBody('data').isEachRemoteRequestVideosValid()
6 9
7 logger.debug('Checking remoteVideos parameters', { parameters: req.body }) 10 logger.debug('Checking remoteVideos parameters', { parameters: req.body })
@@ -9,7 +12,7 @@ function remoteVideosValidator (req, res, next) {
9 checkErrors(req, res, next) 12 checkErrors(req, res, next)
10} 13}
11 14
12function remoteQaduVideosValidator (req, res, next) { 15function remoteQaduVideosValidator (req: express.Request, res: express.Response, next: express.NextFunction) {
13 req.checkBody('data').isEachRemoteRequestVideosQaduValid() 16 req.checkBody('data').isEachRemoteRequestVideosQaduValid()
14 17
15 logger.debug('Checking remoteQaduVideos parameters', { parameters: req.body }) 18 logger.debug('Checking remoteQaduVideos parameters', { parameters: req.body })
@@ -17,7 +20,7 @@ function remoteQaduVideosValidator (req, res, next) {
17 checkErrors(req, res, next) 20 checkErrors(req, res, next)
18} 21}
19 22
20function remoteEventsVideosValidator (req, res, next) { 23function remoteEventsVideosValidator (req: express.Request, res: express.Response, next: express.NextFunction) {
21 req.checkBody('data').isEachRemoteRequestVideosEventsValid() 24 req.checkBody('data').isEachRemoteRequestVideosEventsValid()
22 25
23 logger.debug('Checking remoteEventsVideos parameters', { parameters: req.body }) 26 logger.debug('Checking remoteEventsVideos parameters', { parameters: req.body })
diff --git a/server/middlewares/validators/sort.ts b/server/middlewares/validators/sort.ts
index ebc7333c7..3baee9fb3 100644
--- a/server/middlewares/validators/sort.ts
+++ b/server/middlewares/validators/sort.ts
@@ -1,3 +1,6 @@
1import 'express-validator'
2import * as express from 'express'
3
1import { checkErrors } from './utils' 4import { checkErrors } from './utils'
2import { logger } from '../../helpers' 5import { logger } from '../../helpers'
3import { SORTABLE_COLUMNS } from '../../initializers' 6import { SORTABLE_COLUMNS } from '../../initializers'
@@ -7,15 +10,15 @@ const SORTABLE_USERS_COLUMNS = createSortableColumns(SORTABLE_COLUMNS.USERS)
7const SORTABLE_VIDEO_ABUSES_COLUMNS = createSortableColumns(SORTABLE_COLUMNS.VIDEO_ABUSES) 10const SORTABLE_VIDEO_ABUSES_COLUMNS = createSortableColumns(SORTABLE_COLUMNS.VIDEO_ABUSES)
8const SORTABLE_VIDEOS_COLUMNS = createSortableColumns(SORTABLE_COLUMNS.VIDEOS) 11const SORTABLE_VIDEOS_COLUMNS = createSortableColumns(SORTABLE_COLUMNS.VIDEOS)
9 12
10function usersSortValidator (req, res, next) { 13function usersSortValidator (req: express.Request, res: express.Response, next: express.NextFunction) {
11 checkSort(req, res, next, SORTABLE_USERS_COLUMNS) 14 checkSort(req, res, next, SORTABLE_USERS_COLUMNS)
12} 15}
13 16
14function videoAbusesSortValidator (req, res, next) { 17function videoAbusesSortValidator (req: express.Request, res: express.Response, next: express.NextFunction) {
15 checkSort(req, res, next, SORTABLE_VIDEO_ABUSES_COLUMNS) 18 checkSort(req, res, next, SORTABLE_VIDEO_ABUSES_COLUMNS)
16} 19}
17 20
18function videosSortValidator (req, res, next) { 21function videosSortValidator (req: express.Request, res: express.Response, next: express.NextFunction) {
19 checkSort(req, res, next, SORTABLE_VIDEOS_COLUMNS) 22 checkSort(req, res, next, SORTABLE_VIDEOS_COLUMNS)
20} 23}
21 24
@@ -29,7 +32,7 @@ export {
29 32
30// --------------------------------------------------------------------------- 33// ---------------------------------------------------------------------------
31 34
32function checkSort (req, res, next, sortableColumns) { 35function checkSort (req: express.Request, res: express.Response, next: express.NextFunction, sortableColumns: string[]) {
33 req.checkQuery('sort', 'Should have correct sortable column').optional().isIn(sortableColumns) 36 req.checkQuery('sort', 'Should have correct sortable column').optional().isIn(sortableColumns)
34 37
35 logger.debug('Checking sort parameters', { parameters: req.query }) 38 logger.debug('Checking sort parameters', { parameters: req.query })
@@ -37,7 +40,7 @@ function checkSort (req, res, next, sortableColumns) {
37 checkErrors(req, res, next) 40 checkErrors(req, res, next)
38} 41}
39 42
40function createSortableColumns (sortableColumns) { 43function createSortableColumns (sortableColumns: string[]) {
41 const sortableColumnDesc = sortableColumns.map(sortableColumn => '-' + sortableColumn) 44 const sortableColumnDesc = sortableColumns.map(sortableColumn => '-' + sortableColumn)
42 45
43 return sortableColumns.concat(sortableColumnDesc) 46 return sortableColumns.concat(sortableColumnDesc)
diff --git a/server/middlewares/validators/users.ts b/server/middlewares/validators/users.ts
index e0d1d917a..b7b9ef370 100644
--- a/server/middlewares/validators/users.ts
+++ b/server/middlewares/validators/users.ts
@@ -1,8 +1,11 @@
1import 'express-validator'
2import * as express from 'express'
3
1import { database as db } from '../../initializers/database' 4import { database as db } from '../../initializers/database'
2import { checkErrors } from './utils' 5import { checkErrors } from './utils'
3import { logger } from '../../helpers' 6import { logger } from '../../helpers'
4 7
5function usersAddValidator (req, res, next) { 8function usersAddValidator (req: express.Request, res: express.Response, next: express.NextFunction) {
6 req.checkBody('username', 'Should have a valid username').isUserUsernameValid() 9 req.checkBody('username', 'Should have a valid username').isUserUsernameValid()
7 req.checkBody('password', 'Should have a valid password').isUserPasswordValid() 10 req.checkBody('password', 'Should have a valid password').isUserPasswordValid()
8 req.checkBody('email', 'Should have a valid email').isEmail() 11 req.checkBody('email', 'Should have a valid email').isEmail()
@@ -23,7 +26,7 @@ function usersAddValidator (req, res, next) {
23 }) 26 })
24} 27}
25 28
26function usersRemoveValidator (req, res, next) { 29function usersRemoveValidator (req: express.Request, res: express.Response, next: express.NextFunction) {
27 req.checkParams('id', 'Should have a valid id').notEmpty().isInt() 30 req.checkParams('id', 'Should have a valid id').notEmpty().isInt()
28 31
29 logger.debug('Checking usersRemove parameters', { parameters: req.params }) 32 logger.debug('Checking usersRemove parameters', { parameters: req.params })
@@ -44,7 +47,7 @@ function usersRemoveValidator (req, res, next) {
44 }) 47 })
45} 48}
46 49
47function usersUpdateValidator (req, res, next) { 50function usersUpdateValidator (req: express.Request, res: express.Response, next: express.NextFunction) {
48 req.checkParams('id', 'Should have a valid id').notEmpty().isInt() 51 req.checkParams('id', 'Should have a valid id').notEmpty().isInt()
49 // Add old password verification 52 // Add old password verification
50 req.checkBody('password', 'Should have a valid password').optional().isUserPasswordValid() 53 req.checkBody('password', 'Should have a valid password').optional().isUserPasswordValid()
@@ -55,7 +58,7 @@ function usersUpdateValidator (req, res, next) {
55 checkErrors(req, res, next) 58 checkErrors(req, res, next)
56} 59}
57 60
58function usersVideoRatingValidator (req, res, next) { 61function usersVideoRatingValidator (req: express.Request, res: express.Response, next: express.NextFunction) {
59 req.checkParams('videoId', 'Should have a valid video id').notEmpty().isUUID(4) 62 req.checkParams('videoId', 'Should have a valid video id').notEmpty().isUUID(4)
60 63
61 logger.debug('Checking usersVideoRating parameters', { parameters: req.params }) 64 logger.debug('Checking usersVideoRating parameters', { parameters: req.params })
diff --git a/server/middlewares/validators/utils.ts b/server/middlewares/validators/utils.ts
index 710e65529..0424d5942 100644
--- a/server/middlewares/validators/utils.ts
+++ b/server/middlewares/validators/utils.ts
@@ -1,9 +1,10 @@
1import 'express-validator'
2import * as express from 'express'
1import { inspect } from 'util' 3import { inspect } from 'util'
2 4
3import { logger } from '../../helpers' 5import { logger } from '../../helpers'
4 6
5function checkErrors (req, res, next, statusCode?) { 7function checkErrors (req: express.Request, res: express.Response, next: express.NextFunction, statusCode = 400) {
6 if (statusCode === undefined) statusCode = 400
7 const errors = req.validationErrors() 8 const errors = req.validationErrors()
8 9
9 if (errors) { 10 if (errors) {
diff --git a/server/middlewares/validators/videos.ts b/server/middlewares/validators/videos.ts
index 47825975c..e99cdefb1 100644
--- a/server/middlewares/validators/videos.ts
+++ b/server/middlewares/validators/videos.ts
@@ -1,9 +1,13 @@
1import 'express-validator'
2import * as multer from 'multer'
3import * as express from 'express'
4
1import { database as db } from '../../initializers/database' 5import { database as db } from '../../initializers/database'
2import { checkErrors } from './utils' 6import { checkErrors } from './utils'
3import { CONSTRAINTS_FIELDS, SEARCHABLE_COLUMNS } from '../../initializers' 7import { CONSTRAINTS_FIELDS, SEARCHABLE_COLUMNS } from '../../initializers'
4import { logger, isVideoDurationValid } from '../../helpers' 8import { logger, isVideoDurationValid } from '../../helpers'
5 9
6function videosAddValidator (req, res, next) { 10function videosAddValidator (req: express.Request, res: express.Response, next: express.NextFunction) {
7 req.checkBody('videofile', 'Should have a valid file').isVideoFile(req.files) 11 req.checkBody('videofile', 'Should have a valid file').isVideoFile(req.files)
8 req.checkBody('name', 'Should have a valid name').isVideoNameValid() 12 req.checkBody('name', 'Should have a valid name').isVideoNameValid()
9 req.checkBody('category', 'Should have a valid category').isVideoCategoryValid() 13 req.checkBody('category', 'Should have a valid category').isVideoCategoryValid()
@@ -27,13 +31,13 @@ function videosAddValidator (req, res, next) {
27 return res.status(400).send('Duration of the video file is too big (max: ' + CONSTRAINTS_FIELDS.VIDEOS.DURATION.max + 's).') 31 return res.status(400).send('Duration of the video file is too big (max: ' + CONSTRAINTS_FIELDS.VIDEOS.DURATION.max + 's).')
28 } 32 }
29 33
30 videoFile.duration = duration 34 videoFile['duration'] = duration
31 next() 35 next()
32 }) 36 })
33 }) 37 })
34} 38}
35 39
36function videosUpdateValidator (req, res, next) { 40function videosUpdateValidator (req: express.Request, res: express.Response, next: express.NextFunction) {
37 req.checkParams('id', 'Should have a valid id').notEmpty().isUUID(4) 41 req.checkParams('id', 'Should have a valid id').notEmpty().isUUID(4)
38 req.checkBody('name', 'Should have a valid name').optional().isVideoNameValid() 42 req.checkBody('name', 'Should have a valid name').optional().isVideoNameValid()
39 req.checkBody('category', 'Should have a valid category').optional().isVideoCategoryValid() 43 req.checkBody('category', 'Should have a valid category').optional().isVideoCategoryValid()
@@ -61,7 +65,7 @@ function videosUpdateValidator (req, res, next) {
61 }) 65 })
62} 66}
63 67
64function videosGetValidator (req, res, next) { 68function videosGetValidator (req: express.Request, res: express.Response, next: express.NextFunction) {
65 req.checkParams('id', 'Should have a valid id').notEmpty().isUUID(4) 69 req.checkParams('id', 'Should have a valid id').notEmpty().isUUID(4)
66 70
67 logger.debug('Checking videosGet parameters', { parameters: req.params }) 71 logger.debug('Checking videosGet parameters', { parameters: req.params })
@@ -71,7 +75,7 @@ function videosGetValidator (req, res, next) {
71 }) 75 })
72} 76}
73 77
74function videosRemoveValidator (req, res, next) { 78function videosRemoveValidator (req: express.Request, res: express.Response, next: express.NextFunction) {
75 req.checkParams('id', 'Should have a valid id').notEmpty().isUUID(4) 79 req.checkParams('id', 'Should have a valid id').notEmpty().isUUID(4)
76 80
77 logger.debug('Checking videosRemove parameters', { parameters: req.params }) 81 logger.debug('Checking videosRemove parameters', { parameters: req.params })
@@ -88,7 +92,7 @@ function videosRemoveValidator (req, res, next) {
88 }) 92 })
89} 93}
90 94
91function videosSearchValidator (req, res, next) { 95function videosSearchValidator (req: express.Request, res: express.Response, next: express.NextFunction) {
92 const searchableColumns = SEARCHABLE_COLUMNS.VIDEOS 96 const searchableColumns = SEARCHABLE_COLUMNS.VIDEOS
93 req.checkParams('value', 'Should have a valid search').notEmpty() 97 req.checkParams('value', 'Should have a valid search').notEmpty()
94 req.checkQuery('field', 'Should have correct searchable column').optional().isIn(searchableColumns) 98 req.checkQuery('field', 'Should have correct searchable column').optional().isIn(searchableColumns)
@@ -98,7 +102,7 @@ function videosSearchValidator (req, res, next) {
98 checkErrors(req, res, next) 102 checkErrors(req, res, next)
99} 103}
100 104
101function videoAbuseReportValidator (req, res, next) { 105function videoAbuseReportValidator (req: express.Request, res: express.Response, next: express.NextFunction) {
102 req.checkParams('id', 'Should have a valid id').notEmpty().isUUID(4) 106 req.checkParams('id', 'Should have a valid id').notEmpty().isUUID(4)
103 req.checkBody('reason', 'Should have a valid reason').isVideoAbuseReasonValid() 107 req.checkBody('reason', 'Should have a valid reason').isVideoAbuseReasonValid()
104 108
@@ -109,7 +113,7 @@ function videoAbuseReportValidator (req, res, next) {
109 }) 113 })
110} 114}
111 115
112function videoRateValidator (req, res, next) { 116function videoRateValidator (req: express.Request, res: express.Response, next: express.NextFunction) {
113 req.checkParams('id', 'Should have a valid id').notEmpty().isUUID(4) 117 req.checkParams('id', 'Should have a valid id').notEmpty().isUUID(4)
114 req.checkBody('rating', 'Should have a valid rate type').isVideoRatingTypeValid() 118 req.checkBody('rating', 'Should have a valid rate type').isVideoRatingTypeValid()
115 119
@@ -120,7 +124,7 @@ function videoRateValidator (req, res, next) {
120 }) 124 })
121} 125}
122 126
123function videosBlacklistValidator (req, res, next) { 127function videosBlacklistValidator (req: express.Request, res: express.Response, next: express.NextFunction) {
124 req.checkParams('id', 'Should have a valid id').notEmpty().isUUID(4) 128 req.checkParams('id', 'Should have a valid id').notEmpty().isUUID(4)
125 129
126 logger.debug('Checking videosBlacklist parameters', { parameters: req.params }) 130 logger.debug('Checking videosBlacklist parameters', { parameters: req.params })
@@ -150,7 +154,7 @@ export {
150 154
151// --------------------------------------------------------------------------- 155// ---------------------------------------------------------------------------
152 156
153function checkVideoExists (id, res, callback) { 157function checkVideoExists (id: string, res: express.Response, callback: () => void) {
154 db.Video.loadAndPopulateAuthorAndPodAndTags(id, function (err, video) { 158 db.Video.loadAndPopulateAuthorAndPodAndTags(id, function (err, video) {
155 if (err) { 159 if (err) {
156 logger.error('Error in video request validator.', { error: err }) 160 logger.error('Error in video request validator.', { error: err })
@@ -164,7 +168,7 @@ function checkVideoExists (id, res, callback) {
164 }) 168 })
165} 169}
166 170
167function checkUserCanDeleteVideo (userId, res, callback) { 171function checkUserCanDeleteVideo (userId: number, res: express.Response, callback: () => void) {
168 // Retrieve the user who did the request 172 // Retrieve the user who did the request
169 db.User.loadById(userId, function (err, user) { 173 db.User.loadById(userId, function (err, user) {
170 if (err) { 174 if (err) {
@@ -190,7 +194,7 @@ function checkUserCanDeleteVideo (userId, res, callback) {
190 }) 194 })
191} 195}
192 196
193function checkVideoIsBlacklistable (req, res, callback) { 197function checkVideoIsBlacklistable (req: express.Request, res: express.Response, callback: () => void) {
194 if (res.locals.video.isOwned() === true) { 198 if (res.locals.video.isOwned() === true) {
195 return res.status(403).send('Cannot blacklist a local video') 199 return res.status(403).send('Cannot blacklist a local video')
196 } 200 }
diff --git a/server/models/application-interface.ts b/server/models/application-interface.ts
index 826d25df0..c03513db1 100644
--- a/server/models/application-interface.ts
+++ b/server/models/application-interface.ts
@@ -1,8 +1,11 @@
1import * as Sequelize from 'sequelize' 1import * as Sequelize from 'sequelize'
2 2
3export namespace ApplicationMethods { 3export namespace ApplicationMethods {
4 export type LoadMigrationVersion = (callback: (err: Error, version: number) => void) => void 4 export type LoadMigrationVersionCallback = (err: Error, version: number) => void
5 export type UpdateMigrationVersion = (newVersion: number, transaction: any, callback: any) => void 5 export type LoadMigrationVersion = (callback: LoadMigrationVersionCallback) => void
6
7 export type UpdateMigrationVersionCallback = (err: Error, applicationInstance: ApplicationAttributes) => void
8 export type UpdateMigrationVersion = (newVersion: number, transaction: Sequelize.Transaction, callback: UpdateMigrationVersionCallback) => void
6} 9}
7 10
8export interface ApplicationClass { 11export interface ApplicationClass {
diff --git a/server/models/application.ts b/server/models/application.ts
index acd0dfbf2..14b87777a 100644
--- a/server/models/application.ts
+++ b/server/models/application.ts
@@ -35,7 +35,7 @@ export default function defineApplication (sequelize: Sequelize.Sequelize, DataT
35 35
36// --------------------------------------------------------------------------- 36// ---------------------------------------------------------------------------
37 37
38loadMigrationVersion = function (callback: (err: Error, version: number) => void) { 38loadMigrationVersion = function (callback: ApplicationMethods.LoadMigrationVersionCallback) {
39 const query = { 39 const query = {
40 attributes: [ 'migrationVersion' ] 40 attributes: [ 'migrationVersion' ]
41 } 41 }
@@ -47,15 +47,10 @@ loadMigrationVersion = function (callback: (err: Error, version: number) => void
47 }) 47 })
48} 48}
49 49
50updateMigrationVersion = function (newVersion: number, transaction: any, callback: any) { 50updateMigrationVersion = function (newVersion: number, transaction: Sequelize.Transaction, callback: ApplicationMethods.UpdateMigrationVersionCallback) {
51 const options: Sequelize.UpdateOptions = { 51 const options: Sequelize.UpdateOptions = {
52 where: {} 52 where: {},
53 } 53 transaction: transaction
54
55 if (!callback) {
56 transaction = callback
57 } else {
58 options.transaction = transaction
59 } 54 }
60 55
61 return Application.update({ migrationVersion: newVersion }, options).asCallback(callback) 56 return Application.update({ migrationVersion: newVersion }, options).asCallback(callback)
diff --git a/server/models/author-interface.ts b/server/models/author-interface.ts
index d2475c3bd..b57ce2a6b 100644
--- a/server/models/author-interface.ts
+++ b/server/models/author-interface.ts
@@ -1,7 +1,10 @@
1import * as Sequelize from 'sequelize' 1import * as Sequelize from 'sequelize'
2 2
3import { PodInstance } from './pod-interface'
4
3export namespace AuthorMethods { 5export namespace AuthorMethods {
4 export type FindOrCreateAuthor = (name, podId, userId, transaction, callback) => void 6 export type FindOrCreateAuthorCallback = (err: Error, authorInstance?: AuthorInstance) => void
7 export type FindOrCreateAuthor = (name: string, podId: number, userId: number, transaction: Sequelize.Transaction, callback: FindOrCreateAuthorCallback) => void
5} 8}
6 9
7export interface AuthorClass { 10export interface AuthorClass {
@@ -16,6 +19,9 @@ export interface AuthorInstance extends AuthorClass, AuthorAttributes, Sequelize
16 id: number 19 id: number
17 createdAt: Date 20 createdAt: Date
18 updatedAt: Date 21 updatedAt: Date
22
23 podId: number
24 Pod: PodInstance
19} 25}
20 26
21export interface AuthorModel extends AuthorClass, Sequelize.Model<AuthorInstance, AuthorAttributes> {} 27export interface AuthorModel extends AuthorClass, Sequelize.Model<AuthorInstance, AuthorAttributes> {}
diff --git a/server/models/author.ts b/server/models/author.ts
index b543d17a0..3264d3a88 100644
--- a/server/models/author.ts
+++ b/server/models/author.ts
@@ -74,12 +74,13 @@ function associate (models) {
74 }) 74 })
75} 75}
76 76
77findOrCreateAuthor = function (name, podId, userId, transaction, callback) { 77findOrCreateAuthor = function (
78 if (!callback) { 78 name: string,
79 callback = transaction 79 podId: number,
80 transaction = null 80 userId: number,
81 } 81 transaction: Sequelize.Transaction,
82 82 callback: AuthorMethods.FindOrCreateAuthorCallback
83) {
83 const author = { 84 const author = {
84 name, 85 name,
85 podId, 86 podId,
@@ -91,7 +92,7 @@ findOrCreateAuthor = function (name, podId, userId, transaction, callback) {
91 defaults: author 92 defaults: author
92 } 93 }
93 94
94 if (transaction) query.transaction = transaction 95 if (transaction !== null) query.transaction = transaction
95 96
96 Author.findOrCreate(query).asCallback(function (err, result) { 97 Author.findOrCreate(query).asCallback(function (err, result) {
97 if (err) return callback(err) 98 if (err) return callback(err)
diff --git a/server/models/job-interface.ts b/server/models/job-interface.ts
index ad4e2d2b0..ab6678257 100644
--- a/server/models/job-interface.ts
+++ b/server/models/job-interface.ts
@@ -1,7 +1,8 @@
1import * as Sequelize from 'sequelize' 1import * as Sequelize from 'sequelize'
2 2
3export namespace JobMethods { 3export namespace JobMethods {
4 export type ListWithLimit = (limit, state, callback) => void 4 export type ListWithLimitCallback = (err: Error, jobInstances: JobInstance[]) => void
5 export type ListWithLimit = (limit: number, state: string, callback: ListWithLimitCallback) => void
5} 6}
6 7
7export interface JobClass { 8export interface JobClass {
diff --git a/server/models/job.ts b/server/models/job.ts
index 982b51499..1afae8f08 100644
--- a/server/models/job.ts
+++ b/server/models/job.ts
@@ -48,7 +48,7 @@ export default function defineJob (sequelize: Sequelize.Sequelize, DataTypes) {
48 48
49// --------------------------------------------------------------------------- 49// ---------------------------------------------------------------------------
50 50
51listWithLimit = function (limit, state, callback) { 51listWithLimit = function (limit: number, state: string, callback: JobMethods.ListWithLimitCallback) {
52 const query = { 52 const query = {
53 order: [ 53 order: [
54 [ 'id', 'ASC' ] 54 [ 'id', 'ASC' ]
diff --git a/server/models/oauth-client-interface.ts b/server/models/oauth-client-interface.ts
index 4efd6212a..3b4325740 100644
--- a/server/models/oauth-client-interface.ts
+++ b/server/models/oauth-client-interface.ts
@@ -1,8 +1,12 @@
1import * as Sequelize from 'sequelize' 1import * as Sequelize from 'sequelize'
2 2
3export namespace OAuthClientMethods { 3export namespace OAuthClientMethods {
4 export type CountTotal = (callback) => void 4 export type CountTotalCallback = (err: Error, total: number) => void
5 export type LoadFirstClient = (callback) => void 5 export type CountTotal = (callback: CountTotalCallback) => void
6
7 export type LoadFirstClientCallback = (err: Error, client: OAuthClientInstance) => void
8 export type LoadFirstClient = (callback: LoadFirstClientCallback) => void
9
6 export type GetByIdAndSecret = (clientId, clientSecret) => void 10 export type GetByIdAndSecret = (clientId, clientSecret) => void
7} 11}
8 12
diff --git a/server/models/oauth-client.ts b/server/models/oauth-client.ts
index 2cefb5cb9..22fae2842 100644
--- a/server/models/oauth-client.ts
+++ b/server/models/oauth-client.ts
@@ -67,15 +67,15 @@ function associate (models) {
67 }) 67 })
68} 68}
69 69
70countTotal = function (callback) { 70countTotal = function (callback: OAuthClientMethods.CountTotalCallback) {
71 return OAuthClient.count().asCallback(callback) 71 return OAuthClient.count().asCallback(callback)
72} 72}
73 73
74loadFirstClient = function (callback) { 74loadFirstClient = function (callback: OAuthClientMethods.LoadFirstClientCallback) {
75 return OAuthClient.findOne().asCallback(callback) 75 return OAuthClient.findOne().asCallback(callback)
76} 76}
77 77
78getByIdAndSecret = function (clientId, clientSecret) { 78getByIdAndSecret = function (clientId: string, clientSecret: string) {
79 const query = { 79 const query = {
80 where: { 80 where: {
81 clientId: clientId, 81 clientId: clientId,
diff --git a/server/models/oauth-token-interface.ts b/server/models/oauth-token-interface.ts
index a0cd1ffe7..88526697e 100644
--- a/server/models/oauth-token-interface.ts
+++ b/server/models/oauth-token-interface.ts
@@ -1,11 +1,25 @@
1import * as Sequelize from 'sequelize' 1import * as Sequelize from 'sequelize'
2import * as Bluebird from 'bluebird'
2 3
3import { UserModel } from './user-interface' 4import { UserModel } from './user-interface'
4 5
6export type OAuthTokenInfo = {
7 refreshToken: string
8 refreshTokenExpiresAt: Date,
9 client: {
10 id: number
11 },
12 user: {
13 id: number
14 }
15}
16
5export namespace OAuthTokenMethods { 17export namespace OAuthTokenMethods {
6 export type GetByRefreshTokenAndPopulateClient = (refreshToken) => void 18 export type GetByRefreshTokenAndPopulateClient = (refreshToken: string) => Bluebird<OAuthTokenInfo>
7 export type GetByTokenAndPopulateUser = (bearerToken) => void 19 export type GetByTokenAndPopulateUser = (bearerToken: string) => Bluebird<OAuthTokenInstance>
8 export type GetByRefreshTokenAndPopulateUser = (refreshToken) => any 20 export type GetByRefreshTokenAndPopulateUser = (refreshToken: string) => Bluebird<OAuthTokenInstance>
21
22 export type RemoveByUserIdCallback = (err: Error) => void
9 export type RemoveByUserId = (userId, callback) => void 23 export type RemoveByUserId = (userId, callback) => void
10} 24}
11 25
diff --git a/server/models/oauth-token.ts b/server/models/oauth-token.ts
index 567df1c12..d70bd2bce 100644
--- a/server/models/oauth-token.ts
+++ b/server/models/oauth-token.ts
@@ -8,7 +8,8 @@ import {
8 OAuthTokenInstance, 8 OAuthTokenInstance,
9 OAuthTokenAttributes, 9 OAuthTokenAttributes,
10 10
11 OAuthTokenMethods 11 OAuthTokenMethods,
12 OAuthTokenInfo
12} from './oauth-token-interface' 13} from './oauth-token-interface'
13 14
14let OAuthToken: Sequelize.Model<OAuthTokenInstance, OAuthTokenAttributes> 15let OAuthToken: Sequelize.Model<OAuthTokenInstance, OAuthTokenAttributes>
@@ -90,7 +91,7 @@ function associate (models) {
90 }) 91 })
91} 92}
92 93
93getByRefreshTokenAndPopulateClient = function (refreshToken) { 94getByRefreshTokenAndPopulateClient = function (refreshToken: string) {
94 const query = { 95 const query = {
95 where: { 96 where: {
96 refreshToken: refreshToken 97 refreshToken: refreshToken
@@ -99,9 +100,9 @@ getByRefreshTokenAndPopulateClient = function (refreshToken) {
99 } 100 }
100 101
101 return OAuthToken.findOne(query).then(function (token) { 102 return OAuthToken.findOne(query).then(function (token) {
102 if (!token) return token 103 if (!token) return null
103 104
104 const tokenInfos = { 105 const tokenInfos: OAuthTokenInfo = {
105 refreshToken: token.refreshToken, 106 refreshToken: token.refreshToken,
106 refreshTokenExpiresAt: token.refreshTokenExpiresAt, 107 refreshTokenExpiresAt: token.refreshTokenExpiresAt,
107 client: { 108 client: {
@@ -118,7 +119,7 @@ getByRefreshTokenAndPopulateClient = function (refreshToken) {
118 }) 119 })
119} 120}
120 121
121getByTokenAndPopulateUser = function (bearerToken) { 122getByTokenAndPopulateUser = function (bearerToken: string) {
122 const query = { 123 const query = {
123 where: { 124 where: {
124 accessToken: bearerToken 125 accessToken: bearerToken
@@ -133,7 +134,7 @@ getByTokenAndPopulateUser = function (bearerToken) {
133 }) 134 })
134} 135}
135 136
136getByRefreshTokenAndPopulateUser = function (refreshToken) { 137getByRefreshTokenAndPopulateUser = function (refreshToken: string) {
137 const query = { 138 const query = {
138 where: { 139 where: {
139 refreshToken: refreshToken 140 refreshToken: refreshToken
diff --git a/server/models/pod-interface.ts b/server/models/pod-interface.ts
index 14c88bec6..8f362bd5c 100644
--- a/server/models/pod-interface.ts
+++ b/server/models/pod-interface.ts
@@ -1,18 +1,39 @@
1import * as Sequelize from 'sequelize' 1import * as Sequelize from 'sequelize'
2 2
3// Don't use barrel, import just what we need
4import { Pod as FormatedPod } from '../../shared/models/pod.model'
5
3export namespace PodMethods { 6export namespace PodMethods {
4 export type ToFormatedJSON = () => void 7 export type ToFormatedJSON = () => FormatedPod
5 8
9 export type CountAllCallback = (err: Error, total: number) => void
6 export type CountAll = (callback) => void 10 export type CountAll = (callback) => void
7 export type IncrementScores = (ids, value, callback) => void 11
8 export type List = (callback) => void 12 export type IncrementScoresCallback = (err: Error) => void
9 export type ListAllIds = (transaction, callback) => void 13 export type IncrementScores = (ids: number[], value: number, callback?: IncrementScoresCallback) => void
10 export type ListRandomPodIdsWithRequest = (limit, tableWithPods, tableWithPodsJoins, callback) => void 14
11 export type ListBadPods = (callback) => void 15 export type ListCallback = (err: Error, podInstances?: PodInstance[]) => void
12 export type Load = (id, callback) => void 16 export type List = (callback: ListCallback) => void
13 export type LoadByHost = (host, callback) => void 17
14 export type RemoveAll = (callback) => void 18 export type ListAllIdsCallback = (err: Error, ids?: number[]) => void
15 export type UpdatePodsScore = (goodPods, badPods) => void 19 export type ListAllIds = (transaction: Sequelize.Transaction, callback: ListAllIdsCallback) => void
20
21 export type ListRandomPodIdsWithRequestCallback = (err: Error, podInstanceIds?: number[]) => void
22 export type ListRandomPodIdsWithRequest = (limit: number, tableWithPods: string, tableWithPodsJoins: string, callback: ListRandomPodIdsWithRequestCallback) => void
23
24 export type ListBadPodsCallback = (err: Error, podInstances?: PodInstance[]) => void
25 export type ListBadPods = (callback: ListBadPodsCallback) => void
26
27 export type LoadCallback = (err: Error, podInstance: PodInstance) => void
28 export type Load = (id: number, callback: LoadCallback) => void
29
30 export type LoadByHostCallback = (err: Error, podInstance: PodInstance) => void
31 export type LoadByHost = (host: string, callback: LoadByHostCallback) => void
32
33 export type RemoveAllCallback = (err: Error) => void
34 export type RemoveAll = (callback: RemoveAllCallback) => void
35
36 export type UpdatePodsScore = (goodPods: number[], badPods: number[]) => void
16} 37}
17 38
18export interface PodClass { 39export interface PodClass {
diff --git a/server/models/pod.ts b/server/models/pod.ts
index 2df32e4a4..107744c43 100644
--- a/server/models/pod.ts
+++ b/server/models/pod.ts
@@ -118,11 +118,11 @@ function associate (models) {
118 }) 118 })
119} 119}
120 120
121countAll = function (callback) { 121countAll = function (callback: PodMethods.CountAllCallback) {
122 return Pod.count().asCallback(callback) 122 return Pod.count().asCallback(callback)
123} 123}
124 124
125incrementScores = function (ids, value, callback) { 125incrementScores = function (ids: number[], value: number, callback?: PodMethods.IncrementScoresCallback) {
126 if (!callback) callback = function () { /* empty */ } 126 if (!callback) callback = function () { /* empty */ }
127 127
128 const update = { 128 const update = {
@@ -142,35 +142,25 @@ incrementScores = function (ids, value, callback) {
142 return Pod.update(update, options).asCallback(callback) 142 return Pod.update(update, options).asCallback(callback)
143} 143}
144 144
145list = function (callback) { 145list = function (callback: PodMethods.ListCallback) {
146 return Pod.findAll().asCallback(callback) 146 return Pod.findAll().asCallback(callback)
147} 147}
148 148
149listAllIds = function (transaction, callback) { 149listAllIds = function (transaction: Sequelize.Transaction, callback: PodMethods.ListAllIdsCallback) {
150 if (!callback) {
151 callback = transaction
152 transaction = null
153 }
154
155 const query: any = { 150 const query: any = {
156 attributes: [ 'id' ] 151 attributes: [ 'id' ]
157 } 152 }
158 153
159 if (transaction) query.transaction = transaction 154 if (transaction !== null) query.transaction = transaction
160 155
161 return Pod.findAll(query).asCallback(function (err, pods) { 156 return Pod.findAll(query).asCallback(function (err: Error, pods) {
162 if (err) return callback(err) 157 if (err) return callback(err)
163 158
164 return callback(null, map(pods, 'id')) 159 return callback(null, map(pods, 'id'))
165 }) 160 })
166} 161}
167 162
168listRandomPodIdsWithRequest = function (limit, tableWithPods, tableWithPodsJoins, callback) { 163listRandomPodIdsWithRequest = function (limit: number, tableWithPods: string, tableWithPodsJoins: string, callback: PodMethods.ListRandomPodIdsWithRequestCallback) {
169 if (!callback) {
170 callback = tableWithPodsJoins
171 tableWithPodsJoins = ''
172 }
173
174 Pod.count().asCallback(function (err, count) { 164 Pod.count().asCallback(function (err, count) {
175 if (err) return callback(err) 165 if (err) return callback(err)
176 166
@@ -204,7 +194,7 @@ listRandomPodIdsWithRequest = function (limit, tableWithPods, tableWithPodsJoins
204 }) 194 })
205} 195}
206 196
207listBadPods = function (callback) { 197listBadPods = function (callback: PodMethods.ListBadPodsCallback) {
208 const query = { 198 const query = {
209 where: { 199 where: {
210 score: { $lte: 0 } 200 score: { $lte: 0 }
@@ -214,11 +204,11 @@ listBadPods = function (callback) {
214 return Pod.findAll(query).asCallback(callback) 204 return Pod.findAll(query).asCallback(callback)
215} 205}
216 206
217load = function (id, callback) { 207load = function (id: number, callback: PodMethods.LoadCallback) {
218 return Pod.findById(id).asCallback(callback) 208 return Pod.findById(id).asCallback(callback)
219} 209}
220 210
221loadByHost = function (host, callback) { 211loadByHost = function (host: string, callback: PodMethods.LoadByHostCallback) {
222 const query = { 212 const query = {
223 where: { 213 where: {
224 host: host 214 host: host
@@ -228,11 +218,11 @@ loadByHost = function (host, callback) {
228 return Pod.findOne(query).asCallback(callback) 218 return Pod.findOne(query).asCallback(callback)
229} 219}
230 220
231removeAll = function (callback) { 221removeAll = function (callback: PodMethods.RemoveAllCallback) {
232 return Pod.destroy().asCallback(callback) 222 return Pod.destroy().asCallback(callback)
233} 223}
234 224
235updatePodsScore = function (goodPods, badPods) { 225updatePodsScore = function (goodPods: number[], badPods: number[]) {
236 logger.info('Updating %d good pods and %d bad pods scores.', goodPods.length, badPods.length) 226 logger.info('Updating %d good pods and %d bad pods scores.', goodPods.length, badPods.length)
237 227
238 if (goodPods.length !== 0) { 228 if (goodPods.length !== 0) {
diff --git a/server/models/request-interface.ts b/server/models/request-interface.ts
index 2bba8ce7f..4bbd79966 100644
--- a/server/models/request-interface.ts
+++ b/server/models/request-interface.ts
@@ -1,12 +1,26 @@
1import * as Sequelize from 'sequelize' 1import * as Sequelize from 'sequelize'
2 2
3import { PodAttributes } from './pod-interface' 3import { PodInstance, PodAttributes } from './pod-interface'
4
5export type RequestsGrouped = {
6 [ podId: number ]: {
7 request: RequestInstance,
8 pod: PodInstance
9 }[]
10}
4 11
5export namespace RequestMethods { 12export namespace RequestMethods {
6 export type CountTotalRequests = (callback) => void 13 export type CountTotalRequestsCallback = (err: Error, total: number) => void
7 export type ListWithLimitAndRandom = (limitPods, limitRequestsPerPod, callback) => void 14 export type CountTotalRequests = (callback: CountTotalRequestsCallback) => void
8 export type RemoveWithEmptyTo = (callback) => void 15
9 export type RemoveAll = (callback) => void 16 export type ListWithLimitAndRandomCallback = (err: Error, requestsGrouped?: RequestsGrouped) => void
17 export type ListWithLimitAndRandom = (limitPods, limitRequestsPerPod, callback: ListWithLimitAndRandomCallback) => void
18
19 export type RemoveWithEmptyToCallback = (err: Error) => void
20 export type RemoveWithEmptyTo = (callback: RemoveWithEmptyToCallback) => void
21
22 export type RemoveAllCallback = (err: Error) => void
23 export type RemoveAll = (callback: RemoveAllCallback) => void
10} 24}
11 25
12export interface RequestClass { 26export interface RequestClass {
@@ -21,12 +35,13 @@ export interface RequestAttributes {
21 endpoint: string 35 endpoint: string
22} 36}
23 37
24export interface RequestInstance extends Sequelize.Instance<RequestAttributes> { 38export interface RequestInstance extends RequestClass, RequestAttributes, Sequelize.Instance<RequestAttributes> {
25 id: number 39 id: number
26 createdAt: Date 40 createdAt: Date
27 updatedAt: Date 41 updatedAt: Date
28 42
29 setPods: Sequelize.HasManySetAssociationsMixin<PodAttributes, number> 43 setPods: Sequelize.HasManySetAssociationsMixin<PodAttributes, number>
44 Pods: PodInstance[]
30} 45}
31 46
32export interface RequestModel extends RequestClass, Sequelize.Model<RequestInstance, RequestAttributes> {} 47export interface RequestModel extends RequestClass, Sequelize.Model<RequestInstance, RequestAttributes> {}
diff --git a/server/models/request-to-pod-interface.ts b/server/models/request-to-pod-interface.ts
index 52116d6c4..6d75ca6e5 100644
--- a/server/models/request-to-pod-interface.ts
+++ b/server/models/request-to-pod-interface.ts
@@ -1,7 +1,8 @@
1import * as Sequelize from 'sequelize' 1import * as Sequelize from 'sequelize'
2 2
3export namespace RequestToPodMethods { 3export namespace RequestToPodMethods {
4 export type RemoveByRequestIdsAndPod = (requestsIds, podId, callback) => void 4 export type RemoveByRequestIdsAndPodCallback = (err: Error) => void
5 export type RemoveByRequestIdsAndPod = (requestsIds: number[], podId: number, callback?: RemoveByRequestIdsAndPodCallback) => void
5} 6}
6 7
7export interface RequestToPodClass { 8export interface RequestToPodClass {
@@ -11,7 +12,7 @@ export interface RequestToPodClass {
11export interface RequestToPodAttributes { 12export interface RequestToPodAttributes {
12} 13}
13 14
14export interface RequestToPodInstance extends Sequelize.Instance<RequestToPodAttributes> { 15export interface RequestToPodInstance extends RequestToPodClass, RequestToPodAttributes, Sequelize.Instance<RequestToPodAttributes> {
15 id: number 16 id: number
16 createdAt: Date 17 createdAt: Date
17 updatedAt: Date 18 updatedAt: Date
diff --git a/server/models/request-to-pod.ts b/server/models/request-to-pod.ts
index 681f808b7..3562069cc 100644
--- a/server/models/request-to-pod.ts
+++ b/server/models/request-to-pod.ts
@@ -38,7 +38,7 @@ export default function (sequelize, DataTypes) {
38 38
39// --------------------------------------------------------------------------- 39// ---------------------------------------------------------------------------
40 40
41removeByRequestIdsAndPod = function (requestsIds, podId, callback) { 41removeByRequestIdsAndPod = function (requestsIds: number[], podId: number, callback?: RequestToPodMethods.RemoveByRequestIdsAndPodCallback) {
42 if (!callback) callback = function () { /* empty */ } 42 if (!callback) callback = function () { /* empty */ }
43 43
44 const query = { 44 const query = {
diff --git a/server/models/request-video-event-interface.ts b/server/models/request-video-event-interface.ts
index a31c7108f..ad576a2b1 100644
--- a/server/models/request-video-event-interface.ts
+++ b/server/models/request-video-event-interface.ts
@@ -1,10 +1,30 @@
1import * as Sequelize from 'sequelize' 1import * as Sequelize from 'sequelize'
2 2
3import { VideoInstance } from './video-interface'
4import { PodInstance } from './pod-interface'
5
6export type RequestsVideoEventGrouped = {
7 [ podId: number ]: {
8 id: number
9 type: string
10 count: number
11 video: VideoInstance
12 pod: PodInstance
13 }[]
14}
15
3export namespace RequestVideoEventMethods { 16export namespace RequestVideoEventMethods {
4 export type CountTotalRequests = (callback) => void 17 export type CountTotalRequestsCallback = (err: Error, total: number) => void
5 export type ListWithLimitAndRandom = (limitPods, limitRequestsPerPod, callback) => void 18 export type CountTotalRequests = (callback: CountTotalRequestsCallback) => void
6 export type RemoveByRequestIdsAndPod = (ids, podId, callback) => void 19
7 export type RemoveAll = (callback) => void 20 export type ListWithLimitAndRandomCallback = (err: Error, requestsGrouped?: RequestsVideoEventGrouped) => void
21 export type ListWithLimitAndRandom = (limitPods: number, limitRequestsPerPod: number, callback: ListWithLimitAndRandomCallback) => void
22
23 export type RemoveByRequestIdsAndPodCallback = () => void
24 export type RemoveByRequestIdsAndPod = (ids: number[], podId: number, callback: RemoveByRequestIdsAndPodCallback) => void
25
26 export type RemoveAllCallback = () => void
27 export type RemoveAll = (callback: RemoveAllCallback) => void
8} 28}
9 29
10export interface RequestVideoEventClass { 30export interface RequestVideoEventClass {
@@ -19,8 +39,10 @@ export interface RequestVideoEventAttributes {
19 count: number 39 count: number
20} 40}
21 41
22export interface RequestVideoEventInstance extends Sequelize.Instance<RequestVideoEventAttributes> { 42export interface RequestVideoEventInstance extends RequestVideoEventClass, RequestVideoEventAttributes, Sequelize.Instance<RequestVideoEventAttributes> {
23 id: number 43 id: number
44
45 Video: VideoInstance
24} 46}
25 47
26export interface RequestVideoEventModel extends RequestVideoEventClass, Sequelize.Model<RequestVideoEventInstance, RequestVideoEventAttributes> {} 48export interface RequestVideoEventModel extends RequestVideoEventClass, Sequelize.Model<RequestVideoEventInstance, RequestVideoEventAttributes> {}
diff --git a/server/models/request-video-event.ts b/server/models/request-video-event.ts
index 234e2a8a9..e422649af 100644
--- a/server/models/request-video-event.ts
+++ b/server/models/request-video-event.ts
@@ -5,16 +5,17 @@
5import { values } from 'lodash' 5import { values } from 'lodash'
6import * as Sequelize from 'sequelize' 6import * as Sequelize from 'sequelize'
7 7
8import { database as db } from '../initializers/database'
8import { REQUEST_VIDEO_EVENT_TYPES } from '../initializers' 9import { REQUEST_VIDEO_EVENT_TYPES } from '../initializers'
9import { isVideoEventCountValid } from '../helpers' 10import { isVideoEventCountValid } from '../helpers'
10
11import { addMethodsToModel } from './utils' 11import { addMethodsToModel } from './utils'
12import { 12import {
13 RequestVideoEventClass, 13 RequestVideoEventClass,
14 RequestVideoEventInstance, 14 RequestVideoEventInstance,
15 RequestVideoEventAttributes, 15 RequestVideoEventAttributes,
16 16
17 RequestVideoEventMethods 17 RequestVideoEventMethods,
18 RequestsVideoEventGrouped
18} from './request-video-event-interface' 19} from './request-video-event-interface'
19 20
20let RequestVideoEvent: Sequelize.Model<RequestVideoEventInstance, RequestVideoEventAttributes> 21let RequestVideoEvent: Sequelize.Model<RequestVideoEventInstance, RequestVideoEventAttributes>
@@ -76,13 +77,13 @@ function associate (models) {
76 }) 77 })
77} 78}
78 79
79countTotalRequests = function (callback) { 80countTotalRequests = function (callback: RequestVideoEventMethods.CountTotalRequestsCallback) {
80 const query = {} 81 const query = {}
81 return RequestVideoEvent.count(query).asCallback(callback) 82 return RequestVideoEvent.count(query).asCallback(callback)
82} 83}
83 84
84listWithLimitAndRandom = function (limitPods, limitRequestsPerPod, callback) { 85listWithLimitAndRandom = function (limitPods: number, limitRequestsPerPod: number, callback: RequestVideoEventMethods.ListWithLimitAndRandomCallback) {
85 const Pod = RequestVideoEvent['sequelize'].models.Pod 86 const Pod = db.Pod
86 87
87 // We make a join between videos and authors to find the podId of our video event requests 88 // We make a join between videos and authors to find the podId of our video event requests
88 const podJoins = 'INNER JOIN "Videos" ON "Videos"."authorId" = "Authors"."id" ' + 89 const podJoins = 'INNER JOIN "Videos" ON "Videos"."authorId" = "Authors"."id" ' +
@@ -129,7 +130,7 @@ listWithLimitAndRandom = function (limitPods, limitRequestsPerPod, callback) {
129 }) 130 })
130} 131}
131 132
132removeByRequestIdsAndPod = function (ids, podId, callback) { 133removeByRequestIdsAndPod = function (ids: number[], podId: number, callback: RequestVideoEventMethods.RemoveByRequestIdsAndPodCallback) {
133 const query = { 134 const query = {
134 where: { 135 where: {
135 id: { 136 id: {
@@ -154,15 +155,15 @@ removeByRequestIdsAndPod = function (ids, podId, callback) {
154 RequestVideoEvent.destroy(query).asCallback(callback) 155 RequestVideoEvent.destroy(query).asCallback(callback)
155} 156}
156 157
157removeAll = function (callback) { 158removeAll = function (callback: RequestVideoEventMethods.RemoveAllCallback) {
158 // Delete all requests 159 // Delete all requests
159 RequestVideoEvent.truncate({ cascade: true }).asCallback(callback) 160 RequestVideoEvent.truncate({ cascade: true }).asCallback(callback)
160} 161}
161 162
162// --------------------------------------------------------------------------- 163// ---------------------------------------------------------------------------
163 164
164function groupAndTruncateRequests (events, limitRequestsPerPod) { 165function groupAndTruncateRequests (events: RequestVideoEventInstance[], limitRequestsPerPod: number) {
165 const eventsGrouped = {} 166 const eventsGrouped: RequestsVideoEventGrouped = {}
166 167
167 events.forEach(function (event) { 168 events.forEach(function (event) {
168 const pod = event.Video.Author.Pod 169 const pod = event.Video.Author.Pod
diff --git a/server/models/request-video-qadu-interface.ts b/server/models/request-video-qadu-interface.ts
index 6fe34ee91..04de7f159 100644
--- a/server/models/request-video-qadu-interface.ts
+++ b/server/models/request-video-qadu-interface.ts
@@ -1,10 +1,28 @@
1import * as Sequelize from 'sequelize' 1import * as Sequelize from 'sequelize'
2 2
3import { VideoInstance } from './video-interface'
4import { PodInstance } from './pod-interface'
5
6export type RequestsVideoQaduGrouped = {
7 [ podId: number ]: {
8 request: RequestVideoQaduInstance
9 video: VideoInstance
10 pod: PodInstance
11 }
12}
13
3export namespace RequestVideoQaduMethods { 14export namespace RequestVideoQaduMethods {
4 export type CountTotalRequests = (callback) => void 15 export type CountTotalRequestsCallback = (err: Error, total: number) => void
5 export type ListWithLimitAndRandom = (limitPods, limitRequestsPerPod, callback) => void 16 export type CountTotalRequests = (callback: CountTotalRequestsCallback) => void
6 export type RemoveByRequestIdsAndPod = (ids, podId, callback) => void 17
7 export type RemoveAll = (callback) => void 18 export type ListWithLimitAndRandomCallback = (err: Error, requestsGrouped?: RequestsVideoQaduGrouped) => void
19 export type ListWithLimitAndRandom = (limitPods: number, limitRequestsPerPod: number, callback: ListWithLimitAndRandomCallback) => void
20
21 export type RemoveByRequestIdsAndPodCallback = () => void
22 export type RemoveByRequestIdsAndPod = (ids: number[], podId: number, callback: RemoveByRequestIdsAndPodCallback) => void
23
24 export type RemoveAllCallback = () => void
25 export type RemoveAll = (callback: RemoveAllCallback) => void
8} 26}
9 27
10export interface RequestVideoQaduClass { 28export interface RequestVideoQaduClass {
@@ -18,8 +36,11 @@ export interface RequestVideoQaduAttributes {
18 type: string 36 type: string
19} 37}
20 38
21export interface RequestVideoQaduInstance extends Sequelize.Instance<RequestVideoQaduAttributes> { 39export interface RequestVideoQaduInstance extends RequestVideoQaduClass, RequestVideoQaduAttributes, Sequelize.Instance<RequestVideoQaduAttributes> {
22 id: number 40 id: number
41
42 Pod: PodInstance
43 Video: VideoInstance
23} 44}
24 45
25export interface RequestVideoQaduModel extends RequestVideoQaduClass, Sequelize.Model<RequestVideoQaduInstance, RequestVideoQaduAttributes> {} 46export interface RequestVideoQaduModel extends RequestVideoQaduClass, Sequelize.Model<RequestVideoQaduInstance, RequestVideoQaduAttributes> {}
diff --git a/server/models/request-video-qadu.ts b/server/models/request-video-qadu.ts
index e914e06cd..38627ad55 100644
--- a/server/models/request-video-qadu.ts
+++ b/server/models/request-video-qadu.ts
@@ -12,8 +12,8 @@
12import { values } from 'lodash' 12import { values } from 'lodash'
13import * as Sequelize from 'sequelize' 13import * as Sequelize from 'sequelize'
14 14
15import { database as db } from '../initializers/database'
15import { REQUEST_VIDEO_QADU_TYPES } from '../initializers' 16import { REQUEST_VIDEO_QADU_TYPES } from '../initializers'
16
17import { addMethodsToModel } from './utils' 17import { addMethodsToModel } from './utils'
18import { 18import {
19 RequestVideoQaduClass, 19 RequestVideoQaduClass,
@@ -83,15 +83,16 @@ function associate (models) {
83 }) 83 })
84} 84}
85 85
86countTotalRequests = function (callback) { 86countTotalRequests = function (callback: RequestVideoQaduMethods.CountTotalRequestsCallback) {
87 const query = {} 87 const query = {}
88 return RequestVideoQadu.count(query).asCallback(callback) 88 return RequestVideoQadu.count(query).asCallback(callback)
89} 89}
90 90
91listWithLimitAndRandom = function (limitPods, limitRequestsPerPod, callback) { 91listWithLimitAndRandom = function (limitPods: number, limitRequestsPerPod: number, callback: RequestVideoQaduMethods.ListWithLimitAndRandomCallback) {
92 const Pod = RequestVideoQadu['sequelize'].models.Pod 92 const Pod = db.Pod
93 const tableJoin = ''
93 94
94 Pod.listRandomPodIdsWithRequest(limitPods, 'RequestVideoQadus', function (err, podIds) { 95 Pod.listRandomPodIdsWithRequest(limitPods, 'RequestVideoQadus', tableJoin, function (err, podIds) {
95 if (err) return callback(err) 96 if (err) return callback(err)
96 97
97 // We don't have friends that have requests 98 // We don't have friends that have requests
@@ -122,7 +123,7 @@ listWithLimitAndRandom = function (limitPods, limitRequestsPerPod, callback) {
122 }) 123 })
123} 124}
124 125
125removeByRequestIdsAndPod = function (ids, podId, callback) { 126removeByRequestIdsAndPod = function (ids: number[], podId: number, callback: RequestVideoQaduMethods.RemoveByRequestIdsAndPodCallback) {
126 const query = { 127 const query = {
127 where: { 128 where: {
128 id: { 129 id: {
@@ -135,14 +136,14 @@ removeByRequestIdsAndPod = function (ids, podId, callback) {
135 RequestVideoQadu.destroy(query).asCallback(callback) 136 RequestVideoQadu.destroy(query).asCallback(callback)
136} 137}
137 138
138removeAll = function (callback) { 139removeAll = function (callback: RequestVideoQaduMethods.RemoveAllCallback) {
139 // Delete all requests 140 // Delete all requests
140 RequestVideoQadu.truncate({ cascade: true }).asCallback(callback) 141 RequestVideoQadu.truncate({ cascade: true }).asCallback(callback)
141} 142}
142 143
143// --------------------------------------------------------------------------- 144// ---------------------------------------------------------------------------
144 145
145function groupAndTruncateRequests (requests, limitRequestsPerPod) { 146function groupAndTruncateRequests (requests: RequestVideoQaduInstance[], limitRequestsPerPod: number) {
146 const requestsGrouped = {} 147 const requestsGrouped = {}
147 148
148 requests.forEach(function (request) { 149 requests.forEach(function (request) {
diff --git a/server/models/request.ts b/server/models/request.ts
index 18fa291fa..71f81ae66 100644
--- a/server/models/request.ts
+++ b/server/models/request.ts
@@ -1,15 +1,16 @@
1import { values } from 'lodash' 1import { values } from 'lodash'
2import * as Sequelize from 'sequelize' 2import * as Sequelize from 'sequelize'
3 3
4import { database as db } from '../initializers/database'
4import { REQUEST_ENDPOINTS } from '../initializers' 5import { REQUEST_ENDPOINTS } from '../initializers'
5
6import { addMethodsToModel } from './utils' 6import { addMethodsToModel } from './utils'
7import { 7import {
8 RequestClass, 8 RequestClass,
9 RequestInstance, 9 RequestInstance,
10 RequestAttributes, 10 RequestAttributes,
11 11
12 RequestMethods 12 RequestMethods,
13 RequestsGrouped
13} from './request-interface' 14} from './request-interface'
14 15
15let Request: Sequelize.Model<RequestInstance, RequestAttributes> 16let Request: Sequelize.Model<RequestInstance, RequestAttributes>
@@ -59,7 +60,7 @@ function associate (models) {
59 }) 60 })
60} 61}
61 62
62countTotalRequests = function (callback) { 63countTotalRequests = function (callback: RequestMethods.CountTotalRequestsCallback) {
63 // We need to include Pod because there are no cascade delete when a pod is removed 64 // We need to include Pod because there are no cascade delete when a pod is removed
64 // So we could count requests that do not have existing pod anymore 65 // So we could count requests that do not have existing pod anymore
65 const query = { 66 const query = {
@@ -69,10 +70,11 @@ countTotalRequests = function (callback) {
69 return Request.count(query).asCallback(callback) 70 return Request.count(query).asCallback(callback)
70} 71}
71 72
72listWithLimitAndRandom = function (limitPods, limitRequestsPerPod, callback) { 73listWithLimitAndRandom = function (limitPods: number, limitRequestsPerPod: number, callback: RequestMethods.ListWithLimitAndRandomCallback) {
73 const Pod = Request['sequelize'].models.Pod 74 const Pod = db.Pod
75 const tableJoin = ''
74 76
75 Pod.listRandomPodIdsWithRequest(limitPods, 'RequestToPods', function (err, podIds) { 77 Pod.listRandomPodIdsWithRequest(limitPods, 'RequestToPods', '', function (err, podIds) {
76 if (err) return callback(err) 78 if (err) return callback(err)
77 79
78 // We don't have friends that have requests 80 // We don't have friends that have requests
@@ -105,12 +107,12 @@ listWithLimitAndRandom = function (limitPods, limitRequestsPerPod, callback) {
105 }) 107 })
106} 108}
107 109
108removeAll = function (callback) { 110removeAll = function (callback: RequestMethods.RemoveAllCallback) {
109 // Delete all requests 111 // Delete all requests
110 Request.truncate({ cascade: true }).asCallback(callback) 112 Request.truncate({ cascade: true }).asCallback(callback)
111} 113}
112 114
113removeWithEmptyTo = function (callback) { 115removeWithEmptyTo = function (callback?: RequestMethods.RemoveWithEmptyToCallback) {
114 if (!callback) callback = function () { /* empty */ } 116 if (!callback) callback = function () { /* empty */ }
115 117
116 const query = { 118 const query = {
@@ -128,8 +130,8 @@ removeWithEmptyTo = function (callback) {
128 130
129// --------------------------------------------------------------------------- 131// ---------------------------------------------------------------------------
130 132
131function groupAndTruncateRequests (requests, limitRequestsPerPod) { 133function groupAndTruncateRequests (requests: RequestInstance[], limitRequestsPerPod: number) {
132 const requestsGrouped = {} 134 const requestsGrouped: RequestsGrouped = {}
133 135
134 requests.forEach(function (request) { 136 requests.forEach(function (request) {
135 request.Pods.forEach(function (pod) { 137 request.Pods.forEach(function (pod) {
diff --git a/server/models/tag-interface.ts b/server/models/tag-interface.ts
index f96e1e9c5..e045e7ca5 100644
--- a/server/models/tag-interface.ts
+++ b/server/models/tag-interface.ts
@@ -1,7 +1,8 @@
1import * as Sequelize from 'sequelize' 1import * as Sequelize from 'sequelize'
2 2
3export namespace TagMethods { 3export namespace TagMethods {
4 export type FindOrCreateTags = (tags, transaction, callback) => void 4 export type FindOrCreateTagsCallback = (err: Error, tagInstances: TagInstance[]) => void
5 export type FindOrCreateTags = (tags: string[], transaction: Sequelize.Transaction, callback: FindOrCreateTagsCallback) => void
5} 6}
6 7
7export interface TagClass { 8export interface TagClass {
diff --git a/server/models/tag.ts b/server/models/tag.ts
index b2a9c9f81..c4402e83c 100644
--- a/server/models/tag.ts
+++ b/server/models/tag.ts
@@ -52,15 +52,10 @@ function associate (models) {
52 }) 52 })
53} 53}
54 54
55findOrCreateTags = function (tags, transaction, callback) { 55findOrCreateTags = function (tags: string[], transaction: Sequelize.Transaction, callback: TagMethods.FindOrCreateTagsCallback) {
56 if (!callback) {
57 callback = transaction
58 transaction = null
59 }
60
61 const tagInstances = [] 56 const tagInstances = []
62 57
63 each(tags, function (tag, callbackEach) { 58 each<string, Error>(tags, function (tag, callbackEach) {
64 const query: any = { 59 const query: any = {
65 where: { 60 where: {
66 name: tag 61 name: tag
diff --git a/server/models/user-interface.ts b/server/models/user-interface.ts
index a504f42a1..98963b743 100644
--- a/server/models/user-interface.ts
+++ b/server/models/user-interface.ts
@@ -1,17 +1,35 @@
1import * as Sequelize from 'sequelize' 1import * as Sequelize from 'sequelize'
2import * as Bluebird from 'bluebird'
3
4// Don't use barrel, import just what we need
5import { User as FormatedUser } from '../../shared/models/user.model'
2 6
3export namespace UserMethods { 7export namespace UserMethods {
4 export type IsPasswordMatch = (password, callback) => void 8 export type IsPasswordMatchCallback = (err: Error, same: boolean) => void
5 export type ToFormatedJSON = () => void 9 export type IsPasswordMatch = (password: string, callback: IsPasswordMatchCallback) => void
10
11 export type ToFormatedJSON = () => FormatedUser
6 export type IsAdmin = () => boolean 12 export type IsAdmin = () => boolean
7 13
8 export type CountTotal = (callback) => void 14 export type CountTotalCallback = (err: Error, total: number) => void
9 export type GetByUsername = (username) => any 15 export type CountTotal = (callback: CountTotalCallback) => void
10 export type List = (callback) => void 16
11 export type ListForApi = (start, count, sort, callback) => void 17 export type GetByUsername = (username: string) => Bluebird<UserInstance>
12 export type LoadById = (id, callback) => void 18
13 export type LoadByUsername = (username, callback) => void 19 export type ListCallback = (err: Error, userInstances: UserInstance[]) => void
14 export type LoadByUsernameOrEmail = (username, email, callback) => void 20 export type List = (callback: ListCallback) => void
21
22 export type ListForApiCallback = (err: Error, userInstances?: UserInstance[], total?: number) => void
23 export type ListForApi = (start: number, count: number, sort: string, callback: ListForApiCallback) => void
24
25 export type LoadByIdCallback = (err: Error, userInstance: UserInstance) => void
26 export type LoadById = (id: number, callback: LoadByIdCallback) => void
27
28 export type LoadByUsernameCallback = (err: Error, userInstance: UserInstance) => void
29 export type LoadByUsername = (username: string, callback: LoadByUsernameCallback) => void
30
31 export type LoadByUsernameOrEmailCallback = (err: Error, userInstance: UserInstance) => void
32 export type LoadByUsernameOrEmail = (username: string, email: string, callback: LoadByUsernameOrEmailCallback) => void
15} 33}
16 34
17export interface UserClass { 35export interface UserClass {
diff --git a/server/models/user-video-rate-interface.ts b/server/models/user-video-rate-interface.ts
index 57d2e2b91..e48869fd2 100644
--- a/server/models/user-video-rate-interface.ts
+++ b/server/models/user-video-rate-interface.ts
@@ -1,6 +1,7 @@
1import * as Sequelize from 'sequelize' 1import * as Sequelize from 'sequelize'
2 2
3export namespace UserVideoRateMethods { 3export namespace UserVideoRateMethods {
4 export type LoadCallback = (err: Error, userVideoRateInstance: UserVideoRateInstance) => void
4 export type Load = (userId, videoId, transaction, callback) => void 5 export type Load = (userId, videoId, transaction, callback) => void
5} 6}
6 7
@@ -12,7 +13,7 @@ export interface UserVideoRateAttributes {
12 type: string 13 type: string
13} 14}
14 15
15export interface UserVideoRateInstance extends Sequelize.Instance<UserVideoRateAttributes> { 16export interface UserVideoRateInstance extends UserVideoRateClass, UserVideoRateAttributes, Sequelize.Instance<UserVideoRateAttributes> {
16 id: number 17 id: number
17 createdAt: Date 18 createdAt: Date
18 updatedAt: Date 19 updatedAt: Date
diff --git a/server/models/user-video-rate.ts b/server/models/user-video-rate.ts
index 87886d8d0..6b71e8412 100644
--- a/server/models/user-video-rate.ts
+++ b/server/models/user-video-rate.ts
@@ -67,7 +67,7 @@ function associate (models) {
67 }) 67 })
68} 68}
69 69
70load = function (userId, videoId, transaction, callback) { 70load = function (userId: number, videoId: number, transaction: Sequelize.Transaction, callback: UserVideoRateMethods.LoadCallback) {
71 const options: Sequelize.FindOptions = { 71 const options: Sequelize.FindOptions = {
72 where: { 72 where: {
73 userId, 73 userId,
diff --git a/server/models/user.ts b/server/models/user.ts
index 12ddaaeb7..0fbfdda50 100644
--- a/server/models/user.ts
+++ b/server/models/user.ts
@@ -117,7 +117,7 @@ export default function (sequelize, DataTypes) {
117 return User 117 return User
118} 118}
119 119
120function beforeCreateOrUpdate (user, options) { 120function beforeCreateOrUpdate (user: UserInstance) {
121 return new Promise(function (resolve, reject) { 121 return new Promise(function (resolve, reject) {
122 cryptPassword(user.password, function (err, hash) { 122 cryptPassword(user.password, function (err, hash) {
123 if (err) return reject(err) 123 if (err) return reject(err)
@@ -131,7 +131,7 @@ function beforeCreateOrUpdate (user, options) {
131 131
132// ------------------------------ METHODS ------------------------------ 132// ------------------------------ METHODS ------------------------------
133 133
134isPasswordMatch = function (password, callback) { 134isPasswordMatch = function (password: string, callback: UserMethods.IsPasswordMatchCallback) {
135 return comparePassword(password, this.password, callback) 135 return comparePassword(password, this.password, callback)
136} 136}
137 137
@@ -164,11 +164,11 @@ function associate (models) {
164 }) 164 })
165} 165}
166 166
167countTotal = function (callback) { 167countTotal = function (callback: UserMethods.CountTotalCallback) {
168 return this.count().asCallback(callback) 168 return this.count().asCallback(callback)
169} 169}
170 170
171getByUsername = function (username) { 171getByUsername = function (username: string) {
172 const query = { 172 const query = {
173 where: { 173 where: {
174 username: username 174 username: username
@@ -178,11 +178,11 @@ getByUsername = function (username) {
178 return User.findOne(query) 178 return User.findOne(query)
179} 179}
180 180
181list = function (callback) { 181list = function (callback: UserMethods.ListCallback) {
182 return User.find().asCallback(callback) 182 return User.find().asCallback(callback)
183} 183}
184 184
185listForApi = function (start, count, sort, callback) { 185listForApi = function (start: number, count: number, sort: string, callback: UserMethods.ListForApiCallback) {
186 const query = { 186 const query = {
187 offset: start, 187 offset: start,
188 limit: count, 188 limit: count,
@@ -196,11 +196,11 @@ listForApi = function (start, count, sort, callback) {
196 }) 196 })
197} 197}
198 198
199loadById = function (id, callback) { 199loadById = function (id: number, callback: UserMethods.LoadByIdCallback) {
200 return User.findById(id).asCallback(callback) 200 return User.findById(id).asCallback(callback)
201} 201}
202 202
203loadByUsername = function (username, callback) { 203loadByUsername = function (username: string, callback: UserMethods.LoadByUsernameCallback) {
204 const query = { 204 const query = {
205 where: { 205 where: {
206 username: username 206 username: username
@@ -210,7 +210,7 @@ loadByUsername = function (username, callback) {
210 return User.findOne(query).asCallback(callback) 210 return User.findOne(query).asCallback(callback)
211} 211}
212 212
213loadByUsernameOrEmail = function (username, email, callback) { 213loadByUsernameOrEmail = function (username: string, email: string, callback: UserMethods.LoadByUsernameOrEmailCallback) {
214 const query = { 214 const query = {
215 where: { 215 where: {
216 $or: [ { username }, { email } ] 216 $or: [ { username }, { email } ]
diff --git a/server/models/utils.ts b/server/models/utils.ts
index fd84a9239..7ba96815e 100644
--- a/server/models/utils.ts
+++ b/server/models/utils.ts
@@ -1,7 +1,7 @@
1// Translate for example "-name" to [ 'name', 'DESC' ] 1// Translate for example "-name" to [ 'name', 'DESC' ]
2function getSort (value) { 2function getSort (value: string) {
3 let field 3 let field: string
4 let direction 4 let direction: 'ASC' | 'DESC'
5 5
6 if (value.substring(0, 1) === '-') { 6 if (value.substring(0, 1) === '-') {
7 direction = 'DESC' 7 direction = 'DESC'
diff --git a/server/models/video-abuse-interface.ts b/server/models/video-abuse-interface.ts
index 9b77fc6f5..d9cb93b42 100644
--- a/server/models/video-abuse-interface.ts
+++ b/server/models/video-abuse-interface.ts
@@ -1,9 +1,13 @@
1import * as Sequelize from 'sequelize' 1import * as Sequelize from 'sequelize'
2 2
3// Don't use barrel, import just what we need
4import { VideoAbuse as FormatedVideoAbuse } from '../../shared/models/video-abuse.model'
5
3export namespace VideoAbuseMethods { 6export namespace VideoAbuseMethods {
4 export type toFormatedJSON = () => void 7 export type toFormatedJSON = () => FormatedVideoAbuse
5 8
6 export type ListForApi = (start, count, sort, callback) => void 9 export type ListForApiCallback = (err: Error, videoAbuseInstances?: VideoAbuseInstance[], total?: number) => void
10 export type ListForApi = (start: number, count: number, sort: string, callback: ListForApiCallback) => void
7} 11}
8 12
9export interface VideoAbuseClass { 13export interface VideoAbuseClass {
@@ -15,7 +19,7 @@ export interface VideoAbuseAttributes {
15 reason: string 19 reason: string
16} 20}
17 21
18export interface VideoAbuseInstance extends Sequelize.Instance<VideoAbuseAttributes> { 22export interface VideoAbuseInstance extends VideoAbuseClass, VideoAbuseAttributes, Sequelize.Instance<VideoAbuseAttributes> {
19 id: number 23 id: number
20 createdAt: Date 24 createdAt: Date
21 updatedAt: Date 25 updatedAt: Date
diff --git a/server/models/video-blacklist-interface.ts b/server/models/video-blacklist-interface.ts
index ae2cd6748..974718192 100644
--- a/server/models/video-blacklist-interface.ts
+++ b/server/models/video-blacklist-interface.ts
@@ -1,13 +1,25 @@
1import * as Sequelize from 'sequelize' 1import * as Sequelize from 'sequelize'
2 2
3// Don't use barrel, import just what we need
4import { BlacklistedVideo as FormatedBlacklistedVideo } from '../../shared/models/video-blacklist.model'
5
3export namespace BlacklistedVideoMethods { 6export namespace BlacklistedVideoMethods {
4 export type ToFormatedJSON = () => void 7 export type ToFormatedJSON = () => FormatedBlacklistedVideo
8
9 export type CountTotalCallback = (err: Error, total: number) => void
10 export type CountTotal = (callback: CountTotalCallback) => void
11
12 export type ListCallback = (err: Error, backlistedVideoInstances: BlacklistedVideoInstance[]) => void
13 export type List = (callback: ListCallback) => void
14
15 export type ListForApiCallback = (err: Error, blacklistedVIdeoInstances?: BlacklistedVideoInstance[], total?: number) => void
16 export type ListForApi = (start: number, count: number, sort: string, callback: ListForApiCallback) => void
17
18 export type LoadByIdCallback = (err: Error, blacklistedVideoInstance: BlacklistedVideoInstance) => void
19 export type LoadById = (id: number, callback: LoadByIdCallback) => void
5 20
6 export type CountTotal = (callback) => void 21 export type LoadByVideoIdCallback = (err: Error, blacklistedVideoInstance: BlacklistedVideoInstance) => void
7 export type List = (callback) => void 22 export type LoadByVideoId = (id: string, callback: LoadByVideoIdCallback) => void
8 export type ListForApi = (start, count, sort, callback) => void
9 export type LoadById = (id, callback) => void
10 export type LoadByVideoId = (id, callback) => void
11} 23}
12 24
13export interface BlacklistedVideoClass { 25export interface BlacklistedVideoClass {
diff --git a/server/models/video-blacklist.ts b/server/models/video-blacklist.ts
index fe72d5d46..f36756085 100644
--- a/server/models/video-blacklist.ts
+++ b/server/models/video-blacklist.ts
@@ -66,15 +66,15 @@ function associate (models) {
66 }) 66 })
67} 67}
68 68
69countTotal = function (callback) { 69countTotal = function (callback: BlacklistedVideoMethods.CountTotalCallback) {
70 return BlacklistedVideo.count().asCallback(callback) 70 return BlacklistedVideo.count().asCallback(callback)
71} 71}
72 72
73list = function (callback) { 73list = function (callback: BlacklistedVideoMethods.ListCallback) {
74 return BlacklistedVideo.findAll().asCallback(callback) 74 return BlacklistedVideo.findAll().asCallback(callback)
75} 75}
76 76
77listForApi = function (start, count, sort, callback) { 77listForApi = function (start: number, count: number, sort: string, callback: BlacklistedVideoMethods.ListForApiCallback) {
78 const query = { 78 const query = {
79 offset: start, 79 offset: start,
80 limit: count, 80 limit: count,
@@ -88,11 +88,11 @@ listForApi = function (start, count, sort, callback) {
88 }) 88 })
89} 89}
90 90
91loadById = function (id, callback) { 91loadById = function (id: number, callback: BlacklistedVideoMethods.LoadByIdCallback) {
92 return BlacklistedVideo.findById(id).asCallback(callback) 92 return BlacklistedVideo.findById(id).asCallback(callback)
93} 93}
94 94
95loadByVideoId = function (id, callback) { 95loadByVideoId = function (id: string, callback: BlacklistedVideoMethods.LoadByIdCallback) {
96 const query = { 96 const query = {
97 where: { 97 where: {
98 videoId: id 98 videoId: id
diff --git a/server/models/video-interface.ts b/server/models/video-interface.ts
index b8dbeea35..7005f213c 100644
--- a/server/models/video-interface.ts
+++ b/server/models/video-interface.ts
@@ -1,28 +1,101 @@
1import * as Sequelize from 'sequelize' 1import * as Sequelize from 'sequelize'
2 2
3import { AuthorInstance } from './author-interface'
4import { VideoTagInstance } from './video-tag-interface'
5
6// Don't use barrel, import just what we need
7import { Video as FormatedVideo } from '../../shared/models/video.model'
8
9export type FormatedAddRemoteVideo = {
10 name: string
11 category: number
12 licence: number
13 language: number
14 nsfw: boolean
15 description: string
16 infoHash: string
17 remoteId: string
18 author: string
19 duration: number
20 thumbnailData: string
21 tags: string[]
22 createdAt: Date
23 updatedAt: Date
24 extname: string
25 views: number
26 likes: number
27 dislikes: number
28}
29
30export type FormatedUpdateRemoteVideo = {
31 name: string
32 category: number
33 licence: number
34 language: number
35 nsfw: boolean
36 description: string
37 infoHash: string
38 remoteId: string
39 author: string
40 duration: number
41 tags: string[]
42 createdAt: Date
43 updatedAt: Date
44 extname: string
45 views: number
46 likes: number
47 dislikes: number
48}
49
3export namespace VideoMethods { 50export namespace VideoMethods {
4 export type GenerateMagnetUri = () => void 51 export type GenerateMagnetUri = () => string
5 export type GetVideoFilename = () => void 52 export type GetVideoFilename = () => string
6 export type GetThumbnailName = () => void 53 export type GetThumbnailName = () => string
7 export type GetPreviewName = () => void 54 export type GetPreviewName = () => string
8 export type GetTorrentName = () => void 55 export type GetTorrentName = () => string
9 export type IsOwned = () => void 56 export type IsOwned = () => boolean
10 export type ToFormatedJSON = () => void 57 export type ToFormatedJSON = () => FormatedVideo
11 export type ToAddRemoteJSON = (callback) => void 58
12 export type ToUpdateRemoteJSON = (callback) => void 59 export type ToAddRemoteJSONCallback = (err: Error, videoFormated?: FormatedAddRemoteVideo) => void
13 export type TranscodeVideofile = (callback) => void 60 export type ToAddRemoteJSON = (callback: ToAddRemoteJSONCallback) => void
14 61
15 export type GenerateThumbnailFromData = (video, thumbnailData, callback) => void 62 export type ToUpdateRemoteJSON = () => FormatedUpdateRemoteVideo
63
64 export type TranscodeVideofileCallback = (err: Error) => void
65 export type TranscodeVideofile = (callback: TranscodeVideofileCallback) => void
66
67 export type GenerateThumbnailFromDataCallback = (err: Error, thumbnailName?: string) => void
68 export type GenerateThumbnailFromData = (video: VideoInstance, thumbnailData: string, callback: GenerateThumbnailFromDataCallback) => void
69
70 export type GetDurationFromFileCallback = (err: Error, duration?: number) => void
16 export type GetDurationFromFile = (videoPath, callback) => void 71 export type GetDurationFromFile = (videoPath, callback) => void
17 export type List = (callback) => void 72
18 export type ListForApi = (start, count, sort, callback) => void 73 export type ListCallback = () => void
19 export type LoadByHostAndRemoteId = (fromHost, remoteId, callback) => void 74 export type List = (callback: ListCallback) => void
20 export type ListOwnedAndPopulateAuthorAndTags = (callback) => void 75
21 export type ListOwnedByAuthor = (author, callback) => void 76 export type ListForApiCallback = (err: Error, videoInstances?: VideoInstance[], total?: number) => void
22 export type Load = (id, callback) => void 77 export type ListForApi = (start: number, count: number, sort: string, callback: ListForApiCallback) => void
23 export type LoadAndPopulateAuthor = (id, callback) => void 78
24 export type LoadAndPopulateAuthorAndPodAndTags = (id, callback) => void 79 export type LoadByHostAndRemoteIdCallback = (err: Error, videoInstance: VideoInstance) => void
25 export type SearchAndPopulateAuthorAndPodAndTags = (value, field, start, count, sort, callback) => void 80 export type LoadByHostAndRemoteId = (fromHost: string, remoteId: string, callback: LoadByHostAndRemoteIdCallback) => void
81
82 export type ListOwnedAndPopulateAuthorAndTagsCallback = (err: Error, videoInstances: VideoInstance[]) => void
83 export type ListOwnedAndPopulateAuthorAndTags = (callback: ListOwnedAndPopulateAuthorAndTagsCallback) => void
84
85 export type ListOwnedByAuthorCallback = (err: Error, videoInstances: VideoInstance[]) => void
86 export type ListOwnedByAuthor = (author: string, callback: ListOwnedByAuthorCallback) => void
87
88 export type LoadCallback = (err: Error, videoInstance: VideoInstance) => void
89 export type Load = (id: string, callback: LoadCallback) => void
90
91 export type LoadAndPopulateAuthorCallback = (err: Error, videoInstance: VideoInstance) => void
92 export type LoadAndPopulateAuthor = (id: string, callback: LoadAndPopulateAuthorCallback) => void
93
94 export type LoadAndPopulateAuthorAndPodAndTagsCallback = (err: Error, videoInstance: VideoInstance) => void
95 export type LoadAndPopulateAuthorAndPodAndTags = (id: string, callback: LoadAndPopulateAuthorAndPodAndTagsCallback) => void
96
97 export type SearchAndPopulateAuthorAndPodAndTagsCallback = (err: Error, videoInstances?: VideoInstance[], total?: number) => void
98 export type SearchAndPopulateAuthorAndPodAndTags = (value: string, field: string, start: number, count: number, sort: string, callback: SearchAndPopulateAuthorAndPodAndTagsCallback) => void
26} 99}
27 100
28export interface VideoClass { 101export interface VideoClass {
@@ -64,6 +137,9 @@ export interface VideoAttributes {
64 views?: number 137 views?: number
65 likes?: number 138 likes?: number
66 dislikes?: number 139 dislikes?: number
140
141 Author?: AuthorInstance
142 Tags?: VideoTagInstance[]
67} 143}
68 144
69export interface VideoInstance extends VideoClass, VideoAttributes, Sequelize.Instance<VideoAttributes> { 145export interface VideoInstance extends VideoClass, VideoAttributes, Sequelize.Instance<VideoAttributes> {
diff --git a/server/models/video-tag-interface.ts b/server/models/video-tag-interface.ts
index 468827b8c..f928cecff 100644
--- a/server/models/video-tag-interface.ts
+++ b/server/models/video-tag-interface.ts
@@ -9,7 +9,7 @@ export interface VideoTagClass {
9export interface VideoTagAttributes { 9export interface VideoTagAttributes {
10} 10}
11 11
12export interface VideoTagInstance extends Sequelize.Instance<VideoTagAttributes> { 12export interface VideoTagInstance extends VideoTagClass, VideoTagAttributes, Sequelize.Instance<VideoTagAttributes> {
13 id: number 13 id: number
14 createdAt: Date 14 createdAt: Date
15 updatedAt: Date 15 updatedAt: Date
diff --git a/server/models/video.ts b/server/models/video.ts
index 5558a7c3b..3f808b811 100644
--- a/server/models/video.ts
+++ b/server/models/video.ts
@@ -11,6 +11,7 @@ import { join } from 'path'
11import * as Sequelize from 'sequelize' 11import * as Sequelize from 'sequelize'
12 12
13import { database as db } from '../initializers/database' 13import { database as db } from '../initializers/database'
14import { VideoTagInstance } from './video-tag-interface'
14import { 15import {
15 logger, 16 logger,
16 isVideoNameValid, 17 isVideoNameValid,
@@ -266,7 +267,7 @@ export default function (sequelize, DataTypes) {
266 return Video 267 return Video
267} 268}
268 269
269function beforeValidate (video, options) { 270function beforeValidate (video: VideoInstance) {
270 // Put a fake infoHash if it does not exists yet 271 // Put a fake infoHash if it does not exists yet
271 if (video.isOwned() && !video.infoHash) { 272 if (video.isOwned() && !video.infoHash) {
272 // 40 hexa length 273 // 40 hexa length
@@ -274,7 +275,7 @@ function beforeValidate (video, options) {
274 } 275 }
275} 276}
276 277
277function beforeCreate (video, options) { 278function beforeCreate (video: VideoInstance, options: { transaction: Sequelize.Transaction }) {
278 return new Promise(function (resolve, reject) { 279 return new Promise(function (resolve, reject) {
279 const tasks = [] 280 const tasks = []
280 281
@@ -318,7 +319,7 @@ function beforeCreate (video, options) {
318 }) 319 })
319} 320}
320 321
321function afterDestroy (video, options) { 322function afterDestroy (video: VideoInstance) {
322 return new Promise(function (resolve, reject) { 323 return new Promise(function (resolve, reject) {
323 const tasks = [] 324 const tasks = []
324 325
@@ -401,7 +402,7 @@ generateMagnetUri = function () {
401 } 402 }
402 403
403 const xs = baseUrlHttp + STATIC_PATHS.TORRENTS + this.getTorrentName() 404 const xs = baseUrlHttp + STATIC_PATHS.TORRENTS + this.getTorrentName()
404 const announce = baseUrlWs + '/tracker/socket' 405 const announce = [ baseUrlWs + '/tracker/socket' ]
405 const urlList = [ baseUrlHttp + STATIC_PATHS.WEBSEED + this.getVideoFilename() ] 406 const urlList = [ baseUrlHttp + STATIC_PATHS.WEBSEED + this.getVideoFilename() ]
406 407
407 const magnetHash = { 408 const magnetHash = {
@@ -496,7 +497,7 @@ toFormatedJSON = function () {
496 return json 497 return json
497} 498}
498 499
499toAddRemoteJSON = function (callback) { 500toAddRemoteJSON = function (callback: VideoMethods.ToAddRemoteJSONCallback) {
500 // Get thumbnail data to send to the other pod 501 // Get thumbnail data to send to the other pod
501 const thumbnailPath = join(CONFIG.STORAGE.THUMBNAILS_DIR, this.getThumbnailName()) 502 const thumbnailPath = join(CONFIG.STORAGE.THUMBNAILS_DIR, this.getThumbnailName())
502 fs.readFile(thumbnailPath, (err, thumbnailData) => { 503 fs.readFile(thumbnailPath, (err, thumbnailData) => {
@@ -517,7 +518,7 @@ toAddRemoteJSON = function (callback) {
517 author: this.Author.name, 518 author: this.Author.name,
518 duration: this.duration, 519 duration: this.duration,
519 thumbnailData: thumbnailData.toString('binary'), 520 thumbnailData: thumbnailData.toString('binary'),
520 tags: map(this.Tags, 'name'), 521 tags: map<VideoTagInstance, string>(this.Tags, 'name'),
521 createdAt: this.createdAt, 522 createdAt: this.createdAt,
522 updatedAt: this.updatedAt, 523 updatedAt: this.updatedAt,
523 extname: this.extname, 524 extname: this.extname,
@@ -530,7 +531,7 @@ toAddRemoteJSON = function (callback) {
530 }) 531 })
531} 532}
532 533
533toUpdateRemoteJSON = function (callback) { 534toUpdateRemoteJSON = function () {
534 const json = { 535 const json = {
535 name: this.name, 536 name: this.name,
536 category: this.category, 537 category: this.category,
@@ -542,7 +543,7 @@ toUpdateRemoteJSON = function (callback) {
542 remoteId: this.id, 543 remoteId: this.id,
543 author: this.Author.name, 544 author: this.Author.name,
544 duration: this.duration, 545 duration: this.duration,
545 tags: map(this.Tags, 'name'), 546 tags: map<VideoTagInstance, string>(this.Tags, 'name'),
546 createdAt: this.createdAt, 547 createdAt: this.createdAt,
547 updatedAt: this.updatedAt, 548 updatedAt: this.updatedAt,
548 extname: this.extname, 549 extname: this.extname,
@@ -554,7 +555,7 @@ toUpdateRemoteJSON = function (callback) {
554 return json 555 return json
555} 556}
556 557
557transcodeVideofile = function (finalCallback) { 558transcodeVideofile = function (finalCallback: VideoMethods.TranscodeVideofileCallback) {
558 const video = this 559 const video = this
559 560
560 const videosDirectory = CONFIG.STORAGE.VIDEOS_DIR 561 const videosDirectory = CONFIG.STORAGE.VIDEOS_DIR
@@ -591,9 +592,9 @@ transcodeVideofile = function (finalCallback) {
591 video.save().asCallback(callback) 592 video.save().asCallback(callback)
592 } 593 }
593 594
594 ], function (err) { 595 ], function (err: Error) {
595 if (err) { 596 if (err) {
596 // Autodescruction... 597 // Autodesctruction...
597 video.destroy().asCallback(function (err) { 598 video.destroy().asCallback(function (err) {
598 if (err) logger.error('Cannot destruct video after transcoding failure.', { error: err }) 599 if (err) logger.error('Cannot destruct video after transcoding failure.', { error: err })
599 }) 600 })
@@ -609,7 +610,7 @@ transcodeVideofile = function (finalCallback) {
609 610
610// ------------------------------ STATICS ------------------------------ 611// ------------------------------ STATICS ------------------------------
611 612
612generateThumbnailFromData = function (video, thumbnailData, callback) { 613generateThumbnailFromData = function (video: VideoInstance, thumbnailData: string, callback: VideoMethods.GenerateThumbnailFromDataCallback) {
613 // Creating the thumbnail for a remote video 614 // Creating the thumbnail for a remote video
614 615
615 const thumbnailName = video.getThumbnailName() 616 const thumbnailName = video.getThumbnailName()
@@ -621,7 +622,7 @@ generateThumbnailFromData = function (video, thumbnailData, callback) {
621 }) 622 })
622} 623}
623 624
624getDurationFromFile = function (videoPath, callback) { 625getDurationFromFile = function (videoPath: string, callback: VideoMethods.GetDurationFromFileCallback) {
625 ffmpeg.ffprobe(videoPath, function (err, metadata) { 626 ffmpeg.ffprobe(videoPath, function (err, metadata) {
626 if (err) return callback(err) 627 if (err) return callback(err)
627 628
@@ -629,11 +630,11 @@ getDurationFromFile = function (videoPath, callback) {
629 }) 630 })
630} 631}
631 632
632list = function (callback) { 633list = function (callback: VideoMethods.ListCallback) {
633 return Video.findAll().asCallback(callback) 634 return Video.findAll().asCallback(callback)
634} 635}
635 636
636listForApi = function (start, count, sort, callback) { 637listForApi = function (start: number, count: number, sort: string, callback: VideoMethods.ListForApiCallback) {
637 // Exclude Blakclisted videos from the list 638 // Exclude Blakclisted videos from the list
638 const query = { 639 const query = {
639 distinct: true, 640 distinct: true,
@@ -658,7 +659,7 @@ listForApi = function (start, count, sort, callback) {
658 }) 659 })
659} 660}
660 661
661loadByHostAndRemoteId = function (fromHost, remoteId, callback) { 662loadByHostAndRemoteId = function (fromHost: string, remoteId: string, callback: VideoMethods.LoadByHostAndRemoteIdCallback) {
662 const query = { 663 const query = {
663 where: { 664 where: {
664 remoteId: remoteId 665 remoteId: remoteId
@@ -682,7 +683,7 @@ loadByHostAndRemoteId = function (fromHost, remoteId, callback) {
682 return Video.findOne(query).asCallback(callback) 683 return Video.findOne(query).asCallback(callback)
683} 684}
684 685
685listOwnedAndPopulateAuthorAndTags = function (callback) { 686listOwnedAndPopulateAuthorAndTags = function (callback: VideoMethods.ListOwnedAndPopulateAuthorAndTagsCallback) {
686 // If remoteId is null this is *our* video 687 // If remoteId is null this is *our* video
687 const query = { 688 const query = {
688 where: { 689 where: {
@@ -694,7 +695,7 @@ listOwnedAndPopulateAuthorAndTags = function (callback) {
694 return Video.findAll(query).asCallback(callback) 695 return Video.findAll(query).asCallback(callback)
695} 696}
696 697
697listOwnedByAuthor = function (author, callback) { 698listOwnedByAuthor = function (author: string, callback: VideoMethods.ListOwnedByAuthorCallback) {
698 const query = { 699 const query = {
699 where: { 700 where: {
700 remoteId: null 701 remoteId: null
@@ -712,11 +713,11 @@ listOwnedByAuthor = function (author, callback) {
712 return Video.findAll(query).asCallback(callback) 713 return Video.findAll(query).asCallback(callback)
713} 714}
714 715
715load = function (id, callback) { 716load = function (id: string, callback: VideoMethods.LoadCallback) {
716 return Video.findById(id).asCallback(callback) 717 return Video.findById(id).asCallback(callback)
717} 718}
718 719
719loadAndPopulateAuthor = function (id, callback) { 720loadAndPopulateAuthor = function (id: string, callback: VideoMethods.LoadAndPopulateAuthorCallback) {
720 const options = { 721 const options = {
721 include: [ Video['sequelize'].models.Author ] 722 include: [ Video['sequelize'].models.Author ]
722 } 723 }
@@ -724,7 +725,7 @@ loadAndPopulateAuthor = function (id, callback) {
724 return Video.findById(id, options).asCallback(callback) 725 return Video.findById(id, options).asCallback(callback)
725} 726}
726 727
727loadAndPopulateAuthorAndPodAndTags = function (id, callback) { 728loadAndPopulateAuthorAndPodAndTags = function (id: string, callback: VideoMethods.LoadAndPopulateAuthorAndPodAndTagsCallback) {
728 const options = { 729 const options = {
729 include: [ 730 include: [
730 { 731 {
@@ -738,7 +739,14 @@ loadAndPopulateAuthorAndPodAndTags = function (id, callback) {
738 return Video.findById(id, options).asCallback(callback) 739 return Video.findById(id, options).asCallback(callback)
739} 740}
740 741
741searchAndPopulateAuthorAndPodAndTags = function (value, field, start, count, sort, callback) { 742searchAndPopulateAuthorAndPodAndTags = function (
743 value: string,
744 field: string,
745 start: number,
746 count: number,
747 sort: string,
748 callback: VideoMethods.SearchAndPopulateAuthorAndPodAndTagsCallback
749) {
742 const podInclude: any = { 750 const podInclude: any = {
743 model: Video['sequelize'].models.Pod, 751 model: Video['sequelize'].models.Pod,
744 required: false 752 required: false
@@ -821,27 +829,27 @@ function createBaseVideosWhere () {
821 } 829 }
822} 830}
823 831
824function removeThumbnail (video, callback) { 832function removeThumbnail (video: VideoInstance, callback: (err: Error) => void) {
825 const thumbnailPath = join(CONFIG.STORAGE.THUMBNAILS_DIR, video.getThumbnailName()) 833 const thumbnailPath = join(CONFIG.STORAGE.THUMBNAILS_DIR, video.getThumbnailName())
826 fs.unlink(thumbnailPath, callback) 834 fs.unlink(thumbnailPath, callback)
827} 835}
828 836
829function removeFile (video, callback) { 837function removeFile (video: VideoInstance, callback: (err: Error) => void) {
830 const filePath = join(CONFIG.STORAGE.VIDEOS_DIR, video.getVideoFilename()) 838 const filePath = join(CONFIG.STORAGE.VIDEOS_DIR, video.getVideoFilename())
831 fs.unlink(filePath, callback) 839 fs.unlink(filePath, callback)
832} 840}
833 841
834function removeTorrent (video, callback) { 842function removeTorrent (video: VideoInstance, callback: (err: Error) => void) {
835 const torrenPath = join(CONFIG.STORAGE.TORRENTS_DIR, video.getTorrentName()) 843 const torrenPath = join(CONFIG.STORAGE.TORRENTS_DIR, video.getTorrentName())
836 fs.unlink(torrenPath, callback) 844 fs.unlink(torrenPath, callback)
837} 845}
838 846
839function removePreview (video, callback) { 847function removePreview (video: VideoInstance, callback: (err: Error) => void) {
840 // Same name than video thumnail 848 // Same name than video thumnail
841 fs.unlink(CONFIG.STORAGE.PREVIEWS_DIR + video.getPreviewName(), callback) 849 fs.unlink(CONFIG.STORAGE.PREVIEWS_DIR + video.getPreviewName(), callback)
842} 850}
843 851
844function createTorrentFromVideo (video, videoPath, callback) { 852function createTorrentFromVideo (video: VideoInstance, videoPath: string, callback: (err: Error) => void) {
845 const options = { 853 const options = {
846 announceList: [ 854 announceList: [
847 [ CONFIG.WEBSERVER.WS + '://' + CONFIG.WEBSERVER.HOSTNAME + ':' + CONFIG.WEBSERVER.PORT + '/tracker/socket' ] 855 [ CONFIG.WEBSERVER.WS + '://' + CONFIG.WEBSERVER.HOSTNAME + ':' + CONFIG.WEBSERVER.PORT + '/tracker/socket' ]
@@ -865,24 +873,23 @@ function createTorrentFromVideo (video, videoPath, callback) {
865 }) 873 })
866} 874}
867 875
868function createPreview (video, videoPath, callback) { 876function createPreview (video: VideoInstance, videoPath: string, callback: (err: Error) => void) {
869 generateImage(video, videoPath, CONFIG.STORAGE.PREVIEWS_DIR, video.getPreviewName(), callback) 877 generateImage(video, videoPath, CONFIG.STORAGE.PREVIEWS_DIR, video.getPreviewName(), null, callback)
870} 878}
871 879
872function createThumbnail (video, videoPath, callback) { 880function createThumbnail (video: VideoInstance, videoPath: string, callback: (err: Error) => void) {
873 generateImage(video, videoPath, CONFIG.STORAGE.THUMBNAILS_DIR, video.getThumbnailName(), THUMBNAILS_SIZE, callback) 881 generateImage(video, videoPath, CONFIG.STORAGE.THUMBNAILS_DIR, video.getThumbnailName(), THUMBNAILS_SIZE, callback)
874} 882}
875 883
876function generateImage (video, videoPath, folder, imageName, size, callback?) { 884type GenerateImageCallback = (err: Error, imageName: string) => void
885function generateImage (video: VideoInstance, videoPath: string, folder: string, imageName: string, size: string, callback?: GenerateImageCallback) {
877 const options: any = { 886 const options: any = {
878 filename: imageName, 887 filename: imageName,
879 count: 1, 888 count: 1,
880 folder 889 folder
881 } 890 }
882 891
883 if (!callback) { 892 if (size) {
884 callback = size
885 } else {
886 options.size = size 893 options.size = size
887 } 894 }
888 895
@@ -894,7 +901,7 @@ function generateImage (video, videoPath, folder, imageName, size, callback?) {
894 .thumbnail(options) 901 .thumbnail(options)
895} 902}
896 903
897function removeFromBlacklist (video, callback) { 904function removeFromBlacklist (video: VideoInstance, callback: (err: Error) => void) {
898 // Find the blacklisted video 905 // Find the blacklisted video
899 db.BlacklistedVideo.loadByVideoId(video.id, function (err, video) { 906 db.BlacklistedVideo.loadByVideoId(video.id, function (err, video) {
900 // If an error occured, stop here 907 // If an error occured, stop here
@@ -908,7 +915,7 @@ function removeFromBlacklist (video, callback) {
908 video.destroy().asCallback(callback) 915 video.destroy().asCallback(callback)
909 } else { 916 } else {
910 // If haven't found it, simply ignore it and do nothing 917 // If haven't found it, simply ignore it and do nothing
911 return callback() 918 return callback(null)
912 } 919 }
913 }) 920 })
914} 921}
diff --git a/shared/index.ts b/shared/index.ts
new file mode 100644
index 000000000..ad200c539
--- /dev/null
+++ b/shared/index.ts
@@ -0,0 +1 @@
export * from './models'
diff --git a/shared/models/index.ts b/shared/models/index.ts
new file mode 100644
index 000000000..b498d620a
--- /dev/null
+++ b/shared/models/index.ts
@@ -0,0 +1,5 @@
1export * from './pod.model'
2export * from './user.model'
3export * from './video-abuse.model'
4export * from './video-blacklist.model'
5export * from './video.model'
diff --git a/shared/models/pod.model.ts b/shared/models/pod.model.ts
new file mode 100644
index 000000000..d25421936
--- /dev/null
+++ b/shared/models/pod.model.ts
@@ -0,0 +1,7 @@
1export interface Pod {
2 id: number,
3 host: string,
4 email: string,
5 score: number,
6 createdAt: Date
7}
diff --git a/shared/models/user.model.ts b/shared/models/user.model.ts
new file mode 100644
index 000000000..01cc380d3
--- /dev/null
+++ b/shared/models/user.model.ts
@@ -0,0 +1,8 @@
1export interface User {
2 id: number
3 username: string
4 email: string
5 displayNSFW: boolean
6 role: string[]
7 createdAt: Date
8}
diff --git a/shared/models/video-abuse.model.ts b/shared/models/video-abuse.model.ts
new file mode 100644
index 000000000..e005a1fd5
--- /dev/null
+++ b/shared/models/video-abuse.model.ts
@@ -0,0 +1,8 @@
1export interface VideoAbuse {
2 id: number
3 reporterPodHost: string
4 reason: string
5 reporterUsername: string
6 videoId: number
7 createdAt: Date
8}
diff --git a/shared/models/video-blacklist.model.ts b/shared/models/video-blacklist.model.ts
new file mode 100644
index 000000000..6086250ac
--- /dev/null
+++ b/shared/models/video-blacklist.model.ts
@@ -0,0 +1,5 @@
1export interface BlacklistedVideo {
2 id: number
3 videoId: number
4 createdAt: Date
5}
diff --git a/shared/models/video.model.ts b/shared/models/video.model.ts
new file mode 100644
index 000000000..355e912d2
--- /dev/null
+++ b/shared/models/video.model.ts
@@ -0,0 +1,3 @@
1export interface Video {
2
3}
diff --git a/yarn.lock b/yarn.lock
index 28d33fa97..c219dcea3 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -52,6 +52,12 @@
52 version "4.14.64" 52 version "4.14.64"
53 resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.64.tgz#979cf3a3d4a368670840bf9b3e448dc33ffe84ee" 53 resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.64.tgz#979cf3a3d4a368670840bf9b3e448dc33ffe84ee"
54 54
55"@types/magnet-uri@^5.1.1":
56 version "5.1.1"
57 resolved "https://registry.yarnpkg.com/@types/magnet-uri/-/magnet-uri-5.1.1.tgz#861aaf64c92a3137dd848fefc55cd352a8ea851a"
58 dependencies:
59 "@types/node" "*"
60
55"@types/mime@*": 61"@types/mime@*":
56 version "0.0.29" 62 version "0.0.29"
57 resolved "https://registry.yarnpkg.com/@types/mime/-/mime-0.0.29.tgz#fbcfd330573b912ef59eeee14602bface630754b" 63 resolved "https://registry.yarnpkg.com/@types/mime/-/mime-0.0.29.tgz#fbcfd330573b912ef59eeee14602bface630754b"
@@ -66,6 +72,12 @@
66 dependencies: 72 dependencies:
67 "@types/express" "*" 73 "@types/express" "*"
68 74
75"@types/multer@^0.0.34":
76 version "0.0.34"
77 resolved "https://registry.yarnpkg.com/@types/multer/-/multer-0.0.34.tgz#4b542b380dcf59bced8b66294654dc67a7fab383"
78 dependencies:
79 "@types/express" "*"
80
69"@types/node@*", "@types/node@^7.0.18": 81"@types/node@*", "@types/node@^7.0.18":
70 version "7.0.22" 82 version "7.0.22"
71 resolved "https://registry.yarnpkg.com/@types/node/-/node-7.0.22.tgz#4593f4d828bdd612929478ea40c67b4f403ca255" 83 resolved "https://registry.yarnpkg.com/@types/node/-/node-7.0.22.tgz#4593f4d828bdd612929478ea40c67b4f403ca255"