Example #1
0
        public async Task <HalResourceInspectedContext> OnResourceInspectionAsync(
            HalResourceInspectingContext context,
            HalResourceInspectionDelegate next)
        {
            var inspectedContext = await next();

            if (inspectedContext.Resource?.Links == null)
            {
                return(inspectedContext);
            }

            var httpContext    = context.ActionContext.HttpContext;
            var requestFeature = httpContext.Features.Get <IHttpRequestFeature>();
            var links          = inspectedContext.Resource.Links.ToList();

            foreach (var link in links)
            {
                // TODO: Account for external links.
                var halRequestFeature = new HalHttpRequestFeature(requestFeature)
                {
                    Method = "GET",
                    Path   = link.HRef
                };

                var linkContext = new LinkValidationHttpContext(httpContext, halRequestFeature);

                // Invoke the mvc pipeline. The LinkValidationFilter will short circuit
                // the request after the authorization filters have executed.
                await context.MvcPipeline.Pipeline(linkContext);

                var response = linkContext.Response as HalHttpResponse;
                if (response.Resource == LinkValidatedResult.LinkValidatedObject)
                {
                    logger.LogDebug("Client has permissions to access link '{0}'.", link);
                }
                else
                {
                    logger.LogDebug("Client does not have permission to access link '{0}'. Removing link from resource.", link);
                    inspectedContext.Resource.Links.Remove(link);
                }
            }

            return(inspectedContext);
        }
Example #2
0
        public async Task <HalResourceInspectedContext> OnResourceInspectionAsync(
            HalResourceInspectingContext context,
            HalResourceInspectionDelegate next)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            if (next == null)
            {
                throw new ArgumentNullException(nameof(next));
            }

            if (!context.IsRootResource)
            {
                throw new NotSupportedException("This inspector does not support embedded resources.");
            }

            if (context.Resource == null)
            {
                return(await next());
            }

            if (context.ActionContext == null)
            {
                throw new ArgumentException("ActionContext cannot be null.", nameof(context));
            }

            if (!(context.ActionContext.ActionDescriptor is ControllerActionDescriptor descriptor))
            {
                throw new HalException("Could not establish ControllerActionDescriptor reference.");
            }

            if (context.ActionContext.HttpContext == null || context.ActionContext.HttpContext.Features == null)
            {
                throw new ArgumentException("HttpContext features cannot be null.", nameof(context));
            }

            if (context.MvcPipeline == null)
            {
                throw new ArgumentException("Context does not contain the mvc pipeline.", nameof(context));
            }

            var requestFeature = context.ActionContext.HttpContext.Features.Get <IHttpRequestFeature>();
            var links          = linkService.GetLinks <HalEmbedAttribute>(descriptor, context.ActionContext, context.OriginalObject);

            foreach (var link in links)
            {
                var halRequestFeature = new HalHttpRequestFeature(requestFeature)
                {
                    Method = "GET",
                    Path   = link.Uri
                };

                var halContext = new HalHttpContext(context.ActionContext.HttpContext, halRequestFeature);

                logger.LogDebug("About to invoke MVC pipeline with a GET request on path '{0}'.", link.Uri);
                await context.MvcPipeline.Pipeline(halContext);

                var response = halContext.Response as HalHttpResponse;
                if (response.StatusCode >= 200 && response.StatusCode <= 299)
                {
                    logger.LogDebug("MVC pipeline returned success status code {0}. Invoking HAL resource factory.", response.StatusCode);
                    IResource embedded = await context.EmbeddedResourcePipeline(response.ActionContext, response.Resource);

                    embedded.Rel = link.Rel;

                    if (embedded is IResourceCollection collection)
                    {
                        if (collection.Collection != null)
                        {
                            logger.LogDebug("Embedding collection of {0} resources to rel '{0}'", collection.Collection.Count, link.Rel);
                            foreach (var item in collection.Collection)
                            {
                                item.Rel = link.Rel;
                                context.Resource.Embedded.Add(item);
                            }
                        }
                    }
                    else
                    {
                        logger.LogDebug("Embedding resource to rel '{0}'", link.Rel);
                        context.Resource.Embedded.Add(embedded);
                    }
                }
                else
                {
                    logger.LogWarning("MVC pipeline returned non-success status code {0}. Ignoring result.", response.StatusCode);
                }
            }

            var result = await next();

            logger.LogTrace("After invoke next.");

            return(result);
        }