public async Task <ConnectivityCheckResponse> ConnectivityCheck()
        {
            var connectivityCheckResponse = new ConnectivityCheckResponse();

            // make sure the user can authenticate
            try
            {
                using var response = await httpClient.GetAsync($"{baseUrl}/{baseApiUri}/myself");

                if (response.IsSuccessStatusCode)
                {
                    // make sure the user has browse projects permission
                    using var httpResponseMessage = await httpClient.GetAsync($"{baseUrl}/{baseApiUri}/mypermissions?permissions={BrowseProjectsKey}");

                    if (response.IsSuccessStatusCode)
                    {
                        var jsonContent = await httpResponseMessage.Content.ReadAsStringAsync();

                        var permissionsContainer = JsonConvert.DeserializeObject <PermissionSettingsContainer>(jsonContent);

                        if (permissionsContainer == null)
                        {
                            connectivityCheckResponse.AddMessage(ConnectivityCheckMessageCategory.Error, "Unable to read permissions from response body");
                            return(connectivityCheckResponse);
                        }

                        if (!permissionsContainer.Permissions.ContainsKey(BrowseProjectsKey))
                        {
                            connectivityCheckResponse.AddMessage(
                                ConnectivityCheckMessageCategory.Error,
                                $"Permissions returned from Jira does not contain the {BrowseProjectsKey} permission details.");
                            return(connectivityCheckResponse);
                        }

                        var setting = permissionsContainer.Permissions[BrowseProjectsKey];
                        if (!setting.HavePermission)
                        {
                            connectivityCheckResponse.AddMessage(
                                ConnectivityCheckMessageCategory.Error,
                                $"User does not have the '{setting.Name}' permission in Jira");
                            return(connectivityCheckResponse);
                        }

                        return(connectivityCheckResponse);
                    }
                }

                connectivityCheckResponse.AddMessage(
                    ConnectivityCheckMessageCategory.Error,
                    $"Failed to connect to {baseUrl}. Response code: {response.StatusCode}{(!string.IsNullOrEmpty(response.ReasonPhrase) ? $" Reason: {response.ReasonPhrase}" : "")}");

                return(connectivityCheckResponse);
            }
            catch (HttpRequestException e)
            {
                connectivityCheckResponse.AddMessage(
                    ConnectivityCheckMessageCategory.Error,
                    $"Failed to connect to {baseUrl}. Reason: {e.Message}");
                return(connectivityCheckResponse);
            }
            catch (TaskCanceledException e)
            {
                connectivityCheckResponse.AddMessage(
                    ConnectivityCheckMessageCategory.Error,
                    $"Failed to connect to {baseUrl}. Reason: {e.Message}");
                return(connectivityCheckResponse);
            }
            catch
            {
                connectivityCheckResponse.AddMessage(
                    ConnectivityCheckMessageCategory.Error,
                    $"Failed to connect to {baseUrl}.");
                return(connectivityCheckResponse);
            }
        }
        public Task <IOctoResponseProvider> ExecuteAsync(IOctoRequest request)
        {
            var connectivityCheckResponse = new ConnectivityCheckResponse();

            try
            {
                var requestData = request.GetBody(Data);

                var baseUrl = requestData.BaseUrl;
                // If PersonalAccessToken here is null, it could be that they're clicking the test connectivity button after saving
                // the configuration as we won't have the value of the PersonalAccessToken on client side, so we need to retrieve it
                // from the database
                var personalAccessToken = requestData.PersonalAccessToken.ToSensitiveString();
                if (string.IsNullOrEmpty(personalAccessToken?.Value))
                {
                    personalAccessToken = configurationStore.GetConnections().FirstOrDefault(connection => connection.BaseUrl == baseUrl)?.PersonalAccessToken;
                }

                if (string.IsNullOrEmpty(baseUrl))
                {
                    connectivityCheckResponse.AddMessage(ConnectivityCheckMessageCategory.Error, "Please provide a value for Azure DevOps Base Url.");
                    return(Task.FromResult(Result.Response(connectivityCheckResponse)));
                }

                var urls = AdoProjectUrls.ParseOrganizationAndProjectUrls(baseUrl);
                AdoProjectUrls[] projectUrls;
                if (urls.ProjectUrl != null)
                {
                    projectUrls = new[] { urls };
                }
                else
                {
                    var projectsResult = adoApiClient.GetProjectList(urls, personalAccessToken?.Value);
                    if (projectsResult is FailureResult failure)
                    {
                        connectivityCheckResponse.AddMessage(ConnectivityCheckMessageCategory.Error, failure.ErrorString);
                        return(Task.FromResult(Result.Response(connectivityCheckResponse)));
                    }

                    var projects = (ISuccessResult <string[]>)projectsResult;

                    if (!projects.Value.Any())
                    {
                        connectivityCheckResponse.AddMessage(ConnectivityCheckMessageCategory.Error, "Successfully connected, but unable to find any projects to test permissions.");
                        return(Task.FromResult(Result.Response(connectivityCheckResponse)));
                    }

                    projectUrls = projects.Value.Select(project => new AdoProjectUrls(urls.OrganizationUrl)
                    {
                        ProjectUrl = $"{urls.OrganizationUrl}/{project}"
                    }).ToArray();
                }

                var hasError = false;
                foreach (var projectUrl in projectUrls)
                {
                    var buildScopeTest = adoApiClient.CheckWeCanGetBuilds(projectUrl, personalAccessToken?.Value);
                    if (buildScopeTest is FailureResult buildScopeFailure)
                    {
                        connectivityCheckResponse.AddMessage(ConnectivityCheckMessageCategory.Error, buildScopeFailure.ErrorString);
                        hasError = true;
                    }
                }

                if (!hasError)
                {
                    connectivityCheckResponse.AddMessage(ConnectivityCheckMessageCategory.Info, "Successfully connected to Azure DevOps");

                    if (!configurationStore.GetIsEnabled())
                    {
                        connectivityCheckResponse.AddMessage(ConnectivityCheckMessageCategory.Warning, "The Jira Issue Tracker is not enabled, so its functionality will not currently be available");
                    }
                }

                return(Task.FromResult(Result.Response(connectivityCheckResponse)));
            }
            catch (Exception ex)
            {
                connectivityCheckResponse.AddMessage(ConnectivityCheckMessageCategory.Error, ex.ToString());
                return(Task.FromResult(Result.Response(connectivityCheckResponse)));
            }
        }