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;
};
import { Metadata, PermissionProviderBase, } from '@memberjunction/core';
import { RegisterClass, UUIDsEqual } from '@memberjunction/global';
/**
 * Wraps the {@link Metadata} + `EntityInfo.GetUserPermisions()` path behind the
 * unified {@link PermissionProviderBase} contract. Entity permissions are role-only,
 * additive (OR across roles), and cover the CRUD action set only.
 *
 * `resourceType` is the entity name (e.g., `"Users"`).
 * `resourceId` is unused — entity permissions are domain-wide per entity, not per-row.
 * Row-level filters are a separate concern handled by the RLS system.
 */
let EntityPermissionProvider = class EntityPermissionProvider extends PermissionProviderBase {
    constructor() {
        super(...arguments);
        this.DomainName = 'Entity Permissions';
        this.Description = 'CRUD permissions on MJ entities, role-based with optional row-level security filters and explicit Allow/Deny rows';
        this.SupportedGranteeTypes = ['Role'];
        this.SupportedActions = ['Read', 'Create', 'Update', 'Delete'];
        this.SupportsDeny = true;
    }
    GetResourceTypes(provider) {
        const md = provider ?? new Metadata();
        return md.Entities.map((e) => e.Name).sort((a, b) => a.localeCompare(b));
    }
    async CheckPermission(user, resourceType, _resourceId, action, provider) {
        const md = provider ?? new Metadata();
        const entity = md.EntityByName(resourceType);
        if (!entity) {
            return {
                Allowed: false,
                DomainName: this.DomainName,
                Reason: `Entity '${resourceType}' not found in metadata`,
            };
        }
        const perms = entity.GetUserPermisions(user);
        const allowed = this.checkActionOnPermission(perms, action);
        return {
            Allowed: allowed,
            DomainName: this.DomainName,
            Reason: allowed
                ? `Role grants ${action} on entity '${resourceType}'`
                : `No role grants ${action} on entity '${resourceType}'`,
        };
    }
    async GetEffectivePermissions(user, resourceType, _resourceId, provider) {
        const md = provider ?? new Metadata();
        const entity = md.EntityByName(resourceType);
        if (!entity)
            return [];
        const actions = this.resolveActions(entity.GetUserPermisions(user));
        if (actions.length === 0)
            return [];
        return [this.buildNormalizedPermission({
                resourceType, resourceId: null, resourceName: resourceType,
                granteeType: 'User', granteeId: user.ID, granteeName: user.Name, actions,
            })];
    }
    async GetUserResources(user, resourceType, provider) {
        const md = provider ?? new Metadata();
        const entities = resourceType
            ? md.Entities.filter((e) => e.Name === resourceType)
            : md.Entities;
        const results = [];
        for (const entity of entities) {
            const actions = this.resolveActions(entity.GetUserPermisions(user));
            if (actions.length === 0)
                continue;
            results.push(this.buildNormalizedPermission({
                resourceType: entity.Name, resourceId: null, resourceName: entity.Name,
                granteeType: 'User', granteeId: user.ID, granteeName: user.Name, actions,
            }));
        }
        return results;
    }
    async GetResourcePermissions(resourceType, _resourceId, provider) {
        const md = provider ?? new Metadata();
        const entity = md.EntityByName(resourceType);
        if (!entity)
            return [];
        const results = [];
        for (const ep of entity.Permissions) {
            const actions = this.resolveActions(ep);
            if (actions.length === 0)
                continue;
            const role = md.Roles.find((r) => UUIDsEqual(r.ID, ep.RoleID));
            const isDeny = (ep.Type || 'Allow').trim().toLowerCase() === 'deny';
            results.push(this.buildNormalizedPermission({
                resourceType, resourceId: null, resourceName: resourceType,
                granteeType: 'Role', granteeId: ep.RoleID,
                granteeName: role?.Name ?? ep.RoleID, actions,
                effect: isDeny ? 'Deny' : 'Allow',
                sourceRecordId: ep.ID,
            }));
        }
        return results;
    }
    checkActionOnPermission(perms, action) {
        switch (action) {
            case 'Read':
                return perms.CanRead;
            case 'Create':
                return perms.CanCreate;
            case 'Update':
                return perms.CanUpdate;
            case 'Delete':
                return perms.CanDelete;
            default:
                return false;
        }
    }
    resolveActions(perms) {
        return this.boolsToActions({
            Read: perms.CanRead,
            Create: perms.CanCreate,
            Update: perms.CanUpdate,
            Delete: perms.CanDelete,
        });
    }
};
EntityPermissionProvider = __decorate([
    RegisterClass(PermissionProviderBase, 'MJEntityPermissionProvider')
], EntityPermissionProvider);
export { EntityPermissionProvider };
//# sourceMappingURL=EntityPermissionProvider.js.map