def revoke_access_token(credential): """Revoke an access token. All future requests with the access token will be invalid. Parameters credential (OAuth2Credential) An authorized user's OAuth 2.0 credentials. Raises ClientError (APIError) Thrown if there was an HTTP error. """ url = build_url(auth.AUTH_HOST, auth.REVOKE_PATH) args = { 'token': credential.access_token, 'client_id': credential.client_id, 'client_secret': credential.client_secret, } response = post(url=url, params=args) if response.status_code == codes.ok: return message = 'Failed to revoke access token: {}.' message = message.format(response.reason) raise ClientError(response, message)
def test_simple_422_distance_exceeded_error( simple_422_distance_exceeded_error ): """Test Distance Exceeded Error converted to ClientError correctly.""" client_error = ClientError(simple_422_distance_exceeded_error, 'msg') assert str(client_error) == 'msg' assert isinstance(client_error.errors, list) assert isinstance(client_error.meta, dict) error_details = client_error.errors[0] expected_code = 'distance_exceeded' expected_description = http.ERROR_CODE_DESCRIPTION_DICT[expected_code] assert isinstance(error_details, ErrorDetails) assert error_details.status == http.STATUS_UNPROCESSABLE_ENTITY assert error_details.code == expected_code assert error_details.title == expected_description meta = client_error.meta fields = { 'fields': { 'start_longitude': http.ERROR_CODE_DESCRIPTION_DICT[expected_code], 'end_longitude': http.ERROR_CODE_DESCRIPTION_DICT[expected_code], 'start_latitude': http.ERROR_CODE_DESCRIPTION_DICT[expected_code], 'end_latitude': http.ERROR_CODE_DESCRIPTION_DICT[expected_code], }, } assert meta == fields
def test_simple_422_validation_error(simple_422_validation_error): """Test Validation Error converted to ClientError correctly.""" client_error = ClientError(simple_422_validation_error, 'msg') assert str(client_error) == 'msg' assert isinstance(client_error.errors, list) assert isinstance(client_error.meta, dict) error_details = client_error.errors[0] expected_code = 'validation_failed' expected_description = http.ERROR_CODE_DESCRIPTION_DICT[expected_code] assert isinstance(error_details, ErrorDetails) assert error_details.status == http.STATUS_UNPROCESSABLE_ENTITY assert error_details.code == expected_code assert error_details.title == expected_description meta = client_error.meta fields = { 'fields': { 'latitude': 'Must be between -90.0 and 90.0', 'longitude': 'Must be between -180.0 and 180.0', }, } assert meta == fields
def error_handler(response, **kwargs): """Error Handler to surface 4XX and 5XX errors. Attached as a callback hook on the Request object. Parameters response (requests.Response) The HTTP response from an API request. **kwargs Arbitrary keyword arguments. Raises ClientError (ApiError) Raised if response contains a 4XX status code. ServerError (ApiError) Raised if response contains a 5XX status code. Returns response (requests.Response) The original HTTP response from the API request. """ if 400 <= response.status_code <= 499: raise ClientError(response) elif 500 <= response.status_code <= 599: raise ServerError(response) return response
def make_from_response( cls, response, grant_type, client_id, client_secret=None, redirect_url=None, ): """Alternate constructor for OAuth2Credential(). Create an OAuth2Credential from an HTTP Response. Parameters response (Response) HTTP Response containing OAuth 2.0 credentials. grant_type (str) Type of OAuth 2.0 Grant used to obtain access token. (e.g. 'authorization_code') client_id (str) Your app's Client ID. client_secret (str) Your app's Client Secret. redirect_url (str) The URL that the Uber server will redirect to. Returns (OAuth2Credential) Raises ClientError (APIError) Raised if the response is invalid. """ if response.status_code != codes.ok: message = 'Error with Access Token Request: {}' message = message.format(response.reason) raise ClientError(response, message) response = response.json() # convert space delimited string to set scopes = response.get('scope') scopes_set = {scope for scope in scopes.split()} return cls( client_id=client_id, client_secret=client_secret, redirect_url=redirect_url, access_token=response.get('access_token'), expires_in_seconds=response.get('expires_in'), scopes=scopes_set, grant_type=grant_type, refresh_token=response.get('refresh_token', None), )
def test_simple_401_error(simple_401_error): """Test Unauthorized Error converted to ClientError correctly.""" client_error = ClientError(simple_401_error, 'msg') assert str(client_error) == 'msg' assert isinstance(client_error.errors, list) assert isinstance(client_error.meta, dict) assert not client_error.meta error_details = client_error.errors[0] expected_code = 'unauthorized' expected_description = http.ERROR_CODE_DESCRIPTION_DICT[expected_code] assert isinstance(error_details, ErrorDetails) assert error_details.status == http.STATUS_UNAUTHORIZED assert error_details.code == expected_code assert error_details.title == expected_description
def test_complex_422_same_pickup_dropoff_error( complex_422_same_pickup_dropoff_error): """Test Same Pickup-Dropoff Error converted to ClientError correctly.""" client_error = ClientError(complex_422_same_pickup_dropoff_error, 'msg') assert str(client_error) == 'msg' assert isinstance(client_error.errors, list) assert isinstance(client_error.meta, dict) assert not client_error.meta error_details = client_error.errors[0] expected_code = 'same_pickup_dropoff' expected_description = http.ERROR_CODE_DESCRIPTION_DICT[expected_code] assert isinstance(error_details, ErrorDetails) assert error_details.status == http.STATUS_UNPROCESSABLE_ENTITY assert error_details.code == expected_code assert error_details.title == expected_description
def test_complex_409_surge_error(complex_409_surge_error): """Test Surge Error converted to ClientError correctly.""" client_error = ClientError(complex_409_surge_error, 'msg') assert str(client_error) == 'msg' assert isinstance(client_error.errors, list) assert isinstance(client_error.meta, dict) error_details = client_error.errors[0] expected_code = 'surge' expected_description = http.ERROR_CODE_DESCRIPTION_DICT[expected_code] assert isinstance(error_details, ErrorDetails) assert error_details.status == http.STATUS_CONFLICT assert error_details.code == expected_code assert error_details.title == expected_description surge_meta = client_error.meta['surge_confirmation'] assert surge_meta['surge_confirmation_id'] == 'abc' assert surge_meta['href'] == 'api.uber.com/v1/surge-confirmations/abc'
def error_handler(response, **kwargs): """Error Handler to surface 4XX and 5XX errors. Attached as a callback hook on the Request object. Parameters response (requests.Response) The HTTP response from an API request. **kwargs Arbitrary keyword arguments. Raises ClientError (ApiError) Raised if response contains a 4XX status code. ServerError (ApiError) Raised if response contains a 5XX status code. Returns response (requests.Response) The original HTTP response from the API request. """ try: body = response.json() except ValueError: body = {} status_code = response.status_code message = body.get('message', '') fields = body.get('fields', '') error_message = str(status_code) + ': ' + message + ' ' + str(fields) if 400 <= status_code <= 499: raise ClientError(response, error_message) elif 500 <= status_code <= 599: raise ServerError(response, error_message) return response
def _request_access_token(grant_type, client_id=None, client_secret=None, scopes=None, code=None, redirect_url=None, refresh_token=None): """Make an HTTP POST to request an access token. Parameters grant_type (str) Either 'client_credientials' (Client Credentials Grant) or 'authorization_code' (Authorization Code Grant). client_id (str) Your app's Client ID. client_secret (str) Your app's Client Secret. scopes (set) Set of permission scopes to request. (e.g. {'profile', 'history'}) code (str) The authorization code to switch for an access token. Only used in Authorization Code Grant. redirect_url (str) The URL that the Uber server will redirect to. refresh_token (str) Refresh token used to get a new access token. Only used for Authorization Code Grant. Returns (requests.Response) Successful HTTP response from a 'POST' to request an access token. Raises ClientError (APIError) Thrown if there was an HTTP error. """ url = build_url(auth.AUTH_HOST, auth.ACCESS_TOKEN_PATH) if isinstance(scopes, set): scopes = ' '.join(scopes) args = { 'grant_type': grant_type, 'client_id': client_id, 'client_secret': client_secret, 'scope': scopes, 'code': code, 'redirect_uri': redirect_url, 'refresh_token': refresh_token, } response = post(url=url, data=args) if response.status_code == codes.ok: return response message = 'Failed to request access token: {}.' message = message.format(response.reason) raise ClientError(response, message)