diff options
Diffstat (limited to 'server/initializers')
-rw-r--r-- | server/initializers/checker.ts | 52 | ||||
-rw-r--r-- | server/initializers/database.ts | 99 | ||||
-rw-r--r-- | server/initializers/installer.ts | 75 | ||||
-rw-r--r-- | server/initializers/migrations/0005-email-pod.ts | 38 | ||||
-rw-r--r-- | server/initializers/migrations/0010-email-user.ts | 39 | ||||
-rw-r--r-- | server/initializers/migrations/0015-video-views.ts | 13 | ||||
-rw-r--r-- | server/initializers/migrations/0020-video-likes.ts | 13 | ||||
-rw-r--r-- | server/initializers/migrations/0025-video-dislikes.ts | 13 | ||||
-rw-r--r-- | server/initializers/migrations/0030-video-category.ts | 29 | ||||
-rw-r--r-- | server/initializers/migrations/0035-video-licence.ts | 30 | ||||
-rw-r--r-- | server/initializers/migrations/0040-video-nsfw.ts | 29 | ||||
-rw-r--r-- | server/initializers/migrations/0045-user-display-nsfw.ts | 13 | ||||
-rw-r--r-- | server/initializers/migrations/0050-video-language.ts | 13 | ||||
-rw-r--r-- | server/initializers/migrator.ts | 133 |
14 files changed, 262 insertions, 327 deletions
diff --git a/server/initializers/checker.ts b/server/initializers/checker.ts index 7007f2c0b..fb69e05fc 100644 --- a/server/initializers/checker.ts +++ b/server/initializers/checker.ts | |||
@@ -2,6 +2,7 @@ import * as config from 'config' | |||
2 | 2 | ||
3 | import { database as db } from './database' | 3 | import { database as db } from './database' |
4 | import { CONFIG } from './constants' | 4 | import { CONFIG } from './constants' |
5 | import { promisify0 } from '../helpers/core-utils' | ||
5 | 6 | ||
6 | // Some checks on configuration files | 7 | // Some checks on configuration files |
7 | function checkConfig () { | 8 | function checkConfig () { |
@@ -35,41 +36,36 @@ function checkMissedConfig () { | |||
35 | } | 36 | } |
36 | 37 | ||
37 | // Check the available codecs | 38 | // Check the available codecs |
38 | function checkFFmpeg (callback: (err: Error) => void) { | 39 | function checkFFmpeg () { |
39 | const Ffmpeg = require('fluent-ffmpeg') | 40 | const Ffmpeg = require('fluent-ffmpeg') |
40 | 41 | const getAvailableCodecsPromise = promisify0(Ffmpeg.getAvailableCodecs) | |
41 | Ffmpeg.getAvailableCodecs(function (err, codecs) { | 42 | |
42 | if (err) return callback(err) | 43 | getAvailableCodecsPromise() |
43 | if (CONFIG.TRANSCODING.ENABLED === false) return callback(null) | 44 | .then(codecs => { |
44 | 45 | if (CONFIG.TRANSCODING.ENABLED === false) return undefined | |
45 | const canEncode = [ 'libx264' ] | 46 | |
46 | canEncode.forEach(function (codec) { | 47 | const canEncode = [ 'libx264' ] |
47 | if (codecs[codec] === undefined) { | 48 | canEncode.forEach(function (codec) { |
48 | return callback(new Error('Unknown codec ' + codec + ' in FFmpeg.')) | 49 | if (codecs[codec] === undefined) { |
49 | } | 50 | throw new Error('Unknown codec ' + codec + ' in FFmpeg.') |
50 | 51 | } | |
51 | if (codecs[codec].canEncode !== true) { | 52 | |
52 | return callback(new Error('Unavailable encode codec ' + codec + ' in FFmpeg')) | 53 | if (codecs[codec].canEncode !== true) { |
53 | } | 54 | throw new Error('Unavailable encode codec ' + codec + ' in FFmpeg') |
55 | } | ||
56 | }) | ||
54 | }) | 57 | }) |
55 | |||
56 | return callback(null) | ||
57 | }) | ||
58 | } | 58 | } |
59 | 59 | ||
60 | function clientsExist (callback: (err: Error, clientsExist?: boolean) => void) { | 60 | function clientsExist () { |
61 | db.OAuthClient.countTotal(function (err, totalClients) { | 61 | return db.OAuthClient.countTotal().then(totalClients => { |
62 | if (err) return callback(err) | 62 | return totalClients !== 0 |
63 | |||
64 | return callback(null, totalClients !== 0) | ||
65 | }) | 63 | }) |
66 | } | 64 | } |
67 | 65 | ||
68 | function usersExist (callback: (err: Error, usersExist?: boolean) => void) { | 66 | function usersExist () { |
69 | db.User.countTotal(function (err, totalUsers) { | 67 | return db.User.countTotal().then(totalUsers => { |
70 | if (err) return callback(err) | 68 | return totalUsers !== 0 |
71 | |||
72 | return callback(null, totalUsers !== 0) | ||
73 | }) | 69 | }) |
74 | } | 70 | } |
75 | 71 | ||
diff --git a/server/initializers/database.ts b/server/initializers/database.ts index 705dec6da..6e3a8d009 100644 --- a/server/initializers/database.ts +++ b/server/initializers/database.ts | |||
@@ -1,12 +1,12 @@ | |||
1 | import * as fs from 'fs' | ||
2 | import { join } from 'path' | 1 | import { join } from 'path' |
2 | import { flattenDepth } from 'lodash' | ||
3 | import * as Sequelize from 'sequelize' | 3 | import * as Sequelize from 'sequelize' |
4 | import { each } from 'async' | 4 | import * as Promise from 'bluebird' |
5 | 5 | ||
6 | import { CONFIG } from './constants' | 6 | import { CONFIG } from './constants' |
7 | // Do not use barrel, we need to load database first | 7 | // Do not use barrel, we need to load database first |
8 | import { logger } from '../helpers/logger' | 8 | import { logger } from '../helpers/logger' |
9 | import { isTestInstance } from '../helpers/core-utils' | 9 | import { isTestInstance, readdirPromise } from '../helpers/core-utils' |
10 | import { | 10 | import { |
11 | ApplicationModel, | 11 | ApplicationModel, |
12 | AuthorModel, | 12 | AuthorModel, |
@@ -33,7 +33,7 @@ const password = CONFIG.DATABASE.PASSWORD | |||
33 | 33 | ||
34 | const database: { | 34 | const database: { |
35 | sequelize?: Sequelize.Sequelize, | 35 | sequelize?: Sequelize.Sequelize, |
36 | init?: (silent: any, callback: any) => void, | 36 | init?: (silent: boolean) => Promise<void>, |
37 | 37 | ||
38 | Application?: ApplicationModel, | 38 | Application?: ApplicationModel, |
39 | Author?: AuthorModel, | 39 | Author?: AuthorModel, |
@@ -72,19 +72,17 @@ const sequelize = new Sequelize(dbname, username, password, { | |||
72 | 72 | ||
73 | database.sequelize = sequelize | 73 | database.sequelize = sequelize |
74 | 74 | ||
75 | database.init = function (silent: boolean, callback: (err: Error) => void) { | 75 | database.init = function (silent: boolean) { |
76 | const modelDirectory = join(__dirname, '..', 'models') | 76 | const modelDirectory = join(__dirname, '..', 'models') |
77 | 77 | ||
78 | getModelFiles(modelDirectory, function (err, filePaths) { | 78 | return getModelFiles(modelDirectory).then(filePaths => { |
79 | if (err) throw err | 79 | filePaths.forEach(filePath => { |
80 | |||
81 | filePaths.forEach(function (filePath) { | ||
82 | const model = sequelize.import(filePath) | 80 | const model = sequelize.import(filePath) |
83 | 81 | ||
84 | database[model['name']] = model | 82 | database[model['name']] = model |
85 | }) | 83 | }) |
86 | 84 | ||
87 | Object.keys(database).forEach(function (modelName) { | 85 | Object.keys(database).forEach(modelName => { |
88 | if ('associate' in database[modelName]) { | 86 | if ('associate' in database[modelName]) { |
89 | database[modelName].associate(database) | 87 | database[modelName].associate(database) |
90 | } | 88 | } |
@@ -92,7 +90,7 @@ database.init = function (silent: boolean, callback: (err: Error) => void) { | |||
92 | 90 | ||
93 | if (!silent) logger.info('Database %s is ready.', dbname) | 91 | if (!silent) logger.info('Database %s is ready.', dbname) |
94 | 92 | ||
95 | return callback(null) | 93 | return undefined |
96 | }) | 94 | }) |
97 | } | 95 | } |
98 | 96 | ||
@@ -104,49 +102,50 @@ export { | |||
104 | 102 | ||
105 | // --------------------------------------------------------------------------- | 103 | // --------------------------------------------------------------------------- |
106 | 104 | ||
107 | function getModelFiles (modelDirectory: string, callback: (err: Error, filePaths: string[]) => void) { | 105 | function getModelFiles (modelDirectory: string) { |
108 | fs.readdir(modelDirectory, function (err, files) { | 106 | return readdirPromise(modelDirectory) |
109 | if (err) throw err | 107 | .then(files => { |
110 | 108 | const directories: string[] = files.filter(function (directory) { | |
111 | const directories = files.filter(function (directory) { | 109 | // Find directories |
112 | // Find directories | 110 | if ( |
113 | if ( | 111 | directory.endsWith('.js.map') || |
114 | directory.endsWith('.js.map') || | 112 | directory === 'index.js' || directory === 'index.ts' || |
115 | directory === 'index.js' || directory === 'index.ts' || | 113 | directory === 'utils.js' || directory === 'utils.ts' |
116 | directory === 'utils.js' || directory === 'utils.ts' | 114 | ) return false |
117 | ) return false | 115 | |
116 | return true | ||
117 | }) | ||
118 | 118 | ||
119 | return true | 119 | return directories |
120 | }) | 120 | }) |
121 | 121 | .then(directories => { | |
122 | let modelFilePaths: string[] = [] | 122 | const tasks = [] |
123 | 123 | ||
124 | // For each directory we read it and append model in the modelFilePaths array | 124 | // For each directory we read it and append model in the modelFilePaths array |
125 | each(directories, function (directory: string, eachCallback: ErrorCallback<Error>) { | 125 | directories.forEach(directory => { |
126 | const modelDirectoryPath = join(modelDirectory, directory) | 126 | const modelDirectoryPath = join(modelDirectory, directory) |
127 | 127 | ||
128 | fs.readdir(modelDirectoryPath, function (err, files) { | 128 | const promise = readdirPromise(modelDirectoryPath).then(files => { |
129 | if (err) return eachCallback(err) | 129 | const filteredFiles = files.filter(file => { |
130 | 130 | if ( | |
131 | const filteredFiles = files.filter(file => { | 131 | file === 'index.js' || file === 'index.ts' || |
132 | if ( | 132 | file === 'utils.js' || file === 'utils.ts' || |
133 | file === 'index.js' || file === 'index.ts' || | 133 | file.endsWith('-interface.js') || file.endsWith('-interface.ts') || |
134 | file === 'utils.js' || file === 'utils.ts' || | 134 | file.endsWith('.js.map') |
135 | file.endsWith('-interface.js') || file.endsWith('-interface.ts') || | 135 | ) return false |
136 | file.endsWith('.js.map') | 136 | |
137 | ) return false | 137 | return true |
138 | 138 | }).map(file => join(modelDirectoryPath, file)) | |
139 | return true | 139 | |
140 | }).map(file => { | 140 | return filteredFiles |
141 | return join(modelDirectoryPath, file) | ||
142 | }) | 141 | }) |
143 | 142 | ||
144 | modelFilePaths = modelFilePaths.concat(filteredFiles) | 143 | tasks.push(promise) |
145 | |||
146 | return eachCallback(null) | ||
147 | }) | 144 | }) |
148 | }, function (err: Error) { | 145 | |
149 | return callback(err, modelFilePaths) | 146 | return Promise.all(tasks) |
147 | }) | ||
148 | .then((filteredFiles: string[][]) => { | ||
149 | return flattenDepth<string>(filteredFiles, 1) | ||
150 | }) | 150 | }) |
151 | }) | ||
152 | } | 151 | } |
diff --git a/server/initializers/installer.ts b/server/initializers/installer.ts index f105c8292..1ec24c4ad 100644 --- a/server/initializers/installer.ts +++ b/server/initializers/installer.ts | |||
@@ -1,37 +1,19 @@ | |||
1 | import { join } from 'path' | 1 | import { join } from 'path' |
2 | import * as config from 'config' | 2 | import * as config from 'config' |
3 | import { each, series } from 'async' | ||
4 | import * as mkdirp from 'mkdirp' | ||
5 | import * as passwordGenerator from 'password-generator' | 3 | import * as passwordGenerator from 'password-generator' |
4 | import * as Promise from 'bluebird' | ||
6 | 5 | ||
7 | import { database as db } from './database' | 6 | import { database as db } from './database' |
8 | import { USER_ROLES, CONFIG, LAST_MIGRATION_VERSION } from './constants' | 7 | import { USER_ROLES, CONFIG, LAST_MIGRATION_VERSION } from './constants' |
9 | import { clientsExist, usersExist } from './checker' | 8 | import { clientsExist, usersExist } from './checker' |
10 | import { logger, createCertsIfNotExist, root } from '../helpers' | 9 | import { logger, createCertsIfNotExist, root, mkdirpPromise } from '../helpers' |
11 | 10 | ||
12 | function installApplication (callback: (err: Error) => void) { | 11 | function installApplication () { |
13 | series([ | 12 | return db.sequelize.sync() |
14 | function createDatabase (callbackAsync) { | 13 | .then(() => createDirectoriesIfNotExist()) |
15 | db.sequelize.sync().asCallback(callbackAsync) | 14 | .then(() => createCertsIfNotExist()) |
16 | // db.sequelize.sync({ force: true }).asCallback(callbackAsync) | 15 | .then(() => createOAuthClientIfNotExist()) |
17 | }, | 16 | .then(() => createOAuthAdminIfNotExist()) |
18 | |||
19 | function createDirectories (callbackAsync) { | ||
20 | createDirectoriesIfNotExist(callbackAsync) | ||
21 | }, | ||
22 | |||
23 | function createCertificates (callbackAsync) { | ||
24 | createCertsIfNotExist(callbackAsync) | ||
25 | }, | ||
26 | |||
27 | function createOAuthClient (callbackAsync) { | ||
28 | createOAuthClientIfNotExist(callbackAsync) | ||
29 | }, | ||
30 | |||
31 | function createOAuthUser (callbackAsync) { | ||
32 | createOAuthAdminIfNotExist(callbackAsync) | ||
33 | } | ||
34 | ], callback) | ||
35 | } | 17 | } |
36 | 18 | ||
37 | // --------------------------------------------------------------------------- | 19 | // --------------------------------------------------------------------------- |
@@ -42,21 +24,22 @@ export { | |||
42 | 24 | ||
43 | // --------------------------------------------------------------------------- | 25 | // --------------------------------------------------------------------------- |
44 | 26 | ||
45 | function createDirectoriesIfNotExist (callback: (err: Error) => void) { | 27 | function createDirectoriesIfNotExist () { |
46 | const storages = config.get('storage') | 28 | const storages = config.get('storage') |
47 | 29 | ||
48 | each(Object.keys(storages), function (key, callbackEach) { | 30 | const tasks = [] |
31 | Object.keys(storages).forEach(key => { | ||
49 | const dir = storages[key] | 32 | const dir = storages[key] |
50 | mkdirp(join(root(), dir), callbackEach) | 33 | tasks.push(mkdirpPromise(join(root(), dir))) |
51 | }, callback) | 34 | }) |
52 | } | ||
53 | 35 | ||
54 | function createOAuthClientIfNotExist (callback: (err: Error) => void) { | 36 | return Promise.all(tasks) |
55 | clientsExist(function (err, exist) { | 37 | } |
56 | if (err) return callback(err) | ||
57 | 38 | ||
39 | function createOAuthClientIfNotExist () { | ||
40 | return clientsExist().then(exist => { | ||
58 | // Nothing to do, clients already exist | 41 | // Nothing to do, clients already exist |
59 | if (exist === true) return callback(null) | 42 | if (exist === true) return undefined |
60 | 43 | ||
61 | logger.info('Creating a default OAuth Client.') | 44 | logger.info('Creating a default OAuth Client.') |
62 | 45 | ||
@@ -69,23 +52,19 @@ function createOAuthClientIfNotExist (callback: (err: Error) => void) { | |||
69 | redirectUris: null | 52 | redirectUris: null |
70 | }) | 53 | }) |
71 | 54 | ||
72 | client.save().asCallback(function (err, createdClient) { | 55 | return client.save().then(createdClient => { |
73 | if (err) return callback(err) | ||
74 | |||
75 | logger.info('Client id: ' + createdClient.clientId) | 56 | logger.info('Client id: ' + createdClient.clientId) |
76 | logger.info('Client secret: ' + createdClient.clientSecret) | 57 | logger.info('Client secret: ' + createdClient.clientSecret) |
77 | 58 | ||
78 | return callback(null) | 59 | return undefined |
79 | }) | 60 | }) |
80 | }) | 61 | }) |
81 | } | 62 | } |
82 | 63 | ||
83 | function createOAuthAdminIfNotExist (callback: (err: Error) => void) { | 64 | function createOAuthAdminIfNotExist () { |
84 | usersExist(function (err, exist) { | 65 | return usersExist().then(exist => { |
85 | if (err) return callback(err) | ||
86 | |||
87 | // Nothing to do, users already exist | 66 | // Nothing to do, users already exist |
88 | if (exist === true) return callback(null) | 67 | if (exist === true) return undefined |
89 | 68 | ||
90 | logger.info('Creating the administrator.') | 69 | logger.info('Creating the administrator.') |
91 | 70 | ||
@@ -116,14 +95,12 @@ function createOAuthAdminIfNotExist (callback: (err: Error) => void) { | |||
116 | role | 95 | role |
117 | } | 96 | } |
118 | 97 | ||
119 | db.User.create(userData, createOptions).asCallback(function (err, createdUser) { | 98 | return db.User.create(userData, createOptions).then(createdUser => { |
120 | if (err) return callback(err) | ||
121 | |||
122 | logger.info('Username: ' + username) | 99 | logger.info('Username: ' + username) |
123 | logger.info('User password: ' + password) | 100 | logger.info('User password: ' + password) |
124 | 101 | ||
125 | logger.info('Creating Application table.') | 102 | logger.info('Creating Application table.') |
126 | db.Application.create({ migrationVersion: LAST_MIGRATION_VERSION }).asCallback(callback) | 103 | return db.Application.create({ migrationVersion: LAST_MIGRATION_VERSION }) |
127 | }) | 104 | }) |
128 | }) | 105 | }) |
129 | } | 106 | } |
diff --git a/server/initializers/migrations/0005-email-pod.ts b/server/initializers/migrations/0005-email-pod.ts index a9200c47f..ceefaad4a 100644 --- a/server/initializers/migrations/0005-email-pod.ts +++ b/server/initializers/migrations/0005-email-pod.ts | |||
@@ -1,9 +1,12 @@ | |||
1 | import { waterfall } from 'async' | 1 | import * as Sequelize from 'sequelize' |
2 | 2 | import * as Promise from 'bluebird' | |
3 | // utils = { transaction, queryInterface, sequelize, Sequelize } | 3 | |
4 | function up (utils, finalCallback) { | 4 | function up (utils: { |
5 | transaction: Sequelize.Transaction, | ||
6 | queryInterface: Sequelize.QueryInterface, | ||
7 | sequelize: Sequelize.Sequelize | ||
8 | }): Promise<void> { | ||
5 | const q = utils.queryInterface | 9 | const q = utils.queryInterface |
6 | const Sequelize = utils.Sequelize | ||
7 | 10 | ||
8 | const data = { | 11 | const data = { |
9 | type: Sequelize.STRING(400), | 12 | type: Sequelize.STRING(400), |
@@ -11,27 +14,16 @@ function up (utils, finalCallback) { | |||
11 | defaultValue: '' | 14 | defaultValue: '' |
12 | } | 15 | } |
13 | 16 | ||
14 | waterfall([ | 17 | return q.addColumn('Pods', 'email', data) |
15 | 18 | .then(() => { | |
16 | function addEmailColumn (callback) { | ||
17 | q.addColumn('Pods', 'email', data, { transaction: utils.transaction }).asCallback(function (err) { | ||
18 | return callback(err) | ||
19 | }) | ||
20 | }, | ||
21 | |||
22 | function updateWithFakeEmails (callback) { | ||
23 | const query = 'UPDATE "Pods" SET "email" = \'dummy@example.com\'' | 19 | const query = 'UPDATE "Pods" SET "email" = \'dummy@example.com\'' |
24 | utils.sequelize.query(query, { transaction: utils.transaction }).asCallback(function (err) { | 20 | return utils.sequelize.query(query, { transaction: utils.transaction }) |
25 | return callback(err) | 21 | }) |
26 | }) | 22 | .then(() => { |
27 | }, | ||
28 | |||
29 | function nullOnDefault (callback) { | ||
30 | data.defaultValue = null | 23 | data.defaultValue = null |
31 | 24 | ||
32 | q.changeColumn('Pods', 'email', data, { transaction: utils.transaction }).asCallback(callback) | 25 | return q.changeColumn('Pods', 'email', data) |
33 | } | 26 | }) |
34 | ], finalCallback) | ||
35 | } | 27 | } |
36 | 28 | ||
37 | function down (options, callback) { | 29 | function down (options, callback) { |
diff --git a/server/initializers/migrations/0010-email-user.ts b/server/initializers/migrations/0010-email-user.ts index 4b5d29394..e8865acdb 100644 --- a/server/initializers/migrations/0010-email-user.ts +++ b/server/initializers/migrations/0010-email-user.ts | |||
@@ -1,37 +1,28 @@ | |||
1 | import { waterfall } from 'async' | 1 | import * as Sequelize from 'sequelize' |
2 | 2 | import * as Promise from 'bluebird' | |
3 | // utils = { transaction, queryInterface, sequelize, Sequelize } | 3 | |
4 | function up (utils, finalCallback) { | 4 | function up (utils: { |
5 | transaction: Sequelize.Transaction, | ||
6 | queryInterface: Sequelize.QueryInterface, | ||
7 | sequelize: Sequelize.Sequelize | ||
8 | }): Promise<void> { | ||
5 | const q = utils.queryInterface | 9 | const q = utils.queryInterface |
6 | const Sequelize = utils.Sequelize | ||
7 | 10 | ||
8 | const data = { | 11 | const data = { |
9 | type: Sequelize.STRING(400), | 12 | type: Sequelize.STRING(400), |
10 | allowNull: false, | 13 | allowNull: false, |
11 | defaultValue: '' | 14 | defaultValue: '' |
12 | } | 15 | } |
13 | 16 | return q.addColumn('Users', 'email', data) | |
14 | waterfall([ | 17 | .then(() => { |
15 | |||
16 | function addEmailColumn (callback) { | ||
17 | q.addColumn('Users', 'email', data, { transaction: utils.transaction }).asCallback(function (err) { | ||
18 | return callback(err) | ||
19 | }) | ||
20 | }, | ||
21 | |||
22 | function updateWithFakeEmails (callback) { | ||
23 | const query = 'UPDATE "Users" SET "email" = CONCAT("username", \'@example.com\')' | 18 | const query = 'UPDATE "Users" SET "email" = CONCAT("username", \'@example.com\')' |
24 | utils.sequelize.query(query, { transaction: utils.transaction }).asCallback(function (err) { | 19 | return utils.sequelize.query(query, { transaction: utils.transaction }) |
25 | return callback(err) | 20 | }) |
26 | }) | 21 | .then(() => { |
27 | }, | ||
28 | |||
29 | function nullOnDefault (callback) { | ||
30 | data.defaultValue = null | 22 | data.defaultValue = null |
31 | 23 | ||
32 | q.changeColumn('Users', 'email', data, { transaction: utils.transaction }).asCallback(callback) | 24 | return q.changeColumn('Users', 'email', data) |
33 | } | 25 | }) |
34 | ], finalCallback) | ||
35 | } | 26 | } |
36 | 27 | ||
37 | function down (options, callback) { | 28 | function down (options, callback) { |
diff --git a/server/initializers/migrations/0015-video-views.ts b/server/initializers/migrations/0015-video-views.ts index e70869404..df274d817 100644 --- a/server/initializers/migrations/0015-video-views.ts +++ b/server/initializers/migrations/0015-video-views.ts | |||
@@ -1,7 +1,12 @@ | |||
1 | // utils = { transaction, queryInterface, sequelize, Sequelize } | 1 | import * as Sequelize from 'sequelize' |
2 | function up (utils, finalCallback) { | 2 | import * as Promise from 'bluebird' |
3 | |||
4 | function up (utils: { | ||
5 | transaction: Sequelize.Transaction, | ||
6 | queryInterface: Sequelize.QueryInterface, | ||
7 | sequelize: Sequelize.Sequelize | ||
8 | }): Promise<void> { | ||
3 | const q = utils.queryInterface | 9 | const q = utils.queryInterface |
4 | const Sequelize = utils.Sequelize | ||
5 | 10 | ||
6 | const data = { | 11 | const data = { |
7 | type: Sequelize.INTEGER, | 12 | type: Sequelize.INTEGER, |
@@ -9,7 +14,7 @@ function up (utils, finalCallback) { | |||
9 | defaultValue: 0 | 14 | defaultValue: 0 |
10 | } | 15 | } |
11 | 16 | ||
12 | q.addColumn('Videos', 'views', data, { transaction: utils.transaction }).asCallback(finalCallback) | 17 | return q.addColumn('Videos', 'views', data) |
13 | } | 18 | } |
14 | 19 | ||
15 | function down (options, callback) { | 20 | function down (options, callback) { |
diff --git a/server/initializers/migrations/0020-video-likes.ts b/server/initializers/migrations/0020-video-likes.ts index e435d0657..3d7182d0a 100644 --- a/server/initializers/migrations/0020-video-likes.ts +++ b/server/initializers/migrations/0020-video-likes.ts | |||
@@ -1,7 +1,12 @@ | |||
1 | // utils = { transaction, queryInterface, sequelize, Sequelize } | 1 | import * as Sequelize from 'sequelize' |
2 | function up (utils, finalCallback) { | 2 | import * as Promise from 'bluebird' |
3 | |||
4 | function up (utils: { | ||
5 | transaction: Sequelize.Transaction, | ||
6 | queryInterface: Sequelize.QueryInterface, | ||
7 | sequelize: Sequelize.Sequelize | ||
8 | }): Promise<void> { | ||
3 | const q = utils.queryInterface | 9 | const q = utils.queryInterface |
4 | const Sequelize = utils.Sequelize | ||
5 | 10 | ||
6 | const data = { | 11 | const data = { |
7 | type: Sequelize.INTEGER, | 12 | type: Sequelize.INTEGER, |
@@ -9,7 +14,7 @@ function up (utils, finalCallback) { | |||
9 | defaultValue: 0 | 14 | defaultValue: 0 |
10 | } | 15 | } |
11 | 16 | ||
12 | q.addColumn('Videos', 'likes', data, { transaction: utils.transaction }).asCallback(finalCallback) | 17 | return q.addColumn('Videos', 'likes', data) |
13 | } | 18 | } |
14 | 19 | ||
15 | function down (options, callback) { | 20 | function down (options, callback) { |
diff --git a/server/initializers/migrations/0025-video-dislikes.ts b/server/initializers/migrations/0025-video-dislikes.ts index 57e54e904..ed41095dc 100644 --- a/server/initializers/migrations/0025-video-dislikes.ts +++ b/server/initializers/migrations/0025-video-dislikes.ts | |||
@@ -1,7 +1,12 @@ | |||
1 | // utils = { transaction, queryInterface, sequelize, Sequelize } | 1 | import * as Sequelize from 'sequelize' |
2 | function up (utils, finalCallback) { | 2 | import * as Promise from 'bluebird' |
3 | |||
4 | function up (utils: { | ||
5 | transaction: Sequelize.Transaction, | ||
6 | queryInterface: Sequelize.QueryInterface, | ||
7 | sequelize: Sequelize.Sequelize | ||
8 | }): Promise<void> { | ||
3 | const q = utils.queryInterface | 9 | const q = utils.queryInterface |
4 | const Sequelize = utils.Sequelize | ||
5 | 10 | ||
6 | const data = { | 11 | const data = { |
7 | type: Sequelize.INTEGER, | 12 | type: Sequelize.INTEGER, |
@@ -9,7 +14,7 @@ function up (utils, finalCallback) { | |||
9 | defaultValue: 0 | 14 | defaultValue: 0 |
10 | } | 15 | } |
11 | 16 | ||
12 | q.addColumn('Videos', 'dislikes', data, { transaction: utils.transaction }).asCallback(finalCallback) | 17 | return q.addColumn('Videos', 'dislikes', data) |
13 | } | 18 | } |
14 | 19 | ||
15 | function down (options, callback) { | 20 | function down (options, callback) { |
diff --git a/server/initializers/migrations/0030-video-category.ts b/server/initializers/migrations/0030-video-category.ts index 1073f449c..f5adee8f9 100644 --- a/server/initializers/migrations/0030-video-category.ts +++ b/server/initializers/migrations/0030-video-category.ts | |||
@@ -1,9 +1,12 @@ | |||
1 | import { waterfall } from 'async' | 1 | import * as Sequelize from 'sequelize' |
2 | 2 | import * as Promise from 'bluebird' | |
3 | // utils = { transaction, queryInterface, sequelize, Sequelize } | 3 | |
4 | function up (utils, finalCallback) { | 4 | function up (utils: { |
5 | transaction: Sequelize.Transaction, | ||
6 | queryInterface: Sequelize.QueryInterface, | ||
7 | sequelize: Sequelize.Sequelize | ||
8 | }): Promise<void> { | ||
5 | const q = utils.queryInterface | 9 | const q = utils.queryInterface |
6 | const Sequelize = utils.Sequelize | ||
7 | 10 | ||
8 | const data = { | 11 | const data = { |
9 | type: Sequelize.INTEGER, | 12 | type: Sequelize.INTEGER, |
@@ -11,20 +14,12 @@ function up (utils, finalCallback) { | |||
11 | defaultValue: 0 | 14 | defaultValue: 0 |
12 | } | 15 | } |
13 | 16 | ||
14 | waterfall([ | 17 | return q.addColumn('Videos', 'category', data) |
15 | 18 | .then(() => { | |
16 | function addCategoryColumn (callback) { | ||
17 | q.addColumn('Videos', 'category', data, { transaction: utils.transaction }).asCallback(function (err) { | ||
18 | return callback(err) | ||
19 | }) | ||
20 | }, | ||
21 | |||
22 | function nullOnDefault (callback) { | ||
23 | data.defaultValue = null | 19 | data.defaultValue = null |
24 | 20 | ||
25 | q.changeColumn('Videos', 'category', data, { transaction: utils.transaction }).asCallback(callback) | 21 | return q.changeColumn('Videos', 'category', data) |
26 | } | 22 | }) |
27 | ], finalCallback) | ||
28 | } | 23 | } |
29 | 24 | ||
30 | function down (options, callback) { | 25 | function down (options, callback) { |
diff --git a/server/initializers/migrations/0035-video-licence.ts b/server/initializers/migrations/0035-video-licence.ts index 9316b3c37..00c64d8e7 100644 --- a/server/initializers/migrations/0035-video-licence.ts +++ b/server/initializers/migrations/0035-video-licence.ts | |||
@@ -1,9 +1,12 @@ | |||
1 | import { waterfall } from 'async' | 1 | import * as Sequelize from 'sequelize' |
2 | 2 | import * as Promise from 'bluebird' | |
3 | // utils = { transaction, queryInterface, sequelize, Sequelize } | 3 | |
4 | function up (utils, finalCallback) { | 4 | function up (utils: { |
5 | transaction: Sequelize.Transaction, | ||
6 | queryInterface: Sequelize.QueryInterface, | ||
7 | sequelize: Sequelize.Sequelize | ||
8 | }): Promise<void> { | ||
5 | const q = utils.queryInterface | 9 | const q = utils.queryInterface |
6 | const Sequelize = utils.Sequelize | ||
7 | 10 | ||
8 | const data = { | 11 | const data = { |
9 | type: Sequelize.INTEGER, | 12 | type: Sequelize.INTEGER, |
@@ -11,20 +14,11 @@ function up (utils, finalCallback) { | |||
11 | defaultValue: 0 | 14 | defaultValue: 0 |
12 | } | 15 | } |
13 | 16 | ||
14 | waterfall([ | 17 | return q.addColumn('Videos', 'licence', data) |
15 | 18 | .then(() => { | |
16 | function addLicenceColumn (callback) { | ||
17 | q.addColumn('Videos', 'licence', data, { transaction: utils.transaction }).asCallback(function (err) { | ||
18 | return callback(err) | ||
19 | }) | ||
20 | }, | ||
21 | |||
22 | function nullOnDefault (callback) { | ||
23 | data.defaultValue = null | 19 | data.defaultValue = null |
24 | 20 | return q.changeColumn('Videos', 'licence', data) | |
25 | q.changeColumn('Videos', 'licence', data, { transaction: utils.transaction }).asCallback(callback) | 21 | }) |
26 | } | ||
27 | ], finalCallback) | ||
28 | } | 22 | } |
29 | 23 | ||
30 | function down (options, callback) { | 24 | function down (options, callback) { |
diff --git a/server/initializers/migrations/0040-video-nsfw.ts b/server/initializers/migrations/0040-video-nsfw.ts index c61f496f1..046876b61 100644 --- a/server/initializers/migrations/0040-video-nsfw.ts +++ b/server/initializers/migrations/0040-video-nsfw.ts | |||
@@ -1,9 +1,12 @@ | |||
1 | import { waterfall } from 'async' | 1 | import * as Sequelize from 'sequelize' |
2 | 2 | import * as Promise from 'bluebird' | |
3 | // utils = { transaction, queryInterface, sequelize, Sequelize } | 3 | |
4 | function up (utils, finalCallback) { | 4 | function up (utils: { |
5 | transaction: Sequelize.Transaction, | ||
6 | queryInterface: Sequelize.QueryInterface, | ||
7 | sequelize: Sequelize.Sequelize | ||
8 | }): Promise<void> { | ||
5 | const q = utils.queryInterface | 9 | const q = utils.queryInterface |
6 | const Sequelize = utils.Sequelize | ||
7 | 10 | ||
8 | const data = { | 11 | const data = { |
9 | type: Sequelize.BOOLEAN, | 12 | type: Sequelize.BOOLEAN, |
@@ -11,20 +14,12 @@ function up (utils, finalCallback) { | |||
11 | defaultValue: false | 14 | defaultValue: false |
12 | } | 15 | } |
13 | 16 | ||
14 | waterfall([ | 17 | return q.addColumn('Videos', 'nsfw', data) |
15 | 18 | .then(() => { | |
16 | function addNSFWColumn (callback) { | ||
17 | q.addColumn('Videos', 'nsfw', data, { transaction: utils.transaction }).asCallback(function (err) { | ||
18 | return callback(err) | ||
19 | }) | ||
20 | }, | ||
21 | |||
22 | function nullOnDefault (callback) { | ||
23 | data.defaultValue = null | 19 | data.defaultValue = null |
24 | 20 | ||
25 | q.changeColumn('Videos', 'nsfw', data, { transaction: utils.transaction }).asCallback(callback) | 21 | return q.changeColumn('Videos', 'nsfw', data) |
26 | } | 22 | }) |
27 | ], finalCallback) | ||
28 | } | 23 | } |
29 | 24 | ||
30 | function down (options, callback) { | 25 | function down (options, callback) { |
diff --git a/server/initializers/migrations/0045-user-display-nsfw.ts b/server/initializers/migrations/0045-user-display-nsfw.ts index 1ca317795..75bd3bbea 100644 --- a/server/initializers/migrations/0045-user-display-nsfw.ts +++ b/server/initializers/migrations/0045-user-display-nsfw.ts | |||
@@ -1,7 +1,12 @@ | |||
1 | // utils = { transaction, queryInterface, sequelize, Sequelize } | 1 | import * as Sequelize from 'sequelize' |
2 | function up (utils, finalCallback) { | 2 | import * as Promise from 'bluebird' |
3 | |||
4 | function up (utils: { | ||
5 | transaction: Sequelize.Transaction, | ||
6 | queryInterface: Sequelize.QueryInterface, | ||
7 | sequelize: Sequelize.Sequelize | ||
8 | }): Promise<void> { | ||
3 | const q = utils.queryInterface | 9 | const q = utils.queryInterface |
4 | const Sequelize = utils.Sequelize | ||
5 | 10 | ||
6 | const data = { | 11 | const data = { |
7 | type: Sequelize.BOOLEAN, | 12 | type: Sequelize.BOOLEAN, |
@@ -9,7 +14,7 @@ function up (utils, finalCallback) { | |||
9 | defaultValue: false | 14 | defaultValue: false |
10 | } | 15 | } |
11 | 16 | ||
12 | q.addColumn('Users', 'displayNSFW', data, { transaction: utils.transaction }).asCallback(finalCallback) | 17 | return q.addColumn('Users', 'displayNSFW', data) |
13 | } | 18 | } |
14 | 19 | ||
15 | function down (options, callback) { | 20 | function down (options, callback) { |
diff --git a/server/initializers/migrations/0050-video-language.ts b/server/initializers/migrations/0050-video-language.ts index 95d0a473a..ed08f5866 100644 --- a/server/initializers/migrations/0050-video-language.ts +++ b/server/initializers/migrations/0050-video-language.ts | |||
@@ -1,7 +1,12 @@ | |||
1 | // utils = { transaction, queryInterface, sequelize, Sequelize } | 1 | import * as Sequelize from 'sequelize' |
2 | function up (utils, finalCallback) { | 2 | import * as Promise from 'bluebird' |
3 | |||
4 | function up (utils: { | ||
5 | transaction: Sequelize.Transaction, | ||
6 | queryInterface: Sequelize.QueryInterface, | ||
7 | sequelize: Sequelize.Sequelize | ||
8 | }): Promise<void> { | ||
3 | const q = utils.queryInterface | 9 | const q = utils.queryInterface |
4 | const Sequelize = utils.Sequelize | ||
5 | 10 | ||
6 | const data = { | 11 | const data = { |
7 | type: Sequelize.INTEGER, | 12 | type: Sequelize.INTEGER, |
@@ -9,7 +14,7 @@ function up (utils, finalCallback) { | |||
9 | defaultValue: null | 14 | defaultValue: null |
10 | } | 15 | } |
11 | 16 | ||
12 | q.addColumn('Videos', 'language', data, { transaction: utils.transaction }).asCallback(finalCallback) | 17 | return q.addColumn('Videos', 'language', data) |
13 | } | 18 | } |
14 | 19 | ||
15 | function down (options, callback) { | 20 | function down (options, callback) { |
diff --git a/server/initializers/migrator.ts b/server/initializers/migrator.ts index d8faaebc6..d381551b5 100644 --- a/server/initializers/migrator.ts +++ b/server/initializers/migrator.ts | |||
@@ -1,70 +1,54 @@ | |||
1 | import { waterfall, eachSeries } from 'async' | ||
2 | import * as fs from 'fs' | ||
3 | import * as path from 'path' | 1 | import * as path from 'path' |
4 | import * as Sequelize from 'sequelize' | 2 | import * as Promise from 'bluebird' |
5 | 3 | ||
6 | import { database as db } from './database' | 4 | import { database as db } from './database' |
7 | import { LAST_MIGRATION_VERSION } from './constants' | 5 | import { LAST_MIGRATION_VERSION } from './constants' |
8 | import { logger } from '../helpers' | 6 | import { logger, readdirPromise } from '../helpers' |
9 | 7 | ||
10 | function migrate (finalCallback: (err: Error) => void) { | 8 | function migrate () { |
11 | waterfall([ | 9 | const p = db.sequelize.getQueryInterface().showAllTables() |
12 | 10 | .then(tables => { | |
13 | function checkApplicationTableExists (callback) { | 11 | // No tables, we don't need to migrate anything |
14 | db.sequelize.getQueryInterface().showAllTables().asCallback(function (err, tables) { | 12 | // The installer will do that |
15 | if (err) return callback(err) | 13 | if (tables.length === 0) throw null |
16 | 14 | }) | |
17 | // No tables, we don't need to migrate anything | 15 | .then(() => { |
18 | // The installer will do that | 16 | return db.Application.loadMigrationVersion() |
19 | if (tables.length === 0) return finalCallback(null) | 17 | }) |
20 | 18 | .then(actualVersion => { | |
21 | return callback(null) | ||
22 | }) | ||
23 | }, | ||
24 | |||
25 | function loadMigrationVersion (callback) { | ||
26 | db.Application.loadMigrationVersion(callback) | ||
27 | }, | ||
28 | |||
29 | function createMigrationRowIfNotExists (actualVersion, callback) { | ||
30 | if (actualVersion === null) { | 19 | if (actualVersion === null) { |
31 | db.Application.create({ | 20 | return db.Application.create({ migrationVersion: 0 }).then(() => 0) |
32 | migrationVersion: 0 | ||
33 | }, function (err) { | ||
34 | return callback(err, 0) | ||
35 | }) | ||
36 | } | 21 | } |
37 | 22 | ||
38 | return callback(null, actualVersion) | 23 | return actualVersion |
39 | }, | 24 | }) |
40 | 25 | .then(actualVersion => { | |
41 | function abortMigrationIfNotNeeded (actualVersion, callback) { | 26 | // No need migrations, abort |
42 | // No need migrations | 27 | if (actualVersion >= LAST_MIGRATION_VERSION) throw null |
43 | if (actualVersion >= LAST_MIGRATION_VERSION) return finalCallback(null) | ||
44 | |||
45 | return callback(null, actualVersion) | ||
46 | }, | ||
47 | 28 | ||
48 | function getMigrations (actualVersion, callback) { | 29 | return actualVersion |
30 | }) | ||
31 | .then(actualVersion => { | ||
49 | // If there are a new migration scripts | 32 | // If there are a new migration scripts |
50 | logger.info('Begin migrations.') | 33 | logger.info('Begin migrations.') |
51 | 34 | ||
52 | getMigrationScripts(function (err, migrationScripts) { | 35 | return getMigrationScripts().then(migrationScripts => ({ actualVersion, migrationScripts })) |
53 | return callback(err, actualVersion, migrationScripts) | 36 | }) |
37 | .then(({ actualVersion, migrationScripts }) => { | ||
38 | return Promise.mapSeries(migrationScripts, entity => { | ||
39 | return executeMigration(actualVersion, entity) | ||
54 | }) | 40 | }) |
55 | }, | 41 | }) |
42 | .then(() => { | ||
43 | logger.info('Migrations finished. New migration version schema: %s', LAST_MIGRATION_VERSION) | ||
44 | }) | ||
45 | .catch(err => { | ||
46 | if (err === null) return undefined | ||
56 | 47 | ||
57 | function doMigrations (actualVersion, migrationScripts, callback) { | 48 | throw err |
58 | eachSeries(migrationScripts, function (entity: any, callbackEach) { | 49 | }) |
59 | executeMigration(actualVersion, entity, callbackEach) | ||
60 | }, function (err) { | ||
61 | if (err) return callback(err) | ||
62 | 50 | ||
63 | logger.info('Migrations finished. New migration version schema: %s', LAST_MIGRATION_VERSION) | 51 | return p |
64 | return callback(null) | ||
65 | }) | ||
66 | } | ||
67 | ], finalCallback) | ||
68 | } | 52 | } |
69 | 53 | ||
70 | // --------------------------------------------------------------------------- | 54 | // --------------------------------------------------------------------------- |
@@ -75,12 +59,12 @@ export { | |||
75 | 59 | ||
76 | // --------------------------------------------------------------------------- | 60 | // --------------------------------------------------------------------------- |
77 | 61 | ||
78 | type GetMigrationScriptsCallback = (err: Error, filesToMigrate?: { version: string, script: string }[]) => void | 62 | function getMigrationScripts () { |
79 | function getMigrationScripts (callback: GetMigrationScriptsCallback) { | 63 | return readdirPromise(path.join(__dirname, 'migrations')).then(files => { |
80 | fs.readdir(path.join(__dirname, 'migrations'), function (err, files) { | 64 | const filesToMigrate: { |
81 | if (err) return callback(err) | 65 | version: string, |
82 | 66 | script: string | |
83 | const filesToMigrate = [] | 67 | }[] = [] |
84 | 68 | ||
85 | files.forEach(function (file) { | 69 | files.forEach(function (file) { |
86 | // Filename is something like 'version-blabla.js' | 70 | // Filename is something like 'version-blabla.js' |
@@ -91,15 +75,15 @@ function getMigrationScripts (callback: GetMigrationScriptsCallback) { | |||
91 | }) | 75 | }) |
92 | }) | 76 | }) |
93 | 77 | ||
94 | return callback(err, filesToMigrate) | 78 | return filesToMigrate |
95 | }) | 79 | }) |
96 | } | 80 | } |
97 | 81 | ||
98 | function executeMigration (actualVersion: number, entity: { version: string, script: string }, callback: (err: Error) => void) { | 82 | function executeMigration (actualVersion: number, entity: { version: string, script: string }) { |
99 | const versionScript = parseInt(entity.version, 10) | 83 | const versionScript = parseInt(entity.version, 10) |
100 | 84 | ||
101 | // Do not execute old migration scripts | 85 | // Do not execute old migration scripts |
102 | if (versionScript <= actualVersion) return callback(null) | 86 | if (versionScript <= actualVersion) return undefined |
103 | 87 | ||
104 | // Load the migration module and run it | 88 | // Load the migration module and run it |
105 | const migrationScriptName = entity.script | 89 | const migrationScriptName = entity.script |
@@ -107,30 +91,17 @@ function executeMigration (actualVersion: number, entity: { version: string, scr | |||
107 | 91 | ||
108 | const migrationScript = require(path.join(__dirname, 'migrations', migrationScriptName)) | 92 | const migrationScript = require(path.join(__dirname, 'migrations', migrationScriptName)) |
109 | 93 | ||
110 | db.sequelize.transaction().asCallback(function (err, t) { | 94 | return db.sequelize.transaction(t => { |
111 | if (err) return callback(err) | ||
112 | |||
113 | const options = { | 95 | const options = { |
114 | transaction: t, | 96 | transaction: t, |
115 | queryInterface: db.sequelize.getQueryInterface(), | 97 | queryInterface: db.sequelize.getQueryInterface(), |
116 | sequelize: db.sequelize, | 98 | sequelize: db.sequelize |
117 | Sequelize: Sequelize | ||
118 | } | 99 | } |
119 | migrationScript.up(options, function (err) { | ||
120 | if (err) { | ||
121 | t.rollback() | ||
122 | return callback(err) | ||
123 | } | ||
124 | |||
125 | // Update the new migration version | ||
126 | db.Application.updateMigrationVersion(versionScript, t, function (err) { | ||
127 | if (err) { | ||
128 | t.rollback() | ||
129 | return callback(err) | ||
130 | } | ||
131 | 100 | ||
132 | t.commit().asCallback(callback) | 101 | migrationScript.up(options) |
102 | .then(() => { | ||
103 | // Update the new migration version | ||
104 | db.Application.updateMigrationVersion(versionScript, t) | ||
133 | }) | 105 | }) |
134 | }) | ||
135 | }) | 106 | }) |
136 | } | 107 | } |