// https://docs.microsoft.com/en-us/azure/devops/integrate/get-started/client-libraries/samples?view=vsts
        // https://blog.devmatter.com/personal-access-tokens-and-vsts-apis/
        // https://stackoverflow.com/questions/46719764/cant-access-my-repos-in-vsts-using-rest-api
        public static VssCredentials Create(TfsKnownConnection connection)
        {
            VssCredentials creds = null;

            if (connection.ConnectionType == TfsConnectionTypes.TfsNTLM)
            {
                creds = connection.UseDefaultCredentials
                    ? new VssCredentials(true)
                    : new VssCredentials(
                    new WindowsCredential(
                        new NetworkCredential(connection.Username, connection.Password)));
            }

            /*
             * else if (connection.ConnectionType == TfsConnectionTypes.AzureDevOpsActiveDir)
             * {
             *  if (connection.UseDefaultCredentials)
             *      creds = new VssAadCredential();
             *  else
             *      creds = new VssAadCredential(connection.Username, connection.Password);
             * }
             */
            else if (connection.ConnectionType == TfsConnectionTypes.AzureDevOpsToken)
            {
                creds = new VssBasicCredential(string.Empty, connection.PersonalAccessToken);
            }

            return(creds);
        }
Example #2
0
        private bool ShouldSelectConnection(TfsKnownConnection knownConn, ReportRun lastReportRun)
        {
            if (lastReportRun == null)
            {
                return(false);
            }
            var select = knownConn.Id == lastReportRun.ConnectionId;

            return(select);
        }
Example #3
0
        public async Task <TfsQueryResult> Query(TfsKnownConnection knownConn, TfsStatesViewModel model)
        {
            var sw            = Stopwatch.StartNew();
            var vssConnection = knownConn.ToVssConnection();

            this.workItemClient = vssConnection.GetClient <WorkItemTrackingHttpClient>();
            var wiql           = TfsQueryBuilder.BuildQuery(model);
            var tfsQueryResult = await this.workItemClient.QueryByWiqlAsync(new Wiql { Query = wiql });

            var workItems = tfsQueryResult.WorkItems.ToList();

            this.totalCount = workItems.Count();

            var queue        = new ConcurrentQueue <TfsInfo>();
            var asyncOptions = GetAsyncOptions();

            var getRevsBlock = new ActionBlock <WorkItemReference>(
                async workItemRef =>
            {
                var tfsInfo = await ProcessWorkItemRevisions(workItemRef);

                if (tfsInfo.TransitionCount > model.MinTransitions)
                {
                    queue.Enqueue(tfsInfo);
                }
            },
                asyncOptions);

            foreach (var wiRef in workItems)
            {
                getRevsBlock.Post(wiRef);
            }

            getRevsBlock.Complete();
            await getRevsBlock.Completion;

            var list = queue
                       .OrderBy(i => i.Iteration)
                       .ThenBy(i => i.Id)
                       .ToList();

            sw.Stop();

            var result = new TfsQueryResult
            {
                TfsItems       = list,
                TotalWorkItems = this.processedCount,
                TotalRevisions = this.revisionsCount
            };

            return(result);
        }
        public static VssConnection ToVssConnection(this TfsKnownConnection knownConn)
        {
            if (knownConn == null)
            {
                return(null);
            }

            var creds         = TfsCredentialsFactory.Create(knownConn);
            var vssConnection = new VssConnection(new Uri(knownConn.Url), creds);

            vssConnection.Settings.SendTimeout = TimeSpan.FromSeconds(AppSettings.DefaultTimeoutSeconds);

            return(vssConnection);
        }
Example #5
0
        // TODO: Consider caching such as https://github.com/alastairtree/LazyCache?WT.mc_id=-blog-scottha
        public async Task <List <string> > GetProjectNames(TfsKnownConnection knownConn)
        {
            var vssConnection = knownConn.ToVssConnection();

            var projectClient = vssConnection.GetClient <ProjectHttpClient>();
            var states        = ProjectState.Unchanged | ProjectState.WellFormed;
            var projects      = await projectClient.GetProjects(states, top : 200);

            var projectNames = projects
                               .OrderBy(p => p.Name)
                               .Select(p => p.Name)
                               .ToList();

            return(projectNames);
        }
Example #6
0
        private async Task <List <string> > GetIterationData(TfsKnownConnection knownConn, string project)
        {
            var iterations = new List <string>
            {
                { NoIterationSelected }
            };

            var projectIterations = await this.projectService.GetIterations(knownConn, project);

            if (projectIterations != null)
            {
                iterations.AddRange(projectIterations);
            }

            return(iterations);
        }
        public static TfsConnectionItemViewModel ToViewModel(this TfsKnownConnection knownConn)
        {
            var vm = new TfsConnectionItemViewModel
            {
                ConnectionType  = knownConn.ConnectionType,
                ConnectionTypes = TfsConnectionTypes.Items,
                Id                    = knownConn.Id,
                Name                  = knownConn.Name,
                Password              = knownConn.Password,
                PersonalAccessToken   = knownConn.PersonalAccessToken,
                Url                   = knownConn.Url,
                UseDefaultCredentials = knownConn.UseDefaultCredentials,
                Username              = knownConn.Username
            };

            return(vm);
        }
        public static TfsKnownConnection ToKnownConnection(this TfsConnectionItemViewModel viewModel)
        {
            // TODO: Consider AutoMapper if mapping grows much.

            var knownConn = new TfsKnownConnection
            {
                ConnectionType        = viewModel.ConnectionType,
                Id                    = viewModel.Id,
                Name                  = viewModel.Name,
                Password              = viewModel.Password,
                PersonalAccessToken   = viewModel.PersonalAccessToken,
                Url                   = viewModel.Url,
                UseDefaultCredentials = viewModel.UseDefaultCredentials,
                Username              = viewModel.Username
            };

            return(knownConn);
        }
Example #9
0
        public async Task Save(TfsKnownConnection connection)
        {
            string filename = await GetFilename();

            var connections = await GetRawConnections() ?? new TfsKnownConnections();

            var originalPassword = connection.Password;
            var originalToken    = connection.PersonalAccessToken;

            if (!string.IsNullOrEmpty(connection.Password))
            {
                connection.Password = this.dataProtector.Protect(connection.Password);
            }

            if (!string.IsNullOrEmpty(connection.PersonalAccessToken))
            {
                connection.PersonalAccessToken = this.dataProtector.Protect(connection.PersonalAccessToken);
            }

            var existingConnection = connections.Connections.FirstOrDefault(c => c.Id == connection.Id);

            if (existingConnection == null)
            {
                connection.AddedDate = DateTime.Now;
                connections.Connections.Add(connection);
            }
            else
            {
                connection.UpdatedDate = DateTime.Now;
                var index = connections.Connections.IndexOf(existingConnection);
                connections.Connections[index] = connection;
            }

            await SaveConnections(filename, connections);

            connection.Password            = originalPassword;
            connection.PersonalAccessToken = originalToken;
        }
Example #10
0
        public async Task <List <string> > GetIterations(TfsKnownConnection knownConn, string projectName)
        {
            var vssConnection = knownConn.ToVssConnection();

            var client = vssConnection.GetClient <WorkItemTrackingHttpClient>();

            var rootIterationNode = await client.GetClassificationNodeAsync(
                projectName,
                TreeStructureGroup.Iterations,
                depth : int.MaxValue);

            var list = new List <IterationItem>();

            GetIterations(list, rootIterationNode);

            var sortedIterationNames = list
                                       .OrderBy(i => i.Path)
                                       .ThenBy(i => i.StartDate)
                                       .Select(i => i.Name)
                                       .ToList();

            return(sortedIterationNames);
        }
Example #11
0
        public async Task <TfsConnectionValidationResult> Validate(TfsKnownConnection connection)
        {
            try
            {
                var uri           = new Uri(connection.Url);
                var creds         = TfsCredentialsFactory.Create(connection);
                var vssConnection = new VssConnection(uri, creds);
                vssConnection.Settings.SendTimeout = TimeSpan.FromSeconds(AppSettings.DefaultTimeoutSeconds);

                var projectClient = vssConnection.GetClient <ProjectHttpClient>();

                var projects = await projectClient.GetProjects(ProjectState.All, top : 1);

                if (projects.Count == 0)
                {
                    return(new TfsConnectionValidationResult
                    {
                        IsError = true,
                        Message = "TFS connection validation test failed. Didn't find any projects."
                    });
                }
            }
            catch (Exception ex)
            {
                return(new TfsConnectionValidationResult
                {
                    IsError = true,
                    Message = $"TFS connection validation test failed. {ex.Message}"
                });
            }

            return(new TfsConnectionValidationResult
            {
                Message = $"Successfully connected to {connection.Url}."
            });
        }
Example #12
0
        private async Task LoadLookups(TfsStatesViewModel model)
        {
            model = model ?? new TfsStatesViewModel();

            if (model.Projects?.Any() ?? false)
            {
                return;
            }

            model.Connections.Add(new SelectListItem
            {
                Text = "- Select connection -"
            });

            var settingsUrl = Url.Action("Index", "Settings");

            model.Projects.Insert(0, NoProjectSelected);

            TfsKnownConnection defaultConnection = null;
            var lastReportRun = await this.reportHistoryService.GetLastRunSettings();

            try
            {
                var connections = await settingsService.GetConnections();

                if (connections == null || (connections.Connections?.Count ?? 0) == 0)
                {
                    model.RunReadyState.NotReady(
                        $"<a href='{settingsUrl}'>TFS settings</a> need to first be supplied.");
                }
                else
                {
                    model.Connections.AddRange(
                        connections
                        .Connections
                        .OrderBy(c => c.Name)
                        .Select(c =>
                                new SelectListItem
                    {
                        Text     = c.Name,
                        Value    = c.Id.ToString(),
                        Selected = (1 == connections.Connections.Count ||
                                    ShouldSelectConnection(c, lastReportRun))
                    }));

                    if (model.ConnectionId == Guid.Empty &&
                        lastReportRun != null &&
                        connections.Connection(lastReportRun.ConnectionId) != null)
                    {
                        defaultConnection = connections.Connection(lastReportRun.ConnectionId);
                    }
                    else if (model.ConnectionId != Guid.Empty)
                    {
                        defaultConnection = connections.Connection(model.ConnectionId);
                    }
                    else if (connections.Connections.Count == 1)
                    {
                        defaultConnection = connections.Connections.First();
                    }
                }
            }
            catch (Exception ex)
            {
                Trace.WriteLine(ex);
                model.RunReadyState.NotReady(
                    $"Error loading <a href='{settingsUrl}'>TFS settings</a>. " +
                    $"Adjust settings and try again.");
            }

            if (model.RunReadyState.State == TfsStatesViewModel.RunStates.NotReady)
            {
                return;
            }

            if (defaultConnection != null)
            {
                model.ConnectionId = defaultConnection.Id;

                try
                {
                    var projectNames = await this.projectService.GetProjectNames(defaultConnection);

                    if (projectNames == null || !projectNames.Any())
                    {
                        model.RunReadyState.NotReady(
                            $"No TFS projects found. Check <a href='{settingsUrl}'>TFS settings</a> " +
                            $"and try again.");
                    }
                    else
                    {
                        model.Projects.AddRange(projectNames);
                    }
                }
                catch (Exception ex)
                {
                    Trace.WriteLine(ex);
                    model.RunReadyState.NotReady(
                        $"Error loading TFS projects. Check <a href='{settingsUrl}'>TFS settings</a> " +
                        $"and your connectivity and try again.");
                }

                if (model.RunReadyState.State == TfsStatesViewModel.RunStates.NotReady)
                {
                    return;
                }
            }


            if (lastReportRun != null && defaultConnection != null)
            {
                if (model.Projects?.Any() ?? false &&
                    lastReportRun.ConnectionId == defaultConnection.Id &&
                    model.Projects.Contains(lastReportRun.Project))
                {
                    model.Project = lastReportRun.Project;
                }
            }

            if (defaultConnection != null &&
                !string.IsNullOrEmpty(model.Project) &&
                model.Project != NoProjectSelected &&
                (!model.Iterations?.Any() ?? false))
            {
                try
                {
                    model.Iterations = await GetIterationData(defaultConnection, model.Project);
                }
                catch (Exception ex)
                {
                    Trace.WriteLine(ex);
                    model.RunReadyState.NotReady(
                        $"Error loading TFS iterations. Check <a href='{settingsUrl}'>TFS settings</a> " +
                        $"and your connectivity and try again.");
                }
            }

            if (lastReportRun != null)
            {
                if (model.Iterations?.Any() ?? false && model.Iterations.Contains(lastReportRun.Iteration))
                {
                    model.Iteration = lastReportRun.Iteration;
                }
            }
        }