/**************************************************************************************************** Related Identities #2 */ public IEnumerable <int> GetRelatedIdentities(SecurityContext context, int entityId, PermissionLevel level, IEnumerable <PermissionTypeBase> permissionTypes) { _entityManager.EnterReadLock(); try { var identities = new List <int>(); var mask = PermissionTypeBase.GetPermissionMask(permissionTypes); var root = _entityManager.GetEntitySafe(entityId, true); foreach (var entity in new EntityTreeWalker(root)) { // step forward if there is no any setting if (!entity.HasExplicitAcl) { continue; } // if broken, adding existing parent-s effective identities because all identities are related. if (!entity.IsInherited && entity.Parent != null) { CollectIdentitiesFromAces(context.Evaluator.GetEffectiveEntriesSafe(entity.Parent.Id, null, EntryType.Normal), level, mask, identities); } // adding explicit identities CollectIdentitiesFromAces(context.Evaluator.GetExplicitEntriesSafe(entity.Id, null, EntryType.Normal), level, mask, identities); } return(identities); } finally { _entityManager.ExitReadLock(); } }
internal PermissionValue GetPermissionSafe(int userId, int entityId, int ownerId, EntryType?entryType, params PermissionTypeBase[] permissions) { if (userId == Configuration.Identities.SystemUserId) { return(PermissionValue.Allowed); } //==> var identities = GetIdentities(userId, ownerId, entityId); var allow = 0ul; var deny = 0ul; var firstAcl = SecurityEntity.GetFirstAclSafe(_securityContext, entityId, true); if (firstAcl == null) { return(PermissionValue.Undefined); } if (entryType == null) { if (entityId == firstAcl.EntityId) { firstAcl.AggregateLocalOnlyValues(identities, ref allow, ref deny); } for (var aclInfo = firstAcl; aclInfo != null; aclInfo = aclInfo.Inherits ? aclInfo.Parent : null) { aclInfo.AggregateEffectiveValues(identities, ref allow, ref deny); } } else { if (entityId == firstAcl.EntityId) { firstAcl.AggregateLocalOnlyValues(identities, entryType.Value, ref allow, ref deny); } for (var aclInfo = firstAcl; aclInfo != null; aclInfo = aclInfo.Inherits ? aclInfo.Parent : null) { aclInfo.AggregateEffectiveValues(identities, entryType.Value, ref allow, ref deny); } } //==< var mask = PermissionTypeBase.GetPermissionMask(permissions); if ((deny & mask) != 0) { return(PermissionValue.Denied); } if ((allow & mask) != mask) { return(PermissionValue.Undefined); } return(PermissionValue.Allowed); }
/********************************************************************************************************* Related Entities */ public static IEnumerable <int> GetRelatedEntities(SecurityContext context, int entityId, PermissionLevel level, bool explicitOnly, int identityId, IEnumerable <PermissionTypeBase> permissionTypes) { if (!explicitOnly) { throw new NotSupportedException("Not supported in this version. Use explicitOnly = true"); } SecurityEntity.EnterReadLock(); try { var entityIds = new List <int>(); var mask = PermissionTypeBase.GetPermissionMask(permissionTypes); var identities = new[] { identityId }; var root = SecurityEntity.GetEntitySafe(context, entityId, true); foreach (var entity in new EntityTreeWalker(root)) { // step forward if there is no any setting if (!entity.HasExplicitAcl) { continue; } var added = false; if (!entity.IsInherited && entity.Parent != null) { if (HasBitsByEffectiveAces(context.Evaluator.GetEffectiveEntriesSafe(entity.Parent.Id, identities), level, mask)) { entityIds.Add(entity.Id); added = true; } } // adding explicite identities if (!added) { if (HasBitsByExpliciteAces(context.Evaluator.GetExplicitEntriesSafe(entity.Id, identities), level, mask)) { entityIds.Add(entity.Id); } } } return(entityIds); } finally { SecurityEntity.ExitReadLock(); } }
/********************************************************************************************* Related Entities one level#2 */ public static IEnumerable <int> GetRelatedEntitiesOneLevel(SecurityContext context, int entityId, PermissionLevel level, int identityId, IEnumerable <PermissionTypeBase> permissionTypes) { SecurityEntity.EnterReadLock(); try { var result = new List <int>(); var identities = new[] { identityId }; var mask = PermissionTypeBase.GetPermissionMask(permissionTypes); var root = SecurityEntity.GetEntitySafe(context, entityId, true); foreach (var childEntity in root.Children) { var aces = context.Evaluator.GetEffectiveEntriesSafe(childEntity.Id, identities); if (aces.Any(a => HasBits(a.AllowBits, a.DenyBits, level, mask))) { result.Add(childEntity.Id); } } return(result); } finally { SecurityEntity.ExitReadLock(); } }
internal PermissionValue GetSubtreePermission(int userId, int entityId, int ownerId, params PermissionTypeBase[] permissions) { if (userId == Configuration.Identities.SystemUserId) { return(PermissionValue.Allowed); } var identities = GetIdentities(userId, ownerId, entityId); SecurityEntity.EnterReadLock(); try { var entity = SecurityEntity.GetEntitySafe(_securityContext, entityId, true); var firstAcl = SecurityEntity.GetFirstAclSafe(_securityContext, entityId, true); //======== #1: startbits: getpermbits //==> var allow = 0ul; var deny = 0ul; if (entityId == firstAcl.EntityId) { firstAcl.AggregateLocalOnlyValues(identities, ref allow, ref deny); } for (var permInfo = firstAcl; permInfo != null; permInfo = permInfo.Inherits ? permInfo.Parent : null) { permInfo.AggregateEffectiveValues(identities, ref allow, ref deny); } //==< var mask = PermissionTypeBase.GetPermissionMask(permissions); if ((deny & mask) != 0) { return(PermissionValue.Denied); } if ((allow & mask) != mask) { return(PermissionValue.Undefined); } // doesn't depend from the value of the entity's Inherits (need to evaluate through the breaks) // doesn't depend from the value of the LocalOnly (need to evaluate any entry) foreach (var descendantEntity in new EntityTreeWalker(entity)) { // if nearest holder is different, this entity is irrelevant (there is no entry to evaluate) if (!descendantEntity.HasExplicitAcl) { continue; } // only this level is sufficient to evaluate because any difference from "allow" causes exit instantly // filtered by relevant identities AceInfo[] relevantAces; try { relevantAces = GetExplicitEntriesSafe(descendantEntity.Id, identities).ToArray(); } catch (EntityNotFoundException) // catch only: well known exception { // do nothing because entity was deleted continue; } // different evaluation that depends on the inheritance continuity if (descendantEntity.IsInherited) { // if inherited, only denied bits play foreach (var ace in relevantAces) { deny |= ace.DenyBits; } if ((deny & mask) != 0uL) { return(PermissionValue.Denied); } } else { // if breaked, need to recalculate allow and deny bits too. allow = 0ul; deny = 0ul; var hasLocalOnly = false; // on this level need to explicit "allow" foreach (var ace in relevantAces) { allow |= ace.AllowBits; deny |= ace.DenyBits; hasLocalOnly |= ace.LocalOnly; } // return if inadequate if ((deny & mask) != 0) { return(PermissionValue.Denied); } if ((allow & mask) != mask) { return(PermissionValue.Undefined); } // if there is any local only entry, the children decide to exit or move forward. if (hasLocalOnly) { // move forward if the entity is a leaf (children is null) if (descendantEntity.Children != null) { foreach (var childEntity in descendantEntity.Children) { var value = GetPermissionSafe(userId, childEntity.Id, childEntity.OwnerId, permissions); // return if not allowed if (value != PermissionValue.Allowed) { return(value); } // move forward } } } } // walk forward on the tree } } finally { SecurityEntity.ExitReadLock(); } return(PermissionValue.Allowed); }