# Path: invenio_oauthclient/contrib/cern.py
# OAUTHCLIENT_CERN_SESSION_KEY = 'identity.cern_provides'
# 
# def account_info(remote, resp):
#     """Retrieve remote account information used to find local user."""
#     try:
#         return _account_info(remote, resp)
#     except OAuthCERNRejectedAccountError as e:
#         current_app.logger.warning(e.message, exc_info=True)
#         flash(_('CERN account not allowed.'), category='danger')
#         return redirect('/')
# 
# def disconnect_handler(remote, *args, **kwargs):
#     """Handle unlinking of remote account."""
#     _disconnect(remote, *args, **kwargs)
#     return redirect(url_for('invenio_oauthclient_settings.index'))
# 
# def fetch_extra_data(resource):
#     """Return a dict with extra data retrieved from cern oauth."""
#     person_id = resource.get('PersonID', [None])[0]
#     identity_class = resource.get('IdentityClass', [None])[0]
#     department = resource.get('Department', [None])[0]
# 
#     return dict(
#         person_id=person_id,
#         identity_class=identity_class,
#         department=department
#     )
# 
# def fetch_groups(groups):
#     """Prepare list of allowed group names.
# 
#     :param groups: The complete list of groups.
#     :returns: A filtered list of groups.
#     """
#     hidden_groups = current_app.config.get(
#         'OAUTHCLIENT_CERN_HIDDEN_GROUPS', OAUTHCLIENT_CERN_HIDDEN_GROUPS)
#     hidden_groups_re = current_app.config.get(
#         'OAUTHCLIENT_CERN_HIDDEN_GROUPS_RE',
#         OAUTHCLIENT_CERN_HIDDEN_GROUPS_RE)
#     groups = [group for group in groups if group not in hidden_groups]
#     filter_groups = []
#     for regexp in hidden_groups_re:
#         for group in groups:
#             if regexp.match(group):
#                 filter_groups.append(group)
#     groups = [group for group in groups if group not in filter_groups]
# 
#     return groups
# 
# def get_dict_from_response(response):
#     """Prepare new mapping with 'Value's groupped by 'Type'."""
#     result = {}
#     if getattr(response, '_resp') and response._resp.code > 400:
#         return result
# 
#     for i in response.data:
#         # strip the schema from the key
#         k = i['Type'].replace(REMOTE_APP_RESOURCE_SCHEMA, '')
#         result.setdefault(k, list())
#         result[k].append(i['Value'])
#     return result


from flask import g, session, url_for
from flask_security import login_user, logout_user
from flask_security.utils import hash_password
from helpers import get_state, mock_remote_get, mock_response
from six.moves.urllib_parse import parse_qs, urlparse
from invenio_oauthclient.contrib.cern import OAUTHCLIENT_CERN_SESSION_KEY, \
    account_info, disconnect_handler, fetch_extra_data, fetch_groups, \
    get_dict_from_response
    import re
    """Test a rejected request."""
    with app.test_client() as c:
        c.get(url_for('invenio_oauthclient.login', remote_app='cern'))
        resp = c.get(
            url_for('invenio_oauthclient.authorized',
                    remote_app='cern', error='access_denied',
                    error_description='User denied access',
                    state=get_state('cern')))
        assert resp.status_code in (301, 302)
        assert resp.location == 'http://localhost/'
        # Check message flash
        assert session['_flashes'][0][0] == 'info'


def test_account_info_not_allowed_account(app, example_cern):
    """Test account info extraction."""
    client = app.test_client()

    app.config['OAUTHCLIENT_CERN_ALLOWED_IDENTITY_CLASSES'] = [
        'another cern type'
    ]
    ioc = app.extensions['oauthlib.client']

    # Ensure remote apps have been loaded (due to before first request)
    client.get(url_for('invenio_oauthclient.login', remote_app='cern'))

    example_response, _, example_account_info = example_cern

    mock_remote_get(ioc, 'cern', example_response)


# Path: invenio_oauthclient/contrib/cern.py
# OAUTHCLIENT_CERN_SESSION_KEY = 'identity.cern_provides'
# 
# def account_info(remote, resp):
#     """Retrieve remote account information used to find local user."""
#     try:
#         return _account_info(remote, resp)
#     except OAuthCERNRejectedAccountError as e:
#         current_app.logger.warning(e.message, exc_info=True)
#         flash(_('CERN account not allowed.'), category='danger')
#         return redirect('/')
# 
# def disconnect_handler(remote, *args, **kwargs):
#     """Handle unlinking of remote account."""
#     _disconnect(remote, *args, **kwargs)
#     return redirect(url_for('invenio_oauthclient_settings.index'))
# 
# def fetch_extra_data(resource):
#     """Return a dict with extra data retrieved from cern oauth."""
#     person_id = resource.get('PersonID', [None])[0]
#     identity_class = resource.get('IdentityClass', [None])[0]
#     department = resource.get('Department', [None])[0]
# 
#     return dict(
#         person_id=person_id,
#         identity_class=identity_class,
#         department=department
#     )
# 
# def fetch_groups(groups):
#     """Prepare list of allowed group names.
# 
#     :param groups: The complete list of groups.
#     :returns: A filtered list of groups.
#     """
#     hidden_groups = current_app.config.get(
#         'OAUTHCLIENT_CERN_HIDDEN_GROUPS', OAUTHCLIENT_CERN_HIDDEN_GROUPS)
#     hidden_groups_re = current_app.config.get(
#         'OAUTHCLIENT_CERN_HIDDEN_GROUPS_RE',
#         OAUTHCLIENT_CERN_HIDDEN_GROUPS_RE)
#     groups = [group for group in groups if group not in hidden_groups]
#     filter_groups = []
#     for regexp in hidden_groups_re:
#         for group in groups:
#             if regexp.match(group):
#                 filter_groups.append(group)
#     groups = [group for group in groups if group not in filter_groups]
# 
#     return groups
# 
# def get_dict_from_response(response):
#     """Prepare new mapping with 'Value's groupped by 'Type'."""
#     result = {}
#     if getattr(response, '_resp') and response._resp.code > 400:
#         return result
# 
#     for i in response.data:
#         # strip the schema from the key
#         k = i['Type'].replace(REMOTE_APP_RESOURCE_SCHEMA, '')
#         result.setdefault(k, list())
#         result[k].append(i['Value'])
#     return result


# Path: tests/test_contrib_cern.py
from flask import g, session, url_for
from flask_security import login_user, logout_user
from flask_security.utils import hash_password
from helpers import get_state, mock_remote_get, mock_response
from six.moves.urllib_parse import parse_qs, urlparse
from invenio_oauthclient.contrib.cern import OAUTHCLIENT_CERN_SESSION_KEY, \
    account_info, disconnect_handler, fetch_extra_data, fetch_groups, \
    get_dict_from_response
    import re

    """Test a rejected request."""
    with app.test_client() as c:
        c.get(url_for('invenio_oauthclient.login', remote_app='cern'))
        resp = c.get(
            url_for('invenio_oauthclient.authorized',
                    remote_app='cern', error='access_denied',
                    error_description='User denied access',
                    state=get_state('cern')))
        assert resp.status_code in (301, 302)
        assert resp.location == 'http://localhost/'
        # Check message flash
        assert session['_flashes'][0][0] == 'info'


def test_account_info_not_allowed_account(app, example_cern):
    """Test account info extraction."""
    client = app.test_client()

    app.config['OAUTHCLIENT_CERN_ALLOWED_IDENTITY_CLASSES'] = [
        'another cern type'
    ]
    ioc = app.extensions['oauthlib.client']

    # Ensure remote apps have been loaded (due to before first request)
    client.get(url_for('invenio_oauthclient.login', remote_app='cern'))

    example_response, _, example_account_info = example_cern

    mock_remote_get(ioc, 'cern', example_response)


    resp = account_info(ioc.remote_apps['cern'], None)