コード例 #1
0
        /// <summary>
        /// Verifies the user is authorized to submit the current <see cref="ChangeSet"/>.
        /// </summary>
        /// <returns>True if the <see cref="ChangeSet"/> is authorized, false otherwise.</returns>
        protected virtual bool AuthorizeChangeSet()
        {
            foreach (ChangeSetEntry changeSetEntry in ChangeSet.ChangeSetEntries)
            {
                if (!changeSetEntry.ActionDescriptor.Authorize(ActionContext))
                {
                    return(false);
                }

                // if there are any custom method invocations for this operation
                // we need to authorize them as well
                if (changeSetEntry.EntityActions != null && changeSetEntry.EntityActions.Any())
                {
                    Type entityType = changeSetEntry.Entity.GetType();
                    foreach (var entityAction in changeSetEntry.EntityActions)
                    {
                        UpdateActionDescriptor customAction = Description.GetCustomMethod(entityType, entityAction.Key);
                        if (!customAction.Authorize(ActionContext))
                        {
                            return(false);
                        }
                    }
                }
            }

            return(!ChangeSet.HasError);
        }
コード例 #2
0
 private static void ValidateAction(UpdateActionDescriptor updateAction)
 {
     // Only authorization filters are supported on CUD actions. This will capture 99% of user errors.
     // There is the chance that someone might attempt to implement an attribute that implements both
     // IAuthorizationFilter AND another filter type, but we don't want to have a black-list of filter
     // types here.
     if (updateAction.GetFilters().Any(p => !typeof(AuthorizationFilterAttribute).IsAssignableFrom(p.GetType())))
     {
         throw Error.NotSupported(Resource.InvalidAction_UnsupportedFilterType, updateAction.ControllerDescriptor.ControllerType.Name, updateAction.ActionName);
     }
 }
コード例 #3
0
        private void InvokeCustomUpdateOperations()
        {
            foreach (ChangeSetEntry changeSetEntry in ChangeSet.ChangeSetEntries.Where(op => op.EntityActions != null && op.EntityActions.Any()))
            {
                Type entityType = changeSetEntry.Entity.GetType();
                foreach (var entityAction in changeSetEntry.EntityActions)
                {
                    UpdateActionDescriptor customUpdateAction = Description.GetCustomMethod(entityType, entityAction.Key);

                    List <object> customMethodParams = new List <object>(entityAction.Value);
                    customMethodParams.Insert(0, changeSetEntry.Entity);

                    InvokeAction(customUpdateAction, customMethodParams.ToArray(), changeSetEntry);
                }
            }
        }
コード例 #4
0
        public override HttpActionDescriptor SelectAction(HttpControllerContext controllerContext)
        {
            // first check to see if this is a call to Submit
            string actionName;

            if (controllerContext.RouteData.Values.TryGetValue(ActionRouteKey, out actionName) && actionName.Equals(SubmitActionValue, StringComparison.Ordinal))
            {
                return(new SubmitActionDescriptor(controllerContext.ControllerDescriptor, controllerContext.Controller.GetType()));
            }

            // next check to see if this is a direct invocation of a CUD action
            DomainControllerDescription description = DomainControllerDescription.GetDescription(controllerContext.ControllerDescriptor);
            UpdateActionDescriptor      action      = description.GetUpdateAction(actionName);

            if (action != null)
            {
                return(new SubmitProxyActionDescriptor(action));
            }

            return(base.SelectAction(controllerContext));
        }
コード例 #5
0
        /// <summary>
        /// For all operations in the current changeset, validate that the operation exists, and
        /// set the operation entry.
        /// </summary>
        internal static void ResolveActions(DomainControllerDescription description, IEnumerable <ChangeSetEntry> changeSet)
        {
            // Resolve and set the action for each operation in the changeset
            foreach (ChangeSetEntry changeSetEntry in changeSet)
            {
                Type entityType = changeSetEntry.Entity.GetType();
                UpdateActionDescriptor actionDescriptor = null;
                if (changeSetEntry.Operation == ChangeOperation.Insert ||
                    changeSetEntry.Operation == ChangeOperation.Update ||
                    changeSetEntry.Operation == ChangeOperation.Delete)
                {
                    actionDescriptor = description.GetUpdateAction(entityType, changeSetEntry.Operation);
                }

                // if a custom method invocation is specified, validate that the method exists
                bool isCustomUpdate = false;
                if (changeSetEntry.EntityActions != null && changeSetEntry.EntityActions.Any())
                {
                    var entityAction = changeSetEntry.EntityActions.Single();
                    UpdateActionDescriptor customMethodOperation = description.GetCustomMethod(entityType, entityAction.Key);
                    if (customMethodOperation == null)
                    {
                        throw Error.InvalidOperation(Resource.DomainController_InvalidAction, entityAction.Key, entityType.Name);
                    }

                    // if the primary action for an update is null but the entry
                    // contains a valid custom update action, its considered a "custom update"
                    isCustomUpdate = actionDescriptor == null && customMethodOperation != null;
                }

                if (actionDescriptor == null && !isCustomUpdate)
                {
                    throw Error.InvalidOperation(Resource.DomainController_InvalidAction, changeSetEntry.Operation.ToString(), entityType.Name);
                }

                changeSetEntry.ActionDescriptor = actionDescriptor;
            }
        }
コード例 #6
0
 public SubmitProxyActionDescriptor(UpdateActionDescriptor updateAction)
     : base(updateAction.ControllerDescriptor, updateAction.ControllerDescriptor.ControllerType.GetMethod("Submit", BindingFlags.Instance | BindingFlags.Public))
 {
     _updateAction = updateAction;
 }
コード例 #7
0
        private static DomainControllerDescription CreateDescription(HttpControllerDescriptor controllerDescriptor)
        {
            Type             DomainControllerType = controllerDescriptor.ControllerType;
            MetadataProvider metadataProvider     = CreateMetadataProvider(DomainControllerType);

            // get all public candidate methods and create the operations
            HashSet <Type> entityTypes                     = new HashSet <Type>();
            List <UpdateActionDescriptor> actions          = new List <UpdateActionDescriptor>();
            IEnumerable <MethodInfo>      methodsToInspect =
                DomainControllerType.GetMethods(BindingFlags.Instance | BindingFlags.Public)
                .Where(p => (p.DeclaringType != typeof(DomainController) && (p.DeclaringType != typeof(object))) && !p.IsSpecialName);

            foreach (MethodInfo method in methodsToInspect)
            {
                if (method.GetCustomAttributes(typeof(NonActionAttribute), false).Length > 0)
                {
                    continue;
                }

                if (method.IsVirtual && method.GetBaseDefinition().DeclaringType == typeof(DomainController))
                {
                    // don't want to infer overrides of DomainController virtual methods as
                    // operations
                    continue;
                }

                // We need to ensure the buddy metadata provider is registered BEFORE we
                // attempt to do convention, since we rely on IsEntity which relies on
                // KeyAttributes being present (possibly from "buddy" classes)
                RegisterAssociatedMetadataProvider(method);

                ChangeOperation operationType = ClassifyUpdateOperation(method, metadataProvider);
                if (operationType != ChangeOperation.None)
                {
                    Type entityType = method.GetParameters()[0].ParameterType;
                    UpdateActionDescriptor actionDescriptor = new UpdateActionDescriptor(controllerDescriptor, method, entityType, operationType);
                    ValidateAction(actionDescriptor);
                    actions.Add(actionDescriptor);

                    // TODO : currently considering entity types w/o any query methods
                    // exposing them. Should we?
                    if (metadataProvider.IsEntityType(entityType))
                    {
                        AddEntityType(entityType, entityTypes, metadataProvider);
                    }
                }
                else
                {
                    // if the method is a "query" operation returning an entity,
                    // add to entity types
                    if (method.ReturnType != typeof(void))
                    {
                        Type returnType  = TypeUtility.UnwrapTaskInnerType(method.ReturnType);
                        Type elementType = TypeUtility.GetElementType(returnType);
                        if (metadataProvider.IsEntityType(elementType))
                        {
                            AddEntityType(elementType, entityTypes, metadataProvider);
                        }
                    }
                }
            }

            return(new DomainControllerDescription(DomainControllerType, entityTypes, actions));
        }
コード例 #8
0
 public SubmitProxyActionDescriptor(UpdateActionDescriptor updateAction)
     : base(updateAction.ControllerDescriptor, updateAction.ControllerDescriptor.ControllerType.GetMethod("Submit", BindingFlags.Instance | BindingFlags.Public))
 {
     _updateAction = updateAction;
 }
コード例 #9
0
 private static void ValidateAction(UpdateActionDescriptor updateAction)
 {
     // Only authorization filters are supported on CUD actions. This will capture 99% of user errors.
     // There is the chance that someone might attempt to implement an attribute that implements both
     // IAuthorizationFilter AND another filter type, but we don't want to have a black-list of filter
     // types here.
     if (updateAction.GetFilters().Any(p => !typeof(AuthorizationFilterAttribute).IsAssignableFrom(p.GetType())))
     {
         throw Error.NotSupported(Resource.InvalidAction_UnsupportedFilterType, updateAction.ControllerDescriptor.ControllerType.Name, updateAction.ActionName);
     }
 }
コード例 #10
0
        private static DomainControllerDescription CreateDescription(HttpControllerDescriptor controllerDescriptor)
        {
            Type DomainControllerType = controllerDescriptor.ControllerType;
            MetadataProvider metadataProvider = CreateMetadataProvider(DomainControllerType);

            // get all public candidate methods and create the operations
            HashSet<Type> entityTypes = new HashSet<Type>();
            List<UpdateActionDescriptor> actions = new List<UpdateActionDescriptor>();
            IEnumerable<MethodInfo> methodsToInspect =
                DomainControllerType.GetMethods(BindingFlags.Instance | BindingFlags.Public)
                    .Where(p => (p.DeclaringType != typeof(DomainController) && (p.DeclaringType != typeof(object))) && !p.IsSpecialName);

            foreach (MethodInfo method in methodsToInspect)
            {
                if (method.GetCustomAttributes(typeof(NonActionAttribute), false).Length > 0)
                {
                    continue;
                }

                if (method.IsVirtual && method.GetBaseDefinition().DeclaringType == typeof(DomainController))
                {
                    // don't want to infer overrides of DomainController virtual methods as
                    // operations
                    continue;
                }

                // We need to ensure the buddy metadata provider is registered BEFORE we
                // attempt to do convention, since we rely on IsEntity which relies on
                // KeyAttributes being present (possibly from "buddy" classes)
                RegisterAssociatedMetadataProvider(method);

                ChangeOperation operationType = ClassifyUpdateOperation(method, metadataProvider);
                if (operationType != ChangeOperation.None)
                {
                    Type entityType = method.GetParameters()[0].ParameterType;
                    UpdateActionDescriptor actionDescriptor = new UpdateActionDescriptor(controllerDescriptor, method, entityType, operationType);
                    ValidateAction(actionDescriptor);
                    actions.Add(actionDescriptor);

                    // TODO : currently considering entity types w/o any query methods
                    // exposing them. Should we?
                    if (metadataProvider.IsEntityType(entityType))
                    {
                        AddEntityType(entityType, entityTypes, metadataProvider);
                    }
                }
                else
                {
                    // if the method is a "query" operation returning an entity,
                    // add to entity types
                    if (method.ReturnType != typeof(void))
                    {
                        Type returnType = TypeUtility.UnwrapTaskInnerType(method.ReturnType);
                        Type elementType = TypeUtility.GetElementType(returnType);
                        if (metadataProvider.IsEntityType(elementType))
                        {
                            AddEntityType(elementType, entityTypes, metadataProvider);
                        }
                    }
                }
            }

            return new DomainControllerDescription(DomainControllerType, entityTypes, actions);
        }