X-Git-Url: https://git.immae.eu/?a=blobdiff_plain;f=server%2Finitializers%2Finstaller.ts;h=f48f348a7bc118a91937b774b7eb1ae4fc92ae46;hb=3a380e9a71037b0fcbace58a7599221e7cc76e20;hp=1ec24c4ade1555aeb1bb7da536906e76656669e3;hpb=6fcd19ba737f1f5614a56c6925adb882dea43b8d;p=github%2FChocobozzz%2FPeerTube.git diff --git a/server/initializers/installer.ts b/server/initializers/installer.ts index 1ec24c4ad..f48f348a7 100644 --- a/server/initializers/installer.ts +++ b/server/initializers/installer.ts @@ -1,19 +1,39 @@ +import { ensureDir, readdir, remove } from 'fs-extra' +import passwordGenerator from 'password-generator' import { join } from 'path' -import * as config from 'config' -import * as passwordGenerator from 'password-generator' -import * as Promise from 'bluebird' - -import { database as db } from './database' -import { USER_ROLES, CONFIG, LAST_MIGRATION_VERSION } from './constants' -import { clientsExist, usersExist } from './checker' -import { logger, createCertsIfNotExist, root, mkdirpPromise } from '../helpers' - -function installApplication () { - return db.sequelize.sync() - .then(() => createDirectoriesIfNotExist()) - .then(() => createCertsIfNotExist()) - .then(() => createOAuthClientIfNotExist()) - .then(() => createOAuthAdminIfNotExist()) +import { isTestOrDevInstance } from '@server/helpers/core-utils' +import { getNodeABIVersion } from '@server/helpers/version' +import { UserRole } from '@shared/models' +import { logger } from '../helpers/logger' +import { buildUser, createApplicationActor, createUserAccountAndChannelAndPlaylist } from '../lib/user' +import { ApplicationModel } from '../models/application/application' +import { OAuthClientModel } from '../models/oauth/oauth-client' +import { applicationExist, clientsExist, usersExist } from './checker-after-init' +import { CONFIG } from './config' +import { DIRECTORIES, FILES_CACHE, LAST_MIGRATION_VERSION } from './constants' +import { sequelizeTypescript } from './database' + +async function installApplication () { + try { + await Promise.all([ + // Database related + sequelizeTypescript.sync() + .then(() => { + return Promise.all([ + createApplicationIfNotExist(), + createOAuthClientIfNotExist(), + createOAuthAdminIfNotExist() + ]) + }), + + // Directories + removeCacheAndTmpDirectories() + .then(() => createDirectoriesIfNotExist()) + ]) + } catch (err) { + logger.error('Cannot install application.', { err }) + process.exit(-1) + } } // --------------------------------------------------------------------------- @@ -24,83 +44,142 @@ export { // --------------------------------------------------------------------------- -function createDirectoriesIfNotExist () { - const storages = config.get('storage') +function removeCacheAndTmpDirectories () { + const cacheDirectories = Object.keys(FILES_CACHE) + .map(k => FILES_CACHE[k].DIRECTORY) - const tasks = [] - Object.keys(storages).forEach(key => { - const dir = storages[key] - tasks.push(mkdirpPromise(join(root(), dir))) - }) + const tasks: Promise[] = [] + + // Cache directories + for (const dir of cacheDirectories) { + tasks.push(removeDirectoryOrContent(dir)) + } + + tasks.push(removeDirectoryOrContent(CONFIG.STORAGE.TMP_DIR)) return Promise.all(tasks) } -function createOAuthClientIfNotExist () { - return clientsExist().then(exist => { - // Nothing to do, clients already exist - if (exist === true) return undefined +async function removeDirectoryOrContent (dir: string) { + try { + await remove(dir) + } catch (err) { + logger.debug('Cannot remove directory %s. Removing content instead.', dir, { err }) - logger.info('Creating a default OAuth Client.') + const files = await readdir(dir) - const id = passwordGenerator(32, false, /[a-z0-9]/) - const secret = passwordGenerator(32, false, /[a-zA-Z0-9]/) - const client = db.OAuthClient.build({ - clientId: id, - clientSecret: secret, - grants: [ 'password', 'refresh_token' ], - redirectUris: null - }) + for (const file of files) { + await remove(join(dir, file)) + } + } +} - return client.save().then(createdClient => { - logger.info('Client id: ' + createdClient.clientId) - logger.info('Client secret: ' + createdClient.clientSecret) +function createDirectoriesIfNotExist () { + const storage = CONFIG.STORAGE + const cacheDirectories = Object.keys(FILES_CACHE) + .map(k => FILES_CACHE[k].DIRECTORY) - return undefined - }) - }) + const tasks: Promise[] = [] + for (const key of Object.keys(storage)) { + const dir = storage[key] + tasks.push(ensureDir(dir)) + } + + // Cache directories + for (const dir of cacheDirectories) { + tasks.push(ensureDir(dir)) + } + + tasks.push(ensureDir(DIRECTORIES.HLS_STREAMING_PLAYLIST.PRIVATE)) + tasks.push(ensureDir(DIRECTORIES.HLS_STREAMING_PLAYLIST.PUBLIC)) + tasks.push(ensureDir(DIRECTORIES.VIDEOS.PUBLIC)) + tasks.push(ensureDir(DIRECTORIES.VIDEOS.PRIVATE)) + + // Resumable upload directory + tasks.push(ensureDir(DIRECTORIES.RESUMABLE_UPLOAD)) + + return Promise.all(tasks) } -function createOAuthAdminIfNotExist () { - return usersExist().then(exist => { - // Nothing to do, users already exist - if (exist === true) return undefined +async function createOAuthClientIfNotExist () { + const exist = await clientsExist() + // Nothing to do, clients already exist + if (exist === true) return undefined - logger.info('Creating the administrator.') + logger.info('Creating a default OAuth Client.') - const username = 'root' - const role = USER_ROLES.ADMIN - const email = CONFIG.ADMIN.EMAIL - const createOptions: { validate?: boolean } = {} - let password = '' + const id = passwordGenerator(32, false, /[a-z0-9]/) + const secret = passwordGenerator(32, false, /[a-zA-Z0-9]/) + const client = new OAuthClientModel({ + clientId: id, + clientSecret: secret, + grants: [ 'password', 'refresh_token' ], + redirectUris: null + }) - // Do not generate a random password for tests - if (process.env.NODE_ENV === 'test') { - password = 'test' + const createdClient = await client.save() + logger.info('Client id: ' + createdClient.clientId) + logger.info('Client secret: ' + createdClient.clientSecret) - if (process.env.NODE_APP_INSTANCE) { - password += process.env.NODE_APP_INSTANCE - } + return undefined +} - // Our password is weak so do not validate it - createOptions.validate = false - } else { - password = passwordGenerator(8, true) - } +async function createOAuthAdminIfNotExist () { + const exist = await usersExist() + // Nothing to do, users already exist + if (exist === true) return undefined + + logger.info('Creating the administrator.') + + const username = 'root' + const role = UserRole.ADMINISTRATOR + const email = CONFIG.ADMIN.EMAIL + let validatePassword = true + let password = '' + + // Do not generate a random password for test and dev environments + if (isTestOrDevInstance()) { + password = 'test' - const userData = { - username, - email, - password, - role + if (process.env.NODE_APP_INSTANCE) { + password += process.env.NODE_APP_INSTANCE } - return db.User.create(userData, createOptions).then(createdUser => { - logger.info('Username: ' + username) - logger.info('User password: ' + password) + // Our password is weak so do not validate it + validatePassword = false + } else if (process.env.PT_INITIAL_ROOT_PASSWORD) { + password = process.env.PT_INITIAL_ROOT_PASSWORD + } else { + password = passwordGenerator(16, true) + } + + const user = buildUser({ + username, + email, + password, + role, + emailVerified: true, + videoQuota: -1, + videoQuotaDaily: -1 + }) + + await createUserAccountAndChannelAndPlaylist({ userToCreate: user, channelNames: undefined, validateUser: validatePassword }) + logger.info('Username: ' + username) + logger.info('User password: ' + password) +} - logger.info('Creating Application table.') - return db.Application.create({ migrationVersion: LAST_MIGRATION_VERSION }) - }) +async function createApplicationIfNotExist () { + const exist = await applicationExist() + // Nothing to do, application already exist + if (exist === true) return undefined + + logger.info('Creating application account.') + + const application = await ApplicationModel.create({ + migrationVersion: LAST_MIGRATION_VERSION, + nodeVersion: process.version, + nodeABIVersion: getNodeABIVersion() }) + + return createApplicationActor(application.id) }