aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--package.json5
-rw-r--r--server.ts14
-rw-r--r--server/controllers/api/clients.ts2
-rw-r--r--server/controllers/api/config.ts2
-rw-r--r--server/controllers/api/pods.ts6
-rw-r--r--server/controllers/api/remote/pods.ts4
-rw-r--r--server/controllers/api/remote/videos.ts2
-rw-r--r--server/controllers/api/users.ts4
-rw-r--r--server/controllers/api/videos/abuse.ts2
-rw-r--r--server/controllers/api/videos/blacklist.ts2
-rw-r--r--server/controllers/api/videos/index.ts2
-rw-r--r--server/controllers/api/videos/rate.ts2
-rw-r--r--server/controllers/client.ts7
-rw-r--r--server/helpers/database-utils.ts4
-rw-r--r--server/helpers/logger.ts7
-rw-r--r--server/helpers/utils.ts9
-rw-r--r--server/initializers/checker.ts2
-rw-r--r--server/initializers/constants.ts22
-rw-r--r--server/initializers/database.ts59
-rw-r--r--server/initializers/installer.ts9
-rw-r--r--server/initializers/migrator.ts8
-rw-r--r--server/lib/friends.ts6
-rw-r--r--server/lib/jobs/handlers/video-transcoder.ts2
-rw-r--r--server/lib/jobs/job-scheduler.ts6
-rw-r--r--server/lib/oauth-model.ts4
-rw-r--r--server/lib/request/base-request-scheduler.ts4
-rw-r--r--server/lib/request/request-scheduler.ts9
-rw-r--r--server/lib/request/request-video-event-scheduler.ts2
-rw-r--r--server/lib/request/request-video-qadu-scheduler.ts2
-rw-r--r--server/middlewares/admin.ts2
-rw-r--r--server/middlewares/oauth.ts8
-rw-r--r--server/middlewares/pagination.ts4
-rw-r--r--server/middlewares/pods.ts6
-rw-r--r--server/middlewares/secure.ts10
-rw-r--r--server/middlewares/validators/pods.ts2
-rw-r--r--server/middlewares/validators/users.ts2
-rw-r--r--server/middlewares/validators/videos.ts2
-rw-r--r--server/models/application-interface.ts23
-rw-r--r--server/models/application.ts38
-rw-r--r--server/models/author-interface.ts21
-rw-r--r--server/models/author.ts36
-rw-r--r--server/models/index.ts17
-rw-r--r--server/models/job-interface.ts23
-rw-r--r--server/models/job.ts29
-rw-r--r--server/models/oauth-client-interface.ts28
-rw-r--r--server/models/oauth-client.ts55
-rw-r--r--server/models/oauth-token-interface.ts34
-rw-r--r--server/models/oauth-token.ts75
-rw-r--r--server/models/pod-interface.ts46
-rw-r--r--server/models/pod.ts127
-rw-r--r--server/models/request-interface.ts32
-rw-r--r--server/models/request-to-pod-interface.ts20
-rw-r--r--server/models/request-to-pod.ts32
-rw-r--r--server/models/request-video-event-interface.ts26
-rw-r--r--server/models/request-video-event.ts72
-rw-r--r--server/models/request-video-qadu-interface.ts25
-rw-r--r--server/models/request-video-qadu.ts68
-rw-r--r--server/models/request.ts69
-rw-r--r--server/models/tag-interface.ts19
-rw-r--r--server/models/tag.ts38
-rw-r--r--server/models/user-interface.ts45
-rw-r--r--server/models/user-video-rate-interface.ts21
-rw-r--r--server/models/user-video-rate.ts48
-rw-r--r--server/models/user.ts110
-rw-r--r--server/models/utils.ts6
-rw-r--r--server/models/video-abuse-interface.ts24
-rw-r--r--server/models/video-abuse.ts95
-rw-r--r--server/models/video-blacklist-interface.ts31
-rw-r--r--server/models/video-blacklist.ts80
-rw-r--r--server/models/video-interface.ts75
-rw-r--r--server/models/video-tag-interface.ts18
-rw-r--r--server/models/video-tag.ts17
-rw-r--r--server/models/video.ts379
-rw-r--r--server/tests/api/video-transcoder.js2
-rw-r--r--server/tests/utils/servers.js2
-rw-r--r--yarn.lock349
76 files changed, 1697 insertions, 803 deletions
diff --git a/package.json b/package.json
index 00d0bb5ee..118a0aef6 100644
--- a/package.json
+++ b/package.json
@@ -69,7 +69,7 @@
69 "rimraf": "^2.5.4", 69 "rimraf": "^2.5.4",
70 "safe-buffer": "^5.0.1", 70 "safe-buffer": "^5.0.1",
71 "scripty": "^1.5.0", 71 "scripty": "^1.5.0",
72 "sequelize": "^3.27.0", 72 "sequelize": "4.0.0-2",
73 "typescript": "~2.2.0", 73 "typescript": "~2.2.0",
74 "winston": "^2.1.1", 74 "winston": "^2.1.1",
75 "ws": "^2.0.0" 75 "ws": "^2.0.0"
@@ -85,12 +85,13 @@
85 "@types/morgan": "^1.7.32", 85 "@types/morgan": "^1.7.32",
86 "@types/node": "^7.0.18", 86 "@types/node": "^7.0.18",
87 "@types/request": "^0.0.43", 87 "@types/request": "^0.0.43",
88 "@types/sequelize": "3", 88 "@types/sequelize": "^4.0.55",
89 "@types/winston": "^2.3.2", 89 "@types/winston": "^2.3.2",
90 "@types/ws": "^0.0.41", 90 "@types/ws": "^0.0.41",
91 "chai": "^3.3.0", 91 "chai": "^3.3.0",
92 "commander": "^2.9.0", 92 "commander": "^2.9.0",
93 "mocha": "^3.0.1", 93 "mocha": "^3.0.1",
94 "source-map-support": "^0.4.15",
94 "standard": "^10.0.0", 95 "standard": "^10.0.0",
95 "supertest": "^3.0.0", 96 "supertest": "^3.0.0",
96 "tslint": "^5.2.0", 97 "tslint": "^5.2.0",
diff --git a/server.ts b/server.ts
index 119c0c61d..f5413b8e3 100644
--- a/server.ts
+++ b/server.ts
@@ -1,3 +1,7 @@
1if ([ 'dev', 'test'].indexOf(process.env.NODE_ENV) !== -1) {
2 require('source-map-support').install()
3}
4
1// ----------- Node modules ----------- 5// ----------- Node modules -----------
2import bodyParser = require('body-parser') 6import bodyParser = require('body-parser')
3import express = require('express') 7import express = require('express')
@@ -20,8 +24,8 @@ const app = express()
20import { logger } from './server/helpers/logger' 24import { logger } from './server/helpers/logger'
21import { API_VERSION, CONFIG } from './server/initializers/constants' 25import { API_VERSION, CONFIG } from './server/initializers/constants'
22// Initialize database and models 26// Initialize database and models
23const db = require('./server/initializers/database') 27import { database as db } from './server/initializers/database'
24db.init(onDatabaseInitDone) 28db.init(false, onDatabaseInitDone)
25 29
26// ----------- Checker ----------- 30// ----------- Checker -----------
27import { checkMissedConfig, checkFFmpeg, checkConfig } from './server/initializers/checker' 31import { checkMissedConfig, checkFFmpeg, checkConfig } from './server/initializers/checker'
@@ -52,7 +56,9 @@ import { apiRouter, clientsRouter, staticRouter } from './server/controllers'
52// ----------- App ----------- 56// ----------- App -----------
53 57
54// For the logger 58// For the logger
55// app.use(morgan('combined', { stream: logger.stream })) 59app.use(morgan('combined', {
60 stream: { write: logger.info }
61}))
56// For body requests 62// For body requests
57app.use(bodyParser.json({ limit: '500kb' })) 63app.use(bodyParser.json({ limit: '500kb' }))
58app.use(bodyParser.urlencoded({ extended: false })) 64app.use(bodyParser.urlencoded({ extended: false }))
@@ -75,7 +81,7 @@ app.use('/', staticRouter)
75 81
76// Always serve index client page (the client is a single page application, let it handle routing) 82// Always serve index client page (the client is a single page application, let it handle routing)
77app.use('/*', function (req, res, next) { 83app.use('/*', function (req, res, next) {
78 res.sendFile(path.join(__dirname, './client/dist/index.html')) 84 res.sendFile(path.join(__dirname, '../client/dist/index.html'))
79}) 85})
80 86
81// ----------- Tracker ----------- 87// ----------- Tracker -----------
diff --git a/server/controllers/api/clients.ts b/server/controllers/api/clients.ts
index 902f62995..614163c83 100644
--- a/server/controllers/api/clients.ts
+++ b/server/controllers/api/clients.ts
@@ -2,7 +2,7 @@ import express = require('express')
2 2
3import { CONFIG } from '../../initializers'; 3import { CONFIG } from '../../initializers';
4import { logger } from '../../helpers' 4import { logger } from '../../helpers'
5const db = require('../../initializers/database') 5import { database as db } from '../../initializers/database'
6 6
7const clientsRouter = express.Router() 7const clientsRouter = express.Router()
8 8
diff --git a/server/controllers/api/config.ts b/server/controllers/api/config.ts
index 8f3fa2473..8bdde61b3 100644
--- a/server/controllers/api/config.ts
+++ b/server/controllers/api/config.ts
@@ -1,6 +1,6 @@
1import express = require('express') 1import express = require('express')
2 2
3import { CONFIG } from '../../initializers'; 3import { CONFIG } from '../../initializers'
4 4
5const configRouter = express.Router() 5const configRouter = express.Router()
6 6
diff --git a/server/controllers/api/pods.ts b/server/controllers/api/pods.ts
index 06dfd8295..4ff1f5d9f 100644
--- a/server/controllers/api/pods.ts
+++ b/server/controllers/api/pods.ts
@@ -1,7 +1,7 @@
1import express = require('express') 1import express = require('express')
2import { waterfall } from 'async' 2import { waterfall } from 'async'
3 3
4const db = require('../../initializers/database') 4import { database as db } from '../../initializers/database'
5import { CONFIG } from '../../initializers' 5import { CONFIG } from '../../initializers'
6import { 6import {
7 logger, 7 logger,
@@ -35,12 +35,12 @@ podsRouter.post('/makefriends',
35 ensureIsAdmin, 35 ensureIsAdmin,
36 makeFriendsValidator, 36 makeFriendsValidator,
37 setBodyHostsPort, 37 setBodyHostsPort,
38 makeFriends 38 makeFriendsController
39) 39)
40podsRouter.get('/quitfriends', 40podsRouter.get('/quitfriends',
41 authenticate, 41 authenticate,
42 ensureIsAdmin, 42 ensureIsAdmin,
43 quitFriends 43 quitFriendsController
44) 44)
45 45
46// --------------------------------------------------------------------------- 46// ---------------------------------------------------------------------------
diff --git a/server/controllers/api/remote/pods.ts b/server/controllers/api/remote/pods.ts
index 85ef7bb42..7a9a0c4f0 100644
--- a/server/controllers/api/remote/pods.ts
+++ b/server/controllers/api/remote/pods.ts
@@ -1,7 +1,7 @@
1import express = require('express') 1import express = require('express')
2import { waterfall } from 'async/waterfall' 2import * as waterfall from 'async/waterfall'
3 3
4const db = require('../../../initializers/database') 4import { database as db } from '../../../initializers/database'
5import { checkSignature, signatureValidator } from '../../../middlewares' 5import { checkSignature, signatureValidator } from '../../../middlewares'
6 6
7const remotePodsRouter = express.Router() 7const remotePodsRouter = express.Router()
diff --git a/server/controllers/api/remote/videos.ts b/server/controllers/api/remote/videos.ts
index df4ba8309..178a21e7c 100644
--- a/server/controllers/api/remote/videos.ts
+++ b/server/controllers/api/remote/videos.ts
@@ -1,7 +1,7 @@
1import express = require('express') 1import express = require('express')
2import { eachSeries, waterfall } from 'async' 2import { eachSeries, waterfall } from 'async'
3 3
4const db = require('../../../initializers/database') 4import { database as db } from '../../../initializers/database'
5import { 5import {
6 REQUEST_ENDPOINT_ACTIONS, 6 REQUEST_ENDPOINT_ACTIONS,
7 REQUEST_ENDPOINTS, 7 REQUEST_ENDPOINTS,
diff --git a/server/controllers/api/users.ts b/server/controllers/api/users.ts
index 981a4706a..97a744f54 100644
--- a/server/controllers/api/users.ts
+++ b/server/controllers/api/users.ts
@@ -1,7 +1,7 @@
1import express = require('express') 1import express = require('express')
2import { waterfall } from 'async' 2import { waterfall } from 'async'
3 3
4const db = require('../../initializers/database') 4import { database as db } from '../../initializers/database'
5import { CONFIG, USER_ROLES } from '../../initializers' 5import { CONFIG, USER_ROLES } from '../../initializers'
6import { logger, getFormatedObjects } from '../../helpers' 6import { logger, getFormatedObjects } from '../../helpers'
7import { 7import {
@@ -114,7 +114,7 @@ function getUserVideoRating (req, res, next) {
114 const videoId = req.params.videoId 114 const videoId = req.params.videoId
115 const userId = res.locals.oauth.token.User.id 115 const userId = res.locals.oauth.token.User.id
116 116
117 db.UserVideoRate.load(userId, videoId, function (err, ratingObj) { 117 db.UserVideoRate.load(userId, videoId, null, function (err, ratingObj) {
118 if (err) return next(err) 118 if (err) return next(err)
119 119
120 const rating = ratingObj ? ratingObj.type : 'none' 120 const rating = ratingObj ? ratingObj.type : 'none'
diff --git a/server/controllers/api/videos/abuse.ts b/server/controllers/api/videos/abuse.ts
index 88204120f..3dd884354 100644
--- a/server/controllers/api/videos/abuse.ts
+++ b/server/controllers/api/videos/abuse.ts
@@ -1,7 +1,7 @@
1import express = require('express') 1import express = require('express')
2import { waterfall } from 'async' 2import { waterfall } from 'async'
3 3
4const db = require('../../../initializers/database') 4import { database as db } from '../../../initializers/database'
5import friends = require('../../../lib/friends') 5import friends = require('../../../lib/friends')
6import { 6import {
7 logger, 7 logger,
diff --git a/server/controllers/api/videos/blacklist.ts b/server/controllers/api/videos/blacklist.ts
index db6d95e73..fb4d57d7b 100644
--- a/server/controllers/api/videos/blacklist.ts
+++ b/server/controllers/api/videos/blacklist.ts
@@ -1,6 +1,6 @@
1import express = require('express') 1import express = require('express')
2 2
3const db = require('../../../initializers/database') 3import { database as db } from '../../../initializers/database'
4import { logger } from '../../../helpers' 4import { logger } from '../../../helpers'
5import { 5import {
6 authenticate, 6 authenticate,
diff --git a/server/controllers/api/videos/index.ts b/server/controllers/api/videos/index.ts
index 5fbf03676..6eda7159b 100644
--- a/server/controllers/api/videos/index.ts
+++ b/server/controllers/api/videos/index.ts
@@ -4,7 +4,7 @@ import multer = require('multer')
4import path = require('path') 4import path = require('path')
5import { waterfall } from 'async' 5import { waterfall } from 'async'
6 6
7const db = require('../../../initializers/database') 7import { database as db } from '../../../initializers/database'
8import { 8import {
9 CONFIG, 9 CONFIG,
10 REQUEST_VIDEO_QADU_TYPES, 10 REQUEST_VIDEO_QADU_TYPES,
diff --git a/server/controllers/api/videos/rate.ts b/server/controllers/api/videos/rate.ts
index 21053792a..571ff68e3 100644
--- a/server/controllers/api/videos/rate.ts
+++ b/server/controllers/api/videos/rate.ts
@@ -1,7 +1,7 @@
1import express = require('express') 1import express = require('express')
2import { waterfall } from 'async' 2import { waterfall } from 'async'
3 3
4const db = require('../../../initializers/database') 4import { database as db } from '../../../initializers/database'
5import { 5import {
6 logger, 6 logger,
7 retryTransactionWrapper, 7 retryTransactionWrapper,
diff --git a/server/controllers/client.ts b/server/controllers/client.ts
index aaa04889a..ce5608c9b 100644
--- a/server/controllers/client.ts
+++ b/server/controllers/client.ts
@@ -6,20 +6,21 @@ import expressValidator = require('express-validator')
6// TODO: use .validator when express-validator typing will have validator field 6// TODO: use .validator when express-validator typing will have validator field
7const validator = expressValidator['validator'] 7const validator = expressValidator['validator']
8 8
9const db = require('../initializers/database') 9import { database as db } from '../initializers/database'
10import { 10import {
11 CONFIG, 11 CONFIG,
12 REMOTE_SCHEME, 12 REMOTE_SCHEME,
13 STATIC_PATHS, 13 STATIC_PATHS,
14 STATIC_MAX_AGE 14 STATIC_MAX_AGE
15} from '../initializers' 15} from '../initializers'
16import { root } from '../helpers'
16 17
17const clientsRouter = express.Router() 18const clientsRouter = express.Router()
18 19
19// TODO: move to constants 20// TODO: move to constants
20const opengraphComment = '<!-- opengraph tags -->' 21const opengraphComment = '<!-- opengraph tags -->'
21const distPath = join(__dirname, '..', '..', 'client/dist') 22const distPath = join(root(), 'client', 'dist')
22const embedPath = join(distPath, 'standalone/videos/embed.html') 23const embedPath = join(distPath, 'standalone', 'videos', 'embed.html')
23const indexPath = join(distPath, 'index.html') 24const indexPath = join(distPath, 'index.html')
24 25
25// Special route that add OpenGraph tags 26// Special route that add OpenGraph tags
diff --git a/server/helpers/database-utils.ts b/server/helpers/database-utils.ts
index b842ab9ec..7d6ce4ec8 100644
--- a/server/helpers/database-utils.ts
+++ b/server/helpers/database-utils.ts
@@ -1,7 +1,7 @@
1// TODO: import from ES6 when retry typing file will include errorFilter function 1// TODO: import from ES6 when retry typing file will include errorFilter function
2import retry = require('async/retry') 2import retry = require('async/retry')
3 3
4const db = require('../initializers/database') 4import { database as db } from '../initializers/database'
5import { logger } from './logger' 5import { logger } from './logger'
6 6
7function commitTransaction (t, callback) { 7function commitTransaction (t, callback) {
@@ -52,7 +52,7 @@ function transactionRetryer (func, callback) {
52} 52}
53 53
54function startSerializableTransaction (callback) { 54function startSerializableTransaction (callback) {
55 db.sequelize.transaction({ isolationLevel: 'SERIALIZABLE' }).asCallback(function (err, t) { 55 db.sequelize.transaction(/* { isolationLevel: 'SERIALIZABLE' } */).asCallback(function (err, t) {
56 // We force to return only two parameters 56 // We force to return only two parameters
57 return callback(err, t) 57 return callback(err, t)
58 }) 58 })
diff --git a/server/helpers/logger.ts b/server/helpers/logger.ts
index 3c35e41e0..7c99db55f 100644
--- a/server/helpers/logger.ts
+++ b/server/helpers/logger.ts
@@ -36,13 +36,6 @@ const logger = new winston.Logger({
36 exitOnError: true 36 exitOnError: true
37}) 37})
38 38
39// TODO: useful?
40// logger.stream = {
41// write: function (message) {
42// logger.info(message)
43// }
44// }
45
46// --------------------------------------------------------------------------- 39// ---------------------------------------------------------------------------
47 40
48export { logger } 41export { logger }
diff --git a/server/helpers/utils.ts b/server/helpers/utils.ts
index 09c35a533..bc76cfb26 100644
--- a/server/helpers/utils.ts
+++ b/server/helpers/utils.ts
@@ -1,4 +1,5 @@
1import { pseudoRandomBytes } from 'crypto' 1import { pseudoRandomBytes } from 'crypto'
2import { join } from 'path'
2 3
3import { logger } from './logger' 4import { logger } from './logger'
4 5
@@ -42,6 +43,11 @@ function getFormatedObjects (objects, objectsTotal) {
42 } 43 }
43} 44}
44 45
46function root () {
47 // We are in /dist/helpers/utils.js
48 return join(__dirname, '..', '..', '..')
49}
50
45// --------------------------------------------------------------------------- 51// ---------------------------------------------------------------------------
46 52
47export { 53export {
@@ -50,5 +56,6 @@ export {
50 cleanForExit, 56 cleanForExit,
51 generateRandomString, 57 generateRandomString,
52 isTestInstance, 58 isTestInstance,
53 getFormatedObjects 59 getFormatedObjects,
60 root
54} 61}
diff --git a/server/initializers/checker.ts b/server/initializers/checker.ts
index 370dff2d4..0ee01b0e3 100644
--- a/server/initializers/checker.ts
+++ b/server/initializers/checker.ts
@@ -1,6 +1,6 @@
1import config = require('config') 1import config = require('config')
2 2
3const db = require('./database') 3import { database as db } from './database'
4import { CONFIG } from './constants' 4import { CONFIG } from './constants'
5 5
6// Some checks on configuration files 6// Some checks on configuration files
diff --git a/server/initializers/constants.ts b/server/initializers/constants.ts
index 6bdc261ad..1072d0de0 100644
--- a/server/initializers/constants.ts
+++ b/server/initializers/constants.ts
@@ -1,6 +1,9 @@
1import config = require('config') 1import config = require('config')
2import { join } from 'path' 2import { join } from 'path'
3 3
4// Do not use barrels, remain constants as independent as possible
5import { root, isTestInstance } from '../helpers/utils'
6
4// --------------------------------------------------------------------------- 7// ---------------------------------------------------------------------------
5 8
6const LAST_MIGRATION_VERSION = 50 9const LAST_MIGRATION_VERSION = 50
@@ -44,12 +47,12 @@ const CONFIG = {
44 PASSWORD: config.get<string>('database.password') 47 PASSWORD: config.get<string>('database.password')
45 }, 48 },
46 STORAGE: { 49 STORAGE: {
47 CERT_DIR: join(__dirname, '..', '..', config.get<string>('storage.certs')), 50 CERT_DIR: join(root(), config.get<string>('storage.certs')),
48 LOG_DIR: join(__dirname, '..', '..', config.get<string>('storage.logs')), 51 LOG_DIR: join(root(), config.get<string>('storage.logs')),
49 VIDEOS_DIR: join(__dirname, '..', '..', config.get<string>('storage.videos')), 52 VIDEOS_DIR: join(root(), config.get<string>('storage.videos')),
50 THUMBNAILS_DIR: join(__dirname, '..', '..', config.get<string>('storage.thumbnails')), 53 THUMBNAILS_DIR: join(root(), config.get<string>('storage.thumbnails')),
51 PREVIEWS_DIR: join(__dirname, '..', '..', config.get<string>('storage.previews')), 54 PREVIEWS_DIR: join(root(), config.get<string>('storage.previews')),
52 TORRENTS_DIR: join(__dirname, '..', '..', config.get<string>('storage.torrents')) 55 TORRENTS_DIR: join(root(), config.get<string>('storage.torrents'))
53 }, 56 },
54 WEBSERVER: { 57 WEBSERVER: {
55 SCHEME: config.get<boolean>('webserver.https') === true ? 'https' : 'http', 58 SCHEME: config.get<boolean>('webserver.https') === true ? 'https' : 'http',
@@ -334,10 +337,3 @@ export {
334 VIDEO_LICENCES, 337 VIDEO_LICENCES,
335 VIDEO_RATE_TYPES 338 VIDEO_RATE_TYPES
336} 339}
337
338// ---------------------------------------------------------------------------
339
340// This method exists in utils module but we want to let the constants module independent
341function isTestInstance () {
342 return (process.env.NODE_ENV === 'test')
343}
diff --git a/server/initializers/database.ts b/server/initializers/database.ts
index 753a06669..c89a8b23c 100644
--- a/server/initializers/database.ts
+++ b/server/initializers/database.ts
@@ -6,12 +6,52 @@ import { CONFIG } from './constants'
6// Do not use barrel, we need to load database first 6// Do not use barrel, we need to load database first
7import { logger } from '../helpers/logger' 7import { logger } from '../helpers/logger'
8import { isTestInstance } from '../helpers/utils' 8import { isTestInstance } from '../helpers/utils'
9import {
10 ApplicationModel,
11 AuthorModel,
12 JobModel,
13 OAuthClientModel,
14 OAuthTokenModel,
15 PodModel,
16 RequestModel,
17 RequestToPodModel,
18 RequestVideoEventModel,
19 RequestVideoQaduModel,
20 TagModel,
21 UserModel,
22 UserVideoRateModel,
23 VideoAbuseModel,
24 BlacklistedVideoModel,
25 VideoTagModel,
26 VideoModel
27} from '../models'
9 28
10const dbname = CONFIG.DATABASE.DBNAME 29const dbname = CONFIG.DATABASE.DBNAME
11const username = CONFIG.DATABASE.USERNAME 30const username = CONFIG.DATABASE.USERNAME
12const password = CONFIG.DATABASE.PASSWORD 31const password = CONFIG.DATABASE.PASSWORD
13 32
14const database: any = {} 33const database: {
34 sequelize?: Sequelize.Sequelize,
35 init?: (silent: any, callback: any) => void,
36
37 Application?: ApplicationModel,
38 Author?: AuthorModel,
39 Job?: JobModel,
40 OAuthClient?: OAuthClientModel,
41 OAuthToken?: OAuthTokenModel,
42 Pod?: PodModel,
43 RequestToPod?: RequestToPodModel,
44 RequestVideoEvent?: RequestVideoEventModel,
45 RequestVideoQadu?: RequestVideoQaduModel,
46 Request?: RequestModel,
47 Tag?: TagModel,
48 UserVideoRate?: UserVideoRateModel,
49 User?: UserModel,
50 VideoAbuse?: VideoAbuseModel,
51 BlacklistedVideo?: BlacklistedVideoModel,
52 VideoTag?: VideoTagModel,
53 Video?: VideoModel
54} = {}
15 55
16const sequelize = new Sequelize(dbname, username, password, { 56const sequelize = new Sequelize(dbname, username, password, {
17 dialect: 'postgres', 57 dialect: 'postgres',
@@ -32,12 +72,6 @@ const sequelize = new Sequelize(dbname, username, password, {
32database.sequelize = sequelize 72database.sequelize = sequelize
33 73
34database.init = function (silent, callback) { 74database.init = function (silent, callback) {
35 if (!callback) {
36 callback = silent
37 silent = false
38 }
39
40 if (!callback) callback = function () { /* empty */ }
41 75
42 const modelDirectory = join(__dirname, '..', 'models') 76 const modelDirectory = join(__dirname, '..', 'models')
43 fs.readdir(modelDirectory, function (err, files) { 77 fs.readdir(modelDirectory, function (err, files) {
@@ -45,7 +79,12 @@ database.init = function (silent, callback) {
45 79
46 files.filter(function (file) { 80 files.filter(function (file) {
47 // For all models but not utils.js 81 // For all models but not utils.js
48 if (file === 'utils.js') return false 82 if (
83 file === 'index.js' ||
84 file === 'utils.js' ||
85 file.endsWith('-interface.js') ||
86 file.endsWith('.js.map')
87 ) return false
49 88
50 return true 89 return true
51 }) 90 })
@@ -69,4 +108,6 @@ database.init = function (silent, callback) {
69 108
70// --------------------------------------------------------------------------- 109// ---------------------------------------------------------------------------
71 110
72module.exports = database 111export {
112 database
113}
diff --git a/server/initializers/installer.ts b/server/initializers/installer.ts
index cd1404d48..467164107 100644
--- a/server/initializers/installer.ts
+++ b/server/initializers/installer.ts
@@ -4,10 +4,10 @@ import { each, series } from 'async'
4import mkdirp = require('mkdirp') 4import mkdirp = require('mkdirp')
5import passwordGenerator = require('password-generator') 5import passwordGenerator = require('password-generator')
6 6
7const db = require('./database') 7import { database as db } from './database'
8import { USER_ROLES, CONFIG, LAST_MIGRATION_VERSION } from './constants' 8import { USER_ROLES, CONFIG, LAST_MIGRATION_VERSION } from './constants'
9import { clientsExist, usersExist } from './checker' 9import { clientsExist, usersExist } from './checker'
10import { logger, createCertsIfNotExist } from '../helpers' 10import { logger, createCertsIfNotExist, root } from '../helpers'
11 11
12function installApplication (callback) { 12function installApplication (callback) {
13 series([ 13 series([
@@ -47,7 +47,7 @@ function createDirectoriesIfNotExist (callback) {
47 47
48 each(Object.keys(storages), function (key, callbackEach) { 48 each(Object.keys(storages), function (key, callbackEach) {
49 const dir = storages[key] 49 const dir = storages[key]
50 mkdirp(join(__dirname, '..', '..', dir), callbackEach) 50 mkdirp(join(root(), dir), callbackEach)
51 }, callback) 51 }, callback)
52} 52}
53 53
@@ -65,7 +65,8 @@ function createOAuthClientIfNotExist (callback) {
65 const client = db.OAuthClient.build({ 65 const client = db.OAuthClient.build({
66 clientId: id, 66 clientId: id,
67 clientSecret: secret, 67 clientSecret: secret,
68 grants: [ 'password', 'refresh_token' ] 68 grants: [ 'password', 'refresh_token' ],
69 redirectUris: null
69 }) 70 })
70 71
71 client.save().asCallback(function (err, createdClient) { 72 client.save().asCallback(function (err, createdClient) {
diff --git a/server/initializers/migrator.ts b/server/initializers/migrator.ts
index cfa3220e0..d42cb3ccc 100644
--- a/server/initializers/migrator.ts
+++ b/server/initializers/migrator.ts
@@ -1,10 +1,12 @@
1import { waterfall, eachSeries } from 'async' 1import { waterfall, eachSeries } from 'async'
2import fs = require('fs') 2import fs = require('fs')
3import path = require('path') 3import path = require('path')
4import * as Sequelize from 'sequelize'
4 5
5const db = require('./database') 6import { database as db } from './database'
6import { LAST_MIGRATION_VERSION } from './constants' 7import { LAST_MIGRATION_VERSION } from './constants'
7import { logger } from '../helpers' 8import { logger } from '../helpers'
9import { ApplicationInstance } from '../models'
8 10
9function migrate (finalCallback) { 11function migrate (finalCallback) {
10 waterfall([ 12 waterfall([
@@ -94,7 +96,7 @@ function getMigrationScripts (callback) {
94} 96}
95 97
96function executeMigration (actualVersion, entity, callback) { 98function executeMigration (actualVersion, entity, callback) {
97 const versionScript = parseInt(entity.version) 99 const versionScript = parseInt(entity.version, 10)
98 100
99 // Do not execute old migration scripts 101 // Do not execute old migration scripts
100 if (versionScript <= actualVersion) return callback(null) 102 if (versionScript <= actualVersion) return callback(null)
@@ -112,7 +114,7 @@ function executeMigration (actualVersion, entity, callback) {
112 transaction: t, 114 transaction: t,
113 queryInterface: db.sequelize.getQueryInterface(), 115 queryInterface: db.sequelize.getQueryInterface(),
114 sequelize: db.sequelize, 116 sequelize: db.sequelize,
115 Sequelize: db.Sequelize 117 Sequelize: Sequelize
116 } 118 }
117 migrationScript.up(options, function (err) { 119 migrationScript.up(options, function (err) {
118 if (err) { 120 if (err) {
diff --git a/server/lib/friends.ts b/server/lib/friends.ts
index b32783019..08b776e83 100644
--- a/server/lib/friends.ts
+++ b/server/lib/friends.ts
@@ -1,7 +1,7 @@
1import { each, eachLimit, eachSeries, series, waterfall } from 'async' 1import { each, eachLimit, eachSeries, series, waterfall } from 'async'
2import request = require('request') 2import request = require('request')
3 3
4const db = require('../initializers/database') 4import { database as db } from '../initializers/database'
5import { 5import {
6 API_VERSION, 6 API_VERSION,
7 CONFIG, 7 CONFIG,
@@ -329,7 +329,7 @@ function makeRequestsToWinningPods (cert, podsList, callback) {
329 // Flush pool requests 329 // Flush pool requests
330 requestScheduler.forceSend() 330 requestScheduler.forceSend()
331 331
332 eachLimit(podsList, REQUESTS_IN_PARALLEL, function (pod: any, callbackEach) { 332 eachLimit(podsList, REQUESTS_IN_PARALLEL, function (pod: { host: string }, callbackEach) {
333 const params = { 333 const params = {
334 url: REMOTE_SCHEME.HTTP + '://' + pod.host + '/api/' + API_VERSION + '/pods/', 334 url: REMOTE_SCHEME.HTTP + '://' + pod.host + '/api/' + API_VERSION + '/pods/',
335 method: 'POST', 335 method: 'POST',
@@ -340,7 +340,7 @@ function makeRequestsToWinningPods (cert, podsList, callback) {
340 } 340 }
341 } 341 }
342 342
343 makeRetryRequest(params, function (err, res, body) { 343 makeRetryRequest(params, function (err, res, body: { cert: string, email: string }) {
344 if (err) { 344 if (err) {
345 logger.error('Error with adding %s pod.', pod.host, { error: err }) 345 logger.error('Error with adding %s pod.', pod.host, { error: err })
346 // Don't break the process 346 // Don't break the process
diff --git a/server/lib/jobs/handlers/video-transcoder.ts b/server/lib/jobs/handlers/video-transcoder.ts
index 35db5fb96..43599356a 100644
--- a/server/lib/jobs/handlers/video-transcoder.ts
+++ b/server/lib/jobs/handlers/video-transcoder.ts
@@ -1,4 +1,4 @@
1const db = require('../../../initializers/database') 1import { database as db } from '../../../initializers/database'
2import { logger } from '../../../helpers' 2import { logger } from '../../../helpers'
3import { addVideoToFriends } from '../../../lib' 3import { addVideoToFriends } from '../../../lib'
4 4
diff --git a/server/lib/jobs/job-scheduler.ts b/server/lib/jobs/job-scheduler.ts
index 7b8c6faf9..ad5f7f6d9 100644
--- a/server/lib/jobs/job-scheduler.ts
+++ b/server/lib/jobs/job-scheduler.ts
@@ -1,6 +1,6 @@
1import { forever, queue } from 'async' 1import { forever, queue } from 'async'
2 2
3const db = require('../../initializers/database') 3import { database as db } from '../../initializers/database'
4import { 4import {
5 JOBS_FETCHING_INTERVAL, 5 JOBS_FETCHING_INTERVAL,
6 JOBS_FETCH_LIMIT_PER_CYCLE, 6 JOBS_FETCH_LIMIT_PER_CYCLE,
@@ -24,7 +24,7 @@ class JobScheduler {
24 24
25 logger.info('Jobs scheduler activated.') 25 logger.info('Jobs scheduler activated.')
26 26
27 const jobsQueue = queue(this.processJob) 27 const jobsQueue = queue(this.processJob.bind(this))
28 28
29 // Finish processing jobs from a previous start 29 // Finish processing jobs from a previous start
30 const state = JOB_STATES.PROCESSING 30 const state = JOB_STATES.PROCESSING
@@ -58,7 +58,7 @@ class JobScheduler {
58 }) 58 })
59 } 59 }
60 60
61 createJob (transaction, handlerName, handlerInputData, callback) { 61 createJob (transaction, handlerName: string, handlerInputData: object, callback) {
62 const createQuery = { 62 const createQuery = {
63 state: JOB_STATES.PENDING, 63 state: JOB_STATES.PENDING,
64 handlerName, 64 handlerName,
diff --git a/server/lib/oauth-model.ts b/server/lib/oauth-model.ts
index 00b1afcf5..3bdf0f478 100644
--- a/server/lib/oauth-model.ts
+++ b/server/lib/oauth-model.ts
@@ -1,4 +1,4 @@
1const db = require('../initializers/database') 1import { database as db } from '../initializers/database'
2import { logger } from '../helpers' 2import { logger } from '../helpers'
3 3
4// --------------------------------------------------------------------------- 4// ---------------------------------------------------------------------------
@@ -72,7 +72,7 @@ function saveToken (token, client, user) {
72 userId: user.id 72 userId: user.id
73 } 73 }
74 74
75 return db.OAuthToken.create(tokenToCreate).then(function (tokenCreated) { 75 return db.OAuthToken.create(tokenToCreate).then(function (tokenCreated: any) {
76 tokenCreated.client = client 76 tokenCreated.client = client
77 tokenCreated.user = user 77 tokenCreated.user = user
78 78
diff --git a/server/lib/request/base-request-scheduler.ts b/server/lib/request/base-request-scheduler.ts
index 7fc88b5f1..b7ef6abf9 100644
--- a/server/lib/request/base-request-scheduler.ts
+++ b/server/lib/request/base-request-scheduler.ts
@@ -1,6 +1,6 @@
1import { eachLimit } from 'async/eachLimit' 1import * as eachLimit from 'async/eachLimit'
2 2
3const db = require('../../initializers/database') 3import { database as db } from '../../initializers/database'
4import { logger, makeSecureRequest } from '../../helpers' 4import { logger, makeSecureRequest } from '../../helpers'
5import { 5import {
6 API_VERSION, 6 API_VERSION,
diff --git a/server/lib/request/request-scheduler.ts b/server/lib/request/request-scheduler.ts
index 2006a6f03..26ffbfb86 100644
--- a/server/lib/request/request-scheduler.ts
+++ b/server/lib/request/request-scheduler.ts
@@ -1,4 +1,4 @@
1const db = require('../../initializers/database') 1import { database as db } from '../../initializers/database'
2import { BaseRequestScheduler } from './base-request-scheduler' 2import { BaseRequestScheduler } from './base-request-scheduler'
3import { logger } from '../../helpers' 3import { logger } from '../../helpers'
4import { 4import {
@@ -59,13 +59,14 @@ class RequestScheduler extends BaseRequestScheduler {
59 const toIds = options.toIds 59 const toIds = options.toIds
60 const transaction = options.transaction 60 const transaction = options.transaction
61 61
62 const pods = [] 62 // TODO: check the setPods works
63 const podIds = []
63 64
64 // If there are no destination pods abort 65 // If there are no destination pods abort
65 if (toIds.length === 0) return callback(null) 66 if (toIds.length === 0) return callback(null)
66 67
67 toIds.forEach(toPod => { 68 toIds.forEach(toPod => {
68 pods.push(db.Pod.build({ id: toPod })) 69 podIds.push(toPod)
69 }) 70 })
70 71
71 const createQuery = { 72 const createQuery = {
@@ -83,7 +84,7 @@ class RequestScheduler extends BaseRequestScheduler {
83 return db.Request.create(createQuery, dbRequestOptions).asCallback((err, request) => { 84 return db.Request.create(createQuery, dbRequestOptions).asCallback((err, request) => {
84 if (err) return callback(err) 85 if (err) return callback(err)
85 86
86 return request.setPods(pods, dbRequestOptions).asCallback(callback) 87 return request.setPods(podIds, dbRequestOptions).asCallback(callback)
87 }) 88 })
88 } 89 }
89 90
diff --git a/server/lib/request/request-video-event-scheduler.ts b/server/lib/request/request-video-event-scheduler.ts
index 6e5306c7d..bde50b1d3 100644
--- a/server/lib/request/request-video-event-scheduler.ts
+++ b/server/lib/request/request-video-event-scheduler.ts
@@ -1,4 +1,4 @@
1const db = require('../../initializers/database') 1import { database as db } from '../../initializers/database'
2import { BaseRequestScheduler } from './base-request-scheduler' 2import { BaseRequestScheduler } from './base-request-scheduler'
3import { 3import {
4 REQUESTS_VIDEO_EVENT_LIMIT_PODS, 4 REQUESTS_VIDEO_EVENT_LIMIT_PODS,
diff --git a/server/lib/request/request-video-qadu-scheduler.ts b/server/lib/request/request-video-qadu-scheduler.ts
index d81822723..dab526088 100644
--- a/server/lib/request/request-video-qadu-scheduler.ts
+++ b/server/lib/request/request-video-qadu-scheduler.ts
@@ -1,4 +1,4 @@
1const db = require('../../initializers/database') 1import { database as db } from '../../initializers/database'
2import { BaseRequestScheduler } from './base-request-scheduler' 2import { BaseRequestScheduler } from './base-request-scheduler'
3import { logger } from '../../helpers' 3import { logger } from '../../helpers'
4import { 4import {
diff --git a/server/middlewares/admin.ts b/server/middlewares/admin.ts
index ebafa36a4..28b6a9a12 100644
--- a/server/middlewares/admin.ts
+++ b/server/middlewares/admin.ts
@@ -1,4 +1,4 @@
1const logger = require('../helpers/logger') 1import { logger } from '../helpers'
2 2
3function ensureIsAdmin (req, res, next) { 3function ensureIsAdmin (req, res, next) {
4 const user = res.locals.oauth.token.user 4 const user = res.locals.oauth.token.user
diff --git a/server/middlewares/oauth.ts b/server/middlewares/oauth.ts
index 31ae1e000..07bbded57 100644
--- a/server/middlewares/oauth.ts
+++ b/server/middlewares/oauth.ts
@@ -1,11 +1,11 @@
1import OAuthServer = require('express-oauth-server') 1import OAuthServer = require('express-oauth-server')
2 2
3const constants = require('../initializers/constants') 3import { OAUTH_LIFETIME } from '../initializers'
4const logger = require('../helpers/logger') 4import { logger } from '../helpers'
5 5
6const oAuthServer = new OAuthServer({ 6const oAuthServer = new OAuthServer({
7 accessTokenLifetime: constants.OAUTH_LIFETIME.ACCESS_TOKEN, 7 accessTokenLifetime: OAUTH_LIFETIME.ACCESS_TOKEN,
8 refreshTokenLifetime: constants.OAUTH_LIFETIME.REFRESH_TOKEN, 8 refreshTokenLifetime: OAUTH_LIFETIME.REFRESH_TOKEN,
9 model: require('../lib/oauth-model') 9 model: require('../lib/oauth-model')
10}) 10})
11 11
diff --git a/server/middlewares/pagination.ts b/server/middlewares/pagination.ts
index 8fe9f9082..cadd76980 100644
--- a/server/middlewares/pagination.ts
+++ b/server/middlewares/pagination.ts
@@ -1,10 +1,10 @@
1const constants = require('../initializers/constants') 1import { PAGINATION_COUNT_DEFAULT } from '../initializers'
2 2
3function setPagination (req, res, next) { 3function setPagination (req, res, next) {
4 if (!req.query.start) req.query.start = 0 4 if (!req.query.start) req.query.start = 0
5 else req.query.start = parseInt(req.query.start, 10) 5 else req.query.start = parseInt(req.query.start, 10)
6 6
7 if (!req.query.count) req.query.count = constants.PAGINATION_COUNT_DEFAULT 7 if (!req.query.count) req.query.count = PAGINATION_COUNT_DEFAULT
8 else req.query.count = parseInt(req.query.count, 10) 8 else req.query.count = parseInt(req.query.count, 10)
9 9
10 return next() 10 return next()
diff --git a/server/middlewares/pods.ts b/server/middlewares/pods.ts
index e405f265e..c255be899 100644
--- a/server/middlewares/pods.ts
+++ b/server/middlewares/pods.ts
@@ -1,6 +1,4 @@
1'use strict' 1import { REMOTE_SCHEME } from '../initializers'
2
3const constants = require('../initializers/constants')
4 2
5function setBodyHostsPort (req, res, next) { 3function setBodyHostsPort (req, res, next) {
6 if (!req.body.hosts) return next() 4 if (!req.body.hosts) return next()
@@ -48,7 +46,7 @@ function getHostWithPort (host) {
48 46
49 // The port was not specified 47 // The port was not specified
50 if (splitted.length === 1) { 48 if (splitted.length === 1) {
51 if (constants.REMOTE_SCHEME.HTTP === 'https') return host + ':443' 49 if (REMOTE_SCHEME.HTTP === 'https') return host + ':443'
52 50
53 return host + ':80' 51 return host + ':80'
54 } 52 }
diff --git a/server/middlewares/secure.ts b/server/middlewares/secure.ts
index ee8545028..bd7cfa918 100644
--- a/server/middlewares/secure.ts
+++ b/server/middlewares/secure.ts
@@ -1,6 +1,8 @@
1const db = require('../initializers/database') 1import { database as db } from '../initializers'
2const logger = require('../helpers/logger') 2import {
3const peertubeCrypto = require('../helpers/peertube-crypto') 3 logger,
4 checkSignature as peertubeCryptoCheckSignature
5} from '../helpers'
4 6
5function checkSignature (req, res, next) { 7function checkSignature (req, res, next) {
6 const host = req.body.signature.host 8 const host = req.body.signature.host
@@ -26,7 +28,7 @@ function checkSignature (req, res, next) {
26 signatureShouldBe = host 28 signatureShouldBe = host
27 } 29 }
28 30
29 const signatureOk = peertubeCrypto.checkSignature(pod.publicKey, signatureShouldBe, req.body.signature.signature) 31 const signatureOk = peertubeCryptoCheckSignature(pod.publicKey, signatureShouldBe, req.body.signature.signature)
30 32
31 if (signatureOk === true) { 33 if (signatureOk === true) {
32 res.locals.secure = { 34 res.locals.secure = {
diff --git a/server/middlewares/validators/pods.ts b/server/middlewares/validators/pods.ts
index fbfd268d0..c55a88b85 100644
--- a/server/middlewares/validators/pods.ts
+++ b/server/middlewares/validators/pods.ts
@@ -1,4 +1,4 @@
1const db = require('../../initializers/database') 1import { database as db } from '../../initializers/database'
2import { checkErrors } from './utils' 2import { checkErrors } from './utils'
3import { logger } from '../../helpers' 3import { logger } from '../../helpers'
4import { CONFIG } from '../../initializers' 4import { CONFIG } from '../../initializers'
diff --git a/server/middlewares/validators/users.ts b/server/middlewares/validators/users.ts
index a9149fe1b..e0d1d917a 100644
--- a/server/middlewares/validators/users.ts
+++ b/server/middlewares/validators/users.ts
@@ -1,4 +1,4 @@
1const db = require('../../initializers/database') 1import { database as db } from '../../initializers/database'
2import { checkErrors } from './utils' 2import { checkErrors } from './utils'
3import { logger } from '../../helpers' 3import { logger } from '../../helpers'
4 4
diff --git a/server/middlewares/validators/videos.ts b/server/middlewares/validators/videos.ts
index 5a49cf73c..47825975c 100644
--- a/server/middlewares/validators/videos.ts
+++ b/server/middlewares/validators/videos.ts
@@ -1,4 +1,4 @@
1const db = require('../../initializers/database') 1import { database as db } from '../../initializers/database'
2import { checkErrors } from './utils' 2import { checkErrors } from './utils'
3import { CONSTRAINTS_FIELDS, SEARCHABLE_COLUMNS } from '../../initializers' 3import { CONSTRAINTS_FIELDS, SEARCHABLE_COLUMNS } from '../../initializers'
4import { logger, isVideoDurationValid } from '../../helpers' 4import { logger, isVideoDurationValid } from '../../helpers'
diff --git a/server/models/application-interface.ts b/server/models/application-interface.ts
new file mode 100644
index 000000000..826d25df0
--- /dev/null
+++ b/server/models/application-interface.ts
@@ -0,0 +1,23 @@
1import * as Sequelize from 'sequelize'
2
3export namespace ApplicationMethods {
4 export type LoadMigrationVersion = (callback: (err: Error, version: number) => void) => void
5 export type UpdateMigrationVersion = (newVersion: number, transaction: any, callback: any) => void
6}
7
8export interface ApplicationClass {
9 loadMigrationVersion: ApplicationMethods.LoadMigrationVersion
10 updateMigrationVersion: ApplicationMethods.UpdateMigrationVersion
11}
12
13export interface ApplicationAttributes {
14 migrationVersion: number
15}
16
17export interface ApplicationInstance extends ApplicationClass, ApplicationAttributes, Sequelize.Instance<ApplicationAttributes> {
18 id: number
19 createdAt: Date
20 updatedAt: Date
21}
22
23export interface ApplicationModel extends ApplicationClass, Sequelize.Model<ApplicationInstance, ApplicationAttributes> {}
diff --git a/server/models/application.ts b/server/models/application.ts
index 38a57e327..acd0dfbf2 100644
--- a/server/models/application.ts
+++ b/server/models/application.ts
@@ -1,5 +1,20 @@
1module.exports = function (sequelize, DataTypes) { 1import * as Sequelize from 'sequelize'
2 const Application = sequelize.define('Application', 2
3import { addMethodsToModel } from './utils'
4import {
5 ApplicationClass,
6 ApplicationAttributes,
7 ApplicationInstance,
8
9 ApplicationMethods
10} from './application-interface'
11
12let Application: Sequelize.Model<ApplicationInstance, ApplicationAttributes>
13let loadMigrationVersion: ApplicationMethods.LoadMigrationVersion
14let updateMigrationVersion: ApplicationMethods.UpdateMigrationVersion
15
16export default function defineApplication (sequelize: Sequelize.Sequelize, DataTypes) {
17 Application = sequelize.define<ApplicationInstance, ApplicationAttributes>('Application',
3 { 18 {
4 migrationVersion: { 19 migrationVersion: {
5 type: DataTypes.INTEGER, 20 type: DataTypes.INTEGER,
@@ -9,34 +24,31 @@ module.exports = function (sequelize, DataTypes) {
9 isInt: true 24 isInt: true
10 } 25 }
11 } 26 }
12 },
13 {
14 classMethods: {
15 loadMigrationVersion,
16 updateMigrationVersion
17 }
18 } 27 }
19 ) 28 )
20 29
30 const classMethods = [ loadMigrationVersion, updateMigrationVersion ]
31 addMethodsToModel(Application, classMethods)
32
21 return Application 33 return Application
22} 34}
23 35
24// --------------------------------------------------------------------------- 36// ---------------------------------------------------------------------------
25 37
26function loadMigrationVersion (callback) { 38loadMigrationVersion = function (callback: (err: Error, version: number) => void) {
27 const query = { 39 const query = {
28 attributes: [ 'migrationVersion' ] 40 attributes: [ 'migrationVersion' ]
29 } 41 }
30 42
31 return this.findOne(query).asCallback(function (err, data) { 43 return Application.findOne(query).asCallback(function (err, data) {
32 const version = data ? data.migrationVersion : null 44 const version = data ? data.migrationVersion : null
33 45
34 return callback(err, version) 46 return callback(err, version)
35 }) 47 })
36} 48}
37 49
38function updateMigrationVersion (newVersion, transaction, callback) { 50updateMigrationVersion = function (newVersion: number, transaction: any, callback: any) {
39 const options: { where?: any, transaction?: any } = { 51 const options: Sequelize.UpdateOptions = {
40 where: {} 52 where: {}
41 } 53 }
42 54
@@ -46,5 +58,5 @@ function updateMigrationVersion (newVersion, transaction, callback) {
46 options.transaction = transaction 58 options.transaction = transaction
47 } 59 }
48 60
49 return this.update({ migrationVersion: newVersion }, options).asCallback(callback) 61 return Application.update({ migrationVersion: newVersion }, options).asCallback(callback)
50} 62}
diff --git a/server/models/author-interface.ts b/server/models/author-interface.ts
new file mode 100644
index 000000000..d2475c3bd
--- /dev/null
+++ b/server/models/author-interface.ts
@@ -0,0 +1,21 @@
1import * as Sequelize from 'sequelize'
2
3export namespace AuthorMethods {
4 export type FindOrCreateAuthor = (name, podId, userId, transaction, callback) => void
5}
6
7export interface AuthorClass {
8 findOrCreateAuthor: AuthorMethods.FindOrCreateAuthor
9}
10
11export interface AuthorAttributes {
12 name: string
13}
14
15export interface AuthorInstance extends AuthorClass, AuthorAttributes, Sequelize.Instance<AuthorAttributes> {
16 id: number
17 createdAt: Date
18 updatedAt: Date
19}
20
21export interface AuthorModel extends AuthorClass, Sequelize.Model<AuthorInstance, AuthorAttributes> {}
diff --git a/server/models/author.ts b/server/models/author.ts
index 4a7396929..b543d17a0 100644
--- a/server/models/author.ts
+++ b/server/models/author.ts
@@ -1,7 +1,21 @@
1import * as Sequelize from 'sequelize'
2
1import { isUserUsernameValid } from '../helpers' 3import { isUserUsernameValid } from '../helpers'
2 4
3module.exports = function (sequelize, DataTypes) { 5import { addMethodsToModel } from './utils'
4 const Author = sequelize.define('Author', 6import {
7 AuthorClass,
8 AuthorInstance,
9 AuthorAttributes,
10
11 AuthorMethods
12} from './author-interface'
13
14let Author: Sequelize.Model<AuthorInstance, AuthorAttributes>
15let findOrCreateAuthor: AuthorMethods.FindOrCreateAuthor
16
17export default function defineAuthor (sequelize: Sequelize.Sequelize, DataTypes) {
18 Author = sequelize.define<AuthorInstance, AuthorAttributes>('Author',
5 { 19 {
6 name: { 20 name: {
7 type: DataTypes.STRING, 21 type: DataTypes.STRING,
@@ -30,22 +44,20 @@ module.exports = function (sequelize, DataTypes) {
30 fields: [ 'name', 'podId' ], 44 fields: [ 'name', 'podId' ],
31 unique: true 45 unique: true
32 } 46 }
33 ], 47 ]
34 classMethods: {
35 associate,
36
37 findOrCreateAuthor
38 }
39 } 48 }
40 ) 49 )
41 50
51 const classMethods = [ associate, findOrCreateAuthor ]
52 addMethodsToModel(Author, classMethods)
53
42 return Author 54 return Author
43} 55}
44 56
45// --------------------------------------------------------------------------- 57// ---------------------------------------------------------------------------
46 58
47function associate (models) { 59function associate (models) {
48 this.belongsTo(models.Pod, { 60 Author.belongsTo(models.Pod, {
49 foreignKey: { 61 foreignKey: {
50 name: 'podId', 62 name: 'podId',
51 allowNull: true 63 allowNull: true
@@ -53,7 +65,7 @@ function associate (models) {
53 onDelete: 'cascade' 65 onDelete: 'cascade'
54 }) 66 })
55 67
56 this.belongsTo(models.User, { 68 Author.belongsTo(models.User, {
57 foreignKey: { 69 foreignKey: {
58 name: 'userId', 70 name: 'userId',
59 allowNull: true 71 allowNull: true
@@ -62,7 +74,7 @@ function associate (models) {
62 }) 74 })
63} 75}
64 76
65function findOrCreateAuthor (name, podId, userId, transaction, callback) { 77findOrCreateAuthor = function (name, podId, userId, transaction, callback) {
66 if (!callback) { 78 if (!callback) {
67 callback = transaction 79 callback = transaction
68 transaction = null 80 transaction = null
@@ -81,7 +93,7 @@ function findOrCreateAuthor (name, podId, userId, transaction, callback) {
81 93
82 if (transaction) query.transaction = transaction 94 if (transaction) query.transaction = transaction
83 95
84 this.findOrCreate(query).asCallback(function (err, result) { 96 Author.findOrCreate(query).asCallback(function (err, result) {
85 if (err) return callback(err) 97 if (err) return callback(err)
86 98
87 // [ instance, wasCreated ] 99 // [ instance, wasCreated ]
diff --git a/server/models/index.ts b/server/models/index.ts
new file mode 100644
index 000000000..432c0dc4a
--- /dev/null
+++ b/server/models/index.ts
@@ -0,0 +1,17 @@
1export * from './application-interface'
2export * from './author-interface'
3export * from './job-interface'
4export * from './oauth-client-interface'
5export * from './oauth-token-interface'
6export * from './pod-interface'
7export * from './request-interface'
8export * from './request-to-pod-interface'
9export * from './request-video-event-interface'
10export * from './request-video-qadu-interface'
11export * from './tag-interface'
12export * from './user-video-rate-interface'
13export * from './user-interface'
14export * from './video-abuse-interface'
15export * from './video-blacklist-interface'
16export * from './video-tag-interface'
17export * from './video-interface'
diff --git a/server/models/job-interface.ts b/server/models/job-interface.ts
new file mode 100644
index 000000000..ad4e2d2b0
--- /dev/null
+++ b/server/models/job-interface.ts
@@ -0,0 +1,23 @@
1import * as Sequelize from 'sequelize'
2
3export namespace JobMethods {
4 export type ListWithLimit = (limit, state, callback) => void
5}
6
7export interface JobClass {
8 listWithLimit: JobMethods.ListWithLimit
9}
10
11export interface JobAttributes {
12 state: string
13 handlerName: string
14 handlerInputData: object
15}
16
17export interface JobInstance extends JobClass, JobAttributes, Sequelize.Instance<JobAttributes> {
18 id: number
19 createdAt: Date
20 updatedAt: Date
21}
22
23export interface JobModel extends JobClass, Sequelize.Model<JobInstance, JobAttributes> {}
diff --git a/server/models/job.ts b/server/models/job.ts
index 6843e399b..982b51499 100644
--- a/server/models/job.ts
+++ b/server/models/job.ts
@@ -1,11 +1,22 @@
1import { values } from 'lodash' 1import { values } from 'lodash'
2import * as Sequelize from 'sequelize'
2 3
3import { JOB_STATES } from '../initializers' 4import { JOB_STATES } from '../initializers'
4 5
5// --------------------------------------------------------------------------- 6import { addMethodsToModel } from './utils'
7import {
8 JobClass,
9 JobInstance,
10 JobAttributes,
11
12 JobMethods
13} from './job-interface'
14
15let Job: Sequelize.Model<JobInstance, JobAttributes>
16let listWithLimit: JobMethods.ListWithLimit
6 17
7module.exports = function (sequelize, DataTypes) { 18export default function defineJob (sequelize: Sequelize.Sequelize, DataTypes) {
8 const Job = sequelize.define('Job', 19 Job = sequelize.define<JobInstance, JobAttributes>('Job',
9 { 20 {
10 state: { 21 state: {
11 type: DataTypes.ENUM(values(JOB_STATES)), 22 type: DataTypes.ENUM(values(JOB_STATES)),
@@ -25,19 +36,19 @@ module.exports = function (sequelize, DataTypes) {
25 { 36 {
26 fields: [ 'state' ] 37 fields: [ 'state' ]
27 } 38 }
28 ], 39 ]
29 classMethods: {
30 listWithLimit
31 }
32 } 40 }
33 ) 41 )
34 42
43 const classMethods = [ listWithLimit ]
44 addMethodsToModel(Job, classMethods)
45
35 return Job 46 return Job
36} 47}
37 48
38// --------------------------------------------------------------------------- 49// ---------------------------------------------------------------------------
39 50
40function listWithLimit (limit, state, callback) { 51listWithLimit = function (limit, state, callback) {
41 const query = { 52 const query = {
42 order: [ 53 order: [
43 [ 'id', 'ASC' ] 54 [ 'id', 'ASC' ]
@@ -48,5 +59,5 @@ function listWithLimit (limit, state, callback) {
48 } 59 }
49 } 60 }
50 61
51 return this.findAll(query).asCallback(callback) 62 return Job.findAll(query).asCallback(callback)
52} 63}
diff --git a/server/models/oauth-client-interface.ts b/server/models/oauth-client-interface.ts
new file mode 100644
index 000000000..4efd6212a
--- /dev/null
+++ b/server/models/oauth-client-interface.ts
@@ -0,0 +1,28 @@
1import * as Sequelize from 'sequelize'
2
3export namespace OAuthClientMethods {
4 export type CountTotal = (callback) => void
5 export type LoadFirstClient = (callback) => void
6 export type GetByIdAndSecret = (clientId, clientSecret) => void
7}
8
9export interface OAuthClientClass {
10 countTotal: OAuthClientMethods.CountTotal
11 loadFirstClient: OAuthClientMethods.LoadFirstClient
12 getByIdAndSecret: OAuthClientMethods.GetByIdAndSecret
13}
14
15export interface OAuthClientAttributes {
16 clientId: string
17 clientSecret: string
18 grants: string[]
19 redirectUris: string[]
20}
21
22export interface OAuthClientInstance extends OAuthClientClass, OAuthClientAttributes, Sequelize.Instance<OAuthClientAttributes> {
23 id: number
24 createdAt: Date
25 updatedAt: Date
26}
27
28export interface OAuthClientModel extends OAuthClientClass, Sequelize.Model<OAuthClientInstance, OAuthClientAttributes> {}
diff --git a/server/models/oauth-client.ts b/server/models/oauth-client.ts
index 3198a85ef..2cefb5cb9 100644
--- a/server/models/oauth-client.ts
+++ b/server/models/oauth-client.ts
@@ -1,5 +1,21 @@
1module.exports = function (sequelize, DataTypes) { 1import * as Sequelize from 'sequelize'
2 const OAuthClient = sequelize.define('OAuthClient', 2
3import { addMethodsToModel } from './utils'
4import {
5 OAuthClientClass,
6 OAuthClientInstance,
7 OAuthClientAttributes,
8
9 OAuthClientMethods
10} from './oauth-client-interface'
11
12let OAuthClient: Sequelize.Model<OAuthClientInstance, OAuthClientAttributes>
13let countTotal: OAuthClientMethods.CountTotal
14let loadFirstClient: OAuthClientMethods.LoadFirstClient
15let getByIdAndSecret: OAuthClientMethods.GetByIdAndSecret
16
17export default function (sequelize, DataTypes) {
18 OAuthClient = sequelize.define('OAuthClient',
3 { 19 {
4 clientId: { 20 clientId: {
5 type: DataTypes.STRING, 21 type: DataTypes.STRING,
@@ -26,29 +42,40 @@ module.exports = function (sequelize, DataTypes) {
26 fields: [ 'clientId', 'clientSecret' ], 42 fields: [ 'clientId', 'clientSecret' ],
27 unique: true 43 unique: true
28 } 44 }
29 ], 45 ]
30 classMethods: {
31 countTotal,
32 getByIdAndSecret,
33 loadFirstClient
34 }
35 } 46 }
36 ) 47 )
37 48
49 const classMethods = [
50 associate,
51
52 countTotal,
53 getByIdAndSecret,
54 loadFirstClient
55 ]
56 addMethodsToModel(OAuthClient, classMethods)
57
38 return OAuthClient 58 return OAuthClient
39} 59}
40 60
41// --------------------------------------------------------------------------- 61// ---------------------------------------------------------------------------
42 62
43function countTotal (callback) { 63function associate (models) {
44 return this.count().asCallback(callback) 64 OAuthClient.hasMany(models.OAuthToken, {
65 foreignKey: 'oAuthClientId',
66 onDelete: 'cascade'
67 })
68}
69
70countTotal = function (callback) {
71 return OAuthClient.count().asCallback(callback)
45} 72}
46 73
47function loadFirstClient (callback) { 74loadFirstClient = function (callback) {
48 return this.findOne().asCallback(callback) 75 return OAuthClient.findOne().asCallback(callback)
49} 76}
50 77
51function getByIdAndSecret (clientId, clientSecret) { 78getByIdAndSecret = function (clientId, clientSecret) {
52 const query = { 79 const query = {
53 where: { 80 where: {
54 clientId: clientId, 81 clientId: clientId,
@@ -56,5 +83,5 @@ function getByIdAndSecret (clientId, clientSecret) {
56 } 83 }
57 } 84 }
58 85
59 return this.findOne(query) 86 return OAuthClient.findOne(query)
60} 87}
diff --git a/server/models/oauth-token-interface.ts b/server/models/oauth-token-interface.ts
new file mode 100644
index 000000000..a0cd1ffe7
--- /dev/null
+++ b/server/models/oauth-token-interface.ts
@@ -0,0 +1,34 @@
1import * as Sequelize from 'sequelize'
2
3import { UserModel } from './user-interface'
4
5export namespace OAuthTokenMethods {
6 export type GetByRefreshTokenAndPopulateClient = (refreshToken) => void
7 export type GetByTokenAndPopulateUser = (bearerToken) => void
8 export type GetByRefreshTokenAndPopulateUser = (refreshToken) => any
9 export type RemoveByUserId = (userId, callback) => void
10}
11
12export interface OAuthTokenClass {
13 getByRefreshTokenAndPopulateClient: OAuthTokenMethods.GetByRefreshTokenAndPopulateClient
14 getByTokenAndPopulateUser: OAuthTokenMethods.GetByTokenAndPopulateUser
15 getByRefreshTokenAndPopulateUser: OAuthTokenMethods.GetByRefreshTokenAndPopulateUser
16 removeByUserId: OAuthTokenMethods.RemoveByUserId
17}
18
19export interface OAuthTokenAttributes {
20 accessToken: string
21 accessTokenExpiresAt: Date
22 refreshToken: string
23 refreshTokenExpiresAt: Date
24
25 User?: UserModel
26}
27
28export interface OAuthTokenInstance extends OAuthTokenClass, OAuthTokenAttributes, Sequelize.Instance<OAuthTokenAttributes> {
29 id: number
30 createdAt: Date
31 updatedAt: Date
32}
33
34export interface OAuthTokenModel extends OAuthTokenClass, Sequelize.Model<OAuthTokenInstance, OAuthTokenAttributes> {}
diff --git a/server/models/oauth-token.ts b/server/models/oauth-token.ts
index 74c9180eb..567df1c12 100644
--- a/server/models/oauth-token.ts
+++ b/server/models/oauth-token.ts
@@ -1,9 +1,24 @@
1import * as Sequelize from 'sequelize'
2
1import { logger } from '../helpers' 3import { logger } from '../helpers'
2 4
3// --------------------------------------------------------------------------- 5import { addMethodsToModel } from './utils'
6import {
7 OAuthTokenClass,
8 OAuthTokenInstance,
9 OAuthTokenAttributes,
10
11 OAuthTokenMethods
12} from './oauth-token-interface'
13
14let OAuthToken: Sequelize.Model<OAuthTokenInstance, OAuthTokenAttributes>
15let getByRefreshTokenAndPopulateClient: OAuthTokenMethods.GetByRefreshTokenAndPopulateClient
16let getByTokenAndPopulateUser: OAuthTokenMethods.GetByTokenAndPopulateUser
17let getByRefreshTokenAndPopulateUser: OAuthTokenMethods.GetByRefreshTokenAndPopulateUser
18let removeByUserId: OAuthTokenMethods.RemoveByUserId
4 19
5module.exports = function (sequelize, DataTypes) { 20export default function (sequelize, DataTypes) {
6 const OAuthToken = sequelize.define('OAuthToken', 21 OAuthToken = sequelize.define('OAuthToken',
7 { 22 {
8 accessToken: { 23 accessToken: {
9 type: DataTypes.STRING, 24 type: DataTypes.STRING,
@@ -38,25 +53,27 @@ module.exports = function (sequelize, DataTypes) {
38 { 53 {
39 fields: [ 'oAuthClientId' ] 54 fields: [ 'oAuthClientId' ]
40 } 55 }
41 ], 56 ]
42 classMethods: {
43 associate,
44
45 getByRefreshTokenAndPopulateClient,
46 getByTokenAndPopulateUser,
47 getByRefreshTokenAndPopulateUser,
48 removeByUserId
49 }
50 } 57 }
51 ) 58 )
52 59
60 const classMethods = [
61 associate,
62
63 getByRefreshTokenAndPopulateClient,
64 getByTokenAndPopulateUser,
65 getByRefreshTokenAndPopulateUser,
66 removeByUserId
67 ]
68 addMethodsToModel(OAuthToken, classMethods)
69
53 return OAuthToken 70 return OAuthToken
54} 71}
55 72
56// --------------------------------------------------------------------------- 73// ---------------------------------------------------------------------------
57 74
58function associate (models) { 75function associate (models) {
59 this.belongsTo(models.User, { 76 OAuthToken.belongsTo(models.User, {
60 foreignKey: { 77 foreignKey: {
61 name: 'userId', 78 name: 'userId',
62 allowNull: false 79 allowNull: false
@@ -64,7 +81,7 @@ function associate (models) {
64 onDelete: 'cascade' 81 onDelete: 'cascade'
65 }) 82 })
66 83
67 this.belongsTo(models.OAuthClient, { 84 OAuthToken.belongsTo(models.OAuthClient, {
68 foreignKey: { 85 foreignKey: {
69 name: 'oAuthClientId', 86 name: 'oAuthClientId',
70 allowNull: false 87 allowNull: false
@@ -73,25 +90,25 @@ function associate (models) {
73 }) 90 })
74} 91}
75 92
76function getByRefreshTokenAndPopulateClient (refreshToken) { 93getByRefreshTokenAndPopulateClient = function (refreshToken) {
77 const query = { 94 const query = {
78 where: { 95 where: {
79 refreshToken: refreshToken 96 refreshToken: refreshToken
80 }, 97 },
81 include: [ this.associations.OAuthClient ] 98 include: [ OAuthToken['sequelize'].models.OAuthClient ]
82 } 99 }
83 100
84 return this.findOne(query).then(function (token) { 101 return OAuthToken.findOne(query).then(function (token) {
85 if (!token) return token 102 if (!token) return token
86 103
87 const tokenInfos = { 104 const tokenInfos = {
88 refreshToken: token.refreshToken, 105 refreshToken: token.refreshToken,
89 refreshTokenExpiresAt: token.refreshTokenExpiresAt, 106 refreshTokenExpiresAt: token.refreshTokenExpiresAt,
90 client: { 107 client: {
91 id: token.client.id 108 id: token['client'].id
92 }, 109 },
93 user: { 110 user: {
94 id: token.user 111 id: token['user']
95 } 112 }
96 } 113 }
97 114
@@ -101,42 +118,42 @@ function getByRefreshTokenAndPopulateClient (refreshToken) {
101 }) 118 })
102} 119}
103 120
104function getByTokenAndPopulateUser (bearerToken) { 121getByTokenAndPopulateUser = function (bearerToken) {
105 const query = { 122 const query = {
106 where: { 123 where: {
107 accessToken: bearerToken 124 accessToken: bearerToken
108 }, 125 },
109 include: [ this.sequelize.models.User ] 126 include: [ OAuthToken['sequelize'].models.User ]
110 } 127 }
111 128
112 return this.findOne(query).then(function (token) { 129 return OAuthToken.findOne(query).then(function (token) {
113 if (token) token.user = token.User 130 if (token) token['user'] = token.User
114 131
115 return token 132 return token
116 }) 133 })
117} 134}
118 135
119function getByRefreshTokenAndPopulateUser (refreshToken) { 136getByRefreshTokenAndPopulateUser = function (refreshToken) {
120 const query = { 137 const query = {
121 where: { 138 where: {
122 refreshToken: refreshToken 139 refreshToken: refreshToken
123 }, 140 },
124 include: [ this.sequelize.models.User ] 141 include: [ OAuthToken['sequelize'].models.User ]
125 } 142 }
126 143
127 return this.findOne(query).then(function (token) { 144 return OAuthToken.findOne(query).then(function (token) {
128 token.user = token.User 145 token['user'] = token.User
129 146
130 return token 147 return token
131 }) 148 })
132} 149}
133 150
134function removeByUserId (userId, callback) { 151removeByUserId = function (userId, callback) {
135 const query = { 152 const query = {
136 where: { 153 where: {
137 userId: userId 154 userId: userId
138 } 155 }
139 } 156 }
140 157
141 return this.destroy(query).asCallback(callback) 158 return OAuthToken.destroy(query).asCallback(callback)
142} 159}
diff --git a/server/models/pod-interface.ts b/server/models/pod-interface.ts
new file mode 100644
index 000000000..14c88bec6
--- /dev/null
+++ b/server/models/pod-interface.ts
@@ -0,0 +1,46 @@
1import * as Sequelize from 'sequelize'
2
3export namespace PodMethods {
4 export type ToFormatedJSON = () => void
5
6 export type CountAll = (callback) => void
7 export type IncrementScores = (ids, value, callback) => void
8 export type List = (callback) => void
9 export type ListAllIds = (transaction, callback) => void
10 export type ListRandomPodIdsWithRequest = (limit, tableWithPods, tableWithPodsJoins, callback) => void
11 export type ListBadPods = (callback) => void
12 export type Load = (id, callback) => void
13 export type LoadByHost = (host, callback) => void
14 export type RemoveAll = (callback) => void
15 export type UpdatePodsScore = (goodPods, badPods) => void
16}
17
18export interface PodClass {
19 countAll: PodMethods.CountAll
20 incrementScores: PodMethods.IncrementScores
21 list: PodMethods.List
22 listAllIds: PodMethods.ListAllIds
23 listRandomPodIdsWithRequest: PodMethods.ListRandomPodIdsWithRequest
24 listBadPods: PodMethods.ListBadPods
25 load: PodMethods.Load
26 loadByHost: PodMethods.LoadByHost
27 removeAll: PodMethods.RemoveAll
28 updatePodsScore: PodMethods.UpdatePodsScore
29}
30
31export interface PodAttributes {
32 host?: string
33 publicKey?: string
34 score?: number | Sequelize.literal // Sequelize literal for 'score +' + value
35 email?: string
36}
37
38export interface PodInstance extends PodClass, PodAttributes, Sequelize.Instance<PodAttributes> {
39 id: number
40 createdAt: Date
41 updatedAt: Date
42
43 toFormatedJSON: PodMethods.ToFormatedJSON,
44}
45
46export interface PodModel extends PodClass, Sequelize.Model<PodInstance, PodAttributes> {}
diff --git a/server/models/pod.ts b/server/models/pod.ts
index 0e0262978..2df32e4a4 100644
--- a/server/models/pod.ts
+++ b/server/models/pod.ts
@@ -1,13 +1,34 @@
1import { each, waterfall } from 'async' 1import { each, waterfall } from 'async'
2import { map } from 'lodash' 2import { map } from 'lodash'
3import * as Sequelize from 'sequelize'
3 4
4import { FRIEND_SCORE, PODS_SCORE } from '../initializers' 5import { FRIEND_SCORE, PODS_SCORE } from '../initializers'
5import { logger, isHostValid } from '../helpers' 6import { logger, isHostValid } from '../helpers'
6 7
7// --------------------------------------------------------------------------- 8import { addMethodsToModel } from './utils'
8 9import {
9module.exports = function (sequelize, DataTypes) { 10 PodClass,
10 const Pod = sequelize.define('Pod', 11 PodInstance,
12 PodAttributes,
13
14 PodMethods
15} from './pod-interface'
16
17let Pod: Sequelize.Model<PodInstance, PodAttributes>
18let toFormatedJSON: PodMethods.ToFormatedJSON
19let countAll: PodMethods.CountAll
20let incrementScores: PodMethods.IncrementScores
21let list: PodMethods.List
22let listAllIds: PodMethods.ListAllIds
23let listRandomPodIdsWithRequest: PodMethods.ListRandomPodIdsWithRequest
24let listBadPods: PodMethods.ListBadPods
25let load: PodMethods.Load
26let loadByHost: PodMethods.LoadByHost
27let removeAll: PodMethods.RemoveAll
28let updatePodsScore: PodMethods.UpdatePodsScore
29
30export default function (sequelize, DataTypes) {
31 Pod = sequelize.define('Pod',
11 { 32 {
12 host: { 33 host: {
13 type: DataTypes.STRING, 34 type: DataTypes.STRING,
@@ -49,33 +70,33 @@ module.exports = function (sequelize, DataTypes) {
49 { 70 {
50 fields: [ 'score' ] 71 fields: [ 'score' ]
51 } 72 }
52 ], 73 ]
53 classMethods: {
54 associate,
55
56 countAll,
57 incrementScores,
58 list,
59 listAllIds,
60 listRandomPodIdsWithRequest,
61 listBadPods,
62 load,
63 loadByHost,
64 updatePodsScore,
65 removeAll
66 },
67 instanceMethods: {
68 toFormatedJSON
69 }
70 } 74 }
71 ) 75 )
72 76
77 const classMethods = [
78 associate,
79
80 countAll,
81 incrementScores,
82 list,
83 listAllIds,
84 listRandomPodIdsWithRequest,
85 listBadPods,
86 load,
87 loadByHost,
88 updatePodsScore,
89 removeAll
90 ]
91 const instanceMethods = [ toFormatedJSON ]
92 addMethodsToModel(Pod, classMethods, instanceMethods)
93
73 return Pod 94 return Pod
74} 95}
75 96
76// ------------------------------ METHODS ------------------------------ 97// ------------------------------ METHODS ------------------------------
77 98
78function toFormatedJSON () { 99toFormatedJSON = function () {
79 const json = { 100 const json = {
80 id: this.id, 101 id: this.id,
81 host: this.host, 102 host: this.host,
@@ -90,22 +111,22 @@ function toFormatedJSON () {
90// ------------------------------ Statics ------------------------------ 111// ------------------------------ Statics ------------------------------
91 112
92function associate (models) { 113function associate (models) {
93 this.belongsToMany(models.Request, { 114 Pod.belongsToMany(models.Request, {
94 foreignKey: 'podId', 115 foreignKey: 'podId',
95 through: models.RequestToPod, 116 through: models.RequestToPod,
96 onDelete: 'cascade' 117 onDelete: 'cascade'
97 }) 118 })
98} 119}
99 120
100function countAll (callback) { 121countAll = function (callback) {
101 return this.count().asCallback(callback) 122 return Pod.count().asCallback(callback)
102} 123}
103 124
104function incrementScores (ids, value, callback) { 125incrementScores = function (ids, value, callback) {
105 if (!callback) callback = function () { /* empty */ } 126 if (!callback) callback = function () { /* empty */ }
106 127
107 const update = { 128 const update = {
108 score: this.sequelize.literal('score +' + value) 129 score: Sequelize.literal('score +' + value)
109 } 130 }
110 131
111 const options = { 132 const options = {
@@ -118,14 +139,14 @@ function incrementScores (ids, value, callback) {
118 validate: false 139 validate: false
119 } 140 }
120 141
121 return this.update(update, options).asCallback(callback) 142 return Pod.update(update, options).asCallback(callback)
122} 143}
123 144
124function list (callback) { 145list = function (callback) {
125 return this.findAll().asCallback(callback) 146 return Pod.findAll().asCallback(callback)
126} 147}
127 148
128function listAllIds (transaction, callback) { 149listAllIds = function (transaction, callback) {
129 if (!callback) { 150 if (!callback) {
130 callback = transaction 151 callback = transaction
131 transaction = null 152 transaction = null
@@ -137,22 +158,20 @@ function listAllIds (transaction, callback) {
137 158
138 if (transaction) query.transaction = transaction 159 if (transaction) query.transaction = transaction
139 160
140 return this.findAll(query).asCallback(function (err, pods) { 161 return Pod.findAll(query).asCallback(function (err, pods) {
141 if (err) return callback(err) 162 if (err) return callback(err)
142 163
143 return callback(null, map(pods, 'id')) 164 return callback(null, map(pods, 'id'))
144 }) 165 })
145} 166}
146 167
147function listRandomPodIdsWithRequest (limit, tableWithPods, tableWithPodsJoins, callback) { 168listRandomPodIdsWithRequest = function (limit, tableWithPods, tableWithPodsJoins, callback) {
148 if (!callback) { 169 if (!callback) {
149 callback = tableWithPodsJoins 170 callback = tableWithPodsJoins
150 tableWithPodsJoins = '' 171 tableWithPodsJoins = ''
151 } 172 }
152 173
153 const self = this 174 Pod.count().asCallback(function (err, count) {
154
155 self.count().asCallback(function (err, count) {
156 if (err) return callback(err) 175 if (err) return callback(err)
157 176
158 // Optimization... 177 // Optimization...
@@ -171,13 +190,13 @@ function listRandomPodIdsWithRequest (limit, tableWithPods, tableWithPodsJoins,
171 where: { 190 where: {
172 id: { 191 id: {
173 $in: [ 192 $in: [
174 this.sequelize.literal(`SELECT DISTINCT "${tableWithPods}"."podId" FROM "${tableWithPods}" ${tableWithPodsJoins}`) 193 Sequelize.literal(`SELECT DISTINCT "${tableWithPods}"."podId" FROM "${tableWithPods}" ${tableWithPodsJoins}`)
175 ] 194 ]
176 } 195 }
177 } 196 }
178 } 197 }
179 198
180 return this.findAll(query).asCallback(function (err, pods) { 199 return Pod.findAll(query).asCallback(function (err, pods) {
181 if (err) return callback(err) 200 if (err) return callback(err)
182 201
183 return callback(null, map(pods, 'id')) 202 return callback(null, map(pods, 'id'))
@@ -185,49 +204,47 @@ function listRandomPodIdsWithRequest (limit, tableWithPods, tableWithPodsJoins,
185 }) 204 })
186} 205}
187 206
188function listBadPods (callback) { 207listBadPods = function (callback) {
189 const query = { 208 const query = {
190 where: { 209 where: {
191 score: { $lte: 0 } 210 score: { $lte: 0 }
192 } 211 }
193 } 212 }
194 213
195 return this.findAll(query).asCallback(callback) 214 return Pod.findAll(query).asCallback(callback)
196} 215}
197 216
198function load (id, callback) { 217load = function (id, callback) {
199 return this.findById(id).asCallback(callback) 218 return Pod.findById(id).asCallback(callback)
200} 219}
201 220
202function loadByHost (host, callback) { 221loadByHost = function (host, callback) {
203 const query = { 222 const query = {
204 where: { 223 where: {
205 host: host 224 host: host
206 } 225 }
207 } 226 }
208 227
209 return this.findOne(query).asCallback(callback) 228 return Pod.findOne(query).asCallback(callback)
210} 229}
211 230
212function removeAll (callback) { 231removeAll = function (callback) {
213 return this.destroy().asCallback(callback) 232 return Pod.destroy().asCallback(callback)
214} 233}
215 234
216function updatePodsScore (goodPods, badPods) { 235updatePodsScore = function (goodPods, badPods) {
217 const self = this
218
219 logger.info('Updating %d good pods and %d bad pods scores.', goodPods.length, badPods.length) 236 logger.info('Updating %d good pods and %d bad pods scores.', goodPods.length, badPods.length)
220 237
221 if (goodPods.length !== 0) { 238 if (goodPods.length !== 0) {
222 this.incrementScores(goodPods, PODS_SCORE.BONUS, function (err) { 239 incrementScores(goodPods, PODS_SCORE.BONUS, function (err) {
223 if (err) logger.error('Cannot increment scores of good pods.', { error: err }) 240 if (err) logger.error('Cannot increment scores of good pods.', { error: err })
224 }) 241 })
225 } 242 }
226 243
227 if (badPods.length !== 0) { 244 if (badPods.length !== 0) {
228 this.incrementScores(badPods, PODS_SCORE.MALUS, function (err) { 245 incrementScores(badPods, PODS_SCORE.MALUS, function (err) {
229 if (err) logger.error('Cannot decrement scores of bad pods.', { error: err }) 246 if (err) logger.error('Cannot decrement scores of bad pods.', { error: err })
230 removeBadPods.call(self) 247 removeBadPods()
231 }) 248 })
232 } 249 }
233} 250}
@@ -236,11 +253,9 @@ function updatePodsScore (goodPods, badPods) {
236 253
237// Remove pods with a score of 0 (too many requests where they were unreachable) 254// Remove pods with a score of 0 (too many requests where they were unreachable)
238function removeBadPods () { 255function removeBadPods () {
239 const self = this
240
241 waterfall([ 256 waterfall([
242 function findBadPods (callback) { 257 function findBadPods (callback) {
243 self.sequelize.models.Pod.listBadPods(function (err, pods) { 258 listBadPods(function (err, pods) {
244 if (err) { 259 if (err) {
245 logger.error('Cannot find bad pods.', { error: err }) 260 logger.error('Cannot find bad pods.', { error: err })
246 return callback(err) 261 return callback(err)
diff --git a/server/models/request-interface.ts b/server/models/request-interface.ts
new file mode 100644
index 000000000..2bba8ce7f
--- /dev/null
+++ b/server/models/request-interface.ts
@@ -0,0 +1,32 @@
1import * as Sequelize from 'sequelize'
2
3import { PodAttributes } from './pod-interface'
4
5export namespace RequestMethods {
6 export type CountTotalRequests = (callback) => void
7 export type ListWithLimitAndRandom = (limitPods, limitRequestsPerPod, callback) => void
8 export type RemoveWithEmptyTo = (callback) => void
9 export type RemoveAll = (callback) => void
10}
11
12export interface RequestClass {
13 countTotalRequests: RequestMethods.CountTotalRequests
14 listWithLimitAndRandom: RequestMethods.ListWithLimitAndRandom
15 removeWithEmptyTo: RequestMethods.RemoveWithEmptyTo
16 removeAll: RequestMethods.RemoveAll
17}
18
19export interface RequestAttributes {
20 request: object
21 endpoint: string
22}
23
24export interface RequestInstance extends Sequelize.Instance<RequestAttributes> {
25 id: number
26 createdAt: Date
27 updatedAt: Date
28
29 setPods: Sequelize.HasManySetAssociationsMixin<PodAttributes, number>
30}
31
32export interface RequestModel extends RequestClass, Sequelize.Model<RequestInstance, RequestAttributes> {}
diff --git a/server/models/request-to-pod-interface.ts b/server/models/request-to-pod-interface.ts
new file mode 100644
index 000000000..52116d6c4
--- /dev/null
+++ b/server/models/request-to-pod-interface.ts
@@ -0,0 +1,20 @@
1import * as Sequelize from 'sequelize'
2
3export namespace RequestToPodMethods {
4 export type RemoveByRequestIdsAndPod = (requestsIds, podId, callback) => void
5}
6
7export interface RequestToPodClass {
8 removeByRequestIdsAndPod: RequestToPodMethods.RemoveByRequestIdsAndPod
9}
10
11export interface RequestToPodAttributes {
12}
13
14export interface RequestToPodInstance extends Sequelize.Instance<RequestToPodAttributes> {
15 id: number
16 createdAt: Date
17 updatedAt: Date
18}
19
20export interface RequestToPodModel extends RequestToPodClass, Sequelize.Model<RequestToPodInstance, RequestToPodAttributes> {}
diff --git a/server/models/request-to-pod.ts b/server/models/request-to-pod.ts
index 479202e40..681f808b7 100644
--- a/server/models/request-to-pod.ts
+++ b/server/models/request-to-pod.ts
@@ -1,5 +1,19 @@
1module.exports = function (sequelize, DataTypes) { 1import * as Sequelize from 'sequelize'
2 const RequestToPod = sequelize.define('RequestToPod', {}, { 2
3import { addMethodsToModel } from './utils'
4import {
5 RequestToPodClass,
6 RequestToPodInstance,
7 RequestToPodAttributes,
8
9 RequestToPodMethods
10} from './request-to-pod-interface'
11
12let RequestToPod: Sequelize.Model<RequestToPodInstance, RequestToPodAttributes>
13let removeByRequestIdsAndPod: RequestToPodMethods.RemoveByRequestIdsAndPod
14
15export default function (sequelize, DataTypes) {
16 RequestToPod = sequelize.define('RequestToPod', {}, {
3 indexes: [ 17 indexes: [
4 { 18 {
5 fields: [ 'requestId' ] 19 fields: [ 'requestId' ]
@@ -11,18 +25,20 @@ module.exports = function (sequelize, DataTypes) {
11 fields: [ 'requestId', 'podId' ], 25 fields: [ 'requestId', 'podId' ],
12 unique: true 26 unique: true
13 } 27 }
14 ], 28 ]
15 classMethods: {
16 removeByRequestIdsAndPod
17 }
18 }) 29 })
19 30
31 const classMethods = [
32 removeByRequestIdsAndPod
33 ]
34 addMethodsToModel(RequestToPod, classMethods)
35
20 return RequestToPod 36 return RequestToPod
21} 37}
22 38
23// --------------------------------------------------------------------------- 39// ---------------------------------------------------------------------------
24 40
25function removeByRequestIdsAndPod (requestsIds, podId, callback) { 41removeByRequestIdsAndPod = function (requestsIds, podId, callback) {
26 if (!callback) callback = function () { /* empty */ } 42 if (!callback) callback = function () { /* empty */ }
27 43
28 const query = { 44 const query = {
@@ -34,5 +50,5 @@ function removeByRequestIdsAndPod (requestsIds, podId, callback) {
34 } 50 }
35 } 51 }
36 52
37 this.destroy(query).asCallback(callback) 53 RequestToPod.destroy(query).asCallback(callback)
38} 54}
diff --git a/server/models/request-video-event-interface.ts b/server/models/request-video-event-interface.ts
new file mode 100644
index 000000000..a31c7108f
--- /dev/null
+++ b/server/models/request-video-event-interface.ts
@@ -0,0 +1,26 @@
1import * as Sequelize from 'sequelize'
2
3export namespace RequestVideoEventMethods {
4 export type CountTotalRequests = (callback) => void
5 export type ListWithLimitAndRandom = (limitPods, limitRequestsPerPod, callback) => void
6 export type RemoveByRequestIdsAndPod = (ids, podId, callback) => void
7 export type RemoveAll = (callback) => void
8}
9
10export interface RequestVideoEventClass {
11 countTotalRequests: RequestVideoEventMethods.CountTotalRequests
12 listWithLimitAndRandom: RequestVideoEventMethods.ListWithLimitAndRandom
13 removeByRequestIdsAndPod: RequestVideoEventMethods.RemoveByRequestIdsAndPod
14 removeAll: RequestVideoEventMethods.RemoveAll
15}
16
17export interface RequestVideoEventAttributes {
18 type: string
19 count: number
20}
21
22export interface RequestVideoEventInstance extends Sequelize.Instance<RequestVideoEventAttributes> {
23 id: number
24}
25
26export interface RequestVideoEventModel extends RequestVideoEventClass, Sequelize.Model<RequestVideoEventInstance, RequestVideoEventAttributes> {}
diff --git a/server/models/request-video-event.ts b/server/models/request-video-event.ts
index c61525029..234e2a8a9 100644
--- a/server/models/request-video-event.ts
+++ b/server/models/request-video-event.ts
@@ -3,14 +3,28 @@
3*/ 3*/
4 4
5import { values } from 'lodash' 5import { values } from 'lodash'
6import * as Sequelize from 'sequelize'
6 7
7import { REQUEST_VIDEO_EVENT_TYPES } from '../initializers' 8import { REQUEST_VIDEO_EVENT_TYPES } from '../initializers'
8import { isVideoEventCountValid } from '../helpers' 9import { isVideoEventCountValid } from '../helpers'
9 10
10// --------------------------------------------------------------------------- 11import { addMethodsToModel } from './utils'
12import {
13 RequestVideoEventClass,
14 RequestVideoEventInstance,
15 RequestVideoEventAttributes,
16
17 RequestVideoEventMethods
18} from './request-video-event-interface'
19
20let RequestVideoEvent: Sequelize.Model<RequestVideoEventInstance, RequestVideoEventAttributes>
21let countTotalRequests: RequestVideoEventMethods.CountTotalRequests
22let listWithLimitAndRandom: RequestVideoEventMethods.ListWithLimitAndRandom
23let removeByRequestIdsAndPod: RequestVideoEventMethods.RemoveByRequestIdsAndPod
24let removeAll: RequestVideoEventMethods.RemoveAll
11 25
12module.exports = function (sequelize, DataTypes) { 26export default function (sequelize, DataTypes) {
13 const RequestVideoEvent = sequelize.define('RequestVideoEvent', 27 RequestVideoEvent = sequelize.define('RequestVideoEvent',
14 { 28 {
15 type: { 29 type: {
16 type: DataTypes.ENUM(values(REQUEST_VIDEO_EVENT_TYPES)), 30 type: DataTypes.ENUM(values(REQUEST_VIDEO_EVENT_TYPES)),
@@ -33,26 +47,27 @@ module.exports = function (sequelize, DataTypes) {
33 { 47 {
34 fields: [ 'videoId' ] 48 fields: [ 'videoId' ]
35 } 49 }
36 ], 50 ]
37 classMethods: {
38 associate,
39
40 listWithLimitAndRandom,
41
42 countTotalRequests,
43 removeAll,
44 removeByRequestIdsAndPod
45 }
46 } 51 }
47 ) 52 )
48 53
54 const classMethods = [
55 associate,
56
57 listWithLimitAndRandom,
58 countTotalRequests,
59 removeAll,
60 removeByRequestIdsAndPod
61 ]
62 addMethodsToModel(RequestVideoEvent, classMethods)
63
49 return RequestVideoEvent 64 return RequestVideoEvent
50} 65}
51 66
52// ------------------------------ STATICS ------------------------------ 67// ------------------------------ STATICS ------------------------------
53 68
54function associate (models) { 69function associate (models) {
55 this.belongsTo(models.Video, { 70 RequestVideoEvent.belongsTo(models.Video, {
56 foreignKey: { 71 foreignKey: {
57 name: 'videoId', 72 name: 'videoId',
58 allowNull: false 73 allowNull: false
@@ -61,14 +76,13 @@ function associate (models) {
61 }) 76 })
62} 77}
63 78
64function countTotalRequests (callback) { 79countTotalRequests = function (callback) {
65 const query = {} 80 const query = {}
66 return this.count(query).asCallback(callback) 81 return RequestVideoEvent.count(query).asCallback(callback)
67} 82}
68 83
69function listWithLimitAndRandom (limitPods, limitRequestsPerPod, callback) { 84listWithLimitAndRandom = function (limitPods, limitRequestsPerPod, callback) {
70 const self = this 85 const Pod = RequestVideoEvent['sequelize'].models.Pod
71 const Pod = this.sequelize.models.Pod
72 86
73 // We make a join between videos and authors to find the podId of our video event requests 87 // We make a join between videos and authors to find the podId of our video event requests
74 const podJoins = 'INNER JOIN "Videos" ON "Videos"."authorId" = "Authors"."id" ' + 88 const podJoins = 'INNER JOIN "Videos" ON "Videos"."authorId" = "Authors"."id" ' +
@@ -86,13 +100,13 @@ function listWithLimitAndRandom (limitPods, limitRequestsPerPod, callback) {
86 ], 100 ],
87 include: [ 101 include: [
88 { 102 {
89 model: self.sequelize.models.Video, 103 model: RequestVideoEvent['sequelize'].models.Video,
90 include: [ 104 include: [
91 { 105 {
92 model: self.sequelize.models.Author, 106 model: RequestVideoEvent['sequelize'].models.Author,
93 include: [ 107 include: [
94 { 108 {
95 model: self.sequelize.models.Pod, 109 model: RequestVideoEvent['sequelize'].models.Pod,
96 where: { 110 where: {
97 id: { 111 id: {
98 $in: podIds 112 $in: podIds
@@ -106,7 +120,7 @@ function listWithLimitAndRandom (limitPods, limitRequestsPerPod, callback) {
106 ] 120 ]
107 } 121 }
108 122
109 self.findAll(query).asCallback(function (err, requests) { 123 RequestVideoEvent.findAll(query).asCallback(function (err, requests) {
110 if (err) return callback(err) 124 if (err) return callback(err)
111 125
112 const requestsGrouped = groupAndTruncateRequests(requests, limitRequestsPerPod) 126 const requestsGrouped = groupAndTruncateRequests(requests, limitRequestsPerPod)
@@ -115,7 +129,7 @@ function listWithLimitAndRandom (limitPods, limitRequestsPerPod, callback) {
115 }) 129 })
116} 130}
117 131
118function removeByRequestIdsAndPod (ids, podId, callback) { 132removeByRequestIdsAndPod = function (ids, podId, callback) {
119 const query = { 133 const query = {
120 where: { 134 where: {
121 id: { 135 id: {
@@ -124,10 +138,10 @@ function removeByRequestIdsAndPod (ids, podId, callback) {
124 }, 138 },
125 include: [ 139 include: [
126 { 140 {
127 model: this.sequelize.models.Video, 141 model: RequestVideoEvent['sequelize'].models.Video,
128 include: [ 142 include: [
129 { 143 {
130 model: this.sequelize.models.Author, 144 model: RequestVideoEvent['sequelize'].models.Author,
131 where: { 145 where: {
132 podId 146 podId
133 } 147 }
@@ -137,12 +151,12 @@ function removeByRequestIdsAndPod (ids, podId, callback) {
137 ] 151 ]
138 } 152 }
139 153
140 this.destroy(query).asCallback(callback) 154 RequestVideoEvent.destroy(query).asCallback(callback)
141} 155}
142 156
143function removeAll (callback) { 157removeAll = function (callback) {
144 // Delete all requests 158 // Delete all requests
145 this.truncate({ cascade: true }).asCallback(callback) 159 RequestVideoEvent.truncate({ cascade: true }).asCallback(callback)
146} 160}
147 161
148// --------------------------------------------------------------------------- 162// ---------------------------------------------------------------------------
diff --git a/server/models/request-video-qadu-interface.ts b/server/models/request-video-qadu-interface.ts
new file mode 100644
index 000000000..6fe34ee91
--- /dev/null
+++ b/server/models/request-video-qadu-interface.ts
@@ -0,0 +1,25 @@
1import * as Sequelize from 'sequelize'
2
3export namespace RequestVideoQaduMethods {
4 export type CountTotalRequests = (callback) => void
5 export type ListWithLimitAndRandom = (limitPods, limitRequestsPerPod, callback) => void
6 export type RemoveByRequestIdsAndPod = (ids, podId, callback) => void
7 export type RemoveAll = (callback) => void
8}
9
10export interface RequestVideoQaduClass {
11 countTotalRequests: RequestVideoQaduMethods.CountTotalRequests
12 listWithLimitAndRandom: RequestVideoQaduMethods.ListWithLimitAndRandom
13 removeByRequestIdsAndPod: RequestVideoQaduMethods.RemoveByRequestIdsAndPod
14 removeAll: RequestVideoQaduMethods.RemoveAll
15}
16
17export interface RequestVideoQaduAttributes {
18 type: string
19}
20
21export interface RequestVideoQaduInstance extends Sequelize.Instance<RequestVideoQaduAttributes> {
22 id: number
23}
24
25export interface RequestVideoQaduModel extends RequestVideoQaduClass, Sequelize.Model<RequestVideoQaduInstance, RequestVideoQaduAttributes> {}
diff --git a/server/models/request-video-qadu.ts b/server/models/request-video-qadu.ts
index 2b1ed07c9..e914e06cd 100644
--- a/server/models/request-video-qadu.ts
+++ b/server/models/request-video-qadu.ts
@@ -10,13 +10,27 @@
10*/ 10*/
11 11
12import { values } from 'lodash' 12import { values } from 'lodash'
13import * as Sequelize from 'sequelize'
13 14
14import { REQUEST_VIDEO_QADU_TYPES } from '../initializers' 15import { REQUEST_VIDEO_QADU_TYPES } from '../initializers'
15 16
16// --------------------------------------------------------------------------- 17import { addMethodsToModel } from './utils'
18import {
19 RequestVideoQaduClass,
20 RequestVideoQaduInstance,
21 RequestVideoQaduAttributes,
22
23 RequestVideoQaduMethods
24} from './request-video-qadu-interface'
25
26let RequestVideoQadu: Sequelize.Model<RequestVideoQaduInstance, RequestVideoQaduAttributes>
27let countTotalRequests: RequestVideoQaduMethods.CountTotalRequests
28let listWithLimitAndRandom: RequestVideoQaduMethods.ListWithLimitAndRandom
29let removeByRequestIdsAndPod: RequestVideoQaduMethods.RemoveByRequestIdsAndPod
30let removeAll: RequestVideoQaduMethods.RemoveAll
17 31
18module.exports = function (sequelize, DataTypes) { 32export default function (sequelize, DataTypes) {
19 const RequestVideoQadu = sequelize.define('RequestVideoQadu', 33 RequestVideoQadu = sequelize.define('RequestVideoQadu',
20 { 34 {
21 type: { 35 type: {
22 type: DataTypes.ENUM(values(REQUEST_VIDEO_QADU_TYPES)), 36 type: DataTypes.ENUM(values(REQUEST_VIDEO_QADU_TYPES)),
@@ -32,26 +46,27 @@ module.exports = function (sequelize, DataTypes) {
32 { 46 {
33 fields: [ 'videoId' ] 47 fields: [ 'videoId' ]
34 } 48 }
35 ], 49 ]
36 classMethods: {
37 associate,
38
39 listWithLimitAndRandom,
40
41 countTotalRequests,
42 removeAll,
43 removeByRequestIdsAndPod
44 }
45 } 50 }
46 ) 51 )
47 52
53 const classMethods = [
54 associate,
55
56 listWithLimitAndRandom,
57 countTotalRequests,
58 removeAll,
59 removeByRequestIdsAndPod
60 ]
61 addMethodsToModel(RequestVideoQadu, classMethods)
62
48 return RequestVideoQadu 63 return RequestVideoQadu
49} 64}
50 65
51// ------------------------------ STATICS ------------------------------ 66// ------------------------------ STATICS ------------------------------
52 67
53function associate (models) { 68function associate (models) {
54 this.belongsTo(models.Pod, { 69 RequestVideoQadu.belongsTo(models.Pod, {
55 foreignKey: { 70 foreignKey: {
56 name: 'podId', 71 name: 'podId',
57 allowNull: false 72 allowNull: false
@@ -59,7 +74,7 @@ function associate (models) {
59 onDelete: 'CASCADE' 74 onDelete: 'CASCADE'
60 }) 75 })
61 76
62 this.belongsTo(models.Video, { 77 RequestVideoQadu.belongsTo(models.Video, {
63 foreignKey: { 78 foreignKey: {
64 name: 'videoId', 79 name: 'videoId',
65 allowNull: false 80 allowNull: false
@@ -68,14 +83,13 @@ function associate (models) {
68 }) 83 })
69} 84}
70 85
71function countTotalRequests (callback) { 86countTotalRequests = function (callback) {
72 const query = {} 87 const query = {}
73 return this.count(query).asCallback(callback) 88 return RequestVideoQadu.count(query).asCallback(callback)
74} 89}
75 90
76function listWithLimitAndRandom (limitPods, limitRequestsPerPod, callback) { 91listWithLimitAndRandom = function (limitPods, limitRequestsPerPod, callback) {
77 const self = this 92 const Pod = RequestVideoQadu['sequelize'].models.Pod
78 const Pod = this.sequelize.models.Pod
79 93
80 Pod.listRandomPodIdsWithRequest(limitPods, 'RequestVideoQadus', function (err, podIds) { 94 Pod.listRandomPodIdsWithRequest(limitPods, 'RequestVideoQadus', function (err, podIds) {
81 if (err) return callback(err) 95 if (err) return callback(err)
@@ -86,7 +100,7 @@ function listWithLimitAndRandom (limitPods, limitRequestsPerPod, callback) {
86 const query = { 100 const query = {
87 include: [ 101 include: [
88 { 102 {
89 model: self.sequelize.models.Pod, 103 model: RequestVideoQadu['sequelize'].models.Pod,
90 where: { 104 where: {
91 id: { 105 id: {
92 $in: podIds 106 $in: podIds
@@ -94,12 +108,12 @@ function listWithLimitAndRandom (limitPods, limitRequestsPerPod, callback) {
94 } 108 }
95 }, 109 },
96 { 110 {
97 model: self.sequelize.models.Video 111 model: RequestVideoQadu['sequelize'].models.Video
98 } 112 }
99 ] 113 ]
100 } 114 }
101 115
102 self.findAll(query).asCallback(function (err, requests) { 116 RequestVideoQadu.findAll(query).asCallback(function (err, requests) {
103 if (err) return callback(err) 117 if (err) return callback(err)
104 118
105 const requestsGrouped = groupAndTruncateRequests(requests, limitRequestsPerPod) 119 const requestsGrouped = groupAndTruncateRequests(requests, limitRequestsPerPod)
@@ -108,7 +122,7 @@ function listWithLimitAndRandom (limitPods, limitRequestsPerPod, callback) {
108 }) 122 })
109} 123}
110 124
111function removeByRequestIdsAndPod (ids, podId, callback) { 125removeByRequestIdsAndPod = function (ids, podId, callback) {
112 const query = { 126 const query = {
113 where: { 127 where: {
114 id: { 128 id: {
@@ -118,12 +132,12 @@ function removeByRequestIdsAndPod (ids, podId, callback) {
118 } 132 }
119 } 133 }
120 134
121 this.destroy(query).asCallback(callback) 135 RequestVideoQadu.destroy(query).asCallback(callback)
122} 136}
123 137
124function removeAll (callback) { 138removeAll = function (callback) {
125 // Delete all requests 139 // Delete all requests
126 this.truncate({ cascade: true }).asCallback(callback) 140 RequestVideoQadu.truncate({ cascade: true }).asCallback(callback)
127} 141}
128 142
129// --------------------------------------------------------------------------- 143// ---------------------------------------------------------------------------
diff --git a/server/models/request.ts b/server/models/request.ts
index 672f79d11..18fa291fa 100644
--- a/server/models/request.ts
+++ b/server/models/request.ts
@@ -1,11 +1,25 @@
1import { values } from 'lodash' 1import { values } from 'lodash'
2import * as Sequelize from 'sequelize'
2 3
3import { REQUEST_ENDPOINTS } from '../initializers' 4import { REQUEST_ENDPOINTS } from '../initializers'
4 5
5// --------------------------------------------------------------------------- 6import { addMethodsToModel } from './utils'
7import {
8 RequestClass,
9 RequestInstance,
10 RequestAttributes,
11
12 RequestMethods
13} from './request-interface'
14
15let Request: Sequelize.Model<RequestInstance, RequestAttributes>
16let countTotalRequests: RequestMethods.CountTotalRequests
17let listWithLimitAndRandom: RequestMethods.ListWithLimitAndRandom
18let removeWithEmptyTo: RequestMethods.RemoveWithEmptyTo
19let removeAll: RequestMethods.RemoveAll
6 20
7module.exports = function (sequelize, DataTypes) { 21export default function (sequelize, DataTypes) {
8 const Request = sequelize.define('Request', 22 Request = sequelize.define('Request',
9 { 23 {
10 request: { 24 request: {
11 type: DataTypes.JSON, 25 type: DataTypes.JSON,
@@ -15,27 +29,27 @@ module.exports = function (sequelize, DataTypes) {
15 type: DataTypes.ENUM(values(REQUEST_ENDPOINTS)), 29 type: DataTypes.ENUM(values(REQUEST_ENDPOINTS)),
16 allowNull: false 30 allowNull: false
17 } 31 }
18 },
19 {
20 classMethods: {
21 associate,
22
23 listWithLimitAndRandom,
24
25 countTotalRequests,
26 removeAll,
27 removeWithEmptyTo
28 }
29 } 32 }
30 ) 33 )
31 34
35 const classMethods = [
36 associate,
37
38 listWithLimitAndRandom,
39
40 countTotalRequests,
41 removeAll,
42 removeWithEmptyTo
43 ]
44 addMethodsToModel(Request, classMethods)
45
32 return Request 46 return Request
33} 47}
34 48
35// ------------------------------ STATICS ------------------------------ 49// ------------------------------ STATICS ------------------------------
36 50
37function associate (models) { 51function associate (models) {
38 this.belongsToMany(models.Pod, { 52 Request.belongsToMany(models.Pod, {
39 foreignKey: { 53 foreignKey: {
40 name: 'requestId', 54 name: 'requestId',
41 allowNull: false 55 allowNull: false
@@ -45,19 +59,18 @@ function associate (models) {
45 }) 59 })
46} 60}
47 61
48function countTotalRequests (callback) { 62countTotalRequests = function (callback) {
49 // We need to include Pod because there are no cascade delete when a pod is removed 63 // We need to include Pod because there are no cascade delete when a pod is removed
50 // So we could count requests that do not have existing pod anymore 64 // So we could count requests that do not have existing pod anymore
51 const query = { 65 const query = {
52 include: [ this.sequelize.models.Pod ] 66 include: [ Request['sequelize'].models.Pod ]
53 } 67 }
54 68
55 return this.count(query).asCallback(callback) 69 return Request.count(query).asCallback(callback)
56} 70}
57 71
58function listWithLimitAndRandom (limitPods, limitRequestsPerPod, callback) { 72listWithLimitAndRandom = function (limitPods, limitRequestsPerPod, callback) {
59 const self = this 73 const Pod = Request['sequelize'].models.Pod
60 const Pod = this.sequelize.models.Pod
61 74
62 Pod.listRandomPodIdsWithRequest(limitPods, 'RequestToPods', function (err, podIds) { 75 Pod.listRandomPodIdsWithRequest(limitPods, 'RequestToPods', function (err, podIds) {
63 if (err) return callback(err) 76 if (err) return callback(err)
@@ -73,7 +86,7 @@ function listWithLimitAndRandom (limitPods, limitRequestsPerPod, callback) {
73 ], 86 ],
74 include: [ 87 include: [
75 { 88 {
76 model: self.sequelize.models.Pod, 89 model: Request['sequelize'].models.Pod,
77 where: { 90 where: {
78 id: { 91 id: {
79 $in: podIds 92 $in: podIds
@@ -83,7 +96,7 @@ function listWithLimitAndRandom (limitPods, limitRequestsPerPod, callback) {
83 ] 96 ]
84 } 97 }
85 98
86 self.findAll(query).asCallback(function (err, requests) { 99 Request.findAll(query).asCallback(function (err, requests) {
87 if (err) return callback(err) 100 if (err) return callback(err)
88 101
89 const requestsGrouped = groupAndTruncateRequests(requests, limitRequestsPerPod) 102 const requestsGrouped = groupAndTruncateRequests(requests, limitRequestsPerPod)
@@ -92,25 +105,25 @@ function listWithLimitAndRandom (limitPods, limitRequestsPerPod, callback) {
92 }) 105 })
93} 106}
94 107
95function removeAll (callback) { 108removeAll = function (callback) {
96 // Delete all requests 109 // Delete all requests
97 this.truncate({ cascade: true }).asCallback(callback) 110 Request.truncate({ cascade: true }).asCallback(callback)
98} 111}
99 112
100function removeWithEmptyTo (callback) { 113removeWithEmptyTo = function (callback) {
101 if (!callback) callback = function () { /* empty */ } 114 if (!callback) callback = function () { /* empty */ }
102 115
103 const query = { 116 const query = {
104 where: { 117 where: {
105 id: { 118 id: {
106 $notIn: [ 119 $notIn: [
107 this.sequelize.literal('SELECT "requestId" FROM "RequestToPods"') 120 Sequelize.literal('SELECT "requestId" FROM "RequestToPods"')
108 ] 121 ]
109 } 122 }
110 } 123 }
111 } 124 }
112 125
113 this.destroy(query).asCallback(callback) 126 Request.destroy(query).asCallback(callback)
114} 127}
115 128
116// --------------------------------------------------------------------------- 129// ---------------------------------------------------------------------------
diff --git a/server/models/tag-interface.ts b/server/models/tag-interface.ts
new file mode 100644
index 000000000..f96e1e9c5
--- /dev/null
+++ b/server/models/tag-interface.ts
@@ -0,0 +1,19 @@
1import * as Sequelize from 'sequelize'
2
3export namespace TagMethods {
4 export type FindOrCreateTags = (tags, transaction, callback) => void
5}
6
7export interface TagClass {
8 findOrCreateTags: TagMethods.FindOrCreateTags
9}
10
11export interface TagAttributes {
12 name: string
13}
14
15export interface TagInstance extends TagClass, TagAttributes, Sequelize.Instance<TagAttributes> {
16 id: number
17}
18
19export interface TagModel extends TagClass, Sequelize.Model<TagInstance, TagAttributes> {}
diff --git a/server/models/tag.ts b/server/models/tag.ts
index 85a0442d2..b2a9c9f81 100644
--- a/server/models/tag.ts
+++ b/server/models/tag.ts
@@ -1,9 +1,20 @@
1import { each } from 'async' 1import { each } from 'async'
2import * as Sequelize from 'sequelize'
2 3
3// --------------------------------------------------------------------------- 4import { addMethodsToModel } from './utils'
5import {
6 TagClass,
7 TagInstance,
8 TagAttributes,
9
10 TagMethods
11} from './tag-interface'
4 12
5module.exports = function (sequelize, DataTypes) { 13let Tag: Sequelize.Model<TagInstance, TagAttributes>
6 const Tag = sequelize.define('Tag', 14let findOrCreateTags: TagMethods.FindOrCreateTags
15
16export default function (sequelize, DataTypes) {
17 Tag = sequelize.define('Tag',
7 { 18 {
8 name: { 19 name: {
9 type: DataTypes.STRING, 20 type: DataTypes.STRING,
@@ -17,35 +28,36 @@ module.exports = function (sequelize, DataTypes) {
17 fields: [ 'name' ], 28 fields: [ 'name' ],
18 unique: true 29 unique: true
19 } 30 }
20 ], 31 ]
21 classMethods: {
22 associate,
23
24 findOrCreateTags
25 }
26 } 32 }
27 ) 33 )
28 34
35 const classMethods = [
36 associate,
37
38 findOrCreateTags
39 ]
40 addMethodsToModel(Tag, classMethods)
41
29 return Tag 42 return Tag
30} 43}
31 44
32// --------------------------------------------------------------------------- 45// ---------------------------------------------------------------------------
33 46
34function associate (models) { 47function associate (models) {
35 this.belongsToMany(models.Video, { 48 Tag.belongsToMany(models.Video, {
36 foreignKey: 'tagId', 49 foreignKey: 'tagId',
37 through: models.VideoTag, 50 through: models.VideoTag,
38 onDelete: 'cascade' 51 onDelete: 'cascade'
39 }) 52 })
40} 53}
41 54
42function findOrCreateTags (tags, transaction, callback) { 55findOrCreateTags = function (tags, transaction, callback) {
43 if (!callback) { 56 if (!callback) {
44 callback = transaction 57 callback = transaction
45 transaction = null 58 transaction = null
46 } 59 }
47 60
48 const self = this
49 const tagInstances = [] 61 const tagInstances = []
50 62
51 each(tags, function (tag, callbackEach) { 63 each(tags, function (tag, callbackEach) {
@@ -60,7 +72,7 @@ function findOrCreateTags (tags, transaction, callback) {
60 72
61 if (transaction) query.transaction = transaction 73 if (transaction) query.transaction = transaction
62 74
63 self.findOrCreate(query).asCallback(function (err, res) { 75 Tag.findOrCreate(query).asCallback(function (err, res) {
64 if (err) return callbackEach(err) 76 if (err) return callbackEach(err)
65 77
66 // res = [ tag, isCreated ] 78 // res = [ tag, isCreated ]
diff --git a/server/models/user-interface.ts b/server/models/user-interface.ts
new file mode 100644
index 000000000..a504f42a1
--- /dev/null
+++ b/server/models/user-interface.ts
@@ -0,0 +1,45 @@
1import * as Sequelize from 'sequelize'
2
3export namespace UserMethods {
4 export type IsPasswordMatch = (password, callback) => void
5 export type ToFormatedJSON = () => void
6 export type IsAdmin = () => boolean
7
8 export type CountTotal = (callback) => void
9 export type GetByUsername = (username) => any
10 export type List = (callback) => void
11 export type ListForApi = (start, count, sort, callback) => void
12 export type LoadById = (id, callback) => void
13 export type LoadByUsername = (username, callback) => void
14 export type LoadByUsernameOrEmail = (username, email, callback) => void
15}
16
17export interface UserClass {
18 isPasswordMatch: UserMethods.IsPasswordMatch,
19 toFormatedJSON: UserMethods.ToFormatedJSON,
20 isAdmin: UserMethods.IsAdmin,
21
22 countTotal: UserMethods.CountTotal,
23 getByUsername: UserMethods.GetByUsername,
24 list: UserMethods.List,
25 listForApi: UserMethods.ListForApi,
26 loadById: UserMethods.LoadById,
27 loadByUsername: UserMethods.LoadByUsername,
28 loadByUsernameOrEmail: UserMethods.LoadByUsernameOrEmail
29}
30
31export interface UserAttributes {
32 password: string
33 username: string
34 email: string
35 displayNSFW?: boolean
36 role: string
37}
38
39export interface UserInstance extends UserClass, UserAttributes, Sequelize.Instance<UserAttributes> {
40 id: number
41 createdAt: Date
42 updatedAt: Date
43}
44
45export interface UserModel extends UserClass, Sequelize.Model<UserInstance, UserAttributes> {}
diff --git a/server/models/user-video-rate-interface.ts b/server/models/user-video-rate-interface.ts
new file mode 100644
index 000000000..57d2e2b91
--- /dev/null
+++ b/server/models/user-video-rate-interface.ts
@@ -0,0 +1,21 @@
1import * as Sequelize from 'sequelize'
2
3export namespace UserVideoRateMethods {
4 export type Load = (userId, videoId, transaction, callback) => void
5}
6
7export interface UserVideoRateClass {
8 load: UserVideoRateMethods.Load
9}
10
11export interface UserVideoRateAttributes {
12 type: string
13}
14
15export interface UserVideoRateInstance extends Sequelize.Instance<UserVideoRateAttributes> {
16 id: number
17 createdAt: Date
18 updatedAt: Date
19}
20
21export interface UserVideoRateModel extends UserVideoRateClass, Sequelize.Model<UserVideoRateInstance, UserVideoRateAttributes> {}
diff --git a/server/models/user-video-rate.ts b/server/models/user-video-rate.ts
index 6603c7862..87886d8d0 100644
--- a/server/models/user-video-rate.ts
+++ b/server/models/user-video-rate.ts
@@ -3,13 +3,24 @@
3 3
4*/ 4*/
5import { values } from 'lodash' 5import { values } from 'lodash'
6import * as Sequelize from 'sequelize'
6 7
7import { VIDEO_RATE_TYPES } from '../initializers' 8import { VIDEO_RATE_TYPES } from '../initializers'
8 9
9// --------------------------------------------------------------------------- 10import { addMethodsToModel } from './utils'
11import {
12 UserVideoRateClass,
13 UserVideoRateInstance,
14 UserVideoRateAttributes,
10 15
11module.exports = function (sequelize, DataTypes) { 16 UserVideoRateMethods
12 const UserVideoRate = sequelize.define('UserVideoRate', 17} from './user-video-rate-interface'
18
19let UserVideoRate: Sequelize.Model<UserVideoRateInstance, UserVideoRateAttributes>
20let load: UserVideoRateMethods.Load
21
22export default function (sequelize, DataTypes) {
23 UserVideoRate = sequelize.define('UserVideoRate',
13 { 24 {
14 type: { 25 type: {
15 type: DataTypes.ENUM(values(VIDEO_RATE_TYPES)), 26 type: DataTypes.ENUM(values(VIDEO_RATE_TYPES)),
@@ -22,22 +33,24 @@ module.exports = function (sequelize, DataTypes) {
22 fields: [ 'videoId', 'userId', 'type' ], 33 fields: [ 'videoId', 'userId', 'type' ],
23 unique: true 34 unique: true
24 } 35 }
25 ], 36 ]
26 classMethods: {
27 associate,
28
29 load
30 }
31 } 37 }
32 ) 38 )
33 39
40 const classMethods = [
41 associate,
42
43 load
44 ]
45 addMethodsToModel(UserVideoRate, classMethods)
46
34 return UserVideoRate 47 return UserVideoRate
35} 48}
36 49
37// ------------------------------ STATICS ------------------------------ 50// ------------------------------ STATICS ------------------------------
38 51
39function associate (models) { 52function associate (models) {
40 this.belongsTo(models.Video, { 53 UserVideoRate.belongsTo(models.Video, {
41 foreignKey: { 54 foreignKey: {
42 name: 'videoId', 55 name: 'videoId',
43 allowNull: false 56 allowNull: false
@@ -45,7 +58,7 @@ function associate (models) {
45 onDelete: 'CASCADE' 58 onDelete: 'CASCADE'
46 }) 59 })
47 60
48 this.belongsTo(models.User, { 61 UserVideoRate.belongsTo(models.User, {
49 foreignKey: { 62 foreignKey: {
50 name: 'userId', 63 name: 'userId',
51 allowNull: false 64 allowNull: false
@@ -54,21 +67,14 @@ function associate (models) {
54 }) 67 })
55} 68}
56 69
57function load (userId, videoId, transaction, callback) { 70load = function (userId, videoId, transaction, callback) {
58 if (!callback) { 71 const options: Sequelize.FindOptions = {
59 callback = transaction
60 transaction = null
61 }
62
63 const query = {
64 where: { 72 where: {
65 userId, 73 userId,
66 videoId 74 videoId
67 } 75 }
68 } 76 }
69
70 const options: any = {}
71 if (transaction) options.transaction = transaction 77 if (transaction) options.transaction = transaction
72 78
73 return this.findOne(query, options).asCallback(callback) 79 return UserVideoRate.findOne(options).asCallback(callback)
74} 80}
diff --git a/server/models/user.ts b/server/models/user.ts
index d63a50cc4..12ddaaeb7 100644
--- a/server/models/user.ts
+++ b/server/models/user.ts
@@ -1,4 +1,5 @@
1import { values } from 'lodash' 1import { values } from 'lodash'
2import * as Sequelize from 'sequelize'
2 3
3import { getSort } from './utils' 4import { getSort } from './utils'
4import { USER_ROLES } from '../initializers' 5import { USER_ROLES } from '../initializers'
@@ -10,10 +11,29 @@ import {
10 isUserDisplayNSFWValid 11 isUserDisplayNSFWValid
11} from '../helpers' 12} from '../helpers'
12 13
13// --------------------------------------------------------------------------- 14import { addMethodsToModel } from './utils'
14 15import {
15module.exports = function (sequelize, DataTypes) { 16 UserClass,
16 const User = sequelize.define('User', 17 UserInstance,
18 UserAttributes,
19
20 UserMethods
21} from './user-interface'
22
23let User: Sequelize.Model<UserInstance, UserAttributes>
24let isPasswordMatch: UserMethods.IsPasswordMatch
25let toFormatedJSON: UserMethods.ToFormatedJSON
26let isAdmin: UserMethods.IsAdmin
27let countTotal: UserMethods.CountTotal
28let getByUsername: UserMethods.GetByUsername
29let list: UserMethods.List
30let listForApi: UserMethods.ListForApi
31let loadById: UserMethods.LoadById
32let loadByUsername: UserMethods.LoadByUsername
33let loadByUsernameOrEmail: UserMethods.LoadByUsernameOrEmail
34
35export default function (sequelize, DataTypes) {
36 User = sequelize.define('User',
17 { 37 {
18 password: { 38 password: {
19 type: DataTypes.STRING, 39 type: DataTypes.STRING,
@@ -69,22 +89,6 @@ module.exports = function (sequelize, DataTypes) {
69 unique: true 89 unique: true
70 } 90 }
71 ], 91 ],
72 classMethods: {
73 associate,
74
75 countTotal,
76 getByUsername,
77 list,
78 listForApi,
79 loadById,
80 loadByUsername,
81 loadByUsernameOrEmail
82 },
83 instanceMethods: {
84 isPasswordMatch,
85 toFormatedJSON,
86 isAdmin
87 },
88 hooks: { 92 hooks: {
89 beforeCreate: beforeCreateOrUpdate, 93 beforeCreate: beforeCreateOrUpdate,
90 beforeUpdate: beforeCreateOrUpdate 94 beforeUpdate: beforeCreateOrUpdate
@@ -92,26 +96,46 @@ module.exports = function (sequelize, DataTypes) {
92 } 96 }
93 ) 97 )
94 98
99 const classMethods = [
100 associate,
101
102 countTotal,
103 getByUsername,
104 list,
105 listForApi,
106 loadById,
107 loadByUsername,
108 loadByUsernameOrEmail
109 ]
110 const instanceMethods = [
111 isPasswordMatch,
112 toFormatedJSON,
113 isAdmin
114 ]
115 addMethodsToModel(User, classMethods, instanceMethods)
116
95 return User 117 return User
96} 118}
97 119
98function beforeCreateOrUpdate (user, options, next) { 120function beforeCreateOrUpdate (user, options) {
99 cryptPassword(user.password, function (err, hash) { 121 return new Promise(function (resolve, reject) {
100 if (err) return next(err) 122 cryptPassword(user.password, function (err, hash) {
123 if (err) return reject(err)
101 124
102 user.password = hash 125 user.password = hash
103 126
104 return next() 127 return resolve()
128 })
105 }) 129 })
106} 130}
107 131
108// ------------------------------ METHODS ------------------------------ 132// ------------------------------ METHODS ------------------------------
109 133
110function isPasswordMatch (password, callback) { 134isPasswordMatch = function (password, callback) {
111 return comparePassword(password, this.password, callback) 135 return comparePassword(password, this.password, callback)
112} 136}
113 137
114function toFormatedJSON () { 138toFormatedJSON = function () {
115 return { 139 return {
116 id: this.id, 140 id: this.id,
117 username: this.username, 141 username: this.username,
@@ -122,76 +146,76 @@ function toFormatedJSON () {
122 } 146 }
123} 147}
124 148
125function isAdmin () { 149isAdmin = function () {
126 return this.role === USER_ROLES.ADMIN 150 return this.role === USER_ROLES.ADMIN
127} 151}
128 152
129// ------------------------------ STATICS ------------------------------ 153// ------------------------------ STATICS ------------------------------
130 154
131function associate (models) { 155function associate (models) {
132 this.hasOne(models.Author, { 156 User.hasOne(models.Author, {
133 foreignKey: 'userId', 157 foreignKey: 'userId',
134 onDelete: 'cascade' 158 onDelete: 'cascade'
135 }) 159 })
136 160
137 this.hasMany(models.OAuthToken, { 161 User.hasMany(models.OAuthToken, {
138 foreignKey: 'userId', 162 foreignKey: 'userId',
139 onDelete: 'cascade' 163 onDelete: 'cascade'
140 }) 164 })
141} 165}
142 166
143function countTotal (callback) { 167countTotal = function (callback) {
144 return this.count().asCallback(callback) 168 return this.count().asCallback(callback)
145} 169}
146 170
147function getByUsername (username) { 171getByUsername = function (username) {
148 const query = { 172 const query = {
149 where: { 173 where: {
150 username: username 174 username: username
151 } 175 }
152 } 176 }
153 177
154 return this.findOne(query) 178 return User.findOne(query)
155} 179}
156 180
157function list (callback) { 181list = function (callback) {
158 return this.find().asCallback(callback) 182 return User.find().asCallback(callback)
159} 183}
160 184
161function listForApi (start, count, sort, callback) { 185listForApi = function (start, count, sort, callback) {
162 const query = { 186 const query = {
163 offset: start, 187 offset: start,
164 limit: count, 188 limit: count,
165 order: [ getSort(sort) ] 189 order: [ getSort(sort) ]
166 } 190 }
167 191
168 return this.findAndCountAll(query).asCallback(function (err, result) { 192 return User.findAndCountAll(query).asCallback(function (err, result) {
169 if (err) return callback(err) 193 if (err) return callback(err)
170 194
171 return callback(null, result.rows, result.count) 195 return callback(null, result.rows, result.count)
172 }) 196 })
173} 197}
174 198
175function loadById (id, callback) { 199loadById = function (id, callback) {
176 return this.findById(id).asCallback(callback) 200 return User.findById(id).asCallback(callback)
177} 201}
178 202
179function loadByUsername (username, callback) { 203loadByUsername = function (username, callback) {
180 const query = { 204 const query = {
181 where: { 205 where: {
182 username: username 206 username: username
183 } 207 }
184 } 208 }
185 209
186 return this.findOne(query).asCallback(callback) 210 return User.findOne(query).asCallback(callback)
187} 211}
188 212
189function loadByUsernameOrEmail (username, email, callback) { 213loadByUsernameOrEmail = function (username, email, callback) {
190 const query = { 214 const query = {
191 where: { 215 where: {
192 $or: [ { username }, { email } ] 216 $or: [ { username }, { email } ]
193 } 217 }
194 } 218 }
195 219
196 return this.findOne(query).asCallback(callback) 220 return User.findOne(query).asCallback(callback)
197} 221}
diff --git a/server/models/utils.ts b/server/models/utils.ts
index 601811913..fd84a9239 100644
--- a/server/models/utils.ts
+++ b/server/models/utils.ts
@@ -14,8 +14,14 @@ function getSort (value) {
14 return [ field, direction ] 14 return [ field, direction ]
15} 15}
16 16
17function addMethodsToModel (model: any, classMethods: Function[], instanceMethods: Function[] = []) {
18 classMethods.forEach(m => model[m.name] = m)
19 instanceMethods.forEach(m => model.prototype[m.name] = m)
20}
21
17// --------------------------------------------------------------------------- 22// ---------------------------------------------------------------------------
18 23
19export { 24export {
25 addMethodsToModel,
20 getSort 26 getSort
21} 27}
diff --git a/server/models/video-abuse-interface.ts b/server/models/video-abuse-interface.ts
new file mode 100644
index 000000000..9b77fc6f5
--- /dev/null
+++ b/server/models/video-abuse-interface.ts
@@ -0,0 +1,24 @@
1import * as Sequelize from 'sequelize'
2
3export namespace VideoAbuseMethods {
4 export type toFormatedJSON = () => void
5
6 export type ListForApi = (start, count, sort, callback) => void
7}
8
9export interface VideoAbuseClass {
10 listForApi: VideoAbuseMethods.ListForApi
11}
12
13export interface VideoAbuseAttributes {
14 reporterUsername: string
15 reason: string
16}
17
18export interface VideoAbuseInstance extends Sequelize.Instance<VideoAbuseAttributes> {
19 id: number
20 createdAt: Date
21 updatedAt: Date
22}
23
24export interface VideoAbuseModel extends VideoAbuseClass, Sequelize.Model<VideoAbuseInstance, VideoAbuseAttributes> {}
diff --git a/server/models/video-abuse.ts b/server/models/video-abuse.ts
index 2a18a293d..92168439c 100644
--- a/server/models/video-abuse.ts
+++ b/server/models/video-abuse.ts
@@ -1,9 +1,22 @@
1import * as Sequelize from 'sequelize'
2
1import { CONFIG } from '../initializers' 3import { CONFIG } from '../initializers'
2import { isVideoAbuseReporterUsernameValid, isVideoAbuseReasonValid } from '../helpers' 4import { isVideoAbuseReporterUsernameValid, isVideoAbuseReasonValid } from '../helpers'
3import { getSort } from './utils'
4 5
5module.exports = function (sequelize, DataTypes) { 6import { addMethodsToModel, getSort } from './utils'
6 const VideoAbuse = sequelize.define('VideoAbuse', 7import {
8 VideoAbuseClass,
9 VideoAbuseInstance,
10 VideoAbuseAttributes,
11
12 VideoAbuseMethods
13} from './video-abuse-interface'
14
15let VideoAbuse: Sequelize.Model<VideoAbuseInstance, VideoAbuseAttributes>
16let listForApi: VideoAbuseMethods.ListForApi
17
18export default function (sequelize, DataTypes) {
19 VideoAbuse = sequelize.define('VideoAbuse',
7 { 20 {
8 reporterUsername: { 21 reporterUsername: {
9 type: DataTypes.STRING, 22 type: DataTypes.STRING,
@@ -34,25 +47,51 @@ module.exports = function (sequelize, DataTypes) {
34 { 47 {
35 fields: [ 'reporterPodId' ] 48 fields: [ 'reporterPodId' ]
36 } 49 }
37 ], 50 ]
38 classMethods: {
39 associate,
40
41 listForApi
42 },
43 instanceMethods: {
44 toFormatedJSON
45 }
46 } 51 }
47 ) 52 )
48 53
54 const classMethods = [
55 associate,
56
57 listForApi
58 ]
59 const instanceMethods = [
60 toFormatedJSON
61 ]
62 addMethodsToModel(VideoAbuse, classMethods, instanceMethods)
63
49 return VideoAbuse 64 return VideoAbuse
50} 65}
51 66
52// --------------------------------------------------------------------------- 67// ------------------------------ METHODS ------------------------------
68
69function toFormatedJSON () {
70 let reporterPodHost
71
72 if (this.Pod) {
73 reporterPodHost = this.Pod.host
74 } else {
75 // It means it's our video
76 reporterPodHost = CONFIG.WEBSERVER.HOST
77 }
78
79 const json = {
80 id: this.id,
81 reporterPodHost,
82 reason: this.reason,
83 reporterUsername: this.reporterUsername,
84 videoId: this.videoId,
85 createdAt: this.createdAt
86 }
87
88 return json
89}
90
91// ------------------------------ STATICS ------------------------------
53 92
54function associate (models) { 93function associate (models) {
55 this.belongsTo(models.Pod, { 94 VideoAbuse.belongsTo(models.Pod, {
56 foreignKey: { 95 foreignKey: {
57 name: 'reporterPodId', 96 name: 'reporterPodId',
58 allowNull: true 97 allowNull: true
@@ -60,7 +99,7 @@ function associate (models) {
60 onDelete: 'cascade' 99 onDelete: 'cascade'
61 }) 100 })
62 101
63 this.belongsTo(models.Video, { 102 VideoAbuse.belongsTo(models.Video, {
64 foreignKey: { 103 foreignKey: {
65 name: 'videoId', 104 name: 'videoId',
66 allowNull: false 105 allowNull: false
@@ -69,44 +108,24 @@ function associate (models) {
69 }) 108 })
70} 109}
71 110
72function listForApi (start, count, sort, callback) { 111listForApi = function (start, count, sort, callback) {
73 const query = { 112 const query = {
74 offset: start, 113 offset: start,
75 limit: count, 114 limit: count,
76 order: [ getSort(sort) ], 115 order: [ getSort(sort) ],
77 include: [ 116 include: [
78 { 117 {
79 model: this.sequelize.models.Pod, 118 model: VideoAbuse['sequelize'].models.Pod,
80 required: false 119 required: false
81 } 120 }
82 ] 121 ]
83 } 122 }
84 123
85 return this.findAndCountAll(query).asCallback(function (err, result) { 124 return VideoAbuse.findAndCountAll(query).asCallback(function (err, result) {
86 if (err) return callback(err) 125 if (err) return callback(err)
87 126
88 return callback(null, result.rows, result.count) 127 return callback(null, result.rows, result.count)
89 }) 128 })
90} 129}
91 130
92function toFormatedJSON () {
93 let reporterPodHost
94
95 if (this.Pod) {
96 reporterPodHost = this.Pod.host
97 } else {
98 // It means it's our video
99 reporterPodHost = CONFIG.WEBSERVER.HOST
100 }
101
102 const json = {
103 id: this.id,
104 reporterPodHost,
105 reason: this.reason,
106 reporterUsername: this.reporterUsername,
107 videoId: this.videoId,
108 createdAt: this.createdAt
109 }
110 131
111 return json
112}
diff --git a/server/models/video-blacklist-interface.ts b/server/models/video-blacklist-interface.ts
new file mode 100644
index 000000000..ae2cd6748
--- /dev/null
+++ b/server/models/video-blacklist-interface.ts
@@ -0,0 +1,31 @@
1import * as Sequelize from 'sequelize'
2
3export namespace BlacklistedVideoMethods {
4 export type ToFormatedJSON = () => void
5
6 export type CountTotal = (callback) => void
7 export type List = (callback) => void
8 export type ListForApi = (start, count, sort, callback) => void
9 export type LoadById = (id, callback) => void
10 export type LoadByVideoId = (id, callback) => void
11}
12
13export interface BlacklistedVideoClass {
14 toFormatedJSON: BlacklistedVideoMethods.ToFormatedJSON
15 countTotal: BlacklistedVideoMethods.CountTotal
16 list: BlacklistedVideoMethods.List
17 listForApi: BlacklistedVideoMethods.ListForApi
18 loadById: BlacklistedVideoMethods.LoadById
19 loadByVideoId: BlacklistedVideoMethods.LoadByVideoId
20}
21
22export interface BlacklistedVideoAttributes {
23}
24
25export interface BlacklistedVideoInstance extends BlacklistedVideoClass, BlacklistedVideoAttributes, Sequelize.Instance<BlacklistedVideoAttributes> {
26 id: number
27 createdAt: Date
28 updatedAt: Date
29}
30
31export interface BlacklistedVideoModel extends BlacklistedVideoClass, Sequelize.Model<BlacklistedVideoInstance, BlacklistedVideoAttributes> {}
diff --git a/server/models/video-blacklist.ts b/server/models/video-blacklist.ts
index 1f00702c7..fe72d5d46 100644
--- a/server/models/video-blacklist.ts
+++ b/server/models/video-blacklist.ts
@@ -1,9 +1,24 @@
1import { getSort } from './utils' 1import * as Sequelize from 'sequelize'
2 2
3// --------------------------------------------------------------------------- 3import { addMethodsToModel, getSort } from './utils'
4 4import {
5module.exports = function (sequelize, DataTypes) { 5 BlacklistedVideoClass,
6 const BlacklistedVideo = sequelize.define('BlacklistedVideo', 6 BlacklistedVideoInstance,
7 BlacklistedVideoAttributes,
8
9 BlacklistedVideoMethods
10} from './video-blacklist-interface'
11
12let BlacklistedVideo: Sequelize.Model<BlacklistedVideoInstance, BlacklistedVideoAttributes>
13let toFormatedJSON: BlacklistedVideoMethods.ToFormatedJSON
14let countTotal: BlacklistedVideoMethods.CountTotal
15let list: BlacklistedVideoMethods.List
16let listForApi: BlacklistedVideoMethods.ListForApi
17let loadById: BlacklistedVideoMethods.LoadById
18let loadByVideoId: BlacklistedVideoMethods.LoadByVideoId
19
20export default function (sequelize, DataTypes) {
21 BlacklistedVideo = sequelize.define('BlacklistedVideo',
7 {}, 22 {},
8 { 23 {
9 indexes: [ 24 indexes: [
@@ -11,29 +26,30 @@ module.exports = function (sequelize, DataTypes) {
11 fields: [ 'videoId' ], 26 fields: [ 'videoId' ],
12 unique: true 27 unique: true
13 } 28 }
14 ], 29 ]
15 classMethods: {
16 associate,
17
18 countTotal,
19 list,
20 listForApi,
21 loadById,
22 loadByVideoId
23 },
24 instanceMethods: {
25 toFormatedJSON
26 },
27 hooks: {}
28 } 30 }
29 ) 31 )
30 32
33 const classMethods = [
34 associate,
35
36 countTotal,
37 list,
38 listForApi,
39 loadById,
40 loadByVideoId
41 ]
42 const instanceMethods = [
43 toFormatedJSON
44 ]
45 addMethodsToModel(BlacklistedVideo, classMethods, instanceMethods)
46
31 return BlacklistedVideo 47 return BlacklistedVideo
32} 48}
33 49
34// ------------------------------ METHODS ------------------------------ 50// ------------------------------ METHODS ------------------------------
35 51
36function toFormatedJSON () { 52toFormatedJSON = function () {
37 return { 53 return {
38 id: this.id, 54 id: this.id,
39 videoId: this.videoId, 55 videoId: this.videoId,
@@ -44,44 +60,44 @@ function toFormatedJSON () {
44// ------------------------------ STATICS ------------------------------ 60// ------------------------------ STATICS ------------------------------
45 61
46function associate (models) { 62function associate (models) {
47 this.belongsTo(models.Video, { 63 BlacklistedVideo.belongsTo(models.Video, {
48 foreignKey: 'videoId', 64 foreignKey: 'videoId',
49 onDelete: 'cascade' 65 onDelete: 'cascade'
50 }) 66 })
51} 67}
52 68
53function countTotal (callback) { 69countTotal = function (callback) {
54 return this.count().asCallback(callback) 70 return BlacklistedVideo.count().asCallback(callback)
55} 71}
56 72
57function list (callback) { 73list = function (callback) {
58 return this.findAll().asCallback(callback) 74 return BlacklistedVideo.findAll().asCallback(callback)
59} 75}
60 76
61function listForApi (start, count, sort, callback) { 77listForApi = function (start, count, sort, callback) {
62 const query = { 78 const query = {
63 offset: start, 79 offset: start,
64 limit: count, 80 limit: count,
65 order: [ getSort(sort) ] 81 order: [ getSort(sort) ]
66 } 82 }
67 83
68 return this.findAndCountAll(query).asCallback(function (err, result) { 84 return BlacklistedVideo.findAndCountAll(query).asCallback(function (err, result) {
69 if (err) return callback(err) 85 if (err) return callback(err)
70 86
71 return callback(null, result.rows, result.count) 87 return callback(null, result.rows, result.count)
72 }) 88 })
73} 89}
74 90
75function loadById (id, callback) { 91loadById = function (id, callback) {
76 return this.findById(id).asCallback(callback) 92 return BlacklistedVideo.findById(id).asCallback(callback)
77} 93}
78 94
79function loadByVideoId (id, callback) { 95loadByVideoId = function (id, callback) {
80 const query = { 96 const query = {
81 where: { 97 where: {
82 videoId: id 98 videoId: id
83 } 99 }
84 } 100 }
85 101
86 return this.find(query).asCallback(callback) 102 return BlacklistedVideo.find(query).asCallback(callback)
87} 103}
diff --git a/server/models/video-interface.ts b/server/models/video-interface.ts
new file mode 100644
index 000000000..b8dbeea35
--- /dev/null
+++ b/server/models/video-interface.ts
@@ -0,0 +1,75 @@
1import * as Sequelize from 'sequelize'
2
3export namespace VideoMethods {
4 export type GenerateMagnetUri = () => void
5 export type GetVideoFilename = () => void
6 export type GetThumbnailName = () => void
7 export type GetPreviewName = () => void
8 export type GetTorrentName = () => void
9 export type IsOwned = () => void
10 export type ToFormatedJSON = () => void
11 export type ToAddRemoteJSON = (callback) => void
12 export type ToUpdateRemoteJSON = (callback) => void
13 export type TranscodeVideofile = (callback) => void
14
15 export type GenerateThumbnailFromData = (video, thumbnailData, callback) => void
16 export type GetDurationFromFile = (videoPath, callback) => void
17 export type List = (callback) => void
18 export type ListForApi = (start, count, sort, callback) => void
19 export type LoadByHostAndRemoteId = (fromHost, remoteId, callback) => void
20 export type ListOwnedAndPopulateAuthorAndTags = (callback) => void
21 export type ListOwnedByAuthor = (author, callback) => void
22 export type Load = (id, callback) => void
23 export type LoadAndPopulateAuthor = (id, callback) => void
24 export type LoadAndPopulateAuthorAndPodAndTags = (id, callback) => void
25 export type SearchAndPopulateAuthorAndPodAndTags = (value, field, start, count, sort, callback) => void
26}
27
28export interface VideoClass {
29 generateMagnetUri: VideoMethods.GenerateMagnetUri
30 getVideoFilename: VideoMethods.GetVideoFilename
31 getThumbnailName: VideoMethods.GetThumbnailName
32 getPreviewName: VideoMethods.GetPreviewName
33 getTorrentName: VideoMethods.GetTorrentName
34 isOwned: VideoMethods.IsOwned
35 toFormatedJSON: VideoMethods.ToFormatedJSON
36 toAddRemoteJSON: VideoMethods.ToAddRemoteJSON
37 toUpdateRemoteJSON: VideoMethods.ToUpdateRemoteJSON
38 transcodeVideofile: VideoMethods.TranscodeVideofile
39
40 generateThumbnailFromData: VideoMethods.GenerateThumbnailFromData
41 getDurationFromFile: VideoMethods.GetDurationFromFile
42 list: VideoMethods.List
43 listForApi: VideoMethods.ListForApi
44 loadByHostAndRemoteId: VideoMethods.LoadByHostAndRemoteId
45 listOwnedAndPopulateAuthorAndTags: VideoMethods.ListOwnedAndPopulateAuthorAndTags
46 listOwnedByAuthor: VideoMethods.ListOwnedByAuthor
47 load: VideoMethods.Load
48 loadAndPopulateAuthor: VideoMethods.LoadAndPopulateAuthor
49 loadAndPopulateAuthorAndPodAndTags: VideoMethods.LoadAndPopulateAuthorAndPodAndTags
50 searchAndPopulateAuthorAndPodAndTags: VideoMethods.SearchAndPopulateAuthorAndPodAndTags
51}
52
53export interface VideoAttributes {
54 name: string
55 extname: string
56 remoteId: string
57 category: number
58 licence: number
59 language: number
60 nsfw: boolean
61 description: string
62 infoHash?: string
63 duration: number
64 views?: number
65 likes?: number
66 dislikes?: number
67}
68
69export interface VideoInstance extends VideoClass, VideoAttributes, Sequelize.Instance<VideoAttributes> {
70 id: string
71 createdAt: Date
72 updatedAt: Date
73}
74
75export interface VideoModel extends VideoClass, Sequelize.Model<VideoInstance, VideoAttributes> {}
diff --git a/server/models/video-tag-interface.ts b/server/models/video-tag-interface.ts
new file mode 100644
index 000000000..468827b8c
--- /dev/null
+++ b/server/models/video-tag-interface.ts
@@ -0,0 +1,18 @@
1import * as Sequelize from 'sequelize'
2
3export namespace VideoTagMethods {
4}
5
6export interface VideoTagClass {
7}
8
9export interface VideoTagAttributes {
10}
11
12export interface VideoTagInstance extends Sequelize.Instance<VideoTagAttributes> {
13 id: number
14 createdAt: Date
15 updatedAt: Date
16}
17
18export interface VideoTagModel extends VideoTagClass, Sequelize.Model<VideoTagInstance, VideoTagAttributes> {}
diff --git a/server/models/video-tag.ts b/server/models/video-tag.ts
index 83ff6053f..2ccaf820d 100644
--- a/server/models/video-tag.ts
+++ b/server/models/video-tag.ts
@@ -1,5 +1,18 @@
1module.exports = function (sequelize, DataTypes) { 1import * as Sequelize from 'sequelize'
2 const VideoTag = sequelize.define('VideoTag', {}, { 2
3import { addMethodsToModel } from './utils'
4import {
5 VideoTagClass,
6 VideoTagInstance,
7 VideoTagAttributes,
8
9 VideoTagMethods
10} from './video-tag-interface'
11
12let VideoTag: Sequelize.Model<VideoTagInstance, VideoTagAttributes>
13
14export default function (sequelize, DataTypes) {
15 VideoTag = sequelize.define('VideoTag', {}, {
3 indexes: [ 16 indexes: [
4 { 17 {
5 fields: [ 'videoId' ] 18 fields: [ 'videoId' ]
diff --git a/server/models/video.ts b/server/models/video.ts
index 1e29f1355..9284dfeba 100644
--- a/server/models/video.ts
+++ b/server/models/video.ts
@@ -8,8 +8,9 @@ import { map, values } from 'lodash'
8import { parallel, series } from 'async' 8import { parallel, series } from 'async'
9import parseTorrent = require('parse-torrent') 9import parseTorrent = require('parse-torrent')
10import { join } from 'path' 10import { join } from 'path'
11import * as Sequelize from 'sequelize'
11 12
12const db = require('../initializers/database') 13import { database as db } from '../initializers/database'
13import { 14import {
14 logger, 15 logger,
15 isVideoNameValid, 16 isVideoNameValid,
@@ -32,12 +33,42 @@ import {
32 THUMBNAILS_SIZE 33 THUMBNAILS_SIZE
33} from '../initializers' 34} from '../initializers'
34import { JobScheduler, removeVideoToFriends } from '../lib' 35import { JobScheduler, removeVideoToFriends } from '../lib'
35import { getSort } from './utils'
36 36
37// --------------------------------------------------------------------------- 37import { addMethodsToModel, getSort } from './utils'
38 38import {
39module.exports = function (sequelize, DataTypes) { 39 VideoClass,
40 const Video = sequelize.define('Video', 40 VideoInstance,
41 VideoAttributes,
42
43 VideoMethods
44} from './video-interface'
45
46let Video: Sequelize.Model<VideoInstance, VideoAttributes>
47let generateMagnetUri: VideoMethods.GenerateMagnetUri
48let getVideoFilename: VideoMethods.GetVideoFilename
49let getThumbnailName: VideoMethods.GetThumbnailName
50let getPreviewName: VideoMethods.GetPreviewName
51let getTorrentName: VideoMethods.GetTorrentName
52let isOwned: VideoMethods.IsOwned
53let toFormatedJSON: VideoMethods.ToFormatedJSON
54let toAddRemoteJSON: VideoMethods.ToAddRemoteJSON
55let toUpdateRemoteJSON: VideoMethods.ToUpdateRemoteJSON
56let transcodeVideofile: VideoMethods.TranscodeVideofile
57
58let generateThumbnailFromData: VideoMethods.GenerateThumbnailFromData
59let getDurationFromFile: VideoMethods.GetDurationFromFile
60let list: VideoMethods.List
61let listForApi: VideoMethods.ListForApi
62let loadByHostAndRemoteId: VideoMethods.LoadByHostAndRemoteId
63let listOwnedAndPopulateAuthorAndTags: VideoMethods.ListOwnedAndPopulateAuthorAndTags
64let listOwnedByAuthor: VideoMethods.ListOwnedByAuthor
65let load: VideoMethods.Load
66let loadAndPopulateAuthor: VideoMethods.LoadAndPopulateAuthor
67let loadAndPopulateAuthorAndPodAndTags: VideoMethods.LoadAndPopulateAuthorAndPodAndTags
68let searchAndPopulateAuthorAndPodAndTags: VideoMethods.SearchAndPopulateAuthorAndPodAndTags
69
70export default function (sequelize, DataTypes) {
71 Video = sequelize.define('Video',
41 { 72 {
42 id: { 73 id: {
43 type: DataTypes.UUID, 74 type: DataTypes.UUID,
@@ -194,34 +225,6 @@ module.exports = function (sequelize, DataTypes) {
194 fields: [ 'likes' ] 225 fields: [ 'likes' ]
195 } 226 }
196 ], 227 ],
197 classMethods: {
198 associate,
199
200 generateThumbnailFromData,
201 getDurationFromFile,
202 list,
203 listForApi,
204 listOwnedAndPopulateAuthorAndTags,
205 listOwnedByAuthor,
206 load,
207 loadByHostAndRemoteId,
208 loadAndPopulateAuthor,
209 loadAndPopulateAuthorAndPodAndTags,
210 searchAndPopulateAuthorAndPodAndTags
211 },
212 instanceMethods: {
213 generateMagnetUri,
214 getVideoFilename,
215 getThumbnailName,
216 getPreviewName,
217 getTorrentName,
218 isOwned,
219 toFormatedJSON,
220 toAddRemoteJSON,
221 toUpdateRemoteJSON,
222 transcodeVideofile,
223 removeFromBlacklist
224 },
225 hooks: { 228 hooks: {
226 beforeValidate, 229 beforeValidate,
227 beforeCreate, 230 beforeCreate,
@@ -230,99 +233,139 @@ module.exports = function (sequelize, DataTypes) {
230 } 233 }
231 ) 234 )
232 235
236 const classMethods = [
237 associate,
238
239 generateThumbnailFromData,
240 getDurationFromFile,
241 list,
242 listForApi,
243 listOwnedAndPopulateAuthorAndTags,
244 listOwnedByAuthor,
245 load,
246 loadByHostAndRemoteId,
247 loadAndPopulateAuthor,
248 loadAndPopulateAuthorAndPodAndTags,
249 searchAndPopulateAuthorAndPodAndTags
250 ]
251 const instanceMethods = [
252 generateMagnetUri,
253 getVideoFilename,
254 getThumbnailName,
255 getPreviewName,
256 getTorrentName,
257 isOwned,
258 toFormatedJSON,
259 toAddRemoteJSON,
260 toUpdateRemoteJSON,
261 transcodeVideofile,
262 removeFromBlacklist
263 ]
264 addMethodsToModel(Video, classMethods, instanceMethods)
265
233 return Video 266 return Video
234} 267}
235 268
236function beforeValidate (video, options, next) { 269function beforeValidate (video, options) {
237 // Put a fake infoHash if it does not exists yet 270 // Put a fake infoHash if it does not exists yet
238 if (video.isOwned() && !video.infoHash) { 271 if (video.isOwned() && !video.infoHash) {
239 // 40 hexa length 272 // 40 hexa length
240 video.infoHash = '0123456789abcdef0123456789abcdef01234567' 273 video.infoHash = '0123456789abcdef0123456789abcdef01234567'
241 } 274 }
242
243 return next(null)
244} 275}
245 276
246function beforeCreate (video, options, next) { 277function beforeCreate (video, options) {
247 const tasks = [] 278 return new Promise(function (resolve, reject) {
248 279 const tasks = []
249 if (video.isOwned()) {
250 const videoPath = join(CONFIG.STORAGE.VIDEOS_DIR, video.getVideoFilename())
251
252 tasks.push(
253 function createVideoTorrent (callback) {
254 createTorrentFromVideo(video, videoPath, callback)
255 },
256
257 function createVideoThumbnail (callback) {
258 createThumbnail(video, videoPath, callback)
259 },
260 280
261 function createVideoPreview (callback) { 281 if (video.isOwned()) {
262 createPreview(video, videoPath, callback) 282 const videoPath = join(CONFIG.STORAGE.VIDEOS_DIR, video.getVideoFilename())
263 }
264 )
265 283
266 if (CONFIG.TRANSCODING.ENABLED === true) {
267 tasks.push( 284 tasks.push(
268 function createVideoTranscoderJob (callback) { 285 function createVideoTorrent (callback) {
269 const dataInput = { 286 createTorrentFromVideo(video, videoPath, callback)
270 id: video.id 287 },
271 } 288
289 function createVideoThumbnail (callback) {
290 createThumbnail(video, videoPath, callback)
291 },
272 292
273 JobScheduler.Instance.createJob(options.transaction, 'videoTranscoder', dataInput, callback) 293 function createVideoPreview (callback) {
294 createPreview(video, videoPath, callback)
274 } 295 }
275 ) 296 )
276 }
277 297
278 return parallel(tasks, next) 298 if (CONFIG.TRANSCODING.ENABLED === true) {
279 } 299 tasks.push(
300 function createVideoTranscoderJob (callback) {
301 const dataInput = {
302 id: video.id
303 }
280 304
281 return next() 305 JobScheduler.Instance.createJob(options.transaction, 'videoTranscoder', dataInput, callback)
282} 306 }
307 )
308 }
283 309
284function afterDestroy (video, options, next) { 310 return parallel(tasks, function (err) {
285 const tasks = [] 311 if (err) return reject(err)
286 312
287 tasks.push( 313 return resolve()
288 function (callback) { 314 })
289 removeThumbnail(video, callback)
290 } 315 }
291 )
292 316
293 if (video.isOwned()) { 317 return resolve()
318 })
319}
320
321function afterDestroy (video, options) {
322 return new Promise(function (resolve, reject) {
323 const tasks = []
324
294 tasks.push( 325 tasks.push(
295 function removeVideoFile (callback) { 326 function (callback) {
296 removeFile(video, callback) 327 removeThumbnail(video, callback)
297 }, 328 }
329 )
298 330
299 function removeVideoTorrent (callback) { 331 if (video.isOwned()) {
300 removeTorrent(video, callback) 332 tasks.push(
301 }, 333 function removeVideoFile (callback) {
334 removeFile(video, callback)
335 },
302 336
303 function removeVideoPreview (callback) { 337 function removeVideoTorrent (callback) {
304 removePreview(video, callback) 338 removeTorrent(video, callback)
305 }, 339 },
306 340
307 function removeVideoToFriends (callback) { 341 function removeVideoPreview (callback) {
308 const params = { 342 removePreview(video, callback)
309 remoteId: video.id 343 },
310 }
311 344
312 removeVideoToFriends(params) 345 function notifyFriends (callback) {
346 const params = {
347 remoteId: video.id
348 }
313 349
314 return callback() 350 removeVideoToFriends(params)
315 }
316 )
317 }
318 351
319 parallel(tasks, next) 352 return callback()
353 }
354 )
355 }
356
357 parallel(tasks, function (err) {
358 if (err) return reject(err)
359
360 return resolve()
361 })
362 })
320} 363}
321 364
322// ------------------------------ METHODS ------------------------------ 365// ------------------------------ METHODS ------------------------------
323 366
324function associate (models) { 367function associate (models) {
325 this.belongsTo(models.Author, { 368 Video.belongsTo(models.Author, {
326 foreignKey: { 369 foreignKey: {
327 name: 'authorId', 370 name: 'authorId',
328 allowNull: false 371 allowNull: false
@@ -330,13 +373,13 @@ function associate (models) {
330 onDelete: 'cascade' 373 onDelete: 'cascade'
331 }) 374 })
332 375
333 this.belongsToMany(models.Tag, { 376 Video.belongsToMany(models.Tag, {
334 foreignKey: 'videoId', 377 foreignKey: 'videoId',
335 through: models.VideoTag, 378 through: models.VideoTag,
336 onDelete: 'cascade' 379 onDelete: 'cascade'
337 }) 380 })
338 381
339 this.hasMany(models.VideoAbuse, { 382 Video.hasMany(models.VideoAbuse, {
340 foreignKey: { 383 foreignKey: {
341 name: 'videoId', 384 name: 'videoId',
342 allowNull: false 385 allowNull: false
@@ -345,7 +388,7 @@ function associate (models) {
345 }) 388 })
346} 389}
347 390
348function generateMagnetUri () { 391generateMagnetUri = function () {
349 let baseUrlHttp 392 let baseUrlHttp
350 let baseUrlWs 393 let baseUrlWs
351 394
@@ -372,18 +415,18 @@ function generateMagnetUri () {
372 return magnetUtil.encode(magnetHash) 415 return magnetUtil.encode(magnetHash)
373} 416}
374 417
375function getVideoFilename () { 418getVideoFilename = function () {
376 if (this.isOwned()) return this.id + this.extname 419 if (this.isOwned()) return this.id + this.extname
377 420
378 return this.remoteId + this.extname 421 return this.remoteId + this.extname
379} 422}
380 423
381function getThumbnailName () { 424getThumbnailName = function () {
382 // We always have a copy of the thumbnail 425 // We always have a copy of the thumbnail
383 return this.id + '.jpg' 426 return this.id + '.jpg'
384} 427}
385 428
386function getPreviewName () { 429getPreviewName = function () {
387 const extension = '.jpg' 430 const extension = '.jpg'
388 431
389 if (this.isOwned()) return this.id + extension 432 if (this.isOwned()) return this.id + extension
@@ -391,7 +434,7 @@ function getPreviewName () {
391 return this.remoteId + extension 434 return this.remoteId + extension
392} 435}
393 436
394function getTorrentName () { 437getTorrentName = function () {
395 const extension = '.torrent' 438 const extension = '.torrent'
396 439
397 if (this.isOwned()) return this.id + extension 440 if (this.isOwned()) return this.id + extension
@@ -399,11 +442,11 @@ function getTorrentName () {
399 return this.remoteId + extension 442 return this.remoteId + extension
400} 443}
401 444
402function isOwned () { 445isOwned = function () {
403 return this.remoteId === null 446 return this.remoteId === null
404} 447}
405 448
406function toFormatedJSON () { 449toFormatedJSON = function () {
407 let podHost 450 let podHost
408 451
409 if (this.Author.Pod) { 452 if (this.Author.Pod) {
@@ -453,43 +496,41 @@ function toFormatedJSON () {
453 return json 496 return json
454} 497}
455 498
456function toAddRemoteJSON (callback) { 499toAddRemoteJSON = function (callback) {
457 const self = this
458
459 // Get thumbnail data to send to the other pod 500 // Get thumbnail data to send to the other pod
460 const thumbnailPath = join(CONFIG.STORAGE.THUMBNAILS_DIR, this.getThumbnailName()) 501 const thumbnailPath = join(CONFIG.STORAGE.THUMBNAILS_DIR, this.getThumbnailName())
461 fs.readFile(thumbnailPath, function (err, thumbnailData) { 502 fs.readFile(thumbnailPath, (err, thumbnailData) => {
462 if (err) { 503 if (err) {
463 logger.error('Cannot read the thumbnail of the video') 504 logger.error('Cannot read the thumbnail of the video')
464 return callback(err) 505 return callback(err)
465 } 506 }
466 507
467 const remoteVideo = { 508 const remoteVideo = {
468 name: self.name, 509 name: this.name,
469 category: self.category, 510 category: this.category,
470 licence: self.licence, 511 licence: this.licence,
471 language: self.language, 512 language: this.language,
472 nsfw: self.nsfw, 513 nsfw: this.nsfw,
473 description: self.description, 514 description: this.description,
474 infoHash: self.infoHash, 515 infoHash: this.infoHash,
475 remoteId: self.id, 516 remoteId: this.id,
476 author: self.Author.name, 517 author: this.Author.name,
477 duration: self.duration, 518 duration: this.duration,
478 thumbnailData: thumbnailData.toString('binary'), 519 thumbnailData: thumbnailData.toString('binary'),
479 tags: map(self.Tags, 'name'), 520 tags: map(this.Tags, 'name'),
480 createdAt: self.createdAt, 521 createdAt: this.createdAt,
481 updatedAt: self.updatedAt, 522 updatedAt: this.updatedAt,
482 extname: self.extname, 523 extname: this.extname,
483 views: self.views, 524 views: this.views,
484 likes: self.likes, 525 likes: this.likes,
485 dislikes: self.dislikes 526 dislikes: this.dislikes
486 } 527 }
487 528
488 return callback(null, remoteVideo) 529 return callback(null, remoteVideo)
489 }) 530 })
490} 531}
491 532
492function toUpdateRemoteJSON (callback) { 533toUpdateRemoteJSON = function (callback) {
493 const json = { 534 const json = {
494 name: this.name, 535 name: this.name,
495 category: this.category, 536 category: this.category,
@@ -513,7 +554,7 @@ function toUpdateRemoteJSON (callback) {
513 return json 554 return json
514} 555}
515 556
516function transcodeVideofile (finalCallback) { 557transcodeVideofile = function (finalCallback) {
517 const video = this 558 const video = this
518 559
519 const videosDirectory = CONFIG.STORAGE.VIDEOS_DIR 560 const videosDirectory = CONFIG.STORAGE.VIDEOS_DIR
@@ -568,7 +609,7 @@ function transcodeVideofile (finalCallback) {
568 609
569// ------------------------------ STATICS ------------------------------ 610// ------------------------------ STATICS ------------------------------
570 611
571function generateThumbnailFromData (video, thumbnailData, callback) { 612generateThumbnailFromData = function (video, thumbnailData, callback) {
572 // Creating the thumbnail for a remote video 613 // Creating the thumbnail for a remote video
573 614
574 const thumbnailName = video.getThumbnailName() 615 const thumbnailName = video.getThumbnailName()
@@ -580,7 +621,7 @@ function generateThumbnailFromData (video, thumbnailData, callback) {
580 }) 621 })
581} 622}
582 623
583function getDurationFromFile (videoPath, callback) { 624getDurationFromFile = function (videoPath, callback) {
584 ffmpeg.ffprobe(videoPath, function (err, metadata) { 625 ffmpeg.ffprobe(videoPath, function (err, metadata) {
585 if (err) return callback(err) 626 if (err) return callback(err)
586 627
@@ -588,46 +629,46 @@ function getDurationFromFile (videoPath, callback) {
588 }) 629 })
589} 630}
590 631
591function list (callback) { 632list = function (callback) {
592 return this.findAll().asCallback(callback) 633 return Video.findAll().asCallback(callback)
593} 634}
594 635
595function listForApi (start, count, sort, callback) { 636listForApi = function (start, count, sort, callback) {
596 // Exclude Blakclisted videos from the list 637 // Exclude Blakclisted videos from the list
597 const query = { 638 const query = {
639 distinct: true,
598 offset: start, 640 offset: start,
599 limit: count, 641 limit: count,
600 distinct: true, // For the count, a video can have many tags 642 order: [ getSort(sort), [ Video['sequelize'].models.Tag, 'name', 'ASC' ] ],
601 order: [ getSort(sort), [ this.sequelize.models.Tag, 'name', 'ASC' ] ],
602 include: [ 643 include: [
603 { 644 {
604 model: this.sequelize.models.Author, 645 model: Video['sequelize'].models.Author,
605 include: [ { model: this.sequelize.models.Pod, required: false } ] 646 include: [ { model: Video['sequelize'].models.Pod, required: false } ]
606 }, 647 },
607 648
608 this.sequelize.models.Tag 649 Video['sequelize'].models.Tag
609 ], 650 ],
610 where: createBaseVideosWhere.call(this) 651 where: createBaseVideosWhere()
611 } 652 }
612 653
613 return this.findAndCountAll(query).asCallback(function (err, result) { 654 return Video.findAndCountAll(query).asCallback(function (err, result) {
614 if (err) return callback(err) 655 if (err) return callback(err)
615 656
616 return callback(null, result.rows, result.count) 657 return callback(null, result.rows, result.count)
617 }) 658 })
618} 659}
619 660
620function loadByHostAndRemoteId (fromHost, remoteId, callback) { 661loadByHostAndRemoteId = function (fromHost, remoteId, callback) {
621 const query = { 662 const query = {
622 where: { 663 where: {
623 remoteId: remoteId 664 remoteId: remoteId
624 }, 665 },
625 include: [ 666 include: [
626 { 667 {
627 model: this.sequelize.models.Author, 668 model: Video['sequelize'].models.Author,
628 include: [ 669 include: [
629 { 670 {
630 model: this.sequelize.models.Pod, 671 model: Video['sequelize'].models.Pod,
631 required: true, 672 required: true,
632 where: { 673 where: {
633 host: fromHost 674 host: fromHost
@@ -638,29 +679,29 @@ function loadByHostAndRemoteId (fromHost, remoteId, callback) {
638 ] 679 ]
639 } 680 }
640 681
641 return this.findOne(query).asCallback(callback) 682 return Video.findOne(query).asCallback(callback)
642} 683}
643 684
644function listOwnedAndPopulateAuthorAndTags (callback) { 685listOwnedAndPopulateAuthorAndTags = function (callback) {
645 // If remoteId is null this is *our* video 686 // If remoteId is null this is *our* video
646 const query = { 687 const query = {
647 where: { 688 where: {
648 remoteId: null 689 remoteId: null
649 }, 690 },
650 include: [ this.sequelize.models.Author, this.sequelize.models.Tag ] 691 include: [ Video['sequelize'].models.Author, Video['sequelize'].models.Tag ]
651 } 692 }
652 693
653 return this.findAll(query).asCallback(callback) 694 return Video.findAll(query).asCallback(callback)
654} 695}
655 696
656function listOwnedByAuthor (author, callback) { 697listOwnedByAuthor = function (author, callback) {
657 const query = { 698 const query = {
658 where: { 699 where: {
659 remoteId: null 700 remoteId: null
660 }, 701 },
661 include: [ 702 include: [
662 { 703 {
663 model: this.sequelize.models.Author, 704 model: Video['sequelize'].models.Author,
664 where: { 705 where: {
665 name: author 706 name: author
666 } 707 }
@@ -668,58 +709,58 @@ function listOwnedByAuthor (author, callback) {
668 ] 709 ]
669 } 710 }
670 711
671 return this.findAll(query).asCallback(callback) 712 return Video.findAll(query).asCallback(callback)
672} 713}
673 714
674function load (id, callback) { 715load = function (id, callback) {
675 return this.findById(id).asCallback(callback) 716 return Video.findById(id).asCallback(callback)
676} 717}
677 718
678function loadAndPopulateAuthor (id, callback) { 719loadAndPopulateAuthor = function (id, callback) {
679 const options = { 720 const options = {
680 include: [ this.sequelize.models.Author ] 721 include: [ Video['sequelize'].models.Author ]
681 } 722 }
682 723
683 return this.findById(id, options).asCallback(callback) 724 return Video.findById(id, options).asCallback(callback)
684} 725}
685 726
686function loadAndPopulateAuthorAndPodAndTags (id, callback) { 727loadAndPopulateAuthorAndPodAndTags = function (id, callback) {
687 const options = { 728 const options = {
688 include: [ 729 include: [
689 { 730 {
690 model: this.sequelize.models.Author, 731 model: Video['sequelize'].models.Author,
691 include: [ { model: this.sequelize.models.Pod, required: false } ] 732 include: [ { model: Video['sequelize'].models.Pod, required: false } ]
692 }, 733 },
693 this.sequelize.models.Tag 734 Video['sequelize'].models.Tag
694 ] 735 ]
695 } 736 }
696 737
697 return this.findById(id, options).asCallback(callback) 738 return Video.findById(id, options).asCallback(callback)
698} 739}
699 740
700function searchAndPopulateAuthorAndPodAndTags (value, field, start, count, sort, callback) { 741searchAndPopulateAuthorAndPodAndTags = function (value, field, start, count, sort, callback) {
701 const podInclude: any = { 742 const podInclude: any = {
702 model: this.sequelize.models.Pod, 743 model: Video['sequelize'].models.Pod,
703 required: false 744 required: false
704 } 745 }
705 746
706 const authorInclude: any = { 747 const authorInclude: any = {
707 model: this.sequelize.models.Author, 748 model: Video['sequelize'].models.Author,
708 include: [ 749 include: [
709 podInclude 750 podInclude
710 ] 751 ]
711 } 752 }
712 753
713 const tagInclude: any = { 754 const tagInclude: any = {
714 model: this.sequelize.models.Tag 755 model: Video['sequelize'].models.Tag
715 } 756 }
716 757
717 const query: any = { 758 const query: any = {
718 where: createBaseVideosWhere.call(this), 759 distinct: true,
760 where: createBaseVideosWhere(),
719 offset: start, 761 offset: start,
720 limit: count, 762 limit: count,
721 distinct: true, // For the count, a video can have many tags 763 order: [ getSort(sort), [ Video['sequelize'].models.Tag, 'name', 'ASC' ] ]
722 order: [ getSort(sort), [ this.sequelize.models.Tag, 'name', 'ASC' ] ]
723 } 764 }
724 765
725 // Make an exact search with the magnet 766 // Make an exact search with the magnet
@@ -727,8 +768,8 @@ function searchAndPopulateAuthorAndPodAndTags (value, field, start, count, sort,
727 const infoHash = magnetUtil.decode(value).infoHash 768 const infoHash = magnetUtil.decode(value).infoHash
728 query.where.infoHash = infoHash 769 query.where.infoHash = infoHash
729 } else if (field === 'tags') { 770 } else if (field === 'tags') {
730 const escapedValue = this.sequelize.escape('%' + value + '%') 771 const escapedValue = Video['sequelize'].escape('%' + value + '%')
731 query.where.id.$in = this.sequelize.literal( 772 query.where.id.$in = Video['sequelize'].literal(
732 '(SELECT "VideoTags"."videoId" FROM "Tags" INNER JOIN "VideoTags" ON "Tags"."id" = "VideoTags"."tagId" WHERE name LIKE ' + escapedValue + ')' 773 '(SELECT "VideoTags"."videoId" FROM "Tags" INNER JOIN "VideoTags" ON "Tags"."id" = "VideoTags"."tagId" WHERE name LIKE ' + escapedValue + ')'
733 ) 774 )
734 } else if (field === 'host') { 775 } else if (field === 'host') {
@@ -758,10 +799,10 @@ function searchAndPopulateAuthorAndPodAndTags (value, field, start, count, sort,
758 ] 799 ]
759 800
760 if (tagInclude.where) { 801 if (tagInclude.where) {
761 // query.include.push([ this.sequelize.models.Tag ]) 802 // query.include.push([ Video['sequelize'].models.Tag ])
762 } 803 }
763 804
764 return this.findAndCountAll(query).asCallback(function (err, result) { 805 return Video.findAndCountAll(query).asCallback(function (err, result) {
765 if (err) return callback(err) 806 if (err) return callback(err)
766 807
767 return callback(null, result.rows, result.count) 808 return callback(null, result.rows, result.count)
@@ -773,7 +814,7 @@ function searchAndPopulateAuthorAndPodAndTags (value, field, start, count, sort,
773function createBaseVideosWhere () { 814function createBaseVideosWhere () {
774 return { 815 return {
775 id: { 816 id: {
776 $notIn: this.sequelize.literal( 817 $notIn: Video['sequelize'].literal(
777 '(SELECT "BlacklistedVideos"."videoId" FROM "BlacklistedVideos")' 818 '(SELECT "BlacklistedVideos"."videoId" FROM "BlacklistedVideos")'
778 ) 819 )
779 } 820 }
diff --git a/server/tests/api/video-transcoder.js b/server/tests/api/video-transcoder.js
index 3ff7b230a..c0b597668 100644
--- a/server/tests/api/video-transcoder.js
+++ b/server/tests/api/video-transcoder.js
@@ -12,7 +12,7 @@ const loginUtils = require('../utils/login')
12const serversUtils = require('../utils/servers') 12const serversUtils = require('../utils/servers')
13const videosUtils = require('../utils/videos') 13const videosUtils = require('../utils/videos')
14 14
15describe('Test video blacklists', function () { 15describe('Test video transcoding', function () {
16 let servers = [] 16 let servers = []
17 17
18 before(function (done) { 18 before(function (done) {
diff --git a/server/tests/utils/servers.js b/server/tests/utils/servers.js
index afb08e6fc..c753c1f1d 100644
--- a/server/tests/utils/servers.js
+++ b/server/tests/utils/servers.js
@@ -82,7 +82,7 @@ function runServer (number, callback) {
82 detached: true 82 detached: true
83 } 83 }
84 84
85 server.app = fork(pathUtils.join(__dirname, '..', '..', '..', 'server.js'), [], options) 85 server.app = fork(pathUtils.join(__dirname, '..', '..', '..', 'dist', 'server.js'), [], options)
86 server.app.stdout.on('data', function onStdout (data) { 86 server.app.stdout.on('data', function onStdout (data) {
87 let dontContinue = false 87 let dontContinue = false
88 88
diff --git a/yarn.lock b/yarn.lock
index c0ce443b3..857aa92e6 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -26,8 +26,8 @@
26 resolved "https://registry.yarnpkg.com/@types/config/-/config-0.0.32.tgz#c106055802d78e234e28374adc4dad460d098558" 26 resolved "https://registry.yarnpkg.com/@types/config/-/config-0.0.32.tgz#c106055802d78e234e28374adc4dad460d098558"
27 27
28"@types/express-serve-static-core@*": 28"@types/express-serve-static-core@*":
29 version "4.0.44" 29 version "4.0.45"
30 resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.0.44.tgz#a1c3bd5d80e93c72fba91a03f5412c47f21d4ae7" 30 resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.0.45.tgz#71bb1f87d7187482d0d8851f5b294458e1c78667"
31 dependencies: 31 dependencies:
32 "@types/node" "*" 32 "@types/node" "*"
33 33
@@ -67,8 +67,8 @@
67 "@types/express" "*" 67 "@types/express" "*"
68 68
69"@types/node@*", "@types/node@^7.0.18": 69"@types/node@*", "@types/node@^7.0.18":
70 version "7.0.18" 70 version "7.0.22"
71 resolved "https://registry.yarnpkg.com/@types/node/-/node-7.0.18.tgz#cd67f27d3dc0cfb746f0bdd5e086c4c5d55be173" 71 resolved "https://registry.yarnpkg.com/@types/node/-/node-7.0.22.tgz#4593f4d828bdd612929478ea40c67b4f403ca255"
72 72
73"@types/request@^0.0.43": 73"@types/request@^0.0.43":
74 version "0.0.43" 74 version "0.0.43"
@@ -77,9 +77,9 @@
77 "@types/form-data" "*" 77 "@types/form-data" "*"
78 "@types/node" "*" 78 "@types/node" "*"
79 79
80"@types/sequelize@3": 80"@types/sequelize@^4.0.55":
81 version "3.4.48" 81 version "4.0.55"
82 resolved "https://registry.yarnpkg.com/@types/sequelize/-/sequelize-3.4.48.tgz#f88fac7cc4717d2e87f20f69ebb64aa869e7e4d1" 82 resolved "https://registry.yarnpkg.com/@types/sequelize/-/sequelize-4.0.55.tgz#957335a9de537f17ed9c9e16c088cc147b8805af"
83 dependencies: 83 dependencies:
84 "@types/bluebird" "*" 84 "@types/bluebird" "*"
85 "@types/lodash" "*" 85 "@types/lodash" "*"
@@ -142,8 +142,8 @@ ajv-keywords@^1.0.0:
142 resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-1.5.1.tgz#314dd0a4b3368fad3dfcdc54ede6171b886daf3c" 142 resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-1.5.1.tgz#314dd0a4b3368fad3dfcdc54ede6171b886daf3c"
143 143
144ajv@^4.7.0, ajv@^4.9.1: 144ajv@^4.7.0, ajv@^4.9.1:
145 version "4.11.7" 145 version "4.11.8"
146 resolved "https://registry.yarnpkg.com/ajv/-/ajv-4.11.7.tgz#8655a5d86d0824985cc471a1d913fb6729a0ec48" 146 resolved "https://registry.yarnpkg.com/ajv/-/ajv-4.11.8.tgz#82ffb02b29e662ae53bdc20af15947706739c536"
147 dependencies: 147 dependencies:
148 co "^4.6.0" 148 co "^4.6.0"
149 json-stable-stringify "^1.0.1" 149 json-stable-stringify "^1.0.1"
@@ -243,8 +243,8 @@ assertion-error@^1.0.1:
243 resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.0.2.tgz#13ca515d86206da0bac66e834dd397d87581094c" 243 resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.0.2.tgz#13ca515d86206da0bac66e834dd397d87581094c"
244 244
245async@>=0.2.9, async@^2.0.0: 245async@>=0.2.9, async@^2.0.0:
246 version "2.3.0" 246 version "2.4.1"
247 resolved "https://registry.yarnpkg.com/async/-/async-2.3.0.tgz#1013d1051047dd320fe24e494d5c66ecaf6147d9" 247 resolved "https://registry.yarnpkg.com/async/-/async-2.4.1.tgz#62a56b279c98a11d0987096a01cc3eeb8eb7bbd7"
248 dependencies: 248 dependencies:
249 lodash "^4.14.0" 249 lodash "^4.14.0"
250 250
@@ -381,8 +381,8 @@ bittorrent-tracker@^9.0.0:
381 bufferutil "^3.0.0" 381 bufferutil "^3.0.0"
382 382
383bl@^1.0.0: 383bl@^1.0.0:
384 version "1.2.0" 384 version "1.2.1"
385 resolved "https://registry.yarnpkg.com/bl/-/bl-1.2.0.tgz#1397e7ec42c5f5dc387470c500e34a9f6be9ea98" 385 resolved "https://registry.yarnpkg.com/bl/-/bl-1.2.1.tgz#cac328f7bee45730d404b692203fcb590e172d5e"
386 dependencies: 386 dependencies:
387 readable-stream "^2.0.5" 387 readable-stream "^2.0.5"
388 388
@@ -408,7 +408,7 @@ bluebird@^2.10.0, bluebird@^2.9.13:
408 version "2.11.0" 408 version "2.11.0"
409 resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-2.11.0.tgz#534b9033c022c9579c56ba3b3e5a5caafbb650e1" 409 resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-2.11.0.tgz#534b9033c022c9579c56ba3b3e5a5caafbb650e1"
410 410
411bluebird@^3.0.5, bluebird@^3.3.4, bluebird@^3.4.0, bluebird@^3.4.6: 411bluebird@^3.0.5, bluebird@^3.4.0, bluebird@^3.4.6:
412 version "3.5.0" 412 version "3.5.0"
413 resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.0.tgz#791420d7f551eea2897453a8a77653f96606d67c" 413 resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.0.tgz#791420d7f551eea2897453a8a77653f96606d67c"
414 414
@@ -417,19 +417,19 @@ bn.js@^4.4.0:
417 resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.6.tgz#53344adb14617a13f6e8dd2ce28905d1c0ba3215" 417 resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.6.tgz#53344adb14617a13f6e8dd2ce28905d1c0ba3215"
418 418
419body-parser@^1.12.4: 419body-parser@^1.12.4:
420 version "1.17.1" 420 version "1.17.2"
421 resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.17.1.tgz#75b3bc98ddd6e7e0d8ffe750dfaca5c66993fa47" 421 resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.17.2.tgz#f8892abc8f9e627d42aedafbca66bf5ab99104ee"
422 dependencies: 422 dependencies:
423 bytes "2.4.0" 423 bytes "2.4.0"
424 content-type "~1.0.2" 424 content-type "~1.0.2"
425 debug "2.6.1" 425 debug "2.6.7"
426 depd "~1.1.0" 426 depd "~1.1.0"
427 http-errors "~1.6.1" 427 http-errors "~1.6.1"
428 iconv-lite "0.4.15" 428 iconv-lite "0.4.15"
429 on-finished "~2.3.0" 429 on-finished "~2.3.0"
430 qs "6.4.0" 430 qs "6.4.0"
431 raw-body "~2.2.0" 431 raw-body "~2.2.0"
432 type-is "~1.6.14" 432 type-is "~1.6.15"
433 433
434boom@2.x.x: 434boom@2.x.x:
435 version "2.10.1" 435 version "2.10.1"
@@ -437,7 +437,7 @@ boom@2.x.x:
437 dependencies: 437 dependencies:
438 hoek "2.x.x" 438 hoek "2.x.x"
439 439
440brace-expansion@^1.0.0: 440brace-expansion@^1.1.7:
441 version "1.1.7" 441 version "1.1.7"
442 resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.7.tgz#3effc3c50e000531fb720eaff80f0ae8ef23cf59" 442 resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.7.tgz#3effc3c50e000531fb720eaff80f0ae8ef23cf59"
443 dependencies: 443 dependencies:
@@ -570,6 +570,13 @@ closest-to@~2.0.0:
570 version "2.0.0" 570 version "2.0.0"
571 resolved "https://registry.yarnpkg.com/closest-to/-/closest-to-2.0.0.tgz#bb2a860edb7769b62d04821748ae50da24dbefaa" 571 resolved "https://registry.yarnpkg.com/closest-to/-/closest-to-2.0.0.tgz#bb2a860edb7769b62d04821748ae50da24dbefaa"
572 572
573cls-bluebird@^2.0.1:
574 version "2.0.1"
575 resolved "https://registry.yarnpkg.com/cls-bluebird/-/cls-bluebird-2.0.1.tgz#c259a480ae02c0e506134307bb13db30446ee2e7"
576 dependencies:
577 is-bluebird "^1.0.2"
578 shimmer "^1.1.0"
579
573co-bluebird@^1.1.0: 580co-bluebird@^1.1.0:
574 version "1.1.0" 581 version "1.1.0"
575 resolved "https://registry.yarnpkg.com/co-bluebird/-/co-bluebird-1.1.0.tgz#c8b9f3a9320a7ed30987dcca1a5c3cff59655c7c" 582 resolved "https://registry.yarnpkg.com/co-bluebird/-/co-bluebird-1.1.0.tgz#c8b9f3a9320a7ed30987dcca1a5c3cff59655c7c"
@@ -649,10 +656,11 @@ concurrently@^3.1.0:
649 tree-kill "^1.1.0" 656 tree-kill "^1.1.0"
650 657
651config@^1.14.0: 658config@^1.14.0:
652 version "1.25.1" 659 version "1.26.1"
653 resolved "https://registry.yarnpkg.com/config/-/config-1.25.1.tgz#72ac51cde81e2c77c6b3b66d0130dae527a19c92" 660 resolved "https://registry.yarnpkg.com/config/-/config-1.26.1.tgz#f647ce32c345e80ba73a8eaa7a9a4b4e5b290ca1"
654 dependencies: 661 dependencies:
655 json5 "0.4.0" 662 json5 "0.4.0"
663 os-homedir "1.0.2"
656 664
657console-control-strings@^1.0.0, console-control-strings@~1.1.0: 665console-control-strings@^1.0.0, console-control-strings@~1.1.0:
658 version "1.1.0" 666 version "1.1.0"
@@ -750,8 +758,8 @@ dashdash@^1.12.0:
750 assert-plus "^1.0.0" 758 assert-plus "^1.0.0"
751 759
752date-fns@^1.23.0: 760date-fns@^1.23.0:
753 version "1.28.4" 761 version "1.28.5"
754 resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-1.28.4.tgz#7938aec34ba31fc8bd134d2344bc2e0bbfd95165" 762 resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-1.28.5.tgz#257cfc45d322df45ef5658665967ee841cd73faf"
755 763
756debug-log@^1.0.0: 764debug-log@^1.0.0:
757 version "1.0.1" 765 version "1.0.1"
@@ -769,17 +777,17 @@ debug@2.6.0:
769 dependencies: 777 dependencies:
770 ms "0.7.2" 778 ms "0.7.2"
771 779
772debug@2.6.1: 780debug@2.6.7:
773 version "2.6.1" 781 version "2.6.7"
774 resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.1.tgz#79855090ba2c4e3115cc7d8769491d58f0491351" 782 resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.7.tgz#92bad1f6d05bbb6bba22cca88bcd0ec894c2861e"
775 dependencies: 783 dependencies:
776 ms "0.7.2" 784 ms "2.0.0"
777 785
778debug@2.6.4, debug@^2.0.0, debug@^2.1.0, debug@^2.1.1, debug@^2.1.3, debug@^2.2.0, debug@^2.5.2: 786debug@2.6.8, debug@^2.0.0, debug@^2.1.0, debug@^2.1.1, debug@^2.1.3, debug@^2.2.0, debug@^2.5.2:
779 version "2.6.4" 787 version "2.6.8"
780 resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.4.tgz#7586a9b3c39741c0282ae33445c4e8ac74734fe0" 788 resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.8.tgz#e731531ca2ede27d188222427da17821d68ff4fc"
781 dependencies: 789 dependencies:
782 ms "0.7.3" 790 ms "2.0.0"
783 791
784deep-eql@^0.1.3: 792deep-eql@^0.1.3:
785 version "0.1.3" 793 version "0.1.3"
@@ -788,8 +796,8 @@ deep-eql@^0.1.3:
788 type-detect "0.1.1" 796 type-detect "0.1.1"
789 797
790deep-extend@~0.4.0: 798deep-extend@~0.4.0:
791 version "0.4.1" 799 version "0.4.2"
792 resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.4.1.tgz#efe4113d08085f4e6f9687759810f807469e2253" 800 resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.4.2.tgz#48b699c27e334bf89f10892be432f6e4c7d34a7f"
793 801
794deep-is@~0.1.3: 802deep-is@~0.1.3:
795 version "0.1.3" 803 version "0.1.3"
@@ -932,8 +940,8 @@ es-to-primitive@^1.1.1:
932 is-symbol "^1.0.1" 940 is-symbol "^1.0.1"
933 941
934es5-ext@^0.10.14, es5-ext@^0.10.9, es5-ext@~0.10.14: 942es5-ext@^0.10.14, es5-ext@^0.10.9, es5-ext@~0.10.14:
935 version "0.10.15" 943 version "0.10.21"
936 resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.15.tgz#c330a5934c1ee21284a7c081a86e5fd937c91ea6" 944 resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.21.tgz#19a725f9e51d0300bbc1e8e821109fd9daf55925"
937 dependencies: 945 dependencies:
938 es6-iterator "2" 946 es6-iterator "2"
939 es6-symbol "~3.1" 947 es6-symbol "~3.1"
@@ -1107,8 +1115,8 @@ eslint@~3.19.0:
1107 user-home "^2.0.0" 1115 user-home "^2.0.0"
1108 1116
1109espree@^3.4.0: 1117espree@^3.4.0:
1110 version "3.4.2" 1118 version "3.4.3"
1111 resolved "https://registry.yarnpkg.com/espree/-/espree-3.4.2.tgz#38dbdedbedc95b8961a1fbf04734a8f6a9c8c592" 1119 resolved "https://registry.yarnpkg.com/espree/-/espree-3.4.3.tgz#2910b5ccd49ce893c2ffffaab4fd8b3a31b82374"
1112 dependencies: 1120 dependencies:
1113 acorn "^5.0.1" 1121 acorn "^5.0.1"
1114 acorn-jsx "^3.0.0" 1122 acorn-jsx "^3.0.0"
@@ -1185,8 +1193,8 @@ express-validator@^3.1.0:
1185 validator "~6.2.0" 1193 validator "~6.2.0"
1186 1194
1187express@^4.12.4, express@^4.13.3: 1195express@^4.12.4, express@^4.13.3:
1188 version "4.15.2" 1196 version "4.15.3"
1189 resolved "https://registry.yarnpkg.com/express/-/express-4.15.2.tgz#af107fc148504457f2dca9a6f2571d7129b97b35" 1197 resolved "https://registry.yarnpkg.com/express/-/express-4.15.3.tgz#bab65d0f03aa80c358408972fc700f916944b662"
1190 dependencies: 1198 dependencies:
1191 accepts "~1.3.3" 1199 accepts "~1.3.3"
1192 array-flatten "1.1.1" 1200 array-flatten "1.1.1"
@@ -1194,32 +1202,32 @@ express@^4.12.4, express@^4.13.3:
1194 content-type "~1.0.2" 1202 content-type "~1.0.2"
1195 cookie "0.3.1" 1203 cookie "0.3.1"
1196 cookie-signature "1.0.6" 1204 cookie-signature "1.0.6"
1197 debug "2.6.1" 1205 debug "2.6.7"
1198 depd "~1.1.0" 1206 depd "~1.1.0"
1199 encodeurl "~1.0.1" 1207 encodeurl "~1.0.1"
1200 escape-html "~1.0.3" 1208 escape-html "~1.0.3"
1201 etag "~1.8.0" 1209 etag "~1.8.0"
1202 finalhandler "~1.0.0" 1210 finalhandler "~1.0.3"
1203 fresh "0.5.0" 1211 fresh "0.5.0"
1204 merge-descriptors "1.0.1" 1212 merge-descriptors "1.0.1"
1205 methods "~1.1.2" 1213 methods "~1.1.2"
1206 on-finished "~2.3.0" 1214 on-finished "~2.3.0"
1207 parseurl "~1.3.1" 1215 parseurl "~1.3.1"
1208 path-to-regexp "0.1.7" 1216 path-to-regexp "0.1.7"
1209 proxy-addr "~1.1.3" 1217 proxy-addr "~1.1.4"
1210 qs "6.4.0" 1218 qs "6.4.0"
1211 range-parser "~1.2.0" 1219 range-parser "~1.2.0"
1212 send "0.15.1" 1220 send "0.15.3"
1213 serve-static "1.12.1" 1221 serve-static "1.12.3"
1214 setprototypeof "1.0.3" 1222 setprototypeof "1.0.3"
1215 statuses "~1.3.1" 1223 statuses "~1.3.1"
1216 type-is "~1.6.14" 1224 type-is "~1.6.15"
1217 utils-merge "1.0.0" 1225 utils-merge "1.0.0"
1218 vary "~1.1.0" 1226 vary "~1.1.1"
1219 1227
1220extend@^3.0.0, extend@~3.0.0: 1228extend@^3.0.0, extend@~3.0.0:
1221 version "3.0.0" 1229 version "3.0.1"
1222 resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.0.tgz#5a474353b9f3353ddd8176dfd37b91c83a46f1d4" 1230 resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.1.tgz#a755ea7bc1adfcc5a31ce7e762dbaadc5e636444"
1223 1231
1224extsprintf@1.0.2: 1232extsprintf@1.0.2:
1225 version "1.0.2" 1233 version "1.0.2"
@@ -1256,11 +1264,11 @@ filestream@^4.0.0:
1256 typedarray-to-buffer "^3.0.0" 1264 typedarray-to-buffer "^3.0.0"
1257 xtend "^4.0.1" 1265 xtend "^4.0.1"
1258 1266
1259finalhandler@~1.0.0: 1267finalhandler@~1.0.3:
1260 version "1.0.2" 1268 version "1.0.3"
1261 resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.0.2.tgz#d0e36f9dbc557f2de14423df6261889e9d60c93a" 1269 resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.0.3.tgz#ef47e77950e999780e86022a560e3217e0d0cc89"
1262 dependencies: 1270 dependencies:
1263 debug "2.6.4" 1271 debug "2.6.7"
1264 encodeurl "~1.0.1" 1272 encodeurl "~1.0.1"
1265 escape-html "~1.0.3" 1273 escape-html "~1.0.3"
1266 on-finished "~2.3.0" 1274 on-finished "~2.3.0"
@@ -1285,12 +1293,6 @@ find-up@^2.0.0:
1285 dependencies: 1293 dependencies:
1286 locate-path "^2.0.0" 1294 locate-path "^2.0.0"
1287 1295
1288findup-sync@~0.3.0:
1289 version "0.3.0"
1290 resolved "https://registry.yarnpkg.com/findup-sync/-/findup-sync-0.3.0.tgz#37930aa5d816b777c03445e1966cc6790a4c0b16"
1291 dependencies:
1292 glob "~5.0.0"
1293
1294flat-cache@^1.2.1: 1296flat-cache@^1.2.1:
1295 version "1.2.2" 1297 version "1.2.2"
1296 resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-1.2.2.tgz#fa86714e72c21db88601761ecf2f555d1abc6b96" 1298 resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-1.2.2.tgz#fa86714e72c21db88601761ecf2f555d1abc6b96"
@@ -1375,7 +1377,7 @@ function-bind@^1.0.2, function-bind@^1.1.0:
1375 version "1.1.0" 1377 version "1.1.0"
1376 resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.0.tgz#16176714c801798e4e8f2cf7f7529467bb4a5771" 1378 resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.0.tgz#16176714c801798e4e8f2cf7f7529467bb4a5771"
1377 1379
1378gauge@~2.7.1: 1380gauge@~2.7.3:
1379 version "2.7.4" 1381 version "2.7.4"
1380 resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" 1382 resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7"
1381 dependencies: 1383 dependencies:
@@ -1424,7 +1426,7 @@ github-from-package@0.0.0:
1424 version "0.0.0" 1426 version "0.0.0"
1425 resolved "https://registry.yarnpkg.com/github-from-package/-/github-from-package-0.0.0.tgz#97fb5d96bfde8973313f20e8288ef9a167fa64ce" 1427 resolved "https://registry.yarnpkg.com/github-from-package/-/github-from-package-0.0.0.tgz#97fb5d96bfde8973313f20e8288ef9a167fa64ce"
1426 1428
1427glob@7.1.1, glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.1.1: 1429glob@7.1.1:
1428 version "7.1.1" 1430 version "7.1.1"
1429 resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.1.tgz#805211df04faaf1c63a3600306cdf5ade50b2ec8" 1431 resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.1.tgz#805211df04faaf1c63a3600306cdf5ade50b2ec8"
1430 dependencies: 1432 dependencies:
@@ -1435,13 +1437,14 @@ glob@7.1.1, glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.1.1:
1435 once "^1.3.0" 1437 once "^1.3.0"
1436 path-is-absolute "^1.0.0" 1438 path-is-absolute "^1.0.0"
1437 1439
1438glob@~5.0.0: 1440glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.1.1:
1439 version "5.0.15" 1441 version "7.1.2"
1440 resolved "https://registry.yarnpkg.com/glob/-/glob-5.0.15.tgz#1bc936b9e02f4a603fcc222ecf7633d30b8b93b1" 1442 resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15"
1441 dependencies: 1443 dependencies:
1444 fs.realpath "^1.0.0"
1442 inflight "^1.0.4" 1445 inflight "^1.0.4"
1443 inherits "2" 1446 inherits "2"
1444 minimatch "2 || 3" 1447 minimatch "^3.0.4"
1445 once "^1.3.0" 1448 once "^1.3.0"
1446 path-is-absolute "^1.0.0" 1449 path-is-absolute "^1.0.0"
1447 1450
@@ -1544,8 +1547,8 @@ iconv-lite@0.4.15:
1544 resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.15.tgz#fe265a218ac6a57cfe854927e9d04c19825eddeb" 1547 resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.15.tgz#fe265a218ac6a57cfe854927e9d04c19825eddeb"
1545 1548
1546ignore@^3.0.11, ignore@^3.0.9, ignore@^3.2.0: 1549ignore@^3.0.11, ignore@^3.0.9, ignore@^3.2.0:
1547 version "3.2.7" 1550 version "3.3.3"
1548 resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.2.7.tgz#4810ca5f1d8eca5595213a34b94f2eb4ed926bbd" 1551 resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.3.tgz#432352e57accd87ab3110e82d3fea0e47812156d"
1549 1552
1550immediate-chunk-store@^1.0.8: 1553immediate-chunk-store@^1.0.8:
1551 version "1.0.8" 1554 version "1.0.8"
@@ -1555,9 +1558,9 @@ imurmurhash@^0.1.4:
1555 version "0.1.4" 1558 version "0.1.4"
1556 resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" 1559 resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea"
1557 1560
1558inflection@^1.6.0: 1561inflection@1.10.0:
1559 version "1.12.0" 1562 version "1.10.0"
1560 resolved "https://registry.yarnpkg.com/inflection/-/inflection-1.12.0.tgz#a200935656d6f5f6bc4dc7502e1aecb703228416" 1563 resolved "https://registry.yarnpkg.com/inflection/-/inflection-1.10.0.tgz#5bffcb1197ad3e81050f8e17e21668087ee9eb2f"
1561 1564
1562inflight@^1.0.4: 1565inflight@^1.0.4:
1563 version "1.0.6" 1566 version "1.0.6"
@@ -1618,6 +1621,10 @@ is-ascii@^1.0.0:
1618 version "1.0.0" 1621 version "1.0.0"
1619 resolved "https://registry.yarnpkg.com/is-ascii/-/is-ascii-1.0.0.tgz#f02ad0259a0921cd199ff21ce1b09e0f6b4e3929" 1622 resolved "https://registry.yarnpkg.com/is-ascii/-/is-ascii-1.0.0.tgz#f02ad0259a0921cd199ff21ce1b09e0f6b4e3929"
1620 1623
1624is-bluebird@^1.0.2:
1625 version "1.0.2"
1626 resolved "https://registry.yarnpkg.com/is-bluebird/-/is-bluebird-1.0.2.tgz#096439060f4aa411abee19143a84d6a55346d6e2"
1627
1621is-callable@^1.1.1, is-callable@^1.1.3: 1628is-callable@^1.1.1, is-callable@^1.1.3:
1622 version "1.1.3" 1629 version "1.1.3"
1623 resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.3.tgz#86eb75392805ddc33af71c92a0eedf74ee7604b2" 1630 resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.3.tgz#86eb75392805ddc33af71c92a0eedf74ee7604b2"
@@ -1694,8 +1701,8 @@ is-typedarray@^1.0.0, is-typedarray@~1.0.0:
1694 resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" 1701 resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a"
1695 1702
1696is-windows@^1.0.0: 1703is-windows@^1.0.0:
1697 version "1.0.0" 1704 version "1.0.1"
1698 resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.0.tgz#c61d61020c3ebe99261b781bd3d1622395f547f8" 1705 resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.1.tgz#310db70f742d259a16a369202b51af84233310d9"
1699 1706
1700isarray@0.0.1: 1707isarray@0.0.1:
1701 version "0.0.1" 1708 version "0.0.1"
@@ -1724,8 +1731,8 @@ js-tokens@^3.0.0:
1724 resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.1.tgz#08e9f132484a2c45a30907e9dc4d5567b7f114d7" 1731 resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.1.tgz#08e9f132484a2c45a30907e9dc4d5567b7f114d7"
1725 1732
1726js-yaml@^3.5.1, js-yaml@^3.5.4: 1733js-yaml@^3.5.1, js-yaml@^3.5.4:
1727 version "3.8.3" 1734 version "3.8.4"
1728 resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.8.3.tgz#33a05ec481c850c8875929166fe1beb61c728766" 1735 resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.8.4.tgz#520b4564f86573ba96662af85a8cafa7b4b5a6f6"
1729 dependencies: 1736 dependencies:
1730 argparse "^1.0.7" 1737 argparse "^1.0.7"
1731 esprima "^3.1.1" 1738 esprima "^3.1.1"
@@ -1887,9 +1894,9 @@ lodash.keys@^3.0.0:
1887 lodash.isarguments "^3.0.0" 1894 lodash.isarguments "^3.0.0"
1888 lodash.isarray "^3.0.0" 1895 lodash.isarray "^3.0.0"
1889 1896
1890lodash@4.12.0: 1897lodash@4.15.0:
1891 version "4.12.0" 1898 version "4.15.0"
1892 resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.12.0.tgz#2bd6dc46a040f59e686c972ed21d93dc59053258" 1899 resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.15.0.tgz#3162391d8f0140aa22cf8f6b3c34d6b7f63d3aa9"
1893 1900
1894lodash@^3.3.1: 1901lodash@^3.3.1:
1895 version "3.10.1" 1902 version "3.10.1"
@@ -1959,15 +1966,19 @@ mime-types@^2.1.12, mime-types@~2.1.11, mime-types@~2.1.15, mime-types@~2.1.7:
1959 dependencies: 1966 dependencies:
1960 mime-db "~1.27.0" 1967 mime-db "~1.27.0"
1961 1968
1962mime@1.3.4, mime@^1.3.4: 1969mime@1.3.4:
1963 version "1.3.4" 1970 version "1.3.4"
1964 resolved "https://registry.yarnpkg.com/mime/-/mime-1.3.4.tgz#115f9e3b6b3daf2959983cb38f149a2d40eb5d53" 1971 resolved "https://registry.yarnpkg.com/mime/-/mime-1.3.4.tgz#115f9e3b6b3daf2959983cb38f149a2d40eb5d53"
1965 1972
1966"minimatch@2 || 3", minimatch@^3.0.0, minimatch@^3.0.2, minimatch@^3.0.3: 1973mime@^1.3.4:
1967 version "3.0.3" 1974 version "1.3.6"
1968 resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.3.tgz#2a4e4090b96b2db06a9d7df01055a62a77c9b774" 1975 resolved "https://registry.yarnpkg.com/mime/-/mime-1.3.6.tgz#591d84d3653a6b0b4a3b9df8de5aa8108e72e5e0"
1976
1977minimatch@^3.0.0, minimatch@^3.0.2, minimatch@^3.0.3, minimatch@^3.0.4:
1978 version "3.0.4"
1979 resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
1969 dependencies: 1980 dependencies:
1970 brace-expansion "^1.0.0" 1981 brace-expansion "^1.1.7"
1971 1982
1972minimist@0.0.8, minimist@~0.0.1: 1983minimist@0.0.8, minimist@~0.0.1:
1973 version "0.0.8" 1984 version "0.0.8"
@@ -1984,8 +1995,8 @@ mkdirp@0.5.1, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.1:
1984 minimist "0.0.8" 1995 minimist "0.0.8"
1985 1996
1986mocha@^3.0.1: 1997mocha@^3.0.1:
1987 version "3.3.0" 1998 version "3.4.2"
1988 resolved "https://registry.yarnpkg.com/mocha/-/mocha-3.3.0.tgz#d29b7428d3f52c82e2e65df1ecb7064e1aabbfb5" 1999 resolved "https://registry.yarnpkg.com/mocha/-/mocha-3.4.2.tgz#d0ef4d332126dbf18d0d640c9b382dd48be97594"
1989 dependencies: 2000 dependencies:
1990 browser-stdout "1.3.0" 2001 browser-stdout "1.3.0"
1991 commander "2.9.0" 2002 commander "2.9.0"
@@ -2010,11 +2021,11 @@ moment-timezone@^0.5.4:
2010 resolved "https://registry.yarnpkg.com/moment/-/moment-2.18.1.tgz#c36193dd3ce1c2eed2adb7c802dbbc77a81b1c0f" 2021 resolved "https://registry.yarnpkg.com/moment/-/moment-2.18.1.tgz#c36193dd3ce1c2eed2adb7c802dbbc77a81b1c0f"
2011 2022
2012morgan@^1.5.3: 2023morgan@^1.5.3:
2013 version "1.8.1" 2024 version "1.8.2"
2014 resolved "https://registry.yarnpkg.com/morgan/-/morgan-1.8.1.tgz#f93023d3887bd27b78dfd6023cea7892ee27a4b1" 2025 resolved "https://registry.yarnpkg.com/morgan/-/morgan-1.8.2.tgz#784ac7734e4a453a9c6e6e8680a9329275c8b687"
2015 dependencies: 2026 dependencies:
2016 basic-auth "~1.1.0" 2027 basic-auth "~1.1.0"
2017 debug "2.6.1" 2028 debug "2.6.8"
2018 depd "~1.1.0" 2029 depd "~1.1.0"
2019 on-finished "~2.3.0" 2030 on-finished "~2.3.0"
2020 on-headers "~1.0.1" 2031 on-headers "~1.0.1"
@@ -2042,9 +2053,9 @@ ms@0.7.2:
2042 version "0.7.2" 2053 version "0.7.2"
2043 resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.2.tgz#ae25cf2512b3885a1d95d7f037868d8431124765" 2054 resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.2.tgz#ae25cf2512b3885a1d95d7f037868d8431124765"
2044 2055
2045ms@0.7.3: 2056ms@2.0.0:
2046 version "0.7.3" 2057 version "2.0.0"
2047 resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.3.tgz#708155a5e44e33f5fd0fc53e81d0d40a91be1fff" 2058 resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
2048 2059
2049multer@^1.1.0: 2060multer@^1.1.0:
2050 version "1.3.0" 2061 version "1.3.0"
@@ -2091,8 +2102,8 @@ next-event@^1.0.0:
2091 resolved "https://registry.yarnpkg.com/next-event/-/next-event-1.0.0.tgz#e7778acde2e55802e0ad1879c39cf6f75eda61d8" 2102 resolved "https://registry.yarnpkg.com/next-event/-/next-event-1.0.0.tgz#e7778acde2e55802e0ad1879c39cf6f75eda61d8"
2092 2103
2093node-abi@^2.0.0: 2104node-abi@^2.0.0:
2094 version "2.0.0" 2105 version "2.0.2"
2095 resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-2.0.0.tgz#443bfd151b599231028ae425e592e76cd31cb537" 2106 resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-2.0.2.tgz#00f3e0a58100eb480133b48c99a32cc1f9e6c93e"
2096 2107
2097node-pre-gyp@0.6.32: 2108node-pre-gyp@0.6.32:
2098 version "0.6.32" 2109 version "0.6.32"
@@ -2108,6 +2119,10 @@ node-pre-gyp@0.6.32:
2108 tar "~2.2.1" 2119 tar "~2.2.1"
2109 tar-pack "~3.3.0" 2120 tar-pack "~3.3.0"
2110 2121
2122node-uuid@~1.4.4:
2123 version "1.4.8"
2124 resolved "https://registry.yarnpkg.com/node-uuid/-/node-uuid-1.4.8.tgz#b040eb0923968afabf8d32fb1f17f1167fdab907"
2125
2111noop-logger@^0.1.1: 2126noop-logger@^0.1.1:
2112 version "0.1.1" 2127 version "0.1.1"
2113 resolved "https://registry.yarnpkg.com/noop-logger/-/noop-logger-0.1.1.tgz#94a2b1633c4f1317553007d8966fd0e841b6a4c2" 2128 resolved "https://registry.yarnpkg.com/noop-logger/-/noop-logger-0.1.1.tgz#94a2b1633c4f1317553007d8966fd0e841b6a4c2"
@@ -2119,12 +2134,12 @@ nopt@~3.0.6:
2119 abbrev "1" 2134 abbrev "1"
2120 2135
2121npmlog@^4.0.1: 2136npmlog@^4.0.1:
2122 version "4.0.2" 2137 version "4.1.0"
2123 resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.0.2.tgz#d03950e0e78ce1527ba26d2a7592e9348ac3e75f" 2138 resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.0.tgz#dc59bee85f64f00ed424efb2af0783df25d1c0b5"
2124 dependencies: 2139 dependencies:
2125 are-we-there-yet "~1.1.2" 2140 are-we-there-yet "~1.1.2"
2126 console-control-strings "~1.1.0" 2141 console-control-strings "~1.1.0"
2127 gauge "~2.7.1" 2142 gauge "~2.7.3"
2128 set-blocking "~2.0.0" 2143 set-blocking "~2.0.0"
2129 2144
2130number-is-nan@^1.0.0: 2145number-is-nan@^1.0.0:
@@ -2220,7 +2235,7 @@ optionator@^0.8.2:
2220 type-check "~0.3.2" 2235 type-check "~0.3.2"
2221 wordwrap "~1.0.0" 2236 wordwrap "~1.0.0"
2222 2237
2223os-homedir@^1.0.0, os-homedir@^1.0.1: 2238os-homedir@1.0.2, os-homedir@^1.0.0, os-homedir@^1.0.1:
2224 version "1.0.2" 2239 version "1.0.2"
2225 resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" 2240 resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3"
2226 2241
@@ -2240,9 +2255,9 @@ package-json-versionify@^1.0.2:
2240 dependencies: 2255 dependencies:
2241 browserify-package-json "^1.0.0" 2256 browserify-package-json "^1.0.0"
2242 2257
2243packet-reader@0.2.0: 2258packet-reader@0.3.1:
2244 version "0.2.0" 2259 version "0.3.1"
2245 resolved "https://registry.yarnpkg.com/packet-reader/-/packet-reader-0.2.0.tgz#819df4d010b82d5ea5671f8a1a3acf039bcd7700" 2260 resolved "https://registry.yarnpkg.com/packet-reader/-/packet-reader-0.3.1.tgz#cd62e60af8d7fea8a705ec4ff990871c46871f27"
2246 2261
2247parse-json@^2.2.0: 2262parse-json@^2.2.0:
2248 version "2.2.0" 2263 version "2.2.0"
@@ -2336,11 +2351,11 @@ pg-types@1.*:
2336 postgres-interval "~1.0.0" 2351 postgres-interval "~1.0.0"
2337 2352
2338pg@^6.1.0: 2353pg@^6.1.0:
2339 version "6.1.5" 2354 version "6.2.3"
2340 resolved "https://registry.yarnpkg.com/pg/-/pg-6.1.5.tgz#204fa40c1252ab7220d7cf6992886b20d77862b8" 2355 resolved "https://registry.yarnpkg.com/pg/-/pg-6.2.3.tgz#8988b7c69a1875a997d73b92036c42590b5f8024"
2341 dependencies: 2356 dependencies:
2342 buffer-writer "1.0.1" 2357 buffer-writer "1.0.1"
2343 packet-reader "0.2.0" 2358 packet-reader "0.3.1"
2344 pg-connection-string "0.1.3" 2359 pg-connection-string "0.1.3"
2345 pg-pool "1.*" 2360 pg-pool "1.*"
2346 pg-types "1.*" 2361 pg-types "1.*"
@@ -2348,8 +2363,8 @@ pg@^6.1.0:
2348 semver "4.3.2" 2363 semver "4.3.2"
2349 2364
2350pgpass@1.x: 2365pgpass@1.x:
2351 version "1.0.1" 2366 version "1.0.2"
2352 resolved "https://registry.yarnpkg.com/pgpass/-/pgpass-1.0.1.tgz#0de8b5bef993295d90a7e17d976f568dcd25d49f" 2367 resolved "https://registry.yarnpkg.com/pgpass/-/pgpass-1.0.2.tgz#2a7bb41b6065b67907e91da1b07c1847c877b306"
2353 dependencies: 2368 dependencies:
2354 split "^1.0.0" 2369 split "^1.0.0"
2355 2370
@@ -2461,7 +2476,7 @@ promisify-any@2.0.1:
2461 co-bluebird "^1.1.0" 2476 co-bluebird "^1.1.0"
2462 is-generator "^1.0.2" 2477 is-generator "^1.0.2"
2463 2478
2464proxy-addr@~1.1.3: 2479proxy-addr@~1.1.4:
2465 version "1.1.4" 2480 version "1.1.4"
2466 resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-1.1.4.tgz#27e545f6960a44a627d9b44467e35c1b6b4ce2f3" 2481 resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-1.1.4.tgz#27e545f6960a44a627d9b44467e35c1b6b4ce2f3"
2467 dependencies: 2482 dependencies:
@@ -2488,8 +2503,8 @@ qs@6.4.0, qs@^6.1.0, qs@~6.4.0:
2488 resolved "https://registry.yarnpkg.com/qs/-/qs-6.4.0.tgz#13e26d28ad6b0ffaa91312cd3bf708ed351e7233" 2503 resolved "https://registry.yarnpkg.com/qs/-/qs-6.4.0.tgz#13e26d28ad6b0ffaa91312cd3bf708ed351e7233"
2489 2504
2490random-access-file@^1.0.1: 2505random-access-file@^1.0.1:
2491 version "1.7.0" 2506 version "1.7.2"
2492 resolved "https://registry.yarnpkg.com/random-access-file/-/random-access-file-1.7.0.tgz#3746e28dc27fe24e406ac0a396ffaeef22751983" 2507 resolved "https://registry.yarnpkg.com/random-access-file/-/random-access-file-1.7.2.tgz#053e2e8ec7670370a8e8b10da962e45753f22dbc"
2493 dependencies: 2508 dependencies:
2494 buffer-alloc-unsafe "^1.0.0" 2509 buffer-alloc-unsafe "^1.0.0"
2495 debug "^2.5.2" 2510 debug "^2.5.2"
@@ -2690,8 +2705,8 @@ run-series@^1.0.2:
2690 resolved "https://registry.yarnpkg.com/run-series/-/run-series-1.1.4.tgz#89a73ddc5e75c9ef8ab6320c0a1600d6a41179b9" 2705 resolved "https://registry.yarnpkg.com/run-series/-/run-series-1.1.4.tgz#89a73ddc5e75c9ef8ab6320c0a1600d6a41179b9"
2691 2706
2692rusha@^0.8.1: 2707rusha@^0.8.1:
2693 version "0.8.5" 2708 version "0.8.6"
2694 resolved "https://registry.yarnpkg.com/rusha/-/rusha-0.8.5.tgz#a30ae9bd5a4e80fbc96fbe7a13232b944be24f84" 2709 resolved "https://registry.yarnpkg.com/rusha/-/rusha-0.8.6.tgz#b264ddaa4d49a1d67300061858ba9358c4adca14"
2695 2710
2696rx-lite@^3.1.2: 2711rx-lite@^3.1.2:
2697 version "3.1.2" 2712 version "3.1.2"
@@ -2721,11 +2736,11 @@ semver@5.3.0, semver@^5.0.1, semver@^5.3.0, semver@~5.3.0:
2721 version "5.3.0" 2736 version "5.3.0"
2722 resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f" 2737 resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f"
2723 2738
2724send@0.15.1: 2739send@0.15.3:
2725 version "0.15.1" 2740 version "0.15.3"
2726 resolved "https://registry.yarnpkg.com/send/-/send-0.15.1.tgz#8a02354c26e6f5cca700065f5f0cdeba90ec7b5f" 2741 resolved "https://registry.yarnpkg.com/send/-/send-0.15.3.tgz#5013f9f99023df50d1bd9892c19e3defd1d53309"
2727 dependencies: 2742 dependencies:
2728 debug "2.6.1" 2743 debug "2.6.7"
2729 depd "~1.1.0" 2744 depd "~1.1.0"
2730 destroy "~1.0.4" 2745 destroy "~1.0.4"
2731 encodeurl "~1.0.1" 2746 encodeurl "~1.0.1"
@@ -2734,7 +2749,7 @@ send@0.15.1:
2734 fresh "0.5.0" 2749 fresh "0.5.0"
2735 http-errors "~1.6.1" 2750 http-errors "~1.6.1"
2736 mime "1.3.4" 2751 mime "1.3.4"
2737 ms "0.7.2" 2752 ms "2.0.0"
2738 on-finished "~2.3.0" 2753 on-finished "~2.3.0"
2739 range-parser "~1.2.0" 2754 range-parser "~1.2.0"
2740 statuses "~1.3.1" 2755 statuses "~1.3.1"
@@ -2745,35 +2760,36 @@ sentence-case@^1.1.1:
2745 dependencies: 2760 dependencies:
2746 lower-case "^1.1.1" 2761 lower-case "^1.1.1"
2747 2762
2748sequelize@^3.27.0: 2763sequelize@4.0.0-2:
2749 version "3.30.4" 2764 version "4.0.0-2"
2750 resolved "https://registry.yarnpkg.com/sequelize/-/sequelize-3.30.4.tgz#bda2df1e31854b099e4149a111e9fc0a5ca1d1a4" 2765 resolved "https://registry.yarnpkg.com/sequelize/-/sequelize-4.0.0-2.tgz#8143f50fa00ac62ba95394f4c81bd97e7c3600d5"
2751 dependencies: 2766 dependencies:
2752 bluebird "^3.3.4" 2767 bluebird "^3.4.6"
2768 cls-bluebird "^2.0.1"
2769 debug "^2.2.0"
2753 depd "^1.1.0" 2770 depd "^1.1.0"
2754 dottie "^1.0.0" 2771 dottie "^1.0.0"
2755 generic-pool "2.4.2" 2772 generic-pool "2.4.2"
2756 inflection "^1.6.0" 2773 inflection "1.10.0"
2757 lodash "4.12.0" 2774 lodash "4.15.0"
2758 moment "^2.13.0" 2775 moment "^2.13.0"
2759 moment-timezone "^0.5.4" 2776 moment-timezone "^0.5.4"
2777 node-uuid "~1.4.4"
2760 retry-as-promised "^2.0.0" 2778 retry-as-promised "^2.0.0"
2761 semver "^5.0.1" 2779 semver "^5.0.1"
2762 shimmer "1.1.0" 2780 terraformer-wkt-parser "^1.1.2"
2763 terraformer-wkt-parser "^1.1.0"
2764 toposort-class "^1.0.1" 2781 toposort-class "^1.0.1"
2765 uuid "^3.0.0" 2782 validator "^5.6.0"
2766 validator "^5.2.0" 2783 wkx "0.3.0"
2767 wkx "0.2.0"
2768 2784
2769serve-static@1.12.1: 2785serve-static@1.12.3:
2770 version "1.12.1" 2786 version "1.12.3"
2771 resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.12.1.tgz#7443a965e3ced647aceb5639fa06bf4d1bbe0039" 2787 resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.12.3.tgz#9f4ba19e2f3030c547f8af99107838ec38d5b1e2"
2772 dependencies: 2788 dependencies:
2773 encodeurl "~1.0.1" 2789 encodeurl "~1.0.1"
2774 escape-html "~1.0.3" 2790 escape-html "~1.0.3"
2775 parseurl "~1.3.1" 2791 parseurl "~1.3.1"
2776 send "0.15.1" 2792 send "0.15.3"
2777 2793
2778set-blocking@~2.0.0: 2794set-blocking@~2.0.0:
2779 version "2.0.0" 2795 version "2.0.0"
@@ -2801,7 +2817,7 @@ shelljs@^0.7.5:
2801 interpret "^1.0.0" 2817 interpret "^1.0.0"
2802 rechoir "^0.6.2" 2818 rechoir "^0.6.2"
2803 2819
2804shimmer@1.1.0: 2820shimmer@^1.1.0:
2805 version "1.1.0" 2821 version "1.1.0"
2806 resolved "https://registry.yarnpkg.com/shimmer/-/shimmer-1.1.0.tgz#97d7377137ffbbab425522e429fe0aa89a488b35" 2822 resolved "https://registry.yarnpkg.com/shimmer/-/shimmer-1.1.0.tgz#97d7377137ffbbab425522e429fe0aa89a488b35"
2807 2823
@@ -2866,6 +2882,16 @@ sntp@1.x.x:
2866 dependencies: 2882 dependencies:
2867 hoek "2.x.x" 2883 hoek "2.x.x"
2868 2884
2885source-map-support@^0.4.15:
2886 version "0.4.15"
2887 resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.15.tgz#03202df65c06d2bd8c7ec2362a193056fef8d3b1"
2888 dependencies:
2889 source-map "^0.5.6"
2890
2891source-map@^0.5.6:
2892 version "0.5.6"
2893 resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.6.tgz#75ce38f52bf0733c5a7f0c118d81334a2bb5f412"
2894
2869spawn-command@^0.0.2-1: 2895spawn-command@^0.0.2-1:
2870 version "0.0.2" 2896 version "0.0.2"
2871 resolved "https://registry.yarnpkg.com/spawn-command/-/spawn-command-0.0.2.tgz#9544e1a43ca045f8531aac1a48cb29bdae62338e" 2897 resolved "https://registry.yarnpkg.com/spawn-command/-/spawn-command-0.0.2.tgz#9544e1a43ca045f8531aac1a48cb29bdae62338e"
@@ -2900,8 +2926,8 @@ sshpk@^1.7.0:
2900 tweetnacl "~0.14.0" 2926 tweetnacl "~0.14.0"
2901 2927
2902stack-trace@0.0.x: 2928stack-trace@0.0.x:
2903 version "0.0.9" 2929 version "0.0.10"
2904 resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-0.0.9.tgz#a8f6eaeca90674c333e7c43953f275b451510695" 2930 resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-0.0.10.tgz#547c70b347e8d32b4e108ea1a2a159e5fdde19c0"
2905 2931
2906standard-engine@~7.0.0: 2932standard-engine@~7.0.0:
2907 version "7.0.0" 2933 version "7.0.0"
@@ -2962,7 +2988,7 @@ streamsearch@0.1.2:
2962 version "0.1.2" 2988 version "0.1.2"
2963 resolved "https://registry.yarnpkg.com/streamsearch/-/streamsearch-0.1.2.tgz#808b9d0e56fc273d809ba57338e929919a1a9f1a" 2989 resolved "https://registry.yarnpkg.com/streamsearch/-/streamsearch-0.1.2.tgz#808b9d0e56fc273d809ba57338e929919a1a9f1a"
2964 2990
2965string-width@^1.0.1: 2991string-width@^1.0.1, string-width@^1.0.2:
2966 version "1.0.2" 2992 version "1.0.2"
2967 resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" 2993 resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3"
2968 dependencies: 2994 dependencies:
@@ -2989,10 +3015,10 @@ string_decoder@~0.10.x:
2989 resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" 3015 resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94"
2990 3016
2991string_decoder@~1.0.0: 3017string_decoder@~1.0.0:
2992 version "1.0.0" 3018 version "1.0.1"
2993 resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.0.0.tgz#f06f41157b664d86069f84bdbdc9b0d8ab281667" 3019 resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.0.1.tgz#62e200f039955a6810d8df0a33ffc0f013662d98"
2994 dependencies: 3020 dependencies:
2995 buffer-shims "~1.0.0" 3021 safe-buffer "^5.0.1"
2996 3022
2997stringstream@~0.0.4: 3023stringstream@~0.0.4:
2998 version "0.0.5" 3024 version "0.0.5"
@@ -3094,8 +3120,8 @@ tar-pack@~3.3.0:
3094 uid-number "~0.0.6" 3120 uid-number "~0.0.6"
3095 3121
3096tar-stream@^1.1.2: 3122tar-stream@^1.1.2:
3097 version "1.5.2" 3123 version "1.5.4"
3098 resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-1.5.2.tgz#fbc6c6e83c1a19d4cb48c7d96171fc248effc7bf" 3124 resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-1.5.4.tgz#36549cf04ed1aee9b2a30c0143252238daf94016"
3099 dependencies: 3125 dependencies:
3100 bl "^1.0.0" 3126 bl "^1.0.0"
3101 end-of-stream "^1.0.0" 3127 end-of-stream "^1.0.0"
@@ -3110,7 +3136,7 @@ tar@~2.2.1:
3110 fstream "^1.0.2" 3136 fstream "^1.0.2"
3111 inherits "2" 3137 inherits "2"
3112 3138
3113terraformer-wkt-parser@^1.1.0: 3139terraformer-wkt-parser@^1.1.2:
3114 version "1.1.2" 3140 version "1.1.2"
3115 resolved "https://registry.yarnpkg.com/terraformer-wkt-parser/-/terraformer-wkt-parser-1.1.2.tgz#336a0c8fc82094a5aff83288f69aedecd369bf0c" 3141 resolved "https://registry.yarnpkg.com/terraformer-wkt-parser/-/terraformer-wkt-parser-1.1.2.tgz#336a0c8fc82094a5aff83288f69aedecd369bf0c"
3116 dependencies: 3142 dependencies:
@@ -3127,8 +3153,8 @@ text-table@~0.2.0:
3127 resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" 3153 resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4"
3128 3154
3129thenify@^3.0.0: 3155thenify@^3.0.0:
3130 version "3.2.1" 3156 version "3.3.0"
3131 resolved "https://registry.yarnpkg.com/thenify/-/thenify-3.2.1.tgz#251fd1c80aff6e5cf57cb179ab1fcb724269bd11" 3157 resolved "https://registry.yarnpkg.com/thenify/-/thenify-3.3.0.tgz#e69e38a1babe969b0108207978b9f62b88604839"
3132 dependencies: 3158 dependencies:
3133 any-promise "^1.0.0" 3159 any-promise "^1.0.0"
3134 3160
@@ -3182,8 +3208,8 @@ tryit@^1.0.1:
3182 resolved "https://registry.yarnpkg.com/tryit/-/tryit-1.0.3.tgz#393be730a9446fd1ead6da59a014308f36c289cb" 3208 resolved "https://registry.yarnpkg.com/tryit/-/tryit-1.0.3.tgz#393be730a9446fd1ead6da59a014308f36c289cb"
3183 3209
3184tslib@^1.0.0, tslib@^1.6.0: 3210tslib@^1.0.0, tslib@^1.6.0:
3185 version "1.7.0" 3211 version "1.7.1"
3186 resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.7.0.tgz#6e8366695f72961252b35167b0dd4fbeeafba491" 3212 resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.7.1.tgz#bc8004164691923a79fe8378bbeb3da2017538ec"
3187 3213
3188tslint-config-standard@^5.0.2: 3214tslint-config-standard@^5.0.2:
3189 version "5.0.2" 3215 version "5.0.2"
@@ -3192,31 +3218,34 @@ tslint-config-standard@^5.0.2:
3192 tslint-eslint-rules "^4.0.0" 3218 tslint-eslint-rules "^4.0.0"
3193 3219
3194tslint-eslint-rules@^4.0.0: 3220tslint-eslint-rules@^4.0.0:
3195 version "4.0.0" 3221 version "4.1.0"
3196 resolved "https://registry.yarnpkg.com/tslint-eslint-rules/-/tslint-eslint-rules-4.0.0.tgz#4e0e59ecd5701c9a48c66ed47bdcafb1c635d27b" 3222 resolved "https://registry.yarnpkg.com/tslint-eslint-rules/-/tslint-eslint-rules-4.1.0.tgz#8fee295c42f4c8078139deb16ee7b4510fd516b7"
3197 dependencies: 3223 dependencies:
3198 doctrine "^0.7.2" 3224 doctrine "^0.7.2"
3199 tslib "^1.0.0" 3225 tslib "^1.0.0"
3200 tsutils "^1.4.0" 3226 tsutils "^1.4.0"
3201 3227
3202tslint@^5.2.0: 3228tslint@^5.2.0:
3203 version "5.2.0" 3229 version "5.3.2"
3204 resolved "https://registry.yarnpkg.com/tslint/-/tslint-5.2.0.tgz#16a2addf20cb748385f544e9a0edab086bc34114" 3230 resolved "https://registry.yarnpkg.com/tslint/-/tslint-5.3.2.tgz#e56459fb095a7307f103b84052174f5e3bbef6ed"
3205 dependencies: 3231 dependencies:
3206 babel-code-frame "^6.22.0" 3232 babel-code-frame "^6.22.0"
3207 colors "^1.1.2" 3233 colors "^1.1.2"
3208 diff "^3.2.0" 3234 diff "^3.2.0"
3209 findup-sync "~0.3.0"
3210 glob "^7.1.1" 3235 glob "^7.1.1"
3211 optimist "~0.6.0" 3236 optimist "~0.6.0"
3212 resolve "^1.3.2" 3237 resolve "^1.3.2"
3213 semver "^5.3.0" 3238 semver "^5.3.0"
3214 tslib "^1.6.0" 3239 tslib "^1.6.0"
3215 tsutils "^1.8.0" 3240 tsutils "^2.0.0"
3216 3241
3217tsutils@^1.4.0, tsutils@^1.8.0: 3242tsutils@^1.4.0:
3218 version "1.8.0" 3243 version "1.9.1"
3219 resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-1.8.0.tgz#bf8118ed8e80cd5c9fc7d75728c7963d44ed2f52" 3244 resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-1.9.1.tgz#b9f9ab44e55af9681831d5f28d0aeeaf5c750cb0"
3245
3246tsutils@^2.0.0:
3247 version "2.1.0"
3248 resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-2.1.0.tgz#5be8376c929528f65b302de9e17b0004e4c1eb20"
3220 3249
3221tunnel-agent@^0.4.3: 3250tunnel-agent@^0.4.3:
3222 version "0.4.3" 3251 version "0.4.3"
@@ -3246,7 +3275,7 @@ type-detect@^1.0.0:
3246 version "1.0.0" 3275 version "1.0.0"
3247 resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-1.0.0.tgz#762217cc06db258ec48908a1298e8b95121e8ea2" 3276 resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-1.0.0.tgz#762217cc06db258ec48908a1298e8b95121e8ea2"
3248 3277
3249type-is@^1.6.0, type-is@^1.6.4, type-is@~1.6.14: 3278type-is@^1.6.0, type-is@^1.6.4, type-is@~1.6.15:
3250 version "1.6.15" 3279 version "1.6.15"
3251 resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.15.tgz#cab10fb4909e441c82842eafe1ad646c81804410" 3280 resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.15.tgz#cab10fb4909e441c82842eafe1ad646c81804410"
3252 dependencies: 3281 dependencies:
@@ -3349,7 +3378,7 @@ validator.js@^1.1.1:
3349 version "1.2.3" 3378 version "1.2.3"
3350 resolved "https://registry.yarnpkg.com/validator.js/-/validator.js-1.2.3.tgz#f8e623f60e53bada54880333649970996a3446e1" 3379 resolved "https://registry.yarnpkg.com/validator.js/-/validator.js-1.2.3.tgz#f8e623f60e53bada54880333649970996a3446e1"
3351 3380
3352validator@^5.2.0: 3381validator@^5.6.0:
3353 version "5.7.0" 3382 version "5.7.0"
3354 resolved "https://registry.yarnpkg.com/validator/-/validator-5.7.0.tgz#7a87a58146b695ac486071141c0c49d67da05e5c" 3383 resolved "https://registry.yarnpkg.com/validator/-/validator-5.7.0.tgz#7a87a58146b695ac486071141c0c49d67da05e5c"
3355 3384
@@ -3357,7 +3386,7 @@ validator@~6.2.0:
3357 version "6.2.1" 3386 version "6.2.1"
3358 resolved "https://registry.yarnpkg.com/validator/-/validator-6.2.1.tgz#bc575b78d15beb2e338a665ba9530c7f409ef667" 3387 resolved "https://registry.yarnpkg.com/validator/-/validator-6.2.1.tgz#bc575b78d15beb2e338a665ba9530c7f409ef667"
3359 3388
3360vary@^1, vary@~1.1.0: 3389vary@^1, vary@~1.1.1:
3361 version "1.1.1" 3390 version "1.1.1"
3362 resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.1.tgz#67535ebb694c1d52257457984665323f587e8d37" 3391 resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.1.tgz#67535ebb694c1d52257457984665323f587e8d37"
3363 3392
@@ -3434,10 +3463,10 @@ which@^1.1.1, which@^1.2.9:
3434 isexe "^2.0.0" 3463 isexe "^2.0.0"
3435 3464
3436wide-align@^1.1.0: 3465wide-align@^1.1.0:
3437 version "1.1.0" 3466 version "1.1.2"
3438 resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.0.tgz#40edde802a71fea1f070da3e62dcda2e7add96ad" 3467 resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.2.tgz#571e0f1b0604636ebc0dfc21b0339bbe31341710"
3439 dependencies: 3468 dependencies:
3440 string-width "^1.0.1" 3469 string-width "^1.0.2"
3441 3470
3442winston@^2.1.1: 3471winston@^2.1.1:
3443 version "2.3.1" 3472 version "2.3.1"
@@ -3450,9 +3479,9 @@ winston@^2.1.1:
3450 isstream "0.1.x" 3479 isstream "0.1.x"
3451 stack-trace "0.0.x" 3480 stack-trace "0.0.x"
3452 3481
3453wkx@0.2.0: 3482wkx@0.3.0:
3454 version "0.2.0" 3483 version "0.3.0"
3455 resolved "https://registry.yarnpkg.com/wkx/-/wkx-0.2.0.tgz#76c24f16acd0cd8f93cd34aa331e0f7961256e84" 3484 resolved "https://registry.yarnpkg.com/wkx/-/wkx-0.3.0.tgz#4f24948d879aca65e501674469855e04c2ad78dd"
3456 3485
3457wordwrap@~0.0.2: 3486wordwrap@~0.0.2:
3458 version "0.0.3" 3487 version "0.0.3"