# Path: invenio_oauthclient/errors.py
# class OAuthResponseError(OAuthError):
#     """Define response exception during OAuth process."""
# 
#     def __init__(self, message, remote, response):
#         """Initialize exception.
# 
#         :param message: Error message.
#         :param remote: Remote application.
#         :param response: OAuth response object.
#         """
#         super(OAuthResponseError, self).__init__(message, remote)
#         self.response = response
# 
# Path: invenio_oauthclient/handlers/utils.py
# def response_token_setter(remote, resp):
#     """Extract token from response and set it for the user.
# 
#     :param remote: The remote application.
#     :param resp: The response.
#     :raises invenio_oauthclient.errors.OAuthClientError: If authorization with
#         remote service failed.
#     :raises invenio_oauthclient.errors.OAuthResponseError: In case of bad
#         authorized request.
#     :returns: The token.
#     """
#     if resp is None:
#         raise OAuthRejectedRequestError('User rejected request.', remote, resp)
#     else:
#         if 'access_token' in resp:
#             return oauth2_token_setter(remote, resp)
#         elif 'oauth_token' in resp and 'oauth_token_secret' in resp:
#             return oauth1_token_setter(remote, resp)
#         elif 'error' in resp:
#             # Only OAuth2 specifies how to send error messages
#             raise OAuthClientError(
#                 'Authorization with remote service failed.', remote, resp,
#             )
#     raise OAuthResponseError('Bad OAuth authorized request', remote, resp)
# 
# def token_getter(remote, token=''):
#     """Retrieve OAuth access token.
# 
#     Used by flask-oauthlib to get the access token when making requests.
# 
#     :param remote: The remote application.
#     :param token: Type of token to get. Data passed from ``oauth.request()`` to
#         identify which token to retrieve. (Default: ``''``)
#     :returns: The token.
#     """
#     session_key = token_session_key(remote.name)
# 
#     if session_key not in session and current_user.is_authenticated:
#         # Fetch key from token store if user is authenticated, and the key
#         # isn't already cached in the session.
#         remote_token = RemoteToken.get(
#             current_user.get_id(),
#             remote.consumer_key,
#             token_type=token,
#         )
# 
#         if remote_token is None:
#             return None
# 
#         # Store token and secret in session
#         session[session_key] = remote_token.token()
# 
#     return session.get(session_key, None)
# 
# Path: invenio_oauthclient/utils.py
# def oauth_authenticate(client_id, user, require_existing_link=False):
#     """Authenticate an oauth authorized callback.
# 
#     :param client_id: The client id.
#     :param user: A user instance.
#     :param require_existing_link: If ``True``, check if remote account exists.
#         (Default: ``False``)
#     :returns: ``True`` if the user is successfully authenticated.
#     """
#     # Authenticate via the access token (access token used to get user_id)
#     if not requires_confirmation(user):
#         after_this_request(_commit)
#         if login_user(user, remember=False):
#             if require_existing_link:
#                 account = RemoteAccount.get(user.id, client_id)
#                 if account is None:
#                     logout_user()
#                     return False
#             return True
#     return False


import pytest
from invenio_oauthclient.errors import OAuthResponseError
from invenio_oauthclient.handlers import response_token_setter, token_getter
from invenio_oauthclient.models import RemoteToken
from invenio_oauthclient.utils import oauth_authenticate
    resp_oauth1 = {
        'name': 'Josiah Carberry',
        'expires_in': 3599,
        'oauth_token': 'test_access_token',
        'oauth_token_secret': 'test_refresh_token',
        'scope': '/authenticate',
        'token_type': 'bearer',
    }
    assert not response_token_setter(remote, resp_oauth1)

    # Bad request
    resp_bad = {
        'invalid': 'invalid',
    }
    with pytest.raises(OAuthResponseError):
        response_token_setter(remote, resp_bad)


def test_token_getter(remote, models_fixture, app):
    """Test token getter on response from OAuth server."""
    datastore = app.extensions['invenio-accounts'].datastore
    existing_email = 'existing@inveniosoftware.org'
    user = datastore.find_user(email=existing_email)

    # Missing RemoteToken
    oauth_authenticate('dev', user)
    assert not token_getter(remote)

    # Populated RemoteToken
    RemoteToken.create(user.id, 'testkey', 'mytoken', 'mysecret')

# Path: invenio_oauthclient/errors.py
# class OAuthResponseError(OAuthError):
#     """Define response exception during OAuth process."""
# 
#     def __init__(self, message, remote, response):
#         """Initialize exception.
# 
#         :param message: Error message.
#         :param remote: Remote application.
#         :param response: OAuth response object.
#         """
#         super(OAuthResponseError, self).__init__(message, remote)
#         self.response = response
# 
# Path: invenio_oauthclient/handlers/utils.py
# def response_token_setter(remote, resp):
#     """Extract token from response and set it for the user.
# 
#     :param remote: The remote application.
#     :param resp: The response.
#     :raises invenio_oauthclient.errors.OAuthClientError: If authorization with
#         remote service failed.
#     :raises invenio_oauthclient.errors.OAuthResponseError: In case of bad
#         authorized request.
#     :returns: The token.
#     """
#     if resp is None:
#         raise OAuthRejectedRequestError('User rejected request.', remote, resp)
#     else:
#         if 'access_token' in resp:
#             return oauth2_token_setter(remote, resp)
#         elif 'oauth_token' in resp and 'oauth_token_secret' in resp:
#             return oauth1_token_setter(remote, resp)
#         elif 'error' in resp:
#             # Only OAuth2 specifies how to send error messages
#             raise OAuthClientError(
#                 'Authorization with remote service failed.', remote, resp,
#             )
#     raise OAuthResponseError('Bad OAuth authorized request', remote, resp)
# 
# def token_getter(remote, token=''):
#     """Retrieve OAuth access token.
# 
#     Used by flask-oauthlib to get the access token when making requests.
# 
#     :param remote: The remote application.
#     :param token: Type of token to get. Data passed from ``oauth.request()`` to
#         identify which token to retrieve. (Default: ``''``)
#     :returns: The token.
#     """
#     session_key = token_session_key(remote.name)
# 
#     if session_key not in session and current_user.is_authenticated:
#         # Fetch key from token store if user is authenticated, and the key
#         # isn't already cached in the session.
#         remote_token = RemoteToken.get(
#             current_user.get_id(),
#             remote.consumer_key,
#             token_type=token,
#         )
# 
#         if remote_token is None:
#             return None
# 
#         # Store token and secret in session
#         session[session_key] = remote_token.token()
# 
#     return session.get(session_key, None)
# 
# Path: invenio_oauthclient/utils.py
# def oauth_authenticate(client_id, user, require_existing_link=False):
#     """Authenticate an oauth authorized callback.
# 
#     :param client_id: The client id.
#     :param user: A user instance.
#     :param require_existing_link: If ``True``, check if remote account exists.
#         (Default: ``False``)
#     :returns: ``True`` if the user is successfully authenticated.
#     """
#     # Authenticate via the access token (access token used to get user_id)
#     if not requires_confirmation(user):
#         after_this_request(_commit)
#         if login_user(user, remember=False):
#             if require_existing_link:
#                 account = RemoteAccount.get(user.id, client_id)
#                 if account is None:
#                     logout_user()
#                     return False
#             return True
#     return False


# Path: tests/test_base_handlers.py
import pytest
from invenio_oauthclient.errors import OAuthResponseError
from invenio_oauthclient.handlers import response_token_setter, token_getter
from invenio_oauthclient.models import RemoteToken
from invenio_oauthclient.utils import oauth_authenticate

    resp_oauth1 = {
        'name': 'Josiah Carberry',
        'expires_in': 3599,
        'oauth_token': 'test_access_token',
        'oauth_token_secret': 'test_refresh_token',
        'scope': '/authenticate',
        'token_type': 'bearer',
    }
    assert not response_token_setter(remote, resp_oauth1)

    # Bad request
    resp_bad = {
        'invalid': 'invalid',
    }
    with pytest.raises(OAuthResponseError):
        response_token_setter(remote, resp_bad)


def test_token_getter(remote, models_fixture, app):
    """Test token getter on response from OAuth server."""
    datastore = app.extensions['invenio-accounts'].datastore
    existing_email = 'existing@inveniosoftware.org'
    user = datastore.find_user(email=existing_email)

    # Missing RemoteToken
    oauth_authenticate('dev', user)
    assert not token_getter(remote)

    # Populated RemoteToken
    RemoteToken.create(user.id, 'testkey', 'mytoken', 'mysecret')

    oauth_authenticate('dev', user)