/******************************************************************************************************* Related Identities */

        public static IEnumerable <int> GetRelatedIdentities(SecurityContext context, int entityId, PermissionLevel level)
        {
            var identities = new List <int>();

            SecurityEntity.EnterReadLock();
            try
            {
                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;
                    }

                    // if breaked, adding existing parent-s effective identities because all identities are related.
                    if (!entity.IsInherited && entity.Parent != null)
                    {
                        CollectIdentitiesFromAces(context.Evaluator.GetEffectiveEntriesSafe(entity.Parent.Id), level, identities);
                    }

                    // adding explicite identities
                    CollectIdentitiesFromAces(context.Evaluator.GetExplicitEntriesSafe(entity.Id), level, identities);
                }
            }
            finally
            {
                SecurityEntity.ExitReadLock();
            }
            return(identities);
        }
Exemple #2
0
 internal List <AceInfo> GetEffectiveEntries(int entityId, IEnumerable <int> relatedIdentities = null, EntryType?entryType = null)
 {
     SecurityEntity.EnterReadLock();
     try
     {
         return(GetEffectiveEntriesSafe(entityId, relatedIdentities, entryType));
     }
     finally
     {
         SecurityEntity.ExitReadLock();
     }
 }
        /****************************************************************************************************** Related Permissions */

        public static Dictionary <PermissionTypeBase, int> GetRelatedPermissions(SecurityContext context, int entityId, PermissionLevel level, bool explicitOnly, int identityId, Func <int, bool> isEnabled)
        {
            if (!explicitOnly)
            {
                throw new NotSupportedException("Not supported in this version. Use explicitOnly = true");
            }

            SecurityEntity.EnterReadLock();
            try
            {
                var counters = new int[PermissionTypeBase.PermissionCount];

                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;
                    }

                    if (!isEnabled(entity.Id))
                    {
                        continue;
                    }

                    // if breaked, adding existing parent-s effective identities because all identities are related.
                    var localBits = new PermissionBitMask();
                    if (!entity.IsInherited && entity.Parent != null)
                    {
                        CollectPermissionsFromLocalAces(context.Evaluator.GetEffectiveEntriesSafe(entity.Parent.Id, identities), localBits);
                    }

                    // adding explicite identities
                    CollectPermissionsFromAces(context.Evaluator.GetExplicitEntriesSafe(entity.Id, identities), level, counters, localBits);
                }

                var result = new Dictionary <PermissionTypeBase, int>();
                for (var i = 0; i < PermissionTypeBase.PermissionCount; i++)
                {
                    result.Add(PermissionTypeBase.GetPermissionTypeByIndex(i), counters[i]);
                }

                return(result);
            }
            finally
            {
                SecurityEntity.ExitReadLock();
            }
        }
        /********************************************************************************************************* 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();
            }
        }
Exemple #5
0
        internal PermissionValue GetPermission(int userId, int entityId, int ownerId, EntryType?entryType, params PermissionTypeBase[] permissions)
        {
            if (userId == Configuration.Identities.SystemUserId)
            {
                return(PermissionValue.Allowed);
            }

            SecurityEntity.EnterReadLock();
            try
            {
                return(GetPermissionSafe(userId, entityId, ownerId, entryType, permissions));
            }
            finally
            {
                SecurityEntity.ExitReadLock();
            }
        }
        public static Dictionary <PermissionTypeBase, int> GetExplicitPermissionsInSubtree(SecurityContext context, int entityId, int[] identities, bool includeRoot)
        {
            SecurityEntity.EnterReadLock();
            try
            {
                var counters = new int[PermissionTypeBase.PermissionCount];

                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 || (entity.Id == entityId && !includeRoot))
                    {
                        continue;
                    }

                    // if breaked, adding existing parent-s effective identities because all identities are related.
                    var localBits = new PermissionBitMask();
                    if (!entity.IsInherited && entity.Parent != null && (includeRoot || entity.Parent.Id != entityId))
                    {
                        CollectPermissionsFromLocalAces(context.Evaluator.GetEffectiveEntriesSafe(entity.Parent.Id, identities), localBits);
                    }

                    // adding explicite identities
                    CollectPermissionsFromAces(context.Evaluator.GetExplicitEntriesSafe(entity.Id, identities), PermissionLevel.AllowedOrDenied, counters, localBits);
                }

                var result = new Dictionary <PermissionTypeBase, int>();
                for (var i = 0; i < PermissionTypeBase.PermissionCount; i++)
                {
                    result.Add(PermissionTypeBase.GetPermissionTypeByIndex(i), counters[i]);
                }

                return(result);
            }
            finally
            {
                SecurityEntity.ExitReadLock();
            }
        }
        /// <summary>
        /// Returns all entities in the predefined axis (All, ParentChain, Subtree) of the specified entity.
        /// The collection is empty if the entity was not found.
        /// This operation is thread safe. The thread safety uses system resources, so to minimize these,
        /// it's strongly recommended processing as fast as possible.
        /// </summary>
        /// <param name="entityId">The Id of the focused entity.</param>
        /// <param name="handleBreaks">Controls the permission inheritance handling.</param>
        /// <returns>The IEnumerable&lt;SecurityEntity&gt; to further filtering.</returns>
        public IEnumerable <SecurityEntity> GetEntities(int entityId, BreakOptions handleBreaks = BreakOptions.Default)
        {
            SecurityEntity.EnterReadLock();
            try
            {
                var root = SecurityEntity.GetEntitySafe(_context, entityId, false);

                IEnumerable <SecurityEntity> collection;
                switch (_axis)
                {
                case Axis.All:
                    collection = GetEntitiesFromParentChain(root, handleBreaks)
                                 .Union(GetEntitiesFromSubtree(root, handleBreaks));
                    break;

                case Axis.ParentChain:
                    collection = GetEntitiesFromParentChain(root, handleBreaks);
                    break;

                case Axis.Subtree:
                    collection = GetEntitiesFromSubtree(root, handleBreaks);
                    break;

                default:
                    throw new ArgumentOutOfRangeException("Unknown axis: " + _axis);
                }

                foreach (var entity in collection)
                {
                    yield return(entity);
                }
            }
            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();
            }
        }
Exemple #9
0
        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);
        }