Skip to content
This repository was archived by the owner on Aug 30, 2025. It is now read-only.

Commit 07ac0ed

Browse files
committed
feat: Added UnauthorizedAccessException as default mapped to 401
1 parent 6b30adc commit 07ac0ed

3 files changed

Lines changed: 157 additions & 102 deletions

File tree

samples/PowerUtils.AspNetCore.ErrorHandler.Samples/Controllers/ExceptionsController.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@ public IActionResult Generic()
1818
public IActionResult NotFiniteNumberException()
1919
=> throw new NotImplementedException("NotImplementedException...");
2020

21+
[HttpGet("unauthorized-access-exception")]
22+
public IActionResult UnauthorizedAccessException()
23+
=> throw new UnauthorizedAccessException();
24+
2125
[HttpGet("aggregate-inner-not-implemented-exception")]
2226
public IActionResult AggregateExceptionInnerNotImplementedException()
2327
=> throw new AggregateException(new NotImplementedException("AggregateException..."));

src/ErrorHandlerOptions.cs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,21 +44,26 @@ public PropertyNamingPolicy PropertyNamingPolicy
4444

4545
public ErrorHandlerOptions()
4646
{
47+
ExceptionMappers.Add(
48+
typeof(UnauthorizedAccessException),
49+
new ExceptionMapper<UnauthorizedAccessException>()
50+
{
51+
Handler = (_) => (StatusCodes.Status401Unauthorized, new Dictionary<string, ErrorDetails>())
52+
});
53+
4754
ExceptionMappers.Add(
4855
typeof(NotImplementedException),
4956
new ExceptionMapper<NotImplementedException>()
5057
{
5158
Handler = (_) => (StatusCodes.Status501NotImplemented, new Dictionary<string, ErrorDetails>())
52-
}
53-
);
59+
});
5460

5561
ExceptionMappers.Add(
5662
typeof(TimeoutException),
5763
new ExceptionMapper<TimeoutException>()
5864
{
5965
Handler = (_) => (StatusCodes.Status504GatewayTimeout, new Dictionary<string, ErrorDetails>())
60-
}
61-
);
66+
});
6267

6368
PropertyHandler = Handlers.PropertyHandler.Create(_propertyNamingPolicy);
6469
}

tests/PowerUtils.AspNetCore.ErrorHandler.Tests/Tests/Controllers/ExceptionsControllerTests.cs

Lines changed: 144 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System.Collections.Generic;
22
using System.Net;
33
using FluentAssertions;
4+
using FluentAssertions.Execution;
45
using Microsoft.AspNetCore.Mvc;
56
using Microsoft.Extensions.Options;
67
using PowerUtils.AspNetCore.ErrorHandler.Tests.Config;
@@ -33,14 +34,16 @@ public async void EndpointWithGenericException_Request_500()
3334

3435

3536
// Assert
36-
response.ValidateResponse(HttpStatusCode.InternalServerError);
37-
38-
content.ValidateContent(
39-
HttpStatusCode.InternalServerError,
40-
clientErrorData,
41-
"GET: " + requestUri,
42-
"An unexpected error has occurred."
43-
);
37+
using(new AssertionScope())
38+
{
39+
response.ValidateResponse(HttpStatusCode.InternalServerError);
40+
41+
content.ValidateContent(
42+
HttpStatusCode.InternalServerError,
43+
clientErrorData,
44+
"GET: " + requestUri,
45+
"An unexpected error has occurred.");
46+
}
4447
}
4548

4649
[Fact]
@@ -57,14 +60,44 @@ public async void EndpointWithNotImplementedException_Request_501()
5760

5861

5962
// Assert
60-
response.ValidateResponse(HttpStatusCode.NotImplemented);
61-
62-
content.ValidateContent(
63-
HttpStatusCode.NotImplemented,
64-
clientErrorData,
65-
"GET: " + requestUri,
66-
"The feature has not been implemented."
67-
);
63+
64+
using(new AssertionScope())
65+
{
66+
response.ValidateResponse(HttpStatusCode.NotImplemented);
67+
68+
content.ValidateContent(
69+
HttpStatusCode.NotImplemented,
70+
clientErrorData,
71+
"GET: " + requestUri,
72+
"The feature has not been implemented.");
73+
}
74+
}
75+
76+
[Fact]
77+
public async void EndpointWithUnauthorizedAccessException_Request_401()
78+
{
79+
// Arrange
80+
var requestUri = "/exceptions/unauthorized-access-exception";
81+
var options = _testsFixture.GetService<IOptions<ApiBehaviorOptions>>();
82+
83+
84+
// Act
85+
(var response, var content) = await _testsFixture.Client.SendGetAsync(requestUri);
86+
options.Value.ClientErrorMapping.TryGetValue((int)response.StatusCode, out var clientErrorData);
87+
88+
89+
// Assert
90+
91+
using(new AssertionScope())
92+
{
93+
response.ValidateResponse(HttpStatusCode.Unauthorized);
94+
95+
content.ValidateContent(
96+
HttpStatusCode.Unauthorized,
97+
clientErrorData,
98+
"GET: " + requestUri,
99+
"A authentication error has occurred.");
100+
}
68101
}
69102

70103
[Fact]
@@ -81,14 +114,16 @@ public async void EndpointWithAggregateException_Request_501()
81114

82115

83116
// Assert
84-
response.ValidateResponse(HttpStatusCode.NotImplemented);
85-
86-
content.ValidateContent(
87-
HttpStatusCode.NotImplemented,
88-
clientErrorData,
89-
"GET: " + requestUri,
90-
"The feature has not been implemented."
91-
);
117+
using(new AssertionScope())
118+
{
119+
response.ValidateResponse(HttpStatusCode.NotImplemented);
120+
121+
content.ValidateContent(
122+
HttpStatusCode.NotImplemented,
123+
clientErrorData,
124+
"GET: " + requestUri,
125+
"The feature has not been implemented.");
126+
}
92127
}
93128

94129
[Fact]
@@ -105,14 +140,16 @@ public async void EndpointWithTwoAggregateException_Request_500()
105140

106141

107142
// Assert
108-
response.ValidateResponse(HttpStatusCode.InternalServerError);
109-
110-
content.ValidateContent(
111-
HttpStatusCode.InternalServerError,
112-
clientErrorData,
113-
"GET: " + requestUri,
114-
"An unexpected error has occurred."
115-
);
143+
using(new AssertionScope())
144+
{
145+
response.ValidateResponse(HttpStatusCode.InternalServerError);
146+
147+
content.ValidateContent(
148+
HttpStatusCode.InternalServerError,
149+
clientErrorData,
150+
"GET: " + requestUri,
151+
"An unexpected error has occurred.");
152+
}
116153
}
117154

118155
#if NET6_0_OR_GREATER
@@ -132,18 +169,20 @@ public async void EndpointWithNotFoundException_Request_404WithErrors()
132169

133170

134171
// Assert
135-
response.ValidateResponse(HttpStatusCode.NotFound);
136-
137-
content.ValidateContent(
138-
HttpStatusCode.NotFound,
139-
clientErrorData,
140-
"GET: " + requestUri,
141-
"The entity does not exist",
142-
new Dictionary<string, ErrorDetails>()
143-
{
144-
{ "prop1", new("NOT_FOUND", "The entity does not exist") }
145-
}
146-
);
172+
using(new AssertionScope())
173+
{
174+
response.ValidateResponse(HttpStatusCode.NotFound);
175+
176+
content.ValidateContent(
177+
HttpStatusCode.NotFound,
178+
clientErrorData,
179+
"GET: " + requestUri,
180+
"The entity does not exist",
181+
new Dictionary<string, ErrorDetails>()
182+
{
183+
["prop1"] = new("NOT_FOUND", "The entity does not exist")
184+
});
185+
}
147186
}
148187
#endif
149188

@@ -161,18 +200,20 @@ public async void EndpointWithNotFoundException_Request_409WithErrors()
161200

162201

163202
// Assert
164-
response.ValidateResponse(HttpStatusCode.Conflict);
165-
166-
content.ValidateContent(
167-
HttpStatusCode.Conflict,
168-
clientErrorData,
169-
"GET: " + requestUri,
170-
"double",
171-
new Dictionary<string, ErrorDetails>()
172-
{
173-
{ "prop2", new("DUPLICATED", "double") }
174-
}
175-
);
203+
using(new AssertionScope())
204+
{
205+
response.ValidateResponse(HttpStatusCode.Conflict);
206+
207+
content.ValidateContent(
208+
HttpStatusCode.Conflict,
209+
clientErrorData,
210+
"GET: " + requestUri,
211+
"double",
212+
new Dictionary<string, ErrorDetails>()
213+
{
214+
["prop2"] = new("DUPLICATED", "double")
215+
});
216+
}
176217
}
177218

178219
[Fact]
@@ -189,14 +230,16 @@ public async void CustomExceptionMapper_Request_503()
189230

190231

191232
// Assert
192-
response.ValidateResponse(HttpStatusCode.ServiceUnavailable);
193-
194-
content.ValidateContent(
195-
HttpStatusCode.ServiceUnavailable,
196-
clientErrorData,
197-
"GET: " + requestUri,
198-
"An unexpected error has occurred."
199-
);
233+
using(new AssertionScope())
234+
{
235+
response.ValidateResponse(HttpStatusCode.ServiceUnavailable);
236+
237+
content.ValidateContent(
238+
HttpStatusCode.ServiceUnavailable,
239+
clientErrorData,
240+
"GET: " + requestUri,
241+
"An unexpected error has occurred.");
242+
}
200243
}
201244

202245
[Fact]
@@ -213,20 +256,19 @@ public async void CustomExcetionWithSpecificTitleAndLink_Request_582()
213256

214257

215258
// Assert
216-
response.ValidateResponse(582);
217-
218-
content.ValidateContent(
219-
582,
220-
clientErrorData,
221-
"GET: " + requestUri,
222-
"An unexpected error has occurred."
223-
);
224-
225-
content.Type.Should()
226-
.Be("CustomLink");
227-
228-
content.Title.Should()
229-
.Be("CustomTitle");
259+
using(new AssertionScope())
260+
{
261+
response.ValidateResponse(582);
262+
263+
content.ValidateContent(
264+
582,
265+
clientErrorData,
266+
"GET: " + requestUri,
267+
"An unexpected error has occurred.");
268+
269+
content.Type.Should().Be("CustomLink");
270+
content.Title.Should().Be("CustomTitle");
271+
}
230272
}
231273

232274
[Fact]
@@ -243,14 +285,16 @@ public async void EndpointWithTimeoutException_Request_504StatusCode()
243285

244286

245287
// Assert
246-
response.ValidateResponse(HttpStatusCode.GatewayTimeout);
247-
248-
content.ValidateContent(
249-
HttpStatusCode.GatewayTimeout,
250-
clientErrorData,
251-
"GET: " + requestUri,
252-
"An unexpected error has occurred."
253-
);
288+
using(new AssertionScope())
289+
{
290+
response.ValidateResponse(HttpStatusCode.GatewayTimeout);
291+
292+
content.ValidateContent(
293+
HttpStatusCode.GatewayTimeout,
294+
clientErrorData,
295+
"GET: " + requestUri,
296+
"An unexpected error has occurred.");
297+
}
254298
}
255299

256300
[Fact]
@@ -267,18 +311,20 @@ public async void PropertyException_Request_400WithErrors()
267311

268312

269313
// Assert
270-
response.ValidateResponse(HttpStatusCode.BadRequest);
271-
272-
content.ValidateContent(
273-
HttpStatusCode.BadRequest,
274-
clientErrorData,
275-
"GET: " + requestUri,
276-
"Error validations",
277-
new Dictionary<string, ErrorDetails>()
278-
{
279-
{ "prop", new("Err", "Error validations") }
280-
}
281-
);
314+
using(new AssertionScope())
315+
{
316+
response.ValidateResponse(HttpStatusCode.BadRequest);
317+
318+
content.ValidateContent(
319+
HttpStatusCode.BadRequest,
320+
clientErrorData,
321+
"GET: " + requestUri,
322+
"Error validations",
323+
new Dictionary<string, ErrorDetails>()
324+
{
325+
["prop"] = new("Err", "Error validations")
326+
});
327+
}
282328
}
283329
}
284330
}

0 commit comments

Comments
 (0)