"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const fastify_plugin_1 = __importDefault(require("fastify-plugin"));
const usage_meter_1 = require("../shared/usage-meter");
const basic_auth_1 = __importDefault(require("basic-auth"));
const jsonwebtoken_1 = __importDefault(require("jsonwebtoken"));
const tokenAuthServicePlugin = (fastify, opts, done) => {
    fastify.decorateRequest("tokenId", null);
    fastify.decorate("tokenAuthPreValidation", async (request, reply) => {
        const tokenId = await fastify.tokenAuth.authenticate(request);
        if (tokenId === null) {
            reply.status(401).send("Unauthenticated");
        }
        else {
            request.tokenId = tokenId;
        }
    });
    function decorateTokenAuth(service) {
        fastify.decorate("tokenAuth", service);
    }
    if (!opts.enable) {
        decorateTokenAuth({
            async authenticate() {
                return "anonymous";
            },
        });
        return done();
    }
    async function checkJwt(token) {
        const { jwtPublicKey } = opts;
        if (!jwtPublicKey) {
            return ["not_a_jwt"];
        }
        return await new Promise((resolve) => {
            jsonwebtoken_1.default.verify(token, jwtPublicKey, (err, result) => {
                if (err) {
                    return resolve(["invalid"]);
                }
                const { sub } = result;
                if (sub) {
                    resolve(["success", sub]);
                }
                else {
                    resolve(["invalid"]);
                }
            });
        });
    }
    async function getTokenID(headers) {
        var _a;
        const { authorization } = headers;
        if (!authorization) {
            return null;
        }
        if (authorization.startsWith("Bearer ")) {
            const [_, token] = authorization.split("Bearer ");
            const [result, jwtTokenId] = await checkJwt(token);
            switch (result) {
                case "not_a_jwt":
                    break;
                case "invalid":
                    return null;
                case "success":
                    return { tokenId: jwtTokenId, countUsage: true };
            }
            const redisTokenId = await ((_a = fastify.tokens) === null || _a === void 0 ? void 0 : _a.check(token));
            if (redisTokenId) {
                return { tokenId: redisTokenId, countUsage: true };
            }
            return null;
        }
        else if (authorization.startsWith("Basic ")) {
            const basicCredentials = basic_auth_1.default.parse(authorization);
            if (!basicCredentials) {
                return null;
            }
            const isRootUser = opts.passphrases.includes(basicCredentials.pass);
            if (isRootUser) {
                const countUsage = !!headers["x-quirrel-count-usage"];
                return { tokenId: basicCredentials.name, countUsage };
            }
        }
        return null;
    }
    const usageMeter = new usage_meter_1.UsageMeter(fastify.redis);
    decorateTokenAuth({
        async authenticate(request) {
            const result = await getTokenID(request.headers);
            if (!result) {
                return null;
            }
            const { tokenId, countUsage } = result;
            if (countUsage) {
                usageMeter.record(tokenId);
            }
            return tokenId;
        },
    });
    return done();
};
exports.default = fastify_plugin_1.default(tokenAuthServicePlugin);
//# sourceMappingURL=token-auth.js.map