diff --git a/Octokit/Clients/AuthorizationsClient.cs b/Octokit/Clients/AuthorizationsClient.cs index 0c0f1d2d..2eac60ca 100644 --- a/Octokit/Clients/AuthorizationsClient.cs +++ b/Octokit/Clients/AuthorizationsClient.cs @@ -1,4 +1,5 @@ -#if NET_45 +using System; +#if NET_45 using System.Collections.Generic; #endif using System.Threading.Tasks; @@ -86,7 +87,6 @@ namespace Octokit Ensure.ArgumentNotNullOrEmptyString(clientSecret, "clientSecret"); Ensure.ArgumentNotNull(newAuthorization, "authorization"); - var endpoint = ApiUrls.AuthorizationsForClient(clientId); var requestData = new { client_secret = clientSecret, @@ -95,7 +95,18 @@ namespace Octokit note_url = newAuthorization.NoteUrl }; - return ApiConnection.Put(endpoint, requestData); + if (String.IsNullOrWhiteSpace(newAuthorization.Fingerprint)) + { + // use classic API + var endpoint = ApiUrls.AuthorizationsForClient(clientId); + return ApiConnection.Put(endpoint, requestData); + } + else + { + // use new API + var endpoint = ApiUrls.AuthorizationsForClient(clientId, newAuthorization.Fingerprint); + return ApiConnection.Put(endpoint, requestData, null, previewAcceptsHeader); + } } /// @@ -129,7 +140,6 @@ namespace Octokit Ensure.ArgumentNotNull(newAuthorization, "authorization"); Ensure.ArgumentNotNullOrEmptyString(twoFactorAuthenticationCode, "twoFactorAuthenticationCode"); - var endpoint = ApiUrls.AuthorizationsForClient(clientId); var requestData = new { client_secret = clientSecret, @@ -140,10 +150,25 @@ namespace Octokit try { - return await ApiConnection.Put( - endpoint, - requestData, - twoFactorAuthenticationCode); + if (String.IsNullOrWhiteSpace(newAuthorization.Fingerprint)) + { + // use classic API + var endpoint = ApiUrls.AuthorizationsForClient(clientId); + return await ApiConnection.Put( + endpoint, + requestData, + twoFactorAuthenticationCode); + } + else + { + // use new API + var endpoint = ApiUrls.AuthorizationsForClient(clientId, newAuthorization.Fingerprint); + return await ApiConnection.Put( + endpoint, + requestData, + twoFactorAuthenticationCode, + previewAcceptsHeader); + } } catch (AuthorizationException e) { diff --git a/Octokit/Helpers/ApiUrls.Authorizations.cs b/Octokit/Helpers/ApiUrls.Authorizations.cs index fa441a03..63f97dab 100644 --- a/Octokit/Helpers/ApiUrls.Authorizations.cs +++ b/Octokit/Helpers/ApiUrls.Authorizations.cs @@ -26,10 +26,27 @@ namespace Octokit /// /// Returns the that returns all authorizations for a given client /// - /// The application client Id + /// + /// The 20 character OAuth app client key for which to create the token. + /// public static Uri AuthorizationsForClient(string clientId) { return "authorizations/clients/{0}".FormatUri(clientId); } + + /// + /// Returns the that authorizations for a given client and fingerprint + /// + /// + /// The 20 character OAuth app client key for + /// which to create the token. + /// + /// A unique string to distinguish an authorization from others created + /// for the same client and user. + /// + public static Uri AuthorizationsForClient(string clientId, string fingerprint) + { + return "authorizations/clients/{0}/{1}".FormatUri(clientId, fingerprint); + } } } diff --git a/Octokit/Http/ApiConnection.cs b/Octokit/Http/ApiConnection.cs index b608f424..26346518 100644 --- a/Octokit/Http/ApiConnection.cs +++ b/Octokit/Http/ApiConnection.cs @@ -250,6 +250,27 @@ namespace Octokit return response.BodyAsObject; } + /// + /// Creates or replaces the API resource at the specified URI. + /// + /// The API resource's type. + /// URI of the API resource to create or replace + /// Object that describes the API resource; this will be serialized and used as the request's body + /// The two-factor authentication code in response to the current user's previous challenge + /// Accept header to use for the API request + /// The created API resource. + /// Thrown when an API error occurs. + public async Task Put(Uri uri, object data, string twoFactorAuthenticationCode, string accepts) + { + Ensure.ArgumentNotNull(uri, "uri"); + Ensure.ArgumentNotNull(data, "data"); + + var response = await Connection.Put(uri, data, twoFactorAuthenticationCode).ConfigureAwait(false); + + return response.BodyAsObject; + } + + /// /// Updates the API resource at the specified URI. /// diff --git a/Octokit/Http/Connection.cs b/Octokit/Http/Connection.cs index a3689bee..d38e0c89 100644 --- a/Octokit/Http/Connection.cs +++ b/Octokit/Http/Connection.cs @@ -224,6 +224,17 @@ namespace Octokit twoFactorAuthenticationCode); } + public Task> Put(Uri uri, object body, string twoFactorAuthenticationCode, string accepts) + { + return SendData(uri, + HttpMethod.Put, + body, + accepts, + null, + CancellationToken.None, + twoFactorAuthenticationCode); + } + Task> SendData( Uri uri, HttpMethod method, diff --git a/Octokit/Http/IApiConnection.cs b/Octokit/Http/IApiConnection.cs index 8cd1f563..18416063 100644 --- a/Octokit/Http/IApiConnection.cs +++ b/Octokit/Http/IApiConnection.cs @@ -155,6 +155,19 @@ namespace Octokit /// Thrown when an API error occurs. Task Put(Uri uri, object data, string twoFactorAuthenticationCode); + /// + /// Creates or replaces the API resource at the specified URI. + /// + /// The API resource's type. + /// URI of the API resource to create or replace + /// Object that describes the API resource; this will be serialized and used as the request's body + /// The two-factor authentication code in response to the current user's previous challenge + /// Accept header to use for the API request + /// The created API resource. + /// Thrown when an API error occurs. + Task Put(Uri uri, object data, string twoFactorAuthenticationCode, string accepts); + + /// /// Updates the API resource at the specified URI. /// diff --git a/Octokit/Http/IConnection.cs b/Octokit/Http/IConnection.cs index 8eea35fb..eff26897 100644 --- a/Octokit/Http/IConnection.cs +++ b/Octokit/Http/IConnection.cs @@ -137,6 +137,19 @@ namespace Octokit /// representing the received HTTP response Task> Put(Uri uri, object body, string twoFactorAuthenticationCode); + /// + /// Performs an asynchronous HTTP PUT request using the provided two factor authentication code. + /// Attempts to map the response body to an object of type + /// + /// The type to map the response to + /// URI endpoint to send request to + /// The object to serialize as the body of the request + /// Two factory authentication code to use + /// Specifies accepted response media types. + /// representing the received HTTP response + Task> Put(Uri uri, object body, string twoFactorAuthenticationCode, string accepts); + + /// /// Performs an asynchronous HTTP PUT request that expects an empty response. ///