"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ensureCanAccessPrivateVideoHLSFiles = exports.ensureCanAccessVideoPrivateWebTorrentFiles = void 0;
const tslib_1 = require("tslib");
const express_validator_1 = require("express-validator");
const lru_cache_1 = tslib_1.__importDefault(require("lru-cache"));
const path_1 = require("path");
const misc_1 = require("../../helpers/custom-validators/misc");
const logger_1 = require("../../helpers/logger");
const constants_1 = require("../../initializers/constants");
const video_1 = require("../../models/video/video");
const video_file_1 = require("../../models/video/video-file");
const shared_1 = require("./shared");
const staticFileTokenBypass = new lru_cache_1.default({
    max: constants_1.LRU_CACHE.STATIC_VIDEO_FILES_RIGHTS_CHECK.MAX_SIZE,
    ttl: constants_1.LRU_CACHE.STATIC_VIDEO_FILES_RIGHTS_CHECK.TTL
});
const ensureCanAccessVideoPrivateWebTorrentFiles = [
    (0, express_validator_1.query)('videoFileToken').optional().custom(misc_1.exists),
    (req, res, next) => tslib_1.__awaiter(void 0, void 0, void 0, function* () {
        if ((0, shared_1.areValidationErrors)(req, res))
            return;
        const token = extractTokenOrDie(req, res);
        if (!token)
            return;
        const cacheKey = token + '-' + req.originalUrl;
        if (staticFileTokenBypass.has(cacheKey)) {
            const { allowed, file, video } = staticFileTokenBypass.get(cacheKey);
            if (allowed === true) {
                res.locals.onlyVideo = video;
                res.locals.videoFile = file;
                return next();
            }
            return res.sendStatus(403);
        }
        const result = yield isWebTorrentAllowed(req, res);
        staticFileTokenBypass.set(cacheKey, result);
        if (result.allowed !== true)
            return;
        res.locals.onlyVideo = result.video;
        res.locals.videoFile = result.file;
        return next();
    })
];
exports.ensureCanAccessVideoPrivateWebTorrentFiles = ensureCanAccessVideoPrivateWebTorrentFiles;
const ensureCanAccessPrivateVideoHLSFiles = [
    (0, express_validator_1.query)('videoFileToken')
        .optional()
        .custom(misc_1.exists),
    (0, express_validator_1.query)('reinjectVideoFileToken')
        .optional()
        .customSanitizer(misc_1.toBooleanOrNull)
        .isBoolean().withMessage('Should be a valid reinjectVideoFileToken boolean'),
    (req, res, next) => tslib_1.__awaiter(void 0, void 0, void 0, function* () {
        if ((0, shared_1.areValidationErrors)(req, res))
            return;
        const videoUUID = (0, path_1.basename)((0, path_1.dirname)(req.originalUrl));
        if (!(0, misc_1.isUUIDValid)(videoUUID)) {
            logger_1.logger.debug('Path does not contain valid video UUID to serve static file %s', req.originalUrl);
            return res.sendStatus(403);
        }
        const token = extractTokenOrDie(req, res);
        if (!token)
            return;
        const cacheKey = token + '-' + videoUUID;
        if (staticFileTokenBypass.has(cacheKey)) {
            const { allowed, file, playlist, video } = staticFileTokenBypass.get(cacheKey);
            if (allowed === true) {
                res.locals.onlyVideo = video;
                res.locals.videoFile = file;
                res.locals.videoStreamingPlaylist = playlist;
                return next();
            }
            return res.sendStatus(403);
        }
        const result = yield isHLSAllowed(req, res, videoUUID);
        staticFileTokenBypass.set(cacheKey, result);
        if (result.allowed !== true)
            return;
        res.locals.onlyVideo = result.video;
        res.locals.videoFile = result.file;
        res.locals.videoStreamingPlaylist = result.playlist;
        return next();
    })
];
exports.ensureCanAccessPrivateVideoHLSFiles = ensureCanAccessPrivateVideoHLSFiles;
function isWebTorrentAllowed(req, res) {
    return tslib_1.__awaiter(this, void 0, void 0, function* () {
        const filename = (0, path_1.basename)(req.path);
        const file = yield video_file_1.VideoFileModel.loadWithVideoByFilename(filename);
        if (!file) {
            logger_1.logger.debug('Unknown static file %s to serve', req.originalUrl, { filename });
            res.sendStatus(403);
            return { allowed: false };
        }
        const video = yield video_1.VideoModel.load(file.getVideo().id);
        return {
            file,
            video,
            allowed: yield (0, shared_1.checkCanAccessVideoStaticFiles)({ req, res, video, paramId: video.uuid })
        };
    });
}
function isHLSAllowed(req, res, videoUUID) {
    return tslib_1.__awaiter(this, void 0, void 0, function* () {
        const filename = (0, path_1.basename)(req.path);
        const video = yield video_1.VideoModel.loadWithFiles(videoUUID);
        if (!video) {
            logger_1.logger.debug('Unknown static file %s to serve', req.originalUrl, { videoUUID });
            res.sendStatus(403);
            return { allowed: false };
        }
        const file = yield video_file_1.VideoFileModel.loadByFilename(filename);
        return {
            file,
            video,
            playlist: video.getHLSPlaylist(),
            allowed: yield (0, shared_1.checkCanAccessVideoStaticFiles)({ req, res, video, paramId: video.uuid })
        };
    });
}
function extractTokenOrDie(req, res) {
    var _a;
    const token = ((_a = res.locals.oauth) === null || _a === void 0 ? void 0 : _a.token.accessToken) || req.query.videoFileToken;
    if (!token) {
        return res.fail({
            message: 'Bearer token is missing in headers or video file token is missing in URL query parameters',
            status: 403
        });
    }
    return token;
}
//# sourceMappingURL=static.js.map