Skip to content

Permissions Guide — Deny ACEs & ACL Recalculation

Version: v257.0 Last Updated: 2026-04-10 Audience: Administrators, advanced users


Overview

Cesivi implements SharePoint-compatible role-based access control (RBAC) with an extension: Deny ACEs. Standard SharePoint only supports Allow permissions. Cesivi adds explicit Deny entries that follow NTFS canonical ordering (Deny always wins over Allow at the same scope).

Backward compatibility: All SP-compatible APIs (CSOM, REST, SOAP) return only Allow entries. Deny ACEs are managed exclusively through the Cesivi-specific REST API (/_api/cesivi/permissions/).


1. Deny Permission Management

How Deny Works

Deny ACEs use NTFS canonical ordering:

  1. Explicit Deny (at this scope) — always wins
  2. Explicit Allow (at this scope) — wins if no Deny
  3. Inherited Deny (from parent scope) — wins if no explicit entry
  4. Inherited Allow (from parent scope) — lowest priority

Example: User has Full Control (Allow) + Deny on EditListItems. - AllowMask = FullControl & ~EditListItems - DenyMask = EditListItems - EffectiveMask = FullControl & ~EditListItems (cannot edit, everything else allowed)

Deny ACE REST API

All endpoints require site context and admin permissions.

Add a Deny ACE

POST /_api/cesivi/permissions/deny
Content-Type: application/json

{
  "principalId": 42,
  "scopeId": "web:/",
  "permissionMask": 4
}

scopeId format: "web:/" (root web), "web:/subweb", "list:/Lists/Tasks", "item:/Lists/Tasks/1".

permissionMask is a 64-bit bitmask of SPBasePermissions bits (same as role definition BasePermissionsRaw).

Remove a Deny ACE

DELETE /_api/cesivi/permissions/deny/{aceId}

List Deny ACEs for a scope

GET /_api/cesivi/permissions/deny?scopeId=web:/

List Deny ACEs for a principal

GET /_api/cesivi/permissions/deny?principalId=42

2. ACL Recalculation

How Recalculation Works

The computed ACL table is pre-warmed at startup and updated on every role assignment change. IDP-sourced group memberships (AD groups) are refreshed on a configurable interval.

Two types of membership source: - IDP (PermissionSource.IDP) — from AD/LDAP group membership; refreshed on schedule - CesiviInternal (PermissionSource.CesiviInternal) — from SP group membership; updated on change

SyncIdpGroupMemberships replaces ALL IDP memberships for a user (atomic). CesiviInternal memberships are never touched by this operation.

Configuration

{
  "Cesivi": {
    "AclRecalculation": {
      "RecalcIntervalMinutes": 60,
      "BatchSize": 100,
      "EnableBackgroundRecalc": true
    }
  }
}
Setting Default Description
RecalcIntervalMinutes 60 How often stale users are recalculated (minutes)
BatchSize 100 Users processed per recalc batch
EnableBackgroundRecalc true Enable/disable background recalc service

Force Recalculation REST API

Force recalc for a specific user

POST /_api/cesivi/permissions/recalc
Content-Type: application/json

{ "userId": 42 }

Force recalc for all users in the site collection

POST /_api/cesivi/permissions/recalcall

Recalc status

GET /_api/cesivi/permissions/recalcstatus

Returns: last recalc time, pending count, next scheduled time.


3. Scope IDs

Scope IDs identify the securable object. Format: "objectType:path".

Scope Format Example
Root web web:/ "web:/"
Sub-web web:/subweb "web:/ProjectA"
List list:/Lists/TasksPath "list:/Lists/Tasks"
Item item:/Lists/Tasks/1 "item:/Lists/Tasks/42"

4. CesiviUser Registry

Every user who authenticates gets a CesiviUser entry in the site-collection-scoped registry. Fields include:

Field Description
Id Unique integer ID (same as SPUser.Id)
LoginName Windows/claims login name
DisplayName Display name
IsActive Soft-delete flag
LastLogin Timestamp of last login
LastRecalculated Timestamp of last IDP group refresh

The registry is populated at startup by DefaultDataInitializer.MigrateExistingDataToAclSystemAsync() and updated on every login.


5. SP API Compatibility

API Behavior
CSOM GetEffectivePermissionsAsync Returns effective bitmask (Allow & ~Deny)
REST /_api/web/effectiveBasePermissions Returns effective bitmask
REST role assignments Only Allow entries shown
SOAP GetPermissionCollection Only Allow entries shown
/_api/cesivi/permissions/ Full Deny ACE management

Deny ACEs are invisible to SP-compatible clients — existing integrations are unaffected.