Skip to content

Commit 05108dc

Browse files
authored
Merge pull request #98 from firebase/hkj-auth-errors
feat(auth): Migrating FirebaseAuth API to the new error handling scheme
2 parents 2c63161 + 21d36b3 commit 05108dc

File tree

13 files changed

+817
-147
lines changed

13 files changed

+817
-147
lines changed

FirebaseAdmin/FirebaseAdmin.IntegrationTests/FirebaseAuthTest.cs

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -118,8 +118,10 @@ public async Task SetCustomUserClaimsWithWrongUid()
118118
{
119119
var customClaims = new Dictionary<string, object>();
120120

121-
await Assert.ThrowsAsync<FirebaseException>(
121+
var exception = await Assert.ThrowsAsync<FirebaseAuthException>(
122122
async () => await FirebaseAuth.DefaultInstance.SetCustomUserClaimsAsync("non.existing", customClaims));
123+
124+
Assert.Equal(AuthErrorCode.UserNotFound, exception.AuthErrorCode);
123125
}
124126

125127
[Fact]
@@ -150,8 +152,10 @@ public async Task CreateUserWithParams()
150152
Assert.False(user.Disabled);
151153

152154
// Cannot recreate the same user.
153-
await Assert.ThrowsAsync<FirebaseException>(
155+
var exception = await Assert.ThrowsAsync<FirebaseAuthException>(
154156
async () => await FirebaseAuth.DefaultInstance.CreateUserAsync(args));
157+
158+
Assert.Equal(AuthErrorCode.UidAlreadyExists, exception.AuthErrorCode);
155159
}
156160
finally
157161
{
@@ -247,23 +251,29 @@ public async Task UserLifecycle()
247251
{
248252
// Delete user
249253
await FirebaseAuth.DefaultInstance.DeleteUserAsync(uid);
250-
await Assert.ThrowsAsync<FirebaseException>(
254+
var exception = await Assert.ThrowsAsync<FirebaseAuthException>(
251255
async () => await FirebaseAuth.DefaultInstance.GetUserAsync(uid));
256+
257+
Assert.Equal(AuthErrorCode.UserNotFound, exception.AuthErrorCode);
252258
}
253259
}
254260

255261
[Fact]
256262
public async Task GetUserNonExistingUid()
257263
{
258-
await Assert.ThrowsAsync<FirebaseException>(
264+
var exception = await Assert.ThrowsAsync<FirebaseAuthException>(
259265
async () => await FirebaseAuth.DefaultInstance.GetUserAsync("non.existing"));
266+
267+
Assert.Equal(AuthErrorCode.UserNotFound, exception.AuthErrorCode);
260268
}
261269

262270
[Fact]
263271
public async Task GetUserNonExistingEmail()
264272
{
265-
await Assert.ThrowsAsync<FirebaseException>(
273+
var exception = await Assert.ThrowsAsync<FirebaseAuthException>(
266274
async () => await FirebaseAuth.DefaultInstance.GetUserByEmailAsync("[email protected]"));
275+
276+
Assert.Equal(AuthErrorCode.UserNotFound, exception.AuthErrorCode);
267277
}
268278

269279
[Fact]
@@ -273,15 +283,20 @@ public async Task UpdateUserNonExistingUid()
273283
{
274284
Uid = "non.existing",
275285
};
276-
await Assert.ThrowsAsync<FirebaseException>(
286+
287+
var exception = await Assert.ThrowsAsync<FirebaseAuthException>(
277288
async () => await FirebaseAuth.DefaultInstance.UpdateUserAsync(args));
289+
290+
Assert.Equal(AuthErrorCode.UserNotFound, exception.AuthErrorCode);
278291
}
279292

280293
[Fact]
281294
public async Task DeleteUserNonExistingUid()
282295
{
283-
await Assert.ThrowsAsync<FirebaseException>(
296+
var exception = await Assert.ThrowsAsync<FirebaseAuthException>(
284297
async () => await FirebaseAuth.DefaultInstance.DeleteUserAsync("non.existing"));
298+
299+
Assert.Equal(AuthErrorCode.UserNotFound, exception.AuthErrorCode);
285300
}
286301

287302
[Fact]
Lines changed: 234 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,234 @@
1+
// Copyright 2019, Google Inc. All rights reserved.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
using System;
16+
using System.Collections.Generic;
17+
using System.Net;
18+
using System.Net.Http;
19+
using System.Text;
20+
using FirebaseAdmin.Util;
21+
using Xunit;
22+
23+
namespace FirebaseAdmin.Auth.Tests
24+
{
25+
public class AuthErrorHandlerTest
26+
{
27+
public static readonly IEnumerable<object[]> AuthErrorCodes =
28+
new List<object[]>()
29+
{
30+
new object[]
31+
{
32+
"DUPLICATE_EMAIL",
33+
ErrorCode.AlreadyExists,
34+
AuthErrorCode.EmailAlreadyExists,
35+
},
36+
new object[]
37+
{
38+
"DUPLICATE_LOCAL_ID",
39+
ErrorCode.AlreadyExists,
40+
AuthErrorCode.UidAlreadyExists,
41+
},
42+
new object[]
43+
{
44+
"PHONE_NUMBER_EXISTS",
45+
ErrorCode.AlreadyExists,
46+
AuthErrorCode.PhoneNumberAlreadyExists,
47+
},
48+
new object[]
49+
{
50+
"USER_NOT_FOUND",
51+
ErrorCode.NotFound,
52+
AuthErrorCode.UserNotFound,
53+
},
54+
};
55+
56+
[Theory]
57+
[MemberData(nameof(AuthErrorCodes))]
58+
public void KnownErrorCode(
59+
string code, ErrorCode expectedCode, AuthErrorCode expectedAuthCode)
60+
{
61+
var json = $@"{{
62+
""error"": {{
63+
""message"": ""{code}"",
64+
}}
65+
}}";
66+
var resp = new HttpResponseMessage()
67+
{
68+
StatusCode = HttpStatusCode.ServiceUnavailable,
69+
Content = new StringContent(json, Encoding.UTF8, "application/json"),
70+
};
71+
72+
var error = AuthErrorHandler.Instance.HandleHttpErrorResponse(resp, json);
73+
74+
Assert.Equal(expectedCode, error.ErrorCode);
75+
Assert.Equal(expectedAuthCode, error.AuthErrorCode);
76+
Assert.Same(resp, error.HttpResponse);
77+
Assert.Null(error.InnerException);
78+
Assert.EndsWith($" ({code}).", error.Message);
79+
}
80+
81+
[Theory]
82+
[MemberData(nameof(AuthErrorCodes))]
83+
public void KnownErrorCodeWithDetails(
84+
string code, ErrorCode expectedCode, AuthErrorCode expectedAuthCode)
85+
{
86+
var json = $@"{{
87+
""error"": {{
88+
""message"": ""{code}: Some details."",
89+
}}
90+
}}";
91+
var resp = new HttpResponseMessage()
92+
{
93+
StatusCode = HttpStatusCode.ServiceUnavailable,
94+
Content = new StringContent(json, Encoding.UTF8, "application/json"),
95+
};
96+
97+
var error = AuthErrorHandler.Instance.HandleHttpErrorResponse(resp, json);
98+
99+
Assert.Equal(expectedCode, error.ErrorCode);
100+
Assert.Equal(expectedAuthCode, error.AuthErrorCode);
101+
Assert.Same(resp, error.HttpResponse);
102+
Assert.Null(error.InnerException);
103+
Assert.EndsWith($" ({code}): Some details.", error.Message);
104+
}
105+
106+
[Fact]
107+
public void UnknownErrorCode()
108+
{
109+
var json = $@"{{
110+
""error"": {{
111+
""message"": ""SOMETHING_UNUSUAL"",
112+
}}
113+
}}";
114+
var resp = new HttpResponseMessage()
115+
{
116+
StatusCode = HttpStatusCode.InternalServerError,
117+
Content = new StringContent(json, Encoding.UTF8, "application/json"),
118+
};
119+
120+
var error = AuthErrorHandler.Instance.HandleHttpErrorResponse(resp, json);
121+
122+
Assert.Equal(ErrorCode.Internal, error.ErrorCode);
123+
Assert.Equal(
124+
$"Unexpected HTTP response with status: 500 (InternalServerError)\n{json}",
125+
error.Message);
126+
Assert.Null(error.AuthErrorCode);
127+
Assert.Same(resp, error.HttpResponse);
128+
Assert.Null(error.InnerException);
129+
}
130+
131+
[Fact]
132+
public void UnspecifiedErrorCode()
133+
{
134+
var json = $@"{{
135+
""error"": {{}}
136+
}}";
137+
var resp = new HttpResponseMessage()
138+
{
139+
StatusCode = HttpStatusCode.InternalServerError,
140+
Content = new StringContent(json, Encoding.UTF8, "application/json"),
141+
};
142+
143+
var error = AuthErrorHandler.Instance.HandleHttpErrorResponse(resp, json);
144+
145+
Assert.Equal(ErrorCode.Internal, error.ErrorCode);
146+
Assert.Equal(
147+
$"Unexpected HTTP response with status: 500 (InternalServerError)\n{json}",
148+
error.Message);
149+
Assert.Null(error.AuthErrorCode);
150+
Assert.Same(resp, error.HttpResponse);
151+
Assert.Null(error.InnerException);
152+
}
153+
154+
[Fact]
155+
public void NoDetails()
156+
{
157+
var json = @"{}";
158+
var resp = new HttpResponseMessage()
159+
{
160+
StatusCode = HttpStatusCode.ServiceUnavailable,
161+
Content = new StringContent(json, Encoding.UTF8, "application/json"),
162+
};
163+
164+
var error = AuthErrorHandler.Instance.HandleHttpErrorResponse(resp, json);
165+
166+
Assert.Equal(ErrorCode.Unavailable, error.ErrorCode);
167+
Assert.Equal(
168+
"Unexpected HTTP response with status: 503 (ServiceUnavailable)\n{}",
169+
error.Message);
170+
Assert.Null(error.AuthErrorCode);
171+
Assert.Same(resp, error.HttpResponse);
172+
Assert.Null(error.InnerException);
173+
}
174+
175+
[Fact]
176+
public void NonJson()
177+
{
178+
var text = "plain text";
179+
var resp = new HttpResponseMessage()
180+
{
181+
StatusCode = HttpStatusCode.ServiceUnavailable,
182+
Content = new StringContent(text, Encoding.UTF8, "text/plain"),
183+
};
184+
185+
var error = AuthErrorHandler.Instance.HandleHttpErrorResponse(resp, text);
186+
187+
Assert.Equal(ErrorCode.Unavailable, error.ErrorCode);
188+
Assert.Equal(
189+
$"Unexpected HTTP response with status: 503 (ServiceUnavailable)\n{text}",
190+
error.Message);
191+
Assert.Null(error.AuthErrorCode);
192+
Assert.Same(resp, error.HttpResponse);
193+
Assert.Null(error.InnerException);
194+
}
195+
196+
[Fact]
197+
public void DeserializeException()
198+
{
199+
var text = "plain text";
200+
var resp = new HttpResponseMessage()
201+
{
202+
StatusCode = HttpStatusCode.ServiceUnavailable,
203+
Content = new StringContent(text, Encoding.UTF8, "text/plain"),
204+
};
205+
var inner = new Exception("Deserialization error");
206+
207+
var error = AuthErrorHandler.Instance.HandleDeserializeException(
208+
inner, new ResponseInfo(resp, text));
209+
210+
Assert.Equal(ErrorCode.Unknown, error.ErrorCode);
211+
Assert.Equal(
212+
$"Error while parsing Auth service response. Deserialization error: {text}",
213+
error.Message);
214+
Assert.Equal(AuthErrorCode.UnexpectedResponse, error.AuthErrorCode);
215+
Assert.Same(resp, error.HttpResponse);
216+
Assert.Same(inner, error.InnerException);
217+
}
218+
219+
[Fact]
220+
public void HttpRequestException()
221+
{
222+
var exception = new HttpRequestException("network error");
223+
224+
var error = AuthErrorHandler.Instance.HandleHttpRequestException(exception);
225+
226+
Assert.Equal(ErrorCode.Unknown, error.ErrorCode);
227+
Assert.Equal(
228+
"Unknown error while making a remote service call: network error", error.Message);
229+
Assert.Null(error.AuthErrorCode);
230+
Assert.Null(error.HttpResponse);
231+
Assert.Same(exception, error.InnerException);
232+
}
233+
}
234+
}

0 commit comments

Comments
 (0)