Пример #1
0
async def test_refresh_token_failure(http_request, http_client,
                                     create_json_response):
    auth_lost = MagicMock()
    http_client.set_auth_lost_callback(auth_lost)
    http_request.return_value = create_json_response({"access_token": "token"})
    await http_client.authenticate({})
    http_request.assert_called_once()
    http_request.reset_mock()

    http_request.side_effect = [AccessDenied(), AccessDenied()]
    with pytest.raises(AccessDenied):
        await http_client.get("http://test.com")

    assert http_request.call_count == 2

    auth_lost.assert_called_once_with()
Пример #2
0
async def test_servers_cache_failure(client, protocol_client, backend_client, servers_cache):
    servers_cache.get.return_value = async_raise(AccessDenied())
    await client.run()
    servers_cache.get.assert_called_once_with()
    backend_client.get_authentication_data.assert_not_called()
    protocol_client.authenticate.assert_not_called()
    protocol_client.run.assert_not_called()
Пример #3
0
def handle_exception():
    """
    Context manager translating network related exceptions
    to custom :mod:`~galaxy.api.errors`.
    """
    try:
        yield
    except asyncio.TimeoutError:
        raise BackendTimeout()
    except aiohttp.ServerDisconnectedError:
        raise BackendNotAvailable()
    except aiohttp.ClientConnectionError:
        raise NetworkError()
    except aiohttp.ContentTypeError as error:
        raise UnknownBackendResponse(error.message)
    except aiohttp.ClientResponseError as error:
        if error.status == HTTPStatus.UNAUTHORIZED:
            raise AuthenticationRequired(error.message)
        if error.status == HTTPStatus.FORBIDDEN:
            raise AccessDenied(error.message)
        if error.status == HTTPStatus.SERVICE_UNAVAILABLE:
            raise BackendNotAvailable(error.message)
        if error.status == HTTPStatus.TOO_MANY_REQUESTS:
            raise TooManyRequests(error.message)
        if error.status >= 500:
            raise BackendError(error.message)
        if error.status >= 400:
            logger.warning("Got status %d while performing %s request for %s",
                           error.status, error.request_info.method,
                           str(error.request_info.url))
            raise UnknownError(error.message)
    except aiohttp.ClientError as e:
        logger.exception("Caught exception while performing request")
        raise UnknownError(repr(e))
    async def request(self, method, url, *args, **kwargs):
        try:
            response = await self._session.request(method, url, *args,
                                                   **kwargs)
        except asyncio.TimeoutError:
            raise BackendTimeout()
        except aiohttp.ServerDisconnectedError:
            raise BackendNotAvailable()
        except aiohttp.ClientConnectionError:
            raise NetworkError()
        except aiohttp.ContentTypeError:
            raise UnknownBackendResponse()
        except aiohttp.ClientError:
            logging.exception(
                "Caught exception while running {} request for {}".format(
                    method, url))
            raise UnknownError()
        if response.status == HTTPStatus.UNAUTHORIZED:
            raise AuthenticationRequired()
        if response.status == HTTPStatus.FORBIDDEN:
            raise AccessDenied()
        if response.status == HTTPStatus.SERVICE_UNAVAILABLE:
            raise BackendNotAvailable()
        if response.status == HTTPStatus.TOO_MANY_REQUESTS:
            raise TooManyRequests()
        if response.status >= 500:
            raise BackendError()
        if response.status >= 400:
            logging.warning(
                "Got status {} while running {} request for {}".format(
                    response.status, method, url))
            raise UnknownError()

        return response
Пример #5
0
async def test_servers_cache_failure(client, protocol_client, backend_client, websocket_list):
    websocket_list.get.return_value = async_raise(AccessDenied())
    with pytest.raises(AccessDenied):
        await client.run()
    websocket_list.get.assert_called_once_with(0)
    backend_client.get_authentication_data.assert_not_called()
    protocol_client.authenticate.assert_not_called()
    protocol_client.run.assert_not_called()
    async def get(self, *args, **kwargs):
        if not self._access_token:
            raise AccessDenied("No access token")

        try:
            return await self._authorized_get(*args, **kwargs)
        except (AuthenticationRequired, AccessDenied):
            # Origin backend returns 403 when the auth token expires
            await self._refresh_token()
            return await self._authorized_get(*args, **kwargs)
Пример #7
0
 def handle_status_code(status_code):
     if status_code == HTTPStatus.UNAUTHORIZED:
         raise AuthenticationRequired()
     if status_code == HTTPStatus.FORBIDDEN:
         raise AccessDenied()
     if status_code == HTTPStatus.SERVICE_UNAVAILABLE:
         raise BackendNotAvailable()
     if status_code >= 500:
         raise BackendError()
     if status_code >= 400:
         raise UnknownError()
Пример #8
0
 async def _refresh_token(self):
     try:
         await self._get_access_token()
     except (BackendNotAvailable, BackendTimeout, BackendError, NetworkError):
         logging.warning("Failed to refresh token for independent reasons")
         raise
     except Exception:
         logging.exception("Failed to refresh token")
         self._access_token = None
         if self._auth_lost_callback:
             self._auth_lost_callback()
         raise AccessDenied()
Пример #9
0
    async def do_request(self,
                         method,
                         url,
                         data=None,
                         json=True,
                         headers=None,
                         ignore_failure=False):
        loop = asyncio.get_event_loop()
        if not headers:
            headers = self._authentication_client.session.headers
        try:
            if data is None:
                data = {}
            params = {
                "method": method,
                "url": url,
                "data": data,
                "timeout": self._authentication_client.timeout,
                "headers": headers
            }
            try:
                response = await loop.run_in_executor(
                    None,
                    functools.partial(
                        self._authentication_client.session.request, **params))
            except requests.Timeout:
                raise BackendTimeout()

            if not ignore_failure:
                if response.status_code == HTTPStatus.UNAUTHORIZED:
                    raise AuthenticationRequired()
                if response.status_code == HTTPStatus.FORBIDDEN:
                    raise AccessDenied()
                if response.status_code == HTTPStatus.SERVICE_UNAVAILABLE:
                    raise BackendNotAvailable()
                if response.status_code >= 500:
                    raise BackendError()
                if response.status_code >= 400:
                    raise UnknownError()

            if json:
                return response.json()
            else:
                return response

        except Exception as e:
            log.exception(
                f"Request exception: {str(e)}; url: {url}, method: {method}, data: {data}, headers: {headers}"
            )
            raise
Пример #10
0
    async def _do_request(self, method, url, *args, **kwargs):
        loop = asyncio.get_running_loop()
        r = await loop.run_in_executor(None, functools.partial(self.session.request, method, url, *args, **kwargs))
        log.info(f"{r.status_code}: response from endpoint {url}")

        if r.status_code in (HTTPStatus.UNAUTHORIZED, HTTPStatus.FORBIDDEN):
            raise AccessDenied()
        if r.status_code == HTTPStatus.SERVICE_UNAVAILABLE:
            raise BackendNotAvailable()
        if r.status_code >= 500:
            raise BackendError()
        if r.status_code >= 400:
            raise UnknownError()
        
        j = r.json()  # all ubi endpoints return jsons
        return j
Пример #11
0
    async def authenticate(self, stored_credentials=None):
        if not stored_credentials:
            self.create_task(self._steam_client.run(), "Run WebSocketClient")
            return next_step_response(START_URI.LOGIN, END_URI.LOGIN_FINISHED)

        if stored_credentials.get("cookies", []):
            logger.error(
                'Old http login flow is not unsupported. Please reconnect the plugin'
            )
            raise AccessDenied()

        self._user_info_cache.from_dict(stored_credentials)
        if 'games' in self.persistent_cache:
            self._games_cache.loads(self.persistent_cache['games'])

        steam_run_task = self.create_task(self._steam_client.run(),
                                          "Run WebSocketClient")
        connection_timeout = 30
        try:
            await asyncio.wait_for(self._user_info_cache.initialized.wait(),
                                   connection_timeout)
        except asyncio.TimeoutError:
            try:
                self.raise_websocket_errors()
            except BackendError as e:
                logging.info(
                    f"Unable to keep connection with steam backend {repr(e)}")
                raise
            except InvalidCredentials:
                logging.info("Invalid credentials during authentication")
                raise
            except Exception as e:
                logging.info(
                    f"Internal websocket exception caught during auth {repr(e)}"
                )
                raise
            else:
                logging.info(
                    f"Failed to initialize connection with steam client within {connection_timeout} seconds"
                )
                raise BackendTimeout()
            finally:
                await self.cancel_task(steam_run_task)

        self.store_credentials(self._user_info_cache.to_dict())
        return Authentication(self._user_info_cache.steam_id,
                              self._user_info_cache.persona_name)
Пример #12
0
async def test_refresh_access_token_success(http_request, http_client,
                                            create_json_response):
    http_request.side_effect = [
        create_json_response({"access_token": "token"})
    ]
    await http_client.authenticate({})
    assert http_request.call_count == 1

    http_request.reset_mock()
    http_request.side_effect = [
        AccessDenied(),
        create_json_response({"access_token": "new_token"}),
        create_json_response({})
    ]
    await http_client.get("http://test.com")
    assert http_request.call_count == 3
    headers = http_request.call_args_list[2][1]["headers"]
    assert headers.get("AuthToken") == "new_token"
Пример #13
0
    async def _authenticated_request(self,
                                     method,
                                     url,
                                     data=None,
                                     json=True,
                                     headers=None,
                                     ignore_failure=False):
        try:
            return await self.do_request(method, url, data, json, headers,
                                         ignore_failure)
        except:
            try:
                await self.refresh_cookies()
                self._authentication_client.refresh_credentials()

            except Exception:
                self._plugin.lost_authentication()
                raise AccessDenied()
            return await self.do_request(method, url, data, json, headers,
                                         ignore_failure)
Пример #14
0
    async def _request(self, method, *args, **kwargs):
        try:
            response = await self._session.request(method, *args, **kwargs)
        except asyncio.TimeoutError:
            raise BackendTimeout()
        except aiohttp.ClientConnectionError:
            raise NetworkError()
        logging.debug(f"Request response status: {response.status}")
        if response.status == HTTPStatus.UNAUTHORIZED:
            raise AuthenticationRequired()
        if response.status == HTTPStatus.FORBIDDEN:
            raise AccessDenied()
        if response.status == HTTPStatus.SERVICE_UNAVAILABLE:
            raise BackendNotAvailable()
        if response.status >= 500:
            raise BackendError()
        if response.status >= 400:
            raise UnknownError()

        return response
Пример #15
0
 def _auth_lost(self):
     if self._auth_lost_callback:
         self._auth_lost_callback()
     raise AccessDenied()