"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.installApplication = void 0;
const tslib_1 = require("tslib");
const fs_extra_1 = require("fs-extra");
const password_generator_1 = tslib_1.__importDefault(require("password-generator"));
const path_1 = require("path");
const core_utils_1 = require("../helpers/core-utils");
const version_1 = require("../helpers/version");
const logger_1 = require("../helpers/logger");
const user_1 = require("../lib/user");
const application_1 = require("../models/application/application");
const oauth_client_1 = require("../models/oauth/oauth-client");
const checker_after_init_1 = require("./checker-after-init");
const config_1 = require("./config");
const constants_1 = require("./constants");
const database_1 = require("./database");
function installApplication() {
    return tslib_1.__awaiter(this, void 0, void 0, function* () {
        try {
            yield Promise.all([
                database_1.sequelizeTypescript.sync()
                    .then(() => {
                    return Promise.all([
                        createApplicationIfNotExist(),
                        createOAuthClientIfNotExist(),
                        createOAuthAdminIfNotExist()
                    ]);
                }),
                removeCacheAndTmpDirectories()
                    .then(() => createDirectoriesIfNotExist())
            ]);
        }
        catch (err) {
            logger_1.logger.error('Cannot install application.', { err });
            process.exit(-1);
        }
    });
}
exports.installApplication = installApplication;
function removeCacheAndTmpDirectories() {
    const cacheDirectories = Object.keys(constants_1.FILES_CACHE)
        .map(k => constants_1.FILES_CACHE[k].DIRECTORY);
    const tasks = [];
    for (const key of Object.keys(cacheDirectories)) {
        const dir = cacheDirectories[key];
        tasks.push(removeDirectoryOrContent(dir));
    }
    tasks.push(removeDirectoryOrContent(config_1.CONFIG.STORAGE.TMP_DIR));
    return Promise.all(tasks);
}
function removeDirectoryOrContent(dir) {
    return tslib_1.__awaiter(this, void 0, void 0, function* () {
        try {
            yield (0, fs_extra_1.remove)(dir);
        }
        catch (err) {
            logger_1.logger.debug('Cannot remove directory %s. Removing content instead.', dir, { err });
            const files = yield (0, fs_extra_1.readdir)(dir);
            for (const file of files) {
                yield (0, fs_extra_1.remove)((0, path_1.join)(dir, file));
            }
        }
    });
}
function createDirectoriesIfNotExist() {
    const storage = config_1.CONFIG.STORAGE;
    const cacheDirectories = Object.keys(constants_1.FILES_CACHE)
        .map(k => constants_1.FILES_CACHE[k].DIRECTORY);
    const tasks = [];
    for (const key of Object.keys(storage)) {
        const dir = storage[key];
        tasks.push((0, fs_extra_1.ensureDir)(dir));
    }
    for (const key of Object.keys(cacheDirectories)) {
        const dir = cacheDirectories[key];
        tasks.push((0, fs_extra_1.ensureDir)(dir));
    }
    tasks.push((0, fs_extra_1.ensureDir)(constants_1.DIRECTORIES.HLS_STREAMING_PLAYLIST.PRIVATE));
    tasks.push((0, fs_extra_1.ensureDir)(constants_1.DIRECTORIES.HLS_STREAMING_PLAYLIST.PUBLIC));
    tasks.push((0, fs_extra_1.ensureDir)(constants_1.DIRECTORIES.VIDEOS.PUBLIC));
    tasks.push((0, fs_extra_1.ensureDir)(constants_1.DIRECTORIES.VIDEOS.PRIVATE));
    tasks.push((0, fs_extra_1.ensureDir)(constants_1.DIRECTORIES.RESUMABLE_UPLOAD));
    return Promise.all(tasks);
}
function createOAuthClientIfNotExist() {
    return tslib_1.__awaiter(this, void 0, void 0, function* () {
        const exist = yield (0, checker_after_init_1.clientsExist)();
        if (exist === true)
            return undefined;
        logger_1.logger.info('Creating a default OAuth Client.');
        const id = (0, password_generator_1.default)(32, false, /[a-z0-9]/);
        const secret = (0, password_generator_1.default)(32, false, /[a-zA-Z0-9]/);
        const client = new oauth_client_1.OAuthClientModel({
            clientId: id,
            clientSecret: secret,
            grants: ['password', 'refresh_token'],
            redirectUris: null
        });
        const createdClient = yield client.save();
        logger_1.logger.info('Client id: ' + createdClient.clientId);
        logger_1.logger.info('Client secret: ' + createdClient.clientSecret);
        return undefined;
    });
}
function createOAuthAdminIfNotExist() {
    return tslib_1.__awaiter(this, void 0, void 0, function* () {
        const exist = yield (0, checker_after_init_1.usersExist)();
        if (exist === true)
            return undefined;
        logger_1.logger.info('Creating the administrator.');
        const username = 'root';
        const role = 0;
        const email = config_1.CONFIG.ADMIN.EMAIL;
        let validatePassword = true;
        let password = '';
        if ((0, core_utils_1.isTestOrDevInstance)()) {
            password = 'test';
            if (process.env.NODE_APP_INSTANCE) {
                password += process.env.NODE_APP_INSTANCE;
            }
            validatePassword = false;
        }
        else if (process.env.PT_INITIAL_ROOT_PASSWORD) {
            password = process.env.PT_INITIAL_ROOT_PASSWORD;
        }
        else {
            password = (0, password_generator_1.default)(16, true);
        }
        const user = (0, user_1.buildUser)({
            username,
            email,
            password,
            role,
            emailVerified: true,
            videoQuota: -1,
            videoQuotaDaily: -1
        });
        yield (0, user_1.createUserAccountAndChannelAndPlaylist)({ userToCreate: user, channelNames: undefined, validateUser: validatePassword });
        logger_1.logger.info('Username: ' + username);
        logger_1.logger.info('User password: ' + password);
    });
}
function createApplicationIfNotExist() {
    return tslib_1.__awaiter(this, void 0, void 0, function* () {
        const exist = yield (0, checker_after_init_1.applicationExist)();
        if (exist === true)
            return undefined;
        logger_1.logger.info('Creating application account.');
        const application = yield application_1.ApplicationModel.create({
            migrationVersion: constants_1.LAST_MIGRATION_VERSION,
            nodeVersion: process.version,
            nodeABIVersion: (0, version_1.getNodeABIVersion)()
        });
        return (0, user_1.createApplicationActor)(application.id);
    });
}
//# sourceMappingURL=installer.js.map