Added delete option to database storage.
This commit is contained in:
parent
308604a33c
commit
963b5bc68b
1868 changed files with 192402 additions and 13278 deletions
341
venv/Lib/site-packages/firebase_admin/_utils.py
Normal file
341
venv/Lib/site-packages/firebase_admin/_utils.py
Normal file
|
@ -0,0 +1,341 @@
|
|||
# Copyright 2017 Google Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
"""Internal utilities common to all modules."""
|
||||
|
||||
import io
|
||||
import json
|
||||
import socket
|
||||
|
||||
import googleapiclient
|
||||
import httplib2
|
||||
import requests
|
||||
|
||||
import firebase_admin
|
||||
from firebase_admin import exceptions
|
||||
|
||||
|
||||
_ERROR_CODE_TO_EXCEPTION_TYPE = {
|
||||
exceptions.INVALID_ARGUMENT: exceptions.InvalidArgumentError,
|
||||
exceptions.FAILED_PRECONDITION: exceptions.FailedPreconditionError,
|
||||
exceptions.OUT_OF_RANGE: exceptions.OutOfRangeError,
|
||||
exceptions.UNAUTHENTICATED: exceptions.UnauthenticatedError,
|
||||
exceptions.PERMISSION_DENIED: exceptions.PermissionDeniedError,
|
||||
exceptions.NOT_FOUND: exceptions.NotFoundError,
|
||||
exceptions.ABORTED: exceptions.AbortedError,
|
||||
exceptions.ALREADY_EXISTS: exceptions.AlreadyExistsError,
|
||||
exceptions.CONFLICT: exceptions.ConflictError,
|
||||
exceptions.RESOURCE_EXHAUSTED: exceptions.ResourceExhaustedError,
|
||||
exceptions.CANCELLED: exceptions.CancelledError,
|
||||
exceptions.DATA_LOSS: exceptions.DataLossError,
|
||||
exceptions.UNKNOWN: exceptions.UnknownError,
|
||||
exceptions.INTERNAL: exceptions.InternalError,
|
||||
exceptions.UNAVAILABLE: exceptions.UnavailableError,
|
||||
exceptions.DEADLINE_EXCEEDED: exceptions.DeadlineExceededError,
|
||||
}
|
||||
|
||||
|
||||
_HTTP_STATUS_TO_ERROR_CODE = {
|
||||
400: exceptions.INVALID_ARGUMENT,
|
||||
401: exceptions.UNAUTHENTICATED,
|
||||
403: exceptions.PERMISSION_DENIED,
|
||||
404: exceptions.NOT_FOUND,
|
||||
409: exceptions.CONFLICT,
|
||||
412: exceptions.FAILED_PRECONDITION,
|
||||
429: exceptions.RESOURCE_EXHAUSTED,
|
||||
500: exceptions.INTERNAL,
|
||||
503: exceptions.UNAVAILABLE,
|
||||
}
|
||||
|
||||
|
||||
# See https://github.com/googleapis/googleapis/blob/master/google/rpc/code.proto
|
||||
_RPC_CODE_TO_ERROR_CODE = {
|
||||
1: exceptions.CANCELLED,
|
||||
2: exceptions.UNKNOWN,
|
||||
3: exceptions.INVALID_ARGUMENT,
|
||||
4: exceptions.DEADLINE_EXCEEDED,
|
||||
5: exceptions.NOT_FOUND,
|
||||
6: exceptions.ALREADY_EXISTS,
|
||||
7: exceptions.PERMISSION_DENIED,
|
||||
8: exceptions.RESOURCE_EXHAUSTED,
|
||||
9: exceptions.FAILED_PRECONDITION,
|
||||
10: exceptions.ABORTED,
|
||||
11: exceptions.OUT_OF_RANGE,
|
||||
13: exceptions.INTERNAL,
|
||||
14: exceptions.UNAVAILABLE,
|
||||
15: exceptions.DATA_LOSS,
|
||||
16: exceptions.UNAUTHENTICATED,
|
||||
}
|
||||
|
||||
|
||||
def _get_initialized_app(app):
|
||||
"""Returns a reference to an initialized App instance."""
|
||||
if app is None:
|
||||
return firebase_admin.get_app()
|
||||
|
||||
if isinstance(app, firebase_admin.App):
|
||||
initialized_app = firebase_admin.get_app(app.name)
|
||||
if app is not initialized_app:
|
||||
raise ValueError('Illegal app argument. App instance not '
|
||||
'initialized via the firebase module.')
|
||||
return app
|
||||
|
||||
raise ValueError('Illegal app argument. Argument must be of type '
|
||||
' firebase_admin.App, but given "{0}".'.format(type(app)))
|
||||
|
||||
|
||||
|
||||
def get_app_service(app, name, initializer):
|
||||
app = _get_initialized_app(app)
|
||||
return app._get_service(name, initializer) # pylint: disable=protected-access
|
||||
|
||||
|
||||
def handle_platform_error_from_requests(error, handle_func=None):
|
||||
"""Constructs a ``FirebaseError`` from the given requests error.
|
||||
|
||||
This can be used to handle errors returned by Google Cloud Platform (GCP) APIs.
|
||||
|
||||
Args:
|
||||
error: An error raised by the requests module while making an HTTP call to a GCP API.
|
||||
handle_func: A function that can be used to handle platform errors in a custom way. When
|
||||
specified, this function will be called with three arguments. It has the same
|
||||
signature as ```_handle_func_requests``, but may return ``None``.
|
||||
|
||||
Returns:
|
||||
FirebaseError: A ``FirebaseError`` that can be raised to the user code.
|
||||
"""
|
||||
if error.response is None:
|
||||
return handle_requests_error(error)
|
||||
|
||||
response = error.response
|
||||
content = response.content.decode()
|
||||
status_code = response.status_code
|
||||
error_dict, message = _parse_platform_error(content, status_code)
|
||||
exc = None
|
||||
if handle_func:
|
||||
exc = handle_func(error, message, error_dict)
|
||||
|
||||
return exc if exc else _handle_func_requests(error, message, error_dict)
|
||||
|
||||
|
||||
def handle_operation_error(error):
|
||||
"""Constructs a ``FirebaseError`` from the given operation error.
|
||||
|
||||
Args:
|
||||
error: An error returned by a long running operation.
|
||||
|
||||
Returns:
|
||||
FirebaseError: A ``FirebaseError`` that can be raised to the user code.
|
||||
"""
|
||||
if not isinstance(error, dict):
|
||||
return exceptions.UnknownError(
|
||||
message='Unknown error while making a remote service call: {0}'.format(error),
|
||||
cause=error)
|
||||
|
||||
rpc_code = error.get('code')
|
||||
message = error.get('message')
|
||||
error_code = _rpc_code_to_error_code(rpc_code)
|
||||
err_type = _error_code_to_exception_type(error_code)
|
||||
return err_type(message=message)
|
||||
|
||||
|
||||
def _handle_func_requests(error, message, error_dict):
|
||||
"""Constructs a ``FirebaseError`` from the given GCP error.
|
||||
|
||||
Args:
|
||||
error: An error raised by the requests module while making an HTTP call.
|
||||
message: A message to be included in the resulting ``FirebaseError``.
|
||||
error_dict: Parsed GCP error response.
|
||||
|
||||
Returns:
|
||||
FirebaseError: A ``FirebaseError`` that can be raised to the user code or None.
|
||||
"""
|
||||
code = error_dict.get('status')
|
||||
return handle_requests_error(error, message, code)
|
||||
|
||||
|
||||
def handle_requests_error(error, message=None, code=None):
|
||||
"""Constructs a ``FirebaseError`` from the given requests error.
|
||||
|
||||
This method is agnostic of the remote service that produced the error, whether it is a GCP
|
||||
service or otherwise. Therefore, this method does not attempt to parse the error response in
|
||||
any way.
|
||||
|
||||
Args:
|
||||
error: An error raised by the requests module while making an HTTP call.
|
||||
message: A message to be included in the resulting ``FirebaseError`` (optional). If not
|
||||
specified the string representation of the ``error`` argument is used as the message.
|
||||
code: A GCP error code that will be used to determine the resulting error type (optional).
|
||||
If not specified the HTTP status code on the error response is used to determine a
|
||||
suitable error code.
|
||||
|
||||
Returns:
|
||||
FirebaseError: A ``FirebaseError`` that can be raised to the user code.
|
||||
"""
|
||||
if isinstance(error, requests.exceptions.Timeout):
|
||||
return exceptions.DeadlineExceededError(
|
||||
message='Timed out while making an API call: {0}'.format(error),
|
||||
cause=error)
|
||||
if isinstance(error, requests.exceptions.ConnectionError):
|
||||
return exceptions.UnavailableError(
|
||||
message='Failed to establish a connection: {0}'.format(error),
|
||||
cause=error)
|
||||
if error.response is None:
|
||||
return exceptions.UnknownError(
|
||||
message='Unknown error while making a remote service call: {0}'.format(error),
|
||||
cause=error)
|
||||
|
||||
if not code:
|
||||
code = _http_status_to_error_code(error.response.status_code)
|
||||
if not message:
|
||||
message = str(error)
|
||||
|
||||
err_type = _error_code_to_exception_type(code)
|
||||
return err_type(message=message, cause=error, http_response=error.response)
|
||||
|
||||
|
||||
def handle_platform_error_from_googleapiclient(error, handle_func=None):
|
||||
"""Constructs a ``FirebaseError`` from the given googleapiclient error.
|
||||
|
||||
This can be used to handle errors returned by Google Cloud Platform (GCP) APIs.
|
||||
|
||||
Args:
|
||||
error: An error raised by the googleapiclient while making an HTTP call to a GCP API.
|
||||
handle_func: A function that can be used to handle platform errors in a custom way. When
|
||||
specified, this function will be called with three arguments. It has the same
|
||||
signature as ```_handle_func_googleapiclient``, but may return ``None``.
|
||||
|
||||
Returns:
|
||||
FirebaseError: A ``FirebaseError`` that can be raised to the user code.
|
||||
"""
|
||||
if not isinstance(error, googleapiclient.errors.HttpError):
|
||||
return handle_googleapiclient_error(error)
|
||||
|
||||
content = error.content.decode()
|
||||
status_code = error.resp.status
|
||||
error_dict, message = _parse_platform_error(content, status_code)
|
||||
http_response = _http_response_from_googleapiclient_error(error)
|
||||
exc = None
|
||||
if handle_func:
|
||||
exc = handle_func(error, message, error_dict, http_response)
|
||||
|
||||
return exc if exc else _handle_func_googleapiclient(error, message, error_dict, http_response)
|
||||
|
||||
|
||||
def _handle_func_googleapiclient(error, message, error_dict, http_response):
|
||||
"""Constructs a ``FirebaseError`` from the given GCP error.
|
||||
|
||||
Args:
|
||||
error: An error raised by the googleapiclient module while making an HTTP call.
|
||||
message: A message to be included in the resulting ``FirebaseError``.
|
||||
error_dict: Parsed GCP error response.
|
||||
http_response: A requests HTTP response object to associate with the exception.
|
||||
|
||||
Returns:
|
||||
FirebaseError: A ``FirebaseError`` that can be raised to the user code or None.
|
||||
"""
|
||||
code = error_dict.get('status')
|
||||
return handle_googleapiclient_error(error, message, code, http_response)
|
||||
|
||||
|
||||
def handle_googleapiclient_error(error, message=None, code=None, http_response=None):
|
||||
"""Constructs a ``FirebaseError`` from the given googleapiclient error.
|
||||
|
||||
This method is agnostic of the remote service that produced the error, whether it is a GCP
|
||||
service or otherwise. Therefore, this method does not attempt to parse the error response in
|
||||
any way.
|
||||
|
||||
Args:
|
||||
error: An error raised by the googleapiclient module while making an HTTP call.
|
||||
message: A message to be included in the resulting ``FirebaseError`` (optional). If not
|
||||
specified the string representation of the ``error`` argument is used as the message.
|
||||
code: A GCP error code that will be used to determine the resulting error type (optional).
|
||||
If not specified the HTTP status code on the error response is used to determine a
|
||||
suitable error code.
|
||||
http_response: A requests HTTP response object to associate with the exception (optional).
|
||||
If not specified, one will be created from the ``error``.
|
||||
|
||||
Returns:
|
||||
FirebaseError: A ``FirebaseError`` that can be raised to the user code.
|
||||
"""
|
||||
if isinstance(error, socket.timeout) or (
|
||||
isinstance(error, socket.error) and 'timed out' in str(error)):
|
||||
return exceptions.DeadlineExceededError(
|
||||
message='Timed out while making an API call: {0}'.format(error),
|
||||
cause=error)
|
||||
if isinstance(error, httplib2.ServerNotFoundError):
|
||||
return exceptions.UnavailableError(
|
||||
message='Failed to establish a connection: {0}'.format(error),
|
||||
cause=error)
|
||||
if not isinstance(error, googleapiclient.errors.HttpError):
|
||||
return exceptions.UnknownError(
|
||||
message='Unknown error while making a remote service call: {0}'.format(error),
|
||||
cause=error)
|
||||
|
||||
if not code:
|
||||
code = _http_status_to_error_code(error.resp.status)
|
||||
if not message:
|
||||
message = str(error)
|
||||
if not http_response:
|
||||
http_response = _http_response_from_googleapiclient_error(error)
|
||||
|
||||
err_type = _error_code_to_exception_type(code)
|
||||
return err_type(message=message, cause=error, http_response=http_response)
|
||||
|
||||
|
||||
def _http_response_from_googleapiclient_error(error):
|
||||
"""Creates a requests HTTP Response object from the given googleapiclient error."""
|
||||
resp = requests.models.Response()
|
||||
resp.raw = io.BytesIO(error.content)
|
||||
resp.status_code = error.resp.status
|
||||
return resp
|
||||
|
||||
|
||||
def _http_status_to_error_code(status):
|
||||
"""Maps an HTTP status to a platform error code."""
|
||||
return _HTTP_STATUS_TO_ERROR_CODE.get(status, exceptions.UNKNOWN)
|
||||
|
||||
def _rpc_code_to_error_code(rpc_code):
|
||||
"""Maps an RPC code to a platform error code."""
|
||||
return _RPC_CODE_TO_ERROR_CODE.get(rpc_code, exceptions.UNKNOWN)
|
||||
|
||||
def _error_code_to_exception_type(code):
|
||||
"""Maps a platform error code to an exception type."""
|
||||
return _ERROR_CODE_TO_EXCEPTION_TYPE.get(code, exceptions.UnknownError)
|
||||
|
||||
|
||||
def _parse_platform_error(content, status_code):
|
||||
"""Parses an HTTP error response from a Google Cloud Platform API and extracts the error code
|
||||
and message fields.
|
||||
|
||||
Args:
|
||||
content: Decoded content of the response body.
|
||||
status_code: HTTP status code.
|
||||
|
||||
Returns:
|
||||
tuple: A tuple containing error code and message.
|
||||
"""
|
||||
data = {}
|
||||
try:
|
||||
parsed_body = json.loads(content)
|
||||
if isinstance(parsed_body, dict):
|
||||
data = parsed_body
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
error_dict = data.get('error', {})
|
||||
msg = error_dict.get('message')
|
||||
if not msg:
|
||||
msg = 'Unexpected HTTP response with status: {0}; body: {1}'.format(status_code, content)
|
||||
return error_dict, msg
|
Loading…
Add table
Add a link
Reference in a new issue