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 BillingPermissions from "./BillingPermission";
import EditionPermissions from "./EditionPermission";
import PublicPermission from "./PublicPermission";
import DatabaseCommonInteractionPropsUtil, { PermissionType, } from "../../../../Types/BaseDatabase/DatabaseCommonInteractionPropsUtil";
import NotAuthorizedException from "../../../../Types/Exception/NotAuthorizedException";
import CaptureSpan from "../../../Utils/Telemetry/CaptureSpan";
import Permission, { PermissionHelper, } from "../../../../Types/Permission";
export default class TablePermission {
    static getTablePermission(modelType, type) {
        let modelPermissions = [];
        const model = new modelType();
        if (type === DatabaseRequestType.Create) {
            modelPermissions = model.createRecordPermissions;
        }
        if (type === DatabaseRequestType.Update) {
            modelPermissions = model.updateRecordPermissions;
        }
        if (type === DatabaseRequestType.Delete) {
            modelPermissions = model.deleteRecordPermissions;
        }
        if (type === DatabaseRequestType.Read) {
            modelPermissions = model.readRecordPermissions;
        }
        return modelPermissions;
    }
    static checkTableLevelPermissions(modelType, props, type) {
        // 1 CHECK: PUBLIC check -- Check if this is a public request and if public is allowed.
        PublicPermission.checkIfUserIsLoggedIn(modelType, props, type);
        // 2nd CHECK: Is user project in active state?
        BillingPermissions.checkBillingPermissions(modelType, props, type);
        /*
         * 3rd CHECK: Is this an enterprise-only feature being accessed on the
         * community self-hosted build?
         */
        EditionPermissions.checkEditionPermissions(modelType, props);
        // 4th CHECK: Does user have access to CRUD data on this model.
        const userPermissions = DatabaseCommonInteractionPropsUtil.getUserPermissions(props, PermissionType.Allow);
        const modelPermissions = TablePermission.getTablePermission(modelType, type);
        const effectiveModelPermissions = TablePermission.getEffectiveModelPermissions(modelType, modelPermissions, type);
        if (!PermissionHelper.doesPermissionsIntersect(userPermissions.map((userPermission) => {
            return userPermission.permission;
        }) || [], effectiveModelPermissions)) {
            const permissions = PermissionHelper.getPermissionTitles(modelPermissions);
            if (permissions.length === 0) {
                throw new NotAuthorizedException(`${type} on ${new modelType().singularName} is not allowed.`);
            }
            throw new NotAuthorizedException(`You do not have permissions to ${type} ${new modelType().singularName}. You need one of these permissions: ${permissions.join(", ")}`);
        }
    }
    /*
     * Resolves the model's enumerated permissions plus any wildcards that should
     * grant access. See Internal/Docs/PermissionsSimplification.md.
     *
     * Operational-resource wildcard: models marked @OperationalResource also
     * accept the matching *AllOperationalResources wildcard (ReadAllOperationalResources for read,
     * EditAllOperationalResources for update, etc.). Scope (All/Owned/Labels) on the
     * permission row is evaluated in a later step, not here.
     */
    static getEffectiveModelPermissions(modelType, modelPermissions, type) {
        const effective = [...modelPermissions];
        const model = new modelType();
        if (model.isOperationalResource) {
            const wildcard = TablePermission.getWildcardPermissionForOperation(type);
            if (wildcard && !effective.includes(wildcard)) {
                effective.push(wildcard);
            }
        }
        return effective;
    }
    static getWildcardPermissionForOperation(type) {
        switch (type) {
            case DatabaseRequestType.Read:
                return Permission.ReadAllOperationalResources;
            case DatabaseRequestType.Update:
                return Permission.EditAllOperationalResources;
            case DatabaseRequestType.Delete:
                return Permission.DeleteAllOperationalResources;
            case DatabaseRequestType.Create:
                return Permission.CreateAllOperationalResources;
            default:
                return null;
        }
    }
    static checkTableLevelBlockPermissions(modelType, props, type) {
        // 1 CHECK: PUBLIC check -- Check if this is a public request and if public is allowed.
        PublicPermission.checkIfUserIsLoggedIn(modelType, props, type);
        // 2nd CHECK: Does user have access to CRUD data on this model.
        const userPermissions = DatabaseCommonInteractionPropsUtil.getUserPermissions(props, PermissionType.Block);
        const modelPermissions = TablePermission.getTablePermission(modelType, type);
        const intersectingPermissions = PermissionHelper.getIntersectingPermissions(userPermissions.map((userPermission) => {
            return userPermission.permission;
        }) || [], modelPermissions);
        if (intersectingPermissions && intersectingPermissions.length > 0) {
            for (const permission of intersectingPermissions) {
                const userPermission = userPermissions.find((userPermission) => {
                    return userPermission.permission === permission;
                });
                if (userPermission &&
                    (!userPermission.labelIds || userPermission.labelIds.length === 0)) {
                    throw new NotAuthorizedException(`You are not authorized to ${type} ${new modelType().singularName} because ${userPermission.permission} is in your team's permission block list.`);
                }
            }
        }
    }
}
__decorate([
    CaptureSpan(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object, String]),
    __metadata("design:returntype", Array)
], TablePermission, "getTablePermission", null);
__decorate([
    CaptureSpan(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object, Object, String]),
    __metadata("design:returntype", void 0)
], TablePermission, "checkTableLevelPermissions", null);
__decorate([
    CaptureSpan(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object, Object, String]),
    __metadata("design:returntype", void 0)
], TablePermission, "checkTableLevelBlockPermissions", null);
//# sourceMappingURL=TablePermission.js.map