Skip to content

Commit 030f6e6

Browse files
authored
Adding a few overlooked error types (#319)
* Adding some missing error types * Updated documentation
1 parent 299e808 commit 030f6e6

File tree

4 files changed

+49
-6
lines changed

4 files changed

+49
-6
lines changed

firebase_admin/_auth_utils.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,15 @@ def __init__(self, message, cause, http_response):
202202
exceptions.AlreadyExistsError.__init__(self, message, cause, http_response)
203203

204204

205+
class EmailAlreadyExistsError(exceptions.AlreadyExistsError):
206+
"""The user with the provided email already exists."""
207+
208+
default_message = 'The user with the provided email already exists'
209+
210+
def __init__(self, message, cause, http_response):
211+
exceptions.AlreadyExistsError.__init__(self, message, cause, http_response)
212+
213+
205214
class InvalidDynamicLinkDomainError(exceptions.InvalidArgumentError):
206215
"""Dynamic link domain in ActionCodeSettings is not authorized."""
207216

@@ -220,6 +229,15 @@ def __init__(self, message, cause=None, http_response=None):
220229
exceptions.InvalidArgumentError.__init__(self, message, cause, http_response)
221230

222231

232+
class PhoneNumberAlreadyExistsError(exceptions.AlreadyExistsError):
233+
"""The user with the provided phone number already exists."""
234+
235+
default_message = 'The user with the provided phone number already exists'
236+
237+
def __init__(self, message, cause, http_response):
238+
exceptions.AlreadyExistsError.__init__(self, message, cause, http_response)
239+
240+
223241
class UnexpectedResponseError(exceptions.UnknownError):
224242
"""Backend service responded with an unexpected or malformed response."""
225243

@@ -237,9 +255,11 @@ def __init__(self, message, cause=None, http_response=None):
237255

238256

239257
_CODE_TO_EXC_TYPE = {
258+
'DUPLICATE_EMAIL': EmailAlreadyExistsError,
240259
'DUPLICATE_LOCAL_ID': UidAlreadyExistsError,
241260
'INVALID_DYNAMIC_LINK_DOMAIN': InvalidDynamicLinkDomainError,
242261
'INVALID_ID_TOKEN': InvalidIdTokenError,
262+
'PHONE_NUMBER_EXISTS': PhoneNumberAlreadyExistsError,
243263
'USER_NOT_FOUND': UserNotFoundError,
244264
}
245265

firebase_admin/auth.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
'ActionCodeSettings',
3838
'CertificateFetchError',
3939
'DELETE_ATTRIBUTE',
40+
'EmailAlreadyExistsError',
4041
'ErrorInfo',
4142
'ExpiredIdTokenError',
4243
'ExpiredSessionCookieError',
@@ -46,6 +47,7 @@
4647
'InvalidIdTokenError',
4748
'InvalidSessionCookieError',
4849
'ListUsersPage',
50+
'PhoneNumberAlreadyExistsError',
4951
'RevokedIdTokenError',
5052
'RevokedSessionCookieError',
5153
'TokenSignError',
@@ -81,6 +83,7 @@
8183
ActionCodeSettings = _user_mgt.ActionCodeSettings
8284
CertificateFetchError = _token_gen.CertificateFetchError
8385
DELETE_ATTRIBUTE = _user_mgt.DELETE_ATTRIBUTE
86+
EmailAlreadyExistsError = _auth_utils.EmailAlreadyExistsError
8487
ErrorInfo = _user_import.ErrorInfo
8588
ExpiredIdTokenError = _token_gen.ExpiredIdTokenError
8689
ExpiredSessionCookieError = _token_gen.ExpiredSessionCookieError
@@ -90,6 +93,7 @@
9093
InvalidIdTokenError = _auth_utils.InvalidIdTokenError
9194
InvalidSessionCookieError = _token_gen.InvalidSessionCookieError
9295
ListUsersPage = _user_mgt.ListUsersPage
96+
PhoneNumberAlreadyExistsError = _auth_utils.PhoneNumberAlreadyExistsError
9397
RevokedIdTokenError = _token_gen.RevokedIdTokenError
9498
RevokedSessionCookieError = _token_gen.RevokedSessionCookieError
9599
TokenSignError = _token_gen.TokenSignError

firebase_admin/exceptions.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,18 @@
3838

3939

4040
class FirebaseError(Exception):
41-
"""Base class for all errors raised by the Admin SDK."""
41+
"""Base class for all errors raised by the Admin SDK.
42+
43+
Args:
44+
code: A string error code that represents the type of the exception. Possible error
45+
codes are defined in https://cloud.google.com/apis/design/errors#handling_errors.
46+
message: A human-readable error message string.
47+
cause: The exception that caused this error (optional).
48+
http_response: If this error was caused by an HTTP error response, this property is
49+
set to the ``requests.Response`` object that represents the HTTP response (optional).
50+
See https://2.python-requests.org/en/master/api/#requests.Response for details of
51+
this object.
52+
"""
4253

4354
def __init__(self, code, message, cause=None, http_response=None):
4455
Exception.__init__(self, message)

tests/test_user_mgt.py

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,12 @@ def test_get_user_by_phone_http_error(self, user_mgt_app):
289289

290290
class TestCreateUser(object):
291291

292+
already_exists_errors = {
293+
'DUPLICATE_EMAIL': auth.EmailAlreadyExistsError,
294+
'DUPLICATE_LOCAL_ID': auth.UidAlreadyExistsError,
295+
'PHONE_NUMBER_EXISTS': auth.PhoneNumberAlreadyExistsError,
296+
}
297+
292298
@pytest.mark.parametrize('arg', INVALID_STRINGS[1:] + ['a'*129])
293299
def test_invalid_uid(self, user_mgt_app, arg):
294300
with pytest.raises(ValueError):
@@ -358,13 +364,15 @@ def test_create_user_error(self, user_mgt_app):
358364
assert excinfo.value.http_response is not None
359365
assert excinfo.value.cause is not None
360366

361-
def test_uid_already_exists(self, user_mgt_app):
362-
_instrument_user_manager(user_mgt_app, 500, '{"error": {"message": "DUPLICATE_LOCAL_ID"}}')
363-
with pytest.raises(auth.UidAlreadyExistsError) as excinfo:
367+
@pytest.mark.parametrize('error_code', already_exists_errors.keys())
368+
def test_user_already_exists(self, user_mgt_app, error_code):
369+
resp = {'error': {'message': error_code}}
370+
_instrument_user_manager(user_mgt_app, 500, json.dumps(resp))
371+
exc_type = self.already_exists_errors[error_code]
372+
with pytest.raises(exc_type) as excinfo:
364373
auth.create_user(app=user_mgt_app)
365374
assert isinstance(excinfo.value, exceptions.AlreadyExistsError)
366-
assert str(excinfo.value) == ('The user with the provided uid already exists '
367-
'(DUPLICATE_LOCAL_ID).')
375+
assert str(excinfo.value) == '{0} ({1}).'.format(exc_type.default_message, error_code)
368376
assert excinfo.value.http_response is not None
369377
assert excinfo.value.cause is not None
370378

0 commit comments

Comments
 (0)