From 65fcc3119c334b75dd13bcfdebf186afdc580a8f Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Mon, 15 May 2017 22:22:03 +0200 Subject: [PATCH] First typescript iteration --- .gitignore | 1 + package.json | 16 ++ server.js => server.ts | 80 ++++---- .../api/{clients.js => clients.ts} | 20 +- server/controllers/api/config.js | 22 --- server/controllers/api/config.ts | 22 +++ server/controllers/api/index.js | 35 ---- server/controllers/api/index.ts | 33 ++++ server/controllers/api/pods.js | 109 ----------- server/controllers/api/pods.ts | 118 ++++++++++++ server/controllers/api/remote/index.js | 18 -- server/controllers/api/remote/index.ts | 18 ++ .../api/remote/{pods.js => pods.ts} | 20 +- .../api/remote/{videos.js => videos.ts} | 122 ++++++------ .../api/{requests.js => requests.ts} | 34 ++-- server/controllers/api/{users.js => users.ts} | 96 ++++----- .../api/videos/{abuse.js => abuse.ts} | 77 ++++---- .../api/videos/{blacklist.js => blacklist.ts} | 34 ++-- .../api/videos/{index.js => index.ts} | 182 ++++++++++-------- .../api/videos/{rate.js => rate.ts} | 78 ++++---- server/controllers/{client.js => client.ts} | 56 +++--- server/controllers/index.js | 11 -- server/controllers/index.ts | 3 + server/controllers/static.js | 45 ----- server/controllers/static.ts | 49 +++++ server/helpers/custom-validators/index.js | 19 -- server/helpers/custom-validators/index.ts | 6 + .../custom-validators/{misc.js => misc.ts} | 12 +- .../custom-validators/{pods.js => pods.ts} | 20 +- .../helpers/custom-validators/remote/index.js | 11 -- .../helpers/custom-validators/remote/index.ts | 1 + .../custom-validators/remote/videos.js | 118 ------------ .../custom-validators/remote/videos.ts | 138 +++++++++++++ .../custom-validators/{users.js => users.ts} | 28 ++- .../{videos.js => videos.ts} | 95 ++++----- .../{database-utils.js => database-utils.ts} | 25 ++- server/helpers/index.ts | 6 + server/helpers/{logger.js => logger.ts} | 31 ++- ...{peertube-crypto.js => peertube-crypto.ts} | 67 ++++--- server/helpers/{requests.js => requests.ts} | 41 ++-- server/helpers/{utils.js => utils.ts} | 26 ++- .../initializers/{checker.js => checker.ts} | 24 +-- .../{constants.js => constants.ts} | 52 ++--- .../initializers/{database.js => database.ts} | 51 +++-- server/initializers/index.ts | 6 + .../{installer.js => installer.ts} | 44 ++--- .../{0005-email-pod.js => 0005-email-pod.ts} | 13 +- ...{0010-email-user.js => 0010-email-user.ts} | 13 +- ...015-video-views.js => 0015-video-views.ts} | 11 +- ...020-video-likes.js => 0020-video-likes.ts} | 11 +- ...deo-dislikes.js => 0025-video-dislikes.ts} | 11 +- ...deo-category.js => 0030-video-category.ts} | 13 +- ...video-licence.js => 0035-video-licence.ts} | 13 +- ...{0040-video-nsfw.js => 0040-video-nsfw.ts} | 13 +- ...play-nsfw.js => 0045-user-display-nsfw.ts} | 11 +- ...deo-language.js => 0050-video-language.ts} | 11 +- .../initializers/{migrator.js => migrator.ts} | 25 +-- server/lib/{friends.js => friends.ts} | 133 +++++++------ server/lib/index.ts | 4 + server/lib/jobs/handlers/index.js | 7 - server/lib/jobs/handlers/index.ts | 9 + ...ideo-transcoder.js => video-transcoder.ts} | 22 +-- server/lib/jobs/index.ts | 1 + server/lib/jobs/job-scheduler.js | 129 ------------- server/lib/jobs/job-scheduler.ts | 137 +++++++++++++ server/lib/{oauth-model.js => oauth-model.ts} | 22 +-- ...scheduler.js => base-request-scheduler.ts} | 64 +++--- server/lib/request/index.ts | 3 + ...uest-scheduler.js => request-scheduler.ts} | 25 ++- ...er.js => request-video-event-scheduler.ts} | 28 ++- ...ler.js => request-video-qadu-scheduler.ts} | 37 ++-- server/middlewares/{admin.js => admin.ts} | 10 +- server/middlewares/index.js | 25 --- server/middlewares/index.ts | 8 + server/middlewares/{oauth.js => oauth.ts} | 14 +- .../{pagination.js => pagination.ts} | 11 +- server/middlewares/{pods.js => pods.ts} | 10 +- server/middlewares/{search.js => search.ts} | 10 +- server/middlewares/{secure.js => secure.ts} | 10 +- server/middlewares/{sort.js => sort.ts} | 14 +- server/middlewares/validators/index.js | 21 -- server/middlewares/validators/index.ts | 6 + .../{pagination.js => pagination.ts} | 16 +- .../validators/{pods.js => pods.ts} | 32 ++- server/middlewares/validators/remote/index.js | 13 -- server/middlewares/validators/remote/index.ts | 2 + .../remote/{signature.js => signature.ts} | 16 +- .../remote/{videos.js => videos.ts} | 25 ++- .../validators/{sort.js => sort.ts} | 32 ++- .../validators/{users.js => users.ts} | 28 ++- .../validators/{utils.js => utils.ts} | 18 +- .../validators/{videos.js => videos.ts} | 59 +++--- .../models/{application.js => application.ts} | 4 +- server/models/{author.js => author.ts} | 8 +- server/models/{job.js => job.ts} | 8 +- .../{oauth-client.js => oauth-client.ts} | 2 - .../models/{oauth-token.js => oauth-token.ts} | 4 +- server/models/{pod.js => pod.ts} | 28 ++- .../{request-to-pod.js => request-to-pod.ts} | 6 +- ...-video-event.js => request-video-event.ts} | 12 +- ...st-video-qadu.js => request-video-qadu.ts} | 8 +- server/models/{request.js => request.ts} | 10 +- server/models/{tag.js => tag.ts} | 6 +- ...{user-video-rate.js => user-video-rate.ts} | 11 +- server/models/{user.js => user.ts} | 35 ++-- server/models/{utils.js => utils.ts} | 10 +- .../models/{video-abuse.js => video-abuse.ts} | 16 +- ...{video-blacklist.js => video-blacklist.ts} | 6 +- server/models/{video-tag.js => video-tag.ts} | 4 - server/models/{video.js => video.ts} | 155 ++++++++------- tsconfig.json | 19 ++ tslint.json | 3 + yarn.lock | 166 ++++++++++++++-- 113 files changed, 1982 insertions(+), 1805 deletions(-) rename server.js => server.ts (57%) rename server/controllers/api/{clients.js => clients.ts} (72%) delete mode 100644 server/controllers/api/config.js create mode 100644 server/controllers/api/config.ts delete mode 100644 server/controllers/api/index.js create mode 100644 server/controllers/api/index.ts delete mode 100644 server/controllers/api/pods.js create mode 100644 server/controllers/api/pods.ts delete mode 100644 server/controllers/api/remote/index.js create mode 100644 server/controllers/api/remote/index.ts rename server/controllers/api/remote/{pods.js => pods.ts} (63%) rename server/controllers/api/remote/{videos.js => videos.ts} (83%) rename server/controllers/api/{requests.js => requests.ts} (59%) rename server/controllers/api/{users.js => users.ts} (64%) rename server/controllers/api/videos/{abuse.js => abuse.ts} (59%) rename server/controllers/api/videos/{blacklist.js => blacklist.ts} (57%) rename server/controllers/api/videos/{index.js => index.ts} (74%) rename server/controllers/api/videos/{rate.js => rate.ts} (71%) rename server/controllers/{client.js => client.ts} (63%) delete mode 100644 server/controllers/index.js create mode 100644 server/controllers/index.ts delete mode 100644 server/controllers/static.js create mode 100644 server/controllers/static.ts delete mode 100644 server/helpers/custom-validators/index.js create mode 100644 server/helpers/custom-validators/index.ts rename server/helpers/custom-validators/{misc.js => misc.ts} (76%) rename server/helpers/custom-validators/{pods.js => pods.ts} (62%) delete mode 100644 server/helpers/custom-validators/remote/index.js create mode 100644 server/helpers/custom-validators/remote/index.ts delete mode 100644 server/helpers/custom-validators/remote/videos.js create mode 100644 server/helpers/custom-validators/remote/videos.ts rename server/helpers/custom-validators/{users.js => users.ts} (61%) rename server/helpers/custom-validators/{videos.js => videos.ts} (76%) rename server/helpers/{database-utils.js => database-utils.ts} (89%) create mode 100644 server/helpers/index.ts rename server/helpers/{logger.js => logger.ts} (57%) rename server/helpers/{peertube-crypto.js => peertube-crypto.ts} (70%) rename server/helpers/{requests.js => requests.ts} (63%) rename server/helpers/{utils.js => utils.ts} (84%) rename server/initializers/{checker.js => checker.ts} (90%) rename server/initializers/{constants.js => constants.ts} (84%) rename server/initializers/{database.js => database.ts} (52%) create mode 100644 server/initializers/index.ts rename server/initializers/{installer.js => installer.ts} (75%) rename server/initializers/migrations/{0005-email-pod.js => 0005-email-pod.ts} (86%) rename server/initializers/migrations/{0010-email-user.js => 0010-email-user.ts} (86%) rename server/initializers/migrations/{0015-video-views.js => 0015-video-views.ts} (77%) rename server/initializers/migrations/{0020-video-likes.js => 0020-video-likes.ts} (77%) rename server/initializers/migrations/{0025-video-dislikes.js => 0025-video-dislikes.ts} (78%) rename server/initializers/migrations/{0030-video-category.js => 0030-video-category.ts} (82%) rename server/initializers/migrations/{0035-video-licence.js => 0035-video-licence.ts} (82%) rename server/initializers/migrations/{0040-video-nsfw.js => 0040-video-nsfw.ts} (81%) rename server/initializers/migrations/{0045-user-display-nsfw.js => 0045-user-display-nsfw.ts} (78%) rename server/initializers/migrations/{0050-video-language.js => 0050-video-language.ts} (78%) rename server/initializers/{migrator.js => migrator.ts} (88%) rename server/lib/{friends.js => friends.ts} (79%) create mode 100644 server/lib/index.ts delete mode 100644 server/lib/jobs/handlers/index.js create mode 100644 server/lib/jobs/handlers/index.ts rename server/lib/jobs/handlers/{video-transcoder.js => video-transcoder.ts} (71%) create mode 100644 server/lib/jobs/index.ts delete mode 100644 server/lib/jobs/job-scheduler.js create mode 100644 server/lib/jobs/job-scheduler.ts rename server/lib/{oauth-model.js => oauth-model.ts} (96%) rename server/lib/request/{base-request-scheduler.js => base-request-scheduler.ts} (72%) create mode 100644 server/lib/request/index.ts rename server/lib/request/{request-scheduler.js => request-scheduler.ts} (83%) rename server/lib/request/{request-video-event-scheduler.js => request-video-event-scheduler.ts} (81%) rename server/lib/request/{request-video-qadu-scheduler.js => request-video-qadu-scheduler.ts} (78%) rename server/middlewares/{admin.js => admin.ts} (84%) delete mode 100644 server/middlewares/index.js create mode 100644 server/middlewares/index.ts rename server/middlewares/{oauth.js => oauth.ts} (88%) rename server/middlewares/{pagination.js => pagination.ts} (84%) rename server/middlewares/{pods.js => pods.ts} (95%) rename server/middlewares/{search.js => search.ts} (73%) rename server/middlewares/{secure.js => secure.ts} (94%) rename server/middlewares/{sort.js => sort.ts} (87%) delete mode 100644 server/middlewares/validators/index.js create mode 100644 server/middlewares/validators/index.ts rename server/middlewares/validators/{pagination.js => pagination.ts} (59%) rename server/middlewares/validators/{pods.js => pods.ts} (69%) delete mode 100644 server/middlewares/validators/remote/index.js create mode 100644 server/middlewares/validators/remote/index.ts rename server/middlewares/validators/remote/{signature.js => signature.ts} (59%) rename server/middlewares/validators/remote/{videos.js => videos.ts} (61%) rename server/middlewares/validators/{sort.js => sort.ts} (55%) rename server/middlewares/validators/{users.js => users.ts} (85%) rename server/middlewares/validators/{utils.js => utils.ts} (61%) rename server/middlewares/validators/{videos.js => videos.ts} (85%) rename server/models/{application.js => application.ts} (94%) rename server/models/{author.js => author.ts} (89%) rename server/models/{job.js => job.ts} (83%) rename server/models/{oauth-client.js => oauth-client.ts} (98%) rename server/models/{oauth-token.js => oauth-token.ts} (97%) rename server/models/{pod.js => pod.ts} (88%) rename server/models/{request-to-pod.js => request-to-pod.ts} (83%) rename server/models/{request-video-event.js => request-video-event.ts} (91%) rename server/models/{request-video-qadu.js => request-video-qadu.ts} (94%) rename server/models/{request.js => request.ts} (93%) rename server/models/{tag.js => tag.ts} (95%) rename server/models/{user-video-rate.js => user-video-rate.ts} (85%) rename server/models/{user.js => user.ts} (81%) rename server/models/{utils.js => utils.ts} (87%) rename server/models/{video-abuse.js => video-abuse.ts} (82%) rename server/models/{video-blacklist.js => video-blacklist.ts} (94%) rename server/models/{video-tag.js => video-tag.ts} (72%) rename server/models/{video.js => video.ts} (79%) create mode 100644 tsconfig.json create mode 100644 tslint.json diff --git a/.gitignore b/.gitignore index 28dec58f3..6caee2e4c 100644 --- a/.gitignore +++ b/.gitignore @@ -16,3 +16,4 @@ /ffmpeg/ /*.sublime-project /*.sublime-workspace +/dist diff --git a/package.json b/package.json index 9c63c67b4..00d0bb5ee 100644 --- a/package.json +++ b/package.json @@ -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": { diff --git a/server.js b/server.ts similarity index 57% rename from server.js rename to server.ts index b2487b767..119c0c61d 100644 --- a/server.js +++ b/server.ts @@ -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 diff --git a/server/controllers/api/clients.js b/server/controllers/api/clients.ts similarity index 72% rename from server/controllers/api/clients.js rename to server/controllers/api/clients.ts index cf83cb835..902f62995 100644 --- a/server/controllers/api/clients.js +++ b/server/controllers/api/clients.ts @@ -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 +} diff --git a/server/controllers/api/config.js b/server/controllers/api/config.js deleted file mode 100644 index 8154b6ad0..000000000 --- a/server/controllers/api/config.js +++ /dev/null @@ -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 diff --git a/server/controllers/api/config.ts b/server/controllers/api/config.ts new file mode 100644 index 000000000..8f3fa2473 --- /dev/null +++ b/server/controllers/api/config.ts @@ -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 +} diff --git a/server/controllers/api/index.js b/server/controllers/api/index.js deleted file mode 100644 index 6edc089f4..000000000 --- a/server/controllers/api/index.js +++ /dev/null @@ -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() -} diff --git a/server/controllers/api/index.ts b/server/controllers/api/index.ts new file mode 100644 index 000000000..18bef2d3d --- /dev/null +++ b/server/controllers/api/index.ts @@ -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() +} diff --git a/server/controllers/api/pods.js b/server/controllers/api/pods.js deleted file mode 100644 index ab5763cf6..000000000 --- a/server/controllers/api/pods.js +++ /dev/null @@ -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() - }) -} diff --git a/server/controllers/api/pods.ts b/server/controllers/api/pods.ts new file mode 100644 index 000000000..06dfd8295 --- /dev/null +++ b/server/controllers/api/pods.ts @@ -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() + }) +} diff --git a/server/controllers/api/remote/index.js b/server/controllers/api/remote/index.js deleted file mode 100644 index 6106850ab..000000000 --- a/server/controllers/api/remote/index.js +++ /dev/null @@ -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 diff --git a/server/controllers/api/remote/index.ts b/server/controllers/api/remote/index.ts new file mode 100644 index 000000000..b11439204 --- /dev/null +++ b/server/controllers/api/remote/index.ts @@ -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 +} diff --git a/server/controllers/api/remote/pods.js b/server/controllers/api/remote/pods.ts similarity index 63% rename from server/controllers/api/remote/pods.js rename to server/controllers/api/remote/pods.ts index 0343bc62e..85ef7bb42 100644 --- a/server/controllers/api/remote/pods.js +++ b/server/controllers/api/remote/pods.ts @@ -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 +} // --------------------------------------------------------------------------- diff --git a/server/controllers/api/remote/videos.js b/server/controllers/api/remote/videos.ts similarity index 83% rename from server/controllers/api/remote/videos.js rename to server/controllers/api/remote/videos.ts index e54793628..df4ba8309 100644 --- a/server/controllers/api/remote/videos.js +++ b/server/controllers/api/remote/videos.ts @@ -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') - -const ENDPOINT_ACTIONS = constants.REQUEST_ENDPOINT_ACTIONS[constants.REQUEST_ENDPOINTS.VIDEOS] +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 = 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) diff --git a/server/controllers/api/requests.js b/server/controllers/api/requests.ts similarity index 59% rename from server/controllers/api/requests.js rename to server/controllers/api/requests.ts index 6fd5753ac..304499a4f 100644 --- a/server/controllers/api/requests.js +++ b/server/controllers/api/requests.ts @@ -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) diff --git a/server/controllers/api/users.js b/server/controllers/api/users.ts similarity index 64% rename from server/controllers/api/users.js rename to server/controllers/api/users.ts index c7fe7bf85..981a4706a 100644 --- a/server/controllers/api/users.js +++ b/server/controllers/api/users.ts @@ -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 - -const router = express.Router() - -router.get('/me', - oAuth.authenticate, +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 usersRouter = express.Router() + +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)) }) } diff --git a/server/controllers/api/videos/abuse.js b/server/controllers/api/videos/abuse.ts similarity index 59% rename from server/controllers/api/videos/abuse.js rename to server/controllers/api/videos/abuse.ts index 0fb44bb14..88204120f 100644 --- a/server/controllers/api/videos/abuse.js +++ b/server/controllers/api/videos/abuse.ts @@ -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') - -const router = express.Router() - -router.get('/abuse', - oAuth.authenticate, - admin.ensureIsAdmin, - validatorsPagination.pagination, - validatorsSort.videoAbusesSort, - sort.setVideoAbusesSort, - pagination.setPagination, +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 abuseVideoRouter = express.Router() + +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) diff --git a/server/controllers/api/videos/blacklist.js b/server/controllers/api/videos/blacklist.ts similarity index 57% rename from server/controllers/api/videos/blacklist.js rename to server/controllers/api/videos/blacklist.ts index 8c3e2a69d..db6d95e73 100644 --- a/server/controllers/api/videos/blacklist.js +++ b/server/controllers/api/videos/blacklist.ts @@ -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 - -const router = express.Router() - -router.post('/:id/blacklist', - oAuth.authenticate, - admin.ensureIsAdmin, - validatorsVideos.videosBlacklist, +import { logger } from '../../../helpers' +import { + authenticate, + ensureIsAdmin, + videosBlacklistValidator +} from '../../../middlewares' + +const blacklistRouter = express.Router() + +blacklistRouter.post('/:id/blacklist', + authenticate, + ensureIsAdmin, + videosBlacklistValidator, addVideoToBlacklist ) // --------------------------------------------------------------------------- -module.exports = router +export { + blacklistRouter +} // --------------------------------------------------------------------------- diff --git a/server/controllers/api/videos/index.js b/server/controllers/api/videos/index.ts similarity index 74% rename from server/controllers/api/videos/index.js rename to server/controllers/api/videos/index.ts index 8de44d5ac..5fbf03676 100644 --- a/server/controllers/api/videos/index.js +++ b/server/controllers/api/videos/index.ts @@ -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') - -const abuseController = require('./abuse') -const blacklistController = require('./blacklist') -const rateController = require('./rate') - -const router = express.Router() +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' + +import { abuseVideoRouter } from './abuse' +import { blacklistRouter } from './blacklist' +import { rateVideoRouter } from './rate' + +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)) } ) } diff --git a/server/controllers/api/videos/rate.js b/server/controllers/api/videos/rate.ts similarity index 71% rename from server/controllers/api/videos/rate.js rename to server/controllers/api/videos/rate.ts index df8a69a1d..21053792a 100644 --- a/server/controllers/api/videos/rate.js +++ b/server/controllers/api/videos/rate.ts @@ -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') - -const router = express.Router() - -router.put('/:id/rate', - oAuth.authenticate, - validatorsVideos.videoRate, +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 rateVideoRouter = express.Router() + +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) diff --git a/server/controllers/client.js b/server/controllers/client.ts similarity index 63% rename from server/controllers/client.js rename to server/controllers/client.ts index 83243a4f7..aaa04889a 100644 --- a/server/controllers/client.js +++ b/server/controllers/client.ts @@ -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 = '' -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) diff --git a/server/controllers/index.js b/server/controllers/index.js deleted file mode 100644 index c9ca297ef..000000000 --- a/server/controllers/index.js +++ /dev/null @@ -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 -} diff --git a/server/controllers/index.ts b/server/controllers/index.ts new file mode 100644 index 000000000..bb56fd7cf --- /dev/null +++ b/server/controllers/index.ts @@ -0,0 +1,3 @@ +export * from './static'; +export * from './client'; +export * from './api'; diff --git a/server/controllers/static.js b/server/controllers/static.js deleted file mode 100644 index 810b752af..000000000 --- a/server/controllers/static.js +++ /dev/null @@ -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 diff --git a/server/controllers/static.ts b/server/controllers/static.ts new file mode 100644 index 000000000..51f75c57e --- /dev/null +++ b/server/controllers/static.ts @@ -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 +} diff --git a/server/helpers/custom-validators/index.js b/server/helpers/custom-validators/index.js deleted file mode 100644 index 9383e0304..000000000 --- a/server/helpers/custom-validators/index.js +++ /dev/null @@ -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 diff --git a/server/helpers/custom-validators/index.ts b/server/helpers/custom-validators/index.ts new file mode 100644 index 000000000..1dcab624a --- /dev/null +++ b/server/helpers/custom-validators/index.ts @@ -0,0 +1,6 @@ +export * from './remote' +export * from './misc' +export * from './pods' +export * from './pods' +export * from './users' +export * from './videos' diff --git a/server/helpers/custom-validators/misc.js b/server/helpers/custom-validators/misc.ts similarity index 76% rename from server/helpers/custom-validators/misc.js rename to server/helpers/custom-validators/misc.ts index 052726241..83f50a7fe 100644 --- a/server/helpers/custom-validators/misc.js +++ b/server/helpers/custom-validators/misc.ts @@ -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 +} diff --git a/server/helpers/custom-validators/pods.js b/server/helpers/custom-validators/pods.ts similarity index 62% rename from server/helpers/custom-validators/pods.js rename to server/helpers/custom-validators/pods.ts index 8bb3733ff..e4c827feb 100644 --- a/server/helpers/custom-validators/pods.js +++ b/server/helpers/custom-validators/pods.ts @@ -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 +} diff --git a/server/helpers/custom-validators/remote/index.js b/server/helpers/custom-validators/remote/index.js deleted file mode 100644 index 1939a95f4..000000000 --- a/server/helpers/custom-validators/remote/index.js +++ /dev/null @@ -1,11 +0,0 @@ -'use strict' - -const remoteVideosValidators = require('./videos') - -const validators = { - videos: remoteVideosValidators -} - -// --------------------------------------------------------------------------- - -module.exports = validators diff --git a/server/helpers/custom-validators/remote/index.ts b/server/helpers/custom-validators/remote/index.ts new file mode 100644 index 000000000..d6f9a7e77 --- /dev/null +++ b/server/helpers/custom-validators/remote/index.ts @@ -0,0 +1 @@ +export * from './videos'; diff --git a/server/helpers/custom-validators/remote/videos.js b/server/helpers/custom-validators/remote/videos.js deleted file mode 100644 index 24715b4b3..000000000 --- a/server/helpers/custom-validators/remote/videos.js +++ /dev/null @@ -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 -} diff --git a/server/helpers/custom-validators/remote/videos.ts b/server/helpers/custom-validators/remote/videos.ts new file mode 100644 index 000000000..4b904d011 --- /dev/null +++ b/server/helpers/custom-validators/remote/videos.ts @@ -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 +} diff --git a/server/helpers/custom-validators/users.js b/server/helpers/custom-validators/users.ts similarity index 61% rename from server/helpers/custom-validators/users.js rename to server/helpers/custom-validators/users.ts index 2fc026e98..8fd2dac4f 100644 --- a/server/helpers/custom-validators/users.js +++ b/server/helpers/custom-validators/users.ts @@ -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 +} diff --git a/server/helpers/custom-validators/videos.js b/server/helpers/custom-validators/videos.ts similarity index 76% rename from server/helpers/custom-validators/videos.js rename to server/helpers/custom-validators/videos.ts index 196731e04..2b2370be4 100644 --- a/server/helpers/custom-validators/videos.js +++ b/server/helpers/custom-validators/videos.ts @@ -1,43 +1,24 @@ -'use strict' - -const validator = require('express-validator').validator -const values = require('lodash/values') - -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 -} +import { values } from 'lodash' +import expressValidator = require('express-validator') +// TODO: use .validator when express-validator typing will have validator field +const validator = expressValidator['validator'] + +import { + CONSTRAINTS_FIELDS, + VIDEO_CATEGORIES, + VIDEO_LICENCES, + VIDEO_LANGUAGES, + VIDEO_RATE_TYPES +} from '../../initializers' +import { isUserUsernameValid } from './users' +import { isArray } from './misc' + +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 +} diff --git a/server/helpers/database-utils.js b/server/helpers/database-utils.ts similarity index 89% rename from server/helpers/database-utils.js rename to server/helpers/database-utils.ts index c72d19429..b842ab9ec 100644 --- a/server/helpers/database-utils.js +++ b/server/helpers/database-utils.ts @@ -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 +} diff --git a/server/helpers/index.ts b/server/helpers/index.ts new file mode 100644 index 000000000..e56bd21ad --- /dev/null +++ b/server/helpers/index.ts @@ -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' diff --git a/server/helpers/logger.js b/server/helpers/logger.ts similarity index 57% rename from server/helpers/logger.js rename to server/helpers/logger.ts index 281acedb8..3c35e41e0 100644 --- a/server/helpers/logger.js +++ b/server/helpers/logger.ts @@ -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 } diff --git a/server/helpers/peertube-crypto.js b/server/helpers/peertube-crypto.ts similarity index 70% rename from server/helpers/peertube-crypto.js rename to server/helpers/peertube-crypto.ts index 55ae6fab3..a4e9672e6 100644 --- a/server/helpers/peertube-crypto.js +++ b/server/helpers/peertube-crypto.ts @@ -1,26 +1,21 @@ -'use strict' - -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 crypto = require('crypto') +import bcrypt = require('bcrypt') +import fs = require('fs') +import openssl = require('openssl-wrapper') +import { join } from 'path' + +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, diff --git a/server/helpers/requests.js b/server/helpers/requests.ts similarity index 63% rename from server/helpers/requests.js rename to server/helpers/requests.ts index efe056937..8ded52972 100644 --- a/server/helpers/requests.js +++ b/server/helpers/requests.ts @@ -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 +} diff --git a/server/helpers/utils.js b/server/helpers/utils.ts similarity index 84% rename from server/helpers/utils.js rename to server/helpers/utils.ts index 6d40e8f3f..09c35a533 100644 --- a/server/helpers/utils.js +++ b/server/helpers/utils.ts @@ -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 +} diff --git a/server/initializers/checker.js b/server/initializers/checker.ts similarity index 90% rename from server/initializers/checker.js rename to server/initializers/checker.ts index aa8dea4bf..370dff2d4 100644 --- a/server/initializers/checker.js +++ b/server/initializers/checker.ts @@ -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 +} diff --git a/server/initializers/constants.js b/server/initializers/constants.ts similarity index 84% rename from server/initializers/constants.js rename to server/initializers/constants.ts index 87e9c8002..6bdc261ad 100644 --- a/server/initializers/constants.js +++ b/server/initializers/constants.ts @@ -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('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('database.suffix'), + HOSTNAME: config.get('database.hostname'), + PORT: config.get('database.port'), + USERNAME: config.get('database.username'), + PASSWORD: config.get('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('storage.certs')), + LOG_DIR: join(__dirname, '..', '..', config.get('storage.logs')), + VIDEOS_DIR: join(__dirname, '..', '..', config.get('storage.videos')), + THUMBNAILS_DIR: join(__dirname, '..', '..', config.get('storage.thumbnails')), + PREVIEWS_DIR: join(__dirname, '..', '..', config.get('storage.previews')), + TORRENTS_DIR: join(__dirname, '..', '..', config.get('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('webserver.https') === true ? 'https' : 'http', + WS: config.get('webserver.https') === true ? 'wss' : 'ws', + HOSTNAME: config.get('webserver.hostname'), + PORT: config.get('webserver.port'), + URL: '', + HOST: '' }, ADMIN: { - EMAIL: config.get('admin.email') + EMAIL: config.get('admin.email') }, SIGNUP: { - ENABLED: config.get('signup.enabled') + ENABLED: config.get('signup.enabled') }, TRANSCODING: { - ENABLED: config.get('transcoding.enabled'), - THREADS: config.get('transcoding.threads') + ENABLED: config.get('transcoding.enabled'), + THREADS: config.get('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, diff --git a/server/initializers/database.js b/server/initializers/database.ts similarity index 52% rename from server/initializers/database.js rename to server/initializers/database.ts index 043152a0e..753a06669 100644 --- a/server/initializers/database.js +++ b/server/initializers/database.ts @@ -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 diff --git a/server/initializers/index.ts b/server/initializers/index.ts new file mode 100644 index 000000000..b8400ff84 --- /dev/null +++ b/server/initializers/index.ts @@ -0,0 +1,6 @@ +// Constants first, databse in second! +export * from './constants' +export * from './database' +export * from './checker' +export * from './installer' +export * from './migrator' diff --git a/server/initializers/installer.js b/server/initializers/installer.ts similarity index 75% rename from server/initializers/installer.js rename to server/initializers/installer.ts index 837a987dd..cd1404d48 100644 --- a/server/initializers/installer.js +++ b/server/initializers/installer.ts @@ -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) }) }) } diff --git a/server/initializers/migrations/0005-email-pod.js b/server/initializers/migrations/0005-email-pod.ts similarity index 86% rename from server/initializers/migrations/0005-email-pod.js rename to server/initializers/migrations/0005-email-pod.ts index 9bbb354bf..a9200c47f 100644 --- a/server/initializers/migrations/0005-email-pod.js +++ b/server/initializers/migrations/0005-email-pod.ts @@ -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 +} diff --git a/server/initializers/migrations/0010-email-user.js b/server/initializers/migrations/0010-email-user.ts similarity index 86% rename from server/initializers/migrations/0010-email-user.js rename to server/initializers/migrations/0010-email-user.ts index 1ab27133a..4b5d29394 100644 --- a/server/initializers/migrations/0010-email-user.js +++ b/server/initializers/migrations/0010-email-user.ts @@ -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 +} diff --git a/server/initializers/migrations/0015-video-views.js b/server/initializers/migrations/0015-video-views.ts similarity index 77% rename from server/initializers/migrations/0015-video-views.js rename to server/initializers/migrations/0015-video-views.ts index ae49fe73c..e70869404 100644 --- a/server/initializers/migrations/0015-video-views.js +++ b/server/initializers/migrations/0015-video-views.ts @@ -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 +} diff --git a/server/initializers/migrations/0020-video-likes.js b/server/initializers/migrations/0020-video-likes.ts similarity index 77% rename from server/initializers/migrations/0020-video-likes.js rename to server/initializers/migrations/0020-video-likes.ts index 6db62cb90..e435d0657 100644 --- a/server/initializers/migrations/0020-video-likes.js +++ b/server/initializers/migrations/0020-video-likes.ts @@ -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 +} diff --git a/server/initializers/migrations/0025-video-dislikes.js b/server/initializers/migrations/0025-video-dislikes.ts similarity index 78% rename from server/initializers/migrations/0025-video-dislikes.js rename to server/initializers/migrations/0025-video-dislikes.ts index 40d2e7351..57e54e904 100644 --- a/server/initializers/migrations/0025-video-dislikes.js +++ b/server/initializers/migrations/0025-video-dislikes.ts @@ -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 +} diff --git a/server/initializers/migrations/0030-video-category.js b/server/initializers/migrations/0030-video-category.ts similarity index 82% rename from server/initializers/migrations/0030-video-category.js rename to server/initializers/migrations/0030-video-category.ts index ada95b2fe..1073f449c 100644 --- a/server/initializers/migrations/0030-video-category.js +++ b/server/initializers/migrations/0030-video-category.ts @@ -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 +} diff --git a/server/initializers/migrations/0035-video-licence.js b/server/initializers/migrations/0035-video-licence.ts similarity index 82% rename from server/initializers/migrations/0035-video-licence.js rename to server/initializers/migrations/0035-video-licence.ts index 9cf75858d..9316b3c37 100644 --- a/server/initializers/migrations/0035-video-licence.js +++ b/server/initializers/migrations/0035-video-licence.ts @@ -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 +} diff --git a/server/initializers/migrations/0040-video-nsfw.js b/server/initializers/migrations/0040-video-nsfw.ts similarity index 81% rename from server/initializers/migrations/0040-video-nsfw.js rename to server/initializers/migrations/0040-video-nsfw.ts index 7f3692b28..c61f496f1 100644 --- a/server/initializers/migrations/0040-video-nsfw.js +++ b/server/initializers/migrations/0040-video-nsfw.ts @@ -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 +} diff --git a/server/initializers/migrations/0045-user-display-nsfw.js b/server/initializers/migrations/0045-user-display-nsfw.ts similarity index 78% rename from server/initializers/migrations/0045-user-display-nsfw.js rename to server/initializers/migrations/0045-user-display-nsfw.ts index 03624e593..1ca317795 100644 --- a/server/initializers/migrations/0045-user-display-nsfw.js +++ b/server/initializers/migrations/0045-user-display-nsfw.ts @@ -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 +} diff --git a/server/initializers/migrations/0050-video-language.js b/server/initializers/migrations/0050-video-language.ts similarity index 78% rename from server/initializers/migrations/0050-video-language.js rename to server/initializers/migrations/0050-video-language.ts index 1c978758d..95d0a473a 100644 --- a/server/initializers/migrations/0050-video-language.js +++ b/server/initializers/migrations/0050-video-language.ts @@ -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 +} diff --git a/server/initializers/migrator.js b/server/initializers/migrator.ts similarity index 88% rename from server/initializers/migrator.js rename to server/initializers/migrator.ts index 9a6415b1a..cfa3220e0 100644 --- a/server/initializers/migrator.js +++ b/server/initializers/migrator.ts @@ -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 +} // --------------------------------------------------------------------------- diff --git a/server/lib/friends.js b/server/lib/friends.ts similarity index 79% rename from server/lib/friends.js rename to server/lib/friends.ts index 6dd32406c..b32783019 100644 --- a/server/lib/friends.js +++ b/server/lib/friends.ts @@ -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') - -const ENDPOINT_ACTIONS = constants.REQUEST_ENDPOINT_ACTIONS[constants.REQUEST_ENDPOINTS.VIDEOS] +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 = 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 } diff --git a/server/lib/index.ts b/server/lib/index.ts new file mode 100644 index 000000000..b8697fb96 --- /dev/null +++ b/server/lib/index.ts @@ -0,0 +1,4 @@ +export * from './jobs' +export * from './request' +export * from './friends' +export * from './oauth-model' diff --git a/server/lib/jobs/handlers/index.js b/server/lib/jobs/handlers/index.js deleted file mode 100644 index 59c1ccce5..000000000 --- a/server/lib/jobs/handlers/index.js +++ /dev/null @@ -1,7 +0,0 @@ -'use strict' - -const videoTranscoder = require('./video-transcoder') - -module.exports = { - videoTranscoder -} diff --git a/server/lib/jobs/handlers/index.ts b/server/lib/jobs/handlers/index.ts new file mode 100644 index 000000000..ae5440031 --- /dev/null +++ b/server/lib/jobs/handlers/index.ts @@ -0,0 +1,9 @@ +import * as videoTranscoder from './video-transcoder' + +const jobHandlers = { + videoTranscoder +} + +export { + jobHandlers +} diff --git a/server/lib/jobs/handlers/video-transcoder.js b/server/lib/jobs/handlers/video-transcoder.ts similarity index 71% rename from server/lib/jobs/handlers/video-transcoder.js rename to server/lib/jobs/handlers/video-transcoder.ts index d2ad4f9c7..35db5fb96 100644 --- a/server/lib/jobs/handlers/video-transcoder.js +++ b/server/lib/jobs/handlers/video-transcoder.ts @@ -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 +} diff --git a/server/lib/jobs/index.ts b/server/lib/jobs/index.ts new file mode 100644 index 000000000..b18a3d845 --- /dev/null +++ b/server/lib/jobs/index.ts @@ -0,0 +1 @@ +export * from './job-scheduler' diff --git a/server/lib/jobs/job-scheduler.js b/server/lib/jobs/job-scheduler.js deleted file mode 100644 index 7b239577f..000000000 --- a/server/lib/jobs/job-scheduler.js +++ /dev/null @@ -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) -} diff --git a/server/lib/jobs/job-scheduler.ts b/server/lib/jobs/job-scheduler.ts new file mode 100644 index 000000000..7b8c6faf9 --- /dev/null +++ b/server/lib/jobs/job-scheduler.ts @@ -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 +} diff --git a/server/lib/oauth-model.js b/server/lib/oauth-model.ts similarity index 96% rename from server/lib/oauth-model.js rename to server/lib/oauth-model.ts index 1c12f1b14..00b1afcf5 100644 --- a/server/lib/oauth-model.js +++ b/server/lib/oauth-model.ts @@ -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 +} diff --git a/server/lib/request/base-request-scheduler.js b/server/lib/request/base-request-scheduler.ts similarity index 72% rename from server/lib/request/base-request-scheduler.js rename to server/lib/request/base-request-scheduler.ts index 782448340..7fc88b5f1 100644 --- a/server/lib/request/base-request-scheduler.js +++ b/server/lib/request/base-request-scheduler.ts @@ -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') - -module.exports = class BaseRequestScheduler { - constructor (options) { +import { logger, makeSecureRequest } from '../../helpers' +import { + API_VERSION, + REQUESTS_IN_PARALLEL, + REQUESTS_INTERVAL +} from '../../initializers' + +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 +} diff --git a/server/lib/request/index.ts b/server/lib/request/index.ts new file mode 100644 index 000000000..c98f956db --- /dev/null +++ b/server/lib/request/index.ts @@ -0,0 +1,3 @@ +export * from './request-scheduler' +export * from './request-video-event-scheduler' +export * from './request-video-qadu-scheduler' diff --git a/server/lib/request/request-scheduler.js b/server/lib/request/request-scheduler.ts similarity index 83% rename from server/lib/request/request-scheduler.js rename to server/lib/request/request-scheduler.ts index 555ec3e54..2006a6f03 100644 --- a/server/lib/request/request-scheduler.js +++ b/server/lib/request/request-scheduler.ts @@ -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') - -module.exports = class RequestScheduler extends BaseRequestScheduler { +import { BaseRequestScheduler } from './base-request-scheduler' +import { logger } from '../../helpers' +import { + REQUESTS_LIMIT_PODS, + REQUESTS_LIMIT_PER_POD +} from '../../initializers' + +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 +} diff --git a/server/lib/request/request-video-event-scheduler.js b/server/lib/request/request-video-event-scheduler.ts similarity index 81% rename from server/lib/request/request-video-event-scheduler.js rename to server/lib/request/request-video-event-scheduler.ts index e54d34f4a..6e5306c7d 100644 --- a/server/lib/request/request-video-event-scheduler.js +++ b/server/lib/request/request-video-event-scheduler.ts @@ -1,16 +1,18 @@ -'use strict' - -const BaseRequestScheduler = require('./base-request-scheduler') -const constants = require('../../initializers/constants') const db = require('../../initializers/database') - -module.exports = class RequestVideoEventScheduler extends BaseRequestScheduler { +import { BaseRequestScheduler } from './base-request-scheduler' +import { + REQUESTS_VIDEO_EVENT_LIMIT_PODS, + REQUESTS_VIDEO_EVENT_LIMIT_PER_POD, + REQUEST_VIDEO_EVENT_ENDPOINT +} from '../../initializers' + +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 +} diff --git a/server/lib/request/request-video-qadu-scheduler.js b/server/lib/request/request-video-qadu-scheduler.ts similarity index 78% rename from server/lib/request/request-video-qadu-scheduler.js rename to server/lib/request/request-video-qadu-scheduler.ts index 17402b556..d81822723 100644 --- a/server/lib/request/request-video-qadu-scheduler.js +++ b/server/lib/request/request-video-qadu-scheduler.ts @@ -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') - -module.exports = class RequestVideoQaduScheduler extends BaseRequestScheduler { +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' + +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 +} diff --git a/server/middlewares/admin.js b/server/middlewares/admin.ts similarity index 84% rename from server/middlewares/admin.js rename to server/middlewares/admin.ts index 3288f4c6b..ebafa36a4 100644 --- a/server/middlewares/admin.js +++ b/server/middlewares/admin.ts @@ -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 +} diff --git a/server/middlewares/index.js b/server/middlewares/index.js deleted file mode 100644 index 3f253e31b..000000000 --- a/server/middlewares/index.js +++ /dev/null @@ -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 diff --git a/server/middlewares/index.ts b/server/middlewares/index.ts new file mode 100644 index 000000000..2c1c5fa53 --- /dev/null +++ b/server/middlewares/index.ts @@ -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'; diff --git a/server/middlewares/oauth.js b/server/middlewares/oauth.ts similarity index 88% rename from server/middlewares/oauth.js rename to server/middlewares/oauth.ts index 3a02b9b48..31ae1e000 100644 --- a/server/middlewares/oauth.js +++ b/server/middlewares/oauth.ts @@ -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 +} diff --git a/server/middlewares/pagination.js b/server/middlewares/pagination.ts similarity index 84% rename from server/middlewares/pagination.js rename to server/middlewares/pagination.ts index a90f60aab..8fe9f9082 100644 --- a/server/middlewares/pagination.js +++ b/server/middlewares/pagination.ts @@ -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 +} diff --git a/server/middlewares/pods.js b/server/middlewares/pods.ts similarity index 95% rename from server/middlewares/pods.js rename to server/middlewares/pods.ts index 2647f9ff0..e405f265e 100644 --- a/server/middlewares/pods.js +++ b/server/middlewares/pods.ts @@ -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 +} // --------------------------------------------------------------------------- diff --git a/server/middlewares/search.js b/server/middlewares/search.ts similarity index 73% rename from server/middlewares/search.js rename to server/middlewares/search.ts index bb88faf54..05a2e7442 100644 --- a/server/middlewares/search.js +++ b/server/middlewares/search.ts @@ -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 +} diff --git a/server/middlewares/secure.js b/server/middlewares/secure.ts similarity index 94% rename from server/middlewares/secure.js rename to server/middlewares/secure.ts index 7c5c72508..ee8545028 100644 --- a/server/middlewares/secure.js +++ b/server/middlewares/secure.ts @@ -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 +} diff --git a/server/middlewares/sort.js b/server/middlewares/sort.ts similarity index 87% rename from server/middlewares/sort.js rename to server/middlewares/sort.ts index 39e167265..ab9ccf524 100644 --- a/server/middlewares/sort.js +++ b/server/middlewares/sort.ts @@ -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 +} diff --git a/server/middlewares/validators/index.js b/server/middlewares/validators/index.js deleted file mode 100644 index 6c3a9c2b4..000000000 --- a/server/middlewares/validators/index.js +++ /dev/null @@ -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 diff --git a/server/middlewares/validators/index.ts b/server/middlewares/validators/index.ts new file mode 100644 index 000000000..42ba465ec --- /dev/null +++ b/server/middlewares/validators/index.ts @@ -0,0 +1,6 @@ +export * from './remote' +export * from './pagination' +export * from './pods' +export * from './sort' +export * from './users' +export * from './videos' diff --git a/server/middlewares/validators/pagination.js b/server/middlewares/validators/pagination.ts similarity index 59% rename from server/middlewares/validators/pagination.js rename to server/middlewares/validators/pagination.ts index 16682696e..de719c05b 100644 --- a/server/middlewares/validators/pagination.js +++ b/server/middlewares/validators/pagination.ts @@ -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 +} diff --git a/server/middlewares/validators/pods.js b/server/middlewares/validators/pods.ts similarity index 69% rename from server/middlewares/validators/pods.js rename to server/middlewares/validators/pods.ts index 0bf4b1844..fbfd268d0 100644 --- a/server/middlewares/validators/pods.js +++ b/server/middlewares/validators/pods.ts @@ -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') - -const validatorsPod = { - makeFriends, - podsAdd -} +import { checkErrors } from './utils' +import { logger } from '../../helpers' +import { CONFIG } from '../../initializers' +import { hasFriends } from '../../lib' +import { isTestInstance } from '../../helpers' -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 +} diff --git a/server/middlewares/validators/remote/index.js b/server/middlewares/validators/remote/index.js deleted file mode 100644 index 022a2fe50..000000000 --- a/server/middlewares/validators/remote/index.js +++ /dev/null @@ -1,13 +0,0 @@ -'use strict' - -const remoteSignatureValidators = require('./signature') -const remoteVideosValidators = require('./videos') - -const validators = { - signature: remoteSignatureValidators, - videos: remoteVideosValidators -} - -// --------------------------------------------------------------------------- - -module.exports = validators diff --git a/server/middlewares/validators/remote/index.ts b/server/middlewares/validators/remote/index.ts new file mode 100644 index 000000000..d0d7740b1 --- /dev/null +++ b/server/middlewares/validators/remote/index.ts @@ -0,0 +1,2 @@ +export * from './signature' +export * from './videos' diff --git a/server/middlewares/validators/remote/signature.js b/server/middlewares/validators/remote/signature.ts similarity index 59% rename from server/middlewares/validators/remote/signature.js rename to server/middlewares/validators/remote/signature.ts index 002232c05..6e3ebe7db 100644 --- a/server/middlewares/validators/remote/signature.js +++ b/server/middlewares/validators/remote/signature.ts @@ -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 +} diff --git a/server/middlewares/validators/remote/videos.js b/server/middlewares/validators/remote/videos.ts similarity index 61% rename from server/middlewares/validators/remote/videos.js rename to server/middlewares/validators/remote/videos.ts index f2c6cba5e..3380c29e2 100644 --- a/server/middlewares/validators/remote/videos.js +++ b/server/middlewares/validators/remote/videos.ts @@ -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 +} diff --git a/server/middlewares/validators/sort.js b/server/middlewares/validators/sort.ts similarity index 55% rename from server/middlewares/validators/sort.js rename to server/middlewares/validators/sort.ts index 017d266e6..ebc7333c7 100644 --- a/server/middlewares/validators/sort.js +++ b/server/middlewares/validators/sort.ts @@ -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 +} // --------------------------------------------------------------------------- diff --git a/server/middlewares/validators/users.js b/server/middlewares/validators/users.ts similarity index 85% rename from server/middlewares/validators/users.js rename to server/middlewares/validators/users.ts index 1e7a64793..a9149fe1b 100644 --- a/server/middlewares/validators/users.js +++ b/server/middlewares/validators/users.ts @@ -1,17 +1,8 @@ -'use strict' - -const checkErrors = require('./utils').checkErrors const db = require('../../initializers/database') -const logger = require('../../helpers/logger') - -const validatorsUsers = { - usersAdd, - usersRemove, - usersUpdate, - usersVideoRating -} +import { checkErrors } from './utils' +import { logger } from '../../helpers' -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 +} diff --git a/server/middlewares/validators/utils.js b/server/middlewares/validators/utils.ts similarity index 61% rename from server/middlewares/validators/utils.js rename to server/middlewares/validators/utils.ts index 3741b84c6..710e65529 100644 --- a/server/middlewares/validators/utils.js +++ b/server/middlewares/validators/utils.ts @@ -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 +} diff --git a/server/middlewares/validators/videos.js b/server/middlewares/validators/videos.ts similarity index 85% rename from server/middlewares/validators/videos.js rename to server/middlewares/validators/videos.ts index f18ca1597..5a49cf73c 100644 --- a/server/middlewares/validators/videos.js +++ b/server/middlewares/validators/videos.ts @@ -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') - -const validatorsVideos = { - videosAdd, - videosUpdate, - videosGet, - videosRemove, - videosSearch, - - videoAbuseReport, - - videoRate, - - videosBlacklist -} +import { checkErrors } from './utils' +import { CONSTRAINTS_FIELDS, SEARCHABLE_COLUMNS } from '../../initializers' +import { logger, isVideoDurationValid } from '../../helpers' -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 +} // --------------------------------------------------------------------------- diff --git a/server/models/application.js b/server/models/application.ts similarity index 94% rename from server/models/application.js rename to server/models/application.ts index 64e1a0540..38a57e327 100644 --- a/server/models/application.js +++ b/server/models/application.ts @@ -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: {} } diff --git a/server/models/author.js b/server/models/author.ts similarity index 89% rename from server/models/author.js rename to server/models/author.ts index 34b013097..4a7396929 100644 --- a/server/models/author.js +++ b/server/models/author.ts @@ -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 } diff --git a/server/models/job.js b/server/models/job.ts similarity index 83% rename from server/models/job.js rename to server/models/job.ts index 949f88d44..6843e399b 100644 --- a/server/models/job.js +++ b/server/models/job.ts @@ -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: { diff --git a/server/models/oauth-client.js b/server/models/oauth-client.ts similarity index 98% rename from server/models/oauth-client.js rename to server/models/oauth-client.ts index 021a34007..3198a85ef 100644 --- a/server/models/oauth-client.js +++ b/server/models/oauth-client.ts @@ -1,5 +1,3 @@ -'use strict' - module.exports = function (sequelize, DataTypes) { const OAuthClient = sequelize.define('OAuthClient', { diff --git a/server/models/oauth-token.js b/server/models/oauth-token.ts similarity index 97% rename from server/models/oauth-token.js rename to server/models/oauth-token.ts index 68e7c9ff7..74c9180eb 100644 --- a/server/models/oauth-token.js +++ b/server/models/oauth-token.ts @@ -1,6 +1,4 @@ -'use strict' - -const logger = require('../helpers/logger') +import { logger } from '../helpers' // --------------------------------------------------------------------------- diff --git a/server/models/pod.js b/server/models/pod.ts similarity index 88% rename from server/models/pod.js rename to server/models/pod.ts index 8e2d488e1..0e0262978 100644 --- a/server/models/pod.js +++ b/server/models/pod.ts @@ -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) diff --git a/server/models/request-to-pod.js b/server/models/request-to-pod.ts similarity index 83% rename from server/models/request-to-pod.js rename to server/models/request-to-pod.ts index 0e01a842e..479202e40 100644 --- a/server/models/request-to-pod.js +++ b/server/models/request-to-pod.ts @@ -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: { diff --git a/server/models/request-video-event.js b/server/models/request-video-event.ts similarity index 91% rename from server/models/request-video-event.js rename to server/models/request-video-event.ts index 9ebeaec90..c61525029 100644 --- a/server/models/request-video-event.js +++ b/server/models/request-video-event.ts @@ -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.') } } diff --git a/server/models/request-video-qadu.js b/server/models/request-video-qadu.ts similarity index 94% rename from server/models/request-video-qadu.js rename to server/models/request-video-qadu.ts index 5d88738aa..2b1ed07c9 100644 --- a/server/models/request-video-qadu.js +++ b/server/models/request-video-qadu.ts @@ -1,5 +1,3 @@ -'use strict' - /* Request Video for Quick And Dirty Updates like: - views @@ -11,9 +9,9 @@ So we put it an independant request scheduler. */ -const values = require('lodash/values') +import { values } from 'lodash' -const constants = require('../initializers/constants') +import { REQUEST_VIDEO_QADU_TYPES } from '../initializers' // --------------------------------------------------------------------------- @@ -21,7 +19,7 @@ module.exports = function (sequelize, DataTypes) { const RequestVideoQadu = sequelize.define('RequestVideoQadu', { type: { - type: DataTypes.ENUM(values(constants.REQUEST_VIDEO_QADU_TYPES)), + type: DataTypes.ENUM(values(REQUEST_VIDEO_QADU_TYPES)), allowNull: false } }, diff --git a/server/models/request.js b/server/models/request.ts similarity index 93% rename from server/models/request.js rename to server/models/request.ts index 3a047f7ee..672f79d11 100644 --- a/server/models/request.js +++ b/server/models/request.ts @@ -1,8 +1,6 @@ -'use strict' +import { values } from 'lodash' -const values = require('lodash/values') - -const constants = require('../initializers/constants') +import { REQUEST_ENDPOINTS } from '../initializers' // --------------------------------------------------------------------------- @@ -14,7 +12,7 @@ module.exports = function (sequelize, DataTypes) { allowNull: false }, endpoint: { - type: DataTypes.ENUM(values(constants.REQUEST_ENDPOINTS)), + type: DataTypes.ENUM(values(REQUEST_ENDPOINTS)), allowNull: false } }, @@ -100,7 +98,7 @@ function removeAll (callback) { } function removeWithEmptyTo (callback) { - if (!callback) callback = function () {} + if (!callback) callback = function () { /* empty */ } const query = { where: { diff --git a/server/models/tag.js b/server/models/tag.ts similarity index 95% rename from server/models/tag.js rename to server/models/tag.ts index 145e090c1..85a0442d2 100644 --- a/server/models/tag.js +++ b/server/models/tag.ts @@ -1,6 +1,4 @@ -'use strict' - -const each = require('async/each') +import { each } from 'async' // --------------------------------------------------------------------------- @@ -51,7 +49,7 @@ function findOrCreateTags (tags, transaction, callback) { const tagInstances = [] each(tags, function (tag, callbackEach) { - const query = { + const query: any = { where: { name: tag }, diff --git a/server/models/user-video-rate.js b/server/models/user-video-rate.ts similarity index 85% rename from server/models/user-video-rate.js rename to server/models/user-video-rate.ts index 84007d70c..6603c7862 100644 --- a/server/models/user-video-rate.js +++ b/server/models/user-video-rate.ts @@ -1,13 +1,10 @@ -'use strict' - /* User rates per video. */ +import { values } from 'lodash' -const values = require('lodash/values') - -const constants = require('../initializers/constants') +import { VIDEO_RATE_TYPES } from '../initializers' // --------------------------------------------------------------------------- @@ -15,7 +12,7 @@ module.exports = function (sequelize, DataTypes) { const UserVideoRate = sequelize.define('UserVideoRate', { type: { - type: DataTypes.ENUM(values(constants.VIDEO_RATE_TYPES)), + type: DataTypes.ENUM(values(VIDEO_RATE_TYPES)), allowNull: false } }, @@ -70,7 +67,7 @@ function load (userId, videoId, transaction, callback) { } } - const options = {} + const options: any = {} if (transaction) options.transaction = transaction return this.findOne(query, options).asCallback(callback) diff --git a/server/models/user.js b/server/models/user.ts similarity index 81% rename from server/models/user.js rename to server/models/user.ts index 8f9c2bf65..d63a50cc4 100644 --- a/server/models/user.js +++ b/server/models/user.ts @@ -1,11 +1,14 @@ -'use strict' - -const values = require('lodash/values') - -const modelUtils = require('./utils') -const constants = require('../initializers/constants') -const peertubeCrypto = require('../helpers/peertube-crypto') -const customUsersValidators = require('../helpers/custom-validators').users +import { values } from 'lodash' + +import { getSort } from './utils' +import { USER_ROLES } from '../initializers' +import { + cryptPassword, + comparePassword, + isUserPasswordValid, + isUserUsernameValid, + isUserDisplayNSFWValid +} from '../helpers' // --------------------------------------------------------------------------- @@ -17,7 +20,7 @@ module.exports = function (sequelize, DataTypes) { allowNull: false, validate: { passwordValid: function (value) { - const res = customUsersValidators.isUserPasswordValid(value) + const res = isUserPasswordValid(value) if (res === false) throw new Error('Password not valid.') } } @@ -27,7 +30,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 not valid.') } } @@ -45,13 +48,13 @@ module.exports = function (sequelize, DataTypes) { defaultValue: false, validate: { nsfwValid: function (value) { - const res = customUsersValidators.isUserDisplayNSFWValid(value) + const res = isUserDisplayNSFWValid(value) if (res === false) throw new Error('Display NSFW is not valid.') } } }, role: { - type: DataTypes.ENUM(values(constants.USER_ROLES)), + type: DataTypes.ENUM(values(USER_ROLES)), allowNull: false } }, @@ -93,7 +96,7 @@ module.exports = function (sequelize, DataTypes) { } function beforeCreateOrUpdate (user, options, next) { - peertubeCrypto.cryptPassword(user.password, function (err, hash) { + cryptPassword(user.password, function (err, hash) { if (err) return next(err) user.password = hash @@ -105,7 +108,7 @@ function beforeCreateOrUpdate (user, options, next) { // ------------------------------ METHODS ------------------------------ function isPasswordMatch (password, callback) { - return peertubeCrypto.comparePassword(password, this.password, callback) + return comparePassword(password, this.password, callback) } function toFormatedJSON () { @@ -120,7 +123,7 @@ function toFormatedJSON () { } function isAdmin () { - return this.role === constants.USER_ROLES.ADMIN + return this.role === USER_ROLES.ADMIN } // ------------------------------ STATICS ------------------------------ @@ -159,7 +162,7 @@ function listForApi (start, count, sort, callback) { const query = { offset: start, limit: count, - order: [ modelUtils.getSort(sort) ] + order: [ getSort(sort) ] } return this.findAndCountAll(query).asCallback(function (err, result) { diff --git a/server/models/utils.js b/server/models/utils.ts similarity index 87% rename from server/models/utils.js rename to server/models/utils.ts index 49636b3d8..601811913 100644 --- a/server/models/utils.js +++ b/server/models/utils.ts @@ -1,9 +1,3 @@ -'use strict' - -const utils = { - getSort -} - // Translate for example "-name" to [ 'name', 'DESC' ] function getSort (value) { let field @@ -22,4 +16,6 @@ function getSort (value) { // --------------------------------------------------------------------------- -module.exports = utils +export { + getSort +} diff --git a/server/models/video-abuse.js b/server/models/video-abuse.ts similarity index 82% rename from server/models/video-abuse.js rename to server/models/video-abuse.ts index 67cead3af..2a18a293d 100644 --- a/server/models/video-abuse.js +++ b/server/models/video-abuse.ts @@ -1,8 +1,6 @@ -'use strict' - -const constants = require('../initializers/constants') -const modelUtils = require('./utils') -const customVideosValidators = require('../helpers/custom-validators').videos +import { CONFIG } from '../initializers' +import { isVideoAbuseReporterUsernameValid, isVideoAbuseReasonValid } from '../helpers' +import { getSort } from './utils' module.exports = function (sequelize, DataTypes) { const VideoAbuse = sequelize.define('VideoAbuse', @@ -12,7 +10,7 @@ module.exports = function (sequelize, DataTypes) { allowNull: false, validate: { reporterUsernameValid: function (value) { - const res = customVideosValidators.isVideoAbuseReporterUsernameValid(value) + const res = isVideoAbuseReporterUsernameValid(value) if (res === false) throw new Error('Video abuse reporter username is not valid.') } } @@ -22,7 +20,7 @@ module.exports = function (sequelize, DataTypes) { allowNull: false, validate: { reasonValid: function (value) { - const res = customVideosValidators.isVideoAbuseReasonValid(value) + const res = isVideoAbuseReasonValid(value) if (res === false) throw new Error('Video abuse reason is not valid.') } } @@ -75,7 +73,7 @@ function listForApi (start, count, sort, callback) { const query = { offset: start, limit: count, - order: [ modelUtils.getSort(sort) ], + order: [ getSort(sort) ], include: [ { model: this.sequelize.models.Pod, @@ -98,7 +96,7 @@ function toFormatedJSON () { reporterPodHost = this.Pod.host } else { // It means it's our video - reporterPodHost = constants.CONFIG.WEBSERVER.HOST + reporterPodHost = CONFIG.WEBSERVER.HOST } const json = { diff --git a/server/models/video-blacklist.js b/server/models/video-blacklist.ts similarity index 94% rename from server/models/video-blacklist.js rename to server/models/video-blacklist.ts index 02ea15760..1f00702c7 100644 --- a/server/models/video-blacklist.js +++ b/server/models/video-blacklist.ts @@ -1,6 +1,4 @@ -'use strict' - -const modelUtils = require('./utils') +import { getSort } from './utils' // --------------------------------------------------------------------------- @@ -64,7 +62,7 @@ function listForApi (start, count, sort, callback) { const query = { offset: start, limit: count, - order: [ modelUtils.getSort(sort) ] + order: [ getSort(sort) ] } return this.findAndCountAll(query).asCallback(function (err, result) { diff --git a/server/models/video-tag.js b/server/models/video-tag.ts similarity index 72% rename from server/models/video-tag.js rename to server/models/video-tag.ts index cd9277a6e..83ff6053f 100644 --- a/server/models/video-tag.js +++ b/server/models/video-tag.ts @@ -1,7 +1,3 @@ -'use strict' - -// --------------------------------------------------------------------------- - module.exports = function (sequelize, DataTypes) { const VideoTag = sequelize.define('VideoTag', {}, { indexes: [ diff --git a/server/models/video.js b/server/models/video.ts similarity index 79% rename from server/models/video.js rename to server/models/video.ts index da4ddb420..1e29f1355 100644 --- a/server/models/video.js +++ b/server/models/video.ts @@ -1,24 +1,38 @@ -'use strict' - -const Buffer = require('safe-buffer').Buffer -const createTorrent = require('create-torrent') -const ffmpeg = require('fluent-ffmpeg') -const fs = require('fs') -const magnetUtil = require('magnet-uri') -const map = require('lodash/map') -const parallel = require('async/parallel') -const series = require('async/series') -const parseTorrent = require('parse-torrent') -const pathUtils = require('path') -const values = require('lodash/values') - -const constants = require('../initializers/constants') -const logger = require('../helpers/logger') -const friends = require('../lib/friends') -const modelUtils = require('./utils') -const customVideosValidators = require('../helpers/custom-validators').videos +import safeBuffer = require('safe-buffer') +const Buffer = safeBuffer.Buffer +import createTorrent = require('create-torrent') +import ffmpeg = require('fluent-ffmpeg') +import fs = require('fs') +import magnetUtil = require('magnet-uri') +import { map, values } from 'lodash' +import { parallel, series } from 'async' +import parseTorrent = require('parse-torrent') +import { join } from 'path' + const db = require('../initializers/database') -const jobScheduler = require('../lib/jobs/job-scheduler') +import { + logger, + isVideoNameValid, + isVideoCategoryValid, + isVideoLicenceValid, + isVideoLanguageValid, + isVideoNSFWValid, + isVideoDescriptionValid, + isVideoInfoHashValid, + isVideoDurationValid +} from '../helpers' +import { + CONSTRAINTS_FIELDS, + CONFIG, + REMOTE_SCHEME, + STATIC_PATHS, + VIDEO_CATEGORIES, + VIDEO_LICENCES, + VIDEO_LANGUAGES, + THUMBNAILS_SIZE +} from '../initializers' +import { JobScheduler, removeVideoToFriends } from '../lib' +import { getSort } from './utils' // --------------------------------------------------------------------------- @@ -38,13 +52,13 @@ module.exports = function (sequelize, DataTypes) { allowNull: false, validate: { nameValid: function (value) { - const res = customVideosValidators.isVideoNameValid(value) + const res = isVideoNameValid(value) if (res === false) throw new Error('Video name is not valid.') } } }, extname: { - type: DataTypes.ENUM(values(constants.CONSTRAINTS_FIELDS.VIDEOS.EXTNAME)), + type: DataTypes.ENUM(values(CONSTRAINTS_FIELDS.VIDEOS.EXTNAME)), allowNull: false }, remoteId: { @@ -59,7 +73,7 @@ module.exports = function (sequelize, DataTypes) { allowNull: false, validate: { categoryValid: function (value) { - const res = customVideosValidators.isVideoCategoryValid(value) + const res = isVideoCategoryValid(value) if (res === false) throw new Error('Video category is not valid.') } } @@ -70,7 +84,7 @@ module.exports = function (sequelize, DataTypes) { defaultValue: null, validate: { licenceValid: function (value) { - const res = customVideosValidators.isVideoLicenceValid(value) + const res = isVideoLicenceValid(value) if (res === false) throw new Error('Video licence is not valid.') } } @@ -80,7 +94,7 @@ module.exports = function (sequelize, DataTypes) { allowNull: true, validate: { languageValid: function (value) { - const res = customVideosValidators.isVideoLanguageValid(value) + const res = isVideoLanguageValid(value) if (res === false) throw new Error('Video language is not valid.') } } @@ -90,7 +104,7 @@ module.exports = function (sequelize, DataTypes) { allowNull: false, validate: { nsfwValid: function (value) { - const res = customVideosValidators.isVideoNSFWValid(value) + const res = isVideoNSFWValid(value) if (res === false) throw new Error('Video nsfw attribute is not valid.') } } @@ -100,7 +114,7 @@ module.exports = function (sequelize, DataTypes) { allowNull: false, validate: { descriptionValid: function (value) { - const res = customVideosValidators.isVideoDescriptionValid(value) + const res = isVideoDescriptionValid(value) if (res === false) throw new Error('Video description is not valid.') } } @@ -110,7 +124,7 @@ module.exports = function (sequelize, DataTypes) { allowNull: false, validate: { infoHashValid: function (value) { - const res = customVideosValidators.isVideoInfoHashValid(value) + const res = isVideoInfoHashValid(value) if (res === false) throw new Error('Video info hash is not valid.') } } @@ -120,7 +134,7 @@ module.exports = function (sequelize, DataTypes) { allowNull: false, validate: { durationValid: function (value) { - const res = customVideosValidators.isVideoDurationValid(value) + const res = isVideoDurationValid(value) if (res === false) throw new Error('Video duration is not valid.') } } @@ -233,7 +247,7 @@ function beforeCreate (video, options, next) { const tasks = [] if (video.isOwned()) { - const videoPath = pathUtils.join(constants.CONFIG.STORAGE.VIDEOS_DIR, video.getVideoFilename()) + const videoPath = join(CONFIG.STORAGE.VIDEOS_DIR, video.getVideoFilename()) tasks.push( function createVideoTorrent (callback) { @@ -249,14 +263,14 @@ function beforeCreate (video, options, next) { } ) - if (constants.CONFIG.TRANSCODING.ENABLED === true) { + if (CONFIG.TRANSCODING.ENABLED === true) { tasks.push( function createVideoTranscoderJob (callback) { const dataInput = { id: video.id } - jobScheduler.createJob(options.transaction, 'videoTranscoder', dataInput, callback) + JobScheduler.Instance.createJob(options.transaction, 'videoTranscoder', dataInput, callback) } ) } @@ -295,7 +309,7 @@ function afterDestroy (video, options, next) { remoteId: video.id } - friends.removeVideoToFriends(params) + removeVideoToFriends(params) return callback() } @@ -332,19 +346,20 @@ function associate (models) { } function generateMagnetUri () { - let baseUrlHttp, baseUrlWs + let baseUrlHttp + let baseUrlWs if (this.isOwned()) { - baseUrlHttp = constants.CONFIG.WEBSERVER.URL - baseUrlWs = constants.CONFIG.WEBSERVER.WS + '://' + constants.CONFIG.WEBSERVER.HOSTNAME + ':' + constants.CONFIG.WEBSERVER.PORT + baseUrlHttp = CONFIG.WEBSERVER.URL + baseUrlWs = CONFIG.WEBSERVER.WS + '://' + CONFIG.WEBSERVER.HOSTNAME + ':' + CONFIG.WEBSERVER.PORT } else { - baseUrlHttp = constants.REMOTE_SCHEME.HTTP + '://' + this.Author.Pod.host - baseUrlWs = constants.REMOTE_SCHEME.WS + '://' + this.Author.Pod.host + baseUrlHttp = REMOTE_SCHEME.HTTP + '://' + this.Author.Pod.host + baseUrlWs = REMOTE_SCHEME.WS + '://' + this.Author.Pod.host } - const xs = baseUrlHttp + constants.STATIC_PATHS.TORRENTS + this.getTorrentName() + const xs = baseUrlHttp + STATIC_PATHS.TORRENTS + this.getTorrentName() const announce = baseUrlWs + '/tracker/socket' - const urlList = [ baseUrlHttp + constants.STATIC_PATHS.WEBSEED + this.getVideoFilename() ] + const urlList = [ baseUrlHttp + STATIC_PATHS.WEBSEED + this.getVideoFilename() ] const magnetHash = { xs, @@ -395,19 +410,19 @@ function toFormatedJSON () { podHost = this.Author.Pod.host } else { // It means it's our video - podHost = constants.CONFIG.WEBSERVER.HOST + podHost = CONFIG.WEBSERVER.HOST } // Maybe our pod is not up to date and there are new categories since our version - let categoryLabel = constants.VIDEO_CATEGORIES[this.category] + let categoryLabel = VIDEO_CATEGORIES[this.category] if (!categoryLabel) categoryLabel = 'Misc' // Maybe our pod is not up to date and there are new licences since our version - let licenceLabel = constants.VIDEO_LICENCES[this.licence] + let licenceLabel = VIDEO_LICENCES[this.licence] if (!licenceLabel) licenceLabel = 'Unknown' // Language is an optional attribute - let languageLabel = constants.VIDEO_LANGUAGES[this.language] + let languageLabel = VIDEO_LANGUAGES[this.language] if (!languageLabel) languageLabel = 'Unknown' const json = { @@ -430,7 +445,7 @@ function toFormatedJSON () { likes: this.likes, dislikes: this.dislikes, tags: map(this.Tags, 'name'), - thumbnailPath: pathUtils.join(constants.STATIC_PATHS.THUMBNAILS, this.getThumbnailName()), + thumbnailPath: join(STATIC_PATHS.THUMBNAILS, this.getThumbnailName()), createdAt: this.createdAt, updatedAt: this.updatedAt } @@ -442,7 +457,7 @@ function toAddRemoteJSON (callback) { const self = this // Get thumbnail data to send to the other pod - const thumbnailPath = pathUtils.join(constants.CONFIG.STORAGE.THUMBNAILS_DIR, this.getThumbnailName()) + const thumbnailPath = join(CONFIG.STORAGE.THUMBNAILS_DIR, this.getThumbnailName()) fs.readFile(thumbnailPath, function (err, thumbnailData) { if (err) { logger.error('Cannot read the thumbnail of the video') @@ -501,15 +516,15 @@ function toUpdateRemoteJSON (callback) { function transcodeVideofile (finalCallback) { const video = this - const videosDirectory = constants.CONFIG.STORAGE.VIDEOS_DIR + const videosDirectory = CONFIG.STORAGE.VIDEOS_DIR const newExtname = '.mp4' - const videoInputPath = pathUtils.join(videosDirectory, video.getVideoFilename()) - const videoOutputPath = pathUtils.join(videosDirectory, video.id + '-transcoded' + newExtname) + const videoInputPath = join(videosDirectory, video.getVideoFilename()) + const videoOutputPath = join(videosDirectory, video.id + '-transcoded' + newExtname) ffmpeg(videoInputPath) .output(videoOutputPath) .videoCodec('libx264') - .outputOption('-threads ' + constants.CONFIG.TRANSCODING.THREADS) + .outputOption('-threads ' + CONFIG.TRANSCODING.THREADS) .outputOption('-movflags faststart') .on('error', finalCallback) .on('end', function () { @@ -522,12 +537,12 @@ function transcodeVideofile (finalCallback) { // Important to do this before getVideoFilename() to take in account the new file extension video.set('extname', newExtname) - const newVideoPath = pathUtils.join(videosDirectory, video.getVideoFilename()) + const newVideoPath = join(videosDirectory, video.getVideoFilename()) fs.rename(videoOutputPath, newVideoPath, callback) }, function torrent (callback) { - const newVideoPath = pathUtils.join(videosDirectory, video.getVideoFilename()) + const newVideoPath = join(videosDirectory, video.getVideoFilename()) createTorrentFromVideo(video, newVideoPath, callback) }, @@ -557,7 +572,7 @@ function generateThumbnailFromData (video, thumbnailData, callback) { // Creating the thumbnail for a remote video const thumbnailName = video.getThumbnailName() - const thumbnailPath = pathUtils.join(constants.CONFIG.STORAGE.THUMBNAILS_DIR, thumbnailName) + const thumbnailPath = join(CONFIG.STORAGE.THUMBNAILS_DIR, thumbnailName) fs.writeFile(thumbnailPath, Buffer.from(thumbnailData, 'binary'), function (err) { if (err) return callback(err) @@ -583,7 +598,7 @@ function listForApi (start, count, sort, callback) { offset: start, limit: count, distinct: true, // For the count, a video can have many tags - order: [ modelUtils.getSort(sort), [ this.sequelize.models.Tag, 'name', 'ASC' ] ], + order: [ getSort(sort), [ this.sequelize.models.Tag, 'name', 'ASC' ] ], include: [ { model: this.sequelize.models.Author, @@ -683,28 +698,28 @@ function loadAndPopulateAuthorAndPodAndTags (id, callback) { } function searchAndPopulateAuthorAndPodAndTags (value, field, start, count, sort, callback) { - const podInclude = { + const podInclude: any = { model: this.sequelize.models.Pod, required: false } - const authorInclude = { + const authorInclude: any = { model: this.sequelize.models.Author, include: [ podInclude ] } - const tagInclude = { + const tagInclude: any = { model: this.sequelize.models.Tag } - const query = { + const query: any = { where: createBaseVideosWhere.call(this), offset: start, limit: count, distinct: true, // For the count, a video can have many tags - order: [ modelUtils.getSort(sort), [ this.sequelize.models.Tag, 'name', 'ASC' ] ] + order: [ getSort(sort), [ this.sequelize.models.Tag, 'name', 'ASC' ] ] } // Make an exact search with the magnet @@ -766,39 +781,39 @@ function createBaseVideosWhere () { } function removeThumbnail (video, callback) { - const thumbnailPath = pathUtils.join(constants.CONFIG.STORAGE.THUMBNAILS_DIR, video.getThumbnailName()) + const thumbnailPath = join(CONFIG.STORAGE.THUMBNAILS_DIR, video.getThumbnailName()) fs.unlink(thumbnailPath, callback) } function removeFile (video, callback) { - const filePath = pathUtils.join(constants.CONFIG.STORAGE.VIDEOS_DIR, video.getVideoFilename()) + const filePath = join(CONFIG.STORAGE.VIDEOS_DIR, video.getVideoFilename()) fs.unlink(filePath, callback) } function removeTorrent (video, callback) { - const torrenPath = pathUtils.join(constants.CONFIG.STORAGE.TORRENTS_DIR, video.getTorrentName()) + const torrenPath = join(CONFIG.STORAGE.TORRENTS_DIR, video.getTorrentName()) fs.unlink(torrenPath, callback) } function removePreview (video, callback) { // Same name than video thumnail - fs.unlink(constants.CONFIG.STORAGE.PREVIEWS_DIR + video.getPreviewName(), callback) + fs.unlink(CONFIG.STORAGE.PREVIEWS_DIR + video.getPreviewName(), callback) } function createTorrentFromVideo (video, videoPath, callback) { const options = { announceList: [ - [ constants.CONFIG.WEBSERVER.WS + '://' + constants.CONFIG.WEBSERVER.HOSTNAME + ':' + constants.CONFIG.WEBSERVER.PORT + '/tracker/socket' ] + [ CONFIG.WEBSERVER.WS + '://' + CONFIG.WEBSERVER.HOSTNAME + ':' + CONFIG.WEBSERVER.PORT + '/tracker/socket' ] ], urlList: [ - constants.CONFIG.WEBSERVER.URL + constants.STATIC_PATHS.WEBSEED + video.getVideoFilename() + CONFIG.WEBSERVER.URL + STATIC_PATHS.WEBSEED + video.getVideoFilename() ] } createTorrent(videoPath, options, function (err, torrent) { if (err) return callback(err) - const filePath = pathUtils.join(constants.CONFIG.STORAGE.TORRENTS_DIR, video.getTorrentName()) + const filePath = join(CONFIG.STORAGE.TORRENTS_DIR, video.getTorrentName()) fs.writeFile(filePath, torrent, function (err) { if (err) return callback(err) @@ -810,15 +825,15 @@ function createTorrentFromVideo (video, videoPath, callback) { } function createPreview (video, videoPath, callback) { - generateImage(video, videoPath, constants.CONFIG.STORAGE.PREVIEWS_DIR, video.getPreviewName(), callback) + generateImage(video, videoPath, CONFIG.STORAGE.PREVIEWS_DIR, video.getPreviewName(), callback) } function createThumbnail (video, videoPath, callback) { - generateImage(video, videoPath, constants.CONFIG.STORAGE.THUMBNAILS_DIR, video.getThumbnailName(), constants.THUMBNAILS_SIZE, callback) + generateImage(video, videoPath, CONFIG.STORAGE.THUMBNAILS_DIR, video.getThumbnailName(), THUMBNAILS_SIZE, callback) } -function generateImage (video, videoPath, folder, imageName, size, callback) { - const options = { +function generateImage (video, videoPath, folder, imageName, size, callback?) { + const options: any = { filename: imageName, count: 1, folder diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 000000000..039881230 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,19 @@ +{ + "compilerOptions": { + "module": "commonjs", + "target": "es5", + "noImplicitAny": false, + "sourceMap": false, + "outDir": "./dist", + "lib": [ + "es2015" + ], + "types": [ + "node" + ] + }, + "exclude": [ + "node_modules", + "client" + ] +} diff --git a/tslint.json b/tslint.json new file mode 100644 index 000000000..888779856 --- /dev/null +++ b/tslint.json @@ -0,0 +1,3 @@ +{ + "extends": "tslint-config-standard" +} diff --git a/yarn.lock b/yarn.lock index 284cdb444..c0ce443b3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,34 +2,88 @@ # yarn lockfile v1 -"@types/bluebird@~3.0.36": +"@types/async@^2.0.40": + version "2.0.40" + resolved "https://registry.yarnpkg.com/@types/async/-/async-2.0.40.tgz#ac02de68e66c004a61b7cb16df8b1db3a254cca9" + +"@types/bcrypt@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@types/bcrypt/-/bcrypt-1.0.0.tgz#2c523da191db7d41c06d17de235335c985effe9b" + +"@types/bluebird@*", "@types/bluebird@~3.0.36": version "3.0.37" resolved "https://registry.yarnpkg.com/@types/bluebird/-/bluebird-3.0.37.tgz#2e76b394aa9bea40d04241a31c0887a260283388" +"@types/body-parser@^1.16.3": + version "1.16.3" + resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.16.3.tgz#bc2b9a181f2fa85c80f1ecacd8a05cf1414b85a3" + dependencies: + "@types/express" "*" + "@types/node" "*" + +"@types/config@^0.0.32": + version "0.0.32" + resolved "https://registry.yarnpkg.com/@types/config/-/config-0.0.32.tgz#c106055802d78e234e28374adc4dad460d098558" + "@types/express-serve-static-core@*": version "4.0.44" resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.0.44.tgz#a1c3bd5d80e93c72fba91a03f5412c47f21d4ae7" dependencies: "@types/node" "*" -"@types/express@~4.0.34": +"@types/express@*", "@types/express@^4.0.35", "@types/express@~4.0.34": version "4.0.35" resolved "https://registry.yarnpkg.com/@types/express/-/express-4.0.35.tgz#6267c7b60a51fac473467b3c4a02cd1e441805fe" dependencies: "@types/express-serve-static-core" "*" "@types/serve-static" "*" +"@types/form-data@*": + version "0.0.33" + resolved "https://registry.yarnpkg.com/@types/form-data/-/form-data-0.0.33.tgz#c9ac85b2a5fd18435b8c85d9ecb50e6d6c893ff8" + dependencies: + "@types/node" "*" + "@types/geojson@^1.0.0": version "1.0.2" resolved "https://registry.yarnpkg.com/@types/geojson/-/geojson-1.0.2.tgz#b02d10ab028e2928ac592a051aaa4981a1941d03" +"@types/lodash@*", "@types/lodash@^4.14.64": + version "4.14.64" + resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.64.tgz#979cf3a3d4a368670840bf9b3e448dc33ffe84ee" + "@types/mime@*": version "0.0.29" resolved "https://registry.yarnpkg.com/@types/mime/-/mime-0.0.29.tgz#fbcfd330573b912ef59eeee14602bface630754b" -"@types/node@*": - version "7.0.14" - resolved "https://registry.yarnpkg.com/@types/node/-/node-7.0.14.tgz#1470fa002a113316ac9d9ad163fc738c7a0de2a4" +"@types/mkdirp@^0.3.29": + version "0.3.29" + resolved "https://registry.yarnpkg.com/@types/mkdirp/-/mkdirp-0.3.29.tgz#7f2ad7ec55f914482fc9b1ec4bb1ae6028d46066" + +"@types/morgan@^1.7.32": + version "1.7.32" + resolved "https://registry.yarnpkg.com/@types/morgan/-/morgan-1.7.32.tgz#fab1ece4dae172e1a377d563d33e3634fa04927d" + dependencies: + "@types/express" "*" + +"@types/node@*", "@types/node@^7.0.18": + version "7.0.18" + resolved "https://registry.yarnpkg.com/@types/node/-/node-7.0.18.tgz#cd67f27d3dc0cfb746f0bdd5e086c4c5d55be173" + +"@types/request@^0.0.43": + version "0.0.43" + resolved "https://registry.yarnpkg.com/@types/request/-/request-0.0.43.tgz#fcc59cfd88e63034e813c6884a0aade2d0f7e935" + dependencies: + "@types/form-data" "*" + "@types/node" "*" + +"@types/sequelize@3": + version "3.4.48" + resolved "https://registry.yarnpkg.com/@types/sequelize/-/sequelize-3.4.48.tgz#f88fac7cc4717d2e87f20f69ebb64aa869e7e4d1" + dependencies: + "@types/bluebird" "*" + "@types/lodash" "*" + "@types/validator" "*" "@types/serve-static@*": version "1.7.31" @@ -38,6 +92,22 @@ "@types/express-serve-static-core" "*" "@types/mime" "*" +"@types/validator@*": + version "6.2.0" + resolved "https://registry.yarnpkg.com/@types/validator/-/validator-6.2.0.tgz#020322fe1929f69889eb675a1bdb5a98394b71f0" + +"@types/winston@^2.3.2": + version "2.3.2" + resolved "https://registry.yarnpkg.com/@types/winston/-/winston-2.3.2.tgz#c162547cb47c0b8a450e681bb9fa7041cd80edfa" + dependencies: + "@types/node" "*" + +"@types/ws@^0.0.41": + version "0.0.41" + resolved "https://registry.yarnpkg.com/@types/ws/-/ws-0.0.41.tgz#88a7e0cd1605bd6ea773110954671394c690db1a" + dependencies: + "@types/node" "*" + abbrev@1: version "1.1.0" resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.0.tgz#d0554c2256636e2f56e7c2e5ad183f859428d81f" @@ -198,7 +268,7 @@ aws4@^1.2.1: version "1.6.0" resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.6.0.tgz#83ef5ca860b2b32e4a0deedee8c771b9db57471e" -babel-code-frame@^6.16.0: +babel-code-frame@^6.16.0, babel-code-frame@^6.22.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.22.0.tgz#027620bee567a88c32561574e7fd0801d33118e4" dependencies: @@ -523,6 +593,10 @@ colors@1.0.x: version "1.0.3" resolved "https://registry.yarnpkg.com/colors/-/colors-1.0.3.tgz#0433f44d809680fdeb60ed260f1b0c262e82a40b" +colors@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/colors/-/colors-1.1.2.tgz#168a4701756b6a7f51a12ce0c97bfa28c084ed63" + combined-stream@^1.0.5, combined-stream@~1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.5.tgz#938370a57b4a51dea2c77c15d5c5fdf895164009" @@ -785,7 +859,7 @@ dicer@0.2.5: readable-stream "1.1.x" streamsearch "0.1.2" -diff@3.2.0: +diff@3.2.0, diff@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/diff/-/diff-3.2.0.tgz#c9ce393a4b7cbd0b058a725c93df299027868ff9" @@ -796,6 +870,13 @@ doctrine@1.5.0, doctrine@^1.2.2: esutils "^2.0.2" isarray "^1.0.0" +doctrine@^0.7.2: + version "0.7.2" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-0.7.2.tgz#7cb860359ba3be90e040b26b729ce4bfa654c523" + dependencies: + esutils "^1.1.6" + isarray "0.0.1" + doctrine@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.0.0.tgz#c73d8d2909d22291e1a007a395804da8b665fe63" @@ -1057,6 +1138,10 @@ estraverse@~4.1.0: version "4.1.1" resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.1.1.tgz#f6caca728933a850ef90661d0e17982ba47111a2" +esutils@^1.1.6: + version "1.1.6" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-1.1.6.tgz#c01ccaa9ae4b897c6d0c3e210ae52f3c7a844375" + esutils@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b" @@ -1200,6 +1285,12 @@ find-up@^2.0.0: dependencies: locate-path "^2.0.0" +findup-sync@~0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/findup-sync/-/findup-sync-0.3.0.tgz#37930aa5d816b777c03445e1966cc6790a4c0b16" + dependencies: + glob "~5.0.0" + flat-cache@^1.2.1: version "1.2.2" resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-1.2.2.tgz#fa86714e72c21db88601761ecf2f555d1abc6b96" @@ -1333,7 +1424,7 @@ github-from-package@0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/github-from-package/-/github-from-package-0.0.0.tgz#97fb5d96bfde8973313f20e8288ef9a167fa64ce" -glob@7.1.1, glob@^7.0.0, glob@^7.0.3, glob@^7.0.5: +glob@7.1.1, glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.1.1: version "7.1.1" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.1.tgz#805211df04faaf1c63a3600306cdf5ade50b2ec8" dependencies: @@ -1344,6 +1435,16 @@ glob@7.1.1, glob@^7.0.0, glob@^7.0.3, glob@^7.0.5: once "^1.3.0" path-is-absolute "^1.0.0" +glob@~5.0.0: + version "5.0.15" + resolved "https://registry.yarnpkg.com/glob/-/glob-5.0.15.tgz#1bc936b9e02f4a603fcc222ecf7633d30b8b93b1" + dependencies: + inflight "^1.0.4" + inherits "2" + minimatch "2 || 3" + once "^1.3.0" + path-is-absolute "^1.0.0" + globals@^9.14.0: version "9.17.0" resolved "https://registry.yarnpkg.com/globals/-/globals-9.17.0.tgz#0c0ca696d9b9bb694d2e5470bd37777caad50286" @@ -1862,7 +1963,7 @@ mime@1.3.4, mime@^1.3.4: version "1.3.4" resolved "https://registry.yarnpkg.com/mime/-/mime-1.3.4.tgz#115f9e3b6b3daf2959983cb38f149a2d40eb5d53" -minimatch@^3.0.0, minimatch@^3.0.2, minimatch@^3.0.3: +"minimatch@2 || 3", minimatch@^3.0.0, minimatch@^3.0.2, minimatch@^3.0.3: version "3.0.3" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.3.tgz#2a4e4090b96b2db06a9d7df01055a62a77c9b774" dependencies: @@ -2101,7 +2202,7 @@ openssl-wrapper@^0.3.4: version "0.3.4" resolved "https://registry.yarnpkg.com/openssl-wrapper/-/openssl-wrapper-0.3.4.tgz#c01ec98e4dcd2b5dfe0b693f31827200e3b81b07" -optimist@0.6.1: +optimist@0.6.1, optimist@~0.6.0: version "0.6.1" resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686" dependencies: @@ -2533,7 +2634,7 @@ resolve-from@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-1.0.1.tgz#26cbfe935d1aeeeabb29bc3fe5aeb01e93d44226" -resolve@^1.1.6, resolve@^1.1.7: +resolve@^1.1.6, resolve@^1.1.7, resolve@^1.3.2: version "1.3.3" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.3.3.tgz#655907c3469a8680dc2de3a275a8fdd69691f0e5" dependencies: @@ -2616,7 +2717,7 @@ semver@4.3.2: version "4.3.2" resolved "https://registry.yarnpkg.com/semver/-/semver-4.3.2.tgz#c7a07158a80bedd052355b770d82d6640f803be7" -semver@5.3.0, semver@^5.0.1, semver@~5.3.0: +semver@5.3.0, semver@^5.0.1, semver@^5.3.0, semver@~5.3.0: version "5.3.0" resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f" @@ -3080,6 +3181,43 @@ tryit@^1.0.1: version "1.0.3" resolved "https://registry.yarnpkg.com/tryit/-/tryit-1.0.3.tgz#393be730a9446fd1ead6da59a014308f36c289cb" +tslib@^1.0.0, tslib@^1.6.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.7.0.tgz#6e8366695f72961252b35167b0dd4fbeeafba491" + +tslint-config-standard@^5.0.2: + version "5.0.2" + resolved "https://registry.yarnpkg.com/tslint-config-standard/-/tslint-config-standard-5.0.2.tgz#e98fd5c412a6b973798366dc2c85508cf0ed740f" + dependencies: + tslint-eslint-rules "^4.0.0" + +tslint-eslint-rules@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/tslint-eslint-rules/-/tslint-eslint-rules-4.0.0.tgz#4e0e59ecd5701c9a48c66ed47bdcafb1c635d27b" + dependencies: + doctrine "^0.7.2" + tslib "^1.0.0" + tsutils "^1.4.0" + +tslint@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/tslint/-/tslint-5.2.0.tgz#16a2addf20cb748385f544e9a0edab086bc34114" + dependencies: + babel-code-frame "^6.22.0" + colors "^1.1.2" + diff "^3.2.0" + findup-sync "~0.3.0" + glob "^7.1.1" + optimist "~0.6.0" + resolve "^1.3.2" + semver "^5.3.0" + tslib "^1.6.0" + tsutils "^1.8.0" + +tsutils@^1.4.0, tsutils@^1.8.0: + version "1.8.0" + resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-1.8.0.tgz#bf8118ed8e80cd5c9fc7d75728c7963d44ed2f52" + tunnel-agent@^0.4.3: version "0.4.3" resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.4.3.tgz#6373db76909fe570e08d73583365ed828a74eeeb" @@ -3125,6 +3263,10 @@ typedarray@^0.0.6: version "0.0.6" resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" +typescript@~2.2.0: + version "2.2.2" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.2.2.tgz#606022508479b55ffa368b58fee963a03dfd7b0c" + uid-number@~0.0.6: version "0.0.6" resolved "https://registry.yarnpkg.com/uid-number/-/uid-number-0.0.6.tgz#0ea10e8035e8eb5b8e4449f06da1c730663baa81" -- 2.41.0