def verify_token(self, token, requested_access): """ Check the token bearer is permitted to access the resource :param token: Access token :param requested_access: the access level the client has requested :returns: boolean """ client = API(options.url_auth, auth_username=options.service_id, auth_password=options.client_secret, ssl_options=ssl_server_options()) headers = { 'Content-Type': 'application/x-www-form-urlencoded', 'Accept': 'application/json' } body = urllib.urlencode({ 'token': token, 'requested_access': requested_access }) client.auth.verify.prepare_request(headers=headers, request_timeout=180) try: result = yield client.auth.verify.post(body=body) except tornado.httpclient.HTTPError as ex: # Must be converted to a tornado.web.HTTPError for the server # to handle it correctly logging.exception(ex.message) raise HTTPError(500, 'Internal Server Error') raise Return(result['has_access'])
def send_notification(repository, **kwargs): """ Send a fire-and-forget notification to the index service NOTE: all exceptions are unhandled. It's assumed that the function is used as a callback outside of the request's context using IOLoop.spawn_callback (see: http://www.tornadoweb.org/en/stable/ioloop.html) """ headers = { 'Accept': 'application/json', 'Content-Type': 'application/json' } try: token = yield get_token(options.url_auth, options.service_id, options.client_secret, scope=Write(options.url_index), ssl_options=ssl_server_options()) client = API(options.url_index, token=token, ssl_options=ssl_server_options()) client.index.notifications.prepare_request( request_timeout=options.request_timeout, headers=headers, body=json.dumps({'id': repository.repository_id})) logging.debug('calling send_notification ' + str(repository.repository_id)) yield client.index.notifications.post() except Exception as e: logging.exception("failed to notify index: " + e.message)
def __init__(self, repository_dict, api_client=None): if api_client is None: api_client = API(options.url_accounts, ssl_options=ssl_server_options()) self._repository_dict = repository_dict self._api = api_client self._endpoint = self._api.accounts.repositories self._shelf = shelve.open(options.local_db, writeback=True) self.on_new_repo = None
def repository_service_client(location): """ get an api client for a repository service :params location: base url of the repository """ token = yield get_token(options.url_auth, options.service_id, options.client_secret, scope=Read(), ssl_options=ssl_server_options()) client = API(location, token=token, ssl_options=ssl_server_options()) raise Return(client)
def get_repository(repository_id): """ Lookup the repository location from the accounts service TODO: cache the response :param repository_id: the repository's ID :returns: a URL """ api = API(options.url_accounts, ssl_options=ssl_server_options()) response = yield api.accounts.repositories[repository_id].get() raise Return(response)
def transform(data, content_type, r2rml_url): """ Transforms source data into RDF triples :param data: the source data :param content_type: the http request content type :param r2rml_url: karma mapping file url :return: Transformed data and errors """ logging.debug('>>> transform') response = None http_status = 200 errors = [] try: token = yield oauth2.get_token(options.url_auth, options.service_id, options.client_secret, scope=oauth2.Write( options.url_transformation), ssl_options=ssl_server_options()) except httpclient.HTTPError as exc: logging.exception('Error getting token for the transformation service') raise exceptions.HTTPError(500, 'Internal Server Error') headers = {'Accept': 'application/json', 'Content-Type': content_type} client = API(options.url_transformation, token=token, ssl_options=ssl_server_options()) if r2rml_url: params = urlencode({'r2rml_url': r2rml_url}) client.transformation.assets.path += '?{}'.format(params) try: client.transformation.assets.prepare_request(request_timeout=180, headers=headers, body=data) response = yield client.transformation.assets.post() except httpclient.HTTPError as exc: response = exc.response logging.exception('Transformation service error body:{}'.format( exc.response)) http_status = exc.code errors = json.loads(exc.response.body)['errors'] logging.debug('<<< transform') raise Return((response, http_status, errors))
def get_repository(repository_id): """ Get the repository service address from accounts service for storing data. :param repository_id: the repository ID :return: url of the repository url :raise: HTTPError """ client = API(options.url_accounts, ssl_options=ssl_server_options()) try: response = yield client.accounts.repositories[repository_id].get() logging.debug(response['data']) raise Return(response['data']) except KeyError: error = 'Cannot find a repository' raise exceptions.HTTPError(404, error)
def delete(response_trans, repository_url, repository_id, token=None): """ Send the rdf N3 content to the repository service for it to be deleted :param response_trans: transformed data from the transformation service :param repository_url: url of the repository service :param repository_id: the repository ID :param token: an authorization token :return: Errors """ http_status = 200 errors = [] headers = {'Content-Type': 'text/rdf+n3', 'Accept': 'application/json'} client = API(repository_url, ssl_options=ssl_server_options(), token=token) endpoint = client.repository.repositories[repository_id].assets try: rdf_n3 = response_trans['data']['rdf_n3'] endpoint.prepare_request(request_timeout=180, headers=headers, body=rdf_n3, allow_nonstandard_methods=True) yield endpoint.delete() except httpclient.HTTPError as exc: logging.debug('Repository service error code:{}'.format(exc.code)) logging.debug('Repository service error body:{}'.format(exc.response)) if exc.code in (400, 403): http_status = exc.code errors = json.loads(exc.response.body)['errors'] else: http_status = 500 errors = [{ "message": "Repository service error {}".format(exc.code) }] # socket error can occur if repository_url doesn't resolve to anything # by the dns server except socket.error as exc: http_status = 500 message = "Socket error {} from {}".format(exc.args, repository_url) errors = [{"message": message}] logging.debug('<<< transform') raise Return((http_status, errors))
def delete_from_index(repository, ids, **kwargs): """ Send a fire-and-forget delete to the index service NOTE: all exceptions are unhandled. It's assumed that the function is used as a callback outside of the request's context using IOLoop.spawn_callback (see: http://www.tornadoweb.org/en/stable/ioloop.html) """ headers = { 'Accept': 'application/json', 'Content-Type': 'application/json' } try: # extract the id list and id_type list from the incoming ids parameter source_id_types = ','.join( [urllib.unquote(str(x['source_id_type'])) for x in ids]) source_ids = ','.join( [urllib.unquote(str(x['source_id'])) for x in ids]) logging.debug('delete_from_index : source_id_types ' + source_id_types) logging.debug('delete_from_index : source_ids ' + source_ids) token = yield get_token(options.url_auth, options.service_id, options.client_secret, scope=Write(options.url_index), ssl_options=ssl_server_options()) client = API(options.url_index, token=token, ssl_options=ssl_server_options()) logging.debug('delete_from_index : repo ' + str(repository.repository_id)) yield client.index['entity-types']['asset']['id-types'][ source_id_types].ids[source_ids].repositories[ repository.repository_id].delete() except Exception as e: logging.exception("failed to delete from index: " + e.message)
def test_with_token(header, token): api = API('http://example.com/', token=token) assert api.token == token assert api.default_headers['Authorization'] == header
def test_without_token(): api = API('http://example.com/') assert api.token == '' assert 'Authorization' not in api.default_headers
def test_base_url_ends_with_slash(): api = API('http://example.com/') assert api.base_url == 'http://example.com/' + API_VERSION
def test_async_api(): api = API('http://example.com') assert api.base_url == 'http://example.com/' + API_VERSION isinstance(api.fetch.keywords['httpclient'], AsyncHTTPClient)
# -*- coding: utf-8 -*- # Copyright 2016 Open Permissions Platform Coalition # 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. # from chub import API from tornado.ioloop import IOLoop from tornado.gen import coroutine onboarding = API('https://on-stage.copyrighthub.org/v1/onboarding') accounts = API('https://acc-stage.copyrighthub.org/v1/accounts') def async_call_callback_style(): def _process_capability_response(response): print 'max_file_size =', response['max_file_size'] IOLoop.current().stop() onboarding.capabilities.get(callback=_process_capability_response) IOLoop.instance().start() @coroutine def async_call_coroutine_style(): response = yield onboarding.capabilities.get() print 'max_file_size =', response['max_file_size']