"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ruleHasPermission = exports.removePolicyRule = exports.listPolicyRule = exports.addPolicyRule = void 0;
const database_1 = require("./database");
const utils_1 = require("../utils");
const string_1 = require("../models/string");
const policyDomainName = '_Policy';
function sanitizePolicy4User(_p1) {
    if (_p1.id)
        _p1.id = decodeDot(_p1.id.replace('%id', ''));
    if (_p1.ruleId)
        _p1.ruleId = decodeDot(_p1.ruleId);
    if (_p1.ruleBody)
        _p1.ruleBody = decodeDot(_p1.ruleBody);
    return _p1;
}
function encodeDot(data) {
    return data.replace('.', '%');
}
function decodeDot(data) {
    return data.replace(new RegExp('[%]+', 'ig'), '.');
}
async function addPolicyRule(ruleId, rule, databaseAdapter, context, options) {
    await (0, utils_1.validateInput)(ruleId, string_1.StringSchema, 'ruleId is invalid');
    await (0, utils_1.validateInput)(rule, string_1.StringSchema, 'rule is invalid');
    const policy = {
        id: encodeDot(ruleId).concat('%id'),
        ruleId: encodeDot(ruleId),
        ruleBody: encodeDot(rule),
        return: [],
        createdAt: new Date()
    };
    const wOptions = {
        bypassDomainVerification: context && context.useMasterKey === true
    };
    const updateModel = {
        id: policy.id,
        filter: {},
        upsert: true,
        update: {
            $set: policy
        }
    };
    const _p1 = await (0, database_1.updateDataInStore)(policyDomainName, updateModel, context, databaseAdapter, wOptions, options);
    if (_p1.modified > 0) {
        delete policy.return;
        delete policy.createdAt;
        return sanitizePolicy4User(policy);
    }
    return null;
}
exports.addPolicyRule = addPolicyRule;
async function listPolicyRule(databaseAdapter, context, options) {
    const queryModel = { filter: {}, return: [] };
    const wOptions = { bypassDomainVerification: true };
    const _j1 = await (0, database_1.findDataByFilterInStore)('_Policy', queryModel, context, databaseAdapter, wOptions, options);
    return _j1.map(x => sanitizePolicy4User(x));
}
exports.listPolicyRule = listPolicyRule;
async function removePolicyRule(ruleId, context, databaseAdapter, options) {
    await (0, utils_1.validateInput)(ruleId, string_1.StringSchema, 'invalid rule id');
    const deleteModel = {
        filter: {
            ruleId: ruleId.replace('.', '%'),
        },
        return: ['id'],
    };
    const wOptions = { bypassDomainVerification: true };
    const _y89 = await (0, database_1.removeDataInStore)('_Policy', deleteModel, context, databaseAdapter, wOptions, options);
    return _y89.map(z => sanitizePolicy4User(z));
}
exports.removePolicyRule = removePolicyRule;
function getGlobalRule(ruleId) {
    const ruleIdInArray = ruleId.split('.');
    if (ruleIdInArray.length >= 2) {
        ruleIdInArray[1] = '*';
        const globalRule = ruleIdInArray.join('.');
        return { ruleId: globalRule.replace('.', '%') };
    }
    return null;
}
async function ruleHasPermission(ruleId, context, databaseAdapter, options) {
    await (0, utils_1.validateInput)(ruleId, string_1.StringSchema, 'invalid rule id');
    if (context && context?.useMasterKey === true)
        return true;
    const filter = [];
    const originalRule = { ruleId: ruleId.replace('.', '%') };
    const globalRule = getGlobalRule(ruleId);
    if (globalRule)
        filter.push(globalRule);
    filter.push(originalRule);
    const queryModel = { return: [], filter: { $or: filter } };
    const wOptions = { bypassDomainVerification: true };
    let policies = await (0, database_1.findDataByFilterInStore)(policyDomainName, queryModel, context, databaseAdapter, wOptions, options);
    policies = policies.map(x => sanitizePolicy4User(x));
    if (policies.length === 0)
        return true;
    const originalRuleResult = policies.filter(value => value.ruleId === decodeDot(originalRule.ruleId));
    if (originalRuleResult && originalRuleResult.length === 1 && originalRuleResult[0].ruleBody) {
        const execRule = new Function('context', originalRuleResult[0].ruleBody);
        return execRule(context) === true;
    }
    const globalRuleResult = policies.filter(value => value.ruleId === decodeDot(globalRule.ruleId));
    if (globalRuleResult && globalRuleResult.length === 1 && globalRuleResult[0].ruleBody) {
        const execRule = new Function('context', globalRuleResult[0].ruleBody);
        return execRule(context) === true;
    }
    return false;
}
exports.ruleHasPermission = ruleHasPermission;
