var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
    if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
import DatabaseRequestType from "../../BaseDatabase/DatabaseRequestType";
import QueryUtil from "../QueryUtil";
import AccessControlPermission from "./AccessControlPermission";
import OwnedScopePermission from "./OwnedScopePermission";
import PermissionUtil from "./PermissionsUtil";
import PublicPermission from "./PublicPermission";
import QueryPermission from "./QueryPermission";
import SelectPermission from "./SelectPermission";
import TablePermission from "./TablePermission";
import TenantPermission from "./TenantPermission";
import UserPermissions from "./UserPermission";
import TableColumnType from "../../../../Types/Database/TableColumnType";
import ObjectID from "../../../../Types/ObjectID";
import CaptureSpan from "../../../Utils/Telemetry/CaptureSpan";
export default class BasePermission {
    static async checkPermissions(modelType, query, select, props, type) {
        const model = new modelType();
        if (props.isRoot || props.isMasterAdmin) {
            query = await PermissionUtil.addTenantScopeToQueryAsRoot(modelType, query, props);
        }
        if (!props.isRoot && !props.isMasterAdmin) {
            //check if the user is logged in.
            PublicPermission.checkIfUserIsLoggedIn(modelType, props, type);
            // add tenant scope.
            query = await TenantPermission.addTenantScopeToQuery(modelType, query, select, props, type);
            // add user scope if any
            query = await UserPermissions.addUserScopeToQuery(modelType, query, props);
            if (!props.isMultiTenantRequest) {
                // We will check for this permission in recursive function.
                // check model level permissions.
                TablePermission.checkTableLevelPermissions(modelType, props, type);
                /*
                 * We will check for this permission in recursive function.
                 * check query permissions.
                 */
                QueryPermission.checkQueryPermission(modelType, query, props);
                query = await AccessControlPermission.addAccessControlIdsToQuery(modelType, query, select, props, type);
                /*
                 * Apply the `Owned` permission scope filter (see
                 * Internal/Docs/PermissionsSimplification.md). When the user's
                 * applicable permission rows are exclusively Owned-scoped, this
                 * restricts the query to resources where the user is in *OwnerUser
                 * or any of their teams is in *OwnerTeam.
                 */
                query = await OwnedScopePermission.addOwnedScopeToQuery(modelType, query, props, type);
                /// Implement Related Permissions.
                if (model.canAccessIfCanReadOn) {
                    const tableColumnMetadata = model.getTableColumnMetadata(model.canAccessIfCanReadOn);
                    if (tableColumnMetadata &&
                        tableColumnMetadata.modelType &&
                        (tableColumnMetadata.type === TableColumnType.Entity ||
                            tableColumnMetadata.type === TableColumnType.EntityArray)) {
                        const accessControlIds = AccessControlPermission.getAccessControlIdsForQuery(tableColumnMetadata.modelType, {}, {
                            _id: true,
                        }, props, type);
                        if (accessControlIds.length > 0) {
                            const tableColumnMetadataModel = new tableColumnMetadata.modelType();
                            const accessControlQuery = {
                                [tableColumnMetadataModel.getAccessControlColumn()]: accessControlIds,
                            };
                            /*
                             * Preserve any caller-supplied filter on the relation key
                             * instead of overwriting it. Plain relation objects are
                             * merged (the access-control predicate wins on a key
                             * collision — fail closed, access never widens); a scalar
                             * id filter is folded in as the relation's _id. Anything
                             * else falls back to the access-control query alone.
                             */
                            const existingRelationFilter = query[model.canAccessIfCanReadOn];
                            if (typeof existingRelationFilter === "string" ||
                                existingRelationFilter instanceof ObjectID) {
                                query[model.canAccessIfCanReadOn] = Object.assign({ _id: existingRelationFilter.toString() }, accessControlQuery);
                            }
                            else if (existingRelationFilter &&
                                typeof existingRelationFilter === "object" &&
                                !Array.isArray(existingRelationFilter) &&
                                existingRelationFilter.constructor === Object) {
                                query[model.canAccessIfCanReadOn] = Object.assign(Object.assign({}, existingRelationFilter), accessControlQuery);
                            }
                            else {
                                query[model.canAccessIfCanReadOn] =
                                    accessControlQuery;
                            }
                        }
                    }
                }
                if (select) {
                    // check query permission.
                    SelectPermission.checkSelectPermission(modelType, select, props);
                    QueryPermission.checkRelationQueryPermission(modelType, select, props);
                }
            }
        }
        query = QueryUtil.serializeQuery(modelType, query);
        return { query };
    }
}
__decorate([
    CaptureSpan(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object, Object, Object, Object, String]),
    __metadata("design:returntype", Promise)
], BasePermission, "checkPermissions", null);
//# sourceMappingURL=BasePermission.js.map