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:
- Explicit Deny (at this scope) — always wins
- Explicit Allow (at this scope) — wins if no Deny
- Inherited Deny (from parent scope) — wins if no explicit entry
- 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.