"use strict";
var AccessRightsTreeService_1;
Object.defineProperty(exports, "__esModule", { value: true });
exports.AccessRightsTreeService = void 0;
const tslib_1 = require("tslib");
const authorization_1 = require("@loopback/authorization");
const core_1 = require("@loopback/core");
const entity_name_1 = require("../../models/entity-name");
const object_node_service_1 = require("../object-node/object-node.service");
const object_type_service_1 = require("./../object-type.service");
const access_rights_abstract_service_1 = require("./access-rights-abstract.service");
const access_rights_tree_const_1 = require("./access-rights-tree.const");
const access_rights_const_1 = require("./access-rights.const");
const access_rights_service_1 = require("./access-rights.service");
let AccessRightsTreeService = AccessRightsTreeService_1 = class AccessRightsTreeService extends access_rights_abstract_service_1.AccessRightsAbstractService {
    constructor(accessRightsService, objectNodeService, objectTypeService) {
        super(access_rights_const_1.ACCESS_RIGHT_PROVIDER, AccessRightsTreeService_1.name, accessRightsService, entity_name_1.EntityName.objectTree);
        this.accessRightsService = accessRightsService;
        this.objectNodeService = objectNodeService;
        this.objectTypeService = objectTypeService;
    }
    async authorizeRead(ctx, context) {
        let treeNode = null;
        if (1 < context.scopes.length) {
            switch (context.scopes[1]) {
                case access_rights_tree_const_1.AccessRightsTreeScope.searchOwner:
                    // eslint-disable-next-line @typescript-eslint/no-unused-vars
                    treeNode = await ctx.treeContext.treeNode.getOrSetValue(async () => {
                        return this.objectNodeService.searchOwner(context.invocationContext.args[0], context.invocationContext.args[1]);
                    });
                    break;
                case access_rights_tree_const_1.AccessRightsTreeScope.searchNamespace:
                    // eslint-disable-next-line @typescript-eslint/no-unused-vars
                    treeNode = await ctx.treeContext.treeNode.getOrSetValue(async () => {
                        return this.objectNodeService.searchNamespace(context.invocationContext.args[0], context.invocationContext.args[1], context.invocationContext.args[2], context.invocationContext.args[3]);
                    });
                    break;
                case access_rights_tree_const_1.AccessRightsTreeScope.searchTree:
                    // eslint-disable-next-line @typescript-eslint/no-unused-vars
                    treeNode = await ctx.treeContext.treeNode.getOrSetValue(async () => {
                        return this.objectNodeService.searchTree(context.invocationContext.args[0], context.invocationContext.args[1], context.invocationContext.args[2], context.invocationContext.args[3], context.invocationContext.args[4], context.invocationContext.args[5]);
                    });
                    break;
                case access_rights_tree_const_1.AccessRightsTreeScope.searchNode:
                    {
                        const originalTreeNode = await this.objectNodeService.searchTree(context.invocationContext.args[0], context.invocationContext.args[1], context.invocationContext.args[2], context.invocationContext.args[3], context.invocationContext.args[4], context.invocationContext.args[5]);
                        if (originalTreeNode) {
                            const types = await this.objectTypeService.getImplementingTypes(context.invocationContext.args[6]);
                            const treeNodes = await this.objectNodeService.searchByParentTreeId(originalTreeNode.id, {
                                objectTypeIds: types,
                                name: context.invocationContext.args[7],
                            });
                            if (treeNodes && 1 === treeNodes.length) {
                                treeNode = treeNodes[0];
                            }
                        }
                    }
                    break;
            }
        }
        else {
            treeNode = await ctx.treeContext.treeNode.getOrSetValue(async () => {
                return this.objectNodeService.searchById(context.invocationContext.args[0]);
            });
        }
        if (treeNode) {
            return (await this.accessRightsService.hasNodeAccessRights(access_rights_const_1.AccessRightsScope.read, treeNode, ctx))
                ? authorization_1.AuthorizationDecision.ALLOW
                : authorization_1.AuthorizationDecision.DENY;
        }
        return authorization_1.AuthorizationDecision.DENY;
    }
    async authorizeCreate(ctx, context) {
        const treeNode = await ctx.treeContext.treeNode.getOrSetValue(async () => {
            return this.objectNodeService.searchById(context.invocationContext.args[0]);
        });
        if (treeNode) {
            return (await this.accessRightsService.hasNodeAccessRights(access_rights_const_1.AccessRightsScope.create, treeNode, ctx))
                ? authorization_1.AuthorizationDecision.ALLOW
                : authorization_1.AuthorizationDecision.DENY;
        }
        return authorization_1.AuthorizationDecision.DENY;
    }
    async authorizeUpdate(ctx, context) {
        const treeNode = await ctx.treeContext.treeNode.getOrSetValue(async () => {
            return this.objectNodeService.searchById(context.invocationContext.args[0]);
        });
        if (treeNode) {
            return (await this.accessRightsService.hasNodeAccessRights(access_rights_const_1.AccessRightsScope.update, treeNode, ctx))
                ? authorization_1.AuthorizationDecision.ALLOW
                : authorization_1.AuthorizationDecision.DENY;
        }
        return authorization_1.AuthorizationDecision.DENY;
    }
    async authorizeDelete(ctx, context) {
        const treeNode = await ctx.treeContext.treeNode.getOrSetValue(async () => {
            return this.objectNodeService.searchById(context.invocationContext.args[0]);
        });
        if (treeNode) {
            return (await this.accessRightsService.hasNodeAccessRights(access_rights_const_1.AccessRightsScope.delete, treeNode, ctx))
                ? authorization_1.AuthorizationDecision.ALLOW
                : authorization_1.AuthorizationDecision.DENY;
        }
        return authorization_1.AuthorizationDecision.DENY;
    }
    async cleanReturnedEntity(entity, ctx) {
        const tree = entity;
        if (!tree.children) {
            tree.children = [];
        }
        await ctx.treeContext.treeChildren.getOrSetValue(async () => tree.children.map((child) => child.treeNode));
        if (!tree.entityCtx) {
            tree.entityCtx = { entityType: entity_name_1.EntityName.objectTree };
        }
        tree.entityCtx.aclCtx = {
            rights: await this.accessRightsService.getNodeAccessRights(tree.treeNode, ctx),
        };
        if (tree.entityCtx.aclCtx.rights.read) {
            await this.accessRightsService.cleanReturnedEntities(entity_name_1.EntityName.objectTree, tree.children, ctx);
        }
        else {
            tree.children = [];
        }
        const objectType = await this.objectTypeService.searchById(tree.treeNode.objectTypeId);
        tree.childrenEntityCtx = {};
        if (objectType === null || objectType === void 0 ? void 0 : objectType.objectSubTypes) {
            for (const subType of objectType.objectSubTypes) {
                tree.childrenEntityCtx[subType.subObjectTypeId] = {
                    aclCtx: {
                        rights: await this.accessRightsService.getForcedAccessRightsForObjectType(subType.subObjectTypeId),
                    },
                };
            }
        }
        await this.accessRightsService.cleanReturnedEntity(entity_name_1.EntityName.objectNode, tree.treeNode, ctx);
    }
};
AccessRightsTreeService = AccessRightsTreeService_1 = tslib_1.__decorate([
    core_1.injectable({ scope: core_1.BindingScope.SINGLETON }),
    tslib_1.__param(0, core_1.service(access_rights_service_1.AccessRightsService)),
    tslib_1.__param(1, core_1.service(object_node_service_1.ObjectNodeService)),
    tslib_1.__param(2, core_1.service(object_type_service_1.ObjectTypeService)),
    tslib_1.__metadata("design:paramtypes", [access_rights_service_1.AccessRightsService,
        object_node_service_1.ObjectNodeService,
        object_type_service_1.ObjectTypeService])
], AccessRightsTreeService);
exports.AccessRightsTreeService = AccessRightsTreeService;
//# sourceMappingURL=access-rights-tree.service.js.map