/// <summary> /// Returns a list of users that match the search string. /// This resource cannot be accessed anonymously. /// See: https://docs.atlassian.com/jira/REST/latest/#api/2/user-findUsers /// </summary> /// <param name="query">A query string used to search username, name or e-mail address</param> /// <param name="startAt"></param> /// <param name="maxResults">Maximum number of results returned, default is 20</param> /// <param name="includeActive">If true, then active users are included in the results (default true)</param> /// <param name="includeInactive">If true, then inactive users are included in the results (default false)</param> /// <param name="cancellationToken">CancellationToken</param> /// <returns>SearchResult</returns> public async Task <IList <User> > SearchUserAsync(string query, bool includeActive = true, bool includeInactive = false, int startAt = 0, int maxResults = 20, CancellationToken cancellationToken = default(CancellationToken)) { if (query == null) { throw new ArgumentNullException(nameof(query)); } Log.Debug().WriteLine("Search user via {0}", query); _behaviour.MakeCurrent(); var searchUri = JiraRestUri.AppendSegments("user", "search").ExtendQuery(new Dictionary <string, object> { { "username", query }, { "includeActive", includeActive }, { "includeInactive", includeInactive }, { "startAt", startAt }, { "maxResults", maxResults } }); var response = await searchUri.GetAsAsync <HttpResponse <IList <User>, Error> >(cancellationToken).ConfigureAwait(false); return(HandleErrors(response)); }
/// <summary> /// Attach content to the specified issue /// See: https://docs.atlassian.com/jira/REST/latest/#d2e3035 /// </summary> /// <param name="issueKey"></param> /// <param name="content">the content can be anything what Dapplo.HttpExtensions supports</param> /// <param name="filename">Filename for the attachment</param> /// <param name="contentType">content-type for the attachment</param> /// <param name="cancellationToken">CancellationToken</param> /// <returns>Attachment</returns> public async Task <Attachment> AttachAsync <TContent>(string issueKey, TContent content, string filename, string contentType = null, CancellationToken cancellationToken = default(CancellationToken)) where TContent : class { if (issueKey == null) { throw new ArgumentNullException(nameof(issueKey)); } if (content == null) { throw new ArgumentNullException(nameof(content)); } Log.Debug().WriteLine("Attaching to issue {0}", issueKey); var attachment = new AttachmentContainer <TContent> { Content = content, ContentType = contentType, FileName = filename }; _behaviour.MakeCurrent(); var attachUri = JiraRestUri.AppendSegments("issue", issueKey, "attachments"); var response = await attachUri.PostAsync <HttpResponse <IList <Attachment>, Error> >(attachment, cancellationToken).ConfigureAwait(false); HandleErrors(response); // Return the attachment, should be only one! return(response.Response[0]); }
/// <summary> /// Search for issues, with a JQL (e.g. from a filter) /// See: https://docs.atlassian.com/jira/REST/latest/#d2e2713 /// </summary> /// <param name="jql">Jira Query Language, like SQL, for the search</param> /// <param name="maxResults">Maximum number of results returned, default is 20</param> /// <param name="fields">Jira fields to include, if null the defaults from the JiraConfig.SearchFields are taken</param> /// <param name="cancellationToken">CancellationToken</param> /// <returns>SearchResult</returns> public async Task <SearchResult> SearchAsync(string jql, int maxResults = 20, IEnumerable <string> fields = null, CancellationToken cancellationToken = default(CancellationToken)) { if (jql == null) { throw new ArgumentNullException(nameof(jql)); } Log.Debug().WriteLine("Searching via JQL: {0}", jql); _behaviour.MakeCurrent(); var search = new Search { Jql = jql, ValidateQuery = true, MaxResults = maxResults, Fields = fields ?? new List <string>(JiraConfig.SearchFields) }; var searchUri = JiraRestUri.AppendSegments("search"); // Add the configurable expand values, if the value is not null or empty if (JiraConfig.ExpandSearch?.Length > 0) { searchUri = searchUri.ExtendQuery("expand", string.Join(",", JiraConfig.ExpandSearch)); } var response = await searchUri.PostAsync <HttpResponse <SearchResult, Error> >(search, cancellationToken).ConfigureAwait(false); HandleErrors(response); return(response.Response); }
/// <summary> /// Delete the specified attachment /// </summary> /// <param name="attachmentId">Id from the attachment</param> /// <param name="cancellationToken">CancellationToken</param> public async Task DeleteAttachmentAsync(long attachmentId, CancellationToken cancellationToken = default(CancellationToken)) { Log.Debug().WriteLine("Deleting attachment {0}", attachmentId); _behaviour.MakeCurrent(); var deleteAttachmentUri = JiraRestUri.AppendSegments("attachment", attachmentId); await deleteAttachmentUri.DeleteAsync(cancellationToken).ConfigureAwait(false); }
/// <summary> /// Get currrent user information /// See: https://docs.atlassian.com/jira/REST/latest/#d2e4253 /// </summary> /// <param name="cancellationToken">CancellationToken</param> /// <returns>User</returns> public async Task <User> WhoAmIAsync(CancellationToken cancellationToken = default(CancellationToken)) { Log.Debug().WriteLine("Retieving who I am"); var myselfUri = JiraRestUri.AppendSegments("myself"); _behaviour.MakeCurrent(); var response = await myselfUri.GetAsAsync <HttpResponse <User, Error> >(cancellationToken).ConfigureAwait(false); return(HandleErrors(response)); }
/// <summary> /// Update comment /// See: https://docs.atlassian.com/jira/REST/latest/#d2e1139 /// </summary> /// <param name="issueKey">jira key to which the comment belongs</param> /// <param name="comment">Comment to update</param> /// <param name="cancellationToken">CancellationToken</param> /// <returns>Attachment</returns> public async Task UpdateCommentAsync(string issueKey, Comment comment, CancellationToken cancellationToken = default(CancellationToken)) { if (issueKey == null) { throw new ArgumentNullException(nameof(issueKey)); } Log.Debug().WriteLine("Updating comment {0} for issue {1}", comment.Id, issueKey); _behaviour.MakeCurrent(); var attachUri = JiraRestUri.AppendSegments("issue", issueKey, "comment", comment.Id); await attachUri.PutAsync(comment, cancellationToken).ConfigureAwait(false); }
/// <summary> /// Delete filter /// See: https://docs.atlassian.com/jira/REST/latest/#d2e1388 /// </summary> /// <param name="id">filter id</param> /// <param name="cancellationToken">CancellationToken</param> public async Task DeleteFilterAsync(long id, CancellationToken cancellationToken = default(CancellationToken)) { Log.Debug().WriteLine("Deleting filter {0}", id); _behaviour.MakeCurrent(); var filterUri = JiraRestUri.AppendSegments("filter", id); var response = await filterUri.DeleteAsync <HttpResponse <string, Error> >(cancellationToken).ConfigureAwait(false); if (response.StatusCode != HttpStatusCode.NoContent) { throw new Exception(string.Join(", ", response.ErrorResponse.ErrorMessages)); } }
/// <summary> /// Get user information /// See: https://docs.atlassian.com/jira/REST/latest/#d2e5339 /// </summary> /// <param name="username"></param> /// <param name="cancellationToken">CancellationToken</param> /// <returns>User</returns> public async Task <User> GetUserAsync(string username, CancellationToken cancellationToken = default(CancellationToken)) { if (username == null) { throw new ArgumentNullException(nameof(username)); } Log.Debug().WriteLine("Retrieving user {0}", username); var userUri = JiraRestUri.AppendSegments("user").ExtendQuery("username", username); _behaviour.MakeCurrent(); var response = await userUri.GetAsAsync <HttpResponse <User, Error> >(cancellationToken).ConfigureAwait(false); return(HandleErrors(response)); }
/// <summary> /// Get all visible projects /// See: https://docs.atlassian.com/jira/REST/latest/#d2e2779 /// </summary> /// <param name="cancellationToken">CancellationToken</param> /// <returns>list of ProjectDigest</returns> public async Task <IList <ProjectDigest> > GetProjectsAsync(CancellationToken cancellationToken = default(CancellationToken)) { Log.Debug().WriteLine("Retrieving projects"); var projectsUri = JiraRestUri.AppendSegments("project"); // Add the configurable expand values, if the value is not null or empty if (JiraConfig.ExpandGetProjects?.Length > 0) { projectsUri = projectsUri.ExtendQuery("expand", string.Join(",", JiraConfig.ExpandGetProjects)); } _behaviour.MakeCurrent(); var response = await projectsUri.GetAsAsync <HttpResponse <IList <ProjectDigest>, Error> >(cancellationToken).ConfigureAwait(false); return(HandleErrors(response)); }
/// <summary> /// Get filter /// See: https://docs.atlassian.com/jira/REST/latest/#d2e1388 /// </summary> /// <param name="id">filter id</param> /// <param name="cancellationToken">CancellationToken</param> /// <returns>Filter</returns> public async Task <Filter> GetFilterAsync(long id, CancellationToken cancellationToken = default(CancellationToken)) { Log.Debug().WriteLine("Retrieving filter {0}", id); _behaviour.MakeCurrent(); var filterUri = JiraRestUri.AppendSegments("filter", id); // Add the configurable expand values, if the value is not null or empty if (JiraConfig.ExpandGetFilter?.Length > 0) { filterUri = filterUri.ExtendQuery("expand", string.Join(",", JiraConfig.ExpandGetFilter)); } var response = await filterUri.GetAsAsync <HttpResponse <Filter, Error> >(cancellationToken).ConfigureAwait(false); return(HandleErrors(response)); }
/// <summary> /// Get possible transitions for the specified issue /// See: https://docs.atlassian.com/jira/REST/latest/#d2e1289 /// </summary> /// <param name="issueKey">the issue key</param> /// <param name="cancellationToken">CancellationToken</param> /// <returns>Issue</returns> public async Task <IList <Transition> > GetPossibleTransitionsAsync(string issueKey, CancellationToken cancellationToken = default(CancellationToken)) { if (issueKey == null) { throw new ArgumentNullException(nameof(issueKey)); } Log.Debug().WriteLine("Retrieving transition information for {0}", issueKey); var transitionsUri = JiraRestUri.AppendSegments("issue", issueKey, "transitions"); if (JiraConfig.ExpandGetTransitions?.Length > 0) { transitionsUri = transitionsUri.ExtendQuery("expand", string.Join(",", JiraConfig.ExpandGetTransitions)); } _behaviour.MakeCurrent(); var response = await transitionsUri.GetAsAsync <HttpResponse <Transitions, Error> >(cancellationToken).ConfigureAwait(false); HandleErrors(response); return(response.Response.Items); }
/// <summary> /// Get server information /// See: https://docs.atlassian.com/jira/REST/latest/#d2e3828 /// </summary> /// <param name="cancellationToken">CancellationToken</param> /// <returns>ServerInfo</returns> public async Task <ServerInfo> GetServerInfoAsync(CancellationToken cancellationToken = default(CancellationToken)) { Log.Debug().WriteLine("Retrieving server information"); var serverInfoUri = JiraRestUri.AppendSegments("serverInfo"); _behaviour.MakeCurrent(); var response = await serverInfoUri.GetAsAsync <HttpResponse <ServerInfo, Error> >(cancellationToken).ConfigureAwait(false); if (response.HasError) { return(HandleErrors(response)); } var serverInfo = response.Response; Log.Debug().WriteLine("Server title {0}, version {1}, uri {2}, build date {3}, build number {4}, scm info {5}", serverInfo.ServerTitle, serverInfo.Version, serverInfo.BaseUrl, serverInfo.BuildDate, serverInfo.BuildNumber, serverInfo.ScmInfo); return(HandleErrors(response)); }
/// <summary> /// Get issue information /// See: https://docs.atlassian.com/jira/REST/latest/#d2e4539 /// </summary> /// <param name="issueKey">the issue key</param> /// <param name="cancellationToken">CancellationToken</param> /// <returns>Issue</returns> public async Task <Issue> GetIssueAsync(string issueKey, CancellationToken cancellationToken = default(CancellationToken)) { if (issueKey == null) { throw new ArgumentNullException(nameof(issueKey)); } Log.Debug().WriteLine("Retrieving issue information for {0}", issueKey); var issueUri = JiraRestUri.AppendSegments("issue", issueKey); // Add the configurable expand values, if the value is not null or empty if (JiraConfig.ExpandGetIssue?.Length > 0) { issueUri = issueUri.ExtendQuery("expand", string.Join(",", JiraConfig.ExpandGetIssue)); } _behaviour.MakeCurrent(); var response = await issueUri.GetAsAsync <HttpResponse <Issue, Error> >(cancellationToken).ConfigureAwait(false); HandleErrors(response); return(response.Response); }
/// <summary> /// Add comment to the specified issue /// See: https://docs.atlassian.com/jira/REST/latest/#d2e1139 /// </summary> /// <param name="issueKey">key for the issue</param> /// <param name="body">the body of the comment</param> /// <param name="visibility">optional visibility role</param> /// <param name="cancellationToken">CancellationToken</param> /// <returns>Attachment</returns> public async Task AddCommentAsync(string issueKey, string body, string visibility = null, CancellationToken cancellationToken = default(CancellationToken)) { if (issueKey == null) { throw new ArgumentNullException(nameof(issueKey)); } Log.Debug().WriteLine("Adding comment to {0}", issueKey); var comment = new Comment { Body = body, Visibility = visibility == null ? null : new Visibility { Type = "role", Value = visibility } }; _behaviour.MakeCurrent(); var attachUri = JiraRestUri.AppendSegments("issue", issueKey, "comment"); await attachUri.PostAsync(comment, cancellationToken).ConfigureAwait(false); }
/// <summary> /// Get projects information /// See: https://docs.atlassian.com/jira/REST/latest/#d2e2779 /// </summary> /// <param name="projectKey">key of the project</param> /// <param name="cancellationToken">CancellationToken</param> /// <returns>ProjectDetails</returns> public async Task <Project> GetProjectAsync(string projectKey, CancellationToken cancellationToken = default(CancellationToken)) { if (projectKey == null) { throw new ArgumentNullException(nameof(projectKey)); } Log.Debug().WriteLine("Retrieving project {0}", projectKey); var projectUri = JiraRestUri.AppendSegments("project", projectKey); // Add the configurable expand values, if the value is not null or empty if (JiraConfig.ExpandGetProject?.Length > 0) { projectUri = projectUri.ExtendQuery("expand", string.Join(",", JiraConfig.ExpandGetProject)); } _behaviour.MakeCurrent(); var response = await projectUri.GetAsAsync <HttpResponse <Project, Error> >(cancellationToken).ConfigureAwait(false); return(HandleErrors(response)); }