RoleAccessResolver

Pure (side-effect free) builder of UserRoleAccess from the server-granted per-property roles plus the access-locked property list. Kept separate from AuthenticationManager and MapstedCoreApi so the same policy is shared by both producer trigger points (online login + init/offline-from-cache) and is independently unit-testable.

Policy:

  • The auth userRoleId ("accessRoleId" in the login response) is NOT the accessLevelId the engine matches via EntityUtils.hasAccess(Entity, accessLevelId) — the engine keys on the CMS accessRestrictionId. A UserRolesSource resolves one to the other; until the backend resolution endpoint deploys, the interim IdentityUserRolesSource passes the userRoleId through unchanged (safe: the engine resolves unknown non-empty ids to the property's DEFAULT restrictions, so passthrough cannot over-grant — but it is unenforcing).
  • An empty/absent role for a property means "property default" — the engine resolves "" to the property's DEFAULT access-level restrictions, NOT deny (and a property with no default access config allows; see getActiveAccessLevelId returning ""). So we publish no entry for such an unlocked property and let the default apply.
  • A property in propertiesWithLock for which the user has NO granted role gets the fail-closed sentinel NO_ACCESS_SENTINEL — an accessLevelId the engine does not know. The engine resolves an unknown non-empty accessLevelId to the property's DEFAULT access-level restrictions (fail-closed-to-default — not deny-all, not allow-all), so the sentinel strips any elevated grant down to default-level access; it cannot over-grant.

Properties

Link copied to clipboard
val NO_ACCESS_SENTINEL: String = "__no_access__"
Fail-closed accessLevelId for a locked property the user has no role for.

Functions

Link copied to clipboard
open fun fromGrantedRoles(@Nullable accessRoleIds: Map<Integer, String>, @Nullable propertiesWithLock: List<Integer>): UserRoleAccess
Unresolved convenience overload of fromGrantedRoles: no resolution map, so every granted userRoleId passes through unchanged as the accessLevelId — the safe interim passthrough (the engine resolves an unknown non-empty accessLevelId to the property's DEFAULT restrictions, so it cannot over-grant).
open fun fromGrantedRoles(@Nullable userRoleIds: Map<Integer, String>, @Nullable resolvedAccessRestrictionIds: Map<Integer, String>, @Nullable propertiesWithLock: List<Integer>): UserRoleAccess
Build the published UserRoleAccess from the server-granted roles, the UserRolesSource-resolved access ids, and the access-locked property list.
Link copied to clipboard
Per-property restrictive merge of a cached role access against a computed property-default access.