diff --git a/scripts/danger/clean/cleaner.ts b/scripts/danger/clean/cleaner.ts index d80b8d323..428333528 100644 --- a/scripts/danger/clean/cleaner.ts +++ b/scripts/danger/clean/cleaner.ts @@ -16,7 +16,7 @@ db.init(true) const storageDir = STORAGE[storage] return new Promise((res, rej) => { - rimraf(storageDir, function (err) { + rimraf(storageDir, err => { if (err) return rej(err) console.info('%s deleted.', storageDir) diff --git a/scripts/reset-password.ts b/scripts/reset-password.ts index 5ab7d01e5..f0c06a7bf 100755 --- a/scripts/reset-password.ts +++ b/scripts/reset-password.ts @@ -18,7 +18,7 @@ db.init(true) .then(user => { if (!user) { console.error('User unknown.') - return + process.exit(-1) } const readline = require('readline') diff --git a/scripts/update-host.ts b/scripts/update-host.ts index 5e69e4172..06d84a658 100755 --- a/scripts/update-host.ts +++ b/scripts/update-host.ts @@ -1,8 +1,5 @@ -import { readFileSync, writeFileSync } from 'fs' -import { join } from 'path' -import * as parseTorrent from 'parse-torrent' +import * as Promise from 'bluebird' -import { CONFIG, STATIC_PATHS } from '../server/initializers/constants' import { database as db } from '../server/initializers/database' import { hasFriends } from '../server/lib/friends' @@ -20,11 +17,18 @@ db.init(true) return db.Video.list() }) .then(videos => { + const tasks: Promise[] = [] + videos.forEach(video => { + console.log('Updating video ' + video.uuid) + video.VideoFiles.forEach(file => { - video.createTorrentAndSetInfoHash(file) + tasks.push(video.createTorrentAndSetInfoHash(file)) }) }) + return Promise.all(tasks) + }) + .then(() => { process.exit(0) }) diff --git a/server/helpers/core-utils.ts b/server/helpers/core-utils.ts index f8dd45533..2ec7e6515 100644 --- a/server/helpers/core-utils.ts +++ b/server/helpers/core-utils.ts @@ -25,8 +25,15 @@ function isTestInstance () { } function root () { - // We are in /dist/helpers/utils.js - return join(__dirname, '..', '..', '..') + // We are in /helpers/utils.js + const paths = [ __dirname, '..', '..' ] + + // We are under /dist directory + if (process.mainModule.filename.endsWith('.ts') === false) { + paths.push('..') + } + + return join.apply(null, paths) } function promisify0 (func: (cb: (err: any, result: A) => void) => void): () => Promise { diff --git a/server/helpers/custom-validators/misc.ts b/server/helpers/custom-validators/misc.ts index f6bb02c8e..8d215a416 100644 --- a/server/helpers/custom-validators/misc.ts +++ b/server/helpers/custom-validators/misc.ts @@ -1,3 +1,5 @@ +import 'express-validator' + function exists (value: any) { return value !== undefined && value !== null } diff --git a/server/helpers/custom-validators/pods.ts b/server/helpers/custom-validators/pods.ts index f2ca520c0..844bfdf78 100644 --- a/server/helpers/custom-validators/pods.ts +++ b/server/helpers/custom-validators/pods.ts @@ -1,4 +1,5 @@ import * as validator from 'validator' +import 'express-validator' import { isArray, exists } from './misc' import { isTestInstance } from '../core-utils' diff --git a/server/helpers/custom-validators/remote/videos.ts b/server/helpers/custom-validators/remote/videos.ts index 49f76e909..e5c76f3ca 100644 --- a/server/helpers/custom-validators/remote/videos.ts +++ b/server/helpers/custom-validators/remote/videos.ts @@ -1,3 +1,4 @@ +import 'express-validator' import { has, values } from 'lodash' import { diff --git a/server/helpers/custom-validators/users.ts b/server/helpers/custom-validators/users.ts index 00061f9df..805437efa 100644 --- a/server/helpers/custom-validators/users.ts +++ b/server/helpers/custom-validators/users.ts @@ -1,5 +1,6 @@ import { values } from 'lodash' import * as validator from 'validator' +import 'express-validator' import { exists } from './misc' import { CONSTRAINTS_FIELDS, USER_ROLES } from '../../initializers' diff --git a/server/helpers/custom-validators/videos.ts b/server/helpers/custom-validators/videos.ts index 8b3a26644..1d27e47fc 100644 --- a/server/helpers/custom-validators/videos.ts +++ b/server/helpers/custom-validators/videos.ts @@ -1,5 +1,6 @@ import { values } from 'lodash' import * as validator from 'validator' +import 'express-validator' import 'multer' import { diff --git a/server/initializers/database.ts b/server/initializers/database.ts index d04c8db1b..d59fd3655 100644 --- a/server/initializers/database.ts +++ b/server/initializers/database.ts @@ -8,26 +8,25 @@ import { CONFIG } from './constants' // Do not use barrel, we need to load database first import { logger } from '../helpers/logger' import { isTestInstance, readdirPromise } from '../helpers/core-utils' -import { - ApplicationModel, - AuthorModel, - JobModel, - OAuthClientModel, - OAuthTokenModel, - PodModel, - RequestModel, - RequestToPodModel, - RequestVideoEventModel, - RequestVideoQaduModel, - TagModel, - UserModel, - UserVideoRateModel, - VideoAbuseModel, - BlacklistedVideoModel, - VideoFileModel, - VideoTagModel, - VideoModel -} from '../models' + +import { VideoModel } from './../models/video/video-interface' +import { VideoTagModel } from './../models/video/video-tag-interface' +import { BlacklistedVideoModel } from './../models/video/video-blacklist-interface' +import { VideoFileModel } from './../models/video/video-file-interface' +import { VideoAbuseModel } from './../models/video/video-abuse-interface' +import { UserModel } from './../models/user/user-interface' +import { UserVideoRateModel } from './../models/user/user-video-rate-interface' +import { TagModel } from './../models/video/tag-interface' +import { RequestModel } from './../models/request/request-interface' +import { RequestVideoQaduModel } from './../models/request/request-video-qadu-interface' +import { RequestVideoEventModel } from './../models/request/request-video-event-interface' +import { RequestToPodModel } from './../models/request/request-to-pod-interface' +import { PodModel } from './../models/pod/pod-interface' +import { OAuthTokenModel } from './../models/oauth/oauth-token-interface' +import { OAuthClientModel } from './../models/oauth/oauth-client-interface' +import { JobModel } from './../models/job/job-interface' +import { AuthorModel } from './../models/video/author-interface' +import { ApplicationModel } from './../models/application/application-interface' const dbname = CONFIG.DATABASE.DBNAME const username = CONFIG.DATABASE.USERNAME diff --git a/server/models/oauth/oauth-token-interface.ts b/server/models/oauth/oauth-token-interface.ts index 97af3c815..0c947bde8 100644 --- a/server/models/oauth/oauth-token-interface.ts +++ b/server/models/oauth/oauth-token-interface.ts @@ -1,7 +1,7 @@ import * as Sequelize from 'sequelize' import * as Promise from 'bluebird' -import { UserModel } from '../user' +import { UserModel } from '../user/user-interface' export type OAuthTokenInfo = { refreshToken: string diff --git a/server/models/request/request-interface.ts b/server/models/request/request-interface.ts index 7b0ee4df9..dae35651b 100644 --- a/server/models/request/request-interface.ts +++ b/server/models/request/request-interface.ts @@ -2,7 +2,7 @@ import * as Sequelize from 'sequelize' import * as Promise from 'bluebird' import { AbstractRequestClass } from './abstract-request-interface' -import { PodInstance, PodAttributes } from '../pod' +import { PodInstance, PodAttributes } from '../pod/pod-interface' import { RequestEndpoint } from '../../../shared/models/request-scheduler.model' export type RequestsGrouped = { diff --git a/server/models/request/request-video-event-interface.ts b/server/models/request/request-video-event-interface.ts index a5032e1b1..26cabe3ba 100644 --- a/server/models/request/request-video-event-interface.ts +++ b/server/models/request/request-video-event-interface.ts @@ -2,8 +2,8 @@ import * as Sequelize from 'sequelize' import * as Promise from 'bluebird' import { AbstractRequestClass, AbstractRequestToPodClass } from './abstract-request-interface' -import { VideoInstance } from '../video' -import { PodInstance } from '../pod' +import { VideoInstance } from '../video/video-interface' +import { PodInstance } from '../pod/pod-interface' import { RequestVideoEventType } from '../../../shared/models/request-scheduler.model' diff --git a/server/models/request/request-video-qadu-interface.ts b/server/models/request/request-video-qadu-interface.ts index 9a172a4d4..b7b7b1ecc 100644 --- a/server/models/request/request-video-qadu-interface.ts +++ b/server/models/request/request-video-qadu-interface.ts @@ -2,8 +2,8 @@ import * as Sequelize from 'sequelize' import * as Promise from 'bluebird' import { AbstractRequestClass, AbstractRequestToPodClass } from './abstract-request-interface' -import { VideoInstance } from '../video' -import { PodInstance } from '../pod' +import { VideoInstance } from '../video/video-interface' +import { PodInstance } from '../pod/pod-interface' import { RequestVideoQaduType } from '../../../shared/models/request-scheduler.model' diff --git a/server/models/video/author-interface.ts b/server/models/video/author-interface.ts index dbcb85b17..52a00a1d3 100644 --- a/server/models/video/author-interface.ts +++ b/server/models/video/author-interface.ts @@ -1,7 +1,7 @@ import * as Sequelize from 'sequelize' import * as Promise from 'bluebird' -import { PodInstance } from '../pod' +import { PodInstance } from '../pod/pod-interface' export namespace AuthorMethods { export type FindOrCreateAuthor = ( diff --git a/server/models/video/video-abuse-interface.ts b/server/models/video/video-abuse-interface.ts index abc82f7ac..978268926 100644 --- a/server/models/video/video-abuse-interface.ts +++ b/server/models/video/video-abuse-interface.ts @@ -1,7 +1,7 @@ import * as Sequelize from 'sequelize' import * as Promise from 'bluebird' -import { PodInstance } from '../pod' +import { PodInstance } from '../pod/pod-interface' import { ResultList } from '../../../shared' // Don't use barrel, import just what we need diff --git a/server/models/video/video.ts b/server/models/video/video.ts index 8c69fe189..1134525f0 100644 --- a/server/models/video/video.ts +++ b/server/models/video/video.ts @@ -378,6 +378,8 @@ createTorrentAndSetInfoHash = function (this: VideoInstance, videoFile: VideoFil return createTorrentPromise(this.getVideoFilePath(videoFile), options) .then(torrent => { const filePath = join(CONFIG.STORAGE.TORRENTS_DIR, this.getTorrentFileName(videoFile)) + logger.info('Creating torrent %s.', filePath) + return writeFilePromise(filePath, torrent).then(() => torrent) }) .then(torrent => { diff --git a/server/tests/cli/index.ts b/server/tests/cli/index.ts new file mode 100644 index 000000000..e5a19ff10 --- /dev/null +++ b/server/tests/cli/index.ts @@ -0,0 +1,2 @@ +// Order of the tests we want to execute +import './reset-password' diff --git a/server/tests/cli/reset-password.ts b/server/tests/cli/reset-password.ts new file mode 100644 index 000000000..bbf0b3d11 --- /dev/null +++ b/server/tests/cli/reset-password.ts @@ -0,0 +1,45 @@ +import 'mocha' + +import { + createUser, + execCLI, + flushTests, + getEnvCli, + killallServers, + login, + runServer, + ServerInfo, + setAccessTokensToServers +} from '../utils' + +describe('Test reset password scripts', function () { + let server: ServerInfo + + before(async function () { + this.timeout(30000) + + await flushTests() + server = await runServer(1) + await setAccessTokensToServers([ server ]) + + await createUser(server.url, server.accessToken, 'user_1', 'super password') + }) + + it('Should change the user password from CLI', async function () { + this.timeout(20000) + + const env = getEnvCli(server) + await execCLI(`echo coucou | ${env} npm run reset-password -- -u user_1`) + + await login(server.url, server.client, { username: 'user_1', password: 'coucou' }, 200) + }) + + after(async function () { + killallServers([ server ]) + + // Keep the logs if the test failed + if (this['ok']) { + await flushTests() + } + }) +}) diff --git a/server/tests/cli/update-host.ts b/server/tests/cli/update-host.ts new file mode 100644 index 000000000..af9703b32 --- /dev/null +++ b/server/tests/cli/update-host.ts @@ -0,0 +1,71 @@ +import 'mocha' +import * as chai from 'chai' +const expect = chai.expect + +import { + execCLI, + flushTests, + getEnvCli, + getVideosList, + killallServers, + parseTorrentVideo, + runServer, + ServerInfo, + setAccessTokensToServers, + uploadVideo +} from '../utils' + +describe('Test update host scripts', function () { + let server: ServerInfo + + before(async function () { + this.timeout(30000) + + await flushTests() + + const overrideConfig = { + webserver: { + port: 9256 + } + } + server = await runServer(1, overrideConfig) + await setAccessTokensToServers([ server ]) + + // Upload two videos for our needs + const videoAttributes = {} + await uploadVideo(server.url, server.accessToken, videoAttributes) + await uploadVideo(server.url, server.accessToken, videoAttributes) + }) + + it('Should update torrent hosts', async function () { + this.timeout(20000) + + killallServers([ server ]) + server = await runServer(1) + + const env = getEnvCli(server) + await execCLI(`${env} npm run update-host`) + + const res = await getVideosList(server.url) + const videos = res.body.data + + expect(videos[0].files[0].magnetUri).to.contain('localhost%3A9001%2Ftracker%2Fsocket') + expect(videos[0].files[0].magnetUri).to.contain('localhost%3A9001%2Fstatic%2Fwebseed%2F') + + expect(videos[1].files[0].magnetUri).to.contain('localhost%3A9001%2Ftracker%2Fsocket') + expect(videos[1].files[0].magnetUri).to.contain('localhost%3A9001%2Fstatic%2Fwebseed%2F') + + const torrent = await parseTorrentVideo(server, videos[0].uuid) + expect(torrent.announce[0]).to.equal('ws://localhost:9001/tracker/socket') + expect(torrent.urlList[0]).to.contain('http://localhost:9001/static/webseed') + }) + + after(async function () { + killallServers([ server ]) + + // Keep the logs if the test failed + if (this['ok']) { + await flushTests() + } + }) +}) diff --git a/server/tests/index.ts b/server/tests/index.ts index 26f0816b7..a7dd0d824 100644 --- a/server/tests/index.ts +++ b/server/tests/index.ts @@ -1,3 +1,4 @@ // Order of the tests we want to execute import './client' import './api/' +import './cli/' diff --git a/server/tests/utils/cli.ts b/server/tests/utils/cli.ts new file mode 100644 index 000000000..5f07a832e --- /dev/null +++ b/server/tests/utils/cli.ts @@ -0,0 +1,24 @@ +import { exec } from 'child_process' + +import { ServerInfo } from './servers' + +function getEnvCli (server?: ServerInfo) { + return `NODE_ENV=test NODE_APP_INSTANCE=${server.serverNumber}` +} + +async function execCLI (command: string) { + return new Promise((res, rej) => { + exec(command, (err, stdout, stderr) => { + if (err) return rej(err) + + return res(stdout) + }) + }) +} + +// --------------------------------------------------------------------------- + +export { + execCLI, + getEnvCli +} diff --git a/server/tests/utils/index.ts b/server/tests/utils/index.ts index 9077b0568..0fa28f2af 100644 --- a/server/tests/utils/index.ts +++ b/server/tests/utils/index.ts @@ -1,3 +1,4 @@ +export * from './cli' export * from './clients' export * from './config' export * from './login' diff --git a/server/tests/utils/servers.ts b/server/tests/utils/servers.ts index 272a8935e..88027f74e 100644 --- a/server/tests/utils/servers.ts +++ b/server/tests/utils/servers.ts @@ -5,6 +5,7 @@ interface ServerInfo { app: ChildProcess, url: string host: string + serverNumber: number client: { id: string, @@ -65,9 +66,10 @@ function flushTests () { }) } -function runServer (serverNumber: number) { +function runServer (serverNumber: number, configOverride?: Object) { const server: ServerInfo = { app: null, + serverNumber: serverNumber, url: `http://localhost:${9000 + serverNumber}`, host: `localhost:${9000 + serverNumber}`, client: { @@ -98,6 +100,11 @@ function runServer (serverNumber: number) { const env = Object.create(process.env) env['NODE_ENV'] = 'test' env['NODE_APP_INSTANCE'] = serverNumber.toString() + + if (configOverride !== undefined) { + env['NODE_CONFIG'] = JSON.stringify(configOverride) + } + const options = { silent: true, env: env, diff --git a/server/tests/utils/videos.ts b/server/tests/utils/videos.ts index 42b7dd05a..509a2430a 100644 --- a/server/tests/utils/videos.ts +++ b/server/tests/utils/videos.ts @@ -1,8 +1,11 @@ +import { readFile } from 'fs' import * as request from 'supertest' import { join, isAbsolute } from 'path' +import * as parseTorrent from 'parse-torrent' import { makeGetRequest } from './requests' import { readFilePromise } from './miscs' +import { ServerInfo } from './servers' type VideoAttributes = { name?: string @@ -232,6 +235,17 @@ function rateVideo (url: string, accessToken: string, id: number, rating: string .expect(specialStatus) } +function parseTorrentVideo (server: ServerInfo, videoUUID: string) { + return new Promise((res, rej) => { + const torrentPath = join(__dirname, '..', '..', '..', 'test' + server.serverNumber, 'torrents', videoUUID + '.torrent') + readFile(torrentPath, (err, data) => { + if (err) return rej(err) + + return res(parseTorrent(data)) + }) + }) +} + // --------------------------------------------------------------------------- export { @@ -250,5 +264,6 @@ export { testVideoImage, uploadVideo, updateVideo, - rateVideo + rateVideo, + parseTorrentVideo }