import Permission from "../../../Types/Permission";
import Text from "../../../Types/Text";
import { combineWithPrivacyClause } from "../PrivacyFilterUtil";
import { Raw } from "typeorm";
/*
 * Project owners and admins, plus root/master-admin contexts, see all
 * private incidents. Other users only see private incidents they own
 * (directly via IncidentOwnerUser, or transitively through IncidentOwnerTeam
 * + TeamMember).
 */
export function shouldBypassIncidentPrivacy(props) {
    var _a;
    if (props.isRoot || props.isMasterAdmin) {
        return true;
    }
    if (props.tenantId && props.userTenantAccessPermission) {
        const tenantPerm = props.userTenantAccessPermission[props.tenantId.toString()];
        if ((_a = tenantPerm === null || tenantPerm === void 0 ? void 0 : tenantPerm.permissions) === null || _a === void 0 ? void 0 : _a.some((p) => {
            return (p.permission === Permission.ProjectOwner ||
                p.permission === Permission.ProjectAdmin);
        })) {
            return true;
        }
    }
    return false;
}
/*
 * Raw clause to apply on Incident.isPrivate. Lets non-private rows through
 * unconditionally, and private rows only when the current user is an owner
 * (directly, or via team membership). Returns undefined when the caller
 * should bypass the filter entirely.
 */
export function getIncidentSelfPrivacyRaw(props) {
    if (shouldBypassIncidentPrivacy(props)) {
        return undefined;
    }
    if (!props.userId) {
        return Raw((alias) => {
            return `(${alias} IS NULL OR ${alias} = FALSE)`;
        });
    }
    const uidRid = "uidPriv_" + Text.generateRandomText(10);
    return Raw((alias) => {
        return (`(${alias} IS NULL OR ${alias} = FALSE OR ` +
            `"Incident"."_id" IN (SELECT iou."incidentId" FROM "IncidentOwnerUser" iou WHERE iou."userId" = :${uidRid} AND iou."deletedAt" IS NULL) OR ` +
            `"Incident"."_id" IN (SELECT iot."incidentId" FROM "IncidentOwnerTeam" iot INNER JOIN "TeamMember" tm ON tm."teamId" = iot."teamId" WHERE tm."userId" = :${uidRid} AND tm."deletedAt" IS NULL AND iot."deletedAt" IS NULL))`);
    }, {
        [uidRid]: props.userId.toString(),
    });
}
/*
 * Raw clause to apply on a child table's incidentId column. Only rows whose
 * parent Incident the user is allowed to see pass. Returns undefined when the
 * caller should bypass the filter entirely.
 */
export function getIncidentRelatedRecordPrivacyRaw(props) {
    if (shouldBypassIncidentPrivacy(props)) {
        return undefined;
    }
    if (!props.userId) {
        return Raw((alias) => {
            return `(${alias} IN (SELECT i."_id" FROM "Incident" i WHERE i."deletedAt" IS NULL AND (i."isPrivate" IS NULL OR i."isPrivate" = FALSE)))`;
        });
    }
    const uidRid = "uidRel_" + Text.generateRandomText(10);
    return Raw((alias) => {
        return (`(${alias} IN (SELECT i."_id" FROM "Incident" i WHERE i."deletedAt" IS NULL AND (` +
            `i."isPrivate" IS NULL OR i."isPrivate" = FALSE OR ` +
            `i."_id" IN (SELECT iou."incidentId" FROM "IncidentOwnerUser" iou WHERE iou."userId" = :${uidRid} AND iou."deletedAt" IS NULL) OR ` +
            `i."_id" IN (SELECT iot."incidentId" FROM "IncidentOwnerTeam" iot INNER JOIN "TeamMember" tm ON tm."teamId" = iot."teamId" WHERE tm."userId" = :${uidRid} AND tm."deletedAt" IS NULL AND iot."deletedAt" IS NULL))))`);
    }, {
        [uidRid]: props.userId.toString(),
    });
}
export function applyIncidentSelfPrivacyFilter(query, props) {
    const rawClause = getIncidentSelfPrivacyRaw(props);
    if (!rawClause) {
        return query;
    }
    if (!query) {
        return { isPrivate: rawClause };
    }
    query.isPrivate = combineWithPrivacyClause(query.isPrivate, rawClause);
    return query;
}
export function applyIncidentRelatedRecordPrivacyFilter(query, props) {
    const rawClause = getIncidentRelatedRecordPrivacyRaw(props);
    if (!rawClause) {
        return query;
    }
    if (!query) {
        return { incidentId: rawClause };
    }
    query.incidentId = combineWithPrivacyClause(query.incidentId, rawClause);
    return query;
}
//# sourceMappingURL=IncidentPrivacyFilter.js.map