protected async Task EnqueueCommandAsync(ICommand command)
    {
        if (command is null)
        {
            throw new ArgumentNullException(nameof(command));
        }

        try
        {
            var commandQueue = await commandQueueInstance
                               .Value
                               .ConfigureAwait(false);

            var commandMessage = TeamCloudSerialize.SerializeObject(command);

            await commandQueue
            .SendMessageAsync(commandMessage)
            .ConfigureAwait(false);
        }
        catch
        {
            commandQueueInstance.Reset();

            throw;
        }
    }
Exemple #2
0
    public async Task Serialize_WithErrorsAsync()
    {
        var command = new MockCommand(this.user, MockPayload.Instance);

        var result1 = command.CreateResult();

        result1.Errors = new List <CommandError>
        {
            await CreateFlurlHttpExceptionAsync().ConfigureAwait(false),
            new NotSupportedException()
        };

        var json1 = TeamCloudSerialize.SerializeObject(result1);

        Assert.NotEmpty(json1);
        Assert.Contains("$type", json1);

        var result2 = TeamCloudSerialize.DeserializeObject <ICommandResult>(json1);

        var json2 = TeamCloudSerialize.SerializeObject(result2);

        Assert.NotEmpty(json2);
        Assert.Contains("$type", json2);

        Assert.Equal(json1, json2);
    }
Exemple #3
0
    public void DeserializeRepository()
    {
        var repositoryReference = new RepositoryReference()
        {
            Url      = "https://github.com/foo/bar.git",
            Provider = RepositoryProvider.GitHub,
            Type     = RepositoryReferenceType.Unknown
        };

        var projectTemplate = new ProjectTemplate()
        {
            Id           = Guid.NewGuid().ToString(),
            Organization = Guid.NewGuid().ToString(),
            Repository   = repositoryReference
        };

        var componentPath = "/foo/bar/component.yaml";
        var componentJson = GetComponentDefinitionAsJson("repository");

        var componentTemplate = TeamCloudSerialize
                                .DeserializeObject <ComponentTemplate>(componentJson, new ComponentTemplateConverter(projectTemplate, componentPath));

        Assert.NotNull(componentTemplate);
        Assert.IsAssignableFrom <ComponentRepositoryTemplate>(componentTemplate);

        Assert.NotNull(componentTemplate.Configuration);
        Assert.IsAssignableFrom <ComponentRepositoryConfiguration>(componentTemplate.Configuration);
    }
    public void DeserializeProject()
    {
        var repositoryReference = new RepositoryReference()
        {
            Url      = "https://github.com/foo/bar.git",
            Provider = RepositoryProvider.GitHub,
            Type     = RepositoryReferenceType.Unknown
        };

        var projectTemplate = new ProjectTemplate()
        {
            Id           = Guid.NewGuid().ToString(),
            Organization = Guid.NewGuid().ToString(),
            DisplayName  = "Foo",
            Repository   = repositoryReference
        };

        var porjectPath = "/foo/bar/project.yaml";
        var projectJson = GetProjectDefinitionAsJson("project");

        var projectTemplate2 = TeamCloudSerialize
                               .DeserializeObject <ProjectTemplate>(projectJson, new ProjectTemplateConverter(projectTemplate, porjectPath));

        Assert.NotNull(projectTemplate2);
        Assert.IsAssignableFrom <ProjectTemplate>(projectTemplate2);
    }
Exemple #5
0
    internal async Task <ProjectTemplate> UpdateProjectTemplateAsync(ProjectTemplate projectTemplate)
    {
        if (projectTemplate is null)
        {
            throw new ArgumentNullException(nameof(projectTemplate));
        }

        var repository = projectTemplate.Repository;

        if (!string.IsNullOrEmpty(repository.Token))
        {
            client.Credentials = new Credentials(repository.Token);
        }

        var projectYamlFiles = await client.Repository.Content
                               .GetAllContents(repository.Organization, repository.Repository, Constants.ProjectYaml)
                               .ConfigureAwait(false);

        var projectYamlFile = projectYamlFiles.First();
        var projectYaml     = projectYamlFile.Content;
        var projectJson     = new Deserializer().ToJson(projectYaml);

        projectTemplate = TeamCloudSerialize.DeserializeObject <ProjectTemplate>(projectJson, new ProjectTemplateConverter(projectTemplate, projectYamlFile.Url));

        var result = await client.Git.Tree
                     .GetRecursive(repository.Organization, repository.Repository, repository.Ref)
                     .ConfigureAwait(false);

        projectTemplate.Description = await CheckAndPopulateFileContentAsync(repository, result.Tree, projectTemplate.Description)
                                      .ConfigureAwait(false);

        return(projectTemplate);
    }
Exemple #6
0
    public static void SetCustomStatus(this IDurableOrchestrationContext durableOrchestrationContext, object customStatusObject, ILogger log, Exception exception = null)
    {
        if (durableOrchestrationContext is null)
        {
            throw new ArgumentNullException(nameof(durableOrchestrationContext));
        }

        durableOrchestrationContext.SetCustomStatus(customStatusObject);

        var customStatusMessage = customStatusObject is string customStatusString
            ? customStatusString
            : TeamCloudSerialize.SerializeObject(customStatusObject, Formatting.None);

        var message = $"{durableOrchestrationContext.InstanceId}: CUSTOM STATUS -> {customStatusMessage ?? "NULL"}";
        var safeLog = durableOrchestrationContext.CreateReplaySafeLogger(log ?? NullLogger.Instance);

        if (exception is null)
        {
            safeLog.LogInformation(message);
        }
        else
        {
            safeLog.LogError(exception, message);
        }
    }
    protected ErrorResultException(SerializationInfo info, StreamingContext context) : base(info, context)
    {
        var errorResultJson = info.GetString(nameof(ErrorResult));

        if (!string.IsNullOrWhiteSpace(errorResultJson))
        {
            ErrorResult = TeamCloudSerialize.DeserializeObject(errorResultJson) as IErrorResult;
        }
    }
    public static Exception ToException(this CommandError error)
    {
        if (error is null)
        {
            throw new ArgumentNullException(nameof(error));
        }

        return(new Exception(error.Message)
        {
            Source = TeamCloudSerialize.SerializeObject(error)
        });
    }
Exemple #9
0
    public void Serialize()
    {
        var command = new MockCommand(this.user, MockPayload.Instance);

        var json = TeamCloudSerialize.SerializeObject(command);

        Assert.NotEmpty(json);
        Assert.Contains("$type", json);

        var resultObj = TeamCloudSerialize.DeserializeObject <ICommand>(json);

        Assert.IsType <MockCommand>(resultObj);
    }
    public void LinksMaterializedOnDeserializedInstances()
    {
        Assert.NotNull(ReferenceLink.BaseUrl);

        var mockOwnerJson = TeamCloudSerialize.SerializeObject(new MockOwner());
        var mockOwner     = TeamCloudSerialize.DeserializeObject <MockOwner>(mockOwnerJson);

        var mockOwnerId = mockOwner.Id;

        mockOwner.Id = Guid.NewGuid(); // this must not affect the self link

        Assert.StartsWith(ReferenceLink.BaseUrl, mockOwner.Links.Self.ToString());
        Assert.EndsWith(mockOwnerId.ToString(), mockOwner.Links.Self.ToString());
    }
Exemple #11
0
    public virtual object Clone(bool reset)
    {
        var json = TeamCloudSerialize
                   .SerializeObject(this);

        var clone = (ContainerDocument)TeamCloudSerialize
                    .DeserializeObject(json, GetType());

        if (reset)
        {
            clone.Id = Guid.NewGuid().ToString();
        }

        return(clone);
    }
Exemple #12
0
    public async Task Dequeue(
        [QueueTrigger(CommandHandler.ProcessorQueue)] QueueMessage commandMessage,
        [Queue(CommandHandler.ProcessorQueue)] IAsyncCollector <ICommand> commandQueue,
        [Queue(CommandHandler.MonitorQueue)] IAsyncCollector <string> commandMonitor,
        [DurableClient] IDurableClient durableClient,
        ILogger log)
    {
        if (commandMessage is null)
        {
            throw new ArgumentNullException(nameof(commandMessage));
        }

        if (commandQueue is null)
        {
            throw new ArgumentNullException(nameof(commandQueue));
        }

        if (commandMonitor is null)
        {
            throw new ArgumentNullException(nameof(commandMonitor));
        }

        if (durableClient is null)
        {
            throw new ArgumentNullException(nameof(durableClient));
        }

        if (log is null)
        {
            throw new ArgumentNullException(nameof(log));
        }

        try
        {
            var command = TeamCloudSerialize.DeserializeObject <ICommand>(commandMessage.Body.ToString());

            command.Validate(validatorProvider, throwOnValidationError: true);

            _ = await ProcessCommandAsync(durableClient, command, commandQueue, commandMonitor, log)
                .ConfigureAwait(false);
        }
        catch (Exception exc)
        {
            log.LogError(exc, $"Failed to process queued command: {exc.Message}");

            throw;
        }
    }
Exemple #13
0
    private static async Task <ComponentTemplate> ResolveComponentTemplateAsync(ProjectTemplate projectTemplate, RepositoryReference repository, GitHttpClient client, GitTreeRef tree, GitTreeEntryRef treeItem)
    {
        var componentYamlFile = await client
                                .GetItemAsync(project : repository.Project, repository.Repository, treeItem.RelativePath, download : true, versionDescriptor : repository.VersionDescriptor())
                                .ConfigureAwait(false);

        var componentYaml     = componentYamlFile.Content;
        var componentJson     = new Deserializer().ToJson(componentYaml);
        var componentTemplate = TeamCloudSerialize.DeserializeObject <ComponentTemplate>(componentJson, new ComponentTemplateConverter(projectTemplate, componentYamlFile.Path));

        var folder = treeItem.RelativePath.Split(Constants.ComponentYaml).First().TrimEnd('/');

        componentTemplate.Description = await CheckAndPopulateFileContentAsync(client, repository, tree.TreeEntries, componentTemplate.Description, folder)
                                        .ConfigureAwait(false);

        return(componentTemplate);
    }
    public void DeSerialize_NameValueCollection()
    {
        var nvc = new NameValueCollection();

        for (int i = 1; i <= 10; i++)
            nvc.Add("foo", $"bar{i}");

        var json = TeamCloudSerialize.SerializeObject(nvc);

        for (int i = 1; i <= 10; i++)
            Assert.Contains($"bar{i}", json);

        var nvc2 = TeamCloudSerialize.DeserializeObject<NameValueCollection>(json);

        for (int i = 1; i <= 10; i++)
            Assert.Contains($"bar{i}", nvc2.GetValues("foo"));
    }
Exemple #15
0
    private async Task <ComponentTemplate> ResolveComponentTemplateAsync(ProjectTemplate projectTemplate, RepositoryReference repository, TreeResponse tree, TreeItem treeItem)
    {
        var componentYamlFiles = await client.Repository.Content
                                 .GetAllContents(repository.Organization, repository.Repository, treeItem.Path)
                                 .ConfigureAwait(false);

        var componentYamlFile = componentYamlFiles.First();
        var componentYaml     = componentYamlFile.Content;
        var componentJson     = new Deserializer().ToJson(componentYaml);

        var componentTemplate = TeamCloudSerialize.DeserializeObject <ComponentTemplate>(componentJson, new ComponentTemplateConverter(projectTemplate, treeItem.Url));

        componentTemplate.Folder      = Regex.Replace(treeItem.Path, $"/{Constants.ComponentYaml}$", string.Empty, RegexOptions.IgnoreCase);
        componentTemplate.Description = await CheckAndPopulateFileContentAsync(repository, tree.Tree, componentTemplate.Description, componentTemplate.Folder).ConfigureAwait(false);

        return(componentTemplate);
    }
Exemple #16
0
    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        var projectJson = JObject.ReadFrom(reader) as JObject;

        foreach (var nameToken in projectJson.SelectTokens("$..name").Reverse().ToArray())
        {
            // (nameToken.Parent.Parent as JObject)?.SetProperty("title", nameToken.ToString());
            (nameToken.Parent.Parent as JObject)?.SetProperty("displayName", nameToken.ToString());
            nameToken.Parent.Remove(); // get rid of the name token as we don't need it anymore
        }

        var inputJsonSchemaToken = GenerateInputJsonSchema(projectJson, serializer);

        projectJson.SetProperty(nameof(ComponentTemplate.InputJsonSchema), inputJsonSchemaToken);

        return(TeamCloudSerialize.MergeObject <ProjectTemplate>(projectJson.ToString(), projectTemplate));
    }
Exemple #17
0
    public async Task <T> SetSecretAsync <T>(string secretName, T secretValue)
        where T : class, new()
    {
        if (secretValue is null)
        {
            await SetSecretAsync(secretName, null)
            .ConfigureAwait(false);

            return(secretValue);
        }
        else
        {
            var secretJson = await SetSecretAsync(secretName, TeamCloudSerialize.SerializeObject(secretValue))
                             .ConfigureAwait(false);

            return(TeamCloudSerialize.DeserializeObject <T>(secretJson));
        }
    }
Exemple #18
0
    public static async Task RunActivity(
        [ActivityTrigger] IDurableActivityContext activityContext,
        [DurableClient] IDurableOrchestrationClient orchestrationClient,
        ILogger log)
    {
        if (activityContext is null)
        {
            throw new ArgumentNullException(nameof(activityContext));
        }

        if (orchestrationClient is null)
        {
            throw new ArgumentNullException(nameof(orchestrationClient));
        }

        var functionInput = activityContext.GetInput <Input>();

        try
        {
            await orchestrationClient
            .RaiseEventAsync(functionInput.InstanceId, functionInput.EventName, functionInput.EventData)
            .ConfigureAwait(false);

            log.LogInformation($"Raised event '{functionInput.EventName}' for instance {functionInput.InstanceId}: {SerializeEventData()}");
        }
        catch (Exception exc)
        {
            log.LogError(exc, $"Failed to raise event '{functionInput.EventName}' for instance {functionInput.InstanceId}: {exc.Message}");
        }

        string SerializeEventData()
        {
            if (functionInput.EventData is null)
            {
                return(null);
            }

            var eventDataType = functionInput.EventData.GetType();

            return((eventDataType.IsValueType || eventDataType.Equals(typeof(string)))
                ? functionInput.EventData.ToInvariantString()
                : TeamCloudSerialize.SerializeObject(functionInput.EventData));
        }
    }
        static async Task <string> ReadContentAsync(HttpContent httpContent)
        {
            if ((httpContent?.Headers.ContentLength.GetValueOrDefault(0) ?? 0) == 0)
            {
                return(string.Empty);
            }

            var content = await httpContent
                          .ReadAsStringAsync()
                          .ConfigureAwait(false);

            //TODO: why ist this here needed
            if (httpContent.Headers.ContentType.MediaType.Equals("application/json", StringComparison.OrdinalIgnoreCase))
            {
                var jsonContent = TeamCloudSerialize.DeserializeObject(content);

                return(TeamCloudSerialize.SerializeObject(jsonContent, Formatting.Indented));
            }

            return(content);
        }
    public static async Task <ICommandResult> RunActivity(
        [ActivityTrigger] IDurableActivityContext context,
        [DurableClient] IDurableClient durableClient,
        ILogger log)
    {
        if (context is null)
        {
            throw new ArgumentNullException(nameof(context));
        }

        if (durableClient is null)
        {
            throw new ArgumentNullException(nameof(durableClient));
        }

        try
        {
            var commandResult = context.GetInput <Input>().CommandResult;

            var commandStatus = await durableClient
                                .GetStatusAsync(commandResult.CommandId.ToString())
                                .ConfigureAwait(false);

            if (commandStatus is not null)
            {
                commandResult.ApplyStatus(commandStatus);

                Debug.WriteLine($"Augmented command result: {TeamCloudSerialize.SerializeObject(commandResult)}");
            }

            return(commandResult);
        }
        catch (Exception exc)
        {
            log?.LogError(exc, $"Failed to augment command result with orchestration status: {exc.Message}");

            throw exc.AsSerializable();
        }
    }
    private void AssertException(Exception serializableException, bool serializableExpected = true)
    {
        Assert.Equal(serializableExpected, serializableException.IsSerializable(out _));

        string serializableExceptionJson;

        try
        {
            serializableExceptionJson = TeamCloudSerialize.SerializeObject(serializableException, Formatting.Indented);
        }
        catch
        {
            serializableExceptionJson = default;
        }

        if (serializableExpected)
        {
            Assert.NotNull(serializableExceptionJson);
        }

        if (!string.IsNullOrEmpty(serializableExceptionJson))
        {
            Exception deserializedException;

            try
            {
                deserializedException = (Exception)TeamCloudSerialize.DeserializeObject(serializableExceptionJson, serializableException.GetType());
            }
            catch when(!serializableExpected)
            {
                deserializedException = default;
            }

            if (serializableExpected)
            {
                Assert.NotNull(deserializedException);
            }
        }
    }
Exemple #22
0
    protected JToken GeneratePermissionDictionary(JObject json, JsonSerializer serializer)
    {
        var keyValuePairs = json
                            .SelectTokens("$.permissions[*]")
                            .OfType <JObject>()
                            .Select(t =>
        {
            var role       = Enum.Parse <ProjectUserRole>(t.GetValue("role", StringComparison.OrdinalIgnoreCase)?.ToString().Trim(), true);
            var permission = t.GetValue("permission", StringComparison.OrdinalIgnoreCase)?.ToString().Trim();

            return(new KeyValuePair <ProjectUserRole, string>(role, permission));
        });

        var dictionary = keyValuePairs
                         .Where(kvp => !string.IsNullOrEmpty(kvp.Value))
                         .GroupBy(kvp => kvp.Key)
                         .ToDictionary(grp => grp.Key, grp => grp.Select(kvp => kvp.Value).Distinct());

        return(JObject.Parse(TeamCloudSerialize.SerializeObject(dictionary, new TeamCloudSerializerSettings()
        {
            TypeNameHandling = TypeNameHandling.None
        })));
    }
    public string GetProjectDefinitionAsJson(string suffix)
    {
        var resourceName = GetType().Assembly
                           .GetManifestResourceNames()
                           .FirstOrDefault(name => name.Equals($"{GetType().FullName}_{suffix}.yaml", StringComparison.OrdinalIgnoreCase));

        if (string.IsNullOrEmpty(resourceName))
        {
            throw new NullReferenceException($"Component definition not found.");
        }

        using var resourceStream = GetType().Assembly
                                   .GetManifestResourceStream(resourceName);

        using var resourceReader = new StreamReader(resourceStream);

        var data = new Deserializer().Deserialize(resourceReader);

        return(TeamCloudSerialize.SerializeObject(data, new TeamCloudSerializerSettings()
        {
            // ensure we disable the type name handling to get clean json
            TypeNameHandling = TypeNameHandling.None
        }));
    }
Exemple #24
0
    public void Serialize()
    {
        var broadcastMessage = new BroadcastMessage()
        {
            Action    = "Custom",
            Timestamp = DateTime.UtcNow,
            Items     = new List <BroadcastMessage.Item>()
            {
                new BroadcastMessage.Item()
                {
                    Organization = Guid.NewGuid().ToString(),
                    Project      = Guid.NewGuid().ToString(),
                    Component    = Guid.NewGuid().ToString(),
                    ETag         = Guid.NewGuid().ToString(),
                    Timestamp    = DateTime.UtcNow
                }
            }
        };

        var broadcastJson = TeamCloudSerialize.SerializeObject(broadcastMessage);

        Assert.NotEmpty(broadcastJson);
        Assert.DoesNotContain("$type", broadcastJson);
    }
    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        var componentJson = JObject.ReadFrom(reader) as JObject;

        foreach (var nameToken in componentJson.SelectTokens("$..name").Reverse().ToArray())
        {
            // (nameToken.Parent.Parent as JObject)?.SetProperty("title", nameToken.ToString());
            (nameToken.Parent.Parent as JObject)?.SetProperty("displayName", nameToken.ToString());
            nameToken.Parent.Remove(); // get rid of the name token as we don't need it anymore
        }

        // augment the component json by some project template level data
        componentJson.SetProperty(nameof(ComponentTemplate.Id), repositoryLocation.ToGuid().ToString());
        componentJson.SetProperty(nameof(ComponentTemplate.ParentId), projectTemplate.Id);
        componentJson.SetProperty(nameof(ComponentTemplate.Organization), projectTemplate.Organization);
        componentJson.SetProperty(nameof(ComponentTemplate.OrganizationName), projectTemplate.OrganizationName);
        componentJson.SetProperty(nameof(ComponentTemplate.Repository), repositoryReference);

        var inputJsonSchemaToken = GenerateInputJsonSchema(componentJson, serializer);

        componentJson.SetProperty(nameof(ComponentTemplate.InputJsonSchema), inputJsonSchemaToken);

        var permissionDictionaryToken = GeneratePermissionDictionary(componentJson, serializer);

        componentJson.SetProperty(nameof(ComponentTemplate.Permissions), permissionDictionaryToken);

        var componentType = Enum.Parse <ComponentType>(componentJson.GetValue("type", StringComparison.OrdinalIgnoreCase)?.ToString(), true) switch
        {
            ComponentType.Environment => typeof(ComponentEnvironmentTemplate),
            ComponentType.Repository => typeof(ComponentRepositoryTemplate),
            _ => typeof(ComponentTemplate)
        };

        return(TeamCloudSerialize.DeserializeObject(componentJson.ToString(), componentType));
    }
}
Exemple #26
0
    internal async Task <ProjectTemplate> UpdateProjectTemplateAsync(ProjectTemplate projectTemplate)
    {
        if (projectTemplate is null)
        {
            throw new ArgumentNullException(nameof(projectTemplate));
        }

        var repository = projectTemplate.Repository;

        var creds = new VssBasicCredential(string.Empty, repository.Token);

        using var connection = new VssConnection(new Uri(repository.BaselUrl), creds);
        using var client     = connection.GetClient <GitHttpClient>();

        var commit = await client
                     .GetCommitAsync(project : repository.Project, repository.Ref, repository.Repository)
                     .ConfigureAwait(false);

        var result = await client
                     .GetTreeAsync(project : repository.Project, repository.Repository, commit.TreeId, recursive : true)
                     .ConfigureAwait(false);

        var projectYamlFile = await client
                              .GetItemAsync(project : repository.Project, repository.Repository, Constants.ProjectYaml, download : true, versionDescriptor : repository.VersionDescriptor())
                              .ConfigureAwait(false);

        var projectYaml = projectYamlFile.Content;
        var projectJson = new Deserializer().ToJson(projectYaml);

        TeamCloudSerialize.PopulateObject(projectJson, projectTemplate, new ProjectTemplateConverter(projectTemplate, projectYamlFile.Path));

        projectTemplate.Description = await CheckAndPopulateFileContentAsync(client, repository, result.TreeEntries, projectTemplate.Description)
                                      .ConfigureAwait(false);

        return(projectTemplate);
    }
 private KubernetesData GetKubernetesData(DeploymentScope deploymentScope)
 => TeamCloudSerialize.DeserializeObject <KubernetesData>(deploymentScope.InputData);
Exemple #28
0
    public void Deserialize_Success(string json)
    {
        var data = TeamCloudSerialize.DeserializeObject <KubernetesData>(json);

        data.Validate(validatorProvider, throwOnValidationError: true, throwOnNoValidatorFound: true);
    }
Exemple #29
0
    public override async Task <ICommandResult> HandleAsync(ICommand command, IAsyncCollector <ICommand> commandQueue, IDurableOrchestrationContext orchestrationContext, ILogger log)
    {
        if (command is null)
        {
            throw new ArgumentNullException(nameof(command));
        }

        var commandResult = command.CreateResult();

        try
        {
            if (CanHandle(command))
            {
                var containerDocument = (IContainerDocument)command.Payload;

                using var loggerFactory  = new PassthroughLoggerFactory(log);
                using var serviceManager = CreateServiceManager();

                var broadcastMessage = new BroadcastMessage()
                {
                    Action    = commandResult.CommandAction.ToString().ToLowerInvariant(),
                    Timestamp = commandResult.LastUpdatedTime.GetValueOrDefault(DateTime.UtcNow),
                    Items     = GetItems(containerDocument)
                };

                var broadcastPayload = TeamCloudSerialize.SerializeObject(broadcastMessage);

                await foreach (var hubName in ResolveHubNamesAsync(containerDocument))
                {
                    var hubContext = await serviceManager
                                     .CreateHubContextAsync(hubName, CancellationToken.None)
                                     .ConfigureAwait(false);

                    var negotiation = await hubContext
                                      .NegotiateAsync()
                                      .ConfigureAwait(false);

                    await hubContext.Clients.All
                    .SendAsync(command.CommandAction.ToString(), broadcastMessage)
                    .ConfigureAwait(false);
                }
            }
            else
            {
                throw new NotImplementedException($"Missing orchestrator command handler implementation ICommandHandler<{command.GetTypeName(prettyPrint: true)}> at {GetType()}");
            }
        }
        catch (Exception exc)
        {
            commandResult.Errors.Add(exc);
        }

        return(commandResult);

        async IAsyncEnumerable <string> ResolveHubNamesAsync(object commandResultPayload)
        {
            yield return(commandResultPayload switch
            {
                IProjectContext projectContext => projectContext.GetHubName(),
                IOrganizationContext organizationContext => organizationContext.GetHubName(),
                Organization organization => organization.GetHubName(),
                _ => throw new NotSupportedException($"Unable to resolve hub name for command result payload of type '{commandResultPayload?.GetType()}'.")
            });

            if (commandResultPayload is User user)
            {
                foreach (var membership in user.ProjectMemberships)
                {
                    var project = await projectRepository
                                  .GetAsync(user.Organization, membership.ProjectId)
                                  .ConfigureAwait(false);

                    yield return(project.GetHubName());
                }
            }
        }
Exemple #30
0
    async Task <IActionResult> IAdapterAuthorize.HandleAuthorizeAsync(DeploymentScope deploymentScope, HttpRequest request, IAuthorizationEndpoints authorizationEndpoints)
    {
        if (deploymentScope is null)
        {
            throw new ArgumentNullException(nameof(deploymentScope));
        }

        if (request is null)
        {
            throw new ArgumentNullException(nameof(request));
        }

        if (authorizationEndpoints is null)
        {
            throw new ArgumentNullException(nameof(authorizationEndpoints));
        }

        var queryParams = Url.ParseQueryParams(request.QueryString.ToString());
        var queryState  = queryParams.GetValueOrDefault("state");
        var queryCode   = queryParams.GetValueOrDefault("code");
        var queryError  = queryParams.GetValueOrDefault("error");

        var session = await SessionClient
                      .GetAsync <GitHubSession>(deploymentScope)
                      .ConfigureAwait(false);

        session ??= await SessionClient
        .SetAsync(new GitHubSession(deploymentScope))
        .ConfigureAwait(false);

        var data = string.IsNullOrWhiteSpace(deploymentScope.InputData)
            ? default
            : TeamCloudSerialize.DeserializeObject <GitHubData>(deploymentScope.InputData);

        var token = await TokenClient
                    .GetAsync <GitHubToken>(deploymentScope)
                    .ConfigureAwait(false);

        if (string.IsNullOrEmpty(queryError) && Guid.TryParse(queryState, out var stateId))
        {
            if (!stateId.ToString().Equals(session.SessionId, StringComparison.OrdinalIgnoreCase))
            {
                return(new RedirectResult(authorizationEndpoints.AuthorizationUrl.SetQueryParam("error", "Session timed out.").ToString()));
            }
            else if (string.IsNullOrWhiteSpace(queryCode))
            {
                return(new RedirectResult(authorizationEndpoints.AuthorizationUrl.SetQueryParam("error", "Missing GitHub handshake information.").ToString()));
            }

            token ??= new GitHubToken(deploymentScope);

            // Using Flurl as Octokit doesn't support this API yet
            // https://github.com/octokit/octokit.net/issues/2138

            var url = $"https://api.github.com/app-manifests/{queryCode}/conversions";

            var response = await url
                           .WithHeader("User-Agent", GitHubConstants.ProductHeader.ToString())
                           .PostStringAsync(string.Empty)
                           .ConfigureAwait(false);

            if (!response.IsSuccessStatusCode())
            {
                return(new RedirectResult(authorizationEndpoints.AuthorizationUrl.SetQueryParam("error", $"Failed to get application token ({response.StatusCode} - {response.ResponseMessage.ReasonPhrase}).").ToString()));
            }

            var json = await response
                       .GetStringAsync()
                       .ConfigureAwait(false);

            TeamCloudSerialize.PopulateObject(json, token);

            if (string.IsNullOrEmpty(token.OwnerLogin))
            {
                token.OwnerLogin = JToken.Parse(json)
                                   .SelectToken("owner.login")
                                   .ToString();
            }

            token = await TokenClient
                    .SetAsync(token, true)
                    .ConfigureAwait(false);

            return(new ContentResult
            {
                StatusCode = (int)HttpStatusCode.OK,
                ContentType = "text/html",
                Content = Assembly.GetExecutingAssembly().GetManifestResourceTemplate($"{GetType().FullName}_Install.html", GetFormContext())
            });
        }
        else
        {
            return(new ContentResult
            {
                StatusCode = (int)HttpStatusCode.OK,
                ContentType = "text/html",
                Content = Assembly.GetExecutingAssembly().GetManifestResourceTemplate($"{GetType().FullName}_Register.html", GetFormContext())
            });
        }

        object GetFormContext() => new
        {
            deploymentScope        = deploymentScope,
            authorizationEndpoints = authorizationEndpoints,
            token     = token,
            data      = data,
            session   = session,
            error     = queryError ?? string.Empty,
            succeeded = queryParams.Contains("succeeded")
        };
    }