// Populates index.html template and serves it
        private static async Task <ContentResult> ReturnIndexHtml(ExecutionContext context, ILogger log, string root, string connAndHubName)
        {
            string indexHtmlPath = Path.Join(root, "index.html");
            string html          = await File.ReadAllTextAsync(indexHtmlPath);

            // Replacing our custom meta tag with customized code from Storage or with default Content Security Policy
            string customMetaTagCode = (await CustomTemplates.GetCustomMetaTagCodeAsync()) ?? DefaultContentSecurityPolicyMeta;

            html = html.Replace("<meta name=\"durable-functions-monitor-meta\">", customMetaTagCode);

            // Calculating routePrefix
            string routePrefix    = GetRoutePrefixFromHostJson(context, log);
            string dfmRoutePrefix = GetDfmRoutePrefixFromFunctionJson(context, log);

            if (!string.IsNullOrEmpty(dfmRoutePrefix))
            {
                routePrefix = string.IsNullOrEmpty(routePrefix) ? dfmRoutePrefix : routePrefix + "/" + dfmRoutePrefix;
            }

            // Applying routePrefix, if it is set to something other than empty string
            if (!string.IsNullOrEmpty(routePrefix))
            {
                html = html.Replace("<script>var DfmRoutePrefix=\"\"</script>", $"<script>var DfmRoutePrefix=\"{routePrefix}\"</script>");
                html = html.Replace("href=\"/", $"href=\"/{routePrefix}/");
                html = html.Replace("src=\"/", $"src=\"/{routePrefix}/");
            }

            // Applying client config, if any
            string clientConfigString = Environment.GetEnvironmentVariable(EnvVariableNames.DFM_CLIENT_CONFIG);

            if (!string.IsNullOrEmpty(clientConfigString))
            {
                dynamic clientConfig = JObject.Parse(clientConfigString);
                html = html.Replace("<script>var DfmClientConfig={}</script>", "<script>var DfmClientConfig=" + clientConfig.ToString() + "</script>");
            }

            // Mentioning whether Function Map is available for this Task Hub.
            if (!string.IsNullOrEmpty(connAndHubName))
            {
                // Two bugs away. Validating that the incoming Task Hub name looks like a Task Hub name
                Auth.ThrowIfTaskHubNameHasInvalidSymbols(connAndHubName);

                Globals.SplitConnNameAndHubName(connAndHubName, out var connName, out var hubName);

                string functionMap = (await CustomTemplates.GetFunctionMapsAsync()).GetFunctionMap(hubName);
                if (!string.IsNullOrEmpty(functionMap))
                {
                    html = html.Replace("<script>var IsFunctionGraphAvailable=0</script>", "<script>var IsFunctionGraphAvailable=1</script>");
                }
            }

            return(new ContentResult()
            {
                Content = html,
                ContentType = "text/html; charset=UTF-8"
            });
        }
        public static async Task <IActionResult> DfmGetOrchestrationTabMarkupFunction(
            [HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = Globals.ApiRoutePrefix + "/orchestrations('{instanceId}')/custom-tab-markup('{templateName}')")] HttpRequest req,
            string instanceId,
            string templateName,
            [DurableClient(TaskHub = Globals.TaskHubRouteParamName)] IDurableClient durableClient,
            ILogger log)
        {
            // Checking that the call is authenticated properly
            try
            {
                await Auth.ValidateIdentityAsync(req.HttpContext.User, req.Headers, durableClient.TaskHubName);
            }
            catch (Exception ex)
            {
                log.LogError(ex, "Failed to authenticate request");
                return(new UnauthorizedResult());
            }

            var status = await GetInstanceStatus(instanceId, durableClient, log);

            if (status == null)
            {
                return(new NotFoundObjectResult($"Instance {instanceId} doesn't exist"));
            }

            // The underlying Task never throws, so it's OK.
            var templatesMap = await CustomTemplates.GetTabTemplatesAsync();

            string templateCode = templatesMap.GetTemplate(status.GetEntityTypeName(), templateName);

            if (templateCode == null)
            {
                return(new NotFoundObjectResult("The specified template doesn't exist"));
            }

            try
            {
                var fluidTemplate = FluidTemplate.Parse(templateCode);
                var fluidContext  = new TemplateContext(status);

                return(new ContentResult()
                {
                    Content = fluidTemplate.Render(fluidContext),
                    ContentType = "text/html; charset=UTF-8"
                });
            }
            catch (Exception ex)
            {
                return(new BadRequestObjectResult(ex.Message));
            }
        }
        public Task <IActionResult> DfmGetOrchestrationTabMarkupFunction(
            [HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = Globals.ApiRoutePrefix + "/orchestrations('{instanceId}')/custom-tab-markup('{templateName}')")] HttpRequest req,
            [DurableClient(TaskHub = Globals.HubNameRouteParamName)] IDurableClient defaultDurableClient,
            string connName,
            string hubName,
            string instanceId,
            string templateName,
            ILogger log)
        {
            return(this.HandleAuthAndErrors(defaultDurableClient, req, connName, hubName, log, async(durableClient) => {
                var status = await GetInstanceStatusWithHistory(connName, instanceId, durableClient, log);
                if (status == null)
                {
                    return new NotFoundObjectResult($"Instance {instanceId} doesn't exist");
                }

                // The underlying Task never throws, so it's OK.
                var templatesMap = await CustomTemplates.GetTabTemplatesAsync();

                string templateCode = templatesMap.GetTemplate(status.GetEntityTypeName(), templateName);
                if (templateCode == null)
                {
                    return new NotFoundObjectResult("The specified template doesn't exist");
                }

                try
                {
                    var fluidTemplate = new FluidParser().Parse(templateCode);

                    var options = new TemplateOptions();
                    options.MemberAccessStrategy.Register <JObject, object>((obj, fieldName) => obj[fieldName]);
                    options.ValueConverters.Add(x => x is JObject obj ? new ObjectValue(obj) : null);
                    options.ValueConverters.Add(x => x is JValue val ? val.Value : null);

                    string fluidResult = fluidTemplate.Render(new TemplateContext(status, options));

                    return new ContentResult()
                    {
                        Content = fluidResult,
                        ContentType = "text/html; charset=UTF-8"
                    };
                }
                catch (Exception ex)
                {
                    return new BadRequestObjectResult(ex.Message);
                }
            }));
        }
        public static Task <IActionResult> DfmGetFunctionMap(
            [HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = Globals.ApiRoutePrefix + "/function-map")] HttpRequest req,
            string connName,
            string hubName,
            ILogger log
            )
        {
            return(req.HandleAuthAndErrors(connName, hubName, log, async() => {
                // The underlying Task never throws, so it's OK.
                var functionMapsMap = await CustomTemplates.GetFunctionMapsAsync();

                var functionMapJson = functionMapsMap.GetFunctionMap(hubName);
                if (string.IsNullOrEmpty(functionMapJson))
                {
                    return new NotFoundObjectResult("No Function Map provided");
                }

                return new ContentResult()
                {
                    Content = functionMapJson,
                    ContentType = "application/json; charset=UTF-8"
                };
            }));
        }
Esempio n. 5
0
        public static async Task <IActionResult> DfmServeStaticsFunction(
            [HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = StaticsRoute)] HttpRequest req,
            ExecutionContext context,
            ILogger log
            )
        {
            string root = context.FunctionAppDirectory + "/DfmStatics";
            string path = req.Path.Value;

            string routePrefix    = GetRoutePrefixFromHostJson(context, log);
            string dfmRoutePrefix = GetDfmRoutePrefixFromFunctionJson(context, log);

            if (!string.IsNullOrEmpty(dfmRoutePrefix))
            {
                routePrefix = string.IsNullOrEmpty(routePrefix) ? dfmRoutePrefix : routePrefix + "/" + dfmRoutePrefix;
            }

            // Applying routePrefix, if it is set to something other than empty string
            if (!string.IsNullOrEmpty(routePrefix) && path.StartsWith("/" + routePrefix))
            {
                path = path.Substring(routePrefix.Length + 1);
            }

            var contentType = FileMap.FirstOrDefault((kv => path.StartsWith(kv[0])));

            if (contentType != null)
            {
                return(File.Exists(root + path) ?
                       (IActionResult) new FileStreamResult(File.OpenRead(root + path), contentType[1]) :
                       new NotFoundResult());
            }

            // Returning index.html by default, to support client routing
            string html = await File.ReadAllTextAsync($"{root}/index.html");

            // Replacing our custom meta tag with customized code from Storage or with default Content Security Policy
            string customMetaTagCode = (await CustomTemplates.GetCustomMetaTagCodeAsync()) ?? DefaultContentSecurityPolicyMeta;

            html = html.Replace(Globals.CustomMetaTag, customMetaTagCode);

            // Applying routePrefix, if it is set to something other than empty string
            if (!string.IsNullOrEmpty(routePrefix))
            {
                html = html.Replace("<script>var DfmRoutePrefix=\"\"</script>", $"<script>var DfmRoutePrefix=\"{routePrefix}\"</script>");
                html = html.Replace("href=\"/", $"href=\"/{routePrefix}/");
                html = html.Replace("src=\"/", $"src=\"/{routePrefix}/");
            }

            // Applying client config, if any
            string clientConfigString = Environment.GetEnvironmentVariable(EnvVariableNames.DFM_CLIENT_CONFIG);

            if (!string.IsNullOrEmpty(clientConfigString))
            {
                dynamic clientConfig = JObject.Parse(clientConfigString);
                html = html.Replace("<script>var DfmClientConfig={}</script>", "<script>var DfmClientConfig=" + clientConfig.ToString() + "</script>");
            }

            return(new ContentResult()
            {
                Content = html,
                ContentType = "text/html; charset=UTF-8"
            });
        }