From 87c01d4d8ecb6839b5ae725f5523f28b07dd50b5 Mon Sep 17 00:00:00 2001 From: Adrian Godong Date: Wed, 27 Dec 2017 22:32:53 -0800 Subject: [PATCH 1/7] Added authentication using bearer token. --- Octokit/Authentication/AuthenticationType.cs | 6 ++++- Octokit/Authentication/Authenticator.cs | 3 ++- .../BearerTokenAuthenticator.cs | 23 +++++++++++++++++++ Octokit/Http/Credentials.cs | 16 ++++++++----- 4 files changed, 40 insertions(+), 8 deletions(-) create mode 100644 Octokit/Authentication/BearerTokenAuthenticator.cs diff --git a/Octokit/Authentication/AuthenticationType.cs b/Octokit/Authentication/AuthenticationType.cs index 96c2b4b0d8..4047c8141f 100644 --- a/Octokit/Authentication/AuthenticationType.cs +++ b/Octokit/Authentication/AuthenticationType.cs @@ -16,6 +16,10 @@ public enum AuthenticationType /// /// Delegated access to a third party /// - Oauth + Oauth, + /// + /// Credential for GitHub App using signed JWT + /// + Bearer } } diff --git a/Octokit/Authentication/Authenticator.cs b/Octokit/Authentication/Authenticator.cs index a9a0e856d8..fa07e7b551 100644 --- a/Octokit/Authentication/Authenticator.cs +++ b/Octokit/Authentication/Authenticator.cs @@ -10,7 +10,8 @@ class Authenticator { { AuthenticationType.Anonymous, new AnonymousAuthenticator() }, { AuthenticationType.Basic, new BasicAuthenticator() }, - { AuthenticationType.Oauth, new TokenAuthenticator() } + { AuthenticationType.Oauth, new TokenAuthenticator() }, + { AuthenticationType.Bearer, new BearerTokenAuthenticator() } }; public Authenticator(ICredentialStore credentialStore) diff --git a/Octokit/Authentication/BearerTokenAuthenticator.cs b/Octokit/Authentication/BearerTokenAuthenticator.cs new file mode 100644 index 0000000000..c8fe0953f6 --- /dev/null +++ b/Octokit/Authentication/BearerTokenAuthenticator.cs @@ -0,0 +1,23 @@ +using System; +using System.Globalization; + +namespace Octokit.Internal +{ + class BearerTokenAuthenticator: IAuthenticationHandler + { + public void Authenticate(IRequest request, Credentials credentials) + { + Ensure.ArgumentNotNull(request, "request"); + Ensure.ArgumentNotNull(credentials, "credentials"); + Ensure.ArgumentNotNull(credentials.Password, "credentials.Password"); + + if (credentials.Login != null) + { + throw new InvalidOperationException("The Login is not null for a token authentication request. You " + + "probably did something wrong."); + } + + request.Headers["Authorization"] = string.Format(CultureInfo.InvariantCulture, "Bearer {0}", credentials.Password); + } + } +} diff --git a/Octokit/Http/Credentials.cs b/Octokit/Http/Credentials.cs index f62efa6316..e4cd21b508 100644 --- a/Octokit/Http/Credentials.cs +++ b/Octokit/Http/Credentials.cs @@ -13,13 +13,8 @@ private Credentials() AuthenticationType = AuthenticationType.Anonymous; } - public Credentials(string token) + public Credentials(string token) : this(token, AuthenticationType.Oauth) { - Ensure.ArgumentNotNullOrEmptyString(token, "token"); - - Login = null; - Password = token; - AuthenticationType = AuthenticationType.Oauth; } public Credentials(string login, string password) @@ -32,6 +27,15 @@ public Credentials(string login, string password) AuthenticationType = AuthenticationType.Basic; } + public Credentials(string token, AuthenticationType authenticationType) + { + Ensure.ArgumentNotNullOrEmptyString(token, "token"); + + Login = null; + Password = token; + AuthenticationType = authenticationType; + } + public string Login { get; From 002b7bd72fc5c4661ae7c3dfa80a96c3f29fe2e2 Mon Sep 17 00:00:00 2001 From: Adrian Godong Date: Wed, 27 Dec 2017 23:07:43 -0800 Subject: [PATCH 2/7] Added Installation and AccessToken clients. --- Octokit/Clients/AccessTokensClient.cs | 18 ++++++++++++++++++ Octokit/Clients/IAccessTokensClient.cs | 9 +++++++++ Octokit/Clients/IInstallationsClient.cs | 7 +++++++ Octokit/Clients/InstallationsClient.cs | 12 ++++++++++++ Octokit/GitHubClient.cs | 4 ++++ Octokit/Helpers/ApiUrls.cs | 5 +++++ Octokit/IGitHubClient.cs | 2 ++ Octokit/Models/Response/AccessToken.cs | 10 ++++++++++ 8 files changed, 67 insertions(+) create mode 100644 Octokit/Clients/AccessTokensClient.cs create mode 100644 Octokit/Clients/IAccessTokensClient.cs create mode 100644 Octokit/Clients/IInstallationsClient.cs create mode 100644 Octokit/Clients/InstallationsClient.cs create mode 100644 Octokit/Models/Response/AccessToken.cs diff --git a/Octokit/Clients/AccessTokensClient.cs b/Octokit/Clients/AccessTokensClient.cs new file mode 100644 index 0000000000..098674e9ea --- /dev/null +++ b/Octokit/Clients/AccessTokensClient.cs @@ -0,0 +1,18 @@ +using System.Threading.Tasks; + +namespace Octokit +{ + class AccessTokensClient : ApiClient, IAccessTokensClient + { + private const string AcceptHeader = "application/vnd.github.machine-man-preview+json"; + + public AccessTokensClient(IApiConnection apiConnection) : base(apiConnection) + { + } + + public Task Create(int installationId) + { + return ApiConnection.Post(ApiUrls.AccessTokens(installationId), null, AcceptHeader); + } + } +} diff --git a/Octokit/Clients/IAccessTokensClient.cs b/Octokit/Clients/IAccessTokensClient.cs new file mode 100644 index 0000000000..46f18cb7aa --- /dev/null +++ b/Octokit/Clients/IAccessTokensClient.cs @@ -0,0 +1,9 @@ +using System.Threading.Tasks; + +namespace Octokit +{ + public interface IAccessTokensClient + { + Task Create(int installationId); + } +} diff --git a/Octokit/Clients/IInstallationsClient.cs b/Octokit/Clients/IInstallationsClient.cs new file mode 100644 index 0000000000..66253f8d1b --- /dev/null +++ b/Octokit/Clients/IInstallationsClient.cs @@ -0,0 +1,7 @@ +namespace Octokit +{ + public interface IInstallationsClient + { + IAccessTokensClient AccessTokens { get; } + } +} diff --git a/Octokit/Clients/InstallationsClient.cs b/Octokit/Clients/InstallationsClient.cs new file mode 100644 index 0000000000..d25da7664f --- /dev/null +++ b/Octokit/Clients/InstallationsClient.cs @@ -0,0 +1,12 @@ +namespace Octokit +{ + class InstallationsClient : ApiClient, IInstallationsClient + { + public InstallationsClient(IApiConnection apiConnection) : base(apiConnection) + { + AccessTokens = new AccessTokensClient(apiConnection); + } + + public IAccessTokensClient AccessTokens { get; private set; } + } +} diff --git a/Octokit/GitHubClient.cs b/Octokit/GitHubClient.cs index a630e91254..3623a7da97 100644 --- a/Octokit/GitHubClient.cs +++ b/Octokit/GitHubClient.cs @@ -87,6 +87,7 @@ public GitHubClient(IConnection connection) Enterprise = new EnterpriseClient(apiConnection); Gist = new GistsClient(apiConnection); Git = new GitDatabaseClient(apiConnection); + Installations = new InstallationsClient(apiConnection); Issue = new IssuesClient(apiConnection); Migration = new MigrationClient(apiConnection); Miscellaneous = new MiscellaneousClient(connection); @@ -171,6 +172,9 @@ public Uri BaseAddress /// public IActivitiesClient Activity { get; private set; } + public IInstallationsClient Installations { get; private set; } + + /// /// Access GitHub's Issue API. /// diff --git a/Octokit/Helpers/ApiUrls.cs b/Octokit/Helpers/ApiUrls.cs index 24120b3165..c7602e99c8 100644 --- a/Octokit/Helpers/ApiUrls.cs +++ b/Octokit/Helpers/ApiUrls.cs @@ -293,6 +293,11 @@ public static Uri NotificationSubscription(int id) return "notifications/threads/{0}/subscription".FormatUri(id); } + public static Uri AccessTokens(int installationId) + { + return "installations/{0}/access_tokens".FormatUri(installationId); + } + /// /// Returns the that returns all of the issues across all the authenticated user’s visible /// repositories including owned repositories, member repositories, and organization repositories: diff --git a/Octokit/IGitHubClient.cs b/Octokit/IGitHubClient.cs index 1a66aa446b..5d2b7f594e 100644 --- a/Octokit/IGitHubClient.cs +++ b/Octokit/IGitHubClient.cs @@ -38,6 +38,8 @@ public interface IGitHubClient : IApiInfoProvider /// IActivitiesClient Activity { get; } + IInstallationsClient Installations { get; } + /// /// Access GitHub's Issue API. /// diff --git a/Octokit/Models/Response/AccessToken.cs b/Octokit/Models/Response/AccessToken.cs new file mode 100644 index 0000000000..04d8c41605 --- /dev/null +++ b/Octokit/Models/Response/AccessToken.cs @@ -0,0 +1,10 @@ +using System; + +namespace Octokit +{ + public class AccessToken + { + public string Token { get; set; } + public DateTime ExpiresAt { get; set; } + } +} From 33d659edfe7a133d11f7ae65b7f4687c4a2567e0 Mon Sep 17 00:00:00 2001 From: Adrian Godong Date: Wed, 27 Dec 2017 23:43:39 -0800 Subject: [PATCH 3/7] Added new clients to Reactive project --- .../Clients/IObservableAccessTokensClient.cs | 9 +++++++ .../Clients/IObservableInstallationsClient.cs | 7 ++++++ .../Clients/ObservableAccessTokensClient.cs | 24 +++++++++++++++++++ .../Clients/ObservableInstallationsClient.cs | 19 +++++++++++++++ Octokit.Reactive/IObservableGitHubClient.cs | 1 + Octokit.Reactive/ObservableGitHubClient.cs | 2 ++ Octokit/Models/Response/AccessToken.cs | 23 ++++++++++++++++-- 7 files changed, 83 insertions(+), 2 deletions(-) create mode 100644 Octokit.Reactive/Clients/IObservableAccessTokensClient.cs create mode 100644 Octokit.Reactive/Clients/IObservableInstallationsClient.cs create mode 100644 Octokit.Reactive/Clients/ObservableAccessTokensClient.cs create mode 100644 Octokit.Reactive/Clients/ObservableInstallationsClient.cs diff --git a/Octokit.Reactive/Clients/IObservableAccessTokensClient.cs b/Octokit.Reactive/Clients/IObservableAccessTokensClient.cs new file mode 100644 index 0000000000..629e37378f --- /dev/null +++ b/Octokit.Reactive/Clients/IObservableAccessTokensClient.cs @@ -0,0 +1,9 @@ +using System; + +namespace Octokit.Reactive +{ + public interface IObservableAccessTokensClient + { + IObservable Create(int installationId); + } +} diff --git a/Octokit.Reactive/Clients/IObservableInstallationsClient.cs b/Octokit.Reactive/Clients/IObservableInstallationsClient.cs new file mode 100644 index 0000000000..7bffda2775 --- /dev/null +++ b/Octokit.Reactive/Clients/IObservableInstallationsClient.cs @@ -0,0 +1,7 @@ +namespace Octokit.Reactive +{ + public interface IObservableInstallationsClient + { + IObservableAccessTokensClient AccessTokens { get; } + } +} diff --git a/Octokit.Reactive/Clients/ObservableAccessTokensClient.cs b/Octokit.Reactive/Clients/ObservableAccessTokensClient.cs new file mode 100644 index 0000000000..56f38ac7e9 --- /dev/null +++ b/Octokit.Reactive/Clients/ObservableAccessTokensClient.cs @@ -0,0 +1,24 @@ +using System; +using System.Reactive.Threading.Tasks; + +namespace Octokit.Reactive +{ + class ObservableAccessTokensClient : IObservableAccessTokensClient + { + readonly IAccessTokensClient _client; + readonly IConnection _connection; + + public ObservableAccessTokensClient(IGitHubClient client) + { + Ensure.ArgumentNotNull(client, "client"); + + _client = client.Installations.AccessTokens; + _connection = client.Connection; + } + + public IObservable Create(int installationId) + { + return _client.Create(installationId).ToObservable(); + } + } +} diff --git a/Octokit.Reactive/Clients/ObservableInstallationsClient.cs b/Octokit.Reactive/Clients/ObservableInstallationsClient.cs new file mode 100644 index 0000000000..c03d9fe6fa --- /dev/null +++ b/Octokit.Reactive/Clients/ObservableInstallationsClient.cs @@ -0,0 +1,19 @@ +namespace Octokit.Reactive +{ + class ObservableInstallationsClient : IObservableInstallationsClient + { + readonly IInstallationsClient _client; + readonly IConnection _connection; + + public ObservableInstallationsClient(IGitHubClient client) + { + Ensure.ArgumentNotNull(client, "client"); + + _client = client.Installations; + _connection = client.Connection; + AccessTokens = new ObservableAccessTokensClient(client); + } + + public IObservableAccessTokensClient AccessTokens { get; } + } +} diff --git a/Octokit.Reactive/IObservableGitHubClient.cs b/Octokit.Reactive/IObservableGitHubClient.cs index 9f1875224a..f6b712c00b 100644 --- a/Octokit.Reactive/IObservableGitHubClient.cs +++ b/Octokit.Reactive/IObservableGitHubClient.cs @@ -18,6 +18,7 @@ public interface IObservableGitHubClient : IApiInfoProvider IObservableAuthorizationsClient Authorization { get; } IObservableActivitiesClient Activity { get; } + IObservableInstallationsClient Installations { get; } IObservableIssuesClient Issue { get; } IObservableMiscellaneousClient Miscellaneous { get; } IObservableOauthClient Oauth { get; } diff --git a/Octokit.Reactive/ObservableGitHubClient.cs b/Octokit.Reactive/ObservableGitHubClient.cs index 11cba00e31..413ad71fdf 100644 --- a/Octokit.Reactive/ObservableGitHubClient.cs +++ b/Octokit.Reactive/ObservableGitHubClient.cs @@ -33,6 +33,7 @@ public ObservableGitHubClient(IGitHubClient gitHubClient) _gitHubClient = gitHubClient; Authorization = new ObservableAuthorizationsClient(gitHubClient); Activity = new ObservableActivitiesClient(gitHubClient); + Installations = new ObservableInstallationsClient(gitHubClient); Issue = new ObservableIssuesClient(gitHubClient); Miscellaneous = new ObservableMiscellaneousClient(gitHubClient); Oauth = new ObservableOauthClient(gitHubClient); @@ -69,6 +70,7 @@ public void SetRequestTimeout(TimeSpan timeout) public IObservableAuthorizationsClient Authorization { get; private set; } public IObservableActivitiesClient Activity { get; private set; } + public IObservableInstallationsClient Installations { get; private set; } public IObservableIssuesClient Issue { get; private set; } public IObservableMiscellaneousClient Miscellaneous { get; private set; } public IObservableOauthClient Oauth { get; private set; } diff --git a/Octokit/Models/Response/AccessToken.cs b/Octokit/Models/Response/AccessToken.cs index 04d8c41605..319eb3351c 100644 --- a/Octokit/Models/Response/AccessToken.cs +++ b/Octokit/Models/Response/AccessToken.cs @@ -1,10 +1,29 @@ using System; +using System.Diagnostics; +using System.Globalization; namespace Octokit { + [DebuggerDisplay("{DebuggerDisplay,nq}")] public class AccessToken { - public string Token { get; set; } - public DateTime ExpiresAt { get; set; } + public AccessToken() { } + + public AccessToken(string token, DateTime expiresAt) + { + Token = token; + ExpiresAt = expiresAt; + } + + public string Token { get; protected set; } + public DateTime ExpiresAt { get; protected set; } + + internal string DebuggerDisplay + { + get + { + return string.Format(CultureInfo.InvariantCulture, "Token: {0}, ExpiresAt: {1}", Token, ExpiresAt); + } + } } } From 9c27c0082369503ca9fcbf54f147e8c1080c9a82 Mon Sep 17 00:00:00 2001 From: Itai Bar-Haim Date: Mon, 1 Jan 2018 17:17:42 +0200 Subject: [PATCH 4/7] added support for DateTime serialized as FileTime --- Octokit/SimpleJson.cs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Octokit/SimpleJson.cs b/Octokit/SimpleJson.cs index 40dca76cd2..9efbf7e912 100644 --- a/Octokit/SimpleJson.cs +++ b/Octokit/SimpleJson.cs @@ -1429,6 +1429,14 @@ public virtual object DeserializeObject(object value, Type type) return value; if ((valueIsDouble && type != typeof(double)) || (valueIsLong && type != typeof(long))) { + if (valueIsLong && (type == typeof(DateTimeOffset) || type == typeof(DateTimeOffset?))) + { + return DateTimeOffset.FromFileTime((long)value); + } + else if (valueIsLong && (type == typeof(DateTime) || type == typeof(DateTime?))) + { + return DateTime.FromFileTime((long)value); + } obj = type == typeof(int) || type == typeof(long) || type == typeof(double) || type == typeof(float) || type == typeof(bool) || type == typeof(decimal) || type == typeof(byte) || type == typeof(short) ? Convert.ChangeType(value, type, CultureInfo.InvariantCulture) : value; From fc4e7b256b6c40ad449baacab3daa114ca883196 Mon Sep 17 00:00:00 2001 From: Itai Bar-Haim Date: Tue, 2 Jan 2018 14:59:03 +0200 Subject: [PATCH 5/7] added support for StatusEventPayload --- .../ActivityPayloads/StatusEventPayload.cs | 72 +++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 Octokit/Models/Response/ActivityPayloads/StatusEventPayload.cs diff --git a/Octokit/Models/Response/ActivityPayloads/StatusEventPayload.cs b/Octokit/Models/Response/ActivityPayloads/StatusEventPayload.cs new file mode 100644 index 0000000000..f3e39749b9 --- /dev/null +++ b/Octokit/Models/Response/ActivityPayloads/StatusEventPayload.cs @@ -0,0 +1,72 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; + +namespace Octokit +{ + [DebuggerDisplay("{DebuggerDisplay,nq}")] + public class StatusEventPayload : ActivityPayload + { + /// + /// The name of the repository. + /// + public string Name { get; protected set; } + + /// + /// The SHA of the reference. + /// + public string Sha { get; protected set; } + + /// + /// The date the commit status was created. + /// + public DateTimeOffset CreatedAt { get; protected set; } + + /// + /// The date the commit status was updated. + /// + public DateTimeOffset UpdatedAt { get; protected set; } + + /// + /// The state of the commit + /// + public StringEnum State { get; protected set; } + + /// + /// URL associated with this status. GitHub.com displays this URL as a link to allow users to easily see the + /// ‘source’ of the Status. + /// + public string TargetUrl { get; protected set; } + + /// + /// Short description of the status. + /// + public string Description { get; protected set; } + + /// + /// A string label to differentiate this status from the status of other systems. + /// + public string Context { get; protected set; } + + /// + /// The unique identifier of the status. + /// + public long Id { get; protected set; } + + /// + /// The relevant commit. + /// + public GitHubCommit Commit { get; protected set; } + + /// + /// The organization associated with the event. + /// + public Organization Organization { get; protected set; } + + /// + /// The branches involved. + /// + public IReadOnlyList Branches { get; protected set; } + + } +} From d60be44e953f0048abaa0ebf5a2760e6019dcbb4 Mon Sep 17 00:00:00 2001 From: Itai Bar-Haim Date: Thu, 4 Jan 2018 16:54:12 +0200 Subject: [PATCH 6/7] Added test for StatusEventPayload and fixed serializer to return that event payload type. --- Octokit.Tests/Clients/EventsClientTests.cs | 50 ++++++++++++++++++++++ Octokit/Http/SimpleJsonSerializer.cs | 2 + 2 files changed, 52 insertions(+) diff --git a/Octokit.Tests/Clients/EventsClientTests.cs b/Octokit.Tests/Clients/EventsClientTests.cs index 8be648f6f6..ccce328bbf 100644 --- a/Octokit.Tests/Clients/EventsClientTests.cs +++ b/Octokit.Tests/Clients/EventsClientTests.cs @@ -560,6 +560,7 @@ public async Task EnsuresNonNullArguments() {"PullRequestEvent", typeof(PullRequestEventPayload)}, {"PullRequestReviewCommentEvent", typeof(PullRequestCommentPayload)}, {"PushEvent", typeof(PushEventPayload)}, + {"StatusEvent", typeof(StatusEventPayload)}, {"WatchEvent", typeof(StarredEventPayload)}, {"unknown", typeof(ActivityPayload)} }; @@ -810,6 +811,55 @@ public async Task DeserializesPushEventCorrectly() Assert.Equal("message", payload.Commits.FirstOrDefault().Message); } + [Fact] + public async Task DeserializesStatusEventCorrectly() + { + var jsonObj = new JsonObject + { + { "type", "StatusEvent" }, + { + "payload", new + { + id = 214015194, + sha = "9049f1265b7d61be4a8904a9a27120d2064dab3b", + name = "baxterthehacker/public-repo", + target_url = "https://www.some_target_url.com", + context = "default", + description = "some human readable text", + state = "success", + branches = new [] + { + new + { + name = "master", + commit = new + { + sha = "9049f1265b7d61be4a8904a9a27120d2064dab3b", + url = "https://api.github.com/repos/baxterthehacker/public-repo/commits/9049f1265b7d61be4a8904a9a27120d2064dab3b" + } + } + }, + created_at = "2015-05-05T23:40:39Z" + } + } + }; + + var client = GetTestingEventsClient(jsonObj); + var activities = await client.GetAll(); + Assert.Equal(1, activities.Count); + + var payload = activities.FirstOrDefault().Payload as StatusEventPayload; + Assert.Equal(214015194, payload.Id); + Assert.Equal("9049f1265b7d61be4a8904a9a27120d2064dab3b", payload.Sha); + Assert.Equal("baxterthehacker/public-repo", payload.Name); + Assert.Equal("https://www.some_target_url.com", payload.TargetUrl); + Assert.Equal("default", payload.Context); + Assert.Equal("some human readable text", payload.Description); + Assert.Equal(CommitState.Success, payload.State.Value); + Assert.Equal(1, payload.Branches.Count); + Assert.Equal(new DateTimeOffset(2015, 05, 05, 23, 40, 39, TimeSpan.Zero), payload.CreatedAt); + } + [Fact] public async Task DeserializesStarredEventCorrectly() { diff --git a/Octokit/Http/SimpleJsonSerializer.cs b/Octokit/Http/SimpleJsonSerializer.cs index 429e9d4090..e450d66c1f 100644 --- a/Octokit/Http/SimpleJsonSerializer.cs +++ b/Octokit/Http/SimpleJsonSerializer.cs @@ -225,6 +225,8 @@ private static Type GetPayloadType(string activityType) return typeof(PullRequestCommentPayload); case "PushEvent": return typeof(PushEventPayload); + case "StatusEvent": + return typeof(StatusEventPayload); case "WatchEvent": return typeof(StarredEventPayload); } From 81e178a1168657ed5ce34795a33ff2ae2b6aa4f0 Mon Sep 17 00:00:00 2001 From: Itai Bar-Haim Date: Mon, 8 Jan 2018 17:06:38 +0200 Subject: [PATCH 7/7] WIP - added ApplicationClient and related Api Urls. --- Octokit/Clients/ApplicationClient.cs | 16 ++++++++++++++++ Octokit/Clients/IApplicationClient.cs | 9 +++++++++ Octokit/GitHubClient.cs | 9 +++++++++ Octokit/Helpers/AcceptHeaders.cs | 2 ++ Octokit/Helpers/ApiUrls.cs | 26 ++++++++++++++++++++++++++ 5 files changed, 62 insertions(+) create mode 100644 Octokit/Clients/ApplicationClient.cs create mode 100644 Octokit/Clients/IApplicationClient.cs diff --git a/Octokit/Clients/ApplicationClient.cs b/Octokit/Clients/ApplicationClient.cs new file mode 100644 index 0000000000..bb67c3e536 --- /dev/null +++ b/Octokit/Clients/ApplicationClient.cs @@ -0,0 +1,16 @@ +using System.Threading.Tasks; + +namespace Octokit +{ + public class ApplicationClient : ApiClient, IApplicationClient + { + public ApplicationClient(IApiConnection apiConnection) : base(apiConnection) + { + } + + public Task Create() + { + return ApiConnection.Get(ApiUrls.App(), null, AcceptHeaders.MachineManPreview); + } + } +} \ No newline at end of file diff --git a/Octokit/Clients/IApplicationClient.cs b/Octokit/Clients/IApplicationClient.cs new file mode 100644 index 0000000000..242bb0adb7 --- /dev/null +++ b/Octokit/Clients/IApplicationClient.cs @@ -0,0 +1,9 @@ +using System.Threading.Tasks; + +namespace Octokit +{ + public interface IApplicationClient + { + Task Create(); + } +} \ No newline at end of file diff --git a/Octokit/GitHubClient.cs b/Octokit/GitHubClient.cs index 3623a7da97..43edca7e2a 100644 --- a/Octokit/GitHubClient.cs +++ b/Octokit/GitHubClient.cs @@ -87,6 +87,7 @@ public GitHubClient(IConnection connection) Enterprise = new EnterpriseClient(apiConnection); Gist = new GistsClient(apiConnection); Git = new GitDatabaseClient(apiConnection); + Application = new ApplicationClient(apiConnection); Installations = new InstallationsClient(apiConnection); Issue = new IssuesClient(apiConnection); Migration = new MigrationClient(apiConnection); @@ -255,6 +256,14 @@ public Uri BaseAddress /// public IGitDatabaseClient Git { get; private set; } + /// + /// Access GitHub's Apps API. + /// + /// + /// Refer to the API documentation for more information: https://developer.github.com/v3/git/ + /// + public IApplicationClient Application { get; private set; } + /// /// Access GitHub's Search API. /// diff --git a/Octokit/Helpers/AcceptHeaders.cs b/Octokit/Helpers/AcceptHeaders.cs index afd058d779..d72ec9af8e 100644 --- a/Octokit/Helpers/AcceptHeaders.cs +++ b/Octokit/Helpers/AcceptHeaders.cs @@ -50,5 +50,7 @@ public static class AcceptHeaders public const string OrganizationMembershipPreview = "application/vnd.github.korra-preview+json"; public const string NestedTeamsPreview = "application/vnd.github.hellcat-preview+json"; + + public const string MachineManPreview = "application/vnd.github.machine-man-preview+json"; } } diff --git a/Octokit/Helpers/ApiUrls.cs b/Octokit/Helpers/ApiUrls.cs index c7602e99c8..a7e0da87e2 100644 --- a/Octokit/Helpers/ApiUrls.cs +++ b/Octokit/Helpers/ApiUrls.cs @@ -298,6 +298,32 @@ public static Uri AccessTokens(int installationId) return "installations/{0}/access_tokens".FormatUri(installationId); } + /// + /// Returns the that creates a github app. + /// + public static Uri App() + { + return "app".FormatUri(); + } + + /// + /// Returns the that returns all the installations of the authenticated application. + /// + /// + public static Uri Installations() + { + return "app/installations".FormatUri(); + } + + /// + /// Returns the that returns a single installation of the authenticated application. + /// + /// + public static Uri Installation(int installationId) + { + return "app/installations/{0}".FormatUri(installationId); + } + /// /// Returns the that returns all of the issues across all the authenticated user’s visible /// repositories including owned repositories, member repositories, and organization repositories: