// 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); }
private bool ShouldSelectConnection(TfsKnownConnection knownConn, ReportRun lastReportRun) { if (lastReportRun == null) { return(false); } var select = knownConn.Id == lastReportRun.ConnectionId; return(select); }
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); }
// 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); }
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); }
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; }
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); }
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}." }); }
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; } } }