First typescript iteration

pull/71/head
Chocobozzz 2017-05-15 22:22:03 +02:00
parent d5f345ed4c
commit 65fcc3119c
113 changed files with 1961 additions and 1784 deletions

1
.gitignore vendored
View File

@ -16,3 +16,4 @@
/ffmpeg/
/*.sublime-project
/*.sublime-workspace
/dist

View File

@ -70,15 +70,31 @@
"safe-buffer": "^5.0.1",
"scripty": "^1.5.0",
"sequelize": "^3.27.0",
"typescript": "~2.2.0",
"winston": "^2.1.1",
"ws": "^2.0.0"
},
"devDependencies": {
"@types/async": "^2.0.40",
"@types/bcrypt": "^1.0.0",
"@types/body-parser": "^1.16.3",
"@types/config": "^0.0.32",
"@types/express": "^4.0.35",
"@types/lodash": "^4.14.64",
"@types/mkdirp": "^0.3.29",
"@types/morgan": "^1.7.32",
"@types/node": "^7.0.18",
"@types/request": "^0.0.43",
"@types/sequelize": "3",
"@types/winston": "^2.3.2",
"@types/ws": "^0.0.41",
"chai": "^3.3.0",
"commander": "^2.9.0",
"mocha": "^3.0.1",
"standard": "^10.0.0",
"supertest": "^3.0.0",
"tslint": "^5.2.0",
"tslint-config-standard": "^5.0.2",
"webtorrent": "^0.98.0"
},
"standard": {

View File

@ -1,14 +1,14 @@
'use strict'
// ----------- Node modules -----------
const bodyParser = require('body-parser')
const express = require('express')
import bodyParser = require('body-parser')
import express = require('express')
const expressValidator = require('express-validator')
const http = require('http')
const morgan = require('morgan')
const path = require('path')
const TrackerServer = require('bittorrent-tracker').Server
const WebSocketServer = require('ws').Server
import http = require('http')
import morgan = require('morgan')
import path = require('path')
import bittorrentTracker = require('bittorrent-tracker')
import { Server as WebSocketServer } from 'ws'
const TrackerServer = bittorrentTracker.Server
process.title = 'peertube'
@ -16,70 +16,62 @@ process.title = 'peertube'
const app = express()
// ----------- Database -----------
const constants = require('./server/initializers/constants')
const logger = require('./server/helpers/logger')
// Do not use barels because we don't want to load all modules here (we need to initialize database first)
import { logger } from './server/helpers/logger'
import { API_VERSION, CONFIG } from './server/initializers/constants'
// Initialize database and models
const db = require('./server/initializers/database')
db.init(onDatabaseInitDone)
// ----------- Checker -----------
const checker = require('./server/initializers/checker')
import { checkMissedConfig, checkFFmpeg, checkConfig } from './server/initializers/checker'
const missed = checker.checkMissedConfig()
const missed = checkMissedConfig()
if (missed.length !== 0) {
throw new Error('Miss some configurations keys : ' + missed)
}
checker.checkFFmpeg(function (err) {
checkFFmpeg(function (err) {
if (err) {
throw err
}
})
const errorMessage = checker.checkConfig()
const errorMessage = checkConfig()
if (errorMessage !== null) {
throw new Error(errorMessage)
}
// ----------- PeerTube modules -----------
const customValidators = require('./server/helpers/custom-validators')
const friends = require('./server/lib/friends')
const installer = require('./server/initializers/installer')
const migrator = require('./server/initializers/migrator')
const jobScheduler = require('./server/lib/jobs/job-scheduler')
const routes = require('./server/controllers')
import { migrate, installApplication } from './server/initializers'
import { JobScheduler, activateSchedulers } from './server/lib'
import * as customValidators from './server/helpers/custom-validators'
import { apiRouter, clientsRouter, staticRouter } from './server/controllers'
// ----------- Command line -----------
// ----------- App -----------
// For the logger
app.use(morgan('combined', { stream: logger.stream }))
// app.use(morgan('combined', { stream: logger.stream }))
// For body requests
app.use(bodyParser.json({ limit: '500kb' }))
app.use(bodyParser.urlencoded({ extended: false }))
// Validate some params for the API
app.use(expressValidator({
customValidators: Object.assign(
{},
customValidators.misc,
customValidators.pods,
customValidators.users,
customValidators.videos,
customValidators.remote.videos
)
customValidators: customValidators
}))
// ----------- Views, routes and static files -----------
// API
const apiRoute = '/api/' + constants.API_VERSION
app.use(apiRoute, routes.api)
const apiRoute = '/api/' + API_VERSION
app.use(apiRoute, apiRouter)
// Client files
app.use('/', routes.client)
app.use('/', clientsRouter)
// Static files
app.use('/', routes.static)
app.use('/', staticRouter)
// Always serve index client page (the client is a single page application, let it handle routing)
app.use('/*', function (req, res, next) {
@ -104,7 +96,7 @@ trackerServer.on('warning', function (err) {
})
const server = http.createServer(app)
const wss = new WebSocketServer({server: server, path: '/tracker/socket'})
const wss = new WebSocketServer({ server: server, path: '/tracker/socket' })
wss.on('connection', function (ws) {
trackerServer.onWebSocketConnection(ws)
})
@ -114,7 +106,7 @@ wss.on('connection', function (ws) {
// Catch 404 and forward to error handler
app.use(function (req, res, next) {
const err = new Error('Not Found')
err.status = 404
err['status'] = 404
next(err)
})
@ -126,29 +118,25 @@ app.use(function (err, req, res, next) {
// ----------- Run -----------
function onDatabaseInitDone () {
const port = constants.CONFIG.LISTEN.PORT
const port = CONFIG.LISTEN.PORT
// Run the migration scripts if needed
migrator.migrate(function (err) {
migrate(function (err) {
if (err) throw err
installer.installApplication(function (err) {
installApplication(function (err) {
if (err) throw err
// ----------- Make the server listening -----------
server.listen(port, function () {
// Activate the communication with friends
friends.activate()
activateSchedulers()
// Activate job scheduler
jobScheduler.activate()
JobScheduler.Instance.activate()
logger.info('Server listening on port %d', port)
logger.info('Webserver: %s', constants.CONFIG.WEBSERVER.URL)
app.emit('ready')
logger.info('Webserver: %s', CONFIG.WEBSERVER.URL)
})
})
})
}
module.exports = app

View File

@ -1,19 +1,17 @@
'use strict'
import express = require('express')
const express = require('express')
const constants = require('../../initializers/constants')
import { CONFIG } from '../../initializers';
import { logger } from '../../helpers'
const db = require('../../initializers/database')
const logger = require('../../helpers/logger')
const router = express.Router()
const clientsRouter = express.Router()
router.get('/local', getLocalClient)
clientsRouter.get('/local', getLocalClient)
// Get the client credentials for the PeerTube front end
function getLocalClient (req, res, next) {
const serverHostname = constants.CONFIG.WEBSERVER.HOSTNAME
const serverPort = constants.CONFIG.WEBSERVER.PORT
const serverHostname = CONFIG.WEBSERVER.HOSTNAME
const serverPort = CONFIG.WEBSERVER.PORT
let headerHostShouldBe = serverHostname
if (serverPort !== 80 && serverPort !== 443) {
headerHostShouldBe += ':' + serverPort
@ -38,4 +36,6 @@ function getLocalClient (req, res, next) {
// ---------------------------------------------------------------------------
module.exports = router
export {
clientsRouter
}

View File

@ -1,22 +0,0 @@
'use strict'
const express = require('express')
const constants = require('../../initializers/constants')
const router = express.Router()
router.get('/', getConfig)
// Get the client credentials for the PeerTube front end
function getConfig (req, res, next) {
res.json({
signup: {
enabled: constants.CONFIG.SIGNUP.ENABLED
}
})
}
// ---------------------------------------------------------------------------
module.exports = router

View File

@ -0,0 +1,22 @@
import express = require('express')
import { CONFIG } from '../../initializers';
const configRouter = express.Router()
configRouter.get('/', getConfig)
// Get the client credentials for the PeerTube front end
function getConfig (req, res, next) {
res.json({
signup: {
enabled: CONFIG.SIGNUP.ENABLED
}
})
}
// ---------------------------------------------------------------------------
export {
configRouter
}

View File

@ -1,35 +0,0 @@
'use strict'
const express = require('express')
const utils = require('../../helpers/utils')
const router = express.Router()
const clientsController = require('./clients')
const configController = require('./config')
const podsController = require('./pods')
const remoteController = require('./remote')
const requestsController = require('./requests')
const usersController = require('./users')
const videosController = require('./videos')
router.use('/clients', clientsController)
router.use('/config', configController)
router.use('/pods', podsController)
router.use('/remote', remoteController)
router.use('/requests', requestsController)
router.use('/users', usersController)
router.use('/videos', videosController)
router.use('/ping', pong)
router.use('/*', utils.badRequest)
// ---------------------------------------------------------------------------
module.exports = router
// ---------------------------------------------------------------------------
function pong (req, res, next) {
return res.send('pong').status(200).end()
}

View File

@ -0,0 +1,33 @@
import express = require('express')
import { badRequest } from '../../helpers'
import { clientsRouter } from './clients'
import { configRouter } from './config'
import { podsRouter } from './pods'
import { remoteRouter } from './remote'
import { requestsRouter } from './requests'
import { usersRouter } from './users'
import { videosRouter } from './videos'
const apiRouter = express.Router()
apiRouter.use('/clients', clientsRouter)
apiRouter.use('/config', configRouter)
apiRouter.use('/pods', podsRouter)
apiRouter.use('/remote', remoteRouter)
apiRouter.use('/requests', requestsRouter)
apiRouter.use('/users', usersRouter)
apiRouter.use('/videos', videosRouter)
apiRouter.use('/ping', pong)
apiRouter.use('/*', badRequest)
// ---------------------------------------------------------------------------
export { apiRouter }
// ---------------------------------------------------------------------------
function pong (req, res, next) {
return res.send('pong').status(200).end()
}

View File

@ -1,109 +0,0 @@
'use strict'
const express = require('express')
const waterfall = require('async/waterfall')
const db = require('../../initializers/database')
const constants = require('../../initializers/constants')
const logger = require('../../helpers/logger')
const peertubeCrypto = require('../../helpers/peertube-crypto')
const utils = require('../../helpers/utils')
const friends = require('../../lib/friends')
const middlewares = require('../../middlewares')
const admin = middlewares.admin
const oAuth = middlewares.oauth
const podsMiddleware = middlewares.pods
const validators = middlewares.validators.pods
const router = express.Router()
router.get('/', listPods)
router.post('/',
podsMiddleware.setBodyHostPort, // We need to modify the host before running the validator!
validators.podsAdd,
addPods
)
router.post('/makefriends',
oAuth.authenticate,
admin.ensureIsAdmin,
validators.makeFriends,
podsMiddleware.setBodyHostsPort,
makeFriends
)
router.get('/quitfriends',
oAuth.authenticate,
admin.ensureIsAdmin,
quitFriends
)
// ---------------------------------------------------------------------------
module.exports = router
// ---------------------------------------------------------------------------
function addPods (req, res, next) {
const informations = req.body
waterfall([
function addPod (callback) {
const pod = db.Pod.build(informations)
pod.save().asCallback(function (err, podCreated) {
// Be sure about the number of parameters for the callback
return callback(err, podCreated)
})
},
function sendMyVideos (podCreated, callback) {
friends.sendOwnedVideosToPod(podCreated.id)
callback(null)
},
function fetchMyCertificate (callback) {
peertubeCrypto.getMyPublicCert(function (err, cert) {
if (err) {
logger.error('Cannot read cert file.')
return callback(err)
}
return callback(null, cert)
})
}
], function (err, cert) {
if (err) return next(err)
return res.json({ cert: cert, email: constants.CONFIG.ADMIN.EMAIL })
})
}
function listPods (req, res, next) {
db.Pod.list(function (err, podsList) {
if (err) return next(err)
res.json(utils.getFormatedObjects(podsList, podsList.length))
})
}
function makeFriends (req, res, next) {
const hosts = req.body.hosts
friends.makeFriends(hosts, function (err) {
if (err) {
logger.error('Could not make friends.', { error: err })
return
}
logger.info('Made friends!')
})
res.type('json').status(204).end()
}
function quitFriends (req, res, next) {
friends.quitFriends(function (err) {
if (err) return next(err)
res.type('json').status(204).end()
})
}

View File

@ -0,0 +1,118 @@
import express = require('express')
import { waterfall } from 'async'
const db = require('../../initializers/database')
import { CONFIG } from '../../initializers'
import {
logger,
getMyPublicCert,
getFormatedObjects
} from '../../helpers'
import {
sendOwnedVideosToPod,
makeFriends,
quitFriends
} from '../../lib'
import {
podsAddValidator,
authenticate,
ensureIsAdmin,
makeFriendsValidator,
setBodyHostPort,
setBodyHostsPort
} from '../../middlewares'
const podsRouter = express.Router()
podsRouter.get('/', listPods)
podsRouter.post('/',
setBodyHostPort, // We need to modify the host before running the validator!
podsAddValidator,
addPods
)
podsRouter.post('/makefriends',
authenticate,
ensureIsAdmin,
makeFriendsValidator,
setBodyHostsPort,
makeFriends
)
podsRouter.get('/quitfriends',
authenticate,
ensureIsAdmin,
quitFriends
)
// ---------------------------------------------------------------------------
export {
podsRouter
}
// ---------------------------------------------------------------------------
function addPods (req, res, next) {
const informations = req.body
waterfall([
function addPod (callback) {
const pod = db.Pod.build(informations)
pod.save().asCallback(function (err, podCreated) {
// Be sure about the number of parameters for the callback
return callback(err, podCreated)
})
},
function sendMyVideos (podCreated, callback) {
sendOwnedVideosToPod(podCreated.id)
callback(null)
},
function fetchMyCertificate (callback) {
getMyPublicCert(function (err, cert) {
if (err) {
logger.error('Cannot read cert file.')
return callback(err)
}
return callback(null, cert)
})
}
], function (err, cert) {
if (err) return next(err)
return res.json({ cert: cert, email: CONFIG.ADMIN.EMAIL })
})
}
function listPods (req, res, next) {
db.Pod.list(function (err, podsList) {
if (err) return next(err)
res.json(getFormatedObjects(podsList, podsList.length))
})
}
function makeFriendsController (req, res, next) {
const hosts = req.body.hosts
makeFriends(hosts, function (err) {
if (err) {
logger.error('Could not make friends.', { error: err })
return
}
logger.info('Made friends!')
})
res.type('json').status(204).end()
}
function quitFriendsController (req, res, next) {
quitFriends(function (err) {
if (err) return next(err)
res.type('json').status(204).end()
})
}

View File

@ -1,18 +0,0 @@
'use strict'
const express = require('express')
const utils = require('../../../helpers/utils')
const router = express.Router()
const podsRemoteController = require('./pods')
const videosRemoteController = require('./videos')
router.use('/pods', podsRemoteController)
router.use('/videos', videosRemoteController)
router.use('/*', utils.badRequest)
// ---------------------------------------------------------------------------
module.exports = router

View File

@ -0,0 +1,18 @@
import express = require('express')
import { badRequest } from '../../../helpers'
import { remotePodsRouter } from './pods'
import { remoteVideosRouter } from './videos'
const remoteRouter = express.Router()
remoteRouter.use('/pods', remotePodsRouter)
remoteRouter.use('/videos', remoteVideosRouter)
remoteRouter.use('/*', badRequest)
// ---------------------------------------------------------------------------
export {
remoteRouter
}

View File

@ -1,25 +1,23 @@
'use strict'
const express = require('express')
const waterfall = require('async/waterfall')
import express = require('express')
import { waterfall } from 'async/waterfall'
const db = require('../../../initializers/database')
const middlewares = require('../../../middlewares')
const checkSignature = middlewares.secure.checkSignature
const signatureValidator = middlewares.validators.remote.signature
import { checkSignature, signatureValidator } from '../../../middlewares'
const router = express.Router()
const remotePodsRouter = express.Router()
// Post because this is a secured request
router.post('/remove',
signatureValidator.signature,
remotePodsRouter.post('/remove',
signatureValidator,
checkSignature,
removePods
)
// ---------------------------------------------------------------------------
module.exports = router
export {
remotePodsRouter
}
// ---------------------------------------------------------------------------

View File

@ -1,20 +1,30 @@
'use strict'
const eachSeries = require('async/eachSeries')
const express = require('express')
const waterfall = require('async/waterfall')
import express = require('express')
import { eachSeries, waterfall } from 'async'
const db = require('../../../initializers/database')
const constants = require('../../../initializers/constants')
const middlewares = require('../../../middlewares')
const secureMiddleware = middlewares.secure
const videosValidators = middlewares.validators.remote.videos
const signatureValidators = middlewares.validators.remote.signature
const logger = require('../../../helpers/logger')
const friends = require('../../../lib/friends')
const databaseUtils = require('../../../helpers/database-utils')
import {
REQUEST_ENDPOINT_ACTIONS,
REQUEST_ENDPOINTS,
REQUEST_VIDEO_EVENT_TYPES,
REQUEST_VIDEO_QADU_TYPES
} from '../../../initializers'
import {
checkSignature,
signatureValidator,
remoteVideosValidator,
remoteQaduVideosValidator,
remoteEventsVideosValidator
} from '../../../middlewares'
import {
logger,
commitTransaction,
retryTransactionWrapper,
rollbackTransaction,
startSerializableTransaction
} from '../../../helpers'
import { quickAndDirtyUpdatesVideoToFriends } from '../../../lib'
const ENDPOINT_ACTIONS = constants.REQUEST_ENDPOINT_ACTIONS[constants.REQUEST_ENDPOINTS.VIDEOS]
const ENDPOINT_ACTIONS = REQUEST_ENDPOINT_ACTIONS[REQUEST_ENDPOINTS.VIDEOS]
// Functions to call when processing a remote request
const functionsHash = {}
@ -23,32 +33,34 @@ functionsHash[ENDPOINT_ACTIONS.UPDATE] = updateRemoteVideoRetryWrapper
functionsHash[ENDPOINT_ACTIONS.REMOVE] = removeRemoteVideo
functionsHash[ENDPOINT_ACTIONS.REPORT_ABUSE] = reportAbuseRemoteVideo
const router = express.Router()
const remoteVideosRouter = express.Router()
router.post('/',
signatureValidators.signature,
secureMiddleware.checkSignature,
videosValidators.remoteVideos,
remoteVideosRouter.post('/',
signatureValidator,
checkSignature,
remoteVideosValidator,
remoteVideos
)
router.post('/qadu',
signatureValidators.signature,
secureMiddleware.checkSignature,
videosValidators.remoteQaduVideos,
remoteVideosRouter.post('/qadu',
signatureValidator,
checkSignature,
remoteQaduVideosValidator,
remoteVideosQadu
)
router.post('/events',
signatureValidators.signature,
secureMiddleware.checkSignature,
videosValidators.remoteEventsVideos,
remoteVideosRouter.post('/events',
signatureValidator,
checkSignature,
remoteEventsVideosValidator,
remoteVideosEvents
)
// ---------------------------------------------------------------------------
module.exports = router
export {
remoteVideosRouter
}
// ---------------------------------------------------------------------------
@ -58,7 +70,7 @@ function remoteVideos (req, res, next) {
// We need to process in the same order to keep consistency
// TODO: optimization
eachSeries(requests, function (request, callbackEach) {
eachSeries(requests, function (request: any, callbackEach) {
const data = request.data
// Get the function we need to call in order to process the request
@ -81,7 +93,7 @@ function remoteVideosQadu (req, res, next) {
const requests = req.body.data
const fromPod = res.locals.secure.pod
eachSeries(requests, function (request, callbackEach) {
eachSeries(requests, function (request: any, callbackEach) {
const videoData = request.data
quickAndDirtyUpdateVideoRetryWrapper(videoData, fromPod, callbackEach)
@ -96,7 +108,7 @@ function remoteVideosEvents (req, res, next) {
const requests = req.body.data
const fromPod = res.locals.secure.pod
eachSeries(requests, function (request, callbackEach) {
eachSeries(requests, function (request: any, callbackEach) {
const eventData = request.data
processVideosEventsRetryWrapper(eventData, fromPod, callbackEach)
@ -113,12 +125,12 @@ function processVideosEventsRetryWrapper (eventData, fromPod, finalCallback) {
errorMessage: 'Cannot process videos events with many retries.'
}
databaseUtils.retryTransactionWrapper(processVideosEvents, options, finalCallback)
retryTransactionWrapper(processVideosEvents, options, finalCallback)
}
function processVideosEvents (eventData, fromPod, finalCallback) {
waterfall([
databaseUtils.startSerializableTransaction,
startSerializableTransaction,
function findVideo (t, callback) {
fetchOwnedVideo(eventData.remoteId, function (err, videoInstance) {
@ -133,19 +145,19 @@ function processVideosEvents (eventData, fromPod, finalCallback) {
let qaduType
switch (eventData.eventType) {
case constants.REQUEST_VIDEO_EVENT_TYPES.VIEWS:
case REQUEST_VIDEO_EVENT_TYPES.VIEWS:
columnToUpdate = 'views'
qaduType = constants.REQUEST_VIDEO_QADU_TYPES.VIEWS
qaduType = REQUEST_VIDEO_QADU_TYPES.VIEWS
break
case constants.REQUEST_VIDEO_EVENT_TYPES.LIKES:
case REQUEST_VIDEO_EVENT_TYPES.LIKES:
columnToUpdate = 'likes'
qaduType = constants.REQUEST_VIDEO_QADU_TYPES.LIKES
qaduType = REQUEST_VIDEO_QADU_TYPES.LIKES
break
case constants.REQUEST_VIDEO_EVENT_TYPES.DISLIKES:
case REQUEST_VIDEO_EVENT_TYPES.DISLIKES:
columnToUpdate = 'dislikes'
qaduType = constants.REQUEST_VIDEO_QADU_TYPES.DISLIKES
qaduType = REQUEST_VIDEO_QADU_TYPES.DISLIKES
break
default:
@ -168,17 +180,17 @@ function processVideosEvents (eventData, fromPod, finalCallback) {
}
]
friends.quickAndDirtyUpdatesVideoToFriends(qadusParams, t, function (err) {
quickAndDirtyUpdatesVideoToFriends(qadusParams, t, function (err) {
return callback(err, t)
})
},
databaseUtils.commitTransaction
commitTransaction
], function (err, t) {
if (err) {
logger.debug('Cannot process a video event.', { error: err })
return databaseUtils.rollbackTransaction(err, t, finalCallback)
return rollbackTransaction(err, t, finalCallback)
}
logger.info('Remote video event processed for video %s.', eventData.remoteId)
@ -192,14 +204,14 @@ function quickAndDirtyUpdateVideoRetryWrapper (videoData, fromPod, finalCallback
errorMessage: 'Cannot update quick and dirty the remote video with many retries.'
}
databaseUtils.retryTransactionWrapper(quickAndDirtyUpdateVideo, options, finalCallback)
retryTransactionWrapper(quickAndDirtyUpdateVideo, options, finalCallback)
}
function quickAndDirtyUpdateVideo (videoData, fromPod, finalCallback) {
let videoName
waterfall([
databaseUtils.startSerializableTransaction,
startSerializableTransaction,
function findVideo (t, callback) {
fetchRemoteVideo(fromPod.host, videoData.remoteId, function (err, videoInstance) {
@ -229,12 +241,12 @@ function quickAndDirtyUpdateVideo (videoData, fromPod, finalCallback) {
})
},
databaseUtils.commitTransaction
commitTransaction
], function (err, t) {
if (err) {
logger.debug('Cannot quick and dirty update the remote video.', { error: err })
return databaseUtils.rollbackTransaction(err, t, finalCallback)
return rollbackTransaction(err, t, finalCallback)
}
logger.info('Remote video %s quick and dirty updated', videoName)
@ -249,7 +261,7 @@ function addRemoteVideoRetryWrapper (videoToCreateData, fromPod, finalCallback)
errorMessage: 'Cannot insert the remote video with many retries.'
}
databaseUtils.retryTransactionWrapper(addRemoteVideo, options, finalCallback)
retryTransactionWrapper(addRemoteVideo, options, finalCallback)
}
function addRemoteVideo (videoToCreateData, fromPod, finalCallback) {
@ -257,7 +269,7 @@ function addRemoteVideo (videoToCreateData, fromPod, finalCallback) {
waterfall([
databaseUtils.startSerializableTransaction,
startSerializableTransaction,
function assertRemoteIdAndHostUnique (t, callback) {
db.Video.loadByHostAndRemoteId(fromPod.host, videoToCreateData.remoteId, function (err, video) {
@ -345,13 +357,13 @@ function addRemoteVideo (videoToCreateData, fromPod, finalCallback) {
})
},
databaseUtils.commitTransaction
commitTransaction
], function (err, t) {
if (err) {
// This is just a debug because we will retry the insert
logger.debug('Cannot insert the remote video.', { error: err })
return databaseUtils.rollbackTransaction(err, t, finalCallback)
return rollbackTransaction(err, t, finalCallback)
}
logger.info('Remote video %s inserted.', videoToCreateData.name)
@ -366,7 +378,7 @@ function updateRemoteVideoRetryWrapper (videoAttributesToUpdate, fromPod, finalC
errorMessage: 'Cannot update the remote video with many retries'
}
databaseUtils.retryTransactionWrapper(updateRemoteVideo, options, finalCallback)
retryTransactionWrapper(updateRemoteVideo, options, finalCallback)
}
function updateRemoteVideo (videoAttributesToUpdate, fromPod, finalCallback) {
@ -374,7 +386,7 @@ function updateRemoteVideo (videoAttributesToUpdate, fromPod, finalCallback) {
waterfall([
databaseUtils.startSerializableTransaction,
startSerializableTransaction,
function findVideo (t, callback) {
fetchRemoteVideo(fromPod.host, videoAttributesToUpdate.remoteId, function (err, videoInstance) {
@ -421,13 +433,13 @@ function updateRemoteVideo (videoAttributesToUpdate, fromPod, finalCallback) {
})
},
databaseUtils.commitTransaction
commitTransaction
], function (err, t) {
if (err) {
// This is just a debug because we will retry the insert
logger.debug('Cannot update the remote video.', { error: err })
return databaseUtils.rollbackTransaction(err, t, finalCallback)
return rollbackTransaction(err, t, finalCallback)
}
logger.info('Remote video %s updated', videoAttributesToUpdate.name)

View File

@ -1,32 +1,34 @@
'use strict'
import express = require('express')
import { parallel } from 'async'
const express = require('express')
const parallel = require('async/parallel')
import {
getRequestScheduler,
getRequestVideoQaduScheduler,
getRequestVideoEventScheduler
} from '../../lib'
import { authenticate, ensureIsAdmin } from '../../middlewares'
const friends = require('../../lib/friends')
const middlewares = require('../../middlewares')
const admin = middlewares.admin
const oAuth = middlewares.oauth
const requestsRouter = express.Router()
const router = express.Router()
router.get('/stats',
oAuth.authenticate,
admin.ensureIsAdmin,
requestsRouter.get('/stats',
authenticate,
ensureIsAdmin,
getStatsRequests
)
// ---------------------------------------------------------------------------
module.exports = router
export {
requestsRouter
}
// ---------------------------------------------------------------------------
function getStatsRequests (req, res, next) {
parallel({
requestScheduler: buildRequestSchedulerFunction(friends.getRequestScheduler()),
requestVideoQaduScheduler: buildRequestSchedulerFunction(friends.getRequestVideoQaduScheduler()),
requestVideoEventScheduler: buildRequestSchedulerFunction(friends.getRequestVideoEventScheduler())
requestScheduler: buildRequestSchedulerFunction(getRequestScheduler()),
requestVideoQaduScheduler: buildRequestSchedulerFunction(getRequestVideoQaduScheduler()),
requestVideoEventScheduler: buildRequestSchedulerFunction(getRequestVideoEventScheduler())
}, function (err, result) {
if (err) return next(err)

View File

@ -1,79 +1,83 @@
'use strict'
import express = require('express')
import { waterfall } from 'async'
const express = require('express')
const waterfall = require('async/waterfall')
const constants = require('../../initializers/constants')
const db = require('../../initializers/database')
const logger = require('../../helpers/logger')
const utils = require('../../helpers/utils')
const middlewares = require('../../middlewares')
const admin = middlewares.admin
const oAuth = middlewares.oauth
const pagination = middlewares.pagination
const sort = middlewares.sort
const validatorsPagination = middlewares.validators.pagination
const validatorsSort = middlewares.validators.sort
const validatorsUsers = middlewares.validators.users
import { CONFIG, USER_ROLES } from '../../initializers'
import { logger, getFormatedObjects } from '../../helpers'
import {
authenticate,
ensureIsAdmin,
usersAddValidator,
usersUpdateValidator,
usersRemoveValidator,
usersVideoRatingValidator,
paginationValidator,
setPagination,
usersSortValidator,
setUsersSort,
token
} from '../../middlewares'
const router = express.Router()
const usersRouter = express.Router()
router.get('/me',
oAuth.authenticate,
usersRouter.get('/me',
authenticate,
getUserInformation
)
router.get('/me/videos/:videoId/rating',
oAuth.authenticate,
validatorsUsers.usersVideoRating,
usersRouter.get('/me/videos/:videoId/rating',
authenticate,
usersVideoRatingValidator,
getUserVideoRating
)
router.get('/',
validatorsPagination.pagination,
validatorsSort.usersSort,
sort.setUsersSort,
pagination.setPagination,
usersRouter.get('/',
paginationValidator,
usersSortValidator,
setUsersSort,
setPagination,
listUsers
)
router.post('/',
oAuth.authenticate,
admin.ensureIsAdmin,
validatorsUsers.usersAdd,
usersRouter.post('/',
authenticate,
ensureIsAdmin,
usersAddValidator,
createUser
)
router.post('/register',
usersRouter.post('/register',
ensureRegistrationEnabled,
validatorsUsers.usersAdd,
usersAddValidator,
createUser
)
router.put('/:id',
oAuth.authenticate,
validatorsUsers.usersUpdate,
usersRouter.put('/:id',
authenticate,
usersUpdateValidator,
updateUser
)
router.delete('/:id',
oAuth.authenticate,
admin.ensureIsAdmin,
validatorsUsers.usersRemove,
usersRouter.delete('/:id',
authenticate,
ensureIsAdmin,
usersRemoveValidator,
removeUser
)
router.post('/token', oAuth.token, success)
usersRouter.post('/token', token, success)
// TODO: Once https://github.com/oauthjs/node-oauth2-server/pull/289 is merged, implement revoke token route
// ---------------------------------------------------------------------------
module.exports = router
export {
usersRouter
}
// ---------------------------------------------------------------------------
function ensureRegistrationEnabled (req, res, next) {
const registrationEnabled = constants.CONFIG.SIGNUP.ENABLED
const registrationEnabled = CONFIG.SIGNUP.ENABLED
if (registrationEnabled === true) {
return next()
@ -88,7 +92,7 @@ function createUser (req, res, next) {
password: req.body.password,
email: req.body.email,
displayNSFW: false,
role: constants.USER_ROLES.USER
role: USER_ROLES.USER
})
user.save().asCallback(function (err, createdUser) {
@ -126,7 +130,7 @@ function listUsers (req, res, next) {
db.User.listForApi(req.query.start, req.query.count, req.query.sort, function (err, usersList, usersTotal) {
if (err) return next(err)
res.json(utils.getFormatedObjects(usersList, usersTotal))
res.json(getFormatedObjects(usersList, usersTotal))
})
}

View File

@ -1,43 +1,48 @@
'use strict'
const express = require('express')
const waterfall = require('async/waterfall')
import express = require('express')
import { waterfall } from 'async'
const db = require('../../../initializers/database')
const logger = require('../../../helpers/logger')
const friends = require('../../../lib/friends')
const middlewares = require('../../../middlewares')
const admin = middlewares.admin
const oAuth = middlewares.oauth
const pagination = middlewares.pagination
const validators = middlewares.validators
const validatorsPagination = validators.pagination
const validatorsSort = validators.sort
const validatorsVideos = validators.videos
const sort = middlewares.sort
const databaseUtils = require('../../../helpers/database-utils')
const utils = require('../../../helpers/utils')
import friends = require('../../../lib/friends')
import {
logger,
getFormatedObjects,
retryTransactionWrapper,
startSerializableTransaction,
commitTransaction,
rollbackTransaction
} from '../../../helpers'
import {
authenticate,
ensureIsAdmin,
paginationValidator,
videoAbuseReportValidator,
videoAbusesSortValidator,
setVideoAbusesSort,
setPagination
} from '../../../middlewares'
const router = express.Router()
const abuseVideoRouter = express.Router()
router.get('/abuse',
oAuth.authenticate,
admin.ensureIsAdmin,
validatorsPagination.pagination,
validatorsSort.videoAbusesSort,
sort.setVideoAbusesSort,
pagination.setPagination,
abuseVideoRouter.get('/abuse',
authenticate,
ensureIsAdmin,
paginationValidator,
videoAbusesSortValidator,
setVideoAbusesSort,
setPagination,
listVideoAbuses
)
router.post('/:id/abuse',
oAuth.authenticate,
validatorsVideos.videoAbuseReport,
abuseVideoRouter.post('/:id/abuse',
authenticate,
videoAbuseReportValidator,
reportVideoAbuseRetryWrapper
)
// ---------------------------------------------------------------------------
module.exports = router
export {
abuseVideoRouter
}
// ---------------------------------------------------------------------------
@ -45,7 +50,7 @@ function listVideoAbuses (req, res, next) {
db.VideoAbuse.listForApi(req.query.start, req.query.count, req.query.sort, function (err, abusesList, abusesTotal) {
if (err) return next(err)
res.json(utils.getFormatedObjects(abusesList, abusesTotal))
res.json(getFormatedObjects(abusesList, abusesTotal))
})
}
@ -55,7 +60,7 @@ function reportVideoAbuseRetryWrapper (req, res, next) {
errorMessage: 'Cannot report abuse to the video with many retries.'
}
databaseUtils.retryTransactionWrapper(reportVideoAbuse, options, function (err) {
retryTransactionWrapper(reportVideoAbuse, options, function (err) {
if (err) return next(err)
return res.type('json').status(204).end()
@ -75,7 +80,7 @@ function reportVideoAbuse (req, res, finalCallback) {
waterfall([
databaseUtils.startSerializableTransaction,
startSerializableTransaction,
function createAbuse (t, callback) {
db.VideoAbuse.create(abuse).asCallback(function (err, abuse) {
@ -98,12 +103,12 @@ function reportVideoAbuse (req, res, finalCallback) {
return callback(null, t)
},
databaseUtils.commitTransaction
commitTransaction
], function andFinally (err, t) {
if (err) {
logger.debug('Cannot update the video.', { error: err })
return databaseUtils.rollbackTransaction(err, t, finalCallback)
return rollbackTransaction(err, t, finalCallback)
}
logger.info('Abuse report for video %s created.', videoInstance.name)

View File

@ -1,27 +1,27 @@
'use strict'
const express = require('express')
import express = require('express')
const db = require('../../../initializers/database')
const logger = require('../../../helpers/logger')
const middlewares = require('../../../middlewares')
const admin = middlewares.admin
const oAuth = middlewares.oauth
const validators = middlewares.validators
const validatorsVideos = validators.videos
import { logger } from '../../../helpers'
import {
authenticate,
ensureIsAdmin,
videosBlacklistValidator
} from '../../../middlewares'
const router = express.Router()
const blacklistRouter = express.Router()
router.post('/:id/blacklist',
oAuth.authenticate,
admin.ensureIsAdmin,
validatorsVideos.videosBlacklist,
blacklistRouter.post('/:id/blacklist',
authenticate,
ensureIsAdmin,
videosBlacklistValidator,
addVideoToBlacklist
)
// ---------------------------------------------------------------------------
module.exports = router
export {
blacklistRouter
}
// ---------------------------------------------------------------------------

View File

@ -1,37 +1,57 @@
'use strict'
import express = require('express')
import fs = require('fs')
import multer = require('multer')
import path = require('path')
import { waterfall } from 'async'
const express = require('express')
const fs = require('fs')
const multer = require('multer')
const path = require('path')
const waterfall = require('async/waterfall')
const constants = require('../../../initializers/constants')
const db = require('../../../initializers/database')
const logger = require('../../../helpers/logger')
const friends = require('../../../lib/friends')
const middlewares = require('../../../middlewares')
const oAuth = middlewares.oauth
const pagination = middlewares.pagination
const validators = middlewares.validators
const validatorsPagination = validators.pagination
const validatorsSort = validators.sort
const validatorsVideos = validators.videos
const search = middlewares.search
const sort = middlewares.sort
const databaseUtils = require('../../../helpers/database-utils')
const utils = require('../../../helpers/utils')
import {
CONFIG,
REQUEST_VIDEO_QADU_TYPES,
REQUEST_VIDEO_EVENT_TYPES,
VIDEO_CATEGORIES,
VIDEO_LICENCES,
VIDEO_LANGUAGES
} from '../../../initializers'
import {
addEventToRemoteVideo,
quickAndDirtyUpdateVideoToFriends,
addVideoToFriends,
updateVideoToFriends
} from '../../../lib'
import {
authenticate,
paginationValidator,
videosSortValidator,
setVideosSort,
setPagination,
setVideosSearch,
videosUpdateValidator,
videosSearchValidator,
videosAddValidator,
videosGetValidator,
videosRemoveValidator
} from '../../../middlewares'
import {
logger,
commitTransaction,
retryTransactionWrapper,
rollbackTransaction,
startSerializableTransaction,
generateRandomString,
getFormatedObjects
} from '../../../helpers'
const abuseController = require('./abuse')
const blacklistController = require('./blacklist')
const rateController = require('./rate')
import { abuseVideoRouter } from './abuse'
import { blacklistRouter } from './blacklist'
import { rateVideoRouter } from './rate'
const router = express.Router()
const videosRouter = express.Router()
// multer configuration
const storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, constants.CONFIG.STORAGE.VIDEOS_DIR)
cb(null, CONFIG.STORAGE.VIDEOS_DIR)
},
filename: function (req, file, cb) {
@ -39,7 +59,7 @@ const storage = multer.diskStorage({
if (file.mimetype === 'video/webm') extension = 'webm'
else if (file.mimetype === 'video/mp4') extension = 'mp4'
else if (file.mimetype === 'video/ogg') extension = 'ogv'
utils.generateRandomString(16, function (err, randomString) {
generateRandomString(16, function (err, randomString) {
const fieldname = err ? undefined : randomString
cb(null, fieldname + '.' + extension)
})
@ -48,70 +68,72 @@ const storage = multer.diskStorage({
const reqFiles = multer({ storage: storage }).fields([{ name: 'videofile', maxCount: 1 }])
router.use('/', abuseController)
router.use('/', blacklistController)
router.use('/', rateController)
videosRouter.use('/', abuseVideoRouter)
videosRouter.use('/', blacklistRouter)
videosRouter.use('/', rateVideoRouter)
router.get('/categories', listVideoCategories)
router.get('/licences', listVideoLicences)
router.get('/languages', listVideoLanguages)
videosRouter.get('/categories', listVideoCategories)
videosRouter.get('/licences', listVideoLicences)
videosRouter.get('/languages', listVideoLanguages)
router.get('/',
validatorsPagination.pagination,
validatorsSort.videosSort,
sort.setVideosSort,
pagination.setPagination,
videosRouter.get('/',
paginationValidator,
videosSortValidator,
setVideosSort,
setPagination,
listVideos
)
router.put('/:id',
oAuth.authenticate,
videosRouter.put('/:id',
authenticate,
reqFiles,
validatorsVideos.videosUpdate,
videosUpdateValidator,
updateVideoRetryWrapper
)
router.post('/',
oAuth.authenticate,
videosRouter.post('/',
authenticate,
reqFiles,
validatorsVideos.videosAdd,
videosAddValidator,
addVideoRetryWrapper
)
router.get('/:id',
validatorsVideos.videosGet,
videosRouter.get('/:id',
videosGetValidator,
getVideo
)
router.delete('/:id',
oAuth.authenticate,
validatorsVideos.videosRemove,
videosRouter.delete('/:id',
authenticate,
videosRemoveValidator,
removeVideo
)
router.get('/search/:value',
validatorsVideos.videosSearch,
validatorsPagination.pagination,
validatorsSort.videosSort,
sort.setVideosSort,
pagination.setPagination,
search.setVideosSearch,
videosRouter.get('/search/:value',
videosSearchValidator,
paginationValidator,
videosSortValidator,
setVideosSort,
setPagination,
setVideosSearch,
searchVideos
)
// ---------------------------------------------------------------------------
module.exports = router
export {
videosRouter
}
// ---------------------------------------------------------------------------
function listVideoCategories (req, res, next) {
res.json(constants.VIDEO_CATEGORIES)
res.json(VIDEO_CATEGORIES)
}
function listVideoLicences (req, res, next) {
res.json(constants.VIDEO_LICENCES)
res.json(VIDEO_LICENCES)
}
function listVideoLanguages (req, res, next) {
res.json(constants.VIDEO_LANGUAGES)
res.json(VIDEO_LANGUAGES)
}
// Wrapper to video add that retry the function if there is a database error
@ -122,7 +144,7 @@ function addVideoRetryWrapper (req, res, next) {
errorMessage: 'Cannot insert the video with many retries.'
}
databaseUtils.retryTransactionWrapper(addVideo, options, function (err) {
retryTransactionWrapper(addVideo, options, function (err) {
if (err) return next(err)
// TODO : include Location of the new video -> 201
@ -135,7 +157,7 @@ function addVideo (req, res, videoFile, finalCallback) {
waterfall([
databaseUtils.startSerializableTransaction,
startSerializableTransaction,
function findOrCreateAuthor (t, callback) {
const user = res.locals.oauth.token.User
@ -179,7 +201,7 @@ function addVideo (req, res, videoFile, finalCallback) {
// Set the videoname the same as the id
function renameVideoFile (t, author, tagInstances, video, callback) {
const videoDir = constants.CONFIG.STORAGE.VIDEOS_DIR
const videoDir = CONFIG.STORAGE.VIDEOS_DIR
const source = path.join(videoDir, videoFile.filename)
const destination = path.join(videoDir, video.getVideoFilename())
@ -218,25 +240,25 @@ function addVideo (req, res, videoFile, finalCallback) {
function sendToFriends (t, video, callback) {
// Let transcoding job send the video to friends because the videofile extension might change
if (constants.CONFIG.TRANSCODING.ENABLED === true) return callback(null, t)
if (CONFIG.TRANSCODING.ENABLED === true) return callback(null, t)
video.toAddRemoteJSON(function (err, remoteVideo) {
if (err) return callback(err)
// Now we'll add the video's meta data to our friends
friends.addVideoToFriends(remoteVideo, t, function (err) {
addVideoToFriends(remoteVideo, t, function (err) {
return callback(err, t)
})
})
},
databaseUtils.commitTransaction
commitTransaction
], function andFinally (err, t) {
if (err) {
// This is just a debug because we will retry the insert
logger.debug('Cannot insert the video.', { error: err })
return databaseUtils.rollbackTransaction(err, t, finalCallback)
return rollbackTransaction(err, t, finalCallback)
}
logger.info('Video with name %s created.', videoInfos.name)
@ -250,7 +272,7 @@ function updateVideoRetryWrapper (req, res, next) {
errorMessage: 'Cannot update the video with many retries.'
}
databaseUtils.retryTransactionWrapper(updateVideo, options, function (err) {
retryTransactionWrapper(updateVideo, options, function (err) {
if (err) return next(err)
// TODO : include Location of the new video -> 201
@ -265,7 +287,7 @@ function updateVideo (req, res, finalCallback) {
waterfall([
databaseUtils.startSerializableTransaction,
startSerializableTransaction,
function findOrCreateTags (t, callback) {
if (videoInfosToUpdate.tags) {
@ -312,12 +334,12 @@ function updateVideo (req, res, finalCallback) {
const json = videoInstance.toUpdateRemoteJSON()
// Now we'll update the video's meta data to our friends
friends.updateVideoToFriends(json, t, function (err) {
updateVideoToFriends(json, t, function (err) {
return callback(err, t)
})
},
databaseUtils.commitTransaction
commitTransaction
], function andFinally (err, t) {
if (err) {
@ -331,7 +353,7 @@ function updateVideo (req, res, finalCallback) {
videoInstance.set(key, value)
})
return databaseUtils.rollbackTransaction(err, t, finalCallback)
return rollbackTransaction(err, t, finalCallback)
}
logger.info('Video with name %s updated.', videoInfosToUpdate.name)
@ -354,17 +376,17 @@ function getVideo (req, res, next) {
// For example, only add a view when a user watch a video during 30s etc
const qaduParams = {
videoId: videoInstance.id,
type: constants.REQUEST_VIDEO_QADU_TYPES.VIEWS
type: REQUEST_VIDEO_QADU_TYPES.VIEWS
}
friends.quickAndDirtyUpdateVideoToFriends(qaduParams)
quickAndDirtyUpdateVideoToFriends(qaduParams)
})
} else {
// Just send the event to our friends
const eventParams = {
videoId: videoInstance.id,
type: constants.REQUEST_VIDEO_EVENT_TYPES.VIEWS
type: REQUEST_VIDEO_EVENT_TYPES.VIEWS
}
friends.addEventToRemoteVideo(eventParams)
addEventToRemoteVideo(eventParams)
}
// Do not wait the view system
@ -375,7 +397,7 @@ function listVideos (req, res, next) {
db.Video.listForApi(req.query.start, req.query.count, req.query.sort, function (err, videosList, videosTotal) {
if (err) return next(err)
res.json(utils.getFormatedObjects(videosList, videosTotal))
res.json(getFormatedObjects(videosList, videosTotal))
})
}
@ -398,7 +420,7 @@ function searchVideos (req, res, next) {
function (err, videosList, videosTotal) {
if (err) return next(err)
res.json(utils.getFormatedObjects(videosList, videosTotal))
res.json(getFormatedObjects(videosList, videosTotal))
}
)
}

View File

@ -1,29 +1,41 @@
'use strict'
import express = require('express')
import { waterfall } from 'async'
const express = require('express')
const waterfall = require('async/waterfall')
const constants = require('../../../initializers/constants')
const db = require('../../../initializers/database')
const logger = require('../../../helpers/logger')
const friends = require('../../../lib/friends')
const middlewares = require('../../../middlewares')
const oAuth = middlewares.oauth
const validators = middlewares.validators
const validatorsVideos = validators.videos
const databaseUtils = require('../../../helpers/database-utils')
import {
logger,
retryTransactionWrapper,
startSerializableTransaction,
commitTransaction,
rollbackTransaction
} from '../../../helpers'
import {
VIDEO_RATE_TYPES,
REQUEST_VIDEO_EVENT_TYPES,
REQUEST_VIDEO_QADU_TYPES
} from '../../../initializers'
import {
addEventsToRemoteVideo,
quickAndDirtyUpdatesVideoToFriends
} from '../../../lib'
import {
authenticate,
videoRateValidator
} from '../../../middlewares'
const router = express.Router()
const rateVideoRouter = express.Router()
router.put('/:id/rate',
oAuth.authenticate,
validatorsVideos.videoRate,
rateVideoRouter.put('/:id/rate',
authenticate,
videoRateValidator,
rateVideoRetryWrapper
)
// ---------------------------------------------------------------------------
module.exports = router
export {
rateVideoRouter
}
// ---------------------------------------------------------------------------
@ -33,7 +45,7 @@ function rateVideoRetryWrapper (req, res, next) {
errorMessage: 'Cannot update the user video rate.'
}
databaseUtils.retryTransactionWrapper(rateVideo, options, function (err) {
retryTransactionWrapper(rateVideo, options, function (err) {
if (err) return next(err)
return res.type('json').status(204).end()
@ -46,7 +58,7 @@ function rateVideo (req, res, finalCallback) {
const userInstance = res.locals.oauth.token.User
waterfall([
databaseUtils.startSerializableTransaction,
startSerializableTransaction,
function findPreviousRate (t, callback) {
db.UserVideoRate.load(userInstance.id, videoInstance.id, t, function (err, previousRate) {
@ -60,14 +72,14 @@ function rateVideo (req, res, finalCallback) {
let likesToIncrement = 0
let dislikesToIncrement = 0
if (rateType === constants.VIDEO_RATE_TYPES.LIKE) likesToIncrement++
else if (rateType === constants.VIDEO_RATE_TYPES.DISLIKE) dislikesToIncrement++
if (rateType === VIDEO_RATE_TYPES.LIKE) likesToIncrement++
else if (rateType === VIDEO_RATE_TYPES.DISLIKE) dislikesToIncrement++
// There was a previous rate, update it
if (previousRate) {
// We will remove the previous rate, so we will need to remove it from the video attribute
if (previousRate.type === constants.VIDEO_RATE_TYPES.LIKE) likesToIncrement--
else if (previousRate.type === constants.VIDEO_RATE_TYPES.DISLIKE) dislikesToIncrement--
if (previousRate.type === VIDEO_RATE_TYPES.LIKE) likesToIncrement--
else if (previousRate.type === VIDEO_RATE_TYPES.DISLIKE) dislikesToIncrement--
previousRate.type = rateType
@ -110,7 +122,7 @@ function rateVideo (req, res, finalCallback) {
if (likesToIncrement !== 0) {
eventsParams.push({
videoId: videoInstance.id,
type: constants.REQUEST_VIDEO_EVENT_TYPES.LIKES,
type: REQUEST_VIDEO_EVENT_TYPES.LIKES,
count: likesToIncrement
})
}
@ -118,12 +130,12 @@ function rateVideo (req, res, finalCallback) {
if (dislikesToIncrement !== 0) {
eventsParams.push({
videoId: videoInstance.id,
type: constants.REQUEST_VIDEO_EVENT_TYPES.DISLIKES,
type: REQUEST_VIDEO_EVENT_TYPES.DISLIKES,
count: dislikesToIncrement
})
}
friends.addEventsToRemoteVideo(eventsParams, t, function (err) {
addEventsToRemoteVideo(eventsParams, t, function (err) {
return callback(err, t, likesToIncrement, dislikesToIncrement)
})
},
@ -138,29 +150,29 @@ function rateVideo (req, res, finalCallback) {
if (likesToIncrement !== 0) {
qadusParams.push({
videoId: videoInstance.id,
type: constants.REQUEST_VIDEO_QADU_TYPES.LIKES
type: REQUEST_VIDEO_QADU_TYPES.LIKES
})
}
if (dislikesToIncrement !== 0) {
qadusParams.push({
videoId: videoInstance.id,
type: constants.REQUEST_VIDEO_QADU_TYPES.DISLIKES
type: REQUEST_VIDEO_QADU_TYPES.DISLIKES
})
}
friends.quickAndDirtyUpdatesVideoToFriends(qadusParams, t, function (err) {
quickAndDirtyUpdatesVideoToFriends(qadusParams, t, function (err) {
return callback(err, t)
})
},
databaseUtils.commitTransaction
commitTransaction
], function (err, t) {
if (err) {
// This is just a debug because we will retry the insert
logger.debug('Cannot add the user video rate.', { error: err })
return databaseUtils.rollbackTransaction(err, t, finalCallback)
return rollbackTransaction(err, t, finalCallback)
}
logger.info('User video rate for video %s of user %s updated.', videoInstance.name, userInstance.username)

View File

@ -1,40 +1,48 @@
'use strict'
import { parallel } from 'async'
import express = require('express')
import fs = require('fs')
import { join } from 'path'
import expressValidator = require('express-validator')
// TODO: use .validator when express-validator typing will have validator field
const validator = expressValidator['validator']
const parallel = require('async/parallel')
const express = require('express')
const fs = require('fs')
const path = require('path')
const validator = require('express-validator').validator
const constants = require('../initializers/constants')
const db = require('../initializers/database')
import {
CONFIG,
REMOTE_SCHEME,
STATIC_PATHS,
STATIC_MAX_AGE
} from '../initializers'
const router = express.Router()
const clientsRouter = express.Router()
// TODO: move to constants
const opengraphComment = '<!-- opengraph tags -->'
const distPath = path.join(__dirname, '..', '..', 'client/dist')
const embedPath = path.join(distPath, 'standalone/videos/embed.html')
const indexPath = path.join(distPath, 'index.html')
const distPath = join(__dirname, '..', '..', 'client/dist')
const embedPath = join(distPath, 'standalone/videos/embed.html')
const indexPath = join(distPath, 'index.html')
// Special route that add OpenGraph tags
// Do not use a template engine for a so little thing
router.use('/videos/watch/:id', generateWatchHtmlPage)
clientsRouter.use('/videos/watch/:id', generateWatchHtmlPage)
router.use('/videos/embed', function (req, res, next) {
clientsRouter.use('/videos/embed', function (req, res, next) {
res.sendFile(embedPath)
})
// Static HTML/CSS/JS client files
router.use('/client', express.static(distPath, { maxAge: constants.STATIC_MAX_AGE }))
clientsRouter.use('/client', express.static(distPath, { maxAge: STATIC_MAX_AGE }))
// 404 for static files not found
router.use('/client/*', function (req, res, next) {
clientsRouter.use('/client/*', function (req, res, next) {
res.sendStatus(404)
})
// ---------------------------------------------------------------------------
module.exports = router
export {
clientsRouter
}
// ---------------------------------------------------------------------------
@ -42,16 +50,16 @@ function addOpenGraphTags (htmlStringPage, video) {
let basePreviewUrlHttp
if (video.isOwned()) {
basePreviewUrlHttp = constants.CONFIG.WEBSERVER.URL
basePreviewUrlHttp = CONFIG.WEBSERVER.URL
} else {
basePreviewUrlHttp = constants.REMOTE_SCHEME.HTTP + '://' + video.Author.Pod.host
basePreviewUrlHttp = REMOTE_SCHEME.HTTP + '://' + video.Author.Pod.host
}
// We fetch the remote preview (bigger than the thumbnail)
// This should not overhead the remote server since social websites put in a cache the OpenGraph tags
// We can't use the thumbnail because these social websites want bigger images (> 200x200 for Facebook for example)
const previewUrl = basePreviewUrlHttp + constants.STATIC_PATHS.PREVIEWS + video.getPreviewName()
const videoUrl = constants.CONFIG.WEBSERVER.URL + '/videos/watch/' + video.id
const previewUrl = basePreviewUrlHttp + STATIC_PATHS.PREVIEWS + video.getPreviewName()
const videoUrl = CONFIG.WEBSERVER.URL + '/videos/watch/' + video.id
const metaTags = {
'og:type': 'video',
@ -95,11 +103,11 @@ function generateWatchHtmlPage (req, res, next) {
video: function (callback) {
db.Video.loadAndPopulateAuthorAndPodAndTags(videoId, callback)
}
}, function (err, results) {
}, function (err, result: any) {
if (err) return next(err)
const html = results.file.toString()
const video = results.video
const html = result.file.toString()
const video = result.video
// Let Angular application handle errors
if (!video) return res.sendFile(indexPath)

View File

@ -1,11 +0,0 @@
'use strict'
const apiController = require('./api/')
const clientController = require('./client')
const staticController = require('./static')
module.exports = {
api: apiController,
client: clientController,
static: staticController
}

View File

@ -0,0 +1,3 @@
export * from './static';
export * from './client';
export * from './api';

View File

@ -1,45 +0,0 @@
'use strict'
const express = require('express')
const cors = require('cors')
const constants = require('../initializers/constants')
const router = express.Router()
/*
Cors is very important to let other pods access torrent and video files
*/
const torrentsPhysicalPath = constants.CONFIG.STORAGE.TORRENTS_DIR
router.use(
constants.STATIC_PATHS.TORRENTS,
cors(),
express.static(torrentsPhysicalPath, { maxAge: constants.STATIC_MAX_AGE })
)
// Videos path for webseeding
const videosPhysicalPath = constants.CONFIG.STORAGE.VIDEOS_DIR
router.use(
constants.STATIC_PATHS.WEBSEED,
cors(),
express.static(videosPhysicalPath, { maxAge: constants.STATIC_MAX_AGE })
)
// Thumbnails path for express
const thumbnailsPhysicalPath = constants.CONFIG.STORAGE.THUMBNAILS_DIR
router.use(
constants.STATIC_PATHS.THUMBNAILS,
express.static(thumbnailsPhysicalPath, { maxAge: constants.STATIC_MAX_AGE })
)
// Video previews path for express
const previewsPhysicalPath = constants.CONFIG.STORAGE.PREVIEWS_DIR
router.use(
constants.STATIC_PATHS.PREVIEWS,
express.static(previewsPhysicalPath, { maxAge: constants.STATIC_MAX_AGE })
)
// ---------------------------------------------------------------------------
module.exports = router

View File

@ -0,0 +1,49 @@
import express = require('express')
import cors = require('cors')
import {
CONFIG,
STATIC_MAX_AGE,
STATIC_PATHS
} from '../initializers'
const staticRouter = express.Router()
/*
Cors is very important to let other pods access torrent and video files
*/
const torrentsPhysicalPath = CONFIG.STORAGE.TORRENTS_DIR
staticRouter.use(
STATIC_PATHS.TORRENTS,
cors(),
express.static(torrentsPhysicalPath, { maxAge: STATIC_MAX_AGE })
)
// Videos path for webseeding
const videosPhysicalPath = CONFIG.STORAGE.VIDEOS_DIR
staticRouter.use(
STATIC_PATHS.WEBSEED,
cors(),
express.static(videosPhysicalPath, { maxAge: STATIC_MAX_AGE })
)
// Thumbnails path for express
const thumbnailsPhysicalPath = CONFIG.STORAGE.THUMBNAILS_DIR
staticRouter.use(
STATIC_PATHS.THUMBNAILS,
express.static(thumbnailsPhysicalPath, { maxAge: STATIC_MAX_AGE })
)
// Video previews path for express
const previewsPhysicalPath = CONFIG.STORAGE.PREVIEWS_DIR
staticRouter.use(
STATIC_PATHS.PREVIEWS,
express.static(previewsPhysicalPath, { maxAge: STATIC_MAX_AGE })
)
// ---------------------------------------------------------------------------
export {
staticRouter
}

View File

@ -1,19 +0,0 @@
'use strict'
const miscValidators = require('./misc')
const podsValidators = require('./pods')
const remoteValidators = require('./remote')
const usersValidators = require('./users')
const videosValidators = require('./videos')
const validators = {
misc: miscValidators,
pods: podsValidators,
remote: remoteValidators,
users: usersValidators,
videos: videosValidators
}
// ---------------------------------------------------------------------------
module.exports = validators

View File

@ -0,0 +1,6 @@
export * from './remote'
export * from './misc'
export * from './pods'
export * from './pods'
export * from './users'
export * from './videos'

View File

@ -1,10 +1,3 @@
'use strict'
const miscValidators = {
exists,
isArray
}
function exists (value) {
return value !== undefined && value !== null
}
@ -15,4 +8,7 @@ function isArray (value) {
// ---------------------------------------------------------------------------
module.exports = miscValidators
export {
exists,
isArray
}

View File

@ -1,20 +1,15 @@
'use strict'
import expressValidator = require('express-validator')
// TODO: use .validator when express-validator typing will have validator field
const validator = expressValidator['validator']
const validator = require('express-validator').validator
const miscValidators = require('./misc')
const podsValidators = {
isEachUniqueHostValid,
isHostValid
}
import { isArray } from './misc'
function isHostValid (host) {
return validator.isURL(host) && host.split('://').length === 1
}
function isEachUniqueHostValid (hosts) {
return miscValidators.isArray(hosts) &&
return isArray(hosts) &&
hosts.length !== 0 &&
hosts.every(function (host) {
return isHostValid(host) && hosts.indexOf(host) === hosts.lastIndexOf(host)
@ -23,4 +18,7 @@ function isEachUniqueHostValid (hosts) {
// ---------------------------------------------------------------------------
module.exports = podsValidators
export {
isEachUniqueHostValid,
isHostValid
}

View File

@ -1,11 +0,0 @@
'use strict'
const remoteVideosValidators = require('./videos')
const validators = {
videos: remoteVideosValidators
}
// ---------------------------------------------------------------------------
module.exports = validators

View File

@ -0,0 +1 @@
export * from './videos';

View File

@ -1,118 +0,0 @@
'use strict'
const has = require('lodash/has')
const values = require('lodash/values')
const constants = require('../../../initializers/constants')
const videosValidators = require('../videos')
const miscValidators = require('../misc')
const ENDPOINT_ACTIONS = constants.REQUEST_ENDPOINT_ACTIONS[constants.REQUEST_ENDPOINTS.VIDEOS]
const remoteVideosValidators = {
isEachRemoteRequestVideosValid,
isEachRemoteRequestVideosQaduValid,
isEachRemoteRequestVideosEventsValid
}
function isEachRemoteRequestVideosValid (requests) {
return miscValidators.isArray(requests) &&
requests.every(function (request) {
const video = request.data
if (!video) return false
return (
isRequestTypeAddValid(request.type) &&
isCommonVideoAttributesValid(video) &&
videosValidators.isVideoAuthorValid(video.author) &&
videosValidators.isVideoThumbnailDataValid(video.thumbnailData)
) ||
(
isRequestTypeUpdateValid(request.type) &&
isCommonVideoAttributesValid(video)
) ||
(
isRequestTypeRemoveValid(request.type) &&
videosValidators.isVideoRemoteIdValid(video.remoteId)
) ||
(
isRequestTypeReportAbuseValid(request.type) &&
videosValidators.isVideoRemoteIdValid(request.data.videoRemoteId) &&
videosValidators.isVideoAbuseReasonValid(request.data.reportReason) &&
videosValidators.isVideoAbuseReporterUsernameValid(request.data.reporterUsername)
)
})
}
function isEachRemoteRequestVideosQaduValid (requests) {
return miscValidators.isArray(requests) &&
requests.every(function (request) {
const video = request.data
if (!video) return false
return (
videosValidators.isVideoRemoteIdValid(video.remoteId) &&
(has(video, 'views') === false || videosValidators.isVideoViewsValid) &&
(has(video, 'likes') === false || videosValidators.isVideoLikesValid) &&
(has(video, 'dislikes') === false || videosValidators.isVideoDislikesValid)
)
})
}
function isEachRemoteRequestVideosEventsValid (requests) {
return miscValidators.isArray(requests) &&
requests.every(function (request) {
const eventData = request.data
if (!eventData) return false
return (
videosValidators.isVideoRemoteIdValid(eventData.remoteId) &&
values(constants.REQUEST_VIDEO_EVENT_TYPES).indexOf(eventData.eventType) !== -1 &&
videosValidators.isVideoEventCountValid(eventData.count)
)
})
}
// ---------------------------------------------------------------------------
module.exports = remoteVideosValidators
// ---------------------------------------------------------------------------
function isCommonVideoAttributesValid (video) {
return videosValidators.isVideoDateValid(video.createdAt) &&
videosValidators.isVideoDateValid(video.updatedAt) &&
videosValidators.isVideoCategoryValid(video.category) &&
videosValidators.isVideoLicenceValid(video.licence) &&
videosValidators.isVideoLanguageValid(video.language) &&
videosValidators.isVideoNSFWValid(video.nsfw) &&
videosValidators.isVideoDescriptionValid(video.description) &&
videosValidators.isVideoDurationValid(video.duration) &&
videosValidators.isVideoInfoHashValid(video.infoHash) &&
videosValidators.isVideoNameValid(video.name) &&
videosValidators.isVideoTagsValid(video.tags) &&
videosValidators.isVideoRemoteIdValid(video.remoteId) &&
videosValidators.isVideoExtnameValid(video.extname) &&
videosValidators.isVideoViewsValid(video.views) &&
videosValidators.isVideoLikesValid(video.likes) &&
videosValidators.isVideoDislikesValid(video.dislikes)
}
function isRequestTypeAddValid (value) {
return value === ENDPOINT_ACTIONS.ADD
}
function isRequestTypeUpdateValid (value) {
return value === ENDPOINT_ACTIONS.UPDATE
}
function isRequestTypeRemoveValid (value) {
return value === ENDPOINT_ACTIONS.REMOVE
}
function isRequestTypeReportAbuseValid (value) {
return value === ENDPOINT_ACTIONS.REPORT_ABUSE
}

View File

@ -0,0 +1,138 @@
import { has, values } from 'lodash'
import {
REQUEST_ENDPOINTS,
REQUEST_ENDPOINT_ACTIONS,
REQUEST_VIDEO_EVENT_TYPES
} from '../../../initializers'
import { isArray } from '../misc'
import {
isVideoAuthorValid,
isVideoThumbnailDataValid,
isVideoRemoteIdValid,
isVideoAbuseReasonValid,
isVideoAbuseReporterUsernameValid,
isVideoViewsValid,
isVideoLikesValid,
isVideoDislikesValid,
isVideoEventCountValid,
isVideoDateValid,
isVideoCategoryValid,
isVideoLicenceValid,
isVideoLanguageValid,
isVideoNSFWValid,
isVideoDescriptionValid,
isVideoDurationValid,
isVideoInfoHashValid,
isVideoNameValid,
isVideoTagsValid,
isVideoExtnameValid
} from '../videos'
const ENDPOINT_ACTIONS = REQUEST_ENDPOINT_ACTIONS[REQUEST_ENDPOINTS.VIDEOS]
function isEachRemoteRequestVideosValid (requests) {
return isArray(requests) &&
requests.every(function (request) {
const video = request.data
if (!video) return false
return (
isRequestTypeAddValid(request.type) &&
isCommonVideoAttributesValid(video) &&
isVideoAuthorValid(video.author) &&
isVideoThumbnailDataValid(video.thumbnailData)
) ||
(
isRequestTypeUpdateValid(request.type) &&
isCommonVideoAttributesValid(video)
) ||
(
isRequestTypeRemoveValid(request.type) &&
isVideoRemoteIdValid(video.remoteId)
) ||
(
isRequestTypeReportAbuseValid(request.type) &&
isVideoRemoteIdValid(request.data.videoRemoteId) &&
isVideoAbuseReasonValid(request.data.reportReason) &&
isVideoAbuseReporterUsernameValid(request.data.reporterUsername)
)
})
}
function isEachRemoteRequestVideosQaduValid (requests) {
return isArray(requests) &&
requests.every(function (request) {
const video = request.data
if (!video) return false
return (
isVideoRemoteIdValid(video.remoteId) &&
(has(video, 'views') === false || isVideoViewsValid) &&
(has(video, 'likes') === false || isVideoLikesValid) &&
(has(video, 'dislikes') === false || isVideoDislikesValid)
)
})
}
function isEachRemoteRequestVideosEventsValid (requests) {
return isArray(requests) &&
requests.every(function (request) {
const eventData = request.data
if (!eventData) return false
return (
isVideoRemoteIdValid(eventData.remoteId) &&
values(REQUEST_VIDEO_EVENT_TYPES).indexOf(eventData.eventType) !== -1 &&
isVideoEventCountValid(eventData.count)
)
})
}
// ---------------------------------------------------------------------------
export {
isEachRemoteRequestVideosValid,
isEachRemoteRequestVideosQaduValid,
isEachRemoteRequestVideosEventsValid
}
// ---------------------------------------------------------------------------
function isCommonVideoAttributesValid (video) {
return isVideoDateValid(video.createdAt) &&
isVideoDateValid(video.updatedAt) &&
isVideoCategoryValid(video.category) &&
isVideoLicenceValid(video.licence) &&
isVideoLanguageValid(video.language) &&
isVideoNSFWValid(video.nsfw) &&
isVideoDescriptionValid(video.description) &&
isVideoDurationValid(video.duration) &&
isVideoInfoHashValid(video.infoHash) &&
isVideoNameValid(video.name) &&
isVideoTagsValid(video.tags) &&
isVideoRemoteIdValid(video.remoteId) &&
isVideoExtnameValid(video.extname) &&
isVideoViewsValid(video.views) &&
isVideoLikesValid(video.likes) &&
isVideoDislikesValid(video.dislikes)
}
function isRequestTypeAddValid (value) {
return value === ENDPOINT_ACTIONS.ADD
}
function isRequestTypeUpdateValid (value) {
return value === ENDPOINT_ACTIONS.UPDATE
}
function isRequestTypeRemoveValid (value) {
return value === ENDPOINT_ACTIONS.REMOVE
}
function isRequestTypeReportAbuseValid (value) {
return value === ENDPOINT_ACTIONS.REPORT_ABUSE
}

View File

@ -1,24 +1,17 @@
'use strict'
import { values } from 'lodash'
import expressValidator = require('express-validator')
// TODO: use .validator when express-validator typing will have validator field
const validator = expressValidator['validator']
const validator = require('express-validator').validator
const values = require('lodash/values')
const constants = require('../../initializers/constants')
const USERS_CONSTRAINTS_FIELDS = constants.CONSTRAINTS_FIELDS.USERS
const usersValidators = {
isUserPasswordValid,
isUserRoleValid,
isUserUsernameValid,
isUserDisplayNSFWValid
}
import { CONSTRAINTS_FIELDS, USER_ROLES } from '../../initializers'
const USERS_CONSTRAINTS_FIELDS = CONSTRAINTS_FIELDS.USERS
function isUserPasswordValid (value) {
return validator.isLength(value, USERS_CONSTRAINTS_FIELDS.PASSWORD)
}
function isUserRoleValid (value) {
return values(constants.USER_ROLES).indexOf(value) !== -1
return values(USER_ROLES).indexOf(value) !== -1
}
function isUserUsernameValid (value) {
@ -33,4 +26,9 @@ function isUserDisplayNSFWValid (value) {
// ---------------------------------------------------------------------------
module.exports = usersValidators
export {
isUserPasswordValid,
isUserRoleValid,
isUserUsernameValid,
isUserDisplayNSFWValid
}

View File

@ -1,43 +1,24 @@
'use strict'
import { values } from 'lodash'
import expressValidator = require('express-validator')
// TODO: use .validator when express-validator typing will have validator field
const validator = expressValidator['validator']
const validator = require('express-validator').validator
const values = require('lodash/values')
import {
CONSTRAINTS_FIELDS,
VIDEO_CATEGORIES,
VIDEO_LICENCES,
VIDEO_LANGUAGES,
VIDEO_RATE_TYPES
} from '../../initializers'
import { isUserUsernameValid } from './users'
import { isArray } from './misc'
const constants = require('../../initializers/constants')
const usersValidators = require('./users')
const miscValidators = require('./misc')
const VIDEOS_CONSTRAINTS_FIELDS = constants.CONSTRAINTS_FIELDS.VIDEOS
const VIDEO_ABUSES_CONSTRAINTS_FIELDS = constants.CONSTRAINTS_FIELDS.VIDEO_ABUSES
const VIDEO_EVENTS_CONSTRAINTS_FIELDS = constants.CONSTRAINTS_FIELDS.VIDEO_EVENTS
const videosValidators = {
isVideoAuthorValid,
isVideoDateValid,
isVideoCategoryValid,
isVideoLicenceValid,
isVideoLanguageValid,
isVideoNSFWValid,
isVideoDescriptionValid,
isVideoDurationValid,
isVideoInfoHashValid,
isVideoNameValid,
isVideoTagsValid,
isVideoThumbnailValid,
isVideoThumbnailDataValid,
isVideoExtnameValid,
isVideoRemoteIdValid,
isVideoAbuseReasonValid,
isVideoAbuseReporterUsernameValid,
isVideoFile,
isVideoViewsValid,
isVideoLikesValid,
isVideoRatingTypeValid,
isVideoDislikesValid,
isVideoEventCountValid
}
const VIDEOS_CONSTRAINTS_FIELDS = CONSTRAINTS_FIELDS.VIDEOS
const VIDEO_ABUSES_CONSTRAINTS_FIELDS = CONSTRAINTS_FIELDS.VIDEO_ABUSES
const VIDEO_EVENTS_CONSTRAINTS_FIELDS = CONSTRAINTS_FIELDS.VIDEO_EVENTS
function isVideoAuthorValid (value) {
return usersValidators.isUserUsernameValid(value)
return isUserUsernameValid(value)
}
function isVideoDateValid (value) {
@ -45,15 +26,15 @@ function isVideoDateValid (value) {
}
function isVideoCategoryValid (value) {
return constants.VIDEO_CATEGORIES[value] !== undefined
return VIDEO_CATEGORIES[value] !== undefined
}
function isVideoLicenceValid (value) {
return constants.VIDEO_LICENCES[value] !== undefined
return VIDEO_LICENCES[value] !== undefined
}
function isVideoLanguageValid (value) {
return value === null || constants.VIDEO_LANGUAGES[value] !== undefined
return value === null || VIDEO_LANGUAGES[value] !== undefined
}
function isVideoNSFWValid (value) {
@ -81,7 +62,7 @@ function isVideoNameValid (value) {
}
function isVideoTagsValid (tags) {
return miscValidators.isArray(tags) &&
return isArray(tags) &&
validator.isInt(tags.length, VIDEOS_CONSTRAINTS_FIELDS.TAGS) &&
tags.every(function (tag) {
return validator.isLength(tag, VIDEOS_CONSTRAINTS_FIELDS.TAG)
@ -105,7 +86,7 @@ function isVideoAbuseReasonValid (value) {
}
function isVideoAbuseReporterUsernameValid (value) {
return usersValidators.isUserUsernameValid(value)
return isUserUsernameValid(value)
}
function isVideoViewsValid (value) {
@ -125,7 +106,7 @@ function isVideoEventCountValid (value) {
}
function isVideoRatingTypeValid (value) {
return values(constants.VIDEO_RATE_TYPES).indexOf(value) !== -1
return values(VIDEO_RATE_TYPES).indexOf(value) !== -1
}
function isVideoFile (value, files) {
@ -145,4 +126,28 @@ function isVideoFile (value, files) {
// ---------------------------------------------------------------------------
module.exports = videosValidators
export {
isVideoAuthorValid,
isVideoDateValid,
isVideoCategoryValid,
isVideoLicenceValid,
isVideoLanguageValid,
isVideoNSFWValid,
isVideoDescriptionValid,
isVideoDurationValid,
isVideoInfoHashValid,
isVideoNameValid,
isVideoTagsValid,
isVideoThumbnailValid,
isVideoThumbnailDataValid,
isVideoExtnameValid,
isVideoRemoteIdValid,
isVideoAbuseReasonValid,
isVideoAbuseReporterUsernameValid,
isVideoFile,
isVideoViewsValid,
isVideoLikesValid,
isVideoRatingTypeValid,
isVideoDislikesValid,
isVideoEventCountValid
}

View File

@ -1,17 +1,8 @@
'use strict'
const retry = require('async/retry')
// TODO: import from ES6 when retry typing file will include errorFilter function
import retry = require('async/retry')
const db = require('../initializers/database')
const logger = require('./logger')
const utils = {
commitTransaction,
retryTransactionWrapper,
rollbackTransaction,
startSerializableTransaction,
transactionRetryer
}
import { logger } from './logger'
function commitTransaction (t, callback) {
return t.commit().asCallback(callback)
@ -33,7 +24,7 @@ function rollbackTransaction (err, t, callback) {
function retryTransactionWrapper (functionToRetry, options, finalCallback) {
const args = options.arguments ? options.arguments : []
utils.transactionRetryer(
transactionRetryer(
function (callback) {
return functionToRetry.apply(this, args.concat([ callback ]))
},
@ -69,4 +60,10 @@ function startSerializableTransaction (callback) {
// ---------------------------------------------------------------------------
module.exports = utils
export {
commitTransaction,
retryTransactionWrapper,
rollbackTransaction,
startSerializableTransaction,
transactionRetryer
}

6
server/helpers/index.ts Normal file
View File

@ -0,0 +1,6 @@
export * from './logger'
export * from './custom-validators'
export * from './database-utils'
export * from './peertube-crypto'
export * from './requests'
export * from './utils'

View File

@ -1,23 +1,21 @@
// Thanks http://tostring.it/2014/06/23/advanced-logging-with-nodejs/
'use strict'
import mkdirp = require('mkdirp')
import path = require('path')
import winston = require('winston')
const mkdirp = require('mkdirp')
const path = require('path')
const winston = require('winston')
winston.emitErrs = true
// Do not use barrel (dependencies issues)
import { CONFIG } from '../initializers/constants'
const constants = require('../initializers/constants')
const label = constants.CONFIG.WEBSERVER.HOSTNAME + ':' + constants.CONFIG.WEBSERVER.PORT
const label = CONFIG.WEBSERVER.HOSTNAME + ':' + CONFIG.WEBSERVER.PORT
// Create the directory if it does not exist
mkdirp.sync(constants.CONFIG.STORAGE.LOG_DIR)
mkdirp.sync(CONFIG.STORAGE.LOG_DIR)
const logger = new winston.Logger({
transports: [
new winston.transports.File({
level: 'debug',
filename: path.join(constants.CONFIG.STORAGE.LOG_DIR, 'all-logs.log'),
filename: path.join(CONFIG.STORAGE.LOG_DIR, 'all-logs.log'),
handleExceptions: true,
json: true,
maxsize: 5242880,
@ -38,12 +36,13 @@ const logger = new winston.Logger({
exitOnError: true
})
logger.stream = {
write: function (message, encoding) {
logger.info(message)
}
}
// TODO: useful?
// logger.stream = {
// write: function (message) {
// logger.info(message)
// }
// }
// ---------------------------------------------------------------------------
module.exports = logger
export { logger }

View File

@ -1,26 +1,21 @@
'use strict'
import crypto = require('crypto')
import bcrypt = require('bcrypt')
import fs = require('fs')
import openssl = require('openssl-wrapper')
import { join } from 'path'
const crypto = require('crypto')
const bcrypt = require('bcrypt')
const fs = require('fs')
const openssl = require('openssl-wrapper')
const pathUtils = require('path')
const constants = require('../initializers/constants')
const logger = require('./logger')
const peertubeCrypto = {
checkSignature,
comparePassword,
createCertsIfNotExist,
cryptPassword,
getMyPrivateCert,
getMyPublicCert,
sign
}
import {
SIGNATURE_ALGORITHM,
SIGNATURE_ENCODING,
PRIVATE_CERT_NAME,
CONFIG,
BCRYPT_SALT_SIZE,
PUBLIC_CERT_NAME
} from '../initializers'
import { logger } from './logger'
function checkSignature (publicKey, data, hexSignature) {
const verify = crypto.createVerify(constants.SIGNATURE_ALGORITHM)
const verify = crypto.createVerify(SIGNATURE_ALGORITHM)
let dataString
if (typeof data === 'string') {
@ -36,12 +31,12 @@ function checkSignature (publicKey, data, hexSignature) {
verify.update(dataString, 'utf8')
const isValid = verify.verify(publicKey, hexSignature, constants.SIGNATURE_ENCODING)
const isValid = verify.verify(publicKey, hexSignature, SIGNATURE_ENCODING)
return isValid
}
function sign (data) {
const sign = crypto.createSign(constants.SIGNATURE_ALGORITHM)
const sign = crypto.createSign(SIGNATURE_ALGORITHM)
let dataString
if (typeof data === 'string') {
@ -58,9 +53,9 @@ function sign (data) {
sign.update(dataString, 'utf8')
// TODO: make async
const certPath = pathUtils.join(constants.CONFIG.STORAGE.CERT_DIR, constants.PRIVATE_CERT_NAME)
const certPath = join(CONFIG.STORAGE.CERT_DIR, PRIVATE_CERT_NAME)
const myKey = fs.readFileSync(certPath)
const signature = sign.sign(myKey, constants.SIGNATURE_ENCODING)
const signature = sign.sign(myKey.toString(), SIGNATURE_ENCODING)
return signature
}
@ -88,7 +83,7 @@ function createCertsIfNotExist (callback) {
}
function cryptPassword (password, callback) {
bcrypt.genSalt(constants.BCRYPT_SALT_SIZE, function (err, salt) {
bcrypt.genSalt(BCRYPT_SALT_SIZE, function (err, salt) {
if (err) return callback(err)
bcrypt.hash(password, salt, function (err, hash) {
@ -98,23 +93,31 @@ function cryptPassword (password, callback) {
}
function getMyPrivateCert (callback) {
const certPath = pathUtils.join(constants.CONFIG.STORAGE.CERT_DIR, constants.PRIVATE_CERT_NAME)
const certPath = join(CONFIG.STORAGE.CERT_DIR, PRIVATE_CERT_NAME)
fs.readFile(certPath, 'utf8', callback)
}
function getMyPublicCert (callback) {
const certPath = pathUtils.join(constants.CONFIG.STORAGE.CERT_DIR, constants.PUBLIC_CERT_NAME)
const certPath = join(CONFIG.STORAGE.CERT_DIR, PUBLIC_CERT_NAME)
fs.readFile(certPath, 'utf8', callback)
}
// ---------------------------------------------------------------------------
module.exports = peertubeCrypto
export {
checkSignature,
comparePassword,
createCertsIfNotExist,
cryptPassword,
getMyPrivateCert,
getMyPublicCert,
sign
}
// ---------------------------------------------------------------------------
function certsExist (callback) {
const certPath = pathUtils.join(constants.CONFIG.STORAGE.CERT_DIR, constants.PRIVATE_CERT_NAME)
const certPath = join(CONFIG.STORAGE.CERT_DIR, PRIVATE_CERT_NAME)
fs.access(certPath, function (err) {
// If there is an error the certificates do not exist
const exists = !err
@ -134,7 +137,7 @@ function createCerts (callback) {
logger.info('Generating a RSA key...')
const privateCertPath = pathUtils.join(constants.CONFIG.STORAGE.CERT_DIR, constants.PRIVATE_CERT_NAME)
const privateCertPath = join(CONFIG.STORAGE.CERT_DIR, PRIVATE_CERT_NAME)
const genRsaOptions = {
'out': privateCertPath,
'2048': false
@ -148,7 +151,7 @@ function createCerts (callback) {
logger.info('RSA key generated.')
logger.info('Managing public key...')
const publicCertPath = pathUtils.join(constants.CONFIG.STORAGE.CERT_DIR, 'peertube.pub')
const publicCertPath = join(CONFIG.STORAGE.CERT_DIR, 'peertube.pub')
const rsaOptions = {
'in': privateCertPath,
'pubout': true,

View File

@ -1,21 +1,18 @@
'use strict'
import replay = require('request-replay')
import request = require('request')
const replay = require('request-replay')
const request = require('request')
const constants = require('../initializers/constants')
const peertubeCrypto = require('./peertube-crypto')
const requests = {
makeRetryRequest,
makeSecureRequest
}
import {
RETRY_REQUESTS,
REMOTE_SCHEME,
CONFIG
} from '../initializers'
import { sign } from './peertube-crypto'
function makeRetryRequest (params, callback) {
replay(
request(params, callback),
{
retries: constants.RETRY_REQUESTS,
retries: RETRY_REQUESTS,
factor: 3,
maxTimeout: Infinity,
errorCodes: [ 'EADDRINFO', 'ETIMEDOUT', 'ECONNRESET', 'ESOCKETTIMEDOUT', 'ENOTFOUND', 'ECONNREFUSED' ]
@ -25,18 +22,17 @@ function makeRetryRequest (params, callback) {
function makeSecureRequest (params, callback) {
const requestParams = {
url: constants.REMOTE_SCHEME.HTTP + '://' + params.toPod.host + params.path
url: REMOTE_SCHEME.HTTP + '://' + params.toPod.host + params.path,
json: {}
}
if (params.method !== 'POST') {
return callback(new Error('Cannot make a secure request with a non POST method.'))
}
requestParams.json = {}
// Add signature if it is specified in the params
if (params.sign === true) {
const host = constants.CONFIG.WEBSERVER.HOST
const host = CONFIG.WEBSERVER.HOST
let dataToSign
if (params.data) {
@ -47,22 +43,23 @@ function makeSecureRequest (params, callback) {
dataToSign = host
}
requestParams.json.signature = {
requestParams.json['signature'] = {
host, // Which host we pretend to be
signature: peertubeCrypto.sign(dataToSign)
signature: sign(dataToSign)
}
}
// If there are data informations
if (params.data) {
requestParams.json.data = params.data
requestParams.json['data'] = params.data
}
console.log(requestParams.json.data)
request.post(requestParams, callback)
}
// ---------------------------------------------------------------------------
module.exports = requests
export {
makeRetryRequest,
makeSecureRequest
}

View File

@ -1,24 +1,13 @@
'use strict'
import { pseudoRandomBytes } from 'crypto'
const crypto = require('crypto')
const logger = require('./logger')
const utils = {
badRequest,
createEmptyCallback,
cleanForExit,
generateRandomString,
isTestInstance,
getFormatedObjects
}
import { logger } from './logger'
function badRequest (req, res, next) {
res.type('json').status(400).end()
}
function generateRandomString (size, callback) {
crypto.pseudoRandomBytes(size, function (err, raw) {
pseudoRandomBytes(size, function (err, raw) {
if (err) return callback(err)
callback(null, raw.toString('hex'))
@ -55,4 +44,11 @@ function getFormatedObjects (objects, objectsTotal) {
// ---------------------------------------------------------------------------
module.exports = utils
export {
badRequest,
createEmptyCallback,
cleanForExit,
generateRandomString,
isTestInstance,
getFormatedObjects
}

View File

@ -1,17 +1,7 @@
'use strict'
import config = require('config')
const config = require('config')
const constants = require('./constants')
const db = require('./database')
const checker = {
checkConfig,
checkFFmpeg,
checkMissedConfig,
clientsExist,
usersExist
}
import { CONFIG } from './constants'
// Some checks on configuration files
function checkConfig () {
@ -50,7 +40,7 @@ function checkFFmpeg (callback) {
Ffmpeg.getAvailableCodecs(function (err, codecs) {
if (err) return callback(err)
if (constants.CONFIG.TRANSCODING.ENABLED === false) return callback(null)
if (CONFIG.TRANSCODING.ENABLED === false) return callback(null)
const canEncode = [ 'libx264' ]
canEncode.forEach(function (codec) {
@ -85,4 +75,10 @@ function usersExist (callback) {
// ---------------------------------------------------------------------------
module.exports = checker
export {
checkConfig,
checkFFmpeg,
checkMissedConfig,
clientsExist,
usersExist
}

View File

@ -1,7 +1,5 @@
'use strict'
const config = require('config')
const path = require('path')
import config = require('config')
import { join } from 'path'
// ---------------------------------------------------------------------------
@ -36,38 +34,40 @@ const OAUTH_LIFETIME = {
const CONFIG = {
LISTEN: {
PORT: config.get('listen.port')
PORT: config.get<number>('listen.port')
},
DATABASE: {
DBNAME: 'peertube' + config.get('database.suffix'),
HOSTNAME: config.get('database.hostname'),
PORT: config.get('database.port'),
USERNAME: config.get('database.username'),
PASSWORD: config.get('database.password')
DBNAME: 'peertube' + config.get<string>('database.suffix'),
HOSTNAME: config.get<string>('database.hostname'),
PORT: config.get<number>('database.port'),
USERNAME: config.get<string>('database.username'),
PASSWORD: config.get<string>('database.password')
},
STORAGE: {
CERT_DIR: path.join(__dirname, '..', '..', config.get('storage.certs')),
LOG_DIR: path.join(__dirname, '..', '..', config.get('storage.logs')),
VIDEOS_DIR: path.join(__dirname, '..', '..', config.get('storage.videos')),
THUMBNAILS_DIR: path.join(__dirname, '..', '..', config.get('storage.thumbnails')),
PREVIEWS_DIR: path.join(__dirname, '..', '..', config.get('storage.previews')),
TORRENTS_DIR: path.join(__dirname, '..', '..', config.get('storage.torrents'))
CERT_DIR: join(__dirname, '..', '..', config.get<string>('storage.certs')),
LOG_DIR: join(__dirname, '..', '..', config.get<string>('storage.logs')),
VIDEOS_DIR: join(__dirname, '..', '..', config.get<string>('storage.videos')),
THUMBNAILS_DIR: join(__dirname, '..', '..', config.get<string>('storage.thumbnails')),
PREVIEWS_DIR: join(__dirname, '..', '..', config.get<string>('storage.previews')),
TORRENTS_DIR: join(__dirname, '..', '..', config.get<string>('storage.torrents'))
},
WEBSERVER: {
SCHEME: config.get('webserver.https') === true ? 'https' : 'http',
WS: config.get('webserver.https') === true ? 'wss' : 'ws',
HOSTNAME: config.get('webserver.hostname'),
PORT: config.get('webserver.port')
SCHEME: config.get<boolean>('webserver.https') === true ? 'https' : 'http',
WS: config.get<boolean>('webserver.https') === true ? 'wss' : 'ws',
HOSTNAME: config.get<string>('webserver.hostname'),
PORT: config.get<number>('webserver.port'),
URL: '',
HOST: ''
},
ADMIN: {
EMAIL: config.get('admin.email')
EMAIL: config.get<string>('admin.email')
},
SIGNUP: {
ENABLED: config.get('signup.enabled')
ENABLED: config.get<boolean>('signup.enabled')
},
TRANSCODING: {
ENABLED: config.get('transcoding.enabled'),
THREADS: config.get('transcoding.threads')
ENABLED: config.get<boolean>('transcoding.enabled'),
THREADS: config.get<number>('transcoding.threads')
}
}
CONFIG.WEBSERVER.URL = CONFIG.WEBSERVER.SCHEME + '://' + CONFIG.WEBSERVER.HOSTNAME + ':' + CONFIG.WEBSERVER.PORT
@ -283,12 +283,12 @@ if (isTestInstance() === true) {
JOBS_FETCHING_INTERVAL = 10000
REMOTE_SCHEME.HTTP = 'http'
REMOTE_SCHEME.WS = 'ws'
STATIC_MAX_AGE = 0
STATIC_MAX_AGE = '0'
}
// ---------------------------------------------------------------------------
module.exports = {
export {
API_VERSION,
BCRYPT_SALT_SIZE,
CONFIG,

View File

@ -1,24 +1,23 @@
'use strict'
import fs = require('fs')
import { join } from 'path'
import Sequelize = require('sequelize')
const fs = require('fs')
const path = require('path')
const Sequelize = require('sequelize')
import { CONFIG } from './constants'
// Do not use barrel, we need to load database first
import { logger } from '../helpers/logger'
import { isTestInstance } from '../helpers/utils'
const constants = require('../initializers/constants')
const logger = require('../helpers/logger')
const utils = require('../helpers/utils')
const dbname = CONFIG.DATABASE.DBNAME
const username = CONFIG.DATABASE.USERNAME
const password = CONFIG.DATABASE.PASSWORD
const database = {}
const dbname = constants.CONFIG.DATABASE.DBNAME
const username = constants.CONFIG.DATABASE.USERNAME
const password = constants.CONFIG.DATABASE.PASSWORD
const database: any = {}
const sequelize = new Sequelize(dbname, username, password, {
dialect: 'postgres',
host: constants.CONFIG.DATABASE.HOSTNAME,
port: constants.CONFIG.DATABASE.PORT,
benchmark: utils.isTestInstance(),
host: CONFIG.DATABASE.HOSTNAME,
port: CONFIG.DATABASE.PORT,
benchmark: isTestInstance(),
logging: function (message, benchmark) {
let newMessage = message
@ -31,24 +30,16 @@ const sequelize = new Sequelize(dbname, username, password, {
})
database.sequelize = sequelize
database.Sequelize = Sequelize
database.init = init
// ---------------------------------------------------------------------------
module.exports = database
// ---------------------------------------------------------------------------
function init (silent, callback) {
database.init = function (silent, callback) {
if (!callback) {
callback = silent
silent = false
}
if (!callback) callback = function () {}
if (!callback) callback = function () { /* empty */ }
const modelDirectory = path.join(__dirname, '..', 'models')
const modelDirectory = join(__dirname, '..', 'models')
fs.readdir(modelDirectory, function (err, files) {
if (err) throw err
@ -59,9 +50,9 @@ function init (silent, callback) {
return true
})
.forEach(function (file) {
const model = sequelize.import(path.join(modelDirectory, file))
const model = sequelize.import(join(modelDirectory, file))
database[model.name] = model
database[model['name']] = model
})
Object.keys(database).forEach(function (modelName) {
@ -75,3 +66,7 @@ function init (silent, callback) {
return callback(null)
})
}
// ---------------------------------------------------------------------------
module.exports = database

View File

@ -0,0 +1,6 @@
// Constants first, databse in second!
export * from './constants'
export * from './database'
export * from './checker'
export * from './installer'
export * from './migrator'

View File

@ -1,21 +1,13 @@
'use strict'
import { join } from 'path'
import config = require('config')
import { each, series } from 'async'
import mkdirp = require('mkdirp')
import passwordGenerator = require('password-generator')
const config = require('config')
const each = require('async/each')
const mkdirp = require('mkdirp')
const passwordGenerator = require('password-generator')
const path = require('path')
const series = require('async/series')
const checker = require('./checker')
const constants = require('./constants')
const db = require('./database')
const logger = require('../helpers/logger')
const peertubeCrypto = require('../helpers/peertube-crypto')
const installer = {
installApplication
}
import { USER_ROLES, CONFIG, LAST_MIGRATION_VERSION } from './constants'
import { clientsExist, usersExist } from './checker'
import { logger, createCertsIfNotExist } from '../helpers'
function installApplication (callback) {
series([
@ -29,7 +21,7 @@ function installApplication (callback) {
},
function createCertificates (callbackAsync) {
peertubeCrypto.createCertsIfNotExist(callbackAsync)
createCertsIfNotExist(callbackAsync)
},
function createOAuthClient (callbackAsync) {
@ -44,7 +36,9 @@ function installApplication (callback) {
// ---------------------------------------------------------------------------
module.exports = installer
export {
installApplication
}
// ---------------------------------------------------------------------------
@ -53,12 +47,12 @@ function createDirectoriesIfNotExist (callback) {
each(Object.keys(storages), function (key, callbackEach) {
const dir = storages[key]
mkdirp(path.join(__dirname, '..', '..', dir), callbackEach)
mkdirp(join(__dirname, '..', '..', dir), callbackEach)
}, callback)
}
function createOAuthClientIfNotExist (callback) {
checker.clientsExist(function (err, exist) {
clientsExist(function (err, exist) {
if (err) return callback(err)
// Nothing to do, clients already exist
@ -86,7 +80,7 @@ function createOAuthClientIfNotExist (callback) {
}
function createOAuthAdminIfNotExist (callback) {
checker.usersExist(function (err, exist) {
usersExist(function (err, exist) {
if (err) return callback(err)
// Nothing to do, users already exist
@ -95,9 +89,9 @@ function createOAuthAdminIfNotExist (callback) {
logger.info('Creating the administrator.')
const username = 'root'
const role = constants.USER_ROLES.ADMIN
const email = constants.CONFIG.ADMIN.EMAIL
const createOptions = {}
const role = USER_ROLES.ADMIN
const email = CONFIG.ADMIN.EMAIL
const createOptions: { validate?: boolean } = {}
let password = ''
// Do not generate a random password for tests
@ -128,7 +122,7 @@ function createOAuthAdminIfNotExist (callback) {
logger.info('User password: ' + password)
logger.info('Creating Application table.')
db.Application.create({ migrationVersion: constants.LAST_MIGRATION_VERSION }).asCallback(callback)
db.Application.create({ migrationVersion: LAST_MIGRATION_VERSION }).asCallback(callback)
})
})
}

View File

@ -1,9 +1,7 @@
'use strict'
const waterfall = require('async/waterfall')
import { waterfall } from 'async'
// utils = { transaction, queryInterface, sequelize, Sequelize }
exports.up = function (utils, finalCallback) {
function up (utils, finalCallback) {
const q = utils.queryInterface
const Sequelize = utils.Sequelize
@ -36,6 +34,11 @@ exports.up = function (utils, finalCallback) {
], finalCallback)
}
exports.down = function (options, callback) {
function down (options, callback) {
throw new Error('Not implemented.')
}
export {
up,
down
}

View File

@ -1,9 +1,7 @@
'use strict'
const waterfall = require('async/waterfall')
import { waterfall } from 'async'
// utils = { transaction, queryInterface, sequelize, Sequelize }
exports.up = function (utils, finalCallback) {
function up (utils, finalCallback) {
const q = utils.queryInterface
const Sequelize = utils.Sequelize
@ -36,6 +34,11 @@ exports.up = function (utils, finalCallback) {
], finalCallback)
}
exports.down = function (options, callback) {
function down (options, callback) {
throw new Error('Not implemented.')
}
export {
up,
down
}

View File

@ -1,7 +1,5 @@
'use strict'
// utils = { transaction, queryInterface, sequelize, Sequelize }
exports.up = function (utils, finalCallback) {
function up (utils, finalCallback) {
const q = utils.queryInterface
const Sequelize = utils.Sequelize
@ -14,6 +12,11 @@ exports.up = function (utils, finalCallback) {
q.addColumn('Videos', 'views', data, { transaction: utils.transaction }).asCallback(finalCallback)
}
exports.down = function (options, callback) {
function down (options, callback) {
throw new Error('Not implemented.')
}
export {
up,
down
}

View File

@ -1,7 +1,5 @@
'use strict'
// utils = { transaction, queryInterface, sequelize, Sequelize }
exports.up = function (utils, finalCallback) {
function up (utils, finalCallback) {
const q = utils.queryInterface
const Sequelize = utils.Sequelize
@ -14,6 +12,11 @@ exports.up = function (utils, finalCallback) {
q.addColumn('Videos', 'likes', data, { transaction: utils.transaction }).asCallback(finalCallback)
}
exports.down = function (options, callback) {
function down (options, callback) {
throw new Error('Not implemented.')
}
export {
up,
down
}

View File

@ -1,7 +1,5 @@
'use strict'
// utils = { transaction, queryInterface, sequelize, Sequelize }
exports.up = function (utils, finalCallback) {
function up (utils, finalCallback) {
const q = utils.queryInterface
const Sequelize = utils.Sequelize
@ -14,6 +12,11 @@ exports.up = function (utils, finalCallback) {
q.addColumn('Videos', 'dislikes', data, { transaction: utils.transaction }).asCallback(finalCallback)
}
exports.down = function (options, callback) {
function down (options, callback) {
throw new Error('Not implemented.')
}
export {
up,
down
}

View File

@ -1,9 +1,7 @@
'use strict'
const waterfall = require('async/waterfall')
import { waterfall } from 'async'
// utils = { transaction, queryInterface, sequelize, Sequelize }
exports.up = function (utils, finalCallback) {
function up (utils, finalCallback) {
const q = utils.queryInterface
const Sequelize = utils.Sequelize
@ -29,6 +27,11 @@ exports.up = function (utils, finalCallback) {
], finalCallback)
}
exports.down = function (options, callback) {
function down (options, callback) {
throw new Error('Not implemented.')
}
export {
up,
down
}

View File

@ -1,9 +1,7 @@
'use strict'
const waterfall = require('async/waterfall')
import { waterfall } from 'async'
// utils = { transaction, queryInterface, sequelize, Sequelize }
exports.up = function (utils, finalCallback) {
function up (utils, finalCallback) {
const q = utils.queryInterface
const Sequelize = utils.Sequelize
@ -29,6 +27,11 @@ exports.up = function (utils, finalCallback) {
], finalCallback)
}
exports.down = function (options, callback) {
function down (options, callback) {
throw new Error('Not implemented.')
}
export {
up,
down
}

View File

@ -1,9 +1,7 @@
'use strict'
const waterfall = require('async/waterfall')
import { waterfall } from 'async'
// utils = { transaction, queryInterface, sequelize, Sequelize }
exports.up = function (utils, finalCallback) {
function up (utils, finalCallback) {
const q = utils.queryInterface
const Sequelize = utils.Sequelize
@ -29,6 +27,11 @@ exports.up = function (utils, finalCallback) {
], finalCallback)
}
exports.down = function (options, callback) {
function down (options, callback) {
throw new Error('Not implemented.')
}
export {
up,
down
}

View File

@ -1,7 +1,5 @@
'use strict'
// utils = { transaction, queryInterface, sequelize, Sequelize }
exports.up = function (utils, finalCallback) {
function up (utils, finalCallback) {
const q = utils.queryInterface
const Sequelize = utils.Sequelize
@ -14,6 +12,11 @@ exports.up = function (utils, finalCallback) {
q.addColumn('Users', 'displayNSFW', data, { transaction: utils.transaction }).asCallback(finalCallback)
}
exports.down = function (options, callback) {
function down (options, callback) {
throw new Error('Not implemented.')
}
export {
up,
down
}

View File

@ -1,7 +1,5 @@
'use strict'
// utils = { transaction, queryInterface, sequelize, Sequelize }
exports.up = function (utils, finalCallback) {
function up (utils, finalCallback) {
const q = utils.queryInterface
const Sequelize = utils.Sequelize
@ -14,6 +12,11 @@ exports.up = function (utils, finalCallback) {
q.addColumn('Videos', 'language', data, { transaction: utils.transaction }).asCallback(finalCallback)
}
exports.down = function (options, callback) {
function down (options, callback) {
throw new Error('Not implemented.')
}
export {
up,
down
}

View File

@ -1,17 +1,10 @@
'use strict'
import { waterfall, eachSeries } from 'async'
import fs = require('fs')
import path = require('path')
const waterfall = require('async/waterfall')
const eachSeries = require('async/eachSeries')
const fs = require('fs')
const path = require('path')
const constants = require('./constants')
const db = require('./database')
const logger = require('../helpers/logger')
const migrator = {
migrate: migrate
}
import { LAST_MIGRATION_VERSION } from './constants'
import { logger } from '../helpers'
function migrate (finalCallback) {
waterfall([
@ -46,7 +39,7 @@ function migrate (finalCallback) {
function abortMigrationIfNotNeeded (actualVersion, callback) {
// No need migrations
if (actualVersion >= constants.LAST_MIGRATION_VERSION) return finalCallback(null)
if (actualVersion >= LAST_MIGRATION_VERSION) return finalCallback(null)
return callback(null, actualVersion)
},
@ -66,7 +59,7 @@ function migrate (finalCallback) {
}, function (err) {
if (err) return callback(err)
logger.info('Migrations finished. New migration version schema: %s', constants.LAST_MIGRATION_VERSION)
logger.info('Migrations finished. New migration version schema: %s', LAST_MIGRATION_VERSION)
return callback(null)
})
}
@ -75,7 +68,9 @@ function migrate (finalCallback) {
// ---------------------------------------------------------------------------
module.exports = migrator
export {
migrate
}
// ---------------------------------------------------------------------------

View File

@ -1,48 +1,35 @@
'use strict'
import { each, eachLimit, eachSeries, series, waterfall } from 'async'
import request = require('request')
const each = require('async/each')
const eachLimit = require('async/eachLimit')
const eachSeries = require('async/eachSeries')
const series = require('async/series')
const request = require('request')
const waterfall = require('async/waterfall')
const constants = require('../initializers/constants')
const db = require('../initializers/database')
const logger = require('../helpers/logger')
const peertubeCrypto = require('../helpers/peertube-crypto')
const requests = require('../helpers/requests')
const utils = require('../helpers/utils')
const RequestScheduler = require('./request/request-scheduler')
const RequestVideoQaduScheduler = require('./request/request-video-qadu-scheduler')
const RequestVideoEventScheduler = require('./request/request-video-event-scheduler')
import {
API_VERSION,
CONFIG,
REQUESTS_IN_PARALLEL,
REQUEST_ENDPOINTS,
REQUEST_ENDPOINT_ACTIONS,
REMOTE_SCHEME
} from '../initializers'
import {
logger,
getMyPublicCert,
makeSecureRequest,
makeRetryRequest,
createEmptyCallback
} from '../helpers'
import {
RequestScheduler,
RequestVideoQaduScheduler,
RequestVideoEventScheduler
} from './request'
const ENDPOINT_ACTIONS = constants.REQUEST_ENDPOINT_ACTIONS[constants.REQUEST_ENDPOINTS.VIDEOS]
const ENDPOINT_ACTIONS = REQUEST_ENDPOINT_ACTIONS[REQUEST_ENDPOINTS.VIDEOS]
const requestScheduler = new RequestScheduler()
const requestVideoQaduScheduler = new RequestVideoQaduScheduler()
const requestVideoEventScheduler = new RequestVideoEventScheduler()
const friends = {
activate,
addVideoToFriends,
updateVideoToFriends,
reportAbuseVideoToFriend,
quickAndDirtyUpdateVideoToFriends,
quickAndDirtyUpdatesVideoToFriends,
addEventToRemoteVideo,
addEventsToRemoteVideo,
hasFriends,
makeFriends,
quitFriends,
removeVideoToFriends,
sendOwnedVideosToPod,
getRequestScheduler,
getRequestVideoQaduScheduler,
getRequestVideoEventScheduler
}
function activate () {
function activateSchedulers () {
requestScheduler.activate()
requestVideoQaduScheduler.activate()
requestVideoEventScheduler.activate()
@ -51,7 +38,7 @@ function activate () {
function addVideoToFriends (videoData, transaction, callback) {
const options = {
type: ENDPOINT_ACTIONS.ADD,
endpoint: constants.REQUEST_ENDPOINTS.VIDEOS,
endpoint: REQUEST_ENDPOINTS.VIDEOS,
data: videoData,
transaction
}
@ -61,7 +48,7 @@ function addVideoToFriends (videoData, transaction, callback) {
function updateVideoToFriends (videoData, transaction, callback) {
const options = {
type: ENDPOINT_ACTIONS.UPDATE,
endpoint: constants.REQUEST_ENDPOINTS.VIDEOS,
endpoint: REQUEST_ENDPOINTS.VIDEOS,
data: videoData,
transaction
}
@ -71,7 +58,7 @@ function updateVideoToFriends (videoData, transaction, callback) {
function removeVideoToFriends (videoParams) {
const options = {
type: ENDPOINT_ACTIONS.REMOVE,
endpoint: constants.REQUEST_ENDPOINTS.VIDEOS,
endpoint: REQUEST_ENDPOINTS.VIDEOS,
data: videoParams
}
createRequest(options)
@ -80,14 +67,14 @@ function removeVideoToFriends (videoParams) {
function reportAbuseVideoToFriend (reportData, video) {
const options = {
type: ENDPOINT_ACTIONS.REPORT_ABUSE,
endpoint: constants.REQUEST_ENDPOINTS.VIDEOS,
endpoint: REQUEST_ENDPOINTS.VIDEOS,
data: reportData,
toIds: [ video.Author.podId ]
}
createRequest(options)
}
function quickAndDirtyUpdateVideoToFriends (qaduParams, transaction, callback) {
function quickAndDirtyUpdateVideoToFriends (qaduParams, transaction?, callback?) {
const options = {
videoId: qaduParams.videoId,
type: qaduParams.type,
@ -110,7 +97,7 @@ function quickAndDirtyUpdatesVideoToFriends (qadusParams, transaction, finalCall
series(tasks, finalCallback)
}
function addEventToRemoteVideo (eventParams, transaction, callback) {
function addEventToRemoteVideo (eventParams, transaction?, callback?) {
const options = {
videoId: eventParams.videoId,
type: eventParams.type,
@ -146,7 +133,7 @@ function makeFriends (hosts, callback) {
const podsScore = {}
logger.info('Make friends!')
peertubeCrypto.getMyPublicCert(function (err, cert) {
getMyPublicCert(function (err, cert) {
if (err) {
logger.error('Cannot read public cert.')
return callback(err)
@ -186,16 +173,17 @@ function quitFriends (callback) {
function announceIQuitMyFriends (pods, callbackAsync) {
const requestParams = {
method: 'POST',
path: '/api/' + constants.API_VERSION + '/remote/pods/remove',
sign: true
path: '/api/' + API_VERSION + '/remote/pods/remove',
sign: true,
toPod: null
}
// Announce we quit them
// We don't care if the request fails
// The other pod will exclude us automatically after a while
eachLimit(pods, constants.REQUESTS_IN_PARALLEL, function (pod, callbackEach) {
eachLimit(pods, REQUESTS_IN_PARALLEL, function (pod, callbackEach) {
requestParams.toPod = pod
requests.makeSecureRequest(requestParams, callbackEach)
makeSecureRequest(requestParams, callbackEach)
}, function (err) {
if (err) {
logger.error('Some errors while quitting friends.', { err: err })
@ -207,7 +195,7 @@ function quitFriends (callback) {
},
function removePodsFromDB (pods, callbackAsync) {
each(pods, function (pod, callbackEach) {
each(pods, function (pod: any, callbackEach) {
pod.destroy().asCallback(callbackEach)
}, callbackAsync)
}
@ -239,7 +227,7 @@ function sendOwnedVideosToPod (podId) {
const options = {
type: 'add',
endpoint: constants.REQUEST_ENDPOINTS.VIDEOS,
endpoint: REQUEST_ENDPOINTS.VIDEOS,
data: remoteVideo,
toIds: [ podId ]
}
@ -263,7 +251,24 @@ function getRequestVideoEventScheduler () {
// ---------------------------------------------------------------------------
module.exports = friends
export {
activateSchedulers,
addVideoToFriends,
updateVideoToFriends,
reportAbuseVideoToFriend,
quickAndDirtyUpdateVideoToFriends,
quickAndDirtyUpdatesVideoToFriends,
addEventToRemoteVideo,
addEventsToRemoteVideo,
hasFriends,
makeFriends,
quitFriends,
removeVideoToFriends,
sendOwnedVideosToPod,
getRequestScheduler,
getRequestVideoQaduScheduler,
getRequestVideoEventScheduler
}
// ---------------------------------------------------------------------------
@ -304,9 +309,9 @@ function computeWinningPods (hosts, podsScore) {
}
function getForeignPodsList (host, callback) {
const path = '/api/' + constants.API_VERSION + '/pods'
const path = '/api/' + API_VERSION + '/pods'
request.get(constants.REMOTE_SCHEME.HTTP + '://' + host + path, function (err, response, body) {
request.get(REMOTE_SCHEME.HTTP + '://' + host + path, function (err, response, body) {
if (err) return callback(err)
try {
@ -324,18 +329,18 @@ function makeRequestsToWinningPods (cert, podsList, callback) {
// Flush pool requests
requestScheduler.forceSend()
eachLimit(podsList, constants.REQUESTS_IN_PARALLEL, function (pod, callbackEach) {
eachLimit(podsList, REQUESTS_IN_PARALLEL, function (pod: any, callbackEach) {
const params = {
url: constants.REMOTE_SCHEME.HTTP + '://' + pod.host + '/api/' + constants.API_VERSION + '/pods/',
url: REMOTE_SCHEME.HTTP + '://' + pod.host + '/api/' + API_VERSION + '/pods/',
method: 'POST',
json: {
host: constants.CONFIG.WEBSERVER.HOST,
email: constants.CONFIG.ADMIN.EMAIL,
host: CONFIG.WEBSERVER.HOST,
email: CONFIG.ADMIN.EMAIL,
publicKey: cert
}
}
requests.makeRetryRequest(params, function (err, res, body) {
makeRetryRequest(params, function (err, res, body) {
if (err) {
logger.error('Error with adding %s pod.', pod.host, { error: err })
// Don't break the process
@ -372,8 +377,8 @@ function makeRequestsToWinningPods (cert, podsList, callback) {
// Wrapper that populate "toIds" argument with all our friends if it is not specified
// { type, endpoint, data, toIds, transaction }
function createRequest (options, callback) {
if (!callback) callback = function () {}
function createRequest (options, callback?) {
if (!callback) callback = function () { /* empty */ }
if (options.toIds) return requestScheduler.createRequest(options, callback)
// If the "toIds" pods is not specified, we send the request to all our friends
@ -389,17 +394,17 @@ function createRequest (options, callback) {
}
function createVideoQaduRequest (options, callback) {
if (!callback) callback = utils.createEmptyCallback()
if (!callback) callback = createEmptyCallback()
requestVideoQaduScheduler.createRequest(options, callback)
}
function createVideoEventRequest (options, callback) {
if (!callback) callback = utils.createEmptyCallback()
if (!callback) callback = createEmptyCallback()
requestVideoEventScheduler.createRequest(options, callback)
}
function isMe (host) {
return host === constants.CONFIG.WEBSERVER.HOST
return host === CONFIG.WEBSERVER.HOST
}

4
server/lib/index.ts Normal file
View File

@ -0,0 +1,4 @@
export * from './jobs'
export * from './request'
export * from './friends'
export * from './oauth-model'

View File

@ -1,7 +0,0 @@
'use strict'
const videoTranscoder = require('./video-transcoder')
module.exports = {
videoTranscoder
}

View File

@ -0,0 +1,9 @@
import * as videoTranscoder from './video-transcoder'
const jobHandlers = {
videoTranscoder
}
export {
jobHandlers
}

View File

@ -1,16 +1,6 @@
'use strict'
const db = require('../../../initializers/database')
const logger = require('../../../helpers/logger')
const friends = require('../../../lib/friends')
const VideoTranscoderHandler = {
process,
onError,
onSuccess
}
// ---------------------------------------------------------------------------
import { logger } from '../../../helpers'
import { addVideoToFriends } from '../../../lib'
function process (data, callback) {
db.Video.loadAndPopulateAuthorAndPodAndTags(data.id, function (err, video) {
@ -34,10 +24,14 @@ function onSuccess (data, jobId, video, callback) {
if (err) return callback(err)
// Now we'll add the video's meta data to our friends
friends.addVideoToFriends(remoteVideo, null, callback)
addVideoToFriends(remoteVideo, null, callback)
})
}
// ---------------------------------------------------------------------------
module.exports = VideoTranscoderHandler
export {
process,
onError,
onSuccess
}

1
server/lib/jobs/index.ts Normal file
View File

@ -0,0 +1 @@
export * from './job-scheduler'

View File

@ -1,129 +0,0 @@
'use strict'
const forever = require('async/forever')
const queue = require('async/queue')
const constants = require('../../initializers/constants')
const db = require('../../initializers/database')
const logger = require('../../helpers/logger')
const jobHandlers = require('./handlers')
const jobScheduler = {
activate,
createJob
}
function activate () {
const limit = constants.JOBS_FETCH_LIMIT_PER_CYCLE
logger.info('Jobs scheduler activated.')
const jobsQueue = queue(processJob)
// Finish processing jobs from a previous start
const state = constants.JOB_STATES.PROCESSING
db.Job.listWithLimit(limit, state, function (err, jobs) {
enqueueJobs(err, jobsQueue, jobs)
forever(
function (next) {
if (jobsQueue.length() !== 0) {
// Finish processing the queue first
return setTimeout(next, constants.JOBS_FETCHING_INTERVAL)
}
const state = constants.JOB_STATES.PENDING
db.Job.listWithLimit(limit, state, function (err, jobs) {
if (err) {
logger.error('Cannot list pending jobs.', { error: err })
} else {
jobs.forEach(function (job) {
jobsQueue.push(job)
})
}
// Optimization: we could use "drain" from queue object
return setTimeout(next, constants.JOBS_FETCHING_INTERVAL)
})
}
)
})
}
// ---------------------------------------------------------------------------
module.exports = jobScheduler
// ---------------------------------------------------------------------------
function enqueueJobs (err, jobsQueue, jobs) {
if (err) {
logger.error('Cannot list pending jobs.', { error: err })
} else {
jobs.forEach(function (job) {
jobsQueue.push(job)
})
}
}
function createJob (transaction, handlerName, handlerInputData, callback) {
const createQuery = {
state: constants.JOB_STATES.PENDING,
handlerName,
handlerInputData
}
const options = { transaction }
db.Job.create(createQuery, options).asCallback(callback)
}
function processJob (job, callback) {
const jobHandler = jobHandlers[job.handlerName]
logger.info('Processing job %d with handler %s.', job.id, job.handlerName)
job.state = constants.JOB_STATES.PROCESSING
job.save().asCallback(function (err) {
if (err) return cannotSaveJobError(err, callback)
if (jobHandler === undefined) {
logger.error('Unknown job handler for job %s.', jobHandler.handlerName)
return callback()
}
return jobHandler.process(job.handlerInputData, function (err, result) {
if (err) {
logger.error('Error in job handler %s.', job.handlerName, { error: err })
return onJobError(jobHandler, job, result, callback)
}
return onJobSuccess(jobHandler, job, result, callback)
})
})
}
function onJobError (jobHandler, job, jobResult, callback) {
job.state = constants.JOB_STATES.ERROR
job.save().asCallback(function (err) {
if (err) return cannotSaveJobError(err, callback)
return jobHandler.onError(err, job.id, jobResult, callback)
})
}
function onJobSuccess (jobHandler, job, jobResult, callback) {
job.state = constants.JOB_STATES.SUCCESS
job.save().asCallback(function (err) {
if (err) return cannotSaveJobError(err, callback)
return jobHandler.onSuccess(err, job.id, jobResult, callback)
})
}
function cannotSaveJobError (err, callback) {
logger.error('Cannot save new job state.', { error: err })
return callback(err)
}

View File

@ -0,0 +1,137 @@
import { forever, queue } from 'async'
const db = require('../../initializers/database')
import {
JOBS_FETCHING_INTERVAL,
JOBS_FETCH_LIMIT_PER_CYCLE,
JOB_STATES
} from '../../initializers'
import { logger } from '../../helpers'
import { jobHandlers } from './handlers'
class JobScheduler {
private static instance: JobScheduler
private constructor () { }
static get Instance () {
return this.instance || (this.instance = new this())
}
activate () {
const limit = JOBS_FETCH_LIMIT_PER_CYCLE
logger.info('Jobs scheduler activated.')
const jobsQueue = queue(this.processJob)
// Finish processing jobs from a previous start
const state = JOB_STATES.PROCESSING
db.Job.listWithLimit(limit, state, (err, jobs) => {
this.enqueueJobs(err, jobsQueue, jobs)
forever(
next => {
if (jobsQueue.length() !== 0) {
// Finish processing the queue first
return setTimeout(next, JOBS_FETCHING_INTERVAL)
}
const state = JOB_STATES.PENDING
db.Job.listWithLimit(limit, state, (err, jobs) => {
if (err) {
logger.error('Cannot list pending jobs.', { error: err })
} else {
jobs.forEach(job => {
jobsQueue.push(job)
})
}
// Optimization: we could use "drain" from queue object
return setTimeout(next, JOBS_FETCHING_INTERVAL)
})
},
err => { logger.error('Error in job scheduler queue.', { error: err }) }
)
})
}
createJob (transaction, handlerName, handlerInputData, callback) {
const createQuery = {
state: JOB_STATES.PENDING,
handlerName,
handlerInputData
}
const options = { transaction }
db.Job.create(createQuery, options).asCallback(callback)
}
private enqueueJobs (err, jobsQueue, jobs) {
if (err) {
logger.error('Cannot list pending jobs.', { error: err })
} else {
jobs.forEach(job => {
jobsQueue.push(job)
})
}
}
private processJob (job, callback) {
const jobHandler = jobHandlers[job.handlerName]
logger.info('Processing job %d with handler %s.', job.id, job.handlerName)
job.state = JOB_STATES.PROCESSING
job.save().asCallback(err => {
if (err) return this.cannotSaveJobError(err, callback)
if (jobHandler === undefined) {
logger.error('Unknown job handler for job %s.', jobHandler.handlerName)
return callback()
}
return jobHandler.process(job.handlerInputData, (err, result) => {
if (err) {
logger.error('Error in job handler %s.', job.handlerName, { error: err })
return this.onJobError(jobHandler, job, result, callback)
}
return this.onJobSuccess(jobHandler, job, result, callback)
})
})
}
private onJobError (jobHandler, job, jobResult, callback) {
job.state = JOB_STATES.ERROR
job.save().asCallback(err => {
if (err) return this.cannotSaveJobError(err, callback)
return jobHandler.onError(err, job.id, jobResult, callback)
})
}
private onJobSuccess (jobHandler, job, jobResult, callback) {
job.state = JOB_STATES.SUCCESS
job.save().asCallback(err => {
if (err) return this.cannotSaveJobError(err, callback)
return jobHandler.onSuccess(err, job.id, jobResult, callback)
})
}
private cannotSaveJobError (err, callback) {
logger.error('Cannot save new job state.', { error: err })
return callback(err)
}
}
// ---------------------------------------------------------------------------
export {
JobScheduler
}

View File

@ -1,15 +1,5 @@
const db = require('../initializers/database')
const logger = require('../helpers/logger')
// See https://github.com/oauthjs/node-oauth2-server/wiki/Model-specification for the model specifications
const OAuthModel = {
getAccessToken,
getClient,
getRefreshToken,
getUser,
revokeToken,
saveToken
}
import { logger } from '../helpers'
// ---------------------------------------------------------------------------
@ -94,4 +84,12 @@ function saveToken (token, client, user) {
// ---------------------------------------------------------------------------
module.exports = OAuthModel
// See https://github.com/oauthjs/node-oauth2-server/wiki/Model-specification for the model specifications
export {
getAccessToken,
getClient,
getRefreshToken,
getUser,
revokeToken,
saveToken
}

View File

@ -1,19 +1,31 @@
'use strict'
import { eachLimit } from 'async/eachLimit'
const eachLimit = require('async/eachLimit')
const constants = require('../../initializers/constants')
const db = require('../../initializers/database')
const logger = require('../../helpers/logger')
const requests = require('../../helpers/requests')
import { logger, makeSecureRequest } from '../../helpers'
import {
API_VERSION,
REQUESTS_IN_PARALLEL,
REQUESTS_INTERVAL
} from '../../initializers'
module.exports = class BaseRequestScheduler {
constructor (options) {
abstract class BaseRequestScheduler {
protected lastRequestTimestamp: number
protected timer: NodeJS.Timer
protected requestInterval: number
protected limitPods: number
protected limitPerPod: number
protected description: string
constructor () {
this.lastRequestTimestamp = 0
this.timer = null
this.requestInterval = constants.REQUESTS_INTERVAL
this.requestInterval = REQUESTS_INTERVAL
}
abstract getRequestModel ()
abstract getRequestToPodModel ()
abstract buildRequestObjects (requests: any)
activate () {
logger.info('Requests scheduler activated.')
this.lastRequestTimestamp = Date.now()
@ -38,30 +50,34 @@ module.exports = class BaseRequestScheduler {
remainingMilliSeconds () {
if (this.timer === null) return -1
return constants.REQUESTS_INTERVAL - (Date.now() - this.lastRequestTimestamp)
return REQUESTS_INTERVAL - (Date.now() - this.lastRequestTimestamp)
}
remainingRequestsCount (callback) {
return this.getRequestModel().countTotalRequests(callback)
}
flush (callback) {
this.getRequestModel().removeAll(callback)
}
// ---------------------------------------------------------------------------
// Make a requests to friends of a certain type
makeRequest (toPod, requestEndpoint, requestsToMake, callback) {
if (!callback) callback = function () {}
protected makeRequest (toPod, requestEndpoint, requestsToMake, callback) {
if (!callback) callback = function () { /* empty */ }
const params = {
toPod: toPod,
sign: true, // Prove our identity
method: 'POST',
path: '/api/' + constants.API_VERSION + '/remote/' + requestEndpoint,
path: '/api/' + API_VERSION + '/remote/' + requestEndpoint,
data: requestsToMake // Requests we need to make
}
// Make multiple retry requests to all of pods
// The function fire some useful callbacks
requests.makeSecureRequest(params, (err, res) => {
makeSecureRequest(params, (err, res) => {
if (err || (res.statusCode !== 200 && res.statusCode !== 201 && res.statusCode !== 204)) {
err = err ? err.message : 'Status code not 20x : ' + res.statusCode
logger.error('Error sending secure request to %s pod.', toPod.host, { error: err })
@ -74,7 +90,7 @@ module.exports = class BaseRequestScheduler {
}
// Make all the requests of the scheduler
makeRequests () {
protected makeRequests () {
this.getRequestModel().listWithLimitAndRandom(this.limitPods, this.limitPerPod, (err, requests) => {
if (err) {
logger.error('Cannot get the list of "%s".', this.description, { err: err })
@ -95,7 +111,7 @@ module.exports = class BaseRequestScheduler {
const goodPods = []
const badPods = []
eachLimit(Object.keys(requestsToMakeGrouped), constants.REQUESTS_IN_PARALLEL, (hashKey, callbackEach) => {
eachLimit(Object.keys(requestsToMakeGrouped), REQUESTS_IN_PARALLEL, (hashKey, callbackEach) => {
const requestToMake = requestsToMakeGrouped[hashKey]
const toPod = requestToMake.toPod
@ -122,15 +138,17 @@ module.exports = class BaseRequestScheduler {
})
}
flush (callback) {
this.getRequestModel().removeAll(callback)
}
afterRequestHook () {
protected afterRequestHook () {
// Nothing to do, let children reimplement it
}
afterRequestsHook () {
protected afterRequestsHook () {
// Nothing to do, let children reimplement it
}
}
// ---------------------------------------------------------------------------
export {
BaseRequestScheduler
}

View File

@ -0,0 +1,3 @@
export * from './request-scheduler'
export * from './request-video-event-scheduler'
export * from './request-video-qadu-scheduler'

View File

@ -1,17 +1,18 @@
'use strict'
const constants = require('../../initializers/constants')
const BaseRequestScheduler = require('./base-request-scheduler')
const db = require('../../initializers/database')
const logger = require('../../helpers/logger')
import { BaseRequestScheduler } from './base-request-scheduler'
import { logger } from '../../helpers'
import {
REQUESTS_LIMIT_PODS,
REQUESTS_LIMIT_PER_POD
} from '../../initializers'
module.exports = class RequestScheduler extends BaseRequestScheduler {
class RequestScheduler extends BaseRequestScheduler {
constructor () {
super()
// We limit the size of the requests
this.limitPods = constants.REQUESTS_LIMIT_PODS
this.limitPerPod = constants.REQUESTS_LIMIT_PER_POD
this.limitPods = REQUESTS_LIMIT_PODS
this.limitPerPod = REQUESTS_LIMIT_PER_POD
this.description = 'requests'
}
@ -95,3 +96,9 @@ module.exports = class RequestScheduler extends BaseRequestScheduler {
})
}
}
// ---------------------------------------------------------------------------
export {
RequestScheduler
}

View File

@ -1,16 +1,18 @@
'use strict'
const BaseRequestScheduler = require('./base-request-scheduler')
const constants = require('../../initializers/constants')
const db = require('../../initializers/database')
import { BaseRequestScheduler } from './base-request-scheduler'
import {
REQUESTS_VIDEO_EVENT_LIMIT_PODS,
REQUESTS_VIDEO_EVENT_LIMIT_PER_POD,
REQUEST_VIDEO_EVENT_ENDPOINT
} from '../../initializers'
module.exports = class RequestVideoEventScheduler extends BaseRequestScheduler {
class RequestVideoEventScheduler extends BaseRequestScheduler {
constructor () {
super()
// We limit the size of the requests
this.limitPods = constants.REQUESTS_VIDEO_EVENT_LIMIT_PODS
this.limitPerPod = constants.REQUESTS_VIDEO_EVENT_LIMIT_PER_POD
this.limitPods = REQUESTS_VIDEO_EVENT_LIMIT_PODS
this.limitPerPod = REQUESTS_VIDEO_EVENT_LIMIT_PER_POD
this.description = 'video event requests'
}
@ -45,7 +47,7 @@ module.exports = class RequestVideoEventScheduler extends BaseRequestScheduler {
if (!requestsToMakeGrouped[toPodId]) {
requestsToMakeGrouped[toPodId] = {
toPod: eventToProcess.pod,
endpoint: constants.REQUEST_VIDEO_EVENT_ENDPOINT,
endpoint: REQUEST_VIDEO_EVENT_ENDPOINT,
ids: [], // request ids, to delete them from the DB in the future
datas: [] // requests data
}
@ -94,7 +96,7 @@ module.exports = class RequestVideoEventScheduler extends BaseRequestScheduler {
if (count === undefined) count = 1
const dbRequestOptions = {}
const dbRequestOptions: { transaction?: any } = {}
if (transaction) dbRequestOptions.transaction = transaction
const createQuery = {
@ -106,3 +108,9 @@ module.exports = class RequestVideoEventScheduler extends BaseRequestScheduler {
return db.RequestVideoEvent.create(createQuery, dbRequestOptions).asCallback(callback)
}
}
// ---------------------------------------------------------------------------
export {
RequestVideoEventScheduler
}

View File

@ -1,17 +1,20 @@
'use strict'
const BaseRequestScheduler = require('./base-request-scheduler')
const constants = require('../../initializers/constants')
const db = require('../../initializers/database')
const logger = require('../../helpers/logger')
import { BaseRequestScheduler } from './base-request-scheduler'
import { logger } from '../../helpers'
import {
REQUESTS_VIDEO_QADU_LIMIT_PODS,
REQUESTS_VIDEO_QADU_LIMIT_PER_POD,
REQUEST_VIDEO_QADU_ENDPOINT,
REQUEST_VIDEO_QADU_TYPES
} from '../../initializers'
module.exports = class RequestVideoQaduScheduler extends BaseRequestScheduler {
class RequestVideoQaduScheduler extends BaseRequestScheduler {
constructor () {
super()
// We limit the size of the requests
this.limitPods = constants.REQUESTS_VIDEO_QADU_LIMIT_PODS
this.limitPerPod = constants.REQUESTS_VIDEO_QADU_LIMIT_PER_POD
this.limitPods = REQUESTS_VIDEO_QADU_LIMIT_PODS
this.limitPerPod = REQUESTS_VIDEO_QADU_LIMIT_PER_POD
this.description = 'video QADU requests'
}
@ -37,7 +40,7 @@ module.exports = class RequestVideoQaduScheduler extends BaseRequestScheduler {
if (!requestsToMakeGrouped[hashKey]) {
requestsToMakeGrouped[hashKey] = {
toPod: pod,
endpoint: constants.REQUEST_VIDEO_QADU_ENDPOINT,
endpoint: REQUEST_VIDEO_QADU_ENDPOINT,
ids: [], // request ids, to delete them from the DB in the future
datas: [], // requests data
videos: {}
@ -49,15 +52,15 @@ module.exports = class RequestVideoQaduScheduler extends BaseRequestScheduler {
if (!videoData) videoData = {}
switch (request.type) {
case constants.REQUEST_VIDEO_QADU_TYPES.LIKES:
case REQUEST_VIDEO_QADU_TYPES.LIKES:
videoData.likes = video.likes
break
case constants.REQUEST_VIDEO_QADU_TYPES.DISLIKES:
case REQUEST_VIDEO_QADU_TYPES.DISLIKES:
videoData.dislikes = video.dislikes
break
case constants.REQUEST_VIDEO_QADU_TYPES.VIEWS:
case REQUEST_VIDEO_QADU_TYPES.VIEWS:
videoData.views = video.views
break
@ -99,7 +102,7 @@ module.exports = class RequestVideoQaduScheduler extends BaseRequestScheduler {
const videoId = options.videoId
const transaction = options.transaction
const dbRequestOptions = {}
const dbRequestOptions: { transaction?: any } = {}
if (transaction) dbRequestOptions.transaction = transaction
// Send the update to all our friends
@ -115,3 +118,9 @@ module.exports = class RequestVideoQaduScheduler extends BaseRequestScheduler {
})
}
}
// ---------------------------------------------------------------------------
export {
RequestVideoQaduScheduler
}

View File

@ -1,11 +1,5 @@
'use strict'
const logger = require('../helpers/logger')
const adminMiddleware = {
ensureIsAdmin
}
function ensureIsAdmin (req, res, next) {
const user = res.locals.oauth.token.user
if (user.isAdmin() === false) {
@ -18,4 +12,6 @@ function ensureIsAdmin (req, res, next) {
// ---------------------------------------------------------------------------
module.exports = adminMiddleware
export {
ensureIsAdmin
}

View File

@ -1,25 +0,0 @@
'use strict'
const adminMiddleware = require('./admin')
const oauthMiddleware = require('./oauth')
const paginationMiddleware = require('./pagination')
const podsMiddleware = require('./pods')
const validatorsMiddleware = require('./validators')
const searchMiddleware = require('./search')
const sortMiddleware = require('./sort')
const secureMiddleware = require('./secure')
const middlewares = {
admin: adminMiddleware,
oauth: oauthMiddleware,
pagination: paginationMiddleware,
pods: podsMiddleware,
search: searchMiddleware,
secure: secureMiddleware,
sort: sortMiddleware,
validators: validatorsMiddleware
}
// ---------------------------------------------------------------------------
module.exports = middlewares

View File

@ -0,0 +1,8 @@
export * from './validators';
export * from './admin';
export * from './oauth';
export * from './pagination';
export * from './pods';
export * from './search';
export * from './secure';
export * from './sort';

View File

@ -1,6 +1,4 @@
'use strict'
const OAuthServer = require('express-oauth-server')
import OAuthServer = require('express-oauth-server')
const constants = require('../initializers/constants')
const logger = require('../helpers/logger')
@ -11,11 +9,6 @@ const oAuthServer = new OAuthServer({
model: require('../lib/oauth-model')
})
const oAuth = {
authenticate,
token
}
function authenticate (req, res, next) {
oAuthServer.authenticate()(req, res, function (err) {
if (err) {
@ -35,4 +28,7 @@ function token (req, res, next) {
// ---------------------------------------------------------------------------
module.exports = oAuth
export {
authenticate,
token
}

View File

@ -1,14 +1,9 @@
'use strict'
const constants = require('../initializers/constants')
const paginationMiddleware = {
setPagination
}
function setPagination (req, res, next) {
if (!req.query.start) req.query.start = 0
else req.query.start = parseInt(req.query.start, 10)
if (!req.query.count) req.query.count = constants.PAGINATION_COUNT_DEFAULT
else req.query.count = parseInt(req.query.count, 10)
@ -17,4 +12,6 @@ function setPagination (req, res, next) {
// ---------------------------------------------------------------------------
module.exports = paginationMiddleware
export {
setPagination
}

View File

@ -2,11 +2,6 @@
const constants = require('../initializers/constants')
const podsMiddleware = {
setBodyHostsPort,
setBodyHostPort
}
function setBodyHostsPort (req, res, next) {
if (!req.body.hosts) return next()
@ -41,7 +36,10 @@ function setBodyHostPort (req, res, next) {
// ---------------------------------------------------------------------------
module.exports = podsMiddleware
export {
setBodyHostsPort,
setBodyHostPort
}
// ---------------------------------------------------------------------------

View File

@ -1,9 +1,3 @@
'use strict'
const searchMiddleware = {
setVideosSearch
}
function setVideosSearch (req, res, next) {
if (!req.query.field) req.query.field = 'name'
@ -12,4 +6,6 @@ function setVideosSearch (req, res, next) {
// ---------------------------------------------------------------------------
module.exports = searchMiddleware
export {
setVideosSearch
}

View File

@ -1,13 +1,7 @@
'use strict'
const db = require('../initializers/database')
const logger = require('../helpers/logger')
const peertubeCrypto = require('../helpers/peertube-crypto')
const secureMiddleware = {
checkSignature
}
function checkSignature (req, res, next) {
const host = req.body.signature.host
db.Pod.loadByHost(host, function (err, pod) {
@ -49,4 +43,6 @@ function checkSignature (req, res, next) {
// ---------------------------------------------------------------------------
module.exports = secureMiddleware
export {
checkSignature
}

View File

@ -1,11 +1,3 @@
'use strict'
const sortMiddleware = {
setUsersSort,
setVideoAbusesSort,
setVideosSort
}
function setUsersSort (req, res, next) {
if (!req.query.sort) req.query.sort = '-createdAt'
@ -26,4 +18,8 @@ function setVideosSort (req, res, next) {
// ---------------------------------------------------------------------------
module.exports = sortMiddleware
export {
setUsersSort,
setVideoAbusesSort,
setVideosSort
}

View File

@ -1,21 +0,0 @@
'use strict'
const paginationValidators = require('./pagination')
const podsValidators = require('./pods')
const remoteValidators = require('./remote')
const sortValidators = require('./sort')
const usersValidators = require('./users')
const videosValidators = require('./videos')
const validators = {
pagination: paginationValidators,
pods: podsValidators,
remote: remoteValidators,
sort: sortValidators,
users: usersValidators,
videos: videosValidators
}
// ---------------------------------------------------------------------------
module.exports = validators

View File

@ -0,0 +1,6 @@
export * from './remote'
export * from './pagination'
export * from './pods'
export * from './sort'
export * from './users'
export * from './videos'

View File

@ -1,13 +1,7 @@
'use strict'
import { checkErrors } from './utils'
import { logger } from '../../helpers'
const checkErrors = require('./utils').checkErrors
const logger = require('../../helpers/logger')
const validatorsPagination = {
pagination
}
function pagination (req, res, next) {
function paginationValidator (req, res, next) {
req.checkQuery('start', 'Should have a number start').optional().isInt()
req.checkQuery('count', 'Should have a number count').optional().isInt()
@ -18,4 +12,6 @@ function pagination (req, res, next) {
// ---------------------------------------------------------------------------
module.exports = validatorsPagination
export {
paginationValidator
}

View File

@ -1,20 +1,13 @@
'use strict'
const checkErrors = require('./utils').checkErrors
const constants = require('../../initializers/constants')
const db = require('../../initializers/database')
const friends = require('../../lib/friends')
const logger = require('../../helpers/logger')
const utils = require('../../helpers/utils')
import { checkErrors } from './utils'
import { logger } from '../../helpers'
import { CONFIG } from '../../initializers'
import { hasFriends } from '../../lib'
import { isTestInstance } from '../../helpers'
const validatorsPod = {
makeFriends,
podsAdd
}
function makeFriends (req, res, next) {
function makeFriendsValidator (req, res, next) {
// Force https if the administrator wants to make friends
if (utils.isTestInstance() === false && constants.CONFIG.WEBSERVER.SCHEME === 'http') {
if (isTestInstance() === false && CONFIG.WEBSERVER.SCHEME === 'http') {
return res.status(400).send('Cannot make friends with a non HTTPS webserver.')
}
@ -23,13 +16,13 @@ function makeFriends (req, res, next) {
logger.debug('Checking makeFriends parameters', { parameters: req.body })
checkErrors(req, res, function () {
friends.hasFriends(function (err, hasFriends) {
hasFriends(function (err, heHasFriends) {
if (err) {
logger.error('Cannot know if we have friends.', { error: err })
res.sendStatus(500)
}
if (hasFriends === true) {
if (heHasFriends === true) {
// We need to quit our friends before make new ones
return res.sendStatus(409)
}
@ -39,7 +32,7 @@ function makeFriends (req, res, next) {
})
}
function podsAdd (req, res, next) {
function podsAddValidator (req, res, next) {
req.checkBody('host', 'Should have a host').isHostValid()
req.checkBody('email', 'Should have an email').isEmail()
req.checkBody('publicKey', 'Should have a public key').notEmpty()
@ -64,4 +57,7 @@ function podsAdd (req, res, next) {
// ---------------------------------------------------------------------------
module.exports = validatorsPod
export {
makeFriendsValidator,
podsAddValidator
}

View File

@ -1,13 +0,0 @@
'use strict'
const remoteSignatureValidators = require('./signature')
const remoteVideosValidators = require('./videos')
const validators = {
signature: remoteSignatureValidators,
videos: remoteVideosValidators
}
// ---------------------------------------------------------------------------
module.exports = validators

View File

@ -0,0 +1,2 @@
export * from './signature'
export * from './videos'

View File

@ -1,13 +1,7 @@
'use strict'
import { logger } from '../../../helpers'
import { checkErrors } from '../utils'
const checkErrors = require('../utils').checkErrors
const logger = require('../../../helpers/logger')
const validatorsRemoteSignature = {
signature
}
function signature (req, res, next) {
function signatureValidator (req, res, next) {
req.checkBody('signature.host', 'Should have a signature host').isURL()
req.checkBody('signature.signature', 'Should have a signature').notEmpty()
@ -18,4 +12,6 @@ function signature (req, res, next) {
// ---------------------------------------------------------------------------
module.exports = validatorsRemoteSignature
export {
signatureValidator
}

View File

@ -1,15 +1,7 @@
'use strict'
import { logger } from '../../../helpers'
import { checkErrors } from '../utils'
const checkErrors = require('../utils').checkErrors
const logger = require('../../../helpers/logger')
const validatorsRemoteVideos = {
remoteVideos,
remoteQaduVideos,
remoteEventsVideos
}
function remoteVideos (req, res, next) {
function remoteVideosValidator (req, res, next) {
req.checkBody('data').isEachRemoteRequestVideosValid()
logger.debug('Checking remoteVideos parameters', { parameters: req.body })
@ -17,7 +9,7 @@ function remoteVideos (req, res, next) {
checkErrors(req, res, next)
}
function remoteQaduVideos (req, res, next) {
function remoteQaduVideosValidator (req, res, next) {
req.checkBody('data').isEachRemoteRequestVideosQaduValid()
logger.debug('Checking remoteQaduVideos parameters', { parameters: req.body })
@ -25,13 +17,18 @@ function remoteQaduVideos (req, res, next) {
checkErrors(req, res, next)
}
function remoteEventsVideos (req, res, next) {
function remoteEventsVideosValidator (req, res, next) {
req.checkBody('data').isEachRemoteRequestVideosEventsValid()
logger.debug('Checking remoteEventsVideos parameters', { parameters: req.body })
checkErrors(req, res, next)
}
// ---------------------------------------------------------------------------
module.exports = validatorsRemoteVideos
export {
remoteVideosValidator,
remoteQaduVideosValidator,
remoteEventsVideosValidator
}

View File

@ -1,35 +1,31 @@
'use strict'
const checkErrors = require('./utils').checkErrors
const constants = require('../../initializers/constants')
const logger = require('../../helpers/logger')
const validatorsSort = {
usersSort,
videoAbusesSort,
videosSort
}
import { checkErrors } from './utils'
import { logger } from '../../helpers'
import { SORTABLE_COLUMNS } from '../../initializers'
// Initialize constants here for better performances
const SORTABLE_USERS_COLUMNS = createSortableColumns(constants.SORTABLE_COLUMNS.USERS)
const SORTABLE_VIDEO_ABUSES_COLUMNS = createSortableColumns(constants.SORTABLE_COLUMNS.VIDEO_ABUSES)
const SORTABLE_VIDEOS_COLUMNS = createSortableColumns(constants.SORTABLE_COLUMNS.VIDEOS)
const SORTABLE_USERS_COLUMNS = createSortableColumns(SORTABLE_COLUMNS.USERS)
const SORTABLE_VIDEO_ABUSES_COLUMNS = createSortableColumns(SORTABLE_COLUMNS.VIDEO_ABUSES)
const SORTABLE_VIDEOS_COLUMNS = createSortableColumns(SORTABLE_COLUMNS.VIDEOS)
function usersSort (req, res, next) {
function usersSortValidator (req, res, next) {
checkSort(req, res, next, SORTABLE_USERS_COLUMNS)
}
function videoAbusesSort (req, res, next) {
function videoAbusesSortValidator (req, res, next) {
checkSort(req, res, next, SORTABLE_VIDEO_ABUSES_COLUMNS)
}
function videosSort (req, res, next) {
function videosSortValidator (req, res, next) {
checkSort(req, res, next, SORTABLE_VIDEOS_COLUMNS)
}
// ---------------------------------------------------------------------------
module.exports = validatorsSort
export {
usersSortValidator,
videoAbusesSortValidator,
videosSortValidator
}
// ---------------------------------------------------------------------------

View File

@ -1,17 +1,8 @@
'use strict'
const checkErrors = require('./utils').checkErrors
const db = require('../../initializers/database')
const logger = require('../../helpers/logger')
import { checkErrors } from './utils'
import { logger } from '../../helpers'
const validatorsUsers = {
usersAdd,
usersRemove,
usersUpdate,
usersVideoRating
}
function usersAdd (req, res, next) {
function usersAddValidator (req, res, next) {
req.checkBody('username', 'Should have a valid username').isUserUsernameValid()
req.checkBody('password', 'Should have a valid password').isUserPasswordValid()
req.checkBody('email', 'Should have a valid email').isEmail()
@ -32,7 +23,7 @@ function usersAdd (req, res, next) {
})
}
function usersRemove (req, res, next) {
function usersRemoveValidator (req, res, next) {
req.checkParams('id', 'Should have a valid id').notEmpty().isInt()
logger.debug('Checking usersRemove parameters', { parameters: req.params })
@ -53,7 +44,7 @@ function usersRemove (req, res, next) {
})
}
function usersUpdate (req, res, next) {
function usersUpdateValidator (req, res, next) {
req.checkParams('id', 'Should have a valid id').notEmpty().isInt()
// Add old password verification
req.checkBody('password', 'Should have a valid password').optional().isUserPasswordValid()
@ -64,7 +55,7 @@ function usersUpdate (req, res, next) {
checkErrors(req, res, next)
}
function usersVideoRating (req, res, next) {
function usersVideoRatingValidator (req, res, next) {
req.checkParams('videoId', 'Should have a valid video id').notEmpty().isUUID(4)
logger.debug('Checking usersVideoRating parameters', { parameters: req.params })
@ -85,4 +76,9 @@ function usersVideoRating (req, res, next) {
// ---------------------------------------------------------------------------
module.exports = validatorsUsers
export {
usersAddValidator,
usersRemoveValidator,
usersUpdateValidator,
usersVideoRatingValidator
}

View File

@ -1,20 +1,14 @@
'use strict'
import { inspect } from 'util'
const util = require('util')
import { logger } from '../../helpers'
const logger = require('../../helpers/logger')
const validatorsUtils = {
checkErrors
}
function checkErrors (req, res, next, statusCode) {
function checkErrors (req, res, next, statusCode?) {
if (statusCode === undefined) statusCode = 400
const errors = req.validationErrors()
if (errors) {
logger.warn('Incorrect request parameters', { path: req.originalUrl, err: errors })
return res.status(statusCode).send('There have been validation errors: ' + util.inspect(errors))
return res.status(statusCode).send('There have been validation errors: ' + inspect(errors))
}
return next()
@ -22,4 +16,6 @@ function checkErrors (req, res, next, statusCode) {
// ---------------------------------------------------------------------------
module.exports = validatorsUtils
export {
checkErrors
}

View File

@ -1,26 +1,9 @@
'use strict'
const checkErrors = require('./utils').checkErrors
const constants = require('../../initializers/constants')
const customVideosValidators = require('../../helpers/custom-validators').videos
const db = require('../../initializers/database')
const logger = require('../../helpers/logger')
import { checkErrors } from './utils'
import { CONSTRAINTS_FIELDS, SEARCHABLE_COLUMNS } from '../../initializers'
import { logger, isVideoDurationValid } from '../../helpers'
const validatorsVideos = {
videosAdd,
videosUpdate,
videosGet,
videosRemove,
videosSearch,
videoAbuseReport,
videoRate,
videosBlacklist
}
function videosAdd (req, res, next) {
function videosAddValidator (req, res, next) {
req.checkBody('videofile', 'Should have a valid file').isVideoFile(req.files)
req.checkBody('name', 'Should have a valid name').isVideoNameValid()
req.checkBody('category', 'Should have a valid category').isVideoCategoryValid()
@ -40,8 +23,8 @@ function videosAdd (req, res, next) {
return res.status(400).send('Cannot retrieve metadata of the file.')
}
if (!customVideosValidators.isVideoDurationValid(duration)) {
return res.status(400).send('Duration of the video file is too big (max: ' + constants.CONSTRAINTS_FIELDS.VIDEOS.DURATION.max + 's).')
if (!isVideoDurationValid(duration)) {
return res.status(400).send('Duration of the video file is too big (max: ' + CONSTRAINTS_FIELDS.VIDEOS.DURATION.max + 's).')
}
videoFile.duration = duration
@ -50,7 +33,7 @@ function videosAdd (req, res, next) {
})
}
function videosUpdate (req, res, next) {
function videosUpdateValidator (req, res, next) {
req.checkParams('id', 'Should have a valid id').notEmpty().isUUID(4)
req.checkBody('name', 'Should have a valid name').optional().isVideoNameValid()
req.checkBody('category', 'Should have a valid category').optional().isVideoCategoryValid()
@ -78,7 +61,7 @@ function videosUpdate (req, res, next) {
})
}
function videosGet (req, res, next) {
function videosGetValidator (req, res, next) {
req.checkParams('id', 'Should have a valid id').notEmpty().isUUID(4)
logger.debug('Checking videosGet parameters', { parameters: req.params })
@ -88,7 +71,7 @@ function videosGet (req, res, next) {
})
}
function videosRemove (req, res, next) {
function videosRemoveValidator (req, res, next) {
req.checkParams('id', 'Should have a valid id').notEmpty().isUUID(4)
logger.debug('Checking videosRemove parameters', { parameters: req.params })
@ -105,8 +88,8 @@ function videosRemove (req, res, next) {
})
}
function videosSearch (req, res, next) {
const searchableColumns = constants.SEARCHABLE_COLUMNS.VIDEOS
function videosSearchValidator (req, res, next) {
const searchableColumns = SEARCHABLE_COLUMNS.VIDEOS
req.checkParams('value', 'Should have a valid search').notEmpty()
req.checkQuery('field', 'Should have correct searchable column').optional().isIn(searchableColumns)
@ -115,7 +98,7 @@ function videosSearch (req, res, next) {
checkErrors(req, res, next)
}
function videoAbuseReport (req, res, next) {
function videoAbuseReportValidator (req, res, next) {
req.checkParams('id', 'Should have a valid id').notEmpty().isUUID(4)
req.checkBody('reason', 'Should have a valid reason').isVideoAbuseReasonValid()
@ -126,7 +109,7 @@ function videoAbuseReport (req, res, next) {
})
}
function videoRate (req, res, next) {
function videoRateValidator (req, res, next) {
req.checkParams('id', 'Should have a valid id').notEmpty().isUUID(4)
req.checkBody('rating', 'Should have a valid rate type').isVideoRatingTypeValid()
@ -137,7 +120,7 @@ function videoRate (req, res, next) {
})
}
function videosBlacklist (req, res, next) {
function videosBlacklistValidator (req, res, next) {
req.checkParams('id', 'Should have a valid id').notEmpty().isUUID(4)
logger.debug('Checking videosBlacklist parameters', { parameters: req.params })
@ -151,7 +134,19 @@ function videosBlacklist (req, res, next) {
// ---------------------------------------------------------------------------
module.exports = validatorsVideos
export {
videosAddValidator,
videosUpdateValidator,
videosGetValidator,
videosRemoveValidator,
videosSearchValidator,
videoAbuseReportValidator,
videoRateValidator,
videosBlacklistValidator
}
// ---------------------------------------------------------------------------

View File

@ -1,5 +1,3 @@
'use strict'
module.exports = function (sequelize, DataTypes) {
const Application = sequelize.define('Application',
{
@ -38,7 +36,7 @@ function loadMigrationVersion (callback) {
}
function updateMigrationVersion (newVersion, transaction, callback) {
const options = {
const options: { where?: any, transaction?: any } = {
where: {}
}

View File

@ -1,6 +1,4 @@
'use strict'
const customUsersValidators = require('../helpers/custom-validators').users
import { isUserUsernameValid } from '../helpers'
module.exports = function (sequelize, DataTypes) {
const Author = sequelize.define('Author',
@ -10,7 +8,7 @@ module.exports = function (sequelize, DataTypes) {
allowNull: false,
validate: {
usernameValid: function (value) {
const res = customUsersValidators.isUserUsernameValid(value)
const res = isUserUsernameValid(value)
if (res === false) throw new Error('Username is not valid.')
}
}
@ -76,7 +74,7 @@ function findOrCreateAuthor (name, podId, userId, transaction, callback) {
userId
}
const query = {
const query: any = {
where: author,
defaults: author
}

View File

@ -1,8 +1,6 @@
'use strict'
import { values } from 'lodash'
const values = require('lodash/values')
const constants = require('../initializers/constants')
import { JOB_STATES } from '../initializers'
// ---------------------------------------------------------------------------
@ -10,7 +8,7 @@ module.exports = function (sequelize, DataTypes) {
const Job = sequelize.define('Job',
{
state: {
type: DataTypes.ENUM(values(constants.JOB_STATES)),
type: DataTypes.ENUM(values(JOB_STATES)),
allowNull: false
},
handlerName: {

View File

@ -1,5 +1,3 @@
'use strict'
module.exports = function (sequelize, DataTypes) {
const OAuthClient = sequelize.define('OAuthClient',
{

View File

@ -1,6 +1,4 @@
'use strict'
const logger = require('../helpers/logger')
import { logger } from '../helpers'
// ---------------------------------------------------------------------------

View File

@ -1,12 +1,8 @@
'use strict'
import { each, waterfall } from 'async'
import { map } from 'lodash'
const each = require('async/each')
const map = require('lodash/map')
const waterfall = require('async/waterfall')
const constants = require('../initializers/constants')
const logger = require('../helpers/logger')
const customPodsValidators = require('../helpers/custom-validators').pods
import { FRIEND_SCORE, PODS_SCORE } from '../initializers'
import { logger, isHostValid } from '../helpers'
// ---------------------------------------------------------------------------
@ -18,7 +14,7 @@ module.exports = function (sequelize, DataTypes) {
allowNull: false,
validate: {
isHost: function (value) {
const res = customPodsValidators.isHostValid(value)
const res = isHostValid(value)
if (res === false) throw new Error('Host not valid.')
}
}
@ -29,11 +25,11 @@ module.exports = function (sequelize, DataTypes) {
},
score: {
type: DataTypes.INTEGER,
defaultValue: constants.FRIEND_SCORE.BASE,
defaultValue: FRIEND_SCORE.BASE,
allowNull: false,
validate: {
isInt: true,
max: constants.FRIEND_SCORE.MAX
max: FRIEND_SCORE.MAX
}
},
email: {
@ -106,7 +102,7 @@ function countAll (callback) {
}
function incrementScores (ids, value, callback) {
if (!callback) callback = function () {}
if (!callback) callback = function () { /* empty */ }
const update = {
score: this.sequelize.literal('score +' + value)
@ -135,7 +131,7 @@ function listAllIds (transaction, callback) {
transaction = null
}
const query = {
const query: any = {
attributes: [ 'id' ]
}
@ -223,13 +219,13 @@ function updatePodsScore (goodPods, badPods) {
logger.info('Updating %d good pods and %d bad pods scores.', goodPods.length, badPods.length)
if (goodPods.length !== 0) {
this.incrementScores(goodPods, constants.PODS_SCORE.BONUS, function (err) {
this.incrementScores(goodPods, PODS_SCORE.BONUS, function (err) {
if (err) logger.error('Cannot increment scores of good pods.', { error: err })
})
}
if (badPods.length !== 0) {
this.incrementScores(badPods, constants.PODS_SCORE.MALUS, function (err) {
this.incrementScores(badPods, PODS_SCORE.MALUS, function (err) {
if (err) logger.error('Cannot decrement scores of bad pods.', { error: err })
removeBadPods.call(self)
})
@ -255,7 +251,7 @@ function removeBadPods () {
},
function removeTheseBadPods (pods, callback) {
each(pods, function (pod, callbackEach) {
each(pods, function (pod: any, callbackEach) {
pod.destroy().asCallback(callbackEach)
}, function (err) {
return callback(err, pods.length)

View File

@ -1,7 +1,3 @@
'use strict'
// ---------------------------------------------------------------------------
module.exports = function (sequelize, DataTypes) {
const RequestToPod = sequelize.define('RequestToPod', {}, {
indexes: [
@ -27,7 +23,7 @@ module.exports = function (sequelize, DataTypes) {
// ---------------------------------------------------------------------------
function removeByRequestIdsAndPod (requestsIds, podId, callback) {
if (!callback) callback = function () {}
if (!callback) callback = function () { /* empty */ }
const query = {
where: {

View File

@ -1,13 +1,11 @@
'use strict'
/*
Request Video events (likes, dislikes, views...)
*/
const values = require('lodash/values')
import { values } from 'lodash'
const constants = require('../initializers/constants')
const customVideosValidators = require('../helpers/custom-validators').videos
import { REQUEST_VIDEO_EVENT_TYPES } from '../initializers'
import { isVideoEventCountValid } from '../helpers'
// ---------------------------------------------------------------------------
@ -15,7 +13,7 @@ module.exports = function (sequelize, DataTypes) {
const RequestVideoEvent = sequelize.define('RequestVideoEvent',
{
type: {
type: DataTypes.ENUM(values(constants.REQUEST_VIDEO_EVENT_TYPES)),
type: DataTypes.ENUM(values(REQUEST_VIDEO_EVENT_TYPES)),
allowNull: false
},
count: {
@ -23,7 +21,7 @@ module.exports = function (sequelize, DataTypes) {
allowNull: false,
validate: {
countValid: function (value) {
const res = customVideosValidators.isVideoEventCountValid(value)
const res = isVideoEventCountValid(value)
if (res === false) throw new Error('Video event count is not valid.')
}
}

Some files were not shown because too many files have changed in this diff Show More