99
1010namespace Certes
1111{
12+ /// <summary>
13+ /// Represents a ACME client.
14+ /// </summary>
1215 public class AcmeClient : IDisposable
1316 {
1417 private readonly AcmeHttpHandler handler ;
1518 private IAccountKey key ;
1619
20+ /// <summary>
21+ /// Initializes a new instance of the <see cref="AcmeClient"/> class.
22+ /// </summary>
23+ /// <param name="serverUri">The ACME server URI.</param>
1724 public AcmeClient ( Uri serverUri )
1825 : this ( new AcmeHttpHandler ( serverUri ) )
1926 {
2027 }
2128
29+ /// <summary>
30+ /// Initializes a new instance of the <see cref="AcmeClient"/> class.
31+ /// </summary>
32+ /// <param name="handler">The ACME handler.</param>
2233 public AcmeClient ( AcmeHttpHandler handler )
2334 {
2435 this . handler = handler ;
2536 }
2637
38+ /// <summary>
39+ /// Uses the specified account key data.
40+ /// </summary>
41+ /// <param name="keyData">The account key data.</param>
2742 public void Use ( KeyInfo keyData )
2843 {
2944 this . key = new AccountKey ( keyData ) ;
3045 }
3146
47+ /// <summary>
48+ /// Creates a new registraton.
49+ /// </summary>
50+ /// <param name="contact">The contact method, e.g. <c>mailto:admin@example.com</c>.</param>
51+ /// <returns>The ACME account created.</returns>
3252 public async Task < AcmeAccount > NewRegistraton ( params string [ ] contact )
3353 {
3454 if ( this . key == null )
@@ -44,10 +64,7 @@ public async Task<AcmeAccount> NewRegistraton(params string[] contact)
4464
4565 var uri = await this . handler . GetResourceUri ( registration . Resource ) ;
4666 var result = await this . handler . Post ( uri , registration , key ) ;
47- if ( result . Error != null )
48- {
49- throw new Exception ( $ "{ result . Error . Type } : { result . Error . Detail } ({ result . Error . Status } )") ;
50- }
67+ ThrowIfError ( result ) ;
5168
5269 var account = new AcmeAccount
5370 {
@@ -61,6 +78,12 @@ public async Task<AcmeAccount> NewRegistraton(params string[] contact)
6178 return account ;
6279 }
6380
81+ /// <summary>
82+ /// Updates the registration.
83+ /// </summary>
84+ /// <param name="account">The account to update.</param>
85+ /// <returns>The updated ACME account.</returns>
86+ /// <exception cref="InvalidOperationException">If the account key is missing.</exception>
6487 public async Task < AcmeAccount > UpdateRegistration ( AcmeAccount account )
6588 {
6689 if ( this . key == null )
@@ -71,15 +94,18 @@ public async Task<AcmeAccount> UpdateRegistration(AcmeAccount account)
7194 var registration = account . Data ;
7295
7396 var result = await this . handler . Post ( account . Location , registration , key ) ;
74- if ( result . Error != null )
75- {
76- throw new Exception ( $ "{ result . Error . Type } : { result . Error . Detail } ({ result . Error . Status } )") ;
77- }
97+ ThrowIfError ( result ) ;
7898
7999 account . Data = result . Data ;
80100 return account ;
81101 }
82102
103+ /// <summary>
104+ /// Create a new authorization.
105+ /// </summary>
106+ /// <param name="identifier">The identifier to be authorized.</param>
107+ /// <returns>The authorization created.</returns>
108+ /// <exception cref="InvalidOperationException">If the account key is missing.</exception>
83109 public async Task < AcmeResult < Authorization > > NewAuthorization ( AuthorizationIdentifier identifier )
84110 {
85111 if ( this . key == null )
@@ -95,18 +121,12 @@ public async Task<AcmeResult<Authorization>> NewAuthorization(AuthorizationIdent
95121
96122 var uri = await this . handler . GetResourceUri ( ResourceTypes . NewAuthorization ) ;
97123 var result = await this . handler . Post ( uri , auth , key ) ;
98- if ( result . Error != null )
99- {
100- throw new Exception ( $ "{ result . Error . Type } : { result . Error . Detail } ({ result . Error . Status } )") ;
101- }
124+ ThrowIfError ( result ) ;
102125
103126 if ( result . HttpStatus == HttpStatusCode . SeeOther ) // An authentication with the same identifier exists.
104127 {
105128 result = await this . handler . Get < Authorization > ( result . Location ) ;
106- if ( result . Error != null )
107- {
108- throw new Exception ( $ "{ result . Error . Type } : { result . Error . Detail } ({ result . Error . Status } )") ;
109- }
129+ ThrowIfError ( result ) ;
110130 }
111131
112132 return new AcmeResult < Authorization >
@@ -117,14 +137,16 @@ public async Task<AcmeResult<Authorization>> NewAuthorization(AuthorizationIdent
117137 ContentType = result . ContentType
118138 } ;
119139 }
120-
121- public async Task < AcmeResult < Authorization > > RefreshAuthorization ( Uri location )
140+
141+ /// <summary>
142+ /// Gets the authorization from <paramref name="location"/>.
143+ /// </summary>
144+ /// <param name="location">The authorization location URI.</param>
145+ /// <returns>The authorization retrieved.</returns>
146+ public async Task < AcmeResult < Authorization > > GetAuthorization ( Uri location )
122147 {
123148 var result = await this . handler . Get < Authorization > ( location ) ;
124- if ( result . Error != null )
125- {
126- throw new Exception ( $ "{ result . Error . Type } : { result . Error . Detail } ({ result . Error . Status } )") ;
127- }
149+ ThrowIfError ( result ) ;
128150
129151 return new AcmeResult < Authorization >
130152 {
@@ -134,7 +156,12 @@ public async Task<AcmeResult<Authorization>> RefreshAuthorization(Uri location)
134156 ContentType = result . ContentType
135157 } ;
136158 }
137-
159+
160+ /// <summary>
161+ /// Computes the key authorization string for <paramref name="challenge"/>.
162+ /// </summary>
163+ /// <param name="challenge">The challenge.</param>
164+ /// <returns>The key authorization string.</returns>
138165 public string ComputeKeyAuthorization ( Challenge challenge )
139166 {
140167 var jwkThumbprint = this . key . GenerateThumbprint ( ) ;
@@ -144,6 +171,12 @@ public string ComputeKeyAuthorization(Challenge challenge)
144171
145172 }
146173
174+ /// <summary>
175+ /// Submits the challenge for the ACME server to validate.
176+ /// </summary>
177+ /// <param name="authChallenge">The authentication challenge.</param>
178+ /// <returns>The challenge updated.</returns>
179+ /// <exception cref="InvalidOperationException">If the account key is missing.</exception>
147180 public async Task < AcmeResult < Challenge > > CompleteChallenge ( Challenge authChallenge )
148181 {
149182 if ( this . key == null )
@@ -158,10 +191,7 @@ public async Task<AcmeResult<Challenge>> CompleteChallenge(Challenge authChallen
158191 } ;
159192
160193 var result = await this . handler . Post ( authChallenge . Uri , challenge , key ) ;
161- if ( result . Error != null )
162- {
163- throw new Exception ( $ "{ result . Error . Type } : { result . Error . Detail } ({ result . Error . Status } )") ;
164- }
194+ ThrowIfError ( result ) ;
165195
166196 return new AcmeResult < Challenge >
167197 {
@@ -172,6 +202,11 @@ public async Task<AcmeResult<Challenge>> CompleteChallenge(Challenge authChallen
172202 } ;
173203 }
174204
205+ /// <summary>
206+ /// Creates a new certificate.
207+ /// </summary>
208+ /// <param name="csrProvider">The certificate signing request (CSR) provider.</param>
209+ /// <returns>The certificate issued.</returns>
175210 public async Task < AcmeCertificate > NewCertificate ( ICertificationRequestBuilder csrProvider )
176211 {
177212 var csrBytes = csrProvider . Generate ( ) ;
@@ -184,10 +219,7 @@ public async Task<AcmeCertificate> NewCertificate(ICertificationRequestBuilder c
184219
185220 var uri = await this . handler . GetResourceUri ( ResourceTypes . NewCertificate ) ;
186221 var result = await this . handler . Post ( uri , payload , key ) ;
187- if ( result . Error != null )
188- {
189- throw new Exception ( $ "{ result . Error . Type } : { result . Error . Detail } ({ result . Error . Status } )") ;
190- }
222+ ThrowIfError ( result ) ;
191223
192224 byte [ ] pem ;
193225 using ( var buffer = new MemoryStream ( ) )
@@ -231,6 +263,11 @@ public async Task<AcmeCertificate> NewCertificate(ICertificationRequestBuilder c
231263 return cert ;
232264 }
233265
266+ /// <summary>
267+ /// Revokes the certificate.
268+ /// </summary>
269+ /// <param name="certificate">The certificate.</param>
270+ /// <returns>The certificate revoked.</returns>
234271 public async Task < AcmeCertificate > RevokeCertificate ( AcmeCertificate certificate )
235272 {
236273 var payload = new RevokeCertificate
@@ -241,18 +278,38 @@ public async Task<AcmeCertificate> RevokeCertificate(AcmeCertificate certificate
241278
242279 var uri = await this . handler . GetResourceUri ( ResourceTypes . RevokeCertificate ) ;
243280 var result = await this . handler . Post ( uri , payload , key ) ;
244- if ( result . Error != null )
245- {
246- throw new Exception ( $ "{ result . Error . Type } : { result . Error . Detail } ({ result . Error . Status } )") ;
247- }
281+ ThrowIfError ( result ) ;
248282
249283 certificate . Revoked = true ;
250284 return certificate ;
251285 }
252286
287+ /// <summary>
288+ /// Gets the authorization from <paramref name="location"/>.
289+ /// </summary>
290+ /// <param name="location">The authorization location URI.</param>
291+ /// <returns>The authorization retrieved.</returns>
292+ [ Obsolete ( "Use GetAuthorization(Uri) instead." ) ]
293+ public Task < AcmeResult < Authorization > > RefreshAuthorization ( Uri location )
294+ {
295+ return GetAuthorization ( location ) ;
296+ }
297+
298+ private void ThrowIfError < T > ( AcmeRespone < T > response )
299+ {
300+ if ( response . Error != null )
301+ {
302+ throw new Exception ( $ "{ response . Error . Type } : { response . Error . Detail } ({ response . Error . Status } )") ;
303+ }
304+ }
305+
253306 #region IDisposable Support
254307 private bool disposedValue = false ;
255308
309+ /// <summary>
310+ /// Releases unmanaged and - optionally - managed resources.
311+ /// </summary>
312+ /// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
256313 protected virtual void Dispose ( bool disposing )
257314 {
258315 if ( ! disposedValue )
@@ -266,7 +323,10 @@ protected virtual void Dispose(bool disposing)
266323 disposedValue = true ;
267324 }
268325 }
269-
326+
327+ /// <summary>
328+ /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
329+ /// </summary>
270330 public void Dispose ( )
271331 {
272332 Dispose ( true ) ;
0 commit comments