예제 #1
0
        /// <summary>
        /// Determine the complete list of types reachable as a consequence of a starting group of types.
        /// </summary>
        /// <remarks>
        /// Provide a single shared implementation that is used either at type-level checks, as well as in diagnostic checks to ensure fidelity of result.
        /// </remarks>
        /// <param name="initialTypes">The types to start searching from.</param>
        /// <param name="ancestorsOnlyOnFirst"></param>
        /// <param name="getTargets">
        /// False to follow relationships in reverse to potential sources of grants.
        /// True to follow relationships in forward to target types that receive grants.
        /// </param>
        /// <returns></returns>
        public static IEnumerable <WalkStep <Tuple <Relationship, Direction, EntityType, EntityType> > > ReachableTypes(IEnumerable <EntityType> initialTypes)
        {
            var entityComparer = new EntityIdEqualityComparer <EntityType>( );
            var tupleComparer  = new CastingComparer <Tuple <Relationship, Direction, EntityType, EntityType>, EntityType>(t => t.Item3, entityComparer);

            return(Delegates.WalkGraphWithSteps(
                       initialTypes.Select(et => new Tuple <Relationship, Direction, EntityType, EntityType>(null, Direction.Forward, et, null)),
                       tuple =>
            {
                EntityType et = tuple.Item3;
                var securingRelationships = GetSecuredRelationships(et, false, false); // hmm .. this should probably pass true

                return securingRelationships;                                          // Item3 = the next entityType
            },
                       tupleComparer
                       ));
        }
예제 #2
0
        /// <summary>
        /// Get all securing relationships.
        /// </summary>
        /// <param name="entityType">
        /// The <see cref="EntityType"/> to check. This cannot be null.
        /// </param>
        /// <param name="ancestorsOnly">
        /// True if only ancestores are included, false if all possible types are checked.
        /// </param>
        /// <param name="isModifyPermission">
        /// If true, only consider relationships that should be traversed in modify & delete scenarios.
        /// </param>
        /// <param name="getTargets">
        /// False to follow relationships in reverse to potential sources of grants.
        /// True to follow relationships in forward to target types that receive grants.
        /// </param>
        /// <returns>
        /// The relationships with the secures to or from flags set.
        /// </returns>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="entityType"/> cannot be null.
        /// </exception>
        public static IList <Tuple <Relationship, Direction, EntityType, object> > GetSecuringRelationships(
            this EntityType entityType, bool ancestorsOnly, bool isModifyPermission, bool getTargets = false)
        {
            if (entityType == null)
            {
                throw new ArgumentNullException("entityType");
            }

            IList <EntityType> entityTypes;
            IEqualityComparer <Relationship> relationshipEqualityComparer;
            IList <Tuple <Relationship, Direction, EntityType, object> > forwardRelationships;
            IList <Tuple <Relationship, Direction, EntityType, object> > reverseRelationships;

            relationshipEqualityComparer = new EntityIdEqualityComparer <Relationship>();
            if (ancestorsOnly)
            {
                entityTypes = entityType.GetAncestorsAndSelf()
                              .ToList();
            }
            else
            {
                entityTypes = entityType.GetDescendantsAndSelf()
                              .SelectMany(et => et.GetAncestorsAndSelf())
                              .Distinct(new EntityIdEqualityComparer <EntityType>())
                              .ToList();
            }

            bool isOnlyReadPerm = !isModifyPermission;



            forwardRelationships = entityTypes.SelectMany(et2 => getTargets ? et2.ReverseRelationships : et2.Relationships)
                                   .Distinct(relationshipEqualityComparer)
                                   .Where(r => (r.SecuresFrom == true) && (isOnlyReadPerm || r.SecuresFromReadOnly != true) && (r.ToType != null))
                                   .Select(r => new Tuple <Relationship, Direction, EntityType, object>(r, Direction.Forward, r.ToType, null))
                                   .ToList();
            reverseRelationships = entityTypes.SelectMany(et2 => getTargets ? et2.Relationships : et2.ReverseRelationships)
                                   .Distinct(relationshipEqualityComparer)
                                   .Where(r => (r.SecuresTo == true) && (isOnlyReadPerm || r.SecuresToReadOnly != true) && (r.FromType != null))
                                   .Select(r => new Tuple <Relationship, Direction, EntityType, object>(r, Direction.Reverse, r.FromType, null))
                                   .ToList();

            return(forwardRelationships.Union(reverseRelationships).ToList());
        }
        /// <summary>
        /// Build an <see cref="EntityMemberRequest"/> used to look for entities
        /// to perform additional security checks on.
        /// </summary>
        /// <param name="entityType">The type of entity whose security is being checked.</param>
        /// <param name="permissions">The type of permissions required.</param>
        /// <returns>The <see cref="EntityMemberRequest"/></returns>
        public EntityMemberRequest BuildEntityMemberRequest(EntityType entityType, IList <EntityRef> permissions)
        {
            if (entityType == null)
            {
                throw new ArgumentNullException(nameof(entityType));
            }

            // Should we be following all security relationships, or only ones that convey modify perms.
            bool isModify = false;

            if (permissions != null)
            {
                foreach (EntityRef perm in permissions)
                {
                    if (perm.Id == Permissions.Modify.Id || perm.Id == Permissions.Delete.Id)
                    {
                        isModify = true;
                        break;
                    }
                }
            }

            // Create context
            FactoryContext context = new FactoryContext
            {
                IsModify    = isModify,
                InitialType = entityType
            };

            // Walk graph
            IEqualityComparer <EntityType> comparer = new EntityIdEqualityComparer <EntityType>( );

            Delegates.WalkGraph(entityType, node => VisitNode(node, context), null, comparer).VisitAll( );

            // Register cache invalidations
            using (CacheContext cacheContext = CacheContext.GetContext( ))
            {
                cacheContext.EntityTypes.Add(WellKnownAliases.CurrentTenant.Relationship);
                cacheContext.FieldTypes.Add(WellKnownAliases.CurrentTenant.SecuresFrom, WellKnownAliases.CurrentTenant.SecuresTo, WellKnownAliases.CurrentTenant.SecuresFromReadOnly, WellKnownAliases.CurrentTenant.SecuresToReadOnly);
            }

            return(context.Result);
        }
예제 #4
0
        /// <summary>
        /// Get all securing relationships.
        /// </summary>
        /// <param name="entityType">
        /// The <see cref="EntityType"/> to check. This cannot be null.
        /// </param>
        /// <param name="ancestorsOnly">
        /// True if only ancestores are included, false if all possible types are checked.
        /// </param>
        /// <param name="isModifyPermission">
        /// If true, only consider relationships that should be traversed in modify & delete scenarios.
        /// </param>
        /// <param name="getTargets">
        /// False to follow relationships in reverse to potential sources of grants.
        /// True to follow relationships in forward to target types that receive grants.
        /// </param>
        /// <returns>
        /// The relationships with the secures to or from flags set.
        /// </returns>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="entityType"/> cannot be null.
        /// </exception>
        private static IList <Tuple <Relationship, Direction, EntityType, EntityType> > GetSecuredRelationships(
            EntityType entityType, bool ancestorsOnly, bool isModifyPermission)
        {
            if (entityType == null)
            {
                throw new ArgumentNullException("entityType");
            }

            IList <EntityType> entityTypes;
            IEqualityComparer <Relationship> relationshipEqualityComparer;
            IList <Tuple <Relationship, Direction, EntityType, EntityType> > forwardRelationships;
            IList <Tuple <Relationship, Direction, EntityType, EntityType> > reverseRelationships;

            relationshipEqualityComparer = new EntityIdEqualityComparer <Relationship>( );
            if (ancestorsOnly)
            {
                entityTypes = entityType.GetAncestorsAndSelf( )
                              .ToList( );
            }
            else
            {
                entityTypes = entityType.GetAllMemberContributors( )
                              .ToList( );
            }

            bool isOnlyReadPerm = !isModifyPermission;



            forwardRelationships = entityTypes.SelectMany(et2 => et2.ReverseRelationships)
                                   .Distinct(relationshipEqualityComparer)
                                   .Where(r => (r.SecuresFrom == true) && (isOnlyReadPerm || r.SecuresFromReadOnly != true) && (r.ToType != null))
                                   .Select(r => new Tuple <Relationship, Direction, EntityType, EntityType>(r, Direction.Forward, r.FromType, entityType))
                                   .ToList( );
            reverseRelationships = entityTypes.SelectMany(et2 => et2.Relationships)
                                   .Distinct(relationshipEqualityComparer)
                                   .Where(r => (r.SecuresTo == true) && (isOnlyReadPerm || r.SecuresToReadOnly != true) && (r.FromType != null))
                                   .Select(r => new Tuple <Relationship, Direction, EntityType, EntityType>(r, Direction.Reverse, r.ToType, entityType))
                                   .ToList( );

            return(forwardRelationships.Union(reverseRelationships).ToList( ));
        }