├── .gitignore ├── README.md ├── JiraRestClient.Net ├── JiraRestClient.Net │ ├── ApiVersion.cs │ ├── Domain │ │ ├── Component.cs │ │ ├── Issue │ │ │ ├── IssueResponse.cs │ │ │ ├── IssueType.cs │ │ │ ├── IssueUpdate.cs │ │ │ └── Issue.cs │ │ ├── Permissions.cs │ │ ├── Base.cs │ │ ├── Permission.cs │ │ ├── Version.cs │ │ ├── Attachment.cs │ │ ├── ServerInfo.cs │ │ ├── Project.cs │ │ ├── Error.cs │ │ └── User.cs │ ├── README.md │ ├── Properties │ │ └── PublishProfiles │ │ │ ├── FolderProfile.pubxml.user │ │ │ └── FolderProfile.pubxml │ ├── Jql │ │ ├── JqlSearchResult.cs │ │ ├── SortOrder.cs │ │ ├── ERoles.cs │ │ ├── JqlSearchBean.cs │ │ ├── JqlBuilder.cs │ │ ├── EKeyword.cs │ │ ├── EField.cs │ │ ├── EFieldType.cs │ │ └── EOperator.cs │ ├── Core │ │ ├── BaseClient.cs │ │ ├── Extension │ │ │ └── UriExtension.cs │ │ ├── SearchClient.cs │ │ ├── UserClient.cs │ │ ├── SystemClient.cs │ │ ├── PermissionsClient.cs │ │ ├── ProjectClient.cs │ │ ├── Converter │ │ │ └── PermissionListConverter.cs │ │ └── IssueClient.cs │ ├── JiraRestClient.Net.csproj │ ├── Util │ │ ├── RestParamConstants.cs │ │ ├── RestPathConstants.cs │ │ ├── Constants.cs │ │ └── JsonConstants.cs │ ├── LICENSE.txt │ └── JiraRestClient.cs ├── .gitignore ├── JiraRestClient.Net.Test │ ├── Resources │ │ ├── frogs.png │ │ ├── test.pdf │ │ └── test.runsettings │ ├── TestPermissionsClient.cs │ ├── TestSystemClient.cs │ ├── TestProjectClient.cs │ ├── BaseTest.cs │ ├── TestUriExtension.cs │ ├── TestUserClient.cs │ ├── TestConfiguration.cs │ ├── TestSearchClient.cs │ ├── JiraRestClient.Net.Test.csproj │ ├── Examples │ │ ├── attachments.json │ │ ├── IssueUpdateSchema.json │ │ ├── issue.json │ │ ├── v3 │ │ │ └── issue.json │ │ └── MyPermissions.json │ └── TestIssueClient.cs ├── JiraRestClient.Net.sln.DotSettings.user └── JiraRestClient.Net.sln └── .vscode ├── tasks.json └── launch.json /.gitignore: -------------------------------------------------------------------------------- 1 | /JiraRestClient.Net/.idea/ 2 | .idea 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # JiraRestClient.NETCore 2 | 3 | A RestClient for Jira REST API V2 for .NET Core. 4 | -------------------------------------------------------------------------------- /JiraRestClient.Net/JiraRestClient.Net/ApiVersion.cs: -------------------------------------------------------------------------------- 1 | namespace JiraRestClient.Net; 2 | 3 | public enum ApiVersion 4 | { 5 | V2, V3 6 | } -------------------------------------------------------------------------------- /JiraRestClient.Net/.gitignore: -------------------------------------------------------------------------------- 1 | /JiraRestClient.Net/.idea/ 2 | /JiraRestClient.Net/obj 3 | /JiraRestClient.Net/bin 4 | .idea 5 | /JiraRestClient.Net.Test/obj 6 | /JiraRestClient.Net.Test/bin -------------------------------------------------------------------------------- /JiraRestClient.Net/JiraRestClient.Net.Test/Resources/frogs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mrkoenigstein/JiraRestClient.NETCore/HEAD/JiraRestClient.Net/JiraRestClient.Net.Test/Resources/frogs.png -------------------------------------------------------------------------------- /JiraRestClient.Net/JiraRestClient.Net.Test/Resources/test.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mrkoenigstein/JiraRestClient.NETCore/HEAD/JiraRestClient.Net/JiraRestClient.Net.Test/Resources/test.pdf -------------------------------------------------------------------------------- /JiraRestClient.Net/JiraRestClient.Net/Domain/Component.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | 3 | namespace JiraRestClient.Net.Domain 4 | { 5 | public class Component :Base 6 | { 7 | [JsonPropertyName("description")] 8 | public string Description { get; set; } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.1.0", 3 | "command": "dotnet", 4 | "isShellCommand": true, 5 | "args": [], 6 | "tasks": [ 7 | { 8 | "taskName": "build", 9 | "args": [], 10 | "isBuildCommand": true, 11 | "problemMatcher": "$msCompile" 12 | } 13 | ] 14 | } -------------------------------------------------------------------------------- /JiraRestClient.Net/JiraRestClient.Net/README.md: -------------------------------------------------------------------------------- 1 | # JiraRestClient.NETCore 2 | 3 | A RestClient for Jira REST API V2 using .NetStandard2.0 4 | 5 | ## Changelog 6 | 7 | # Version 3.0 8 | 9 | * Change the Client to communicate with Cloud Jira and Rest Api v3 10 | * This Client works only for Jira Cloud and Rest Api V3 11 | 12 | # Version 2.1 13 | 14 | * This Client works only for Jira Server and Rest Api V2 15 | * Add AddAttachment to IssueClient -------------------------------------------------------------------------------- /JiraRestClient.Net/JiraRestClient.Net/Domain/Issue/IssueResponse.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Text.Json.Serialization; 3 | 4 | namespace JiraRestClient.Net.Domain.Issue 5 | { 6 | public class IssueResponse : KeyBase 7 | { 8 | [JsonPropertyName("errorMessages")] 9 | public List ErrorMessages { get; set; } 10 | 11 | [JsonPropertyName("errors")] 12 | public Errors Errors { get; set; } 13 | } 14 | } -------------------------------------------------------------------------------- /JiraRestClient.Net/JiraRestClient.Net/Properties/PublishProfiles/FolderProfile.pubxml.user: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | -------------------------------------------------------------------------------- /JiraRestClient.Net/JiraRestClient.Net/Domain/Issue/IssueType.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | 3 | namespace JiraRestClient.Net.Domain.Issue 4 | { 5 | public class IssueType : Base 6 | { 7 | [JsonPropertyName("description")] 8 | public string Description { get; set; } 9 | [JsonPropertyName("iconurl")] 10 | public string IconUrl { get; set; } 11 | [JsonPropertyName("subtask")] 12 | public bool Subtask { get; set; } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /JiraRestClient.Net/JiraRestClient.Net.Test/Resources/test.runsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /JiraRestClient.Net/JiraRestClient.Net/Jql/JqlSearchResult.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using JiraRestClient.Net.Domain.Issue; 3 | 4 | namespace JiraRestClient.Net.Jql 5 | { 6 | public class JqlSearchResult 7 | { 8 | public string Expand { get; set; } 9 | 10 | public int StartAt { get; set; } 11 | 12 | public int MaxResults { get; set; } 13 | 14 | public int Total { get; set; } 15 | 16 | public List Issues { get; set; } 17 | 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /JiraRestClient.Net/JiraRestClient.Net.Test/TestPermissionsClient.cs: -------------------------------------------------------------------------------- 1 | using FluentAssertions; 2 | using Microsoft.VisualStudio.TestTools.UnitTesting; 3 | 4 | namespace JiraRestClient.Net.Test 5 | { 6 | [TestClass] 7 | public class TestPermissionsClient : BaseTest 8 | { 9 | 10 | [TestMethod] 11 | public void TestGetMyPermissions() 12 | { 13 | var myPermissions = RestClient.PermissionsClient.GetMyPermissions(ProjectKey); 14 | myPermissions.Should().NotBeNull(); 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /JiraRestClient.Net/JiraRestClient.Net/Jql/SortOrder.cs: -------------------------------------------------------------------------------- 1 | namespace JiraRestClient.Net.Jql 2 | { 3 | public class SortOrder 4 | { 5 | private string Name { get; set; } 6 | 7 | public static readonly SortOrder Desc = new SortOrder("desc"); 8 | public static readonly SortOrder Asc = new SortOrder("asc"); 9 | 10 | private SortOrder(string name) 11 | { 12 | Name = name; 13 | } 14 | 15 | public override string ToString() 16 | { 17 | return Name; 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /JiraRestClient.Net/JiraRestClient.Net.sln.DotSettings.user: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | D:\github\JiraRestClient.NETCore\JiraRestClient.Net\JiraRestClient.Net.Test\Resources\test.runsettings -------------------------------------------------------------------------------- /JiraRestClient.Net/JiraRestClient.Net/Domain/Permissions.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | 3 | namespace JiraRestClient.Net.Domain 4 | { 5 | public class Permissions : Base 6 | { 7 | [JsonPropertyName("permissions")] 8 | public PermissionsList PermissionsList { get; set; } 9 | } 10 | 11 | public class PermissionsList 12 | { 13 | [JsonPropertyName("CREATE_ISSUES")] 14 | public Permission CreateIssue { get; set; } 15 | 16 | [JsonPropertyName("EDIT_ISSUE")] 17 | public Permission EditIssue { get; set; } 18 | } 19 | } -------------------------------------------------------------------------------- /JiraRestClient.Net/JiraRestClient.Net/Domain/Base.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | 3 | namespace JiraRestClient.Net.Domain 4 | { 5 | public class Base 6 | { 7 | [JsonPropertyName("id")] 8 | public string Id { get; set; } 9 | 10 | [JsonPropertyName("self")] 11 | public string Self { get; set; } 12 | 13 | [JsonPropertyName("name")] 14 | public string Name { get; set; } 15 | } 16 | 17 | public class KeyBase : Base 18 | { 19 | [JsonPropertyName("key")] 20 | public string Key { get; set; } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /JiraRestClient.Net/JiraRestClient.Net/Jql/ERoles.cs: -------------------------------------------------------------------------------- 1 | using JiraRestClient.Net.Util; 2 | 3 | namespace JiraRestClient.Net.Jql 4 | { 5 | public class ERoles 6 | { 7 | public static readonly ERoles Administrators = new ERoles(JsonConstants.RoleAdministrators); 8 | public static readonly ERoles Users = new ERoles(JsonConstants.RoleUsers); 9 | public static readonly ERoles Developers = new ERoles(JsonConstants.RoleDevelopers); 10 | 11 | private string Name { get; set; } 12 | 13 | public ERoles(string name) 14 | { 15 | Name = name; 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /JiraRestClient.Net/JiraRestClient.Net/Domain/Permission.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | 3 | namespace JiraRestClient.Net.Domain 4 | { 5 | public class Permission : KeyBase 6 | { 7 | [JsonPropertyName("type")] 8 | public string Type { get; set; } 9 | 10 | [JsonPropertyName("description")] 11 | public string Description{ get; set; } 12 | 13 | [JsonPropertyName("havePermission")] 14 | public bool HavePermission { get; set; } 15 | 16 | [JsonPropertyName("deprecatedKey")] 17 | public bool DeprecatedKey { get; set; } 18 | } 19 | } -------------------------------------------------------------------------------- /JiraRestClient.Net/JiraRestClient.Net/Core/BaseClient.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Net.Http; 3 | 4 | namespace JiraRestClient.Net.Core 5 | { 6 | /// 7 | /// Base Class for all Clients, contains common Informations. 8 | /// 9 | public abstract class BaseClient 10 | { 11 | protected readonly Uri BaseUri; 12 | 13 | protected readonly HttpClient Client; 14 | 15 | protected readonly string Username; 16 | 17 | protected BaseClient(JiraRestClient jiraRestClient) 18 | { 19 | Client = jiraRestClient.Client; 20 | BaseUri = jiraRestClient.BaseUri; 21 | Username = jiraRestClient.Username; 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /JiraRestClient.Net/JiraRestClient.Net.Test/TestSystemClient.cs: -------------------------------------------------------------------------------- 1 | using FluentAssertions; 2 | using Microsoft.VisualStudio.TestTools.UnitTesting; 3 | 4 | namespace JiraRestClient.Net.Test 5 | { 6 | [TestClass] 7 | public class TestSystemClient : BaseTest 8 | { 9 | 10 | [TestMethod] 11 | public void TestGetIssueTypes() 12 | { 13 | var issueTypes = RestClient.SystemClient.GetIssueTypes(); 14 | issueTypes.Should().NotBeNullOrEmpty(); 15 | } 16 | 17 | [TestMethod] 18 | public void TestGetPriorities(){ 19 | var priorities = RestClient.SystemClient.GetPriorities(); 20 | priorities.Should().NotBeNullOrEmpty(); 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /JiraRestClient.Net/JiraRestClient.Net/Properties/PublishProfiles/FolderProfile.pubxml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | FileSystem 9 | Release 10 | netcoreapp1.0 11 | bin\Release\PublishOutput 12 | 13 | -------------------------------------------------------------------------------- /JiraRestClient.Net/JiraRestClient.Net.Test/TestProjectClient.cs: -------------------------------------------------------------------------------- 1 | using FluentAssertions; 2 | using Microsoft.VisualStudio.TestTools.UnitTesting; 3 | 4 | namespace JiraRestClient.Net.Test 5 | { 6 | [TestClass] 7 | public class TestProjectClient :BaseTest 8 | { 9 | [TestMethod] 10 | public void TestGetAllProjects(){ 11 | var task = RestClient.ProjectClient.GetAllProjects(); 12 | task.Should().NotBeNullOrEmpty(); 13 | } 14 | 15 | [TestMethod] 16 | public void TestProjectByKey(){ 17 | var project = RestClient.ProjectClient.GetProjectByKey(ProjectKey); 18 | project.Should().NotBeNull(); 19 | project.Key.Should().Be(ProjectKey); 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /JiraRestClient.Net/JiraRestClient.Net/Domain/Version.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | 3 | namespace JiraRestClient.Net.Domain 4 | { 5 | public class Version :Base 6 | { 7 | [JsonPropertyName("description")] 8 | public string Description { get; set; } 9 | [JsonPropertyName("archived")] 10 | public bool Archived { get; set; } 11 | [JsonPropertyName("released")] 12 | public bool Released { get; set; } 13 | [JsonPropertyName("overdue")] 14 | public bool Overdue { get; set; } 15 | [JsonPropertyName("releasedate")] 16 | public string ReleaseDate { get; set; } 17 | [JsonPropertyName("userreleasedate")] 18 | public string UserReleaseDate { get; set; } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /JiraRestClient.Net/JiraRestClient.Net.Test/BaseTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace JiraRestClient.Net.Test; 4 | 5 | public abstract class BaseTest 6 | { 7 | protected readonly Uri Uri = new(""); 8 | 9 | /// 10 | /// To get a User from the RestApi 11 | /// 12 | protected const string AccountId = ""; 13 | 14 | protected const string Username = ""; 15 | 16 | protected const string Password = ""; 17 | 18 | protected const string ProjectKey = "KAN"; 19 | 20 | protected const string IssueKeyToSearch = "KAN-1"; 21 | 22 | protected readonly JiraRestClient RestClient; 23 | 24 | protected Uri BaseUri; 25 | 26 | public BaseTest(){ 27 | RestClient = new JiraRestClient(Uri, Username, Password); 28 | BaseUri = RestClient.BaseUri; 29 | } 30 | } -------------------------------------------------------------------------------- /JiraRestClient.Net/JiraRestClient.Net/Domain/Attachment.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | 3 | namespace JiraRestClient.Net.Domain; 4 | 5 | public class Attachment 6 | { 7 | [JsonPropertyName("author")] 8 | private User Author { get; set; } 9 | 10 | [JsonPropertyName("content")] 11 | private string Content { get; set; } 12 | 13 | [JsonPropertyName("created")] 14 | private string Created { get; set; } 15 | 16 | [JsonPropertyName("filename")] 17 | private string Filename { get; set; } 18 | 19 | [JsonPropertyName("id")] 20 | private string Id { get; set; } 21 | 22 | [JsonPropertyName("self")] 23 | private string Self { get; set; } 24 | 25 | [JsonPropertyName("size")] 26 | private string Size { get; set; } 27 | 28 | [JsonPropertyName("thumbmail")] 29 | private string Thumbnail { get; set; } 30 | } -------------------------------------------------------------------------------- /JiraRestClient.Net/JiraRestClient.Net/JiraRestClient.Net.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netstandard2.0 5 | JiraRestClient.Net 6 | 3.1 7 | Christian Schulze (mrkoenigstein@outlook.com) 8 | true 9 | latest 10 | Library 11 | true 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | Always 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /JiraRestClient.Net/JiraRestClient.Net/Util/RestParamConstants.cs: -------------------------------------------------------------------------------- 1 | namespace JiraRestClient.Net.Util 2 | { 3 | public class RestParamConstants 4 | { 5 | public const string Username = "username"; 6 | 7 | public const string Expand = "expand"; 8 | 9 | public const string TransitionsFields = "transitions.fields"; 10 | 11 | public const string RenderedFields = "renderedFields"; 12 | 13 | public const string IssueKey = "issueKey"; 14 | 15 | public const string IssueId = "IssueId"; 16 | 17 | public const string StartAt = "startAt"; 18 | 19 | public const string MaxResults = "maxResults"; 20 | 21 | public const string Project = "project"; 22 | 23 | public const string ProjectKey = "projectKey"; 24 | 25 | public const string ProjectId = "projectId"; 26 | 27 | public const string Fields = "fields"; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /JiraRestClient.Net/JiraRestClient.Net.Test/TestUriExtension.cs: -------------------------------------------------------------------------------- 1 | using JiraRestClient.Net.Core.Extension; 2 | using JiraRestClient.Net.Util; 3 | using Microsoft.VisualStudio.TestTools.UnitTesting; 4 | 5 | namespace JiraRestClient.Net.Test 6 | { 7 | [TestClass] 8 | public class TestUriHelper : BaseTest 9 | { 10 | [TestMethod] 11 | public void TestBuilderPath() 12 | { 13 | var uri = BaseUri.AddPaths(RestPathConstants.User, RestPathConstants.Attachments, 14 | RestParamConstants.IssueKey); 15 | Assert.AreEqual($"{BaseUri}/user/attachments/issueKey", uri.ToString()); 16 | } 17 | 18 | [TestMethod] 19 | public void TestAddQuery() 20 | { 21 | var uri = BaseUri.AddQuery("expand=summary", "field=renderedFields"); 22 | Assert.AreEqual($"{BaseUri}?expand=summary&field=renderedFields", 23 | uri.ToString()); 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /JiraRestClient.Net/JiraRestClient.Net/Domain/ServerInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Text.Json.Serialization; 3 | 4 | namespace JiraRestClient.Net.Domain 5 | { 6 | public class ServerInfo 7 | { 8 | [JsonPropertyName("baseurl")] 9 | public string BaseUrl { get; set; } 10 | [JsonPropertyName("version")] 11 | public string Version { get; set; } 12 | [JsonPropertyName("versionnumbers")] 13 | public IList VersionNumbers { get; set; } 14 | [JsonPropertyName("buildnumber")] 15 | public int BuildNumber { get; set; } 16 | [JsonPropertyName("builddate")] 17 | public string BuildDate { get; set; } 18 | [JsonPropertyName("servertime")] 19 | public string ServerTime { get; set; } 20 | [JsonPropertyName("scminfo")] 21 | public string ScmInfo { get; set; } 22 | [JsonPropertyName("servertitle")] 23 | public string ServerTitle { get; set; } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /JiraRestClient.Net/JiraRestClient.Net.Test/TestUserClient.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using FluentAssertions; 3 | using Microsoft.VisualStudio.TestTools.UnitTesting; 4 | 5 | namespace JiraRestClient.Net.Test 6 | { 7 | [TestClass] 8 | public class TestUserClient : BaseTest 9 | { 10 | 11 | [TestMethod] 12 | public void TestGetUserByUsername() 13 | { 14 | var userClient = RestClient.UserClient; 15 | var user = userClient.GetUserByUsername(AccountId); 16 | user.Should().NotBeNull(); 17 | } 18 | 19 | [TestMethod] 20 | public void TestGetAccountIds() 21 | { 22 | var usernames = new List 23 | { 24 | Username 25 | }; 26 | var userClient = RestClient.UserClient; 27 | var userMigrations = userClient.GetAccountIds(usernames); 28 | userMigrations.Should().NotBeNull().And.NotBeEmpty(); 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /JiraRestClient.Net/JiraRestClient.Net/Core/Extension/UriExtension.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | 4 | namespace JiraRestClient.Net.Core.Extension; 5 | 6 | public static class UriExtension 7 | { 8 | public static Uri AddPaths(this Uri uri, params string[] paths) 9 | { 10 | return new Uri(paths.Aggregate(uri.AbsoluteUri, (current, path) => 11 | $"{current.TrimEnd('/')}/{path.TrimStart('/')}")); 12 | } 13 | 14 | public static Uri AddQuery(this Uri uri, params string[] query) 15 | { 16 | var uriBuilder = new UriBuilder(uri) { Query = string.Join("&", query) }; 17 | return uriBuilder.Uri; 18 | } 19 | 20 | public static Uri AddQuery(this Uri uri, string query) 21 | { 22 | var uriBuilder = new UriBuilder(uri) { Query = query }; 23 | return uriBuilder.Uri; 24 | } 25 | 26 | public static Uri AddIssueKey(this Uri uri, string issueKey) 27 | { 28 | var temp = uri.AbsoluteUri + "/"; 29 | var retVal = new Uri(temp); 30 | return new Uri(retVal, issueKey); 31 | } 32 | } -------------------------------------------------------------------------------- /JiraRestClient.Net/JiraRestClient.Net/Core/SearchClient.cs: -------------------------------------------------------------------------------- 1 | using System.Net.Http; 2 | using System.Text; 3 | using System.Text.Json; 4 | using JiraRestClient.Net.Core.Extension; 5 | using JiraRestClient.Net.Jql; 6 | using JiraRestClient.Net.Util; 7 | 8 | namespace JiraRestClient.Net.Core 9 | { 10 | public class SearchClient : BaseClient 11 | { 12 | public SearchClient(JiraRestClient jiraRestClient) : base(jiraRestClient) 13 | { 14 | } 15 | 16 | public JqlSearchResult SearchIssues(JqlSearchBean jqlSearchBean) 17 | { 18 | var json = JsonSerializer.Serialize(jqlSearchBean); 19 | var uri = BaseUri.AddPaths(RestPathConstants.Search); 20 | var httpContent = new StringContent(json, Encoding.UTF8, "application/json"); 21 | var response = Client.PostAsync(uri.ToString(), httpContent); 22 | var readAsStringAsync = response.Result.Content.ReadAsStringAsync(); 23 | var result = readAsStringAsync.Result; 24 | return JsonSerializer.Deserialize(result); 25 | } 26 | } 27 | 28 | } -------------------------------------------------------------------------------- /JiraRestClient.Net/JiraRestClient.Net/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright 2020 Christian Schulze (cschulc@outlook.com) 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /JiraRestClient.Net/JiraRestClient.Net.Test/TestConfiguration.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using Microsoft.VisualStudio.TestTools.UnitTesting; 4 | 5 | namespace JiraRestClient.Net.Test; 6 | 7 | public class TestConfiguration 8 | { 9 | private readonly IDictionary _properties; 10 | 11 | public Uri Uri => new(GetProperty("BaseUrl")); 12 | 13 | public string AccountId => GetProperty("AccountId"); 14 | 15 | public string Username => GetProperty("Username"); 16 | 17 | public string Password => GetProperty("Password"); 18 | 19 | public string ProjectKey => GetProperty("ProjectKey"); 20 | 21 | public string IssueKeyToSearch => GetProperty("IssueKeyToSearch"); 22 | 23 | public TestConfiguration(TestContext testContext) 24 | { 25 | _properties = testContext.Properties; 26 | } 27 | 28 | private string GetProperty(string name) 29 | { 30 | if (_properties.Contains(name) == false) 31 | { 32 | return null; 33 | } 34 | 35 | var property = _properties[name]; 36 | return property as string; 37 | } 38 | } -------------------------------------------------------------------------------- /JiraRestClient.Net/JiraRestClient.Net.Test/TestSearchClient.cs: -------------------------------------------------------------------------------- 1 | using FluentAssertions; 2 | using JiraRestClient.Net.Jql; 3 | using JiraRestClient.Net.Util; 4 | using Microsoft.VisualStudio.TestTools.UnitTesting; 5 | 6 | namespace JiraRestClient.Net.Test 7 | { 8 | [TestClass] 9 | public class TestSearchClient : BaseTest 10 | { 11 | [TestMethod] 12 | public void TestSearchIssues() 13 | { 14 | var jsb = new JqlSearchBean(); 15 | var builder = new JqlBuilder(); 16 | var jql = builder.AddCondition(EField.Project, EOperator.EQUALS, "DEMO") 17 | .And().AddCondition(EField.Status, EOperator.EQUALS, Constants.StatusInProgress) 18 | .OrderBy(SortOrder.Asc, EField.Created); 19 | jsb.Jql = jql; 20 | jsb.AddField(EField.IssueKey, EField.Status, EField.Due, EField.Summary, EField.IssueType, EField.Priority, EField.Updated, EField.Transitions); 21 | jsb.AddExpand(EField.Transitions); 22 | var result = RestClient.SearchClient.SearchIssues(jsb); 23 | result.Should().NotBeNull(); 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /JiraRestClient.Net/JiraRestClient.Net.Test/JiraRestClient.Net.Test.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net6.0 5 | 6 | false 7 | 8 | 11 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | Always 26 | 27 | 28 | Always 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /JiraRestClient.Net/JiraRestClient.Net/Core/UserClient.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Text.Json; 3 | using JiraRestClient.Net.Core.Extension; 4 | using JiraRestClient.Net.Domain; 5 | using JiraRestClient.Net.Util; 6 | 7 | namespace JiraRestClient.Net.Core; 8 | 9 | public class UserClient : BaseClient 10 | { 11 | public UserClient(JiraRestClient jiraRestClient) : base(jiraRestClient) 12 | { 13 | } 14 | 15 | public User GetUserByUsername(string accountId) 16 | { 17 | var uri = BaseUri.AddPaths(RestPathConstants.User); 18 | uri = uri.AddQuery($"accountId={accountId}"); 19 | var stream = Client.GetStringAsync(uri); 20 | var result = stream.Result; 21 | return JsonSerializer.Deserialize(result); 22 | } 23 | 24 | public IEnumerable GetAccountIds(List username) 25 | { 26 | var uri = BaseUri.AddPaths(RestPathConstants.User, RestPathConstants.Bulk, RestPathConstants.Migration); 27 | uri = uri.AddQuery($"username={username}"); 28 | var stream = Client.GetStringAsync(uri); 29 | var streamResult = stream.Result; 30 | return JsonSerializer.Deserialize>(streamResult); 31 | } 32 | } -------------------------------------------------------------------------------- /JiraRestClient.Net/JiraRestClient.Net.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JiraRestClient.Net", "JiraRestClient.Net\JiraRestClient.Net.csproj", "{3475F11D-B88A-4611-9623-3FBF9B33985B}" 4 | EndProject 5 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JiraRestClient.Net.Test", "JiraRestClient.Net.Test\JiraRestClient.Net.Test.csproj", "{A305E2B0-796F-42F5-9BBD-FFEE7A8D7BCE}" 6 | EndProject 7 | Global 8 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 9 | Debug|Any CPU = Debug|Any CPU 10 | Release|Any CPU = Release|Any CPU 11 | EndGlobalSection 12 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 13 | {3475F11D-B88A-4611-9623-3FBF9B33985B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 14 | {3475F11D-B88A-4611-9623-3FBF9B33985B}.Debug|Any CPU.Build.0 = Debug|Any CPU 15 | {3475F11D-B88A-4611-9623-3FBF9B33985B}.Release|Any CPU.ActiveCfg = Release|Any CPU 16 | {3475F11D-B88A-4611-9623-3FBF9B33985B}.Release|Any CPU.Build.0 = Release|Any CPU 17 | {A305E2B0-796F-42F5-9BBD-FFEE7A8D7BCE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 18 | {A305E2B0-796F-42F5-9BBD-FFEE7A8D7BCE}.Debug|Any CPU.Build.0 = Debug|Any CPU 19 | {A305E2B0-796F-42F5-9BBD-FFEE7A8D7BCE}.Release|Any CPU.ActiveCfg = Release|Any CPU 20 | {A305E2B0-796F-42F5-9BBD-FFEE7A8D7BCE}.Release|Any CPU.Build.0 = Release|Any CPU 21 | EndGlobalSection 22 | EndGlobal 23 | -------------------------------------------------------------------------------- /JiraRestClient.Net/JiraRestClient.Net/Core/SystemClient.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Text.Json; 3 | using JiraRestClient.Net.Core.Extension; 4 | using JiraRestClient.Net.Domain.Issue; 5 | using JiraRestClient.Net.Util; 6 | 7 | namespace JiraRestClient.Net.Core 8 | { 9 | public class SystemClient : BaseClient 10 | { 11 | public SystemClient(JiraRestClient jiraRestClient) : base(jiraRestClient) 12 | { 13 | } 14 | 15 | public IEnumerable GetIssueTypes() 16 | { 17 | var restUriBuilder = BaseUri.AddPaths(RestPathConstants.IssueTypes); 18 | var stream = Client.GetStringAsync(restUriBuilder.ToString()); 19 | return JsonSerializer.Deserialize>(stream.Result); 20 | } 21 | 22 | public IEnumerable GetPriorities(){ 23 | var restUriBuilder = BaseUri.AddPaths(RestPathConstants.Priority); 24 | var stream = Client.GetStringAsync(restUriBuilder.ToString()); 25 | return JsonSerializer.Deserialize>(stream.Result); 26 | } 27 | 28 | public List GetStates(){ 29 | var restUriBuilder = BaseUri.AddPaths(RestPathConstants.Status); 30 | var stream = Client.GetStringAsync(restUriBuilder.ToString()); 31 | return JsonSerializer.Deserialize>(stream.Result); 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /JiraRestClient.Net/JiraRestClient.Net/Util/RestPathConstants.cs: -------------------------------------------------------------------------------- 1 | namespace JiraRestClient.Net.Util 2 | { 3 | public class RestPathConstants : JsonConstants 4 | { 5 | 6 | 7 | // REST Paths 8 | public const string BaseRestPath = "rest/api/2"; 9 | 10 | public const string V3BaseRestPath = "rest/api/3"; 11 | 12 | public const string Project = "project"; 13 | 14 | public const string User = "user"; 15 | 16 | public const string Search = "search"; 17 | 18 | public const string Issue = "issue"; 19 | 20 | public const string Comment = "comment"; 21 | 22 | public const string Versions = "versions"; 23 | 24 | public const string Components = "components"; 25 | 26 | public const string IssueTypes = "issuetype"; 27 | 28 | public const string Status = "status"; 29 | 30 | public const string Priority = "priority"; 31 | 32 | public const string Transitions = "transitions"; 33 | 34 | public const string Worklog = "worklog"; 35 | 36 | public const string Attachments = "attachments"; 37 | 38 | public const string Assignable = "assignable"; 39 | 40 | public const string ServerInfo = "serverInfo"; 41 | 42 | public const string MyPermissions = "mypermissions"; 43 | 44 | public const string Bulk = "bulk"; 45 | 46 | public const string Migration = "migration"; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /JiraRestClient.Net/JiraRestClient.Net/Jql/JqlSearchBean.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace JiraRestClient.Net.Jql 4 | { 5 | public class JqlSearchBean 6 | { 7 | /** 8 | * Result list start at. 9 | */ 10 | public int StartAt { get; set; } 11 | 12 | /** 13 | * Maximum result list size. 14 | */ 15 | public int MaxResults { get; set; } 16 | 17 | /** 18 | * Result fields for a query. 19 | */ 20 | public readonly List Fields = new(); 21 | 22 | public string Jql { get; set; } 23 | 24 | public readonly List Expand = new(); 25 | 26 | 27 | public JqlSearchBean() 28 | { 29 | StartAt = 0; 30 | MaxResults = 50; 31 | } 32 | 33 | /** 34 | * Adds fields which should be returned after the request. 35 | * 36 | * @param fields = returned fields 37 | */ 38 | public void AddField(params EField[] efields) 39 | { 40 | foreach (var element in efields) 41 | { 42 | Fields.Add(element.ToString()); 43 | } 44 | } 45 | 46 | public void AddExpand(params EField[] efields) 47 | { 48 | foreach (var element in efields) 49 | { 50 | Expand.Add(element.ToString()); 51 | } 52 | } 53 | 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /JiraRestClient.Net/JiraRestClient.Net/Domain/Project.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Text.Json.Serialization; 3 | using JiraRestClient.Net.Domain.Issue; 4 | 5 | namespace JiraRestClient.Net.Domain 6 | { 7 | public class Project : KeyBase 8 | { 9 | [JsonPropertyName("expand")] 10 | public string Expand { get; set; } 11 | [JsonPropertyName("description")] 12 | public string Description { get; set; } 13 | [JsonPropertyName("lead")] 14 | public User Lead { get; set; } 15 | [JsonPropertyName("components")] 16 | public List Components { get; set; } 17 | [JsonPropertyName("issuetypes")] 18 | public List IssueTypes { get; set; } 19 | [JsonPropertyName("assigneetype")] 20 | public string AssigneeType { get; set; } 21 | [JsonPropertyName("versions")] 22 | public List Versions { get; set; } 23 | [JsonPropertyName("roles")] 24 | public Roles Roles { get; set; } 25 | [JsonPropertyName("avatarurls")] 26 | public AvatarUrls AvatarUrls { get; set; } 27 | } 28 | 29 | public class Roles 30 | { 31 | [JsonPropertyName("users")] 32 | public string Users { get; set; } 33 | [JsonPropertyName("administrators")] 34 | public string Administrators { get; set; } 35 | [JsonPropertyName("developers")] 36 | public string Developers { get; set; } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "name": ".NET Core Launch (console)", 6 | "type": "coreclr", 7 | "request": "launch", 8 | "preLaunchTask": "build", 9 | "program": "${workspaceRoot}/bin/Debug/netcoreapp1.0/hwapp.dll", 10 | "args": [], 11 | "cwd": "${workspaceRoot}", 12 | "stopAtEntry": false 13 | }, 14 | { 15 | "name": ".NET Core Launch (web)", 16 | "type": "coreclr", 17 | "request": "launch", 18 | "preLaunchTask": "build", 19 | "program": "${workspaceRoot}/bin/Debug/netcoreapp1.0/hwapp.dll", 20 | "args": [], 21 | "cwd": "${workspaceRoot}", 22 | "stopAtEntry": false, 23 | "launchBrowser": { 24 | "enabled": true, 25 | "args": "${auto-detect-url}", 26 | "windows": { 27 | "command": "cmd.exe", 28 | "args": "/C start ${auto-detect-url}" 29 | }, 30 | "osx": { 31 | "command": "open" 32 | }, 33 | "linux": { 34 | "command": "xdg-open" 35 | } 36 | } 37 | }, 38 | { 39 | "name": ".NET Core Attach", 40 | "type": "coreclr", 41 | "request": "attach", 42 | "processName": "" 43 | } 44 | ] 45 | } -------------------------------------------------------------------------------- /JiraRestClient.Net/JiraRestClient.Net/Domain/Error.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | 3 | namespace JiraRestClient.Net.Domain 4 | { 5 | public class Errors 6 | { 7 | [JsonPropertyName("project")] 8 | public string Project {get;set;} 9 | [JsonPropertyName("subtasks")] 10 | public string Subtasks {get;set;} 11 | [JsonPropertyName("attachment")] 12 | public string Attachment {get;set;} 13 | [JsonPropertyName("issuelinks")] 14 | public string IssueLinks {get;set;} 15 | [JsonPropertyName("issuetype")] 16 | public string IssueType {get;set;} 17 | [JsonPropertyName("reporter")] 18 | public string Reporter {get;set;} 19 | [JsonPropertyName("assignee")] 20 | public string Assignee {get;set;} 21 | [JsonPropertyName("environment")] 22 | public string Environment {get;set;} 23 | [JsonPropertyName("filterName")] 24 | public string FilterName {get;set;} 25 | [JsonPropertyName("versions")] 26 | public string Versions {get;set;} 27 | [JsonPropertyName("components")] 28 | public string Components {get;set;} 29 | [JsonPropertyName("email")] 30 | public string Email {get;set;} 31 | [JsonPropertyName("projectType")] 32 | public string ProjectType {get;set;} 33 | [JsonPropertyName("projectKey")] 34 | public string ProjectKey {get;set;} 35 | [JsonPropertyName("projectName")] 36 | public string ProjectName {get;set;} 37 | } 38 | } -------------------------------------------------------------------------------- /JiraRestClient.Net/JiraRestClient.Net/Domain/User.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Text.Json.Serialization; 3 | using JiraRestClient.Net.Domain.Issue; 4 | 5 | namespace JiraRestClient.Net.Domain 6 | { 7 | public class User : KeyBase 8 | { 9 | [JsonPropertyName("emailAddress")] 10 | public string EmailAddress { get; set; } 11 | 12 | [JsonPropertyName("avatarUrls")] 13 | public AvatarUrls AvatarUrls { get; set; } 14 | 15 | [JsonPropertyName("displayName")] 16 | public string DisplayName { get; set; } 17 | 18 | [JsonPropertyName("active")] 19 | public bool Active { get; set; } 20 | 21 | [JsonPropertyName("timeZone")] 22 | public string TimeZone { get; set; } 23 | 24 | [JsonPropertyName("groups")] 25 | public Groups Groups { get; set; } 26 | 27 | [JsonPropertyName("expand")] 28 | public string Expand { get; set; } 29 | } 30 | 31 | public class Groups 32 | { 33 | [JsonPropertyName("size")] 34 | public int Size { get; set; } 35 | 36 | [JsonPropertyName("items")] 37 | public IList Items { get; set; } 38 | } 39 | 40 | public class Group :Base 41 | { 42 | 43 | } 44 | 45 | public class UserMigration 46 | { 47 | [JsonPropertyName("username")] 48 | public string Username { get; set; } 49 | [JsonPropertyName("accountId")] 50 | public string AccountId { get; set; } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /JiraRestClient.Net/JiraRestClient.Net/Core/PermissionsClient.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json; 2 | using JiraRestClient.Net.Core.Extension; 3 | using JiraRestClient.Net.Domain; 4 | using JiraRestClient.Net.Util; 5 | 6 | namespace JiraRestClient.Net.Core 7 | { 8 | public class PermissionsClient : BaseClient 9 | { 10 | public PermissionsClient(JiraRestClient jiraRestClient) : base(jiraRestClient) 11 | { 12 | } 13 | 14 | public Permissions GetMyPermissions(string projectKey = null, 15 | string projectId = null, 16 | string issueKey = null, 17 | string issueId = null) 18 | { 19 | var uri = BaseUri.AddPaths(RestPathConstants.MyPermissions); 20 | if (string.IsNullOrEmpty(projectKey) == false) 21 | { 22 | uri = uri.AddQuery($"{RestParamConstants.ProjectKey}={projectKey}"); 23 | } 24 | 25 | if (string.IsNullOrEmpty(projectId) == false) 26 | { 27 | uri = uri.AddQuery($"{RestParamConstants.ProjectId}={projectId}"); 28 | } 29 | 30 | if (string.IsNullOrEmpty(issueKey) == false) 31 | { 32 | uri = uri.AddQuery($"{RestParamConstants.IssueKey}={issueKey}"); 33 | } 34 | 35 | if (string.IsNullOrEmpty(issueId) == false) 36 | { 37 | uri = uri.AddQuery($"{RestParamConstants.IssueId}={issueId}"); 38 | } 39 | 40 | var stream = Client.GetStringAsync(uri.ToString()); 41 | var streamResult = stream.Result; 42 | return JsonSerializer.Deserialize(streamResult); 43 | } 44 | } 45 | } -------------------------------------------------------------------------------- /JiraRestClient.Net/JiraRestClient.Net/Core/ProjectClient.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Text.Json; 3 | using JiraRestClient.Net.Core.Extension; 4 | using JiraRestClient.Net.Domain; 5 | using JiraRestClient.Net.Util; 6 | 7 | namespace JiraRestClient.Net.Core 8 | { 9 | /// 10 | /// Client to get Issues 11 | /// 12 | public class ProjectClient : BaseClient 13 | { 14 | public ProjectClient(JiraRestClient jiraRestClient) : base(jiraRestClient) 15 | { 16 | } 17 | 18 | public Project GetProjectByKey(string key) 19 | { 20 | var restUriBuilder = BaseUri.AddPaths(RestPathConstants.Project, key); 21 | var completeUri = restUriBuilder.ToString(); 22 | var stream = Client.GetStringAsync(completeUri); 23 | return JsonSerializer.Deserialize(stream.Result); 24 | } 25 | 26 | public IEnumerable GetAllProjects() 27 | { 28 | var restUriBuilder = BaseUri.AddPaths(RestPathConstants.Project); 29 | var stream = Client.GetStringAsync(restUriBuilder.ToString()); 30 | return JsonSerializer.Deserialize>(stream.Result); 31 | } 32 | 33 | public List GetProjectVersions(string key){ 34 | var restUriBuilder = BaseUri.AddPaths(RestPathConstants.Project, key, RestPathConstants.Versions); 35 | var stream = Client.GetStringAsync(restUriBuilder.ToString()); 36 | return JsonSerializer.Deserialize>(stream.Result); 37 | } 38 | 39 | public List GetProjectComponents(string key){ 40 | var restUriBuilder = BaseUri.AddPaths(RestPathConstants.Project, key, RestPathConstants.Components); 41 | var stream = Client.GetStringAsync(restUriBuilder.ToString()); 42 | return JsonSerializer.Deserialize>(stream.Result); 43 | } 44 | } 45 | } -------------------------------------------------------------------------------- /JiraRestClient.Net/JiraRestClient.Net/Util/Constants.cs: -------------------------------------------------------------------------------- 1 | namespace JiraRestClient.Net.Util 2 | { 3 | public static class Constants 4 | { 5 | public const string Project = "project"; 6 | 7 | public const string OrderBy = "ORDER_BY"; 8 | 9 | public const string Issuetype = "issuetype"; 10 | 11 | public const string Status = "status"; 12 | 13 | public const string And = "and"; 14 | 15 | public const string Or = "or"; 16 | 17 | // Issue Field Names für die JQL Suche 18 | 19 | public const string FieldSummary = "summary"; 20 | 21 | public const string FieldIssuetype = "issuetype"; 22 | 23 | public const string FieldStatus = "status"; 24 | 25 | public const string FieldDuedate = "duedate"; 26 | 27 | public const string FieldPriority = "priority"; 28 | 29 | //Issue Status für die JQL Suche 30 | 31 | public const string StatusOpen = "open"; 32 | 33 | public const string StatusClosed = "closed"; 34 | 35 | public const string StatusResolved = "resolved"; 36 | 37 | public const string StatusInProgress = "in progress"; 38 | 39 | public const string StatusReopened = "reopened"; 40 | 41 | //Issue Type für die JQL Suche 42 | 43 | public const string IssueTypeImprovement = "improvement"; 44 | 45 | public const string IssueTypeBug = "bug"; 46 | 47 | public const string IssueTypeNewFeature = "new feature"; 48 | 49 | public const string IssueTypeSubtask = "sub-task"; 50 | 51 | public const string IssueTypeTask = "task"; 52 | 53 | public const string IssueTypeStory = "Story"; 54 | 55 | //Priority für die SQL Suche 56 | 57 | public const string PriorityHighest = "1"; 58 | 59 | public const string PriorityHigh = "2"; 60 | 61 | public const string PriorityMedium = "3"; 62 | 63 | public const string PriorityLow = "4"; 64 | 65 | public const string PriorityLowest = "5"; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /JiraRestClient.Net/JiraRestClient.Net/Core/Converter/PermissionListConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text.Json; 3 | using System.Text.Json.Serialization; 4 | using JiraRestClient.Net.Domain; 5 | 6 | namespace JiraRestClient.Net.Core.Converter 7 | { 8 | public class PermissionListConverter : JsonConverter 9 | { 10 | public override Permissions Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) 11 | { 12 | while (reader.Read()) 13 | { 14 | switch (reader.TokenType) 15 | { 16 | case JsonTokenType.PropertyName: 17 | break; 18 | case JsonTokenType.StartObject: 19 | break; 20 | case JsonTokenType.None: 21 | break; 22 | case JsonTokenType.EndObject: 23 | break; 24 | case JsonTokenType.StartArray: 25 | break; 26 | case JsonTokenType.EndArray: 27 | break; 28 | case JsonTokenType.Comment: 29 | break; 30 | case JsonTokenType.String: 31 | break; 32 | case JsonTokenType.Number: 33 | break; 34 | case JsonTokenType.True: 35 | break; 36 | case JsonTokenType.False: 37 | break; 38 | case JsonTokenType.Null: 39 | break; 40 | default: 41 | throw new ArgumentOutOfRangeException(); 42 | } 43 | } 44 | return new Permissions(); 45 | } 46 | 47 | public override void Write(Utf8JsonWriter writer, Permissions value, JsonSerializerOptions options) 48 | { 49 | throw new NotImplementedException(); 50 | } 51 | } 52 | } -------------------------------------------------------------------------------- /JiraRestClient.Net/JiraRestClient.Net.Test/Examples/attachments.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "self": "http://localhost:8080/rest/api/2/attachment/10001", 4 | "id": "10001", 5 | "filename": "frogs.png", 6 | "author": { 7 | "self": "http://localhost:8080/rest/api/2/user?username=admin", 8 | "name": "admin", 9 | "key": "JIRAUSER10000", 10 | "emailAddress": "cschulc@outlook.com", 11 | "avatarUrls": { 12 | "48x48": "https://www.gravatar.com/avatar/0be77329bf7ff7015df5c513855589e9?d=mm&s=48", 13 | "24x24": "https://www.gravatar.com/avatar/0be77329bf7ff7015df5c513855589e9?d=mm&s=24", 14 | "16x16": "https://www.gravatar.com/avatar/0be77329bf7ff7015df5c513855589e9?d=mm&s=16", 15 | "32x32": "https://www.gravatar.com/avatar/0be77329bf7ff7015df5c513855589e9?d=mm&s=32" 16 | }, 17 | "displayName": "Administrator", 18 | "active": true, 19 | "timeZone": "Etc/UTC" 20 | }, 21 | "created": "2022-05-11T07:36:20.170+0000", 22 | "size": 866805, 23 | "content": "http://localhost:8080/secure/attachment/10001/frogs.png", 24 | "thumbnail": "http://localhost:8080/secure/thumbnail/10001/_thumb_10001.png" 25 | }, 26 | { 27 | "self": "http://localhost:8080/rest/api/2/attachment/10002", 28 | "id": "10002", 29 | "filename": "test.pdf", 30 | "author": { 31 | "self": "http://localhost:8080/rest/api/2/user?username=admin", 32 | "name": "admin", 33 | "key": "JIRAUSER10000", 34 | "emailAddress": "cschulc@outlook.com", 35 | "avatarUrls": { 36 | "48x48": "https://www.gravatar.com/avatar/0be77329bf7ff7015df5c513855589e9?d=mm&s=48", 37 | "24x24": "https://www.gravatar.com/avatar/0be77329bf7ff7015df5c513855589e9?d=mm&s=24", 38 | "16x16": "https://www.gravatar.com/avatar/0be77329bf7ff7015df5c513855589e9?d=mm&s=16", 39 | "32x32": "https://www.gravatar.com/avatar/0be77329bf7ff7015df5c513855589e9?d=mm&s=32" 40 | }, 41 | "displayName": "Administrator", 42 | "active": true, 43 | "timeZone": "Etc/UTC" 44 | }, 45 | "created": "2022-05-11T07:36:20.174+0000", 46 | "size": 50908, 47 | "content": "http://localhost:8080/secure/attachment/10002/test.pdf" 48 | } 49 | ] -------------------------------------------------------------------------------- /JiraRestClient.Net/JiraRestClient.Net/Jql/JqlBuilder.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text; 3 | 4 | namespace JiraRestClient.Net.Jql 5 | { 6 | public class JqlBuilder 7 | { 8 | private StringBuilder Jql { get; set; } 9 | 10 | public JqlBuilder() 11 | { 12 | Jql = new StringBuilder(); 13 | } 14 | 15 | public JqlKeyword AddCondition(EField field, EOperator eoperator, String operand) 16 | { 17 | var jqlKeyword = new JqlKeyword {Jqlbuilder = this}; 18 | if (field != null) 19 | { 20 | Jql.Append(field + " "); 21 | } 22 | if (eoperator != null) 23 | { 24 | Jql.Append(eoperator + " "); 25 | } 26 | if (operand != null) 27 | { 28 | Jql.Append(operand + " "); 29 | } 30 | return jqlKeyword; 31 | } 32 | 33 | public void Clear() 34 | { 35 | Jql.Clear(); 36 | } 37 | 38 | public class JqlKeyword 39 | { 40 | public JqlBuilder Jqlbuilder { get; set; } 41 | 42 | public JqlBuilder And() 43 | { 44 | Jqlbuilder.Jql.Append(EKeyword.AND + " "); 45 | return Jqlbuilder; 46 | } 47 | 48 | public JqlBuilder Or() 49 | { 50 | Jqlbuilder.Jql.Append(EKeyword.OR + " "); 51 | return Jqlbuilder; 52 | } 53 | 54 | public String OrderBy(SortOrder order, params EField[] fields) 55 | { 56 | if (fields == null || order == null || fields.Length == 0) 57 | { 58 | return Build(); 59 | } 60 | 61 | Jqlbuilder.Jql.Append(EKeyword.ORDER_BY + " "); 62 | Jqlbuilder.Jql.Append(fields[0]); 63 | 64 | for (int i = 1; i < fields.Length; i++) 65 | { 66 | Jqlbuilder.Jql.Append(", "); 67 | Jqlbuilder.Jql.Append(fields[i]); 68 | } 69 | 70 | Jqlbuilder.Jql.Append(" " + order); 71 | 72 | return Build(); 73 | } 74 | public String Build() 75 | { 76 | String request = Jqlbuilder.Jql.ToString(); 77 | Jqlbuilder.Clear(); 78 | return request; 79 | } 80 | 81 | 82 | } 83 | 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /JiraRestClient.Net/JiraRestClient.Net/Domain/Issue/IssueUpdate.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Text.Json.Serialization; 3 | 4 | namespace JiraRestClient.Net.Domain.Issue 5 | { 6 | public class IssueUpdate 7 | { 8 | [JsonPropertyName("fields")] 9 | public IssueFields Fields { get; set; } 10 | 11 | [JsonPropertyName("transition")] 12 | public Transition Transition { get; set; } 13 | 14 | [JsonPropertyName("historyMetadata")] 15 | public HistoryMetadata HistoryMetadata { get; set; } 16 | 17 | [JsonPropertyName("properties")] 18 | public List Properties { get; set; } 19 | } 20 | 21 | public class HistoryMetadata 22 | { 23 | [JsonPropertyName("activityDescription")] 24 | public string ActivityDescription { get; set; } 25 | 26 | [JsonPropertyName("activityDescriptionKey")] 27 | public string ActivityDescriptionKey { get; set; } 28 | 29 | [JsonPropertyName("actor")] 30 | public HistoryMetadataParticipant Actor { get; set; } 31 | 32 | [JsonPropertyName("cause")] 33 | public HistoryMetadataParticipant Cause { get; set; } 34 | 35 | [JsonPropertyName("description")] 36 | public string Description { get; set; } 37 | 38 | [JsonPropertyName("descriptionKey")] 39 | public string DescriptionKey { get; set; } 40 | 41 | [JsonPropertyName("emailDescription")] 42 | public string EmailDescription { get; set; } 43 | 44 | [JsonPropertyName("emailDescriptionKey")] 45 | public string EmailDescriptionKey { get; set; } 46 | 47 | [JsonPropertyName("extraData")] 48 | public ExtraData ExtraData { get; set; } 49 | 50 | [JsonPropertyName("generator")] 51 | public HistoryMetadataParticipant Generator { get; set; } 52 | 53 | [JsonPropertyName("type")] 54 | public string Type { get; set; } 55 | } 56 | 57 | public class ExtraData 58 | { 59 | } 60 | 61 | public class HistoryMetadataParticipant 62 | { 63 | [JsonPropertyName("avatarUrl")] 64 | public string AvatarUrl { get; set; } 65 | 66 | [JsonPropertyName("displayName")] 67 | public string DisplayName { get; set; } 68 | 69 | [JsonPropertyName("displayNameKey")] 70 | public string DisplayNameKey { get; set; } 71 | 72 | [JsonPropertyName("id")] 73 | public string Id { get; set; } 74 | 75 | [JsonPropertyName("type")] 76 | public string Type { get; set; } 77 | 78 | [JsonPropertyName("url")] 79 | public string Url { get; set; } 80 | } 81 | 82 | public class EntityProperty 83 | { 84 | [JsonPropertyName("key")] 85 | public string Key { get; set; } 86 | 87 | [JsonPropertyName("value")] 88 | public object Value { get; set; } 89 | } 90 | } -------------------------------------------------------------------------------- /JiraRestClient.Net/JiraRestClient.Net/Jql/EKeyword.cs: -------------------------------------------------------------------------------- 1 | namespace JiraRestClient.Net.Jql 2 | { 3 | public class EKeyword 4 | { 5 | /** 6 | * Used to combine multiple clauses, allowing you to refine your search. 7 | *

Examples:

8 | *
    9 | *
  • project = "New office" and status = "open"
  • 10 | *
  • status = open and priority = urgent and assignee = jsmith
  • 11 | *
  • project = JRA and assignee != jsmith
  • 12 | *
  • project in (JRA,CONF) and fixVersion = "3.14"
  • 13 | *
  • reporter not in (Jack,Jill,John) and assignee not in (Jack,Jill,John)
  • 14 | *
15 | */ 16 | public static readonly EKeyword AND = new EKeyword("and"); 17 | 18 | /** 19 | * Used to combine multiple clauses, allowing you to expand your search. 20 | *

Examples:

21 | *
    22 | *
  • reporter = jsmith or reporter = jbrown
  • 23 | *
  • duedate < now() or duedate is empty
  • 24 | *
25 | */ 26 | public static readonly EKeyword OR = new EKeyword("or"); 27 | 28 | /** 29 | * Used to negate individual clauses or a complex JQL query (a query made up of more than one clause) 30 | * using parentheses, allowing you to refine your search. 31 | *

Examples:

32 | *
    33 | *
  • not assignee = jsmith
  • 34 | *
  • not (reporter = jsmith or reporter = jbrown)
  • 35 | *
36 | */ 37 | public static readonly EKeyword NOT = new EKeyword("not"); 38 | 39 | /** 40 | * Used to search for issues where a given field does not have a value. 41 | *

Examples:

42 | *
    43 | *
  • duedate = empty
  • 44 | *
  • duedate is empty
  • 45 | *
46 | */ 47 | public static readonly EKeyword EMPTY = new EKeyword("empty"); 48 | 49 | /** 50 | * Used to search for issues where a given field does not have a value. 51 | *

Examples:

52 | *
    53 | *
  • duedate = null
  • 54 | *
  • duedate is null
  • 55 | *
56 | */ 57 | public static readonly EKeyword NULL = new EKeyword("null"); 58 | 59 | /** 60 | * Used to specify the fields by whose values the search results will be sorted. 61 | *

Examples:

62 | *
    63 | *
  • duedate = empty order by created
  • 64 | *
  • duedate = empty order by created, priority desc
  • 65 | *
  • duedate = empty order by created, priority asc
  • 66 | *
67 | */ 68 | public static readonly EKeyword ORDER_BY = new EKeyword("order by"); 69 | 70 | 71 | private string Keyword { get; set; } 72 | 73 | /* 74 | * Instantiates a new keyword. 75 | * 76 | * @param keyword name of the keyword 77 | */ 78 | private EKeyword(string keyword) 79 | { 80 | Keyword = keyword; 81 | } 82 | 83 | public override string ToString() 84 | { 85 | return Keyword; 86 | } 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /JiraRestClient.Net/JiraRestClient.Net.Test/TestIssueClient.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.IO; 3 | using FluentAssertions; 4 | using JiraRestClient.Net.Domain; 5 | using JiraRestClient.Net.Domain.Issue; 6 | using JiraRestClient.Net.Jql; 7 | using Microsoft.VisualStudio.TestTools.UnitTesting; 8 | 9 | namespace JiraRestClient.Net.Test 10 | { 11 | [TestClass] 12 | public class TestIssueClient : BaseTest 13 | { 14 | [TestMethod] 15 | public void TestGetIssueByKey() 16 | { 17 | var issue = RestClient.IssueClient.GetIssueByKey(IssueKeyToSearch); 18 | issue.Should().NotBeNull(); 19 | } 20 | 21 | [TestMethod] 22 | public void TestGetIssueByKeyWithFields() 23 | { 24 | var fields = new List { EField.Summary.Field, EField.Description.Field }; 25 | var expands = new List 26 | { 27 | EField.Renderedfields.Field, EField.Transitions.Field, EField.Changelog.Field 28 | }; 29 | var issue = RestClient.IssueClient.GetIssueByKey(IssueKeyToSearch, fields, expands); 30 | issue.Should().NotBeNull(); 31 | issue.Fields.Summary.Should().NotBeNull(); 32 | issue.Fields.Description.Should().NotBeNull(); 33 | issue.RenderedFields.Description.Should().NotBeNull(); 34 | } 35 | 36 | [TestMethod] 37 | public void TestCreateIssue() 38 | { 39 | var issueUpdate = new IssueUpdate 40 | { 41 | Fields = new IssueFields 42 | { 43 | Description = new Description 44 | { 45 | Version = 1, 46 | Type = "doc", 47 | Content = new List 48 | { 49 | new() 50 | { 51 | Type = "paragraph", 52 | Contents = new List 53 | { 54 | new () 55 | { 56 | Type = "text", 57 | Text = "Lorem ipsum" 58 | } 59 | } 60 | } 61 | } 62 | }, 63 | Summary = "Created via RestAPI", 64 | Project = new Project 65 | { 66 | Key = ProjectKey 67 | }, 68 | Issuetype = new IssueType 69 | { 70 | Id = "10009", 71 | Name = "Story" 72 | } 73 | } 74 | }; 75 | var issueResponse = RestClient.IssueClient.CreateIssue(issueUpdate); 76 | issueResponse.Should().NotBeNull(); 77 | issueResponse.Key.Should().NotBeNullOrEmpty(); 78 | } 79 | 80 | 81 | [TestMethod] 82 | public void TestAddAttachment() 83 | { 84 | var png = File.OpenRead("./Resources/frogs.png"); 85 | var pdf = File.OpenRead("./Resources/test.pdf"); 86 | 87 | var streams = new List 88 | { 89 | png, pdf 90 | }; 91 | var attachments = RestClient.IssueClient.AddAttachment("DEMO-3", streams); 92 | attachments.Should().NotBeEmpty().And.HaveCount(2); 93 | } 94 | } 95 | } -------------------------------------------------------------------------------- /JiraRestClient.Net/JiraRestClient.Net/JiraRestClient.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Net; 3 | using System.Net.Http; 4 | using System.Net.Http.Headers; 5 | using System.Text; 6 | using JiraRestClient.Net.Core; 7 | using JiraRestClient.Net.Core.Extension; 8 | using JiraRestClient.Net.Util; 9 | 10 | namespace JiraRestClient.Net; 11 | 12 | public class JiraRestClient 13 | { 14 | public HttpClient Client { get; } 15 | 16 | public Uri BaseUri { get; } 17 | 18 | public string Username { get; private set; } 19 | 20 | private string Base64Token { get; set; } 21 | 22 | private IssueClient _issueClient; 23 | 24 | private UserClient _userClient; 25 | 26 | private SearchClient _searchClient; 27 | 28 | private SystemClient _systemClient; 29 | 30 | private ProjectClient _projectClient; 31 | 32 | private PermissionsClient _permissionsClient; 33 | 34 | /// 35 | /// 36 | /// 37 | /// 38 | /// 39 | /// 40 | /// 41 | public JiraRestClient(Uri uri, string username, string password, ApiVersion apiVersion = ApiVersion.V3) 42 | { 43 | ServicePointManager.ServerCertificateValidationCallback += (_, _, _, _) => true; 44 | Client = new HttpClient(); 45 | var versionPath = RestPathConstants.V3BaseRestPath; 46 | if (apiVersion == ApiVersion.V2) 47 | { 48 | versionPath = RestPathConstants.BaseRestPath; 49 | } 50 | 51 | BaseUri = uri.AddPaths(versionPath); 52 | Username = username; 53 | var bytes = Encoding.ASCII.GetBytes(username + ":" + password); 54 | Base64Token = Convert.ToBase64String(bytes); 55 | Client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Base64Token); 56 | } 57 | 58 | public JiraRestClient(Uri uri, string token) 59 | { 60 | ServicePointManager.ServerCertificateValidationCallback += (_, _, _, _) => true; 61 | Client = new HttpClient(); 62 | BaseUri = uri; 63 | Client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", token); 64 | } 65 | 66 | public JiraRestClient(Uri uri) 67 | { 68 | ServicePointManager.ServerCertificateValidationCallback += (_, _, _, _) => true; 69 | Client = new HttpClient(); 70 | BaseUri = uri; 71 | } 72 | 73 | public string Login(string username, string password) 74 | { 75 | Username = username; 76 | var bytes = Encoding.ASCII.GetBytes(username + ":" + password); 77 | Base64Token = Convert.ToBase64String(bytes); 78 | Client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Base64Token); 79 | return Base64Token; 80 | } 81 | 82 | public void Login(string base64Token) 83 | { 84 | Base64Token = base64Token; 85 | Client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Base64Token); 86 | } 87 | 88 | public IssueClient IssueClient => _issueClient ??= new IssueClient(this); 89 | 90 | public UserClient UserClient => _userClient ??= new UserClient(this); 91 | 92 | public SearchClient SearchClient => _searchClient ??= new SearchClient(this); 93 | 94 | public SystemClient SystemClient => _systemClient ??= new SystemClient(this); 95 | 96 | public ProjectClient ProjectClient => _projectClient ??= new ProjectClient(this); 97 | 98 | public PermissionsClient PermissionsClient => 99 | _permissionsClient ??= new PermissionsClient(this); 100 | } -------------------------------------------------------------------------------- /JiraRestClient.Net/JiraRestClient.Net/Jql/EField.cs: -------------------------------------------------------------------------------- 1 | namespace JiraRestClient.Net.Jql 2 | { 3 | public class EField 4 | { 5 | public static readonly EField All = new EField("*all", null); 6 | 7 | public static readonly EField Navigable = new EField("*navigable", null); 8 | 9 | public static readonly EField AffectedVersion = new EField("affectedVersion", EFieldType.Version); 10 | 11 | public static readonly EField Assignee = new EField("assignee", EFieldType.User); 12 | 13 | public static readonly EField Category = new EField("category", EFieldType.Category); 14 | 15 | public static readonly EField Comment = new EField("comment", EFieldType.Text); 16 | 17 | public static readonly EField Component = new EField("component", EFieldType.Component); 18 | 19 | public static readonly EField Created = new EField("created", EFieldType.Date); 20 | 21 | public static readonly EField Description = new EField("description", EFieldType.Text); 22 | 23 | public static readonly EField Due = new EField("due", EFieldType.Date); 24 | 25 | public static readonly EField Environment = new EField("environment", EFieldType.Text); 26 | 27 | public static readonly EField EpicLinks = new EField("epic link", EFieldType.CustomType); 28 | 29 | public static readonly EField Filter = new EField("filter", EFieldType.Filter); 30 | 31 | public static readonly EField FixVersion = new EField("fixVersion", EFieldType.Version); 32 | 33 | public static readonly EField IssueKey = new EField("issueKey", EFieldType.Issue); 34 | 35 | public static readonly EField LastViewed = new EField("lastViewed", EFieldType.Date); 36 | 37 | public static readonly EField Level = new EField("level", EFieldType.SecurityLevel); 38 | 39 | public static readonly EField OriginalEstimate = new EField("originalEstimate", EFieldType.Duration); 40 | 41 | public static readonly EField Parent = new EField("parent", EFieldType.Issue); 42 | 43 | public static readonly EField Priority = new EField("priority", EFieldType.Priority); 44 | 45 | public static readonly EField Project = new EField("project", EFieldType.Project); 46 | 47 | public static readonly EField RemainingEstimate = new EField("remainingEstimate", EFieldType.Duration); 48 | 49 | public static readonly EField Reporter = new EField("reporter", EFieldType.User); 50 | 51 | public static readonly EField Resolution = new EField("resolution", EFieldType.Resolution); 52 | 53 | public static readonly EField Resolved = new EField("resolved", EFieldType.Date); 54 | 55 | public static readonly EField Sprint = new EField("sprint", EFieldType.Number); 56 | 57 | public static readonly EField Status = new EField("status", EFieldType.Status); 58 | 59 | public static readonly EField Summary = new EField("summary", EFieldType.Text); 60 | 61 | public static readonly EField Text = new EField("text", EFieldType.TextMaster); 62 | 63 | public static readonly EField IssueType = new EField("issuetype", EFieldType.IssueType); 64 | 65 | public static readonly EField TimeSpent = new EField("timeSpent", EFieldType.Duration); 66 | 67 | public static readonly EField Updated = new EField("updated", EFieldType.Date); 68 | 69 | public static readonly EField Voter = new EField("voter", EFieldType.User); 70 | 71 | public static readonly EField Votes = new EField("votes", EFieldType.Number); 72 | 73 | public static readonly EField Watcher = new EField("watcher", EFieldType.User); 74 | 75 | public static readonly EField Watchers = new EField("watchers", EFieldType.Number); 76 | 77 | public static readonly EField WorkRatio = new EField("workRatio", EFieldType.Number); 78 | 79 | public static readonly EField Transitions = new EField("transitions", EFieldType.CustomType); 80 | 81 | public static readonly EField Changelog = new EField("changelog", EFieldType.CustomType); 82 | 83 | public static readonly EField Renderedfields = new EField("renderedFields", EFieldType.CustomType); 84 | 85 | public string Field { get; private set; } 86 | 87 | public EFieldType Type { get; private set; } 88 | 89 | private EField(string field, EFieldType type) 90 | { 91 | this.Field = field; 92 | this.Type = type; 93 | } 94 | 95 | public override string ToString() 96 | { 97 | return Field; 98 | } 99 | } 100 | } -------------------------------------------------------------------------------- /JiraRestClient.Net/JiraRestClient.Net/Jql/EFieldType.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace JiraRestClient.Net.Jql 4 | { 5 | public class EFieldType 6 | { 7 | public static readonly EFieldType Version = new EFieldType(EOperator.EQUALS, EOperator.NOT_EQUALS, 8 | EOperator.LESS_THAN, EOperator.LESS_THAN_EQUALS, EOperator.IN, EOperator.NOT_IN, EOperator.GREATER_THAN, 9 | EOperator.GREATER_THAN_EQUALS, EOperator.IS, EOperator.IS_NOT, EOperator.WAS, EOperator.WAS_IN, 10 | EOperator.WAS_NOT, EOperator.WAS_NOT_IN, EOperator.CHANGED); 11 | 12 | public static readonly EFieldType User = new EFieldType(EOperator.EQUALS, EOperator.NOT_EQUALS, EOperator.IS, 13 | EOperator.IS_NOT, EOperator.IN, EOperator.NOT_IN, EOperator.WAS, EOperator.WAS_IN, EOperator.WAS_NOT, 14 | EOperator.WAS_NOT_IN, EOperator.CHANGED); 15 | 16 | 17 | public static readonly EFieldType Category = new EFieldType(EOperator.EQUALS, EOperator.NOT_EQUALS, 18 | EOperator.IS, EOperator.IS_NOT, EOperator.IN, EOperator.NOT_IN); 19 | 20 | 21 | public static readonly EFieldType Text = new EFieldType(EOperator.CONTAINS, EOperator.DOES_NOT_CONTAIN, 22 | EOperator.IS, EOperator.IS_NOT); 23 | 24 | 25 | public static readonly EFieldType Component = new EFieldType(EOperator.EQUALS, EOperator.NOT_EQUALS, 26 | EOperator.IS, EOperator.IS_NOT, EOperator.IN, EOperator.NOT_IN); 27 | 28 | 29 | public static readonly EFieldType Date = new EFieldType(EOperator.EQUALS, EOperator.NOT_EQUALS, 30 | EOperator.LESS_THAN, EOperator.LESS_THAN_EQUALS, EOperator.IN, EOperator.NOT_IN, EOperator.GREATER_THAN, 31 | EOperator.GREATER_THAN_EQUALS, EOperator.IS, EOperator.IS_NOT); 32 | 33 | 34 | public static readonly EFieldType Filter = 35 | new EFieldType(EOperator.EQUALS, EOperator.NOT_EQUALS, EOperator.IN, EOperator.NOT_IN); 36 | 37 | 38 | public static readonly EFieldType Issue = new EFieldType(EOperator.EQUALS, EOperator.NOT_EQUALS, 39 | EOperator.LESS_THAN, EOperator.LESS_THAN_EQUALS, EOperator.IN, EOperator.NOT_IN, EOperator.GREATER_THAN, 40 | EOperator.GREATER_THAN_EQUALS, EOperator.IS, EOperator.IS_NOT); 41 | 42 | 43 | public static readonly EFieldType SecurityLevel = new EFieldType(EOperator.EQUALS, EOperator.NOT_EQUALS, 44 | EOperator.IS, EOperator.IS_NOT, EOperator.IN, EOperator.NOT_IN); 45 | 46 | public static readonly EFieldType Duration = new EFieldType(EOperator.EQUALS, EOperator.NOT_EQUALS, 47 | EOperator.LESS_THAN, EOperator.LESS_THAN_EQUALS, EOperator.IN, EOperator.NOT_IN, EOperator.GREATER_THAN, 48 | EOperator.GREATER_THAN_EQUALS, EOperator.IS, EOperator.IS_NOT); 49 | 50 | 51 | public static readonly EFieldType Priority = new EFieldType(EOperator.EQUALS, EOperator.NOT_EQUALS, 52 | EOperator.LESS_THAN, EOperator.LESS_THAN_EQUALS, EOperator.IN, EOperator.NOT_IN, EOperator.GREATER_THAN, 53 | EOperator.GREATER_THAN_EQUALS, EOperator.IS, EOperator.IS_NOT, EOperator.WAS, EOperator.WAS_IN, 54 | EOperator.WAS_NOT, EOperator.WAS_NOT_IN, EOperator.CHANGED); 55 | 56 | public static readonly EFieldType Project = new EFieldType(EOperator.EQUALS, EOperator.NOT_EQUALS, EOperator.IS, 57 | EOperator.IS_NOT, EOperator.IN, EOperator.NOT_IN); 58 | 59 | public static readonly EFieldType Resolution = new EFieldType(EOperator.EQUALS, EOperator.NOT_EQUALS, 60 | EOperator.LESS_THAN, EOperator.LESS_THAN_EQUALS, EOperator.IN, EOperator.NOT_IN, EOperator.GREATER_THAN, 61 | EOperator.GREATER_THAN_EQUALS, EOperator.IS, EOperator.IS_NOT, EOperator.WAS, EOperator.WAS_IN, 62 | EOperator.WAS_NOT, EOperator.WAS_NOT_IN, EOperator.CHANGED); 63 | 64 | 65 | public static readonly EFieldType Number = new EFieldType(EOperator.EQUALS, EOperator.NOT_EQUALS, EOperator.IS, 66 | EOperator.IS_NOT, EOperator.IN, EOperator.NOT_IN); 67 | 68 | 69 | public static readonly EFieldType Status = new EFieldType(EOperator.EQUALS, EOperator.NOT_EQUALS, EOperator.IS, 70 | EOperator.IS_NOT, EOperator.IN, EOperator.NOT_IN, EOperator.WAS, EOperator.WAS_IN, EOperator.WAS_NOT, 71 | EOperator.WAS_NOT_IN, EOperator.CHANGED); 72 | 73 | 74 | public static readonly EFieldType TextMaster = new EFieldType(EOperator.CONTAINS); 75 | 76 | 77 | public static readonly EFieldType IssueType = new EFieldType(EOperator.EQUALS, EOperator.NOT_EQUALS, 78 | EOperator.IS, EOperator.IS_NOT, EOperator.IN, EOperator.NOT_IN); 79 | 80 | public static readonly EFieldType CustomType; 81 | 82 | public List SupportedOperators { get; private set; } 83 | 84 | public EFieldType(params EOperator[] values) 85 | { 86 | SupportedOperators = new List(values); 87 | } 88 | } 89 | } -------------------------------------------------------------------------------- /JiraRestClient.Net/JiraRestClient.Net.Test/Examples/IssueUpdateSchema.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "https://docs.atlassian.com/jira/REST/schema/issue-update#", 3 | "title": "Issue Update", 4 | "type": "object", 5 | "properties": { 6 | "transition": { 7 | "title": "Transition", 8 | "type": "object", 9 | "properties": { 10 | "id": { 11 | "type": "string" 12 | }, 13 | "name": { 14 | "type": "string" 15 | }, 16 | "to": { 17 | "title": "Status", 18 | "type": "object", 19 | "properties": { 20 | "statusColor": { 21 | "type": "string" 22 | }, 23 | "description": { 24 | "type": "string" 25 | }, 26 | "iconUrl": { 27 | "type": "string" 28 | }, 29 | "name": { 30 | "type": "string" 31 | }, 32 | "id": { 33 | "type": "string" 34 | }, 35 | "statusCategory": { 36 | "title": "Status Category", 37 | "type": "object", 38 | "properties": { 39 | "id": { 40 | "type": "integer" 41 | }, 42 | "key": { 43 | "type": "string" 44 | }, 45 | "colorName": { 46 | "type": "string" 47 | }, 48 | "name": { 49 | "type": "string" 50 | } 51 | }, 52 | "additionalProperties": false 53 | } 54 | }, 55 | "additionalProperties": false 56 | }, 57 | "fields": { 58 | "type": "object", 59 | "patternProperties": { 60 | ".+": { 61 | "title": "Field Meta", 62 | "type": "object", 63 | "properties": { 64 | "required": { 65 | "type": "boolean" 66 | }, 67 | "schema": { 68 | "title": "Json Type", 69 | "type": "object", 70 | "properties": { 71 | "type": { 72 | "type": "string" 73 | }, 74 | "items": { 75 | "type": "string" 76 | }, 77 | "system": { 78 | "type": "string" 79 | }, 80 | "custom": { 81 | "type": "string" 82 | }, 83 | "customId": { 84 | "type": "integer" 85 | } 86 | }, 87 | "additionalProperties": false 88 | }, 89 | "name": { 90 | "type": "string" 91 | }, 92 | "fieldId": { 93 | "type": "string" 94 | }, 95 | "autoCompleteUrl": { 96 | "type": "string" 97 | }, 98 | "hasDefaultValue": { 99 | "type": "boolean" 100 | }, 101 | "operations": { 102 | "type": "array", 103 | "items": { 104 | "type": "string" 105 | } 106 | }, 107 | "allowedValues": { 108 | "type": "array", 109 | "items": {} 110 | }, 111 | "defaultValue": {} 112 | }, 113 | "additionalProperties": false, 114 | "required": [ 115 | "required" 116 | ] 117 | } 118 | }, 119 | "additionalProperties": false 120 | } 121 | }, 122 | "additionalProperties": false 123 | }, 124 | "fields": { 125 | "type": "object", 126 | "patternProperties": { 127 | ".+": {} 128 | }, 129 | "additionalProperties": false 130 | }, 131 | "update": { 132 | "type": "object", 133 | "patternProperties": { 134 | ".+": { 135 | "type": "array", 136 | "items": { 137 | "title": "Field Operation", 138 | "type": "object" 139 | } 140 | } 141 | }, 142 | "additionalProperties": false 143 | }, 144 | "historyMetadata": { 145 | "title": "History Metadata", 146 | "type": "object", 147 | "properties": { 148 | "type": { 149 | "type": "string" 150 | }, 151 | "description": { 152 | "type": "string" 153 | }, 154 | "descriptionKey": { 155 | "type": "string" 156 | }, 157 | "activityDescription": { 158 | "type": "string" 159 | }, 160 | "activityDescriptionKey": { 161 | "type": "string" 162 | }, 163 | "emailDescription": { 164 | "type": "string" 165 | }, 166 | "emailDescriptionKey": { 167 | "type": "string" 168 | }, 169 | "actor": { 170 | "$ref": "#/definitions/history-metadata-participant" 171 | }, 172 | "generator": { 173 | "$ref": "#/definitions/history-metadata-participant" 174 | }, 175 | "cause": { 176 | "$ref": "#/definitions/history-metadata-participant" 177 | }, 178 | "extraData": { 179 | "type": "object", 180 | "patternProperties": { 181 | ".+": { 182 | "type": "string" 183 | } 184 | }, 185 | "additionalProperties": false 186 | } 187 | }, 188 | "additionalProperties": false 189 | }, 190 | "properties": { 191 | "type": "array", 192 | "items": { 193 | "title": "Entity Property", 194 | "type": "object", 195 | "properties": { 196 | "key": { 197 | "type": "string" 198 | }, 199 | "value": {} 200 | }, 201 | "additionalProperties": false 202 | } 203 | } 204 | }, 205 | "definitions": { 206 | "history-metadata-participant": { 207 | "title": "History Metadata Participant", 208 | "type": "object", 209 | "properties": { 210 | "id": { 211 | "type": "string" 212 | }, 213 | "displayName": { 214 | "type": "string" 215 | }, 216 | "displayNameKey": { 217 | "type": "string" 218 | }, 219 | "type": { 220 | "type": "string" 221 | }, 222 | "avatarUrl": { 223 | "type": "string" 224 | }, 225 | "url": { 226 | "type": "string" 227 | } 228 | }, 229 | "additionalProperties": false 230 | } 231 | }, 232 | "additionalProperties": false 233 | } -------------------------------------------------------------------------------- /JiraRestClient.Net/JiraRestClient.Net.Test/Examples/issue.json: -------------------------------------------------------------------------------- 1 | { 2 | "expand": "renderedFields,names,schema,operations,editmeta,changelog,versionedRepresentations", 3 | "id": "10000", 4 | "self": "http://localhost:2990/jira/rest/api/2/issue/10000", 5 | "key": "DEMO-1", 6 | "fields": { 7 | "issuetype": { 8 | "self": "http://localhost:2990/jira/rest/api/2/issuetype/10001", 9 | "id": "10001", 10 | "description": "Von Jira Software erstellt – nicht bearbeiten oder löschen. Vorgangstyp für eine User Story.", 11 | "iconUrl": "http://localhost:2990/jira/images/icons/issuetypes/story.svg", 12 | "name": "Story", 13 | "subtask": false 14 | }, 15 | "components": [], 16 | "timespent": null, 17 | "timeoriginalestimate": null, 18 | "description": "*About Scrum*\n\nScrum is an iterative approach to Agile software development. The methodology has been around since the 1980s but was popularised by Jeff Sutherland and Ken Schwaber. \n\nScrum breaks the development of a product down in to discrete iterations (termed Sprints) that each deliver functionality that could potentially be shipped to users.\n\nThe Scrum Alliance offers an excellent [introduction to Scrum|http://www.scrumalliance.org/resources/47] that provides an overview of key Scrum concepts, stakeholders, processes and artefacts.", 19 | "project": { 20 | "self": "http://localhost:2990/jira/rest/api/2/project/10000", 21 | "id": "10000", 22 | "key": "DEMO", 23 | "name": "Demo", 24 | "projectTypeKey": "software", 25 | "avatarUrls": { 26 | "48x48": "http://localhost:2990/jira/secure/projectavatar?avatarId=10324", 27 | "24x24": "http://localhost:2990/jira/secure/projectavatar?size=small&avatarId=10324", 28 | "16x16": "http://localhost:2990/jira/secure/projectavatar?size=xsmall&avatarId=10324", 29 | "32x32": "http://localhost:2990/jira/secure/projectavatar?size=medium&avatarId=10324" 30 | } 31 | }, 32 | "fixVersions": [ 33 | { 34 | "self": "http://localhost:2990/jira/rest/api/2/version/10001", 35 | "id": "10001", 36 | "name": "Version 2.0", 37 | "archived": false, 38 | "released": false, 39 | "releaseDate": "2020-09-22" 40 | } 41 | ], 42 | "aggregatetimespent": null, 43 | "resolution": null, 44 | "timetracking": {}, 45 | "archiveddate": null, 46 | "customfield_10006": 2.0, 47 | "attachment": [], 48 | "aggregatetimeestimate": null, 49 | "resolutiondate": null, 50 | "workratio": -1, 51 | "summary": "As an Agile team, I'd like to learn about Scrum >> Click the \"DEMO-1\" link at the left of this row to see detail in the Description tab on the right", 52 | "lastViewed": null, 53 | "watches": { 54 | "self": "http://localhost:2990/jira/rest/api/2/issue/DEMO-1/watchers", 55 | "watchCount": 0, 56 | "isWatching": false 57 | }, 58 | "creator": { 59 | "self": "http://localhost:2990/jira/rest/api/2/user?username=admin", 60 | "name": "admin", 61 | "key": "admin", 62 | "emailAddress": "admin@admin.com", 63 | "avatarUrls": { 64 | "48x48": "https://www.gravatar.com/avatar/64e1b8d34f425d19e1ee2ea7236d3028?d=mm&s=48", 65 | "24x24": "https://www.gravatar.com/avatar/64e1b8d34f425d19e1ee2ea7236d3028?d=mm&s=24", 66 | "16x16": "https://www.gravatar.com/avatar/64e1b8d34f425d19e1ee2ea7236d3028?d=mm&s=16", 67 | "32x32": "https://www.gravatar.com/avatar/64e1b8d34f425d19e1ee2ea7236d3028?d=mm&s=32" 68 | }, 69 | "displayName": "admin", 70 | "active": true, 71 | "timeZone": "Europe/Berlin" 72 | }, 73 | "subtasks": [], 74 | "created": "2020-09-15T14:25:49.144+0200", 75 | "reporter": { 76 | "self": "http://localhost:2990/jira/rest/api/2/user?username=admin", 77 | "name": "admin", 78 | "key": "admin", 79 | "emailAddress": "admin@admin.com", 80 | "avatarUrls": { 81 | "48x48": "https://www.gravatar.com/avatar/64e1b8d34f425d19e1ee2ea7236d3028?d=mm&s=48", 82 | "24x24": "https://www.gravatar.com/avatar/64e1b8d34f425d19e1ee2ea7236d3028?d=mm&s=24", 83 | "16x16": "https://www.gravatar.com/avatar/64e1b8d34f425d19e1ee2ea7236d3028?d=mm&s=16", 84 | "32x32": "https://www.gravatar.com/avatar/64e1b8d34f425d19e1ee2ea7236d3028?d=mm&s=32" 85 | }, 86 | "displayName": "admin", 87 | "active": true, 88 | "timeZone": "Europe/Berlin" 89 | }, 90 | "aggregateprogress": { 91 | "progress": 0, 92 | "total": 0 93 | }, 94 | "priority": { 95 | "self": "http://localhost:2990/jira/rest/api/2/priority/3", 96 | "iconUrl": "http://localhost:2990/jira/images/icons/priorities/medium.svg", 97 | "name": "Medium", 98 | "id": "3" 99 | }, 100 | "customfield_10100": "{summaryBean=com.atlassian.jira.plugin.devstatus.rest.SummaryBean@17c77da8[summary={pullrequest=com.atlassian.jira.plugin.devstatus.rest.SummaryItemBean@3072c541[overall=PullRequestOverallBean{stateCount=0, state='OPEN', details=PullRequestOverallDetails{openCount=0, mergedCount=0, declinedCount=0}},byInstanceType={}], build=com.atlassian.jira.plugin.devstatus.rest.SummaryItemBean@697b1bb2[overall=com.atlassian.jira.plugin.devstatus.summary.beans.BuildOverallBean@4f058311[failedBuildCount=0,successfulBuildCount=0,unknownBuildCount=0,count=0,lastUpdated=,lastUpdatedTimestamp=],byInstanceType={}], review=com.atlassian.jira.plugin.devstatus.rest.SummaryItemBean@7e47ce0b[overall=com.atlassian.jira.plugin.devstatus.summary.beans.ReviewsOverallBean@53335c8f[stateCount=0,state=,dueDate=,overDue=false,count=0,lastUpdated=,lastUpdatedTimestamp=],byInstanceType={}], deployment-environment=com.atlassian.jira.plugin.devstatus.rest.SummaryItemBean@62246bd0[overall=com.atlassian.jira.plugin.devstatus.summary.beans.DeploymentOverallBean@15a718e[topEnvironments=[],showProjects=false,successfulCount=0,count=0,lastUpdated=,lastUpdatedTimestamp=],byInstanceType={}], repository=com.atlassian.jira.plugin.devstatus.rest.SummaryItemBean@41add038[overall=com.atlassian.jira.plugin.devstatus.summary.beans.CommitOverallBean@8333ba6[count=0,lastUpdated=,lastUpdatedTimestamp=],byInstanceType={}], branch=com.atlassian.jira.plugin.devstatus.rest.SummaryItemBean@4908bb9b[overall=com.atlassian.jira.plugin.devstatus.summary.beans.BranchOverallBean@1b0c7535[count=0,lastUpdated=,lastUpdatedTimestamp=],byInstanceType={}]},errors=[],configErrors=[]], devSummaryJson={\"cachedValue\":{\"errors\":[],\"configErrors\":[],\"summary\":{\"pullrequest\":{\"overall\":{\"count\":0,\"lastUpdated\":null,\"stateCount\":0,\"state\":\"OPEN\",\"details\":{\"openCount\":0,\"mergedCount\":0,\"declinedCount\":0,\"total\":0},\"open\":true},\"byInstanceType\":{}},\"build\":{\"overall\":{\"count\":0,\"lastUpdated\":null,\"failedBuildCount\":0,\"successfulBuildCount\":0,\"unknownBuildCount\":0},\"byInstanceType\":{}},\"review\":{\"overall\":{\"count\":0,\"lastUpdated\":null,\"stateCount\":0,\"state\":null,\"dueDate\":null,\"overDue\":false,\"completed\":false},\"byInstanceType\":{}},\"deployment-environment\":{\"overall\":{\"count\":0,\"lastUpdated\":null,\"topEnvironments\":[],\"showProjects\":false,\"successfulCount\":0},\"byInstanceType\":{}},\"repository\":{\"overall\":{\"count\":0,\"lastUpdated\":null},\"byInstanceType\":{}},\"branch\":{\"overall\":{\"count\":0,\"lastUpdated\":null},\"byInstanceType\":{}}}},\"isStale\":false}}", 101 | "labels": [], 102 | "environment": null, 103 | "timeestimate": null, 104 | "aggregatetimeoriginalestimate": null, 105 | "versions": [], 106 | "duedate": null, 107 | "progress": { 108 | "progress": 0, 109 | "total": 0 110 | }, 111 | "comment": { 112 | "comments": [], 113 | "maxResults": 0, 114 | "total": 0, 115 | "startAt": 0 116 | }, 117 | "issuelinks": [], 118 | "votes": { 119 | "self": "http://localhost:2990/jira/rest/api/2/issue/DEMO-1/votes", 120 | "votes": 0, 121 | "hasVoted": false 122 | }, 123 | "worklog": { 124 | "startAt": 0, 125 | "maxResults": 20, 126 | "total": 0, 127 | "worklogs": [] 128 | }, 129 | "assignee": null, 130 | "archivedby": null, 131 | "updated": "2020-09-15T14:25:49.144+0200", 132 | "status": { 133 | "self": "http://localhost:2990/jira/rest/api/2/status/10000", 134 | "description": "", 135 | "iconUrl": "http://localhost:2990/jira/", 136 | "name": "Aufgaben", 137 | "id": "10000", 138 | "statusCategory": { 139 | "self": "http://localhost:2990/jira/rest/api/2/statuscategory/2", 140 | "id": 2, 141 | "key": "new", 142 | "colorName": "blue-gray", 143 | "name": "Aufgaben" 144 | } 145 | } 146 | } 147 | } -------------------------------------------------------------------------------- /JiraRestClient.Net/JiraRestClient.Net/Util/JsonConstants.cs: -------------------------------------------------------------------------------- 1 | namespace JiraRestClient.Net.Util 2 | { 3 | public class JsonConstants 4 | { 5 | 6 | public const string PropId = "id"; 7 | 8 | public const string PropSelf = "self"; 9 | 10 | public const string PropName = "name"; 11 | 12 | public const string PropKey = "key"; 13 | 14 | public const string PropDescription = "description"; 15 | 16 | public const string PropDisplayname = "displayName"; 17 | 18 | public const string PropActive = "active"; 19 | 20 | public const string Prop16X16 = "16x16"; 21 | 22 | public const string Prop48X48 = "48x48"; 23 | 24 | public const string PropAssigneetype = "assigneeType"; 25 | 26 | public const string PropIsassigneetypevalid = "isAssigneeTypeValid"; 27 | 28 | public const string PropReleasedate = "releaseDate"; 29 | 30 | public const string PropOverdue = "overdue"; 31 | 32 | public const string PropReleased = "released"; 33 | 34 | public const string PropArchived = "archived"; 35 | 36 | public const string PropSubtask = "subtask"; 37 | 38 | public const string PropSubtasks = "subtasks"; 39 | 40 | public const string PropIconurl = "iconUrl"; 41 | 42 | public const string PropSummary = "summary"; 43 | 44 | public const string PropDuedate = "duedate"; 45 | 46 | public const string PropIssuetype = "issuetype"; 47 | 48 | public const string PropHasVoted = "hasVoted"; 49 | 50 | 51 | public const string PropResolutiondate = "resolutiondate"; 52 | 53 | public const string PropTimespent = "timeSpent"; 54 | 55 | public const string PropEmailAdress = "emailAddress"; 56 | 57 | public const string PropAggregatetimeoriginalestimate = "aggregatetimeoriginalestimate"; 58 | 59 | public const string PropUpdated = "updated"; 60 | 61 | public const string PropCreated = "created"; 62 | 63 | public const string PropIssuelinks = "issuelinks"; 64 | 65 | public const string PropLabels = "labels"; 66 | 67 | public const string PropWorkratio = "workratio"; 68 | 69 | public const string PropAttachment = "attachment"; 70 | 71 | public const string PropAggregatetimeestimate = "aggregatetimeestimate"; 72 | 73 | public const string PropEnvironment = "environment"; 74 | 75 | public const string PropTimeestimate = "timeestimate"; 76 | 77 | public const string PropAggregateprogress = "aggregateprogress"; 78 | 79 | public const string PropLastViewed = "lastViewed"; 80 | 81 | public const string PropComment = "comment"; 82 | 83 | public const string PropComments = "comments"; 84 | 85 | public const string PropTimeoriginalestimate = "timeoriginalestimate"; 86 | 87 | public const string PropAggregatetimespent = "aggregatetimespent"; 88 | 89 | public const string PropWorklogs = "worklogs"; 90 | 91 | public const string PropWatchCount = "watchCount"; 92 | 93 | public const string PropIsWatching = "isWatching"; 94 | 95 | public const string PropOriginalestimate = "originalEstimate"; 96 | 97 | public const string PropRemainingestimate = "remainingEstimate"; 98 | 99 | public const string PropOriginalEstimateSeconds = "originalEstimateSeconds"; 100 | 101 | public const string PropRemainingEstimateSeconds = "remainingEstimateSeconds"; 102 | 103 | public const string PropTimeSpentSeconds = "timeSpentSeconds"; 104 | 105 | public const string PropVotes = "votes"; 106 | 107 | public const string PropResolution = "resolution"; 108 | 109 | public const string PropInward = "inward"; 110 | 111 | public const string PropOutward = "outward"; 112 | 113 | public const string PropType = "type"; 114 | 115 | public const string PropValue = "value"; 116 | 117 | public const string PropStarted = "started"; 118 | 119 | public const string PropFilename = "filename"; 120 | 121 | public const string PropSize = "size"; 122 | 123 | public const string PropMimeType = "mimeType"; 124 | 125 | public const string PropContent = "content"; 126 | 127 | public const string PropThumbnail = "thumbnail"; 128 | 129 | public const string PropRealAssigneeType = "realAssigneeType"; 130 | 131 | public const string PropBody = "body"; 132 | 133 | public const string PropUserReleaseDate = "userReleaseDate"; 134 | 135 | public const string PropSteps = "steps"; 136 | 137 | public const string PropDefault = "default"; 138 | 139 | public const string PropTo = "to"; 140 | 141 | public const string PropTransitions = "transitions"; 142 | 143 | public const string PropErrorMessages = "errorMessages"; 144 | 145 | public const string PropErrors = "errors"; 146 | 147 | public const string PropRequired = "required"; 148 | 149 | public const string PropFrom = "from"; 150 | 151 | public const string PropFromString = "fromstring"; 152 | 153 | public const string PropToString = "tostring"; 154 | 155 | public const string PropFieldtype = "fieldtype"; 156 | 157 | public const string PropField = "field"; 158 | 159 | // Properties und Elemente der JQL-Suche 160 | 161 | public const string PropExpand = "expand"; 162 | 163 | public const string PropStartat = "startAt"; 164 | 165 | public const string PropMaxresults = "maxResults"; 166 | 167 | public const string PropTotal = "total"; 168 | 169 | public const string ElemIssues = "issues"; 170 | 171 | // ElementNamen 172 | 173 | public const string ElemComponents = "components"; 174 | 175 | public const string ElemIssuetype = "issuetype"; 176 | 177 | public const string ElemVersions = "versions"; 178 | 179 | public const string ElemFixVersions = "fixVersions"; 180 | 181 | public const string ElemRoles = "roles"; 182 | 183 | public const string ElemAssignee = "assignee"; 184 | 185 | public const string ElemLead = "lead"; 186 | 187 | public const string ElemAvatarUrls = "avatarUrls"; 188 | 189 | public const string ElemFields = "fields"; 190 | 191 | public const string ElemStatus = "status"; 192 | 193 | public const string ElemProgress = "progress"; 194 | 195 | public const string ElemTimetracking = "timetracking"; 196 | 197 | public const string ElemVotes = "votes"; 198 | 199 | public const string ElemReporter = "reporter"; 200 | 201 | public const string ElemPriority = "priority"; 202 | 203 | public const string ElemWatches = "watches"; 204 | 205 | public const string ElemWorklog = "worklog"; 206 | 207 | public const string ElemType = "type"; 208 | 209 | public const string ElemOutwardIssue = "outwardIssue"; 210 | 211 | public const string ElemInwardIssue = "inwardIssue"; 212 | 213 | public const string ElemAuthor = "author"; 214 | 215 | public const string ElemUpdateAuthor = "updateAuthor"; 216 | 217 | public const string ElemVisibility = "visibility"; 218 | 219 | public const string ElemAttachment = "attachment"; 220 | 221 | public const string ElemProject = "project"; 222 | 223 | public const string ElemAggregateprogress = "aggregateprogress"; 224 | 225 | public const string ElemRealAssignee = "realAssignee"; 226 | 227 | public const string ElemComment = "comment"; 228 | 229 | public const string ElemParent = "parent"; 230 | 231 | public const string ElemTransition = "transition"; 232 | 233 | public const string ElemChangelog = "changelog"; 234 | 235 | public const string ElemItems = "items"; 236 | 237 | public const string ElemHistories = "histories"; 238 | 239 | public const string ElemRenderedFields = "renderedFields"; 240 | 241 | // Rollen 242 | 243 | public const string RoleAdministrators = "Administrator"; 244 | 245 | public const string RoleUsers = "Users"; 246 | 247 | public const string RoleDevelopers = "Developers"; 248 | 249 | //Issue Type für die JQL Suche 250 | 251 | public const string IssuetypeImprovement = "Improvement"; 252 | 253 | public const string IssuetypeBug = "Bug"; 254 | 255 | public const string IssuetypeNewFeature = "New Feature"; 256 | 257 | public const string IssuetypeSubtask = "Sub-Task"; 258 | 259 | public const string IssuetypeTask = "Task"; 260 | 261 | //Priority für die JQL Suche 262 | 263 | public const string PriorityMajor = "Major"; 264 | 265 | public const string PriorityBlocker = "Blocker"; 266 | 267 | public const string PriorityCritical = "Critical"; 268 | 269 | public const string PriorityMinor = "Minor"; 270 | 271 | public const string PriorityTrivial = "Trivial"; 272 | 273 | } 274 | } 275 | -------------------------------------------------------------------------------- /JiraRestClient.Net/JiraRestClient.Net/Core/IssueClient.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Net; 5 | using System.Net.Http; 6 | using System.Text; 7 | using System.Text.Json; 8 | using JiraRestClient.Net.Core.Extension; 9 | using JiraRestClient.Net.Domain.Issue; 10 | using JiraRestClient.Net.Util; 11 | 12 | namespace JiraRestClient.Net.Core 13 | { 14 | /// 15 | /// Client to get Issues 16 | /// 17 | public class IssueClient : BaseClient 18 | { 19 | public IssueClient(JiraRestClient jiraRestClient) : base(jiraRestClient) 20 | { 21 | } 22 | 23 | /// 24 | /// Get a Issue by key 25 | /// 26 | /// The key of the Issue 27 | /// A async Task containing the Issue 28 | public Issue GetIssueByKey(string key) 29 | { 30 | var restUriBuilder = BaseUri.AddPaths(RestPathConstants.Issue, key); 31 | var completeUri = restUriBuilder.ToString(); 32 | var stream = Client.GetStringAsync(completeUri); 33 | var streamResult = stream.Result; 34 | return JsonSerializer.Deserialize(streamResult); 35 | } 36 | 37 | 38 | public Issue GetIssueByKey(string key, List fields, List expand) 39 | { 40 | var uri = BaseUri.AddPaths(RestPathConstants.Issue, key); 41 | if (fields is { Count: > 0 }) 42 | { 43 | var fieldsParam = string.Join(",", fields); 44 | uri.AddQuery($"{RestParamConstants.Fields}={fieldsParam}"); 45 | } 46 | 47 | if (expand is { Count: > 0 }) 48 | { 49 | var expandParam = string.Join(",", expand); 50 | uri.AddQuery($"{RestParamConstants.Expand}={expandParam}"); 51 | } 52 | 53 | var completeUri = uri.ToString(); 54 | var stream = Client.GetStringAsync(completeUri); 55 | var streamResult = stream.Result; 56 | return JsonSerializer.Deserialize(streamResult); 57 | } 58 | 59 | public IssueResponse CreateIssue(IssueUpdate issue) 60 | { 61 | var json = JsonSerializer.Serialize(issue, new JsonSerializerOptions 62 | { 63 | IgnoreNullValues = true 64 | }); 65 | var uri = BaseUri.AddPaths(RestPathConstants.Issue); 66 | var httpContent = new StringContent(json, Encoding.UTF8, "application/json"); 67 | var response = Client.PostAsync(uri.ToString(), httpContent); 68 | var httpResponseMessage = response.Result; 69 | switch (httpResponseMessage.StatusCode) 70 | { 71 | case HttpStatusCode.OK: 72 | { 73 | var readAsStringAsync = httpResponseMessage.Content.ReadAsStringAsync(); 74 | var result = readAsStringAsync.Result; 75 | var createdIssue = JsonSerializer.Deserialize(result); 76 | return new IssueResponse 77 | { 78 | Key = createdIssue.Key 79 | }; 80 | } 81 | case HttpStatusCode.BadRequest: 82 | { 83 | var readAsStringAsync = httpResponseMessage.Content.ReadAsStringAsync(); 84 | var result = readAsStringAsync.Result; 85 | return JsonSerializer.Deserialize(result); 86 | } 87 | case HttpStatusCode.Accepted: 88 | break; 89 | case HttpStatusCode.Ambiguous: 90 | break; 91 | case HttpStatusCode.BadGateway: 92 | break; 93 | case HttpStatusCode.Conflict: 94 | break; 95 | case HttpStatusCode.Continue: 96 | break; 97 | case HttpStatusCode.Created: 98 | { 99 | var readAsStringAsync = httpResponseMessage.Content.ReadAsStringAsync(); 100 | var result = readAsStringAsync.Result; 101 | var createdIssue = JsonSerializer.Deserialize(result); 102 | return new IssueResponse 103 | { 104 | Key = createdIssue.Key 105 | }; 106 | } 107 | case HttpStatusCode.ExpectationFailed: 108 | break; 109 | case HttpStatusCode.Forbidden: 110 | break; 111 | case HttpStatusCode.Found: 112 | break; 113 | case HttpStatusCode.GatewayTimeout: 114 | break; 115 | case HttpStatusCode.Gone: 116 | break; 117 | case HttpStatusCode.HttpVersionNotSupported: 118 | break; 119 | case HttpStatusCode.InternalServerError: 120 | { 121 | var readAsStringAsync = httpResponseMessage.Content.ReadAsStringAsync(); 122 | var result = readAsStringAsync.Result; 123 | return JsonSerializer.Deserialize(result); 124 | } 125 | case HttpStatusCode.LengthRequired: 126 | break; 127 | case HttpStatusCode.MethodNotAllowed: 128 | break; 129 | case HttpStatusCode.Moved: 130 | break; 131 | case HttpStatusCode.NoContent: 132 | break; 133 | case HttpStatusCode.NonAuthoritativeInformation: 134 | break; 135 | case HttpStatusCode.NotAcceptable: 136 | break; 137 | case HttpStatusCode.NotFound: 138 | break; 139 | case HttpStatusCode.NotImplemented: 140 | break; 141 | case HttpStatusCode.NotModified: 142 | break; 143 | case HttpStatusCode.PartialContent: 144 | break; 145 | case HttpStatusCode.PaymentRequired: 146 | break; 147 | case HttpStatusCode.PreconditionFailed: 148 | break; 149 | case HttpStatusCode.ProxyAuthenticationRequired: 150 | break; 151 | case HttpStatusCode.RedirectKeepVerb: 152 | break; 153 | case HttpStatusCode.RedirectMethod: 154 | break; 155 | case HttpStatusCode.RequestedRangeNotSatisfiable: 156 | break; 157 | case HttpStatusCode.RequestEntityTooLarge: 158 | break; 159 | case HttpStatusCode.RequestTimeout: 160 | break; 161 | case HttpStatusCode.RequestUriTooLong: 162 | break; 163 | case HttpStatusCode.ResetContent: 164 | break; 165 | case HttpStatusCode.ServiceUnavailable: 166 | break; 167 | case HttpStatusCode.SwitchingProtocols: 168 | break; 169 | case HttpStatusCode.Unauthorized: 170 | return new IssueResponse 171 | { 172 | ErrorMessages = new List { "Unauthorized" } 173 | }; 174 | case HttpStatusCode.UnsupportedMediaType: 175 | break; 176 | case HttpStatusCode.Unused: 177 | break; 178 | case HttpStatusCode.UpgradeRequired: 179 | break; 180 | case HttpStatusCode.UseProxy: 181 | break; 182 | default: 183 | return new IssueResponse 184 | { 185 | ErrorMessages = new List { $"HttpStatusCode: {httpResponseMessage.StatusCode}" } 186 | }; 187 | } 188 | 189 | return null; 190 | } 191 | 192 | 193 | public IEnumerable AddAttachment(string issueKey, List files) 194 | { 195 | var restUriBuilder = 196 | BaseUri.AddPaths(RestPathConstants.Issue, issueKey, RestPathConstants.Attachments); 197 | 198 | using var multipartFormContent = new MultipartFormDataContent(); 199 | multipartFormContent.Headers.Add("X-Atlassian-Token", "nocheck"); 200 | foreach (var file in files) 201 | { 202 | var fileName = GetFileName(file.Name); 203 | var contentStream = new StreamContent(file); 204 | multipartFormContent.Add(contentStream, "file", fileName); 205 | } 206 | 207 | var completeUri = restUriBuilder.ToString(); 208 | var postAsync = Client.PostAsync(completeUri, multipartFormContent); 209 | var httpResponseMessage = postAsync.Result; 210 | var response = httpResponseMessage.Content.ReadAsStringAsync(); 211 | return JsonSerializer.Deserialize>(response.Result); 212 | 213 | 214 | string GetFileName(string path) 215 | { 216 | var lastIndexOf = path.LastIndexOf(Path.DirectorySeparatorChar.ToString(), StringComparison.Ordinal) + 217 | 1; 218 | return path.Substring(lastIndexOf); 219 | } 220 | } 221 | } 222 | } -------------------------------------------------------------------------------- /JiraRestClient.Net/JiraRestClient.Net/Jql/EOperator.cs: -------------------------------------------------------------------------------- 1 | namespace JiraRestClient.Net.Jql 2 | { 3 | public class EOperator 4 | { 5 | /* 6 | * The "=" operator is used to search for issues where the value of the specified field exactly matches the specified value. 7 | * (Note: cannot be used with text fields; see the CONTAINS operator instead.) To find issues where the value of a specified 8 | * field exactly matches multiple values, use multiple "=" statements with the AND operator. 9 | */ 10 | public static readonly EOperator EQUALS = new EOperator("="); 11 | 12 | 13 | /* 14 | * The "!=" operator is used to search for issues where the value of the specified field does not match the specified value. 15 | * (Note: cannot be used with text fields; see the DOES NOT MATCH ("!~") operator instead.) Note that typing field != value 16 | * is the same as typing NOT field = value, and that field != EMPTY is the same as field IS_NOT EMPTY. 17 | * The "!=" operator will not match a field that has no value (i.e. a field that is empty). For example, component != fred 18 | * will only match issues that have a component and the component is not "fred". To find issues that have a component other 19 | * than "fred" or have no component, you would need to type: component != fred or component is empty. 20 | */ 21 | public static readonly EOperator NOT_EQUALS = new EOperator("!="); 22 | 23 | /* 24 | * The ">" operator is used to search for issues where the value of the specified field is greater than the specified value. 25 | * Cannot be used with text fields. Note that the ">" operator can only be used with fields which support ordering 26 | * (e.g. date fields and version fields). To see a field's supported operators, check the individual field reference. 27 | */ 28 | public static readonly EOperator GREATER_THAN = new EOperator(">"); 29 | 30 | /* 31 | * The ">=" operator is used to search for issues where the value of the specified field is greater than or equal to the 32 | * specified value. Cannot be used with text fields. Note that the ">=" operator can only be used with fields which support 33 | * ordering (e.g. date fields and version fields). To see a field's supported operators, check the individual field reference. 34 | */ 35 | public static readonly EOperator GREATER_THAN_EQUALS = new EOperator(">="); 36 | 37 | /* 38 | * The < operator is used to search for issues where the value of the specified field is less than the specified value. 39 | * Cannot be used with text fields.Note that the < operator can only be used with fields which support ordering (e.g. date fields and version fields). 40 | * To see a fields supported operators, check the individual field reference. 41 | */ 42 | public static readonly EOperator LESS_THAN = new EOperator("<"); 43 | 44 | /* 45 | * The <= operator is used to search for issues where the value of the specified field is less than or equal to than the 46 | * specified value. Cannot be used with text fields. Note that the "<=" operator can only be used with fields which support 47 | * ordering (e.g. date fields and version fields). To see a field's supported operators, check the individual field reference. 48 | */ 49 | public static readonly EOperator LESS_THAN_EQUALS = new EOperator("<="); 50 | 51 | /* 52 | * The "IN" operator is used to search for issues where the value of the specified field is one of multiple specified values. The 53 | * values are specified as a comma-delimited list, surrounded by parentheses. 54 | * Using "IN" is equivalent to using multiple EQUALS (=) statements, but is shorter and more convenient. That is, typing reporter 55 | * IN (tom, jane, harry) is the same as typing reporter = "tom" OR reporter = "jane" OR reporter = "harry". 56 | */ 57 | public static readonly EOperator IN = new EOperator("in"); 58 | 59 | /* 60 | * The "NOT IN" operator is used to search for issues where the value of the specified field is not one of multiple specified values. 61 | * Using "NOT IN" is equivalent to using multiple NOT_EQUALS (!=) statements, but is shorter and more convenient. That is, typing 62 | * reporter NOT IN (tom, jane, harry) is the same as typing reporter != "tom" AND reporter != "jane" AND reporter != "harry". The "NOT IN" 63 | * operator will not match a field that has no value (i.e. a field that is empty). For example, assignee not in (jack,jill) will only 64 | * match issues that have an assignee and the assignee is not "jack" or "jill". To find issues that are assigned to someone other than 65 | * "jack" or "jill" or are unassigned, you would need to type: assignee not in (jack,jill) or assignee is empty. 66 | */ 67 | public static readonly EOperator NOT_IN = new EOperator("not in"); 68 | 69 | /* 70 | * The "~" operator is used to search for issues where the value of the specified field matches the specified value (either an exact match or 71 | * a "fuzzy" match — see examples below). For use with text fields only, i.e.: 72 | *
  • Summary
  • 73 | *
  • Description
  • 74 | *
  • Environment
  • 75 | *
  • Comments
  • 76 | */ 77 | public static readonly EOperator CONTAINS = new EOperator("~"); 78 | 79 | /* 80 | * The "!~" operator is used to search for issues where the value of the specified field is not a "fuzzy" match for the specified value. 81 | * For use with text fields only, i.e.: 82 | *
  • Summary
  • 83 | *
  • Description
  • 84 | *
  • Environment
  • 85 | *
  • Comments
  • 86 | */ 87 | public static readonly EOperator DOES_NOT_CONTAIN = new EOperator("!~"); 88 | 89 | /* 90 | * The "IS" operator can only be used with EMPTY or NULL. That is, it is used to search for issues where the specified field has no value. 91 | * Note that not all fields are compatible with this operator; see the individual field reference for details. 92 | */ 93 | public static readonly EOperator IS = new EOperator("is"); 94 | 95 | /* 96 | * The "IS NOT" operator can only be used with EMPTY or NULL. That is, it is used to search for issues where the specified field has a value. 97 | * Note that not all fields are compatible with this operator; see the individual field reference for details. 98 | */ 99 | public static readonly EOperator IS_NOT = new EOperator("is not"); 100 | 101 | /* 102 | * The "WAS" operator is used to find issues that currently have, or previously had, the specified value for the specified field. 103 | * This operator has the following optional predicates: 104 | *
  • AFTER "date"
  • 105 | *
  • BEFORE "date"
  • 106 | *
  • BY "username"
  • 107 | *
  • DURING ("date1","date2")
  • 108 | *
  • ON "date"
  • 109 | *
    110 | * This operator will match the value name (e.g. "Resolved"), which was configured in your system at the time that the field was changed. 111 | * This operator will also match the value ID associated with that value name too — that is, it will match "4" as well as "Resolved". 112 | * (Note: This operator can be used with the Assignee, Fix Version, Priority, Reporter, Resolution and Status fields only.) 113 | */ 114 | public static readonly EOperator WAS = new EOperator("was"); 115 | 116 | /* 117 | * The "WAS IN" operator is used to find issues that currently have, or previously had, any of multiple specified values for the specified field. 118 | * The values are specified as a comma-delimited list, surrounded by parentheses. Using "WAS IN" is equivalent to using multiple WAS statements, 119 | * but is shorter and more convenient. That is, typing status WAS IN ('Resolved', 'Closed') is the same as typing status WAS "Resolved" OR status WAS "Closed". 120 | *
  • AFTER "date"
  • 121 | *
  • BEFORE "date"
  • 122 | *
  • BY "username"
  • 123 | *
  • DURING ("date1","date2")
  • 124 | *
  • ON "date"
  • 125 | *
    126 | * This operator will match the value name (e.g. "Resolved"), which was configured in your system at the time that the field was changed. This 127 | * operator will also match the value ID associated with that value name too — that is, it will match "4" as well as "Resolved". (Note: This 128 | * operator can be used with the Assignee, Fix Version, Priority, Reporter, Resolution and Status fields only.) 129 | */ 130 | public static readonly EOperator WAS_IN = new EOperator("was in"); 131 | 132 | /* 133 | * The "WAS NOT IN" operator is used to search for issues where the value of the specified field has never been one of multiple specified values. 134 | * Using "WAS NOT IN" is equivalent to using multiple WAS_NOT statements, but is shorter and more convenient. That is, typing status 135 | * WAS NOT IN ("Resolved","In Progress") is the same as typing status WAS NOT "Resolved" AND status WAS NOT "In Progress". 136 | * This operator has the following optional predicates: 137 | *
  • AFTER "date"
  • 138 | *
  • BEFORE "date"
  • 139 | *
  • BY "username"
  • 140 | *
  • DURING ("date1","date2")
  • 141 | *
  • ON "date"
  • 142 | *
    143 | * This operator will match the value name (e.g. "Resolved"), which was configured in your system at the time that the field was changed. 144 | * This operator will also match the value ID associated with that value name too — that is, it will match "4" as well as "Resolved". 145 | * (Note: This operator can be used with the Assignee, Fix Version, Priority, Reporter, Resolution and Status fields only.) 146 | */ 147 | public static readonly EOperator WAS_NOT_IN = new EOperator("was not in"); 148 | 149 | /* 150 | * The "WAS NOT" operator is used to find issues that have never had the specified value for the specified field. 151 | * This operator has the following optional predicates: 152 | *
  • AFTER "date"
  • 153 | *
  • BEFORE "date"
  • 154 | *
  • BY "username"
  • 155 | *
  • DURING ("date1","date2")
  • 156 | *
  • ON "date"
  • 157 | *
    158 | * This operator will match the value name (e.g. "Resolved"), which was configured in your system at the time that the field was changed. 159 | * This operator will also match the value ID associated with that value name too — that is, it will match "4" as well as "Resolved". 160 | * (Note: This operator can be used with the Assignee, Fix Version, Priority, Reporter, Resolution and Status fields only.) 161 | */ 162 | public static readonly EOperator WAS_NOT = new EOperator("was not"); 163 | 164 | /* 165 | * The "CHANGED" operator is used to find issues that have a value which had changed for the specified field. 166 | * This operator has the following optional predicates: 167 | *
  • AFTER "date"
  • 168 | *
  • BEFORE "date"
  • 169 | *
  • BY "username"
  • 170 | *
  • DURING ("date1","date2")
  • 171 | *
  • ON "date"
  • 172 | *
  • FROM "oldvalue"
  • 173 | *
  • TO "newvalue"
  • 174 | *
    175 | * (Note: This operator can be used with the Assignee, Fix Version, Priority, Reporter, Resolution and Status fields only.) 176 | */ 177 | public static readonly EOperator CHANGED = new EOperator("changed"); 178 | public static readonly EOperator AFTER = new EOperator("after"); 179 | public static readonly EOperator BEFORE = new EOperator("before"); 180 | public static readonly EOperator BY = new EOperator("by"); 181 | public static readonly EOperator FROM = new EOperator("from"); 182 | public static readonly EOperator ON = new EOperator("on"); 183 | public static readonly EOperator TO = new EOperator("to"); 184 | 185 | /* 186 | * The operator. 187 | */ 188 | public string Eoperator { get; set; } 189 | 190 | /* 191 | * Instantiates a new operator. 192 | * 193 | * @param eoperator the name of the operator 194 | */ 195 | public EOperator(string eoperator) 196 | { 197 | Eoperator = eoperator; 198 | } 199 | 200 | 201 | public override string ToString() 202 | { 203 | return Eoperator; 204 | } 205 | 206 | } 207 | } 208 | -------------------------------------------------------------------------------- /JiraRestClient.Net/JiraRestClient.Net/Domain/Issue/Issue.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Text.Json.Serialization; 3 | 4 | namespace JiraRestClient.Net.Domain.Issue 5 | { 6 | public class Issue : KeyBase 7 | { 8 | [JsonPropertyName("expand")] 9 | public string Expand { get; set; } 10 | 11 | [JsonPropertyName("fields")] 12 | public IssueFields Fields { get; set; } 13 | 14 | [JsonPropertyName("renderedFields")] 15 | public RenderedFields RenderedFields { get; set; } 16 | 17 | [JsonPropertyName("transitions")] 18 | public List Transitions { get; set; } 19 | 20 | [JsonPropertyName("changelog")] 21 | public ChangeLog Changelog { get; set; } 22 | } 23 | 24 | public class Aggregateprogress 25 | { 26 | [JsonPropertyName("progress")] 27 | public int? Progress { get; set; } 28 | [JsonPropertyName("total")] 29 | public int? Total { get; set; } 30 | } 31 | 32 | public class Attachment 33 | { 34 | [JsonPropertyName("self")] 35 | public string Self { get; set; } 36 | [JsonPropertyName("id")] 37 | public string Id { get; set; } 38 | [JsonPropertyName("filename")] 39 | public string Filename { get; set; } 40 | [JsonPropertyName("author")] 41 | public User Author { get; set; } 42 | [JsonPropertyName("created")] 43 | public string Created { get; set; } 44 | [JsonPropertyName("size")] 45 | public int? Size { get; set; } 46 | [JsonPropertyName("mimetype")] 47 | public string MimeType { get; set; } 48 | [JsonPropertyName("content")] 49 | public string Content { get; set; } 50 | [JsonPropertyName("thumbnail")] 51 | public string Thumbnail { get; set; } 52 | } 53 | 54 | public class Attrs 55 | { 56 | [JsonPropertyName("url")] 57 | public string Url { get; set; } 58 | 59 | [JsonPropertyName("level")] 60 | public int Level { get; set; } 61 | } 62 | 63 | public class Content 64 | { 65 | [JsonPropertyName("type")] 66 | public string Type { get; set; } 67 | [JsonPropertyName("content")] 68 | public List Contents { get; set; } 69 | [JsonPropertyName("text")] 70 | public string Text { get; set; } 71 | [JsonPropertyName("attrs")] 72 | public Attrs Attrs { get; set; } 73 | } 74 | 75 | public class Description 76 | { 77 | [JsonPropertyName("version")] 78 | public int Version { get; set; } 79 | [JsonPropertyName("type")] 80 | public string Type { get; set; } 81 | [JsonPropertyName("content")] 82 | public List Content { get; set; } 83 | } 84 | 85 | 86 | public class IssueFields 87 | { 88 | [JsonPropertyName("parent")] 89 | public Issue Parent { get; set; } 90 | 91 | [JsonPropertyName("summary")] 92 | public string Summary { get; set; } 93 | [JsonPropertyName("progress")] 94 | public Progress Progress { get; set; } 95 | [JsonPropertyName("timetracking")] 96 | public Timetracking Timetracking { get; set; } 97 | [JsonPropertyName("issuetype")] 98 | public IssueType Issuetype { get; set; } 99 | [JsonPropertyName("votes")] 100 | public Votes Votes { get; set; } 101 | [JsonPropertyName("resolution")] 102 | public Resolution Resolution { get; set; } 103 | [JsonPropertyName("fixversions")] 104 | public List FixVersions { get; set; } 105 | [JsonPropertyName("resolutiondate")] 106 | public string Resolutiondate { get; set; } 107 | [JsonPropertyName("timespent")] 108 | public int? Timespent { get; set; } 109 | [JsonPropertyName("creator")] 110 | public User Creator { get; set; } 111 | [JsonPropertyName("reporter")] 112 | public User Reporter { get; set; } 113 | [JsonPropertyName("aggregatetimeoriginalestimate")] 114 | public int? Aggregatetimeoriginalestimate { get; set; } 115 | [JsonPropertyName("created")] 116 | public string Created { get; set; } 117 | [JsonPropertyName("updated")] 118 | public string Updated { get; set; } 119 | [JsonPropertyName("description")] 120 | public Description Description { get; set; } 121 | [JsonPropertyName("priority")] 122 | public Priority Priority { get; set; } 123 | [JsonPropertyName("duedate")] 124 | public string Duedate { get; set; } 125 | [JsonPropertyName("issuelinks")] 126 | public List Issuelinks { get; set; } 127 | [JsonPropertyName("watches")] 128 | public Watches Watches { get; set; } 129 | [JsonPropertyName("worklog")] 130 | public Worklog Worklog { get; set; } 131 | [JsonPropertyName("subtasks")] 132 | public List Subtasks { get; set; } 133 | [JsonPropertyName("status")] 134 | public Status Status { get; set; } 135 | [JsonPropertyName("labels")] 136 | public List Labels { get; set; } 137 | [JsonPropertyName("workratio")] 138 | public int? Workratio { get; set; } 139 | [JsonPropertyName("assignee")] 140 | public User Assignee { get; set; } 141 | [JsonPropertyName("attachment")] 142 | public List Attachment { get; set; } 143 | [JsonPropertyName("aggregatetimeestimate")] 144 | public int? Aggregatetimeestimate { get; set; } 145 | [JsonPropertyName("project")] 146 | public Project Project { get; set; } 147 | [JsonPropertyName("versions")] 148 | public List Versions { get; set; } 149 | [JsonPropertyName("environment")] 150 | public string Environment { get; set; } 151 | [JsonPropertyName("timestimate")] 152 | public int? Timeestimate { get; set; } 153 | [JsonPropertyName("aggregateprogress")] 154 | public Aggregateprogress Aggregateprogress { get; set; } 155 | [JsonPropertyName("lastviewed")] 156 | public string LastViewed { get; set; } 157 | [JsonPropertyName("components")] 158 | public List Components { get; set; } 159 | [JsonPropertyName("comment")] 160 | public CommentList CommentList { get; set; } 161 | [JsonPropertyName("timeoriginalestimate")] 162 | public int? Timeoriginalestimate { get; set; } 163 | [JsonPropertyName("aggregatetimespent")] 164 | public int? Aggregatetimespent { get; set; } 165 | } 166 | 167 | public class Timetracking 168 | { 169 | [JsonPropertyName("originalestimate")] 170 | public string OriginalEstimate { get; set; } 171 | [JsonPropertyName("originalestimateseconds")] 172 | public int? OriginalEstimateSeconds { get; set; } 173 | } 174 | 175 | public class Votes 176 | { 177 | [JsonPropertyName("self")] 178 | public string Self { get; set; } 179 | [JsonPropertyName("votes")] 180 | public int? Vote { get; set; } 181 | [JsonPropertyName("hasvoted")] 182 | public bool HasVoted { get; set; } 183 | } 184 | 185 | public class Progress 186 | { 187 | [JsonPropertyName("progress")] 188 | public int? ProgressValue { get; set; } 189 | [JsonPropertyName("total")] 190 | public int? Total { get; set; } 191 | } 192 | 193 | public class AvatarUrls 194 | { 195 | [JsonPropertyName("16x16")] 196 | public string Url16X16 { get; set; } 197 | [JsonPropertyName("24x24")] 198 | public string Url24X24 { get; set; } 199 | [JsonPropertyName("32x32")] 200 | public string Url32X32 { get; set; } 201 | [JsonPropertyName("48x48")] 202 | public string Url48X48 { get; set; } 203 | } 204 | 205 | public class Priority : Base 206 | { 207 | [JsonPropertyName("iconurl")] 208 | public string IconUrl { get; set; } 209 | } 210 | 211 | public class Watches 212 | { 213 | [JsonPropertyName("self")] 214 | public string Self { get; set; } 215 | [JsonPropertyName("watchcount")] 216 | public int? WatchCount { get; set; } 217 | [JsonPropertyName("iswatching")] 218 | public bool IsWatching { get; set; } 219 | } 220 | 221 | public class Worklog 222 | { 223 | [JsonPropertyName("startat")] 224 | public int? StartAt { get; set; } 225 | [JsonPropertyName("maxresults")] 226 | public int? MaxResults { get; set; } 227 | [JsonPropertyName("total")] 228 | public int? Total { get; set; } 229 | [JsonPropertyName("worklogs")] 230 | public List Worklogs { get; set; } 231 | } 232 | 233 | public class StatusCategory : KeyBase 234 | { 235 | [JsonPropertyName("colorname")] 236 | public string ColorName { get; set; } 237 | } 238 | 239 | public class Status : Base 240 | { 241 | [JsonPropertyName("description")] 242 | public string Description { get; set; } 243 | [JsonPropertyName("iconurl")] 244 | public string IconUrl { get; set; } 245 | [JsonPropertyName("statuscategory")] 246 | public StatusCategory StatusCategory { get; set; } 247 | [JsonPropertyName("statusColor")] 248 | public string StatusColor { get; set; } 249 | } 250 | 251 | public class CommentList 252 | { 253 | public int? StartAt { get; set; } 254 | public int? MaxResults { get; set; } 255 | public int? Total { get; set; } 256 | public List Comments { get; set; } 257 | } 258 | 259 | public class Resolution : Base 260 | { 261 | public string Description { get; set; } 262 | } 263 | 264 | public class Comment : Base 265 | { 266 | public User Author { get; set; } 267 | 268 | public string Body { get; set; } 269 | 270 | public User UpdateAuthor { get; set; } 271 | 272 | public string Created { get; set; } 273 | 274 | public string Updated { get; set; } 275 | } 276 | 277 | public class RenderedFields : Base 278 | { 279 | [JsonPropertyName("aggregatetimeestimate")] 280 | public string Aggregatetimeestimate { get; set; } 281 | 282 | [JsonPropertyName("aggregatetimeoriginalestimate")] 283 | public string Aggregatetimeoriginalestimate { get; set; } 284 | 285 | [JsonPropertyName("timetracking")] 286 | public Timetracking Timetracking { get; set; } 287 | 288 | [JsonPropertyName("environment")] 289 | public string Environment { get; set; } 290 | 291 | [JsonPropertyName("created")] 292 | public string Created { get; set; } 293 | 294 | [JsonPropertyName("updated")] 295 | public string Updated { get; set; } 296 | 297 | [JsonPropertyName("description")] 298 | public string Description { get; set; } 299 | 300 | [JsonPropertyName("timeestimate")] 301 | public string Timeestimate { get; set; } 302 | 303 | [JsonPropertyName("duedate")] 304 | public string Duedate { get; set; } 305 | 306 | [JsonPropertyName("lastviewed")] 307 | public string LastViewed { get; set; } 308 | 309 | [JsonPropertyName("attachment")] 310 | public List Attachment { get; set; } 311 | 312 | [JsonPropertyName("comment")] 313 | public CommentList Comment { get; set; } 314 | 315 | [JsonPropertyName("timeoriginalestimate")] 316 | public string Timeoriginalestimate { get; set; } 317 | 318 | [JsonPropertyName("timespent")] 319 | public object Timespent { get; set; } 320 | 321 | [JsonPropertyName("worklog")] 322 | public Worklog Worklog { get; set; } 323 | 324 | [JsonPropertyName("aggregatetimespent")] 325 | public object Aggregatetimespent { get; set; } 326 | } 327 | 328 | public class ChangeLog : Base 329 | { 330 | [JsonPropertyName("startat")] 331 | public int StartAt { get; set; } 332 | 333 | [JsonPropertyName("maxresults")] 334 | public int MaxResults { get; set; } 335 | 336 | [JsonPropertyName("total")] 337 | public int Total { get; set; } 338 | 339 | [JsonPropertyName("histories")] 340 | public List Histories { get; set; } 341 | } 342 | 343 | public class History : Base 344 | { 345 | [JsonPropertyName("author")] 346 | public User Author { get; set; } 347 | 348 | [JsonPropertyName("created")] 349 | public string Created { get; set; } 350 | 351 | [JsonPropertyName("items")] 352 | public List Items { get; set; } 353 | } 354 | 355 | public class Item : Base 356 | { 357 | [JsonPropertyName("field")] 358 | public string Field { get; set; } 359 | 360 | [JsonPropertyName("fieldtype")] 361 | public string Fieldtype { get; set; } 362 | 363 | [JsonPropertyName("from")] 364 | public string From { get; set; } 365 | 366 | [JsonPropertyName("fromstring")] 367 | public string FromString { get; set; } 368 | 369 | [JsonPropertyName("to")] 370 | public string To { get; set; } 371 | } 372 | 373 | public class Transition : KeyBase 374 | { 375 | 376 | [JsonPropertyName("fields")] 377 | public TransitionFields Fields { get; set; } 378 | 379 | [JsonPropertyName("to")] 380 | public Status To { get; set; } 381 | } 382 | 383 | public class TransitionFields 384 | { 385 | } 386 | } -------------------------------------------------------------------------------- /JiraRestClient.Net/JiraRestClient.Net.Test/Examples/v3/issue.json: -------------------------------------------------------------------------------- 1 | { 2 | "expand": "renderedFields,names,schema,operations,editmeta,changelog,versionedRepresentations,customfield_10621.cmdb.label,customfield_10621.cmdb.objectKey,customfield_10621.cmdb.attributes,customfield_10052.properties,customfield_10053.properties,customfield_10010.requestTypePractice", 3 | "id": "333004", 4 | "self": "https://sma.atlassian.net/rest/api/3/issue/333004", 5 | "key": "UITEST-1388", 6 | "fields": { 7 | "parent": { 8 | "id": "116409", 9 | "key": "IGUPROG-782", 10 | "self": "https://sma.atlassian.net/rest/api/3/issue/116409", 11 | "fields": { 12 | "summary": "Weiterentwicklung der E2E-Info-Webapp unter e2e.sma.de", 13 | "status": { 14 | "self": "https://sma.atlassian.net/rest/api/3/status/10180", 15 | "description": "(Migrated on 24 Feb 2023 16:56 UTC)", 16 | "iconUrl": "https://sma.atlassian.net/images/icons/statuses/generic.png", 17 | "name": "Funnel", 18 | "id": "10180", 19 | "statusCategory": { 20 | "self": "https://sma.atlassian.net/rest/api/3/statuscategory/2", 21 | "id": 2, 22 | "key": "new", 23 | "colorName": "blue-gray", 24 | "name": "To Do" 25 | } 26 | }, 27 | "priority": { 28 | "self": "https://sma.atlassian.net/rest/api/3/priority/3", 29 | "iconUrl": "https://sma.atlassian.net/images/icons/priorities/medium.svg", 30 | "name": "Medium", 31 | "id": "3" 32 | }, 33 | "issuetype": { 34 | "self": "https://sma.atlassian.net/rest/api/3/issuetype/10000", 35 | "id": "10000", 36 | "description": "A big user story that needs to be broken down. Created by Jira Software - do not edit or delete.", 37 | "iconUrl": "https://sma.atlassian.net/images/icons/issuetypes/epic.svg", 38 | "name": "Epic", 39 | "subtask": false, 40 | "hierarchyLevel": 1 41 | } 42 | } 43 | }, 44 | "resolution": { 45 | "self": "https://sma.atlassian.net/rest/api/3/resolution/10000", 46 | "id": "10000", 47 | "description": "Work has been completed on this issue.", 48 | "name": "Done" 49 | }, 50 | 51 | "lastViewed": "2023-03-13T13:20:17.633+0100", 52 | "aggregatetimeoriginalestimate": null, 53 | "issuelinks": [], 54 | "assignee": { 55 | "self": "https://sma.atlassian.net/rest/api/3/user?accountId=5ccaa3a43252b611c8ec161a", 56 | "accountId": "5ccaa3a43252b611c8ec161a", 57 | "emailAddress": "christian.schulze@sma.de", 58 | "avatarUrls": { 59 | "48x48": "https://avatar-management--avatars.us-west-2.prod.public.atl-paas.net/5ccaa3a43252b611c8ec161a/a91d4ab2-3208-44ae-a8c6-995c9fe978ad/48", 60 | "24x24": "https://avatar-management--avatars.us-west-2.prod.public.atl-paas.net/5ccaa3a43252b611c8ec161a/a91d4ab2-3208-44ae-a8c6-995c9fe978ad/24", 61 | "16x16": "https://avatar-management--avatars.us-west-2.prod.public.atl-paas.net/5ccaa3a43252b611c8ec161a/a91d4ab2-3208-44ae-a8c6-995c9fe978ad/16", 62 | "32x32": "https://avatar-management--avatars.us-west-2.prod.public.atl-paas.net/5ccaa3a43252b611c8ec161a/a91d4ab2-3208-44ae-a8c6-995c9fe978ad/32" 63 | }, 64 | "displayName": "Christian Schulze", 65 | "active": true, 66 | "timeZone": "Europe/Berlin", 67 | "accountType": "atlassian" 68 | }, 69 | "subtasks": [], 70 | "worklog": { 71 | "startAt": 0, 72 | "maxResults": 20, 73 | "total": 0, 74 | "worklogs": [] 75 | }, 76 | "issuetype": { 77 | "self": "https://sma.atlassian.net/rest/api/3/issuetype/10009", 78 | "id": "10009", 79 | "description": "Stories track functionality or features expressed as user goals.", 80 | "iconUrl": "https://sma.atlassian.net/images/icons/issuetypes/story.svg", 81 | "name": "Story", 82 | "subtask": false, 83 | "hierarchyLevel": 0 84 | }, 85 | "timetracking": {}, 86 | "duedate": null, 87 | "timeestimate": null, 88 | "status": { 89 | "self": "https://sma.atlassian.net/rest/api/3/status/6", 90 | "description": "The issue is considered finished, the resolution is correct. Issues which are closed can be reopened.", 91 | "iconUrl": "https://sma.atlassian.net/images/icons/statuses/closed.png", 92 | "name": "Closed", 93 | "id": "6", 94 | "statusCategory": { 95 | "self": "https://sma.atlassian.net/rest/api/3/statuscategory/3", 96 | "id": 3, 97 | "key": "done", 98 | "colorName": "green", 99 | "name": "Done" 100 | } 101 | }, 102 | "aggregatetimeestimate": null, 103 | "creator": { 104 | "self": "https://sma.atlassian.net/rest/api/3/user?accountId=5c88dfc843de836baaa6eeb9", 105 | "accountId": "5c88dfc843de836baaa6eeb9", 106 | "emailAddress": "melissa.weber@sma.de", 107 | "avatarUrls": { 108 | "48x48": "https://secure.gravatar.com/avatar/adfad45fe118030d8ac4e2b5c25179f2?d=https%3A%2F%2Favatar-management--avatars.us-west-2.prod.public.atl-paas.net%2Finitials%2FMW-4.png", 109 | "24x24": "https://secure.gravatar.com/avatar/adfad45fe118030d8ac4e2b5c25179f2?d=https%3A%2F%2Favatar-management--avatars.us-west-2.prod.public.atl-paas.net%2Finitials%2FMW-4.png", 110 | "16x16": "https://secure.gravatar.com/avatar/adfad45fe118030d8ac4e2b5c25179f2?d=https%3A%2F%2Favatar-management--avatars.us-west-2.prod.public.atl-paas.net%2Finitials%2FMW-4.png", 111 | "32x32": "https://secure.gravatar.com/avatar/adfad45fe118030d8ac4e2b5c25179f2?d=https%3A%2F%2Favatar-management--avatars.us-west-2.prod.public.atl-paas.net%2Finitials%2FMW-4.png" 112 | }, 113 | "displayName": "Melissa Weber", 114 | "active": true, 115 | "timeZone": "Europe/Berlin", 116 | "accountType": "atlassian" 117 | }, 118 | "timespent": null, 119 | "aggregatetimespent": null, 120 | 121 | "workratio": -1, 122 | "labels": [], 123 | "components": [ 124 | { 125 | "self": "https://sma.atlassian.net/rest/api/3/component/14449", 126 | "id": "14449", 127 | "name": "WebApp", 128 | "description": "WebApp zur Auswertung der Iguana-Ui-Tests" 129 | } 130 | ], 131 | "reporter": { 132 | "self": "https://sma.atlassian.net/rest/api/3/user?accountId=5c88dfc843de836baaa6eeb9", 133 | "accountId": "5c88dfc843de836baaa6eeb9", 134 | "emailAddress": "melissa.weber@sma.de", 135 | "avatarUrls": { 136 | "48x48": "https://secure.gravatar.com/avatar/adfad45fe118030d8ac4e2b5c25179f2?d=https%3A%2F%2Favatar-management--avatars.us-west-2.prod.public.atl-paas.net%2Finitials%2FMW-4.png", 137 | "24x24": "https://secure.gravatar.com/avatar/adfad45fe118030d8ac4e2b5c25179f2?d=https%3A%2F%2Favatar-management--avatars.us-west-2.prod.public.atl-paas.net%2Finitials%2FMW-4.png", 138 | "16x16": "https://secure.gravatar.com/avatar/adfad45fe118030d8ac4e2b5c25179f2?d=https%3A%2F%2Favatar-management--avatars.us-west-2.prod.public.atl-paas.net%2Finitials%2FMW-4.png", 139 | "32x32": "https://secure.gravatar.com/avatar/adfad45fe118030d8ac4e2b5c25179f2?d=https%3A%2F%2Favatar-management--avatars.us-west-2.prod.public.atl-paas.net%2Finitials%2FMW-4.png" 140 | }, 141 | "displayName": "Melissa Weber", 142 | "active": true, 143 | "timeZone": "Europe/Berlin", 144 | "accountType": "atlassian" 145 | }, 146 | "progress": { 147 | "progress": 0, 148 | "total": 0 149 | }, 150 | "project": { 151 | "self": "https://sma.atlassian.net/rest/api/3/project/10357", 152 | "id": "10357", 153 | "key": "UITEST", 154 | "name": "Iguana-UI-Test", 155 | "projectTypeKey": "software", 156 | "simplified": false, 157 | "avatarUrls": { 158 | "48x48": "https://sma.atlassian.net/rest/api/3/universal_avatar/view/type/project/avatar/10400", 159 | "24x24": "https://sma.atlassian.net/rest/api/3/universal_avatar/view/type/project/avatar/10400?size=small", 160 | "16x16": "https://sma.atlassian.net/rest/api/3/universal_avatar/view/type/project/avatar/10400?size=xsmall", 161 | "32x32": "https://sma.atlassian.net/rest/api/3/universal_avatar/view/type/project/avatar/10400?size=medium" 162 | }, 163 | "projectCategory": { 164 | "self": "https://sma.atlassian.net/rest/api/3/projectCategory/10008", 165 | "id": "10008", 166 | "description": "Projects in Technology with standard configuration", 167 | "name": "Technology PEP Development" 168 | } 169 | }, 170 | "resolutiondate": "2023-03-13T13:20:17.775+0100", 171 | "watches": { 172 | "self": "https://sma.atlassian.net/rest/api/3/issue/UITEST-1388/watchers", 173 | "watchCount": 0, 174 | "isWatching": false 175 | }, 176 | "updated": "2023-03-13T13:20:17.804+0100", 177 | "timeoriginalestimate": null, 178 | "description": { 179 | "version": 1, 180 | "type": "doc", 181 | "content": [ 182 | { 183 | "type": "paragraph", 184 | "content": [ 185 | { 186 | "type": "text", 187 | "text": "Mit Einführung der Jira-Cloud müssen in der WebApp die URLs angepasst werden, sodass weiterhin neue Tickets erstellt werden, bei einer Report Anfrage." 188 | } 189 | ] 190 | }, 191 | { 192 | "type": "paragraph", 193 | "content": [ 194 | { 195 | "type": "text", 196 | "text": "Info aus der AskMe-Session der JiraCloud: Es reicht nicht einfach die URL auszutauschen, da man Tokens verwenden muss. Weitere Infos sind hier " 197 | }, 198 | { 199 | "type": "inlineCard", 200 | "attrs": { 201 | "url": "https://developer.atlassian.com/cloud/jira/platform/rest/v3/intro/#version" 202 | } 203 | }, 204 | { 205 | "type": "text", 206 | "text": " zu finden oder wir müssen ein Service-Ticket erstellen, um Hilfe anzufordern." 207 | } 208 | ] 209 | }, 210 | { 211 | "type": "paragraph", 212 | "content": [ 213 | { 214 | "type": "text", 215 | "text": "Anbei sind die Codestellen, die angepasst werden müssen." 216 | } 217 | ] 218 | } 219 | ] 220 | }, 221 | "summary": "URL für die neue Jira-Cloud anpassen", 222 | "comment": { 223 | "comments": [ 224 | { 225 | "self": "https://sma.atlassian.net/rest/api/3/issue/333004/comment/1209708", 226 | "id": "1209708", 227 | "author": { 228 | "self": "https://sma.atlassian.net/rest/api/3/user?accountId=5ccaa3a43252b611c8ec161a", 229 | "accountId": "5ccaa3a43252b611c8ec161a", 230 | "emailAddress": "christian.schulze@sma.de", 231 | "avatarUrls": { 232 | "48x48": "https://avatar-management--avatars.us-west-2.prod.public.atl-paas.net/5ccaa3a43252b611c8ec161a/a91d4ab2-3208-44ae-a8c6-995c9fe978ad/48", 233 | "24x24": "https://avatar-management--avatars.us-west-2.prod.public.atl-paas.net/5ccaa3a43252b611c8ec161a/a91d4ab2-3208-44ae-a8c6-995c9fe978ad/24", 234 | "16x16": "https://avatar-management--avatars.us-west-2.prod.public.atl-paas.net/5ccaa3a43252b611c8ec161a/a91d4ab2-3208-44ae-a8c6-995c9fe978ad/16", 235 | "32x32": "https://avatar-management--avatars.us-west-2.prod.public.atl-paas.net/5ccaa3a43252b611c8ec161a/a91d4ab2-3208-44ae-a8c6-995c9fe978ad/32" 236 | }, 237 | "displayName": "Christian Schulze", 238 | "active": true, 239 | "timeZone": "Europe/Berlin", 240 | "accountType": "atlassian" 241 | }, 242 | "body": { 243 | "version": 1, 244 | "type": "doc", 245 | "content": [ 246 | { 247 | "type": "paragraph", 248 | "content": [ 249 | { 250 | "type": "text", 251 | "text": "In der Jira Cloud Rest Api ist BasicAuth nicht mehr verfügbar. Wir können lediglich pro User einen ApiToken nutzen welcher jedoch von jedem selbst generiert werden muss. " 252 | }, 253 | { 254 | "type": "hardBreak" 255 | }, 256 | { 257 | "type": "text", 258 | "text": "Diese Api Tokens will ich aber auch auf keinen Fall in unserer Datenbank speichern. Von daher wird wohl die Jira Verbindung sterben. " 259 | } 260 | ] 261 | } 262 | ] 263 | }, 264 | "updateAuthor": { 265 | "self": "https://sma.atlassian.net/rest/api/3/user?accountId=5ccaa3a43252b611c8ec161a", 266 | "accountId": "5ccaa3a43252b611c8ec161a", 267 | "emailAddress": "christian.schulze@sma.de", 268 | "avatarUrls": { 269 | "48x48": "https://avatar-management--avatars.us-west-2.prod.public.atl-paas.net/5ccaa3a43252b611c8ec161a/a91d4ab2-3208-44ae-a8c6-995c9fe978ad/48", 270 | "24x24": "https://avatar-management--avatars.us-west-2.prod.public.atl-paas.net/5ccaa3a43252b611c8ec161a/a91d4ab2-3208-44ae-a8c6-995c9fe978ad/24", 271 | "16x16": "https://avatar-management--avatars.us-west-2.prod.public.atl-paas.net/5ccaa3a43252b611c8ec161a/a91d4ab2-3208-44ae-a8c6-995c9fe978ad/16", 272 | "32x32": "https://avatar-management--avatars.us-west-2.prod.public.atl-paas.net/5ccaa3a43252b611c8ec161a/a91d4ab2-3208-44ae-a8c6-995c9fe978ad/32" 273 | }, 274 | "displayName": "Christian Schulze", 275 | "active": true, 276 | "timeZone": "Europe/Berlin", 277 | "accountType": "atlassian" 278 | }, 279 | "created": "2023-03-07T07:46:22.162+0100", 280 | "updated": "2023-03-07T07:46:22.162+0100", 281 | "jsdPublic": true 282 | } 283 | ], 284 | "self": "https://sma.atlassian.net/rest/api/3/issue/333004/comment", 285 | "maxResults": 1, 286 | "total": 1, 287 | "startAt": 0 288 | }, 289 | "statuscategorychangedate": "2023-03-13T13:20:17.805+0100", 290 | "fixVersions": [ 291 | { 292 | "self": "https://sma.atlassian.net/rest/api/3/version/17912", 293 | "id": "17912", 294 | "name": "Lankoon 1.5.1", 295 | "archived": false, 296 | "released": false 297 | } 298 | ], 299 | "customfield_10904": null, 300 | "priority": { 301 | "self": "https://sma.atlassian.net/rest/api/3/priority/1", 302 | "iconUrl": "https://sma.atlassian.net/images/icons/priorities/highest.svg", 303 | "name": "Highest", 304 | "id": "1" 305 | }, 306 | "versions": [ 307 | { 308 | "self": "https://sma.atlassian.net/rest/api/3/version/17908", 309 | "id": "17908", 310 | "name": "Lankoon 1.5", 311 | "archived": false, 312 | "released": true, 313 | "releaseDate": "2022-01-19" 314 | } 315 | ], 316 | "aggregateprogress": { 317 | "progress": 0, 318 | "total": 0 319 | }, 320 | "issuerestriction": { 321 | "issuerestrictions": {}, 322 | "shouldDisplay": false 323 | }, 324 | "created": "2023-02-28T11:56:36.725+0100", 325 | "security": null, 326 | "attachment": [ 327 | { 328 | "self": "https://sma.atlassian.net/rest/api/3/attachment/511224", 329 | "id": "511224", 330 | "filename": "jira-url.png", 331 | "author": { 332 | "self": "https://sma.atlassian.net/rest/api/3/user?accountId=5c88dfc843de836baaa6eeb9", 333 | "accountId": "5c88dfc843de836baaa6eeb9", 334 | "emailAddress": "melissa.weber@sma.de", 335 | "avatarUrls": { 336 | "48x48": "https://secure.gravatar.com/avatar/adfad45fe118030d8ac4e2b5c25179f2?d=https%3A%2F%2Favatar-management--avatars.us-west-2.prod.public.atl-paas.net%2Finitials%2FMW-4.png", 337 | "24x24": "https://secure.gravatar.com/avatar/adfad45fe118030d8ac4e2b5c25179f2?d=https%3A%2F%2Favatar-management--avatars.us-west-2.prod.public.atl-paas.net%2Finitials%2FMW-4.png", 338 | "16x16": "https://secure.gravatar.com/avatar/adfad45fe118030d8ac4e2b5c25179f2?d=https%3A%2F%2Favatar-management--avatars.us-west-2.prod.public.atl-paas.net%2Finitials%2FMW-4.png", 339 | "32x32": "https://secure.gravatar.com/avatar/adfad45fe118030d8ac4e2b5c25179f2?d=https%3A%2F%2Favatar-management--avatars.us-west-2.prod.public.atl-paas.net%2Finitials%2FMW-4.png" 340 | }, 341 | "displayName": "Melissa Weber", 342 | "active": true, 343 | "timeZone": "Europe/Berlin", 344 | "accountType": "atlassian" 345 | }, 346 | "created": "2023-02-28T12:29:49.734+0100", 347 | "size": 45777, 348 | "mimeType": "image/png", 349 | "content": "https://sma.atlassian.net/rest/api/3/attachment/content/511224", 350 | "thumbnail": "https://sma.atlassian.net/rest/api/3/attachment/thumbnail/511224" 351 | } 352 | ] 353 | } 354 | } -------------------------------------------------------------------------------- /JiraRestClient.Net/JiraRestClient.Net.Test/Examples/MyPermissions.json: -------------------------------------------------------------------------------- 1 | { 2 | "permissions": { 3 | "ARCHIVE_ISSUES": { 4 | "id": "-1", 5 | "key": "ARCHIVE_ISSUES", 6 | "name": "Vorgänge archivieren", 7 | "type": "PROJECT", 8 | "description": "Die Fähigkeit, Vorgänge für ein bestimmtes Projekt archivieren zu können.", 9 | "havePermission": false 10 | }, 11 | "VIEW_WORKFLOW_READONLY": { 12 | "id": "45", 13 | "key": "VIEW_WORKFLOW_READONLY", 14 | "name": "Schreibgeschützten Arbeitsablauf anzeigen", 15 | "type": "PROJECT", 16 | "description": "admin.permissions.descriptions.VIEW_WORKFLOW_READONLY", 17 | "havePermission": true, 18 | "deprecatedKey": true 19 | }, 20 | "CREATE_ISSUES": { 21 | "id": "11", 22 | "key": "CREATE_ISSUES", 23 | "name": "Vorgänge erstellen", 24 | "type": "PROJECT", 25 | "description": "Die Fähigkeit, Vorgänge erstellen zu können.", 26 | "havePermission": true 27 | }, 28 | "VIEW_DEV_TOOLS": { 29 | "id": "29", 30 | "key": "VIEW_DEV_TOOLS", 31 | "name": "Entwicklungstools anzeigen", 32 | "type": "PROJECT", 33 | "description": "Ermöglicht Benutzern die Anzeige entwicklungsbezogener Informationen in einem Softwareprojekt, darunter Übertragungen, Überprüfungen und Build-Informationen.", 34 | "havePermission": true 35 | }, 36 | "BULK_CHANGE": { 37 | "id": "33", 38 | "key": "BULK_CHANGE", 39 | "name": "Mehrfachändern", 40 | "type": "GLOBAL", 41 | "description": "Die Fähigkeit, mehrere Vorgänge gleichzeitig ändern zu können. Beispielsweise können so mehrere Vorgänge in einem Schritt gelöst werden.", 42 | "havePermission": true 43 | }, 44 | "CREATE_ATTACHMENT": { 45 | "id": "19", 46 | "key": "CREATE_ATTACHMENT", 47 | "name": "Anhänge erstellen", 48 | "type": "PROJECT", 49 | "description": "Benutzer mit dieser Berechtigung können Anhänge erstellen.", 50 | "havePermission": true, 51 | "deprecatedKey": true 52 | }, 53 | "DELETE_OWN_COMMENTS": { 54 | "id": "37", 55 | "key": "DELETE_OWN_COMMENTS", 56 | "name": "Eigene Kommentare löschen", 57 | "type": "PROJECT", 58 | "description": "Die Fähigkeit, eigene zu Vorgängen gemachte Kommentare löschen zu können.", 59 | "havePermission": true 60 | }, 61 | "WORK_ON_ISSUES": { 62 | "id": "20", 63 | "key": "WORK_ON_ISSUES", 64 | "name": "An Vorgängen arbeiten", 65 | "type": "PROJECT", 66 | "description": "Die Fähigkeit, Arbeiten an einem Vorgang protokollieren zu können. Dies ist nur dann nützlich, wenn die Zeitverfolgung eingeschaltet ist.", 67 | "havePermission": true 68 | }, 69 | "PROJECT_ADMIN": { 70 | "id": "23", 71 | "key": "PROJECT_ADMIN", 72 | "name": "Projekte verwalten", 73 | "type": "PROJECT", 74 | "description": "Die Fähigkeit, in Jira ein Projekt verwalten zu können.", 75 | "havePermission": true, 76 | "deprecatedKey": true 77 | }, 78 | "COMMENT_EDIT_ALL": { 79 | "id": "34", 80 | "key": "COMMENT_EDIT_ALL", 81 | "name": "Alle Kommentare bearbeiten", 82 | "type": "PROJECT", 83 | "description": "Die Fähigkeit, alle zu Vorgängen gemachten Kommentare bearbeiten zu können.", 84 | "havePermission": true, 85 | "deprecatedKey": true 86 | }, 87 | "ATTACHMENT_DELETE_OWN": { 88 | "id": "39", 89 | "key": "ATTACHMENT_DELETE_OWN", 90 | "name": "Eigene Anhänge löschen", 91 | "type": "PROJECT", 92 | "description": "Benutzer mit dieser Berechtigung können eigene Anhänge löschen.", 93 | "havePermission": true, 94 | "deprecatedKey": true 95 | }, 96 | "WORKLOG_DELETE_OWN": { 97 | "id": "42", 98 | "key": "WORKLOG_DELETE_OWN", 99 | "name": "Eigene Arbeitsprotokolle löschen", 100 | "type": "PROJECT", 101 | "description": "Die Fähigkeit, eigene zu Vorgängen gemachte Arbeitsprotokolle löschen zu können.", 102 | "havePermission": true, 103 | "deprecatedKey": true 104 | }, 105 | "CLOSE_ISSUE": { 106 | "id": "18", 107 | "key": "CLOSE_ISSUE", 108 | "name": "Vorgänge schließen", 109 | "type": "PROJECT", 110 | "description": "Die Fähigkeit, Vorgänge schließen zu können. Dies ist oftmals nützlich, wenn Ihre Entwickler Vorgänge lösen und eine QA-Abteilung sie schließt.", 111 | "havePermission": true, 112 | "deprecatedKey": true 113 | }, 114 | "MANAGE_WATCHER_LIST": { 115 | "id": "32", 116 | "key": "MANAGE_WATCHER_LIST", 117 | "name": "Beobachter verwalten", 118 | "type": "PROJECT", 119 | "description": "Die Fähigkeit, die Beobachter eines Vorgangs verwalten zu können.", 120 | "havePermission": true, 121 | "deprecatedKey": true 122 | }, 123 | "VIEW_VOTERS_AND_WATCHERS": { 124 | "id": "31", 125 | "key": "VIEW_VOTERS_AND_WATCHERS", 126 | "name": "Stimmabgaben und Beobachter anzeigen", 127 | "type": "PROJECT", 128 | "description": "Die Fähigkeit, die Wähler und Beobachter eines Vorgangs anzeigen zu können.", 129 | "havePermission": true 130 | }, 131 | "ADD_COMMENTS": { 132 | "id": "15", 133 | "key": "ADD_COMMENTS", 134 | "name": "Kommentare hinzufügen", 135 | "type": "PROJECT", 136 | "description": "Die Fähigkeit, Vorgänge kommentieren zu können.", 137 | "havePermission": true 138 | }, 139 | "COMMENT_DELETE_ALL": { 140 | "id": "36", 141 | "key": "COMMENT_DELETE_ALL", 142 | "name": "Alle Kommentare löschen", 143 | "type": "PROJECT", 144 | "description": "Die Fähigkeit, alle zu Vorgängen gemachten Kommentare löschen zu können.", 145 | "havePermission": true, 146 | "deprecatedKey": true 147 | }, 148 | "CREATE_ISSUE": { 149 | "id": "11", 150 | "key": "CREATE_ISSUE", 151 | "name": "Vorgänge erstellen", 152 | "type": "PROJECT", 153 | "description": "Die Fähigkeit, Vorgänge erstellen zu können.", 154 | "havePermission": true, 155 | "deprecatedKey": true 156 | }, 157 | "DELETE_OWN_ATTACHMENTS": { 158 | "id": "39", 159 | "key": "DELETE_OWN_ATTACHMENTS", 160 | "name": "Eigene Anhänge löschen", 161 | "type": "PROJECT", 162 | "description": "Benutzer mit dieser Berechtigung können eigene Anhänge löschen.", 163 | "havePermission": true 164 | }, 165 | "DELETE_ALL_ATTACHMENTS": { 166 | "id": "38", 167 | "key": "DELETE_ALL_ATTACHMENTS", 168 | "name": "Alle Anhänge löschen", 169 | "type": "PROJECT", 170 | "description": "Benutzer mit dieser Berechtigung können alle Anhänge löschen.", 171 | "havePermission": true 172 | }, 173 | "ASSIGN_ISSUE": { 174 | "id": "13", 175 | "key": "ASSIGN_ISSUE", 176 | "name": "Vorgänge zuweisen", 177 | "type": "PROJECT", 178 | "description": "Die Fähigkeit, Vorgänge anderen Personen zuweisen zu können.", 179 | "havePermission": true, 180 | "deprecatedKey": true 181 | }, 182 | "LINK_ISSUE": { 183 | "id": "21", 184 | "key": "LINK_ISSUE", 185 | "name": "Vorgänge verknüpfen", 186 | "type": "PROJECT", 187 | "description": "Die Fähigkeit, Vorgänge verknüpfen und verknüpfte Vorgänge erstellen zu können. Dies ist nur dann nützlich, wenn das Verknüpfen von Vorgängen eingeschaltet ist.", 188 | "havePermission": true, 189 | "deprecatedKey": true 190 | }, 191 | "EDIT_OWN_WORKLOGS": { 192 | "id": "40", 193 | "key": "EDIT_OWN_WORKLOGS", 194 | "name": "Eigene Arbeitsprotokolle bearbeiten", 195 | "type": "PROJECT", 196 | "description": "Die Fähigkeit, eigene zu Vorgängen gemachte Arbeitsprotokolle bearbeiten zu können.", 197 | "havePermission": true 198 | }, 199 | "CREATE_ATTACHMENTS": { 200 | "id": "19", 201 | "key": "CREATE_ATTACHMENTS", 202 | "name": "Anhänge erstellen", 203 | "type": "PROJECT", 204 | "description": "Benutzer mit dieser Berechtigung können Anhänge erstellen.", 205 | "havePermission": true 206 | }, 207 | "EDIT_ALL_WORKLOGS": { 208 | "id": "41", 209 | "key": "EDIT_ALL_WORKLOGS", 210 | "name": "Alle Arbeitsprotokolle bearbeiten", 211 | "type": "PROJECT", 212 | "description": "Die Fähigkeit, alle zu Vorgängen gemachten Arbeitsprotokolle bearbeiten zu können.", 213 | "havePermission": true 214 | }, 215 | "SCHEDULE_ISSUE": { 216 | "id": "28", 217 | "key": "SCHEDULE_ISSUE", 218 | "name": "Vorgänge planen", 219 | "type": "PROJECT", 220 | "description": "Die Fähigkeit, das Fälligkeitsdatum eines Vorgangs anzeigen oder bearbeiten zu können.", 221 | "havePermission": true, 222 | "deprecatedKey": true 223 | }, 224 | "CLOSE_ISSUES": { 225 | "id": "18", 226 | "key": "CLOSE_ISSUES", 227 | "name": "Vorgänge schließen", 228 | "type": "PROJECT", 229 | "description": "Die Fähigkeit, Vorgänge schließen zu können. Dies ist oftmals nützlich, wenn Ihre Entwickler Vorgänge lösen und eine QA-Abteilung sie schließt.", 230 | "havePermission": true 231 | }, 232 | "SET_ISSUE_SECURITY": { 233 | "id": "26", 234 | "key": "SET_ISSUE_SECURITY", 235 | "name": "Vorgangssicherheit festlegen", 236 | "type": "PROJECT", 237 | "description": "Die Fähigkeit, die Sicherheitsstufe für einen Vorgang festlegen zu können, sodass nur Personen dieser Sicherheitsstufe den Vorgang anzeigen können.", 238 | "havePermission": false 239 | }, 240 | "SCHEDULE_ISSUES": { 241 | "id": "28", 242 | "key": "SCHEDULE_ISSUES", 243 | "name": "Vorgänge planen", 244 | "type": "PROJECT", 245 | "description": "Die Fähigkeit, das Fälligkeitsdatum eines Vorgangs anzeigen oder bearbeiten zu können.", 246 | "havePermission": true 247 | }, 248 | "WORKLOG_DELETE_ALL": { 249 | "id": "43", 250 | "key": "WORKLOG_DELETE_ALL", 251 | "name": "Alle Arbeitsprotokolle löschen", 252 | "type": "PROJECT", 253 | "description": "Die Fähigkeit, alle zu Vorgängen gemachten Arbeitsprotokolle löschen zu können.", 254 | "havePermission": true, 255 | "deprecatedKey": true 256 | }, 257 | "COMMENT_DELETE_OWN": { 258 | "id": "37", 259 | "key": "COMMENT_DELETE_OWN", 260 | "name": "Eigene Kommentare löschen", 261 | "type": "PROJECT", 262 | "description": "Die Fähigkeit, eigene zu Vorgängen gemachte Kommentare löschen zu können.", 263 | "havePermission": true, 264 | "deprecatedKey": true 265 | }, 266 | "ADMINISTER_PROJECTS": { 267 | "id": "23", 268 | "key": "ADMINISTER_PROJECTS", 269 | "name": "Projekte verwalten", 270 | "type": "PROJECT", 271 | "description": "Die Fähigkeit, in Jira ein Projekt verwalten zu können.", 272 | "havePermission": true 273 | }, 274 | "DELETE_ALL_COMMENTS": { 275 | "id": "36", 276 | "key": "DELETE_ALL_COMMENTS", 277 | "name": "Alle Kommentare löschen", 278 | "type": "PROJECT", 279 | "description": "Die Fähigkeit, alle zu Vorgängen gemachten Kommentare löschen zu können.", 280 | "havePermission": true 281 | }, 282 | "RESOLVE_ISSUES": { 283 | "id": "14", 284 | "key": "RESOLVE_ISSUES", 285 | "name": "Vorgänge lösen", 286 | "type": "PROJECT", 287 | "description": "Die Fähigkeit, Vorgänge lösen und erneut öffnen zu können. Dies umfasst auch die Fähigkeit, eine Lösungsversion festzulegen.", 288 | "havePermission": true 289 | }, 290 | "VIEW_READONLY_WORKFLOW": { 291 | "id": "45", 292 | "key": "VIEW_READONLY_WORKFLOW", 293 | "name": "Schreibgeschützten Arbeitsablauf anzeigen", 294 | "type": "PROJECT", 295 | "description": "Die Fähigkeit, die Nur-Lese-Version eines Arbeitsablaufs einsehen zu können.\n", 296 | "havePermission": true 297 | }, 298 | "ADMINISTER": { 299 | "id": "0", 300 | "key": "ADMINISTER", 301 | "name": "Jira-Administratoren", 302 | "type": "GLOBAL", 303 | "description": "Die Fähigkeit, die meisten Administrationsfunktionen auszuführen (außer Import & Export, SMTP-Konfiguration usw.).", 304 | "havePermission": true 305 | }, 306 | "GLOBAL_BROWSE_ARCHIVE": { 307 | "id": "-1", 308 | "key": "GLOBAL_BROWSE_ARCHIVE", 309 | "name": "Archiv durchsuchen", 310 | "type": "GLOBAL", 311 | "description": "Die Fähigkeit, alle archivierten Vorgänge durchsuchen zu können.", 312 | "havePermission": false 313 | }, 314 | "MOVE_ISSUES": { 315 | "id": "25", 316 | "key": "MOVE_ISSUES", 317 | "name": "Vorgänge verschieben", 318 | "type": "PROJECT", 319 | "description": "Die Fähigkeit, Vorgänge zwischen Projekten oder zwischen Arbeitsabläufen desselben Projekts (wenn zutreffend) zu verschieben. Beachten Sie, dass ein Benutzer Vorgänge nur in ein Projekt verschieben kann, für das er über die Berechtigung zum Erstellen verfügt.", 320 | "havePermission": true 321 | }, 322 | "TRANSITION_ISSUES": { 323 | "id": "46", 324 | "key": "TRANSITION_ISSUES", 325 | "name": "Arbeitsablauf-Aktionen", 326 | "type": "PROJECT", 327 | "description": "Fähigkeit, den Status eines Vorgangs im Arbeitsablauf zu ändern.", 328 | "havePermission": true 329 | }, 330 | "SYSTEM_ADMIN": { 331 | "id": "44", 332 | "key": "SYSTEM_ADMIN", 333 | "name": "Jira-Systemadministratoren", 334 | "type": "GLOBAL", 335 | "description": "Die Fähigkeit, alle Administrationsfunktionen auszuführen. Es muss mindestens eine Gruppe mit dieser Berechtigung vorhanden sein.", 336 | "havePermission": true 337 | }, 338 | "DELETE_OWN_WORKLOGS": { 339 | "id": "42", 340 | "key": "DELETE_OWN_WORKLOGS", 341 | "name": "Eigene Arbeitsprotokolle löschen", 342 | "type": "PROJECT", 343 | "description": "Die Fähigkeit, eigene zu Vorgängen gemachte Arbeitsprotokolle löschen zu können.", 344 | "havePermission": true 345 | }, 346 | "BROWSE": { 347 | "id": "10", 348 | "key": "BROWSE", 349 | "name": "Projekte durchsuchen", 350 | "type": "PROJECT", 351 | "description": "Die Fähigkeit, Projekte und die darin enthaltenen Vorgänge durchsuchen zu können.", 352 | "havePermission": true, 353 | "deprecatedKey": true 354 | }, 355 | "EDIT_ISSUE": { 356 | "id": "12", 357 | "key": "EDIT_ISSUE", 358 | "name": "Vorgänge bearbeiten", 359 | "type": "PROJECT", 360 | "description": "Die Fähigkeit, Vorgänge bearbeiten zu können.", 361 | "havePermission": true, 362 | "deprecatedKey": true 363 | }, 364 | "MODIFY_REPORTER": { 365 | "id": "30", 366 | "key": "MODIFY_REPORTER", 367 | "name": "Autor ändern", 368 | "type": "PROJECT", 369 | "description": "Die Fähigkeit, den Autor beim Erstellen oder Bearbeiten eines Vorgangs ändern zu können.", 370 | "havePermission": true 371 | }, 372 | "EDIT_ISSUES": { 373 | "id": "12", 374 | "key": "EDIT_ISSUES", 375 | "name": "Vorgänge bearbeiten", 376 | "type": "PROJECT", 377 | "description": "Die Fähigkeit, Vorgänge bearbeiten zu können.", 378 | "havePermission": true 379 | }, 380 | "MANAGE_WATCHERS": { 381 | "id": "32", 382 | "key": "MANAGE_WATCHERS", 383 | "name": "Beobachter verwalten", 384 | "type": "PROJECT", 385 | "description": "Die Fähigkeit, die Beobachter eines Vorgangs verwalten zu können.", 386 | "havePermission": true 387 | }, 388 | "EDIT_OWN_COMMENTS": { 389 | "id": "35", 390 | "key": "EDIT_OWN_COMMENTS", 391 | "name": "Eigene Kommentare bearbeiten", 392 | "type": "PROJECT", 393 | "description": "Die Fähigkeit, eigene zu Vorgängen gemachte Kommentare bearbeiten zu können.", 394 | "havePermission": true 395 | }, 396 | "ASSIGN_ISSUES": { 397 | "id": "13", 398 | "key": "ASSIGN_ISSUES", 399 | "name": "Vorgänge zuweisen", 400 | "type": "PROJECT", 401 | "description": "Die Fähigkeit, Vorgänge anderen Personen zuweisen zu können.", 402 | "havePermission": true 403 | }, 404 | "BROWSE_PROJECTS": { 405 | "id": "10", 406 | "key": "BROWSE_PROJECTS", 407 | "name": "Projekte durchsuchen", 408 | "type": "PROJECT", 409 | "description": "Die Fähigkeit, Projekte und die darin enthaltenen Vorgänge durchsuchen zu können.", 410 | "havePermission": true 411 | }, 412 | "RESTORE_ISSUES": { 413 | "id": "-1", 414 | "key": "RESTORE_ISSUES", 415 | "name": "Vorgänge wiederherstellen", 416 | "type": "PROJECT", 417 | "description": "Die Fähigkeit, Vorgänge für ein bestimmtes Projekt wiederherstellen zu können.", 418 | "havePermission": false 419 | }, 420 | "BROWSE_ARCHIVE": { 421 | "id": "-1", 422 | "key": "BROWSE_ARCHIVE", 423 | "name": "Projektarchiv durchsuchen", 424 | "type": "PROJECT", 425 | "description": "Die Fähigkeit, archivierte Vorgänge eines bestimmten Projekts durchsuchen zu können.", 426 | "havePermission": false 427 | }, 428 | "VIEW_VERSION_CONTROL": { 429 | "id": "29", 430 | "key": "VIEW_VERSION_CONTROL", 431 | "name": "Entwicklungstools anzeigen", 432 | "type": "PROJECT", 433 | "description": "Ermöglicht Benutzern die Anzeige entwicklungsbezogener Informationen auf der Bildschirmmaske 'Vorgang anzeigen' (wie Übertragungen, Überprüfungen und Build-Informationen).", 434 | "havePermission": true, 435 | "deprecatedKey": true 436 | }, 437 | "WORK_ISSUE": { 438 | "id": "20", 439 | "key": "WORK_ISSUE", 440 | "name": "An Vorgängen arbeiten", 441 | "type": "PROJECT", 442 | "description": "Die Fähigkeit, Arbeiten an einem Vorgang protokollieren zu können. Dies ist nur dann nützlich, wenn die Zeitverfolgung eingeschaltet ist.", 443 | "havePermission": true, 444 | "deprecatedKey": true 445 | }, 446 | "COMMENT_ISSUE": { 447 | "id": "15", 448 | "key": "COMMENT_ISSUE", 449 | "name": "Kommentare hinzufügen", 450 | "type": "PROJECT", 451 | "description": "Die Fähigkeit, Vorgänge kommentieren zu können.", 452 | "havePermission": true, 453 | "deprecatedKey": true 454 | }, 455 | "WORKLOG_EDIT_ALL": { 456 | "id": "41", 457 | "key": "WORKLOG_EDIT_ALL", 458 | "name": "Alle Arbeitsprotokolle bearbeiten", 459 | "type": "PROJECT", 460 | "description": "Die Fähigkeit, alle zu Vorgängen gemachten Arbeitsprotokolle bearbeiten zu können.", 461 | "havePermission": true, 462 | "deprecatedKey": true 463 | }, 464 | "EDIT_ALL_COMMENTS": { 465 | "id": "34", 466 | "key": "EDIT_ALL_COMMENTS", 467 | "name": "Alle Kommentare bearbeiten", 468 | "type": "PROJECT", 469 | "description": "Die Fähigkeit, alle zu Vorgängen gemachten Kommentare bearbeiten zu können.", 470 | "havePermission": true 471 | }, 472 | "DELETE_ISSUE": { 473 | "id": "16", 474 | "key": "DELETE_ISSUE", 475 | "name": "Vorgänge löschen", 476 | "type": "PROJECT", 477 | "description": "Die Fähigkeit, Vorgänge zu löschen.", 478 | "havePermission": true, 479 | "deprecatedKey": true 480 | }, 481 | "MANAGE_SPRINTS_PERMISSION": { 482 | "id": "-1", 483 | "key": "MANAGE_SPRINTS_PERMISSION", 484 | "name": "Sprints verwalten", 485 | "type": "PROJECT", 486 | "description": "Möglichkeit zum Verwalten von Sprints.", 487 | "havePermission": true 488 | }, 489 | "USER_PICKER": { 490 | "id": "27", 491 | "key": "USER_PICKER", 492 | "name": "Benutzer durchsuchen", 493 | "type": "GLOBAL", 494 | "description": "Die Möglichkeit, Benutzer oder Gruppen von einem Popup Fenster auszuwählen. Darüber hinaus kann die \"Teilen\" Funktion genutzt werden. Benutzer mit dieser Berechtigung können die Namen aller Benutzer und Gruppen auf diesem System einsehen.", 495 | "havePermission": true 496 | }, 497 | "CREATE_SHARED_OBJECTS": { 498 | "id": "22", 499 | "key": "CREATE_SHARED_OBJECTS", 500 | "name": "Freigegebene Objekte erstellen", 501 | "type": "GLOBAL", 502 | "description": "Die Fähigkeit, Dashboards und Filter für andere Benutzer, Gruppen und Rollen freizugeben.", 503 | "havePermission": true 504 | }, 505 | "ATTACHMENT_DELETE_ALL": { 506 | "id": "38", 507 | "key": "ATTACHMENT_DELETE_ALL", 508 | "name": "Alle Anhänge löschen", 509 | "type": "PROJECT", 510 | "description": "Benutzer mit dieser Berechtigung können alle Anhänge löschen.", 511 | "havePermission": true, 512 | "deprecatedKey": true 513 | }, 514 | "DELETE_ISSUES": { 515 | "id": "16", 516 | "key": "DELETE_ISSUES", 517 | "name": "Vorgänge löschen", 518 | "type": "PROJECT", 519 | "description": "Die Fähigkeit, Vorgänge zu löschen.", 520 | "havePermission": true 521 | }, 522 | "MANAGE_GROUP_FILTER_SUBSCRIPTIONS": { 523 | "id": "24", 524 | "key": "MANAGE_GROUP_FILTER_SUBSCRIPTIONS", 525 | "name": "Gruppenfilterabonnement verwalten", 526 | "type": "GLOBAL", 527 | "description": "Die Fähigkeit, Gruppenfilterabonnements verwalten (erstellen und löschen) zu können.", 528 | "havePermission": true 529 | }, 530 | "RESOLVE_ISSUE": { 531 | "id": "14", 532 | "key": "RESOLVE_ISSUE", 533 | "name": "Vorgänge lösen", 534 | "type": "PROJECT", 535 | "description": "Die Fähigkeit, Vorgänge lösen und erneut öffnen zu können. Dies umfasst auch die Fähigkeit, eine Lösungsversion festzulegen.", 536 | "havePermission": true, 537 | "deprecatedKey": true 538 | }, 539 | "ASSIGNABLE_USER": { 540 | "id": "17", 541 | "key": "ASSIGNABLE_USER", 542 | "name": "Zuweisbarer Benutzer", 543 | "type": "PROJECT", 544 | "description": "Benutzer mit dieser Berechtigung können Vorgängen zugewiesen werden.", 545 | "havePermission": true 546 | }, 547 | "TRANSITION_ISSUE": { 548 | "id": "46", 549 | "key": "TRANSITION_ISSUE", 550 | "name": "Arbeitsablauf-Aktionen", 551 | "type": "PROJECT", 552 | "description": "Fähigkeit, den Status eines Vorgangs im Arbeitsablauf zu ändern.", 553 | "havePermission": true, 554 | "deprecatedKey": true 555 | }, 556 | "COMMENT_EDIT_OWN": { 557 | "id": "35", 558 | "key": "COMMENT_EDIT_OWN", 559 | "name": "Eigene Kommentare bearbeiten", 560 | "type": "PROJECT", 561 | "description": "Die Fähigkeit, eigene zu Vorgängen gemachte Kommentare bearbeiten zu können.", 562 | "havePermission": true, 563 | "deprecatedKey": true 564 | }, 565 | "MOVE_ISSUE": { 566 | "id": "25", 567 | "key": "MOVE_ISSUE", 568 | "name": "Vorgänge verschieben", 569 | "type": "PROJECT", 570 | "description": "Die Fähigkeit, Vorgänge zwischen Projekten oder zwischen Arbeitsabläufen desselben Projekts (wenn zutreffend) zu verschieben. Beachten Sie, dass ein Benutzer Vorgänge nur in ein Projekt verschieben kann, für das er über die Berechtigung zum Erstellen verfügt.", 571 | "havePermission": true, 572 | "deprecatedKey": true 573 | }, 574 | "WORKLOG_EDIT_OWN": { 575 | "id": "40", 576 | "key": "WORKLOG_EDIT_OWN", 577 | "name": "Eigene Arbeitsprotokolle bearbeiten", 578 | "type": "PROJECT", 579 | "description": "Die Fähigkeit, eigene zu Vorgängen gemachte Arbeitsprotokolle bearbeiten zu können.", 580 | "havePermission": true, 581 | "deprecatedKey": true 582 | }, 583 | "DELETE_ALL_WORKLOGS": { 584 | "id": "43", 585 | "key": "DELETE_ALL_WORKLOGS", 586 | "name": "Alle Arbeitsprotokolle löschen", 587 | "type": "PROJECT", 588 | "description": "Die Fähigkeit, alle zu Vorgängen gemachten Arbeitsprotokolle löschen zu können.", 589 | "havePermission": true 590 | }, 591 | "LINK_ISSUES": { 592 | "id": "21", 593 | "key": "LINK_ISSUES", 594 | "name": "Vorgänge verknüpfen", 595 | "type": "PROJECT", 596 | "description": "Die Fähigkeit, Vorgänge verknüpfen und verknüpfte Vorgänge erstellen zu können. Dies ist nur dann nützlich, wenn das Verknüpfen von Vorgängen eingeschaltet ist.", 597 | "havePermission": true 598 | } 599 | } 600 | } --------------------------------------------------------------------------------