Skip to content

Commit

Permalink
Code reflectoring.
Browse files Browse the repository at this point in the history
  • Loading branch information
fszlin committed Jul 6, 2016
1 parent c5f5eac commit 8a232e0
Show file tree
Hide file tree
Showing 4 changed files with 100 additions and 39 deletions.
2 changes: 1 addition & 1 deletion appveyor.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
version: 1.0.0.{build}
version: 1.0.1.{build}
build:
verbosity: minimal

Expand Down
2 changes: 1 addition & 1 deletion src/Certes.Cli/Processors/AuthorizationCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ private async Task RefreshAuthorization(AcmeContext context, string[] values)
var auth = authorizations?.TryGet(name);
if (auth != null)
{
auth = authorizations[name] = await client.RefreshAuthorization(auth.Location);
auth = authorizations[name] = await client.GetAuthorization(auth.Location);

var challenge = auth?
.Data?
Expand Down
132 changes: 96 additions & 36 deletions src/Certes/AcmeClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,26 +9,46 @@

namespace Certes
{
/// <summary>
/// Represents a ACME client.
/// </summary>
public class AcmeClient : IDisposable
{
private readonly AcmeHttpHandler handler;
private IAccountKey key;

/// <summary>
/// Initializes a new instance of the <see cref="AcmeClient"/> class.
/// </summary>
/// <param name="serverUri">The ACME server URI.</param>
public AcmeClient(Uri serverUri)
: this(new AcmeHttpHandler(serverUri))
{
}

/// <summary>
/// Initializes a new instance of the <see cref="AcmeClient"/> class.
/// </summary>
/// <param name="handler">The ACME handler.</param>
public AcmeClient(AcmeHttpHandler handler)
{
this.handler = handler;
}

/// <summary>
/// Uses the specified account key data.
/// </summary>
/// <param name="keyData">The account key data.</param>
public void Use(KeyInfo keyData)
{
this.key = new AccountKey(keyData);
}

/// <summary>
/// Creates a new registraton.
/// </summary>
/// <param name="contact">The contact method, e.g. <c>mailto:admin@example.com</c>.</param>
/// <returns>The ACME account created.</returns>
public async Task<AcmeAccount> NewRegistraton(params string[] contact)
{
if (this.key == null)
Expand All @@ -44,10 +64,7 @@ public async Task<AcmeAccount> NewRegistraton(params string[] contact)

var uri = await this.handler.GetResourceUri(registration.Resource);
var result = await this.handler.Post(uri, registration, key);
if (result.Error != null)
{
throw new Exception($"{ result.Error.Type}: {result.Error.Detail} ({result.Error.Status})");
}
ThrowIfError(result);

var account = new AcmeAccount
{
Expand All @@ -61,6 +78,12 @@ public async Task<AcmeAccount> NewRegistraton(params string[] contact)
return account;
}

/// <summary>
/// Updates the registration.
/// </summary>
/// <param name="account">The account to update.</param>
/// <returns>The updated ACME account.</returns>
/// <exception cref="InvalidOperationException">If the account key is missing.</exception>
public async Task<AcmeAccount> UpdateRegistration(AcmeAccount account)
{
if (this.key == null)
Expand All @@ -71,15 +94,18 @@ public async Task<AcmeAccount> UpdateRegistration(AcmeAccount account)
var registration = account.Data;

var result = await this.handler.Post(account.Location, registration, key);
if (result.Error != null)
{
throw new Exception($"{result.Error.Type}: {result.Error.Detail} ({result.Error.Status})");
}
ThrowIfError(result);

account.Data = result.Data;
return account;
}

/// <summary>
/// Create a new authorization.
/// </summary>
/// <param name="identifier">The identifier to be authorized.</param>
/// <returns>The authorization created.</returns>
/// <exception cref="InvalidOperationException">If the account key is missing.</exception>
public async Task<AcmeResult<Authorization>> NewAuthorization(AuthorizationIdentifier identifier)
{
if (this.key == null)
Expand All @@ -95,18 +121,12 @@ public async Task<AcmeResult<Authorization>> NewAuthorization(AuthorizationIdent

var uri = await this.handler.GetResourceUri(ResourceTypes.NewAuthorization);
var result = await this.handler.Post(uri, auth, key);
if (result.Error != null)
{
throw new Exception($"{result.Error.Type}: {result.Error.Detail} ({result.Error.Status})");
}
ThrowIfError(result);

if (result.HttpStatus == HttpStatusCode.SeeOther) // An authentication with the same identifier exists.
{
result = await this.handler.Get<Authorization>(result.Location);
if (result.Error != null)
{
throw new Exception($"{result.Error.Type}: {result.Error.Detail} ({result.Error.Status})");
}
ThrowIfError(result);
}

return new AcmeResult<Authorization>
Expand All @@ -117,14 +137,16 @@ public async Task<AcmeResult<Authorization>> NewAuthorization(AuthorizationIdent
ContentType = result.ContentType
};
}

public async Task<AcmeResult<Authorization>> RefreshAuthorization(Uri location)

/// <summary>
/// Gets the authorization from <paramref name="location"/>.
/// </summary>
/// <param name="location">The authorization location URI.</param>
/// <returns>The authorization retrieved.</returns>
public async Task<AcmeResult<Authorization>> GetAuthorization(Uri location)
{
var result = await this.handler.Get<Authorization>(location);
if (result.Error != null)
{
throw new Exception($"{ result.Error.Type}: {result.Error.Detail} ({result.Error.Status})");
}
ThrowIfError(result);

return new AcmeResult<Authorization>
{
Expand All @@ -134,7 +156,12 @@ public async Task<AcmeResult<Authorization>> RefreshAuthorization(Uri location)
ContentType = result.ContentType
};
}


/// <summary>
/// Computes the key authorization string for <paramref name="challenge"/>.
/// </summary>
/// <param name="challenge">The challenge.</param>
/// <returns>The key authorization string.</returns>
public string ComputeKeyAuthorization(Challenge challenge)
{
var jwkThumbprint = this.key.GenerateThumbprint();
Expand All @@ -144,6 +171,12 @@ public string ComputeKeyAuthorization(Challenge challenge)

}

/// <summary>
/// Submits the challenge for the ACME server to validate.
/// </summary>
/// <param name="authChallenge">The authentication challenge.</param>
/// <returns>The challenge updated.</returns>
/// <exception cref="InvalidOperationException">If the account key is missing.</exception>
public async Task<AcmeResult<Challenge>> CompleteChallenge(Challenge authChallenge)
{
if (this.key == null)
Expand All @@ -158,10 +191,7 @@ public async Task<AcmeResult<Challenge>> CompleteChallenge(Challenge authChallen
};

var result = await this.handler.Post(authChallenge.Uri, challenge, key);
if (result.Error != null)
{
throw new Exception($"{ result.Error.Type}: {result.Error.Detail} ({result.Error.Status})");
}
ThrowIfError(result);

return new AcmeResult<Challenge>
{
Expand All @@ -172,6 +202,11 @@ public async Task<AcmeResult<Challenge>> CompleteChallenge(Challenge authChallen
};
}

/// <summary>
/// Creates a new certificate.
/// </summary>
/// <param name="csrProvider">The certificate signing request (CSR) provider.</param>
/// <returns>The certificate issued.</returns>
public async Task<AcmeCertificate> NewCertificate(ICertificationRequestBuilder csrProvider)
{
var csrBytes = csrProvider.Generate();
Expand All @@ -184,10 +219,7 @@ public async Task<AcmeCertificate> NewCertificate(ICertificationRequestBuilder c

var uri = await this.handler.GetResourceUri(ResourceTypes.NewCertificate);
var result = await this.handler.Post(uri, payload, key);
if (result.Error != null)
{
throw new Exception($"{ result.Error.Type}: {result.Error.Detail} ({result.Error.Status})");
}
ThrowIfError(result);

byte[] pem;
using (var buffer = new MemoryStream())
Expand Down Expand Up @@ -231,6 +263,11 @@ public async Task<AcmeCertificate> NewCertificate(ICertificationRequestBuilder c
return cert;
}

/// <summary>
/// Revokes the certificate.
/// </summary>
/// <param name="certificate">The certificate.</param>
/// <returns>The certificate revoked.</returns>
public async Task<AcmeCertificate> RevokeCertificate(AcmeCertificate certificate)
{
var payload = new RevokeCertificate
Expand All @@ -241,18 +278,38 @@ public async Task<AcmeCertificate> RevokeCertificate(AcmeCertificate certificate

var uri = await this.handler.GetResourceUri(ResourceTypes.RevokeCertificate);
var result = await this.handler.Post(uri, payload, key);
if (result.Error != null)
{
throw new Exception($"{ result.Error.Type}: {result.Error.Detail} ({result.Error.Status})");
}
ThrowIfError(result);

certificate.Revoked = true;
return certificate;
}

/// <summary>
/// Gets the authorization from <paramref name="location"/>.
/// </summary>
/// <param name="location">The authorization location URI.</param>
/// <returns>The authorization retrieved.</returns>
[Obsolete("Use GetAuthorization(Uri) instead.")]
public Task<AcmeResult<Authorization>> RefreshAuthorization(Uri location)
{
return GetAuthorization(location);
}

private void ThrowIfError<T>(AcmeRespone<T> response)
{
if (response.Error != null)
{
throw new Exception($"{ response.Error.Type}: {response.Error.Detail} ({response.Error.Status})");
}
}

#region IDisposable Support
private bool disposedValue = false;

/// <summary>
/// Releases unmanaged and - optionally - managed resources.
/// </summary>
/// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
protected virtual void Dispose(bool disposing)
{
if (!disposedValue)
Expand All @@ -266,7 +323,10 @@ protected virtual void Dispose(bool disposing)
disposedValue = true;
}
}


/// <summary>
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
/// </summary>
public void Dispose()
{
Dispose(true);
Expand Down
3 changes: 2 additions & 1 deletion src/Certes/project.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@
]
},
"compilationOptions": {
"warningsAsErrors": true
"warningsAsErrors": true,
"xmlDoc": true
},
"packOptions": {
"projectUrl": "https://github.com/fszlin/certes",
Expand Down

0 comments on commit 8a232e0

Please sign in to comment.