"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.AccessRightsInterceptor = void 0;
const tslib_1 = require("tslib");
const context_1 = require("@loopback/context");
const core_1 = require("@loopback/core");
const http_1 = require("http");
const lodash_1 = require("lodash");
const application_error_1 = require("../helper/application-error");
const access_rights_service_1 = require("../services/access-rights/access-rights.service");
const application_service_1 = require("../services/application.service");
const method_value_result_1 = require("./../helper/method-value-result");
const abstract_interceptor_1 = require("./abstract.interceptor");
/**
 * This class will be bound to the application as an `Interceptor` during
 * `boot`
 */
let AccessRightsInterceptor = class AccessRightsInterceptor extends abstract_interceptor_1.AbstractInterceptor {
    constructor(accessRightsService, ctx) {
        super();
        this.accessRightsService = accessRightsService;
        this.ctx = ctx;
    }
    /**
     * This method is used by LoopBack context to produce an interceptor function
     * for the binding.
     *
     * @returns An interceptor function
     */
    value() {
        return this.intercept.bind(this);
    }
    /**
     * The logic to intercept an invocation
     * @param invocationCtx - Invocation context
     * @param next - A function to invoke next interceptor or the target method
     */
    async intercept(invocationCtx, next) {
        var _a, _b;
        // eslint-disable-next-line no-useless-catch
        try {
            // Add pre-invocation logic here
            const result = await next();
            // Add post-invocation logic here
            if (Array.isArray(result)) {
                if (result.length > 0) {
                    let cleanDone = false;
                    if ((_a = result[0]) === null || _a === void 0 ? void 0 : _a.uri) {
                        const uriParts = await this.getUriParts(invocationCtx, this.ctx);
                        const entityName = this.getEntityName((_b = result[0]) === null || _b === void 0 ? void 0 : _b.uri, uriParts.baseUri);
                        if (lodash_1.every(result, (oneResult) => {
                            return (this.getEntityName(oneResult.uri, uriParts.baseUri) ===
                                entityName);
                        })) {
                            await this.accessRightsService.cleanReturnedEntities(entityName, result, this.ctx);
                            cleanDone = true;
                        }
                    }
                    else {
                        throw application_error_1.ApplicationError.forbidden();
                    }
                    if (!cleanDone) {
                        for (const oneResult of result) {
                            if (oneResult === null || oneResult === void 0 ? void 0 : oneResult.uri) {
                                const uriParts = await this.getUriParts(invocationCtx, this.ctx);
                                const entityName = this.getEntityName(oneResult.uri, uriParts.baseUri);
                                await this.accessRightsService.cleanReturnedEntity(entityName, oneResult, this.ctx);
                            }
                            else {
                                throw application_error_1.ApplicationError.forbidden();
                            }
                        }
                    }
                }
            }
            else if (lodash_1.isObject(result) &&
                !(result instanceof http_1.ServerResponse) &&
                !(result instanceof method_value_result_1.ValueResult)) {
                const entity = result;
                if (entity === null || entity === void 0 ? void 0 : entity.uri) {
                    const uriParts = await this.getUriParts(invocationCtx, this.ctx);
                    const entityName = this.getEntityName(entity.uri, uriParts.baseUri);
                    await this.accessRightsService.cleanReturnedEntity(entityName, result, this.ctx);
                }
                else {
                    const uriParts = await this.getUriParts(invocationCtx, this.ctx);
                    if (-1 === ['/explorer/openapi.json/'].indexOf(uriParts.objectUri)) {
                        console.trace('missing rights', uriParts);
                        throw application_error_1.ApplicationError.forbidden();
                    }
                }
            }
            return result;
        }
        catch (err) {
            // Add error handling logic here
            if (!err.statusCode) {
                throw application_error_1.ApplicationError.unexpectedError(err);
            }
            throw err;
        }
    }
};
AccessRightsInterceptor.BINDING_KEY = `interceptors.${AccessRightsInterceptor.name}`;
AccessRightsInterceptor = tslib_1.__decorate([
    tslib_1.__param(0, core_1.service(access_rights_service_1.AccessRightsService)),
    tslib_1.__param(1, context_1.inject(application_service_1.CURRENT_CONTEXT)),
    tslib_1.__metadata("design:paramtypes", [access_rights_service_1.AccessRightsService,
        application_service_1.CurrentContext])
], AccessRightsInterceptor);
exports.AccessRightsInterceptor = AccessRightsInterceptor;
//# sourceMappingURL=access-rights.interceptor.js.map