"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ParsedJwtResolver = void 0;
exports.getJwtFromRequest = getJwtFromRequest;
exports.getEntityIdFromRequestJwt = getEntityIdFromRequestJwt;
exports.getEntityFromRequestJwt = getEntityFromRequestJwt;
exports.createAuthMiddleware = createAuthMiddleware;
exports.createBasicAuthMiddleware = createBasicAuthMiddleware;
exports.resolveEntityFromRequestJwt = resolveEntityFromRequestJwt;
exports.createEntityFromRequestJwtParameterResolver = createEntityFromRequestJwtParameterResolver;
const __ΩInstanceType = ['T', 'args', 'new', 'InstanceType', 'l>e"!R"RPde#!P"@2"h"!/#qk#\'QRb!Pde"!p)w$y'];
function __assignType(fn, args) {
    fn.__type = args;
    return fn;
}
/*@ts-ignore*/
var { __ΩRouteParameterResolverContext, __ΩRouteParameterResolver } = require('@deepkit/http');
const http_1 = require("@deepkit/http");
/*@ts-ignore*/
var { __ΩScopedLogger } = require('@deepkit/logger');
const crypto_1 = require("crypto");
const auth_1 = require("../auth");
const database_1 = require("../database");
const middleware_1 = require("./middleware");
const store_1 = require("./store");
/**
 * base request JWT lookup
 */
async function getJwtFromRequest(request) {
    return (0, store_1.getOrCacheValue)(request, auth_1.ParsedJwt, _getJwtFromRequest);
}
getJwtFromRequest.__type = [() => http_1.HttpRequest, 'request', () => auth_1.ParsedJwt, 'getJwtFromRequest', 'PP7!2"PP7#-J`/$'];
async function _getJwtFromRequest(request) {
    const jwt = await auth_1.JWT.processWithRequest(request);
    if (!jwt)
        return undefined;
    if (!jwt.isValid) {
        if (!jwt.isSignatureValid)
            throw new http_1.HttpUnauthorizedError('Invalid JWT signature');
        if (!jwt.isNotExpired)
            throw new http_1.HttpUnauthorizedError('Expired JWT');
        throw new http_1.HttpUnauthorizedError('Invalid JWT');
    }
    return jwt;
}
_getJwtFromRequest.__type = [() => http_1.HttpRequest, 'request', () => auth_1.ParsedJwt, '_getJwtFromRequest', 'PP7!2"PP7#-J`/$'];
class ParsedJwtResolver {
    async resolve(context) {
        const jwt = await getJwtFromRequest(context.request);
        if (!jwt && !context.type.isOptional()) {
            throw new http_1.HttpUnauthorizedError('Request does not contain required JWT');
        }
        return jwt;
    }
}
exports.ParsedJwtResolver = ParsedJwtResolver;
ParsedJwtResolver.__type = [() => __ΩRouteParameterResolverContext, 'context', () => auth_1.ParsedJwt, 'resolve', () => __ΩRouteParameterResolver, 'ParsedJwtResolver', 'Pn!2"PP7#-J`0$5n%x"w&'];
/**
 * base request JWT user ID lookup
 */
const EntityIdSymbol = Symbol('EntityId');
// eslint-disable-next-line @typescript-eslint/no-explicit-any
async function getEntityIdFromRequestJwt(request) {
    const jwt = await getJwtFromRequest(request);
    return jwt?.subject;
}
getEntityIdFromRequestJwt.__type = [() => http_1.HttpRequest, 'request', 'getEntityIdFromRequestJwt', 'PP7!2""`/#'];
/**
 * request JWT user ID to user object
 */
async function getEntityFromRequestJwt(request, EntityClass) {
    const entityId = await getEntityIdFromRequestJwt(request);
    return entityId ? (0, database_1.getEntity)(EntityClass, entityId) : undefined;
}
getEntityFromRequestJwt.__type = [() => http_1.HttpRequest, 'request', 'EntityClass', () => __ΩInstanceType, 'getEntityFromRequestJwt', 'PP7!2""2#P"o$"-J`/%'];
const __ΩEntityValidator = ['T', () => http_1.HttpRequest, 'request', 'getEntityIdFromRequest', () => http_1.HttpRequest, () => __ΩInstanceType, 'entity', 'validateEntity', 'EntityValidator', 'b!PPP7"2#"`1$PP7%2#e#!o&"2\'$`1(8Mw)y'];
function createAuthMiddleware(EntityClass) {
    var _a;
    return _a = class extends middleware_1.HttpMiddleware {
            async handle(request) {
                const entityId = await (0, store_1.getOrCacheValue)(request, (0, store_1.getCompositeCacheKey)(EntityClass, EntityIdSymbol), this.getEntityIdFromRequest.bind(this));
                await this.loadAndValidateEntity(request, entityId);
            }
            async getEntityIdFromRequest(request) {
                const id = await getEntityIdFromRequestJwt(request);
                if (!id)
                    throw new http_1.HttpUnauthorizedError();
                return id;
            }
            // eslint-disable-next-line @typescript-eslint/no-explicit-any
            async loadAndValidateEntity(request, id) {
                const validateFn = this.validateEntity;
                if (validateFn) {
                    const entity = await (0, store_1.getOrCacheValue)(request, EntityClass, () => (0, database_1.getEntityOrUndefined)(EntityClass, id));
                    if (!entity)
                        throw new http_1.HttpUnauthorizedError();
                    await validateFn(request, entity);
                }
            }
        },
        _a.__type = [() => middleware_1.HttpMiddleware, () => http_1.HttpRequest, 'request', 'handle', () => http_1.HttpRequest, 'getEntityIdFromRequest', () => http_1.HttpRequest, 'id', 'loadAndValidateEntity', () => __ΩEntityValidator, () => EntityClass, 'P7!PP7"2#"0$PP7%2#"0&PP7\'2#"2("0)5Pdi+h!!qe!!!jo*"x"'],
        _a;
}
createAuthMiddleware.__type = ['EntityClass', 'createAuthMiddleware', 'P"2!"/"'];
/**
 * HTTP basic auth middleware
 */
function createBasicAuthMiddleware(expectedUsername) {
    var _a;
    return _a = class extends middleware_1.HttpMiddleware {
            constructor(logger) {
                super();
                this.logger = logger;
                // todo:figure this out
                // eslint-disable-next-line @typescript-eslint/no-require-imports
                this.config = require('../app').getAppConfig();
                if (!this.config.AUTH_BASIC_SECRET) {
                    this.logger.error('No AUTH_BASIC_SECRET provided');
                }
            }
            async handle(request) {
                const authHeader = request.headers['authorization'];
                if (!authHeader) {
                    throw new http_1.HttpUnauthorizedError();
                }
                const [scheme, credentials] = authHeader.split(' ');
                if (scheme.toLowerCase() !== 'basic') {
                    throw new http_1.HttpUnauthorizedError('Invalid authorization scheme');
                }
                const [username, password] = Buffer.from(credentials, 'base64').toString().split(':');
                const secret = this.config.AUTH_BASIC_SECRET ?? '';
                const usernameInvalid = expectedUsername && expectedUsername !== username;
                const passwordBuf = Buffer.from(password);
                const secretBuf = Buffer.from(secret);
                const passwordInvalid = passwordBuf.length !== secretBuf.length || !(0, crypto_1.timingSafeEqual)(passwordBuf, secretBuf);
                if (usernameInvalid || passwordInvalid) {
                    throw new http_1.HttpUnauthorizedError('Invalid credentials');
                }
            }
        },
        _a.__type = [() => middleware_1.HttpMiddleware, 'BaseAppConfig', 'config', () => __ΩScopedLogger, 'logger', 'constructor', () => http_1.HttpRequest, 'request', 'handle', 'P7!"w"3#Pn$2%:"0&PP7\'2("0)5'],
        _a;
}
createBasicAuthMiddleware.__type = ['expectedUsername', 'createBasicAuthMiddleware', 'P&2!8"/"'];
/**
 * standard authed entity resolver
 */
async function resolveEntityFromRequestJwt(context, EntityClass) {
    const ent = await getEntityFromRequestJwt(context.request, EntityClass);
    if (!ent && !context.type.isOptional()) {
        throw new http_1.HttpUnauthorizedError();
    }
    return ent;
}
resolveEntityFromRequestJwt.__type = [() => __ΩRouteParameterResolverContext, 'context', 'EntityClass', 'resolveEntityFromRequestJwt', 'Pn!2""2#"/$'];
function createEntityFromRequestJwtParameterResolver(EntityClass) {
    return (0, store_1.createCachingParameterResolver)(EntityClass, __assignType(async (context) => {
        return resolveEntityFromRequestJwt(context, EntityClass);
    }, [() => __ΩRouteParameterResolverContext, 'context', '', 'Pn!2""/#']));
}
createEntityFromRequestJwtParameterResolver.__type = ['EntityClass', 'createEntityFromRequestJwtParameterResolver', 'P"2!"/"'];
//# sourceMappingURL=auth.js.map