diff --git a/firebase_admin/_user_mgt.py b/firebase_admin/_user_mgt.py index 3910f9690..435594224 100644 --- a/firebase_admin/_user_mgt.py +++ b/firebase_admin/_user_mgt.py @@ -24,9 +24,6 @@ from firebase_admin import _user_import -USER_IMPORT_ERROR = 'USER_IMPORT_ERROR' -USER_DOWNLOAD_ERROR = 'LIST_USERS_ERROR' - MAX_LIST_USERS_RESULTS = 1000 MAX_IMPORT_USERS_SIZE = 1000 @@ -44,15 +41,6 @@ def __init__(self, description): DELETE_ATTRIBUTE = Sentinel('Value used to delete an attribute from a user profile') -class ApiCallError(Exception): - """Represents an Exception encountered while invoking the Firebase user management API.""" - - def __init__(self, code, message, error=None): - Exception.__init__(self, message) - self.code = code - self.detail = error - - class UserMetadata(object): """Contains additional metadata associated with a user account.""" @@ -510,7 +498,7 @@ def list_users(self, page_token=None, max_results=MAX_LIST_USERS_RESULTS): try: return self._client.body('get', '/accounts:batchGet', params=payload) except requests.exceptions.RequestException as error: - self._handle_http_error(USER_DOWNLOAD_ERROR, 'Failed to download user accounts.', error) + raise _auth_utils.handle_auth_backend_error(error) def create_user(self, uid=None, display_name=None, email=None, phone_number=None, photo_url=None, password=None, disabled=None, email_verified=None): @@ -619,13 +607,15 @@ def import_users(self, users, hash_alg=None): raise ValueError('A UserImportHash is required to import users with passwords.') payload.update(hash_alg.to_dict()) try: - response = self._client.body('post', '/accounts:batchCreate', json=payload) + body, http_resp = self._client.body_and_response( + 'post', '/accounts:batchCreate', json=payload) except requests.exceptions.RequestException as error: - self._handle_http_error(USER_IMPORT_ERROR, 'Failed to import users.', error) + raise _auth_utils.handle_auth_backend_error(error) else: - if not isinstance(response, dict): - raise ApiCallError(USER_IMPORT_ERROR, 'Failed to import users.') - return response + if not isinstance(body, dict): + raise _auth_utils.UnexpectedResponseError( + 'Failed to import users.', http_response=http_resp) + return body def generate_email_action_link(self, action_type, email, action_code_settings=None): """Fetches the email action links for types @@ -640,7 +630,7 @@ def generate_email_action_link(self, action_type, email, action_code_settings=No link_url: action url to be emailed to the user Raises: - ApiCallError: If an error occurs while generating the link + FirebaseError: If an error occurs while generating the link ValueError: If the provided arguments are invalid """ payload = { @@ -663,13 +653,6 @@ def generate_email_action_link(self, action_type, email, action_code_settings=No 'Failed to generate email action link.', http_response=http_resp) return body.get('oobLink') - def _handle_http_error(self, code, msg, error): - if error.response is not None: - msg += '\nServer response: {0}'.format(error.response.content.decode()) - else: - msg += '\nReason: {0}'.format(error) - raise ApiCallError(code, msg, error) - class _UserIterator(object): """An iterator that allows iterating over user accounts, one at a time. diff --git a/firebase_admin/auth.py b/firebase_admin/auth.py index 61d71ad9f..0913e50f7 100644 --- a/firebase_admin/auth.py +++ b/firebase_admin/auth.py @@ -308,14 +308,11 @@ def list_users(page_token=None, max_results=_user_mgt.MAX_LIST_USERS_RESULTS, ap Raises: ValueError: If max_results or page_token are invalid. - AuthError: If an error occurs while retrieving the user accounts. + FirebaseError: If an error occurs while retrieving the user accounts. """ user_manager = _get_auth_service(app).user_manager def download(page_token, max_results): - try: - return user_manager.list_users(page_token, max_results) - except _user_mgt.ApiCallError as error: - raise AuthError(error.code, str(error), error.detail) + return user_manager.list_users(page_token, max_results) return ListUsersPage(download, page_token, max_results) @@ -443,14 +440,11 @@ def import_users(users, hash_alg=None, app=None): Raises: ValueError: If the provided arguments are invalid. - AuthError: If an error occurs while importing users. + FirebaseError: If an error occurs while importing users. """ user_manager = _get_auth_service(app).user_manager - try: - result = user_manager.import_users(users, hash_alg) - return UserImportResult(result, len(users)) - except _user_mgt.ApiCallError as error: - raise AuthError(error.code, str(error), error.detail) + result = user_manager.import_users(users, hash_alg) + return UserImportResult(result, len(users)) def generate_password_reset_link(email, action_code_settings=None, app=None): diff --git a/tests/test_user_mgt.py b/tests/test_user_mgt.py index 594de2d4c..34e2b019b 100644 --- a/tests/test_user_mgt.py +++ b/tests/test_user_mgt.py @@ -731,10 +731,9 @@ def test_list_users_with_all_args(self, user_mgt_app): def test_list_users_error(self, user_mgt_app): _instrument_user_manager(user_mgt_app, 500, '{"error":"test"}') - with pytest.raises(auth.AuthError) as excinfo: + with pytest.raises(exceptions.InternalError) as excinfo: auth.list_users(app=user_mgt_app) - assert excinfo.value.code == _user_mgt.USER_DOWNLOAD_ERROR - assert '{"error":"test"}' in str(excinfo.value) + assert str(excinfo.value) == 'Unexpected error response: {"error":"test"}' def _check_page(self, page): assert isinstance(page, auth.ListUsersPage) @@ -1076,6 +1075,25 @@ def test_import_users_with_hash(self, user_mgt_app): } self._check_rpc_calls(recorder, expected) + def test_import_users_http_error(self, user_mgt_app): + _instrument_user_manager(user_mgt_app, 401, '{"error": {"message": "ERROR_CODE"}}') + users = [ + auth.ImportUserRecord(uid='user1'), + auth.ImportUserRecord(uid='user2'), + ] + with pytest.raises(exceptions.UnauthenticatedError) as excinfo: + auth.import_users(users, app=user_mgt_app) + assert str(excinfo.value) == 'Error while calling Auth service (ERROR_CODE).' + + def test_import_users_unexpected_response(self, user_mgt_app): + _instrument_user_manager(user_mgt_app, 200, '"not dict"') + users = [ + auth.ImportUserRecord(uid='user1'), + auth.ImportUserRecord(uid='user2'), + ] + with pytest.raises(auth.UnexpectedResponseError): + auth.import_users(users, app=user_mgt_app) + def _check_rpc_calls(self, recorder, expected): assert len(recorder) == 1 request = json.loads(recorder[0].body.decode())