Ejemplo n.º 1
0
def test_record_restricted_api_read(app, api_client, user_info, status):
    """Test permissions of a restricted record through the API."""

    if user_info:
        login_user_via_session(api_client, email=user_info['email'])

    assert api_client.get('/literature/1090628').status_code == status
Ejemplo n.º 2
0
def test_record_public_detailed_read(app, app_client, user_info, status):
    """Test that a record can be read by everybody through web interface."""
    if user_info:
        # Login as user
        login_user_via_session(app_client, email=user_info['email'])

    assert app_client.get('/literature/111').status_code == status
Ejemplo n.º 3
0
def edit_workflow(workflow_app):
    app_client = workflow_app.test_client()
    user = User.query.filter_by(email='*****@*****.**').one()
    login_user_via_session(app_client, user=user)

    record = {
        '$schema': 'http://localhost:5000/schemas/records/hep.json',
        'arxiv_eprints': [
            {
                'categories': [
                    'nucl-th'
                ],
                'value': '1802.03287'
            }
        ],
        'control_number': 123,
        'document_type': ['article'],
        'titles': [{'title': 'Resource Pooling in Large-Scale Content Delivery Systems'}],
        'self': {'$ref': 'http://localhost:5000/schemas/records/hep.json'},
        '_collections': ['Literature']
    }
    factory = TestRecordMetadata.create_from_kwargs(json=record)
    eng_uuid = start('edit_article', data=factory.record_metadata.json)
    obj = WorkflowEngine.from_uuid(eng_uuid).objects[0]

    assert obj.status == ObjectStatus.WAITING
    assert obj.extra_data['callback_url']
    return obj
Ejemplo n.º 4
0
def test_record_public_api_read(app, app_client, user_info, status):
    """Test that a record can be read by everybody through the API."""
    if user_info:
        # Login as user
        login_user_via_session(app_client, email=user_info['email'])

    assert app_client.get('/old-literature/1497201').status_code == status
Ejemplo n.º 5
0
def test_edit_article_callback_redirects_to_rt(
    edit_workflow,
    workflow_api_client,
    mocked_external_services,
    workflow_app,
):
    user_info = {'email': '*****@*****.**'}

    login_user_via_session(workflow_api_client, email=user_info['email'])

    edit_workflow.extra_data['curation_ticket_id'] = 1234
    payload = {
        "_id": edit_workflow.id,
        "_extra_data": edit_workflow.extra_data,
        "metadata": edit_workflow.data,
    }
    response = workflow_api_client.put(
        edit_workflow.extra_data['callback_url'],
        data=json.dumps(payload),
        content_type='application/json',
    )

    expected_redirect = get_rt_link_for_ticket(1234)

    assert response.status_code == 200
    data = json.loads(response.data)
    assert 'redirect_url' in data
    assert data['redirect_url'] == expected_redirect
Ejemplo n.º 6
0
def test_responses_with_etag(workflow_app):

    factory = TestRecordMetadata.create_from_kwargs(
        json={'titles': [{'title': 'Etag version'}]}
    )

    workflow_id = build_workflow(factory.record_metadata.json).id
    obj = workflow_object_class.get(workflow_id)
    obj.save()
    db.session.commit()

    workflow_url = '/api/holdingpen/{}'.format(obj.id)

    with workflow_app.test_client() as client:
        login_user_via_session(client, email='*****@*****.**')
        response = client.get(workflow_url)
        assert response.status_code == 200

        etag = response.headers['ETag']
        last_modified = response.headers['Last-Modified']

        response = client.get(
            workflow_url, headers={'If-Modified-Since': last_modified})
        assert response.status_code == 304

        response = client.get(workflow_url, headers={'If-None-Match': etag})
        assert response.status_code == 304

        response = client.get(workflow_url, headers={'If-None-Match': 'Jessica Jones'})
        assert response.status_code == 200
Ejemplo n.º 7
0
def test_load_user_collections(app_client, user_info, collections):
    if user_info:
        login_user_via_session(app_client, email=user_info['email'])

    with app_client.get('/'):
        assert 'restricted_collection' not in session
        load_user_collections(current_app, current_user)
        assert session['restricted_collections'] == collections
Ejemplo n.º 8
0
def log_in_as_cataloger(api_client):
    """Ensure that we're logged in as a privileged user."""
    login_user_via_session(api_client, email='*****@*****.**')

    yield

    SessionActivity.query.delete()
    db.session.commit()
Ejemplo n.º 9
0
def log_in_as_scientist(api_client):
    """Ensure that we're logged in as an unprivileged user."""
    login_user_via_session(api_client, email='*****@*****.**')

    yield

    SessionActivity.query.delete()
    db.session.commit()
Ejemplo n.º 10
0
def test_record_restricted_detailed_read(app, app_client, user_info, status):
    """Test permissions of restricted record accessing detailed view."""

    if user_info:
        # Login as user
        login_user_via_session(app_client, email=user_info['email'])

    assert app_client.get('/old-literature/1090628').status_code == status
Ejemplo n.º 11
0
def test_record_public_detailed_read(app, sample_record, users, user_info, status):
    """Test that a record can be read by everybody through web interface."""
    with app.test_client() as client:
        if user_info:
            # Login as user
            login_user_via_session(client, email=user_info['email'])

        assert client.get("/literature/123").status_code == status
Ejemplo n.º 12
0
def test_record_api_update(app, api_client, sample_record, user_info, status):
    """Test that a record can be updated only from admin
       and cataloger users through the API."""
    if user_info:
        login_user_via_session(api_client, email=user_info['email'])
    resp = api_client.put('/literature/111/db',
                          data=json.dumps(sample_record.dumps()),
                          content_type='application/json')
    assert resp.status_code == status
Ejemplo n.º 13
0
def test_record_restricted_detailed_read(app, restricted_record, users, user_info, status):
    """Test permissions of restricted record accessing detailed view."""

    with app.test_client() as client:
        if user_info:
            # Login as user
            login_user_via_session(client, email=user_info['email'])

        assert client.get("/literature/222").status_code == status
Ejemplo n.º 14
0
def test_edit_article_view(workflow_api_client):
    login_user_via_session(workflow_api_client, email='*****@*****.**')

    factory = TestRecordMetadata.create_from_kwargs(json={})
    control_number = factory.record_metadata.json['control_number']
    endpoint_url = "/workflows/edit_article/{}".format(control_number)

    response = workflow_api_client.get(endpoint_url)
    assert response.status_code == 302
    assert "/editor/holdingpen/" in response.headers['Location']
Ejemplo n.º 15
0
def test_login_user_via_session(app):
    """Test the login-via-view function/hack."""
    email = '*****@*****.**'
    password = '******'

    with app.app_context():
        user = testutils.create_test_user(email, password)
        with app.test_client() as client:
            assert not testutils.client_authenticated(client)
            testutils.login_user_via_session(client, email=user.email)
            assert testutils.client_authenticated(client)
Ejemplo n.º 16
0
def test_record_api_update_restricted_record(app, api_client, user_info, status):
    """Test that a restricted record can be updated only by
       users with the right permission."""
    if user_info:
        login_user_via_session(api_client, email=user_info['email'])

    record = get_db_record('lit', 1090628)

    resp = api_client.put('/literature/1090628',
                          data=json.dumps(record),
                          content_type='application/json')
    assert resp.status_code == status
Ejemplo n.º 17
0
def test_edit_article_view_sets_user_id(workflow_api_client):
    user = User.query.filter_by(email='*****@*****.**').one()
    login_user_via_session(workflow_api_client, user=user)

    factory = TestRecordMetadata.create_from_kwargs(json={})
    control_number = factory.record_metadata.json['control_number']
    endpoint_url = "/workflows/edit_article/{}".format(control_number)

    response = workflow_api_client.get(endpoint_url)
    wflw_id = response.headers['Location'].split('/')[-1]
    wflw = workflow_object_class.get(wflw_id)

    assert wflw.id_user == int(user.get_id())
Ejemplo n.º 18
0
def test_index_new(app, test_client, users):
    """Test index view."""
    with app.test_request_context():
        index_url = url_for('invenio_deposit_ui.index')
        new_url = url_for('invenio_deposit_ui.new')

    for u in [index_url, new_url]:
        res = test_client.get(u)
        assert res.status_code == 302
        assert '/login/' in res.location

    login_user_via_session(test_client, user=users[0])
    for u in [index_url, new_url]:
        assert test_client.get(u).status_code == 200
Ejemplo n.º 19
0
def _call_workflow_resolve_api(app, workflow_id, data):
    """Calls to the workflow resolve endpoint.

    :param app: flask app to use
    :param workflow_id: id of the workflow to accept.
    :param action: action taken (normally on of 'reject', accept_core',
    'accept')
    """
    client = app.test_client()
    login_user_via_session(client, email='*****@*****.**')
    return client.post(
        '/api/holdingpen/%s/action/resolve' % workflow_id,
        data=json.dumps(data),
        content_type='application/json',
    )
Ejemplo n.º 20
0
def test_rejected(views_fixture, monkeypatch):
    """Test rejected."""
    # Mock session id
    monkeypatch.setattr('invenio_oauthclient._compat._create_identifier',
                        lambda: '1234')
    monkeypatch.setattr(
        'invenio_oauthclient.views.client._create_identifier', lambda: '1234')

    app = views_fixture
    oauth = app.extensions['oauthlib.client']

    # Mock user id
    user = MagicMock()
    user.get_id = MagicMock(return_value=1)
    user.is_authenticated = MagicMock(return_value=True)

    with app.test_client() as c:
        login_user_via_session(c, user)
        # First call login to be redirected
        res = c.get(url_for('invenio_oauthclient.login',
                            remote_app='full'))
        assert res.status_code == 302
        assert res.location.startswith(
            oauth.remote_apps['full'].authorize_url
        )

        # Mock response to imitate an invalid response. Here, an
        # example from GitHub when the code is expired.
        mock_response(app.extensions['oauthlib.client'], 'full', data=dict(
            error_uri='http://developer.github.com/v3/oauth/'
            '#bad-verification-code',
            error_description='The code passed is '
            'incorrect or expired.',
            error='bad_verification_code',
        ))

        # Imitate that the user authorized our request in the remote
        # application (however, the remote app will son reply with an
        # error)
        state = serializer.dumps({
            'app': 'full', 'sid': '1234',  'next': None,
        })

        res = c.get(url_for(
            'invenio_oauthclient.authorized', remote_app='full',
            code='test', state=state
        ))
        assert res.status_code == 302
Ejemplo n.º 21
0
def test_edit_article_start_permission(
    workflow_app,
    workflow_api_client,
    user_info,
    expected_status_code,
    mocked_external_services,
):
    if user_info:
        login_user_via_session(workflow_api_client, email=user_info['email'])

    factory = TestRecordMetadata.create_from_kwargs(json={})
    control_number = factory.record_metadata.json['control_number']
    endpoint_url = "/workflows/edit_article/{}".format(control_number)

    response = workflow_api_client.get(endpoint_url)
    assert response.status_code == expected_status_code
def test_all_records_are_there(app_client):
    # Use superadmin user to ensure we can visit all records
    login_user_via_session(app_client, email='*****@*****.**')

    failed = []
    for record in [record.json for record in RecordMetadata.query.all()]:
        try:
            absolute_url = record['self']['$ref']
            relative_url = absolute_url.partition('api')[2]
            response = app_client.get(relative_url)

            assert response.status_code == 200
        except Exception:
            failed.append(record['control_number'])

    assert failed == []
Ejemplo n.º 23
0
def test_edit_article_view_sets_curation_ticket_if_referrer_is_rt_ticket(workflow_api_client):
    login_user_via_session(workflow_api_client, email='*****@*****.**')

    factory = TestRecordMetadata.create_from_kwargs(json={})
    control_number = factory.record_metadata.json['control_number']
    endpoint_url = "/workflows/edit_article/{}".format(control_number)

    response = workflow_api_client.get(
        endpoint_url,
        headers={'Referer': get_rt_link_for_ticket(1234)}
    )
    assert response.status_code == 302
    assert "/editor/holdingpen/" in response.headers['Location']

    wflw_id = response.headers['Location'].split('/')[-1]
    wflw = workflow_object_class.get(wflw_id)
    assert wflw.extra_data.get('curation_ticket_id') == 1234
def test_holdingpen_author_views_access(app, app_client, users):
    """Check permissions of author related views."""
    # An anonymous user is redirected to login page
    res = app_client.get(url_for('inspirehep_authors.newreview'))
    assert res.status_code == 302
    assert 'login' in res.location

    res = app_client.post(
        url_for('inspirehep_authors.reviewhandler'))
    assert res.status_code == 302
    assert 'login' in res.location

    res = app_client.get(
        url_for('inspirehep_authors.holdingpenreview'))
    assert res.status_code == 302
    assert 'login' in res.location

    # Logged-in user with no permission should receive 403
    login_user_via_session(app_client, email='*****@*****.**')

    res = app_client.get(url_for('inspirehep_authors.newreview'))
    assert res.status_code == 403

    res = app_client.post(
        url_for('inspirehep_authors.reviewhandler'))
    assert res.status_code == 403

    res = app_client.get(
        url_for('inspirehep_authors.holdingpenreview'))
    assert res.status_code == 403

    # User with admin-holdingpen-authors action allowed can access
    # XXX: 400 is returned because no object id is passed to the views
    login_user_via_session(app_client, email='*****@*****.**')

    res = app_client.get(url_for('inspirehep_authors.newreview'))
    assert res.status_code == 400

    res = app_client.post(
        url_for('inspirehep_authors.reviewhandler'))
    assert res.status_code == 400

    res = app_client.get(
        url_for('inspirehep_authors.holdingpenreview'))
    assert res.status_code == 400
def test_headers_info(app, users):
    """Test if session and user id is set response header."""
    u = users[0]
    url = url_for_security('change_password')
    with app.app_context():
        with app.test_client() as client:
            response = client.get(url)
            # Not logged in, so only session id available
            assert not testutils.client_authenticated(client)
            assert 'X-Session-ID' in response.headers
            assert 'X-User-ID' not in response.headers
            # Login
            testutils.login_user_via_session(client, email=u['email'])
            response = client.get(url)
            cookie = requests.utils.dict_from_cookiejar(client.cookie_jar)
            assert response.headers['X-Session-ID'] == \
                cookie['session'].split('.')[0]
            assert int(response.headers['X-User-ID']) == u['id']
Ejemplo n.º 26
0
def test_edit_article_callback_permission(
    user_info,
    expected_status_code,
    edit_workflow,
    workflow_api_client,
    mocked_external_services,
):
    if user_info:
        login_user_via_session(workflow_api_client, email=user_info['email'])
    else:
        with workflow_api_client.session_transaction() as sess:
            sess['user_id'] = None

    payload = {
        "_id": edit_workflow.id,
        "_extra_data": edit_workflow.extra_data,
        "metadata": edit_workflow.data,
    }
    response = workflow_api_client.put(
        edit_workflow.extra_data['callback_url'],
        data=json.dumps(payload),
        content_type='application/json'
    )
    assert response.status_code == expected_status_code
Ejemplo n.º 27
0
def test_tombstone(app, app_client, deposit, deposit_file, users):
    """Test tombstone for edit pages."""
    with app.test_request_context():
        record_url = url_for(
            'invenio_records_ui.recid', pid_value=deposit['_deposit']['id'])
        deposit_url = url_for(
            'invenio_deposit_ui.depid', pid_value=deposit['_deposit']['id'])
        delete_url = url_for(
            'zenodo_deposit.delete', pid_value=deposit['_deposit']['id'])

    deposit.publish()
    recid, record = deposit.fetch_published()
    recid.delete()
    deposit.pid.delete()

    assert app_client.post(record_url).status_code == 302
    assert app_client.get(delete_url).status_code == 302
    assert app_client.get(deposit_url).status_code == 410
    login_user_via_session(app_client, email=users[0]['email'])
    assert app_client.post(record_url).status_code == 410
    assert app_client.get(deposit_url).status_code == 410
    assert app_client.get(delete_url).status_code == 410
    login_user_via_session(app_client, email=users[2]['email'])
    assert app_client.get(delete_url).status_code == 410
Ejemplo n.º 28
0
def test_edit_article_callback_does_not_have_redirect_url_if_no_ticket_id(
    edit_workflow,
    workflow_api_client,
    mocked_external_services,
    workflow_app,
):
    user_info = {'email': '*****@*****.**'}

    login_user_via_session(workflow_api_client, email=user_info['email'])

    payload = {
        "_id": edit_workflow.id,
        "_extra_data": edit_workflow.extra_data,
        "metadata": edit_workflow.data,
    }
    response = workflow_api_client.put(
        edit_workflow.extra_data['callback_url'],
        data=json.dumps(payload),
        content_type='application/json',
    )

    assert response.status_code == 200
    data = json.loads(response.data)
    assert 'redirect_url' not in data
Ejemplo n.º 29
0
def test_deposit_ui_login(app, app_client, deposit, deposit_file, users):
    """Test login on deposit views."""
    with app.test_request_context():
        record_url = url_for(
            'invenio_records_ui.recid', pid_value=deposit['_deposit']['id'])
        delete_url = url_for(
            'zenodo_deposit.delete', pid_value=deposit['_deposit']['id'])
        deposit_url = url_for(
            'invenio_deposit_ui.depid', pid_value=deposit['_deposit']['id'])
        new_url = url_for('invenio_deposit_ui.new')
        index_url = url_for('invenio_deposit_ui.index')

    # Unauthenticated users
    assert app_client.get(index_url).status_code == 302
    assert app_client.get(new_url).status_code == 302
    assert app_client.get(deposit_url).status_code == 302
    assert app_client.get(delete_url).status_code == 302
    deposit.publish()
    assert app_client.get(record_url).status_code == 200
    assert app_client.post(record_url).status_code == 302

    # Login user NOT owner of deposit
    login_user_via_session(app_client, email=users[1]['email'])

    # Can list deposits, create new, and view record.
    assert app_client.get(index_url).status_code == 200
    assert app_client.get(new_url).status_code == 200
    assert app_client.get(record_url).status_code == 200

    # - cannot view deposit or put record in edit mode
    assert app_client.get(deposit_url).status_code == 403
    assert app_client.post(record_url).status_code == 403
    assert app_client.get(delete_url).status_code == 403

    # Login owner of deposit
    login_user_via_session(app_client, email=users[0]['email'])

    # - can view deposit or put record in edit mode
    res = app_client.post(record_url)
    assert res.status_code == 302
    assert 'login' not in res.location
    assert app_client.get(deposit_url).status_code == 200
    assert app_client.get(delete_url).status_code == 403

    login_user_via_session(app_client, email=users[2]['email'])
Ejemplo n.º 30
0
def _login(client, user, users):
    """Login user and return url."""
    login_user_via_session(client, user=User.query.get(user.id))
    return user
Ejemplo n.º 31
0
def test_update(client, make_user, superuser, admin, moderator, submitter,
                user):
    """Test update users permissions."""
    headers = {
        'Content-Type': 'application/json',
        'Accept': 'application/json'
    }

    # Not logged
    res = client.put(url_for('invenio_records_rest.user_item',
                             pid_value=user['pid']),
                     data=json.dumps(user.dumps()),
                     headers=headers)
    assert res.status_code == 401

    # Logged as user and update himself
    login_user_via_session(client, email=user['email'])
    res = client.put(url_for('invenio_records_rest.user_item',
                             pid_value=user['pid']),
                     data=json.dumps(user.dumps()),
                     headers=headers)
    assert res.status_code == 200

    # Logged as user and update other
    login_user_via_session(client, email=user['email'])
    res = client.put(url_for('invenio_records_rest.user_item',
                             pid_value=moderator['pid']),
                     data=json.dumps(moderator.dumps()),
                     headers=headers)
    assert res.status_code == 403

    # Logged as submitter
    login_user_via_session(client, email=submitter['email'])
    res = client.put(url_for('invenio_records_rest.user_item',
                             pid_value=submitter['pid']),
                     data=json.dumps(submitter.dumps()),
                     headers=headers)
    assert res.status_code == 200

    login_user_via_session(client, email=submitter['email'])
    res = client.put(url_for('invenio_records_rest.user_item',
                             pid_value=user['pid']),
                     data=json.dumps(user.dumps()),
                     headers=headers)
    assert res.status_code == 403

    # Logged as moderator
    login_user_via_session(client, email=moderator['email'])
    res = client.put(url_for('invenio_records_rest.user_item',
                             pid_value=moderator['pid']),
                     data=json.dumps(moderator.dumps()),
                     headers=headers)
    assert res.status_code == 200

    login_user_via_session(client, email=moderator['email'])
    res = client.put(url_for('invenio_records_rest.user_item',
                             pid_value=user['pid']),
                     data=json.dumps(user.dumps()),
                     headers=headers)
    assert res.status_code == 403

    # Logged as admin
    login_user_via_session(client, email=admin['email'])
    res = client.put(url_for('invenio_records_rest.user_item',
                             pid_value=user['pid']),
                     data=json.dumps(user.dumps()),
                     headers=headers)
    assert res.status_code == 200

    # Logged as admin, try to update super user
    login_user_via_session(client, email=admin['email'])
    res = client.put(url_for('invenio_records_rest.user_item',
                             pid_value=superuser['pid']),
                     data=json.dumps(superuser.dumps()),
                     headers=headers)
    assert res.status_code == 403

    # Logged as admin of other organisation
    other_admin = make_user('admin', 'org2')
    login_user_via_session(client, email=other_admin['email'])
    res = client.put(url_for('invenio_records_rest.user_item',
                             pid_value=user['pid']),
                     data=json.dumps(user.dumps()),
                     headers=headers)
    assert res.status_code == 403

    # Logged as superuser
    login_user_via_session(client, email=superuser['email'])
    res = client.put(url_for('invenio_records_rest.user_item',
                             pid_value=user['pid']),
                     data=json.dumps(user.dumps()),
                     headers=headers)
    assert res.status_code == 200
Ejemplo n.º 32
0
def test_create(client, organisation, superuser, admin, moderator, submitter,
                user):
    """Test create users permissions."""
    headers = {
        'Content-Type': 'application/json',
        'Accept': 'application/json'
    }

    user_json = {
        'email': '*****@*****.**',
        'full_name': 'User',
        'roles': ['user']
    }

    # Not logged
    res = client.post(url_for('invenio_records_rest.user_list'),
                      data=json.dumps(user_json),
                      headers=headers)
    assert res.status_code == 401

    # User
    login_user_via_session(client, email=user['email'])
    res = client.post(url_for('invenio_records_rest.user_list'),
                      data=json.dumps(user_json),
                      headers=headers)
    assert res.status_code == 403

    # submitter
    login_user_via_session(client, email=submitter['email'])
    res = client.post(url_for('invenio_records_rest.user_list'),
                      data=json.dumps(user_json),
                      headers=headers)
    assert res.status_code == 403

    # Moderator
    login_user_via_session(client, email=moderator['email'])
    res = client.post(url_for('invenio_records_rest.user_list'),
                      data=json.dumps(user_json),
                      headers=headers)
    assert res.status_code == 403

    # Admin
    login_user_via_session(client, email=admin['email'])
    res = client.post(url_for('invenio_records_rest.user_list'),
                      data=json.dumps(user_json),
                      headers=headers)
    assert res.status_code == 201
    assert res.json['metadata']['organisation'][
        '$ref'] == 'https://sonar.ch/api/organisations/org'

    # Super user
    user_json['organisation'] = {
        '$ref':
        'https://sonar.ch/api/organisations/{organisation}'.format(
            organisation=organisation['pid'])
    }

    login_user_via_session(client, email=superuser['email'])
    res = client.post(url_for('invenio_records_rest.user_list'),
                      data=json.dumps(user_json),
                      headers=headers)
    assert res.status_code == 201
    assert res.json['metadata']['organisation'][
        '$ref'] == 'https://sonar.ch/api/organisations/org'
Ejemplo n.º 33
0
def test_items_automatic_checkin(client, librarian_martigny_no_email,
                                 patron_martigny_no_email, loc_public_martigny,
                                 item_type_standard_martigny, loc_public_saxon,
                                 item_lib_martigny, json_header,
                                 circulation_policies):
    """Test automatic checkin for items."""
    login_user_via_session(client, librarian_martigny_no_email.user)
    item = item_lib_martigny
    item_pid = item.pid
    patron_pid = patron_martigny_no_email.pid
    location = loc_public_martigny

    # loose item
    res, _ = postdata(client, 'api_item.lose', dict(item_pid=item_pid))
    assert res.status_code == 200

    # return missing item
    res, data = postdata(client, 'api_item.automatic_checkin',
                         dict(item_barcode=item.get('barcode')))
    assert res.status_code == 200
    item_data = data.get('metadata')
    actions = data.get('action_applied')
    assert item_data.get('status') == ItemStatus.ON_SHELF
    assert LoanAction.RETURN_MISSING in actions

    # checkout
    res, data = postdata(client, 'api_item.checkout',
                         dict(item_pid=item_pid, patron_pid=patron_pid))
    assert res.status_code == 200
    actions = data.get('action_applied')
    loan_pid = actions[LoanAction.CHECKOUT].get('pid')

    # checkin
    res, data = postdata(
        client, 'api_item.checkin',
        dict(item_pid=item_pid,
             pid=loan_pid,
             transaction_location_pid=loc_public_saxon.pid))
    assert res.status_code == 200
    item_data = data.get('metadata')
    actions = data.get('action_applied')
    assert item_data.get('status') == ItemStatus.IN_TRANSIT
    assert LoanAction.CHECKIN in actions

    # receive
    res, data = postdata(
        client, 'api_item.automatic_checkin',
        dict(item_pid=item_pid,
             pid=loan_pid,
             transaction_location_pid=loc_public_martigny.pid))
    assert res.status_code == 200
    item_data = data.get('metadata')
    actions = data.get('action_applied')
    assert item_data.get('status') == ItemStatus.ON_SHELF
    assert LoanAction.RECEIVE in actions

    # checkout
    res, _ = postdata(client, 'api_item.checkout',
                      dict(item_pid=item_pid, patron_pid=patron_pid))
    assert res.status_code == 200

    # checkin
    res, data = postdata(client, 'api_item.automatic_checkin',
                         dict(item_barcode=item.get('barcode')))
    assert res.status_code == 200
    item_data = data.get('metadata')
    actions = data.get('action_applied')
    assert item_data.get('status') == ItemStatus.ON_SHELF
    assert LoanAction.CHECKIN in actions
Ejemplo n.º 34
0
def test_delete(client, db, make_deposit, superuser, admin, moderator,
                submitter, user):
    """Test delete deposits permissions."""
    deposit1 = make_deposit('submitter', 'org')
    deposit2 = make_deposit('submitter', 'org2')

    # Not logged
    res = client.delete(
        url_for('invenio_records_rest.depo_item', pid_value=deposit1['pid']))
    assert res.status_code == 401

    # Logged as user
    login_user_via_session(client, email=user['email'])
    res = client.delete(
        url_for('invenio_records_rest.depo_item', pid_value=deposit1['pid']))
    assert res.status_code == 403

    # Logged as submitter
    login_user_via_session(client, email=submitter['email'])
    res = client.delete(
        url_for('invenio_records_rest.depo_item', pid_value=deposit2['pid']))
    assert res.status_code == 403

    deposit1['status'] = DepositRecord.STATUS_VALIDATED
    deposit1.commit()
    db.session.commit()

    res = client.delete(
        url_for('invenio_records_rest.depo_item', pid_value=deposit1['pid']))
    assert res.status_code == 403

    deposit1['status'] = DepositRecord.STATUS_IN_PROGRESS
    deposit1.commit()
    db.session.commit()

    res = client.delete(
        url_for('invenio_records_rest.depo_item', pid_value=deposit1['pid']))
    assert res.status_code == 204

    deposit1 = make_deposit('submitter', 'org')

    # Logged as moderator
    login_user_via_session(client, email=moderator['email'])
    res = client.delete(
        url_for('invenio_records_rest.depo_item', pid_value=deposit2['pid']))
    assert res.status_code == 403

    res = client.delete(
        url_for('invenio_records_rest.depo_item', pid_value=deposit1['pid']))
    assert res.status_code == 204

    deposit1 = make_deposit('submitter', 'org')

    # Logged as admin
    login_user_via_session(client, email=admin['email'])
    res = client.delete(
        url_for('invenio_records_rest.depo_item', pid_value=deposit2['pid']))
    assert res.status_code == 403

    res = client.delete(
        url_for('invenio_records_rest.depo_item', pid_value=deposit1['pid']))
    assert res.status_code == 204

    deposit1 = make_deposit('submitter', 'org')

    # Logged as superuser
    login_user_via_session(client, email=superuser['email'])
    res = client.delete(
        url_for('invenio_records_rest.depo_item', pid_value=deposit1['pid']))
    assert res.status_code == 204
Ejemplo n.º 35
0
def test_read(client, db, make_deposit, make_user, superuser, admin, moderator,
              submitter, user, subdivision, subdivision2):
    """Test read deposits permissions."""
    deposit1 = make_deposit('submitter', 'org')
    deposit2 = make_deposit('submitter', 'org2')

    # Not logged
    res = client.get(
        url_for('invenio_records_rest.depo_item', pid_value=deposit1['pid']))
    assert res.status_code == 401

    # Logged as user
    login_user_via_session(client, email=user['email'])
    res = client.get(
        url_for('invenio_records_rest.depo_item', pid_value=deposit1['pid']))
    assert res.status_code == 403

    # Logged as submitter
    login_user_via_session(client, email=submitter['email'])
    res = client.get(
        url_for('invenio_records_rest.depo_item', pid_value=deposit1['pid']))
    assert res.status_code == 200

    res = client.get(
        url_for('invenio_records_rest.depo_item', pid_value=deposit2['pid']))
    assert res.status_code == 403

    # Logged as moderator
    login_user_via_session(client, email=moderator['email'])
    res = client.get(
        url_for('invenio_records_rest.depo_item', pid_value=deposit1['pid']))
    assert res.status_code == 200

    # Moderator has subdivision, I can read a deposit of my subdivision
    sub_pid = deposit1["diffusion"]["subdivisions"][0]["$ref"].split('/')[-1]
    moderator['subdivision'] = {
        '$ref': f'https://sonar.ch/api/subdivisions/{sub_pid}'
    }
    moderator.commit()
    moderator.reindex()
    db.session.commit()
    res = client.get(
        url_for('invenio_records_rest.depo_item', pid_value=deposit1['pid']))
    assert res.status_code == 200

    # Moderator has subdivision, I cannot read deposit outside of his
    # subdivision
    moderator['subdivision'] = {
        '$ref': f'https://sonar.ch/api/subdivisions/{subdivision2["pid"]}'
    }
    moderator.commit()
    moderator.reindex()
    db.session.commit()
    res = client.get(
        url_for('invenio_records_rest.depo_item', pid_value=deposit1['pid']))
    assert res.status_code == 403

    # Cannot read deposit of other organisations
    res = client.get(
        url_for('invenio_records_rest.depo_item', pid_value=deposit2['pid']))
    assert res.status_code == 403

    # Logged as admin
    login_user_via_session(client, email=admin['email'])
    res = client.get(
        url_for('invenio_records_rest.depo_item', pid_value=deposit1['pid']))
    assert res.status_code == 200

    # Cannot read deposit of other organisations
    res = client.get(
        url_for('invenio_records_rest.depo_item', pid_value=deposit2['pid']))
    assert res.status_code == 403

    # Logged as admin of other organisation
    other_admin = make_user('admin', 'org2')
    login_user_via_session(client, email=other_admin['email'])
    res = client.get(
        url_for('invenio_records_rest.depo_item', pid_value=deposit1['pid']))
    assert res.status_code == 403

    # Logged as superuser
    login_user_via_session(client, email=superuser['email'])
    res = client.get(
        url_for('invenio_records_rest.depo_item', pid_value=deposit1['pid']))
    assert res.status_code == 200
Ejemplo n.º 36
0
def test_create_over_and_due_soon_notifications_task(
        client, librarian_martigny_no_email, patron_martigny_no_email,
        item_lib_martigny, circ_policy_short_martigny, loc_public_martigny,
        lib_martigny):
    """Test overdue and due_soon loans."""
    login_user_via_session(client, librarian_martigny_no_email.user)
    item = item_lib_martigny
    item_pid = item.pid
    patron_pid = patron_martigny_no_email.pid
    # checkout
    res, data = postdata(
        client, 'api_item.checkout',
        dict(
            item_pid=item_pid,
            patron_pid=patron_pid,
            transaction_location_pid=loc_public_martigny.pid,
            transaction_user_pid=librarian_martigny_no_email.pid,
        ))
    assert res.status_code == 200

    loan_pid = data.get('action_applied')[LoanAction.CHECKOUT].get('pid')
    loan = Loan.get_record_by_pid(loan_pid)

    # test due_soon notification
    end_date = datetime.now(timezone.utc) + timedelta(days=3)
    loan['end_date'] = end_date.isoformat()
    loan.update(loan, dbcommit=True, reindex=True)

    due_soon_loans = get_due_soon_loans()

    assert due_soon_loans[0].get('pid') == loan_pid

    create_over_and_due_soon_notifications()
    flush_index(NotificationsSearch.Meta.index)
    flush_index(LoansSearch.Meta.index)

    assert loan.is_notified(notification_type='due_soon')

    # test overdue notification
    end_date = datetime.now(timezone.utc) - timedelta(days=7)
    loan['end_date'] = end_date.isoformat()
    loan.update(loan, dbcommit=True, reindex=True)

    overdue_loans = get_overdue_loans()
    assert overdue_loans[0].get('pid') == loan_pid

    create_over_and_due_soon_notifications()
    flush_index(NotificationsSearch.Meta.index)
    flush_index(LoansSearch.Meta.index)

    assert loan.is_notified(notification_type='overdue')
    assert number_of_reminders_sent(loan) == 1

    # checkin the item to put it back to it's original state
    res, _ = postdata(
        client, 'api_item.checkin',
        dict(item_pid=item_pid,
             pid=loan_pid,
             transaction_location_pid=loc_public_martigny.pid,
             transaction_user_pid=librarian_martigny_no_email.pid))
    assert res.status_code == 200
Ejemplo n.º 37
0
def test_simple_workflow(app, db, es, users, location, cds_jsonresolver,
                         project_metadata, json_headers, deposit_rest,
                         data_file_1, data_file_2):
    """Test project simple workflow."""
    def check_connection(videos, project):
        """check project <---> video connection."""
        assert all({"$reference": video.ref} in project['videos']
                   for video in videos)
        assert len(videos) == len(project['videos'])

    project_schema = ('https://cdslabs.cern.ch/schemas/'
                      'deposits/records/project-v1.0.0.json')
    video_schema = ('https://cdslabs.cern.ch/schemas/'
                    'deposits/records/video-v1.0.0.json')

    with app.test_client() as client:
        login_user_via_session(client, email=User.query.get(users[0]).email)

        # [[ CREATE NEW PROJECT ]]
        res = client.post(url_for('invenio_deposit_rest.project_list'),
                          data=json.dumps(project_metadata),
                          headers=json_headers)

        # check returned value
        assert res.status_code == 201
        project_dict = json.loads(res.data.decode('utf-8'))
        assert project_dict['metadata']['videos'] == []
        assert project_dict['metadata']['title']['title'] == 'my project'
        assert project_dict['links']['bucket'].startswith(
            'http://localhost/files/')
        assert all(
            link.startswith('http://localhost/deposits/project')
            for (key, link) in project_dict['links'].items()
            if key not in ['html', 'bucket'])
        # check database
        project_id = project_dict['metadata']['_deposit']['id']
        project = project_resolver(project_id)
        assert project['$schema'] == project_schema

        # [[ ADD A NEW EMPTY VIDEO_1 ]]
        res = client.post(url_for('invenio_deposit_rest.video_list'),
                          data=json.dumps({
                              '_project_id':
                              project_dict['metadata']['_deposit']['id'],
                          }),
                          headers=json_headers)

        # check returned value
        assert res.status_code == 201
        video_1_dict = json.loads(res.data.decode('utf-8'))
        assert video_1_dict['metadata']['_project_id'] == project_id
        assert all(
            link.startswith('http://localhost/deposits/video')
            for (key, link) in video_1_dict['links'].items()
            if key not in ['html', 'bucket'])
        # check database: connection project <---> videos
        video_ids = [video_1_dict['metadata']['_deposit']['id']]
        [video_1] = video_resolver(video_ids)
        check_connection([video_1],
                         project_resolver(
                             project_dict['metadata']['_deposit']['id']))
        assert video_1['$schema'] == video_schema

        # [[ GET THE VIDEO 1 ]]
        res = client.get(video_1_dict['links']['self'], headers=json_headers)

        # check returned value
        assert res.status_code == 200
        video_1_dict = json.loads(res.data.decode('utf-8'))
        assert video_1_dict['metadata']['_files'] == []

        # [[ ADD A NEW EMPTY VIDEO_2 ]]
        res = client.post(url_for('invenio_deposit_rest.video_list'),
                          data=json.dumps({
                              '_project_id':
                              project_dict['metadata']['_deposit']['id'],
                          }),
                          headers=json_headers)

        # check returned value
        assert res.status_code == 201
        video_2_dict = json.loads(res.data.decode('utf-8'))
        assert video_2_dict['metadata']['_project_id'] == project_id
        assert all(
            link.startswith('http://localhost/deposits/video')
            for (key, link) in video_2_dict['links'].items()
            if key not in ['html', 'bucket'])
        # check database: connection project <---> videos
        video_ids = [
            video_1_dict['metadata']['_deposit']['id'],
            video_2_dict['metadata']['_deposit']['id']
        ]
        [video_1, video_2] = video_resolver(video_ids)
        check_connection([video_1, video_2],
                         project_resolver(
                             project_dict['metadata']['_deposit']['id']))
        assert video_2['$schema'] == video_schema

        # [[ ADD A FILE INSIDE VIDEO_1 ]]
        res = client.post(url_for(
            'invenio_deposit_rest.video_files',
            pid_value=video_1_dict['metadata']['_deposit']['id']),
                          data=data_file_1,
                          content_type='multipart/form-data')

        # check returned value
        assert res.status_code == 201
        file_1 = json.loads(res.data.decode('utf-8'))
        assert file_1['checksum'] == 'md5:eb88ae1e3666e6fe96a33ea72aab630e'
        assert file_1['filesize'] == 24
        assert file_1['filename'] == 'test.json'
        assert file_1['id']
        # check database: connection project <---> videos
        [video_1
         ] = video_resolver([video_1_dict['metadata']['_deposit']['id']])
        assert video_1['_files'][0]['key'] == 'test.json'
        video_ids = [
            video_1_dict['metadata']['_deposit']['id'],
            video_2_dict['metadata']['_deposit']['id']
        ]
        check_connection(
            video_resolver(video_ids),
            project_resolver(project_dict['metadata']['_deposit']['id']))

        # [[ GET THE VIDEO 1 ]]
        res = client.get(video_1_dict['links']['self'], headers=json_headers)

        # check video metadata
        assert res.status_code == 200
        video_1_dict = json.loads(res.data.decode('utf-8'))
        assert len(video_1_dict['metadata']['_files']) == 1
        myfile = video_1_dict['metadata']['_files'][0]
        assert myfile['links']['self'].startswith('/api/files/')
        assert myfile['checksum'] == 'md5:eb88ae1e3666e6fe96a33ea72aab630e'
        assert myfile['completed'] is True
        assert 'version_id' in myfile
        assert myfile['key'] == 'test.json'
        assert myfile['progress'] == 100
        assert myfile['size'] == 24

        # [[ PUBLISH VIDEO_1 ]]
        # Not need to send _files
        del video_1_dict['metadata']['_files']
        res = client.post(url_for('invenio_deposit_rest.video_actions',
                                  pid_value=video_1['_deposit']['id'],
                                  action='publish'),
                          headers=json_headers)

        # check returned value
        assert res.status_code == 202
        video_1_dict = json.loads(res.data.decode('utf-8'))
        assert video_1_dict['metadata']['_deposit']['status'] == 'published'
        assert video_1_dict['metadata']['recid'] == 1
        assert video_1_dict['metadata']['_project_id'] == project_id
        # check database: connection project <---> videos
        video_ids = [
            video_1_dict['metadata']['_deposit']['id'],
            video_2_dict['metadata']['_deposit']['id']
        ]
        check_connection(
            video_resolver(video_ids),
            project_resolver(project_dict['metadata']['_deposit']['id']))

        # [[ ADD A VIDEO INSIDE VIDEO_2 ]]
        res = client.post(url_for(
            'invenio_deposit_rest.video_files',
            pid_value=video_2_dict['metadata']['_deposit']['id']),
                          data=data_file_2,
                          content_type='multipart/form-data')

        # check returned value
        assert res.status_code == 201
        file_2 = json.loads(res.data.decode('utf-8'))
        assert file_2['checksum'] == 'md5:95405c14852500dcbb6dbfd9e27a3594'
        assert file_2['filesize'] == 26
        assert file_2['filename'] == 'test2.json'
        # check connection project <---> videos
        [video_2
         ] = video_resolver([video_2_dict['metadata']['_deposit']['id']])
        assert video_2['_files'][0]['key'] == 'test2.json'
        video_ids = [
            video_1_dict['metadata']['_deposit']['id'],
            video_2_dict['metadata']['_deposit']['id']
        ]
        check_connection(
            video_resolver(video_ids),
            project_resolver(project_dict['metadata']['_deposit']['id']))

        # [[ PUBLISH THE PROJECT ]]
        res = client.post(url_for('invenio_deposit_rest.project_actions',
                                  pid_value=project['_deposit']['id'],
                                  action='publish'),
                          headers=json_headers)

        # check returned value
        assert res.status_code == 202
        project_dict = json.loads(res.data.decode('utf-8'))
        assert project_dict['metadata']['_deposit']['status'] == 'published'
        assert project_dict['metadata']['recid'] == 3
        assert project_dict['metadata']['videos'][0] == {
            '$reference': '/record/1'
        }
        assert project_dict['metadata']['videos'][1] == {
            '$reference': '/record/2'
        }
        # check database: connection project <---> videos
        video_ids = [
            video_1_dict['metadata']['_deposit']['id'],
            video_2_dict['metadata']['_deposit']['id']
        ]
        check_connection(
            video_resolver(video_ids),
            project_resolver(project_dict['metadata']['_deposit']['id']))

        # [[ EDIT THE PROJECT ]]
        res = client.post(url_for(
            'invenio_deposit_rest.project_actions',
            pid_value=project_dict['metadata']['_deposit']['id'],
            action='edit'),
                          headers=json_headers)

        # check returned value
        assert res.status_code == 201
        project_dict = json.loads(res.data.decode('utf-8'))
        assert project_dict['metadata']['_deposit']['status'] == 'draft'
        # check database
        project = project_resolver(project_dict['metadata']['_deposit']['id'])
        assert project['_deposit']['status'] == 'draft'

        # [[ MODIFY PROJECT ]]
        project_dict['metadata']['title']['title'] = 'new project title'
        # Not need to send _files
        del project_dict['metadata']['_files']
        res = client.put(url_for(
            'invenio_deposit_rest.project_item',
            pid_value=project_dict['metadata']['_deposit']['id']),
                         data=json.dumps(project_dict['metadata']),
                         headers=json_headers)
        # check returned value
        assert res.status_code == 200
        project_dict = json.loads(res.data.decode('utf-8'))
        assert project_dict['metadata']['title']['title'] ==\
            'new project title'
        assert all(
            link.startswith('http://localhost/deposits/project')
            for (key, link) in project_dict['links'].items()
            if key not in ['html', 'bucket'])
        # check database
        project = project_resolver(project_dict['metadata']['_deposit']['id'])
        assert project['title']['title'] == 'new project title'

        # [[ DISCARD PROJECT ]]
        res = client.post(url_for(
            'invenio_deposit_rest.project_actions',
            pid_value=project_dict['metadata']['_deposit']['id'],
            action='discard'),
                          headers=json_headers)
        # check returned value
        assert res.status_code == 201
        project_dict = json.loads(res.data.decode('utf-8'))
        assert project_dict['metadata']['title']['title'] == 'my project'
        # check database
        project = project_resolver(project_dict['metadata']['_deposit']['id'])
        assert project['title']['title'] == 'my project'
Ejemplo n.º 38
0
def test_patrons_count(client, patron_sion_no_email,
                       librarian_martigny_no_email,
                       system_librarian_sion_no_email):
    """Test number of email address."""

    librarian_email = librarian_martigny_no_email.get('email')
    url = url_for('api_patrons.number_of_patrons', q=librarian_email)

    res = client.get(url)
    assert res.status_code == 401

    login_user_via_session(client, patron_sion_no_email.user)
    res = client.get(url)
    assert res.status_code == 403

    login_user_via_session(client, librarian_martigny_no_email.user)
    # malformed url
    res = client.get(url)
    assert res.status_code == 400

    # librarian email
    url = url_for('api_patrons.number_of_patrons',
                  q='email:"{email}"'.format(
                      email=librarian_martigny_no_email.get('email')))
    res = client.get(url)
    assert res.status_code == 200
    assert get_json(res) == dict(hits=dict(total=1))

    # patron email
    url = url_for(
        'api_patrons.number_of_patrons',
        q='email:"{email}"'.format(email=patron_sion_no_email.get('email')))
    res = client.get(url)
    assert res.status_code == 200
    assert get_json(res) == dict(hits=dict(total=1))

    # patron email excluding itself
    url = url_for('api_patrons.number_of_patrons',
                  q='email:"{email}" NOT pid:{pid}'.format(
                      email=patron_sion_no_email.get('email'),
                      pid=patron_sion_no_email.pid))
    res = client.get(url)
    assert get_json(res) == dict(hits=dict(total=0))

    # patron email excluding itself
    url = url_for('api_patrons.number_of_patrons',
                  q='email:"{email}"'.format(email='*****@*****.**'))
    res = client.get(url)
    assert get_json(res) == dict(hits=dict(total=0))

    # librarian email uppercase
    url = url_for('api_patrons.number_of_patrons',
                  q='email:"{email}"'.format(email=librarian_email.upper()))
    res = client.get(url)
    assert get_json(res) == dict(hits=dict(total=1))

    # librarian email with spaces
    url = url_for('api_patrons.number_of_patrons',
                  q='email:" {email} "'.format(email=librarian_email.upper()))
    res = client.get(url)
    assert get_json(res) == dict(hits=dict(total=1))

    # system librarian email containing a + char
    url = url_for(
        'api_patrons.number_of_patrons',
        q='email:"{email}"'.format(
            email=system_librarian_sion_no_email.get('email').upper()))
    res = client.get(url)
    assert get_json(res) == dict(hits=dict(total=1))

    # patron username
    url = url_for('api_patrons.number_of_patrons',
                  q='username:"******"'.format(
                      username=patron_sion_no_email.get('username')))
    res = client.get(url)
    assert res.status_code == 200
    assert get_json(res) == dict(hits=dict(total=1))
Ejemplo n.º 39
0
def test_pending_loans_order(client, librarian_martigny,
                             patron_martigny, loc_public_martigny,
                             item_type_standard_martigny,
                             item2_lib_martigny, json_header,
                             patron2_martigny, patron_sion,
                             circulation_policies):
    """Test sort of pending loans."""
    login_user_via_session(client, librarian_martigny.user)
    library_pid = librarian_martigny\
        .replace_refs()['libraries'][0]['pid']

    res, _ = postdata(
        client,
        'api_item.librarian_request',
        dict(
            item_pid=item2_lib_martigny.pid,
            patron_pid=patron_sion.pid,
            pickup_location_pid=loc_public_martigny.pid,
            transaction_user_pid=librarian_martigny.pid,
            transaction_location_pid=loc_public_martigny.pid
        )
    )

    res, _ = postdata(
        client,
        'api_item.librarian_request',
        dict(
            item_pid=item2_lib_martigny.pid,
            patron_pid=patron_martigny.pid,
            pickup_location_pid=loc_public_martigny.pid,
            transaction_user_pid=librarian_martigny.pid,
            transaction_location_pid=loc_public_martigny.pid
        )
    )
    assert res.status_code == 200

    res, _ = postdata(
        client,
        'api_item.librarian_request',
        dict(
            item_pid=item2_lib_martigny.pid,
            patron_pid=patron2_martigny.pid,
            pickup_location_pid=loc_public_martigny.pid,
            transaction_user_pid=librarian_martigny.pid,
            transaction_location_pid=loc_public_martigny.pid
        )
    )
    assert res.status_code == 200

    # sort by pid asc
    res = client.get(
        url_for(
            'api_item.requested_loans', library_pid=library_pid,
            sort='pid'))
    assert res.status_code == 200
    data = get_json(res)
    loans = data['hits']['hits'][0]['item']['pending_loans']
    assert loans[2]['pid'] > loans[1]['pid'] > loans[0]['pid']

    # sort by pid desc
    res = client.get(
        url_for(
            'api_item.requested_loans', library_pid=library_pid,
            sort='-pid'))
    assert res.status_code == 200
    data = get_json(res)
    loans = data['hits']['hits'][0]['item']['pending_loans']
    assert loans[2]['pid'] < loans[1]['pid'] < loans[0]['pid']

    # sort by transaction desc
    res = client.get(
        url_for(
            'api_item.requested_loans', library_pid=library_pid,
            sort='-transaction_date'))
    assert res.status_code == 200
    data = get_json(res)
    loans = data['hits']['hits'][0]['item']['pending_loans']
    assert loans[2]['pid'] < loans[1]['pid'] < loans[0]['pid']

    # sort by patron_pid asc
    res = client.get(
        url_for(
            'api_item.requested_loans', library_pid=library_pid,
            sort='patron_pid'))
    assert res.status_code == 200
    data = get_json(res)
    loans = data['hits']['hits'][0]['item']['pending_loans']
    assert loans[0]['patron_pid'] == patron_sion.pid
    assert loans[1]['patron_pid'] == patron_martigny.pid
    assert loans[2]['patron_pid'] == patron2_martigny.pid

    # sort by invalid field
    res = client.get(
        url_for(
            'api_item.requested_loans', library_pid=library_pid,
            sort='does not exist'))
    assert res.status_code == 500
    data = get_json(res)
    assert 'RequestError(400' in data['status']
def test_patron_transaction_event_secure_api_create(
        client, librarian_martigny,
        librarian_sion, patron_transaction_overdue_event_martigny,
        system_librarian_martigny,
        system_librarian_sion):
    """Test patron transction event secure api create."""
    # Martigny
    login_user_via_session(client, librarian_martigny.user)
    post_entrypoint = 'invenio_records_rest.ptre_list'
    patron_event = deepcopy(patron_transaction_overdue_event_martigny)
    del patron_event['pid']
    res, _ = postdata(
        client,
        post_entrypoint,
        patron_event
    )
    # librarian is authorized to create a patron event in its library.
    assert res.status_code == 201

    patron_event_2 = deepcopy(patron_transaction_overdue_event_martigny)

    del patron_event_2['pid']
    res, _ = postdata(
        client,
        post_entrypoint,
        patron_event_2
    )
    # librarian is can create a patron event in other libraries.
    assert res.status_code == 201

    login_user_via_session(client, system_librarian_martigny.user)
    res, _ = postdata(
        client,
        post_entrypoint,
        patron_event_2
    )
    # sys_librarian is authorized to create any patron event in its org.
    assert res.status_code == 201

    # Sion
    login_user_via_session(client, librarian_sion.user)

    patron_event_3 = deepcopy(patron_transaction_overdue_event_martigny)
    del patron_event_3['pid']

    res, _ = postdata(
        client,
        post_entrypoint,
        patron_event_3
    )
    # librarian is not authorized to create a patron event at other org.
    assert res.status_code == 403

    login_user_via_session(client, system_librarian_sion.user)
    res, _ = postdata(
        client,
        post_entrypoint,
        patron_event_3
    )
    # sys_librarian can not to create a patron event in other org.
    assert res.status_code == 403
def test_records_rest(api_app, users, es, api_project_published, vtt_headers,
                      datacite_headers, json_headers, smil_headers,
                      drupal_headers, extra_metadata, _deposit_metadata):
    """Test view."""
    indexer = RecordIndexer()
    (project, video_1, video_2) = api_project_published
    pid, record_project = project.fetch_published()
    vid, record_video = video_1.fetch_published()
    bucket_id = str(video_1['_buckets']['deposit'])

    # index project
    project.indexer.index(record_project)
    # index video
    record_video['_files'] = get_files_metadata(bucket_id)
    record_video['_deposit'].update(_deposit_metadata)
    record_video.update(extra_metadata)
    record_video.commit()
    indexer.index(record_video)
    sleep(1)

    with api_app.test_client() as client:
        login_user_via_session(client, email=User.query.get(users[0]).email)
        url = url_for('invenio_records_rest.recid_item',
                      pid_value=pid.pid_value)
        url2 = url_for('invenio_records_rest.recid_item',
                       pid_value=vid.pid_value)

        # try get json
        res = client.get(url, headers=json_headers)
        assert res.status_code == 200
        project_dict = json.loads(res.data.decode('utf-8'))
        assert project_dict['metadata']['_deposit']['id'] == project[
            '_deposit']['id']

        # try get smil
        res = client.get(url, headers=smil_headers)
        assert res.status_code == 400

        res = client.get(url2, headers=smil_headers)
        assert res.status_code == 200

        # try get vtt
        res = client.get(url, headers=vtt_headers)
        assert res.status_code == 400

        res = client.get(url2, headers=vtt_headers)
        assert res.status_code == 200

        # try get drupal
        report_number = u'CERN-MOVIE-2017-1-1'
        file_frame = 'http://cds.cern.ch/api/files/123/frame-1.jpg'
        with mock.patch('cds.modules.records.api.CDSFileObject._link',
                        return_value=file_frame):
            res = client.get(url2, headers=drupal_headers)
            # test legacy api/mediaexport url
            legacy_url = u'/mediaexport?id={id}'.format(id=report_number)
            assert client.get(legacy_url, follow_redirects=False) \
                .status_code == 301
            res_legacy = client.get(legacy_url, follow_redirects=True)

        assert res.status_code == 200
        assert res_legacy.status_code == 200
        drupal = json.loads(res.data.decode('utf-8'))
        thumbnail = u'http://cds.cern.ch/api/files/123/frame-1.jpg'
        expected = {
            u'entries': [{
                u'entry': {
                    u'caption_en': u'in tempor reprehenderit enim eiusmod',
                    u'caption_fr': u'france caption',
                    u'copyright_date': u'2017',
                    u'copyright_holder': u'CERN',
                    u'creation_date': u'2017-03-02',
                    u'directors': u'paperone, pluto',
                    u'entry_date': u'2017-09-25',
                    u'id': report_number,
                    u'keywords': u'keyword1, keyword2',
                    u'license_body': u'GPLv2',
                    u'license_url': u'http://license.cern.ch',
                    u'producer': u'nonna papera, zio paperino',
                    u'record_id': u'1',
                    u'thumbnail': thumbnail,
                    u'title_en': u'My english title',
                    u'title_fr': u'My french title',
                    u'type': u'video',
                    u'video_length': u'00:01:00',
                }
            }]
        }
        assert expected == drupal
        drupal_legacy = json.loads(res_legacy.data.decode('utf-8'))
        assert expected == drupal_legacy

        # try get datacite
        res = client.get(url2, headers=datacite_headers)
        assert res.status_code == 200
        assert res.data.decode('utf-8').startswith('<?xml version=')

    # test corner cases
    del record_video['title_translations']
    del record_video['description_translations']
    record_video.commit()
    db.session.commit()

    with api_app.test_client() as client:
        # try get drupal
        file_frame = 'http://cds.cern.ch/api/files/123/frame-1.jpg'
        with mock.patch('cds.modules.records.api.CDSFileObject._link',
                        return_value=file_frame):
            res = client.get(url2, headers=drupal_headers)

        assert res.status_code == 200
        drupal = json.loads(res.data.decode('utf-8'))
        thumbnail = u'http://cds.cern.ch/api/files/123/frame-1.jpg'
        expected = {
            u'entries': [{
                u'entry': {
                    u'caption_en': u'in tempor reprehenderit enim eiusmod',
                    u'caption_fr': u'',
                    u'copyright_date': u'2017',
                    u'copyright_holder': u'CERN',
                    u'creation_date': u'2017-03-02',
                    u'directors': u'paperone, pluto',
                    u'entry_date': u'2017-09-25',
                    u'id': u'CERN-MOVIE-2017-1-1',
                    u'keywords': u'keyword1, keyword2',
                    u'license_body': u'GPLv2',
                    u'license_url': u'http://license.cern.ch',
                    u'producer': u'nonna papera, zio paperino',
                    u'record_id': u'1',
                    u'thumbnail': thumbnail,
                    u'title_en': u'My english title',
                    u'title_fr': u'',
                    u'type': u'video',
                    u'video_length': u'00:01:00',
                }
            }]
        }
        assert expected == drupal
Ejemplo n.º 42
0
def test_system_librarian_permissions(client, json_header,
                                      system_librarian_martigny_no_email,
                                      patron_martigny_no_email,
                                      patron_type_adults_martigny,
                                      librarian_fully_no_email):
    """Test system_librarian permissions."""
    # Login as system_librarian
    login_user_via_session(client, system_librarian_martigny_no_email.user)

    record = {
        "$schema": "https://ils.rero.ch/schemas/patrons/patron-v0.0.1.json",
        "first_name": "first_name",
        "last_name": "Last_name",
        "street": "Avenue Leopold-Robert, 132",
        "postal_code": "1920",
        "city": "Martigny",
        "birth_date": "1967-06-07",
        "phone": "+41324993111"
    }

    # can retrieve all type of users.
    list_url = url_for('invenio_records_rest.ptrn_list')
    res = client.get(list_url)
    assert res.status_code == 200
    data = get_json(res)
    assert data['hits']['total'] == 3

    # can manage all types of patron roles
    role_url = url_for('api_patrons.get_roles_management_permissions')
    res = client.get(role_url)
    assert res.status_code == 200
    data = get_json(res)
    assert 'system_librarian' in data['allowed_roles']

    # can create all type of users.
    system_librarian = deepcopy(record)
    librarian = deepcopy(record)
    patron = deepcopy(record)
    counter = 1
    records = [{
        'data': patron,
        'role': ['patron'],
        'patron_type': {
            '$ref': 'https://ils.rero.ch/api/patron_types/ptty2'
        }
    }, {
        'data': librarian,
        'role': ['librarian'],
        'library': {
            '$ref': 'https://ils.rero.ch/api/libraries/lib1'
        }
    }, {
        'data': system_librarian,
        'role': ['librarian', 'system_librarian'],
        'library': {
            '$ref': 'https://ils.rero.ch/api/libraries/lib1'
        }
    }]
    for record in records:
        counter += 1
        data = record['data']
        data['roles'] = record['role']
        data['barcode'] = 'barcode' + str(counter)
        data['email'] = str(counter) + '@domain.com'
        if record.get('patron_type'):
            data['patron_type'] = record['patron_type']
        if record.get('library'):
            data['library'] = record['library']
        with mock.patch('rero_ils.modules.patrons.api.'
                        'send_reset_password_instructions'):
            res, _ = postdata(client, 'invenio_records_rest.ptrn_list', data)
            assert res.status_code == 201
            user = get_json(res)['metadata']
            user_pid = user.get('pid')
            record_url = url_for('invenio_records_rest.ptrn_item',
                                 pid_value=user_pid)
            res = client.get(record_url)
            assert res.status_code == 200
            user = get_json(res)['metadata']

            # can update all type of user records.
            user['first_name'] = 'New Name' + str(counter)
            res = client.put(record_url,
                             data=json.dumps(user),
                             headers=json_header)
            assert res.status_code == 200

            # can delete all type of user records.
            record_url = url_for('invenio_records_rest.ptrn_item',
                                 pid_value=user_pid)

            res = client.delete(record_url)
            assert res.status_code == 204
Ejemplo n.º 43
0
def test_pttr_permissions_api(client, patron_martigny_no_email,
                              system_librarian_martigny_no_email,
                              librarian_martigny_no_email,
                              patron_transaction_overdue_martigny,
                              patron_transaction_overdue_saxon,
                              patron_transaction_overdue_sion):
    """Test patron transactions permissions api."""
    pttr_permissions_url = url_for('api_blueprint.permissions',
                                   route_name='patron_transactions')
    pttr_martigny_permission_url = url_for(
        'api_blueprint.permissions',
        route_name='patron_transactions',
        record_pid=patron_transaction_overdue_martigny.pid)
    pttr_saxon_permission_url = url_for(
        'api_blueprint.permissions',
        route_name='patron_transactions',
        record_pid=patron_transaction_overdue_saxon.pid)
    pttr_sion_permission_url = url_for(
        'api_blueprint.permissions',
        route_name='patron_transactions',
        record_pid=patron_transaction_overdue_sion.pid)

    # Not logged
    res = client.get(pttr_permissions_url)
    assert res.status_code == 401

    # Logged as patron
    login_user_via_session(client, patron_martigny_no_email.user)
    res = client.get(pttr_permissions_url)
    assert res.status_code == 403

    # Logged as librarian
    #   * lib can 'list' and 'read' pttr of its own organisation
    #   * lib can 'create', 'update', 'delete' only for its library
    #   * lib can't 'read' acq_account of others organisation.
    #   * lib can't 'create', 'update', 'delete' acq_account for other org/lib
    login_user_via_session(client, librarian_martigny_no_email.user)
    res = client.get(pttr_martigny_permission_url)
    assert res.status_code == 200
    data = get_json(res)
    assert data['read']['can']
    assert data['list']['can']
    assert data['create']['can']
    assert data['update']['can']
    # 'delete' should be true but return false because an event is linked
    # assert data['delete']['can']

    res = client.get(pttr_saxon_permission_url)
    assert res.status_code == 200
    data = get_json(res)
    assert data['read']['can']
    assert data['list']['can']
    assert data['update']['can']
    # 'delete' should be true but return false because an event is linked
    # assert not data['delete']['can']

    res = client.get(pttr_sion_permission_url)
    assert res.status_code == 200
    data = get_json(res)
    assert not data['read']['can']
    assert data['list']['can']
    assert not data['update']['can']
    assert not data['delete']['can']

    # Logged as system librarian
    #   * sys_lib can do everything about pttr of its own organisation
    #   * sys_lib can't do anything about pttr of other organisation
    login_user_via_session(client, system_librarian_martigny_no_email.user)
    res = client.get(pttr_saxon_permission_url)
    assert res.status_code == 200
    data = get_json(res)
    assert data['read']['can']
    assert data['list']['can']
    assert data['create']['can']
    assert data['update']['can']
    # 'delete' should be true but return false because an event is linked
    # assert data['delete']['can']

    res = client.get(pttr_sion_permission_url)
    assert res.status_code == 200
    data = get_json(res)
    assert not data['read']['can']
    assert not data['update']['can']
    assert not data['delete']['can']
Ejemplo n.º 44
0
def test_assign_without_to_author(inspire_app, override_config):
    with override_config(FEATURE_FLAG_ENABLE_BAI_PROVIDER=True,
                         FEATURE_FLAG_ENABLE_BAI_CREATION=True):
        cataloger = create_user(role="cataloger")
        from_author = create_record("aut",
                                    data={"name": {
                                        "value": "Urhan, Harun"
                                    }})
        literature1 = create_record(
            "lit",
            data={
                "authors": [{
                    "curated_relation": False,
                    "full_name": "Urhan, Harun",
                    "record": {
                        "$ref":
                        f"http://localhost:5000/api/authors/{from_author['control_number']}"
                    },
                }]
            },
        )

        literature2 = create_record(
            "lit",
            data={
                "authors": [{
                    "curated_relation": False,
                    "full_name": "Urhan, H",
                    "record": {
                        "$ref":
                        f"http://localhost:5000/api/authors/{from_author['control_number']}"
                    },
                }]
            },
        )

        with inspire_app.test_client() as client:
            login_user_via_session(client, email=cataloger.email)
            response = client.post(
                "/assign/author",
                data=orjson.dumps({
                    "literature_recids": [
                        literature1["control_number"],
                        literature2["control_number"],
                    ],
                    "from_author_recid":
                    from_author["control_number"],
                }),
                content_type="application/json",
            )
        response_status_code = response.status_code

    assert response_status_code == 200
    stub_author_id = response.json["stub_author_id"]

    literature1_after = LiteratureRecord.get_record_by_pid_value(
        literature1["control_number"])
    literature1_author = literature1_after["authors"][0]
    literature1_author_recid = get_recid_from_ref(literature1_author["record"])
    assert literature1_author_recid != from_author["control_number"]
    assert literature1_author_recid == stub_author_id
    assert not literature1_author.get("curated_relation")

    literature2_after = LiteratureRecord.get_record_by_pid_value(
        literature1["control_number"])
    literature2_author = literature2_after["authors"][0]
    literature2_author_recid = get_recid_from_ref(literature2_author["record"])
    assert literature2_author_recid != from_author["control_number"]
    assert literature2_author_recid == stub_author_id
    assert not literature2_author.get("curated_relation")

    author = AuthorsRecord.get_record_by_pid_value(stub_author_id)
    assert author["stub"] is True
    assert author["name"] == {
        "value": "Urhan, Harun",
        "name_variants": ["Urhan, H"]
    }
    assert get_values_for_schema(author["ids"],
                                 "INSPIRE BAI")[0] == "H.Urhan.2"
    assert (get_values_for_schema(author["ids"], "INSPIRE BAI")[0] !=
            get_values_for_schema(from_author["ids"], "INSPIRE BAI")[0])
Ejemplo n.º 45
0
def test_create(client, db, deposit_json, bucket_location, superuser, admin,
                moderator, submitter, user, subdivision):
    """Test create deposits permissions."""
    headers = {
        'Content-Type': 'application/json',
        'Accept': 'application/json'
    }

    # Not logged
    res = client.post(url_for('invenio_records_rest.depo_list'),
                      data=json.dumps(deposit_json),
                      headers=headers)
    assert res.status_code == 401

    # User
    login_user_via_session(client, email=user['email'])
    deposit_json['user'] = {
        '$ref': 'https://sonar.ch/api/users/{pid}'.format(pid=user['pid'])
    }
    res = client.post(url_for('invenio_records_rest.depo_list'),
                      data=json.dumps(deposit_json),
                      headers=headers)
    assert res.status_code == 403

    # submitter
    login_user_via_session(client, email=submitter['email'])
    submitter['subdivision'] = {
        '$ref':
        'https://sonar.ch/api/subdivisions/{subdivision}'.format(
            subdivision=subdivision['pid'])
    }
    submitter.commit()
    submitter.reindex()
    db.session.commit()
    deposit_json['user'] = {
        '$ref': 'https://sonar.ch/api/users/{pid}'.format(pid=submitter['pid'])
    }
    del deposit_json['diffusion']['subdivisions']
    res = client.post(url_for('invenio_records_rest.depo_list'),
                      data=json.dumps(deposit_json),
                      headers=headers)
    assert res.status_code == 201
    assert res.json['metadata']['diffusion']['subdivisions']

    # Moderator
    login_user_via_session(client, email=moderator['email'])
    deposit_json['user'] = {
        '$ref': 'https://sonar.ch/api/users/{pid}'.format(pid=moderator['pid'])
    }
    res = client.post(url_for('invenio_records_rest.depo_list'),
                      data=json.dumps(deposit_json),
                      headers=headers)
    assert res.status_code == 201

    # Admin
    login_user_via_session(client, email=admin['email'])
    deposit_json['user'] = {
        '$ref': 'https://sonar.ch/api/users/{pid}'.format(pid=admin['pid'])
    }
    res = client.post(url_for('invenio_records_rest.depo_list'),
                      data=json.dumps(deposit_json),
                      headers=headers)
    assert res.status_code == 201

    # Super user
    login_user_via_session(client, email=superuser['email'])
    deposit_json['user'] = {
        '$ref': 'https://sonar.ch/api/users/{pid}'.format(pid=superuser['pid'])
    }
    res = client.post(url_for('invenio_records_rest.depo_list'),
                      data=json.dumps(deposit_json),
                      headers=headers)
    assert res.status_code == 201
Ejemplo n.º 46
0
def test_video_events_on_download_check_index(api_app, webhooks, db,
                                              api_project, access_token,
                                              json_headers, users):
    """Test deposit events."""
    (project, video_1, video_2) = api_project
    prepare_videos_for_publish([video_1, video_2])
    project_depid = project['_deposit']['id']
    video_1_depid = video_1['_deposit']['id']
    bucket_id = video_1._bucket.id

    with api_app.test_request_context():
        url = url_for(
            'invenio_webhooks.event_list',
            receiver_id='downloader',
            access_token=access_token)

    with mock.patch('requests.get') as mock_request, \
            api_app.test_client() as client:
        login_user_via_session(client, email=User.query.get(users[0]).email)

        file_size = 1024 * 1024
        mock_request.return_value = type(
            'Response', (object, ), {
                'raw': BytesIO(b'\x00' * file_size),
                'headers': {'Content-Length': file_size}
            })

        payload = dict(
            uri='http://example.com/test.pdf',
            bucket_id=str(bucket_id),
            deposit_id=video_1_depid,
            key='test.pdf')

        resp = client.post(url, headers=json_headers, data=json.dumps(payload))
        assert resp.status_code == 201

        # run indexer
        RecordIndexer().process_bulk_queue()
        sleep(2)

        deposit = deposit_video_resolver(video_1_depid)
        file_dumps = deposit._get_files_dump()
        assert len(file_dumps) == 1

        def search_record(url):
            res = client.get(url, headers=json_headers)
            assert res.status_code == 200
            data = json.loads(
                res.data.decode('utf-8')
            )['hits']['hits'][0]['metadata']
            return data

        # check if the tasks states and files are inside elasticsearch
        # -> check video
        url_video_deposit = url_for('invenio_deposit_rest.video_list',
                                    q='_deposit.id:{0}'.format(video_1_depid),
                                    access_token=access_token)
        data = search_record(url_video_deposit)
        assert data['_cds']['state']['file_download'] == states.SUCCESS
        assert file_dumps == data['_files']
        # -> check project
        url_project_deposit = url_for(
            'invenio_deposit_rest.project_list',
            q='_deposit.id:{0}'.format(project_depid),
            access_token=access_token)
        search_record(url_project_deposit)
        assert data['_cds']['state']['file_download'] == states.SUCCESS

        # [[ EDIT VIDEO ]]
        deposit = deposit_video_resolver(video_1_depid)
        video_edited = deepcopy(deposit)
        del video_edited['_files']
        del video_edited['_cds']['state']
        reset_oauth2()
        res = client.put(
            url_for('invenio_deposit_rest.video_item',
                    pid_value=video_1_depid),
            data=json.dumps(video_edited),
            headers=json_headers
        )
        assert res.status_code == 200

        # check if the tasks states and files are inside elasticsearch
        # -> check video
        data = search_record(url_video_deposit)
        assert data['_cds']['state']['file_download'] == states.SUCCESS
        assert file_dumps == data['_files']
        # -> check project
        url_project_deposit = url_for(
            'invenio_deposit_rest.project_list',
            q='_deposit.id:{0}'.format(project_depid),
            access_token=access_token)
        search_record(url_project_deposit)
        assert data['_cds']['state']['file_download'] == states.SUCCESS

        # [[ PUBLISH THE PROJECT ]]
        reset_oauth2()
        res = client.post(
            url_for('invenio_deposit_rest.project_actions',
                    pid_value=project['_deposit']['id'], action='publish',
                    ), headers=json_headers)
        assert res.status_code == 202

        # run indexer
        RecordIndexer().process_bulk_queue()
        sleep(2)

        deposit = deposit_video_resolver(video_1_depid)

        # check if the files are inside elasticsearch
        # -> check video deposit
        data = search_record(url_video_deposit)
        assert data['_cds']['state']['file_download'] == states.SUCCESS
        assert file_dumps == data['_files']
        # check video record
        pid, record = deposit.fetch_published()
        url = url_for('invenio_records_rest.recid_list',
                      q='_deposit.pid.value:{0}'.format(pid.pid_value))
        data = search_record(url)
        assert record['_files'] == data['_files']
Ejemplo n.º 47
0
def test_update(client, make_deposit, superuser, admin, moderator, submitter,
                user):
    """Test update deposits permissions."""
    deposit1 = make_deposit('submitter', 'org')
    deposit2 = make_deposit('submitter', 'org2')

    headers = {
        'Content-Type': 'application/json',
        'Accept': 'application/json'
    }

    # Not logged
    res = client.put(url_for('invenio_records_rest.depo_item',
                             pid_value=deposit1['pid']),
                     data=json.dumps(deposit1.dumps()),
                     headers=headers)
    assert res.status_code == 401

    # Logged as user
    login_user_via_session(client, email=user['email'])
    res = client.put(url_for('invenio_records_rest.depo_item',
                             pid_value=deposit1['pid']),
                     data=json.dumps(deposit1.dumps()),
                     headers=headers)
    assert res.status_code == 403

    # Logged as submitter
    login_user_via_session(client, email=submitter['email'])
    res = client.put(url_for('invenio_records_rest.depo_item',
                             pid_value=deposit1['pid']),
                     data=json.dumps(deposit1.dumps()),
                     headers=headers)
    assert res.status_code == 200

    res = client.put(url_for('invenio_records_rest.depo_item',
                             pid_value=deposit2['pid']),
                     data=json.dumps(deposit2.dumps()),
                     headers=headers)
    assert res.status_code == 403

    # Logged as moderator
    login_user_via_session(client, email=moderator['email'])
    res = client.put(url_for('invenio_records_rest.depo_item',
                             pid_value=deposit1['pid']),
                     data=json.dumps(deposit1.dumps()),
                     headers=headers)
    assert res.status_code == 200

    res = client.put(url_for('invenio_records_rest.depo_item',
                             pid_value=deposit2['pid']),
                     data=json.dumps(deposit2.dumps()),
                     headers=headers)
    assert res.status_code == 403

    # Logged as admin
    login_user_via_session(client, email=admin['email'])
    res = client.put(url_for('invenio_records_rest.depo_item',
                             pid_value=deposit1['pid']),
                     data=json.dumps(deposit1.dumps()),
                     headers=headers)
    assert res.status_code == 200

    res = client.put(url_for('invenio_records_rest.depo_item',
                             pid_value=deposit2['pid']),
                     data=json.dumps(deposit2.dumps()),
                     headers=headers)
    assert res.status_code == 403

    # Logged as superuser
    login_user_via_session(client, email=superuser['email'])
    res = client.put(url_for('invenio_records_rest.depo_item',
                             pid_value=deposit1['pid']),
                     data=json.dumps(deposit1.dumps()),
                     headers=headers)
    assert res.status_code == 200

    login_user_via_session(client, email=superuser['email'])
    res = client.put(url_for('invenio_records_rest.depo_item',
                             pid_value=deposit2['pid']),
                     data=json.dumps(deposit2.dumps()),
                     headers=headers)
    assert res.status_code == 200
Ejemplo n.º 48
0
def test_token_getter_setter(views_fixture, monkeypatch):
    """Test token getter setter."""
    # Mock session id
    monkeypatch.setattr('invenio_oauthclient._compat._create_identifier',
                        lambda: '1234')
    monkeypatch.setattr(
        'invenio_oauthclient.views.client._create_identifier', lambda: '1234')

    app = views_fixture
    oauth = app.extensions['oauthlib.client']

    # Mock user
    user = MagicMock()
    user.id = 1
    user.get_id = MagicMock(return_value=1)
    user.is_anonymous = False

    with app.test_client() as c:
        login_user_via_session(c, user)
        # First call login to be redirected
        res = c.get(url_for('invenio_oauthclient.login',
                            remote_app='full'))
        assert res.status_code == 302
        assert res.location.startswith(
            oauth.remote_apps['full'].authorize_url
        )
        state = parse_qs(urlparse(res.location).query)['state'][0]

        # Mock resposen class
        mock_response(app.extensions['oauthlib.client'], 'full')

        # Imitate that the user authorized our request in the remote
        # application.
        c.get(url_for(
            'invenio_oauthclient.authorized', remote_app='full',
            code='test', state=state,
        ))

        # Assert if everything is as it should be.
        from flask import session as flask_session
        assert flask_session['oauth_token_full'] == \
            ('test_access_token', '')

        t = RemoteToken.get(1, 'fullid')
        assert t.remote_account.client_id == 'fullid'
        assert t.access_token == 'test_access_token'
        assert RemoteToken.query.count() == 1

        # Mock a new authorized request
        mock_response(app.extensions['oauthlib.client'], 'full', data={
            'access_token': 'new_access_token',
            'scope': "",
            'token_type': 'bearer'
        })

        c.get(url_for(
            'invenio_oauthclient.authorized', remote_app='full',
            code='test', state=state
        ))

        t = RemoteToken.get(1, 'fullid')
        assert t.access_token == 'new_access_token'
        assert RemoteToken.query.count() == 1

        val = token_getter(
            app.extensions['oauthlib.client'].remote_apps['full'])
        assert val == ('new_access_token', '')

        # Disconnect account
        res = c.get(url_for(
            'invenio_oauthclient.disconnect', remote_app='full',
        ))
        assert res.status_code == 302
        assert res.location.endswith(
            url_for('invenio_oauthclient_settings.index')
        )
        # Assert that remote account have been removed.
        t = RemoteToken.get(1, 'fullid')
        assert t is None
        # TODO: Figure out what is leaving session open & blocked
        db.session.close()
Ejemplo n.º 49
0
def test_items_in_transit_between_locations(
        client, librarian_martigny_no_email, patron_martigny_no_email,
        loc_public_martigny, item_type_standard_martigny,
        loc_restricted_martigny, item_lib_martigny, json_header,
        circulation_policies):
    """Test item in-transit scenarios."""
    login_user_via_session(client, librarian_martigny_no_email.user)
    item = item_lib_martigny
    item_pid = item.pid
    patron_pid = patron_martigny_no_email.pid
    location = loc_public_martigny

    # request to pick at another location
    res, data = postdata(
        client, 'api_item.librarian_request',
        dict(item_pid=item_pid,
             pickup_location_pid=loc_restricted_martigny.pid,
             patron_pid=patron_pid))
    assert res.status_code == 200
    item_data = data.get('metadata')
    actions = data.get('action_applied')
    assert item_data.get('status') == ItemStatus.ON_SHELF
    assert actions.get(LoanAction.REQUEST)
    loan_pid = actions[LoanAction.REQUEST].get('pid')
    item = Item.get_record_by_pid(item_pid)

    # validate (send) request
    res, data = postdata(client, 'api_item.validate_request',
                         dict(item_pid=item_pid, pid=loan_pid))
    assert res.status_code == 200
    item_data = data.get('metadata')
    actions = data.get('action_applied')
    assert item_data.get('status') == ItemStatus.IN_TRANSIT
    assert actions.get(LoanAction.VALIDATE)

    # checkout action to req patron is possible without the receive action
    res = client.get(
        url_for('api_item.item',
                item_barcode=item.get('barcode'),
                patron_pid=patron_pid))
    assert res.status_code == 200
    data = get_json(res)
    actions = data.get('metadata').get('item').get('actions')
    assert 'checkout' in actions

    # checkout
    res, data = postdata(
        client, 'api_item.checkout',
        dict(item_pid=item_pid, patron_pid=patron_pid, pid=loan_pid))
    assert res.status_code == 200
    assert Item.get_record_by_pid(item_pid).get('status') == ItemStatus.ON_LOAN

    # checkin at location other than item location
    res, data = postdata(
        client, 'api_item.checkin',
        dict(item_pid=item_pid,
             pid=loan_pid,
             transaction_location_pid=loc_restricted_martigny.pid))
    assert res.status_code == 200
    item_data = data.get('metadata')
    actions = data.get('action_applied')
    assert item_data.get('status') == ItemStatus.IN_TRANSIT
    assert actions.get(LoanAction.CHECKIN)
    loan_pid = actions[LoanAction.CHECKIN].get('pid')
    loan = actions[LoanAction.CHECKIN]
    assert loan.get('state') == 'ITEM_IN_TRANSIT_TO_HOUSE'

    # a new checkout
    res, data = postdata(client, 'api_item.checkout',
                         dict(item_pid=item_pid, patron_pid=patron_pid))
    assert res.status_code == 200
    assert Item.get_record_by_pid(item_pid).get('status') == ItemStatus.ON_LOAN
    actions = data.get('action_applied')
    loan_pid = actions[LoanAction.CHECKOUT].get('pid')

    # checkin at the request location
    res, _ = postdata(
        client, 'api_item.checkin',
        dict(item_pid=item.pid,
             pid=loan_pid,
             transaction_location_pid=location.pid))
    assert res.status_code == 200
Ejemplo n.º 50
0
def test_multiple_loans_on_item_error(
        client, patron_martigny_no_email, patron2_martigny_no_email,
        loc_public_martigny, item_type_standard_martigny, item_lib_martigny,
        json_header, circulation_policies, loc_public_fully,
        librarian_martigny_no_email):
    """Test MultipleLoansOnItemError."""
    login_user_via_session(client, librarian_martigny_no_email.user)
    item = item_lib_martigny
    checked_patron = patron2_martigny_no_email.pid
    requested_patron = patron_martigny_no_email.pid
    location = loc_public_martigny
    # checkout to checked_patron
    res, data = postdata(
        client, 'api_item.checkout',
        dict(item_pid=item.pid,
             patron_pid=checked_patron,
             transaction_location_pid=location.pid))
    assert res.status_code == 200
    assert Item.get_record_by_pid(item.pid).get('status') == ItemStatus.ON_LOAN
    item_data = data.get('metadata')
    actions = data.get('action_applied')
    assert item_data.get('status') == ItemStatus.ON_LOAN
    assert actions.get(LoanAction.CHECKOUT)
    loan_pid = actions[LoanAction.CHECKOUT].get('pid')
    item = Item.get_record_by_pid(item.pid)

    # request by requested patron to pick at another location
    res, data = postdata(
        client, 'api_item.librarian_request',
        dict(item_pid=item.pid,
             pickup_location_pid=loc_public_fully.pid,
             patron_pid=requested_patron))
    assert res.status_code == 200
    item_data = data.get('metadata')
    actions = data.get('action_applied')
    assert item_data.get('status') == ItemStatus.ON_LOAN
    assert actions.get(LoanAction.REQUEST)
    req_loan_pid = actions[LoanAction.REQUEST].get('pid')
    item = Item.get_record_by_pid(item.pid)

    # checkin at the request location
    res, data = postdata(
        client, 'api_item.checkin',
        dict(item_pid=item.pid,
             pid=loan_pid,
             transaction_location_pid=loc_public_fully.pid))
    assert res.status_code == 200
    # test the returned three actions
    loans = data.get('action_applied')
    checked_in_loan = loans.get(LoanAction.CHECKIN)
    cancelled_loan = loans.get(LoanAction.CANCEL)
    validated_loan = loans.get(LoanAction.VALIDATE)
    assert checked_in_loan.get('pid') == cancelled_loan.get('pid')
    assert validated_loan.get('pid') == req_loan_pid

    assert Loan.get_record_by_pid(loan_pid).get('state') == 'CANCELLED'
    new_loan = Loan.get_record_by_pid(req_loan_pid)
    assert new_loan.get('state') == 'ITEM_AT_DESK'
    assert Item.get_record_by_pid(item.pid).get('status') == \
        ItemStatus.AT_DESK
    # cancel request
    res, _ = postdata(client, 'api_item.cancel_loan',
                      dict(item_pid=item.pid, pid=req_loan_pid))
    assert res.status_code == 200
Ejemplo n.º 51
0
def test_items_requests(client, librarian_martigny_no_email,
                        patron_martigny_no_email, loc_public_martigny,
                        item_type_standard_martigny, lib_martigny,
                        item_lib_martigny, json_header, circulation_policies):
    """Test requesting an item and validation."""
    login_user_via_session(client, librarian_martigny_no_email.user)
    item = item_lib_martigny
    item_pid = item.pid
    patron = patron_martigny_no_email
    patron_pid = patron.pid
    library_pid = librarian_martigny_no_email.replace_refs()['library']['pid']

    location = loc_public_martigny

    assert not item.patron_request_rank(patron.get('barcode'))
    assert not item.is_requested_by_patron(patron.get('barcode'))
    # request
    res, data = postdata(
        client, 'api_item.librarian_request',
        dict(item_pid=item_pid,
             pickup_location_pid=location.pid,
             patron_pid=patron_pid))
    assert res.status_code == 200
    item_data = data.get('metadata')
    actions = data.get('action_applied')
    assert item_data.get('status') == ItemStatus.ON_SHELF
    assert actions.get(LoanAction.REQUEST)
    loan_pid = actions[LoanAction.REQUEST].get('pid')
    item = Item.get_record_by_pid(item_pid)
    assert item.patron_request_rank(patron.get('barcode')) == 1
    assert item.is_requested_by_patron(patron.get('barcode'))

    # test can not request item already requested to patron
    res = client.get(
        url_for('api_item.can_request',
                item_pid=item_pid,
                library_pid=lib_martigny.pid,
                patron_barcode=patron.get('barcode')))
    assert res.status_code == 200
    data = get_json(res)
    assert not data.get('can_request')

    # checkout
    res, data = postdata(client, 'api_item.checkout',
                         dict(item_pid=item_pid, pid=loan_pid))
    assert res.status_code == 200
    item_data = data.get('metadata')
    actions = data.get('action_applied')
    assert item_data.get('status') == ItemStatus.ON_LOAN
    assert actions.get(LoanAction.CHECKOUT)

    res, data = postdata(client, 'api_item.checkin',
                         dict(item_pid=item_pid, pid=loan_pid))
    assert res.status_code == 200
    item_data = data.get('metadata')
    actions = data.get('action_applied')
    assert item_data.get('status') == ItemStatus.ON_SHELF
    assert actions.get(LoanAction.CHECKIN)

    # request
    res, data = postdata(
        client, 'api_item.librarian_request',
        dict(item_pid=item_pid,
             pickup_location_pid=location.pid,
             patron_pid=patron_pid))
    assert res.status_code == 200
    item_data = data.get('metadata')
    actions = data.get('action_applied')
    assert item_data.get('status') == ItemStatus.ON_SHELF
    assert actions.get(LoanAction.REQUEST)
    loan_pid = actions[LoanAction.REQUEST].get('pid')

    # get requests to validate
    res = client.get(
        url_for('api_item.requested_loans', library_pid='not exists'))
    assert res.status_code == 500

    res = client.get(
        url_for('api_item.requested_loans', library_pid=library_pid))
    assert res.status_code == 200
    data = get_json(res)
    assert data['hits']['total'] == 1
    assert len(data['hits']['hits']) == 1

    # validate request
    res, data = postdata(client, 'api_item.validate_request',
                         dict(item_pid=item_pid, pid=loan_pid))
    assert res.status_code == 200
    item_data = data.get('metadata')
    actions = data.get('action_applied')
    assert item_data.get('status') == ItemStatus.AT_DESK
    assert actions.get(LoanAction.VALIDATE)

    # checkout
    res, data = postdata(client, 'api_item.checkout',
                         dict(item_pid=item_pid, pid=loan_pid))
    assert res.status_code == 200
    item_data = data.get('metadata')
    actions = data.get('action_applied')
    assert item_data.get('status') == ItemStatus.ON_LOAN
    assert actions.get(LoanAction.CHECKOUT)

    res, data = postdata(client, 'api_item.checkin',
                         dict(item_pid=item_pid, pid=loan_pid))
    assert res.status_code == 200
    item_data = data.get('metadata')
    actions = data.get('action_applied')
    assert item_data.get('status') == ItemStatus.ON_SHELF
    assert actions.get(LoanAction.CHECKIN)
def login_user(client, user):
    """Log user in."""
    flask_security.login_user(user, remember=True)
    login_user_via_session(client, email=user.email)
Ejemplo n.º 53
0
def test_recall_notification(client, patron_sion, lib_sion, json_header,
                             patron_sion_without_email1, item_lib_sion,
                             librarian_sion, circulation_policies,
                             loc_public_sion, mailbox):
    """Test recall notification."""
    mailbox.clear()
    login_user_via_session(client, librarian_sion.user)
    res, data = postdata(
        client, 'api_item.checkout',
        dict(
            item_pid=item_lib_sion.pid,
            patron_pid=patron_sion.pid,
            transaction_location_pid=loc_public_sion.pid,
            transaction_user_pid=librarian_sion.pid,
        ))
    assert res.status_code == 200
    loan_pid = data.get('action_applied')[LoanAction.CHECKOUT].get('pid')
    loan = Loan.get_record_by_pid(loan_pid)

    assert not loan.is_notified(
        notification_type=Notification.RECALL_NOTIFICATION_TYPE)
    # test notification permissions
    res, data = postdata(
        client, 'api_item.librarian_request',
        dict(item_pid=item_lib_sion.pid,
             pickup_location_pid=loc_public_sion.pid,
             patron_pid=patron_sion_without_email1.pid,
             transaction_library_pid=lib_sion.pid,
             transaction_user_pid=librarian_sion.pid))
    assert res.status_code == 200

    request_loan_pid = data.get('action_applied')[LoanAction.REQUEST].get(
        'pid')

    flush_index(NotificationsSearch.Meta.index)

    assert loan.is_notified(
        notification_type=Notification.RECALL_NOTIFICATION_TYPE)
    notification = get_notification(
        loan, notification_type=Notification.RECALL_NOTIFICATION_TYPE)
    assert notification.loan_pid == loan.pid
    assert not loan.is_notified(
        notification_type=Notification.AVAILABILITY_NOTIFICATION_TYPE)
    assert not get_notification(
        loan, notification_type=Notification.AVAILABILITY_NOTIFICATION_TYPE)

    # one new email for the patron
    assert mailbox[0].recipients == [patron_sion.dumps()['email']]

    mailbox.clear()

    # cancel request
    res, _ = postdata(
        client, 'api_item.cancel_item_request',
        dict(item_pid=item_lib_sion.pid,
             pid=request_loan_pid,
             transaction_user_pid=librarian_sion.pid,
             transaction_location_pid=loc_public_sion.pid))
    assert res.status_code == 200

    # no new notification is send for the second time
    res, _ = postdata(
        client, 'api_item.librarian_request',
        dict(item_pid=item_lib_sion.pid,
             pickup_location_pid=loc_public_sion.pid,
             patron_pid=patron_sion_without_email1.pid,
             transaction_library_pid=lib_sion.pid,
             transaction_user_pid=librarian_sion.pid))
    assert res.status_code == 200

    flush_index(NotificationsSearch.Meta.index)

    assert loan.is_notified(
        notification_type=Notification.RECALL_NOTIFICATION_TYPE)
    notification = get_notification(
        loan, notification_type=Notification.RECALL_NOTIFICATION_TYPE)
    assert notification.loan_pid == loan.pid
    assert not loan.is_notified(
        notification_type=Notification.AVAILABILITY_NOTIFICATION_TYPE)
    assert not get_notification(
        loan, notification_type=Notification.AVAILABILITY_NOTIFICATION_TYPE)
    assert len(mailbox) == 0
Ejemplo n.º 54
0
def test_delete(client, make_user, superuser, admin, moderator, submitter,
                user):
    """Test delete users permissions."""
    # Not logged
    res = client.delete(
        url_for('invenio_records_rest.user_item', pid_value=user['pid']))
    assert res.status_code == 401

    # Logged as user
    login_user_via_session(client, email=user['email'])
    res = client.delete(
        url_for('invenio_records_rest.user_item', pid_value=user['pid']))
    assert res.status_code == 403

    # Logged as submitter
    login_user_via_session(client, email=submitter['email'])
    res = client.delete(
        url_for('invenio_records_rest.user_item', pid_value=user['pid']))
    assert res.status_code == 403

    # Logged as moderator
    login_user_via_session(client, email=moderator['email'])
    res = client.delete(
        url_for('invenio_records_rest.user_item', pid_value=user['pid']))
    assert res.status_code == 403

    # Logged as admin
    login_user_via_session(client, email=admin['email'])
    res = client.delete(
        url_for('invenio_records_rest.user_item', pid_value=user['pid']))
    assert res.status_code == 204

    # Create a new user
    user = make_user('user', 'org3')

    # Logged as admin of other organisation
    other_admin = make_user('admin', 'org2')
    login_user_via_session(client, email=other_admin['email'])
    res = client.delete(
        url_for('invenio_records_rest.user_item', pid_value=user['pid']))
    assert res.status_code == 403

    # Logged as superuser
    login_user_via_session(client, email=superuser['email'])
    res = client.delete(
        url_for('invenio_records_rest.user_item', pid_value=user['pid']))
    assert res.status_code == 204
Ejemplo n.º 55
0
def test_edit_article_workflow_deleting(workflow_app,
                                        mocked_external_services):
    app_client = workflow_app.test_client()
    login_user_via_session(app_client, email='*****@*****.**')

    record = {
        '$schema':
        'http://localhost:5000/schemas/records/hep.json',
        'arxiv_eprints': [{
            'categories': ['nucl-th'],
            'value': '1802.03287'
        }],
        'control_number':
        123,
        'document_type': ['article'],
        'titles': [{
            'title':
            'Resource Pooling in Large-Scale Content Delivery Systems'
        }],
        'self': {
            '$ref': 'http://localhost:5000/schemas/records/hep.json'
        },
        '_collections': ['Literature']
    }
    factory = TestRecordMetadata.create_from_kwargs(json=record)
    eng_uuid = start('edit_article', data=factory.record_metadata.json)
    obj = WorkflowEngine.from_uuid(eng_uuid).objects[0]

    assert obj.status == ObjectStatus.WAITING
    assert obj.extra_data['callback_url']

    record = get_db_record('lit', 123)
    search = LiteratureSearch()
    search.get_source(record.id)

    # simulate changes in the editor and save
    obj.data['deleted'] = True

    payload = {
        'id': obj.id,
        'metadata': obj.data,
        '_extra_data': obj.extra_data
    }

    app_client.put(obj.extra_data['callback_url'],
                   data=json.dumps(payload),
                   content_type='application/json')

    obj = WorkflowEngine.from_uuid(eng_uuid).objects[0]
    assert obj.status == ObjectStatus.WAITING  # waiting for robot_upload
    assert obj.data['deleted'] is True

    do_robotupload_callback(
        app=workflow_app,
        workflow_id=obj.id,
        recids=[obj.data['control_number']],
    )

    record = get_db_record('lit', 123)
    assert record['deleted'] is True

    with pytest.raises(NotFoundError):
        search.get_source(record.id)

    obj = WorkflowEngine.from_uuid(eng_uuid).objects[0]
    assert obj.status == ObjectStatus.COMPLETED
    pending_records = WorkflowsPendingRecord.query.filter_by(
        workflow_id=obj.id).all()
    assert not pending_records
Ejemplo n.º 56
0
def test_library_secure_api_update(client, lib_fully, lib_martigny,
                                   librarian_martigny, librarian_sion,
                                   json_header, system_librarian_martigny,
                                   system_librarian_sion):
    """Test library secure api update."""
    # Martigny
    login_user_via_session(client, librarian_martigny.user)
    record_url = url_for('invenio_records_rest.lib_item',
                         pid_value=lib_martigny.pid)

    lib_martigny['name'] = 'New Name'
    res = client.put(record_url,
                     data=json.dumps(lib_martigny),
                     headers=json_header)
    # a librarian is authorized to update its library in its org
    assert res.status_code == 200

    record_url = url_for('invenio_records_rest.lib_item',
                         pid_value=lib_fully.pid)

    lib_fully['name'] = 'New Name'
    res = client.put(record_url,
                     data=json.dumps(lib_fully),
                     headers=json_header)
    # a librarian is not authorized to update an external library of its org
    assert res.status_code == 403

    login_user_via_session(client, system_librarian_martigny.user)
    res = client.put(record_url,
                     data=json.dumps(lib_fully),
                     headers=json_header)
    # a sys_librarian is authorized to update any library of its org
    assert res.status_code == 200

    record_url = url_for('invenio_records_rest.lib_item',
                         pid_value=lib_martigny.pid)
    lib_martigny['name'] = 'New Name 2'
    res = client.put(record_url,
                     data=json.dumps(lib_martigny),
                     headers=json_header)
    # a sys_librarian is authorized to update any library of its org
    assert res.status_code == 200

    # Sion
    login_user_via_session(client, librarian_sion.user)

    record_url = url_for('invenio_records_rest.lib_item',
                         pid_value=lib_fully.pid)

    lib_fully['name'] = 'New Name 2'
    res = client.put(record_url,
                     data=json.dumps(lib_fully),
                     headers=json_header)
    # librarian is not authorized to update an external library of another org
    assert res.status_code == 403

    login_user_via_session(client, system_librarian_sion.user)
    res = client.put(record_url,
                     data=json.dumps(lib_fully),
                     headers=json_header)
    # sys_lib is not authorized to update an external library of another org
    assert res.status_code == 403
Ejemplo n.º 57
0
def test_assign_from_an_author_to_another_that_is_not_stub(inspire_app):
    cataloger = create_user(role="cataloger")
    author_data = {
        "name": {
            "value": "Aad, Georges",
            "preferred_name": "Georges Aad"
        },
        "ids": [{
            "value": "G.Aad.1",
            "schema": "INSPIRE BAI"
        }],
        "stub": False,
    }
    from_author = create_record("aut")
    to_author = create_record("aut", data=author_data)
    literature = create_record(
        "lit",
        data={
            "authors": [
                {
                    "full_name": "Urhan, Ahmet",
                    "record": {
                        "$ref": "http://localhost:5000/api/authors/17200"
                    },
                },
                {
                    "full_name": "Urhan, Harun",
                    "record": {
                        "$ref":
                        f"http://localhost:5000/api/authors/{from_author['control_number']}"
                    },
                },
            ]
        },
    )

    with inspire_app.test_client() as client:
        login_user_via_session(client, email=cataloger.email)
        response = client.post(
            "/assign/author",
            data=orjson.dumps({
                "literature_recids": [literature["control_number"]],
                "from_author_recid":
                from_author["control_number"],
                "to_author_recid":
                to_author["control_number"],
            }),
            content_type="application/json",
        )
    response_status_code = response.status_code

    assert response_status_code == 200

    literature_after = LiteratureRecord.get_record_by_pid_value(
        literature["control_number"])
    literature_author = literature_after["authors"][1]
    assert literature_author["record"] == {
        "$ref":
        f"http://localhost:5000/api/authors/{to_author['control_number']}"
    }
    assert literature_author["curated_relation"]
    assert literature_author["ids"] == to_author["ids"]

    to_author_after = AuthorsRecord.get_record_by_pid_value(
        to_author["control_number"])
    assert not to_author_after["stub"]
Ejemplo n.º 58
0
def test_read(client, make_user, superuser, admin, moderator, submitter, user):
    """Test read users permissions."""
    # Not logged
    res = client.get(
        url_for('invenio_records_rest.user_item', pid_value=user['pid']))
    assert res.status_code == 401

    # Logged as user and read himself
    login_user_via_session(client, email=user['email'])
    res = client.get(
        url_for('invenio_records_rest.user_item', pid_value=user['pid']))
    assert res.status_code == 200
    assert res.json['metadata']['permissions'] == {
        'delete': False,
        'read': True,
        'update': True
    }

    # Logged as user and read other
    login_user_via_session(client, email=user['email'])
    res = client.get(
        url_for('invenio_records_rest.user_item', pid_value=moderator['pid']))
    assert res.status_code == 403

    # Logged as submitter
    login_user_via_session(client, email=submitter['email'])
    res = client.get(
        url_for('invenio_records_rest.user_item', pid_value=submitter['pid']))
    assert res.status_code == 200
    assert res.json['metadata']['permissions'] == {
        'delete': False,
        'read': True,
        'update': True
    }

    login_user_via_session(client, email=submitter['email'])
    res = client.get(
        url_for('invenio_records_rest.user_item', pid_value=user['pid']))
    assert res.status_code == 403

    # Logged as moderator
    login_user_via_session(client, email=moderator['email'])
    res = client.get(
        url_for('invenio_records_rest.user_item', pid_value=moderator['pid']))
    assert res.status_code == 200
    assert res.json['metadata']['permissions'] == {
        'delete': False,
        'read': True,
        'update': True
    }

    login_user_via_session(client, email=moderator['email'])
    res = client.get(
        url_for('invenio_records_rest.user_item', pid_value=user['pid']))
    assert res.status_code == 403

    # Logged as admin
    login_user_via_session(client, email=admin['email'])
    res = client.get(
        url_for('invenio_records_rest.user_item', pid_value=user['pid']))
    assert res.status_code == 200
    assert res.json['metadata']['permissions'] == {
        'delete': True,
        'read': True,
        'update': True
    }

    # Logged as admin, try to read superuser
    login_user_via_session(client, email=admin['email'])
    res = client.get(
        url_for('invenio_records_rest.user_item', pid_value=superuser['pid']))
    assert res.status_code == 403

    # Logged as admin of other organisation
    other_admin = make_user('admin', 'org2')
    login_user_via_session(client, email=other_admin['email'])
    res = client.get(
        url_for('invenio_records_rest.user_item', pid_value=user['pid']))
    assert res.status_code == 403

    # Logged as superuser
    login_user_via_session(client, email=superuser['email'])
    res = client.get(
        url_for('invenio_records_rest.user_item', pid_value=user['pid']))
    assert res.status_code == 200
    assert res.json['metadata']['permissions'] == {
        'delete': True,
        'read': True,
        'update': True
    }
Ejemplo n.º 59
0
def test_ebook_links(app, client, testdata, json_headers, admin):
    """Test ebook links when login_required."""

    # re-index documents to resolve eitems
    ri = RecordIndexer()
    for rec in testdata["documents"]:
        ri.index(rec)
    current_search.flush_and_refresh(index="*")

    def _test_list(endpoint):
        """Get list."""
        url = url_for(endpoint)
        res = client.get(url, headers=json_headers)
        return res.get_json()["hits"]["hits"]

    def _test_read(endpoint, pid):
        """Get record."""
        url = url_for(endpoint, pid_value=pid)
        res = client.get(url, headers=json_headers)
        return res.get_json()

    def _get_item(doc, eitem_pid):
        """Get item from the document record."""
        return [
            eitem for eitem in doc["eitems"]["hits"]
            if eitem["pid"] == eitem_pid
        ][0]

    def assert_urls(urls):
        """Test urls."""
        protected = urls[0]
        assert protected["login_required"]
        assert protected["value"] == "http://protected-cds-ils.ch/"
        login_required_url = app.config["CDS_ILS_EZPROXY_URL"].format(
            url=protected["value"])
        assert protected["login_required_url"] == login_required_url

        not_protected = urls[1]
        assert not not_protected["login_required"]
        assert not_protected["value"] == "http://cds-ils.ch/"
        assert "login_required_url" not in not_protected

    EITEM_PID = "eitemid-2"
    DOC_PID = "docid-2"
    # documents/literature search endpoint
    for endpoint in [
            "invenio_records_rest.docid_list",
            "invenio_records_rest.litid_list",
    ]:
        records = _test_list(endpoint)
        doc = [r for r in records if r["metadata"]["pid"] == DOC_PID][0]
        eitem = _get_item(doc["metadata"], EITEM_PID)
        assert_urls(eitem["urls"])

    # test doc item endpoint
    doc = _test_read("invenio_records_rest.docid_item", DOC_PID)
    eitem = _get_item(doc["metadata"], EITEM_PID)
    assert_urls(eitem["urls"])

    # eitems endpoint
    login_user_via_session(client, email=admin.email)
    records = _test_list("invenio_records_rest.eitmid_list")
    eitem = [r for r in records if r["metadata"]["pid"] == EITEM_PID][0]
    assert_urls(eitem["metadata"]["urls"])

    eitem = _test_read("invenio_records_rest.eitmid_item", EITEM_PID)
    assert_urls(eitem["metadata"]["urls"])
def test_librarian_permissions(
        client, system_librarian_martigny_no_email, json_header,
        patron_martigny_no_email,
        librarian_fully_no_email,
        patron_martigny_data_tmp,
        lib_saxon):
    """Test librarian permissions."""
    # Login as librarian
    login_user_via_session(client, librarian_fully_no_email.user)

    record = {
        "$schema": "https://ils.rero.ch/schema/patrons/patron-v0.0.1.json",
        "first_name": "first_name",
        "last_name": "Last_name",
        "street": "Avenue Leopold-Robert, 132",
        "postal_code": "1920",
        "city": "Martigny",
        "birth_date": "1967-06-07",
        "patron_type": {"$ref": "https://ils.rero.ch/api/patron_types/ptty1"},
        "library": {"$ref": "https://ils.rero.ch/api/libraries/lib1"},
        "phone": "+41324993111"
    }

    # can retrieve all type of users.
    list_url = url_for('invenio_records_rest.ptrn_list')
    res = client.get(list_url)
    assert res.status_code == 200
    data = get_json(res)
    assert data['hits']['total'] == 3

    # can create all type of users except system_librarians
    post_entrypoint = 'invenio_records_rest.ptrn_list'
    system_librarian = deepcopy(record)
    librarian = deepcopy(record)
    librarian_saxon = deepcopy(record)
    librarian_saxon['library'] = \
        {"$ref": "https://ils.rero.ch/api/libraries/lib2"}
    librarian['library'] = \
        {"$ref": "https://ils.rero.ch/api/libraries/lib3"}
    patron = deepcopy(record)
    patron['library'] = \
        {"$ref": "https://ils.rero.ch/api/libraries/lib3"}
    counter = 1
    for record in [
        {'data': patron, 'role': 'patron'},
        {'data': librarian, 'role': 'librarian'},
    ]:
        counter += 1
        data = record['data']
        data['roles'] = [record['role']]
        data['barcode'] = 'barcode' + str(counter)
        data['email'] = str(counter) + '@domain.com'
        with mock.patch('rero_ils.modules.patrons.api.'
                        'send_reset_password_instructions'):
            res, _ = postdata(
                client,
                post_entrypoint,
                data
            )
            assert res.status_code == 201
            user = get_json(res)['metadata']
            user_pid = user.get('pid')
            record_url = url_for('invenio_records_rest.ptrn_item',
                                 pid_value=user_pid)
            res = client.get(record_url)
            assert res.status_code == 200
            user = get_json(res)['metadata']

    # can update all type of user records except system_librarian.
            user['first_name'] = 'New Name' + str(counter)
            res = client.put(
                record_url,
                data=json.dumps(user),
                headers=json_header
            )
            assert res.status_code == 200

    # can not add the role system_librarian to user
            user['roles'] = ['system_librarian']
            res = client.put(
                record_url,
                data=json.dumps(user),
                headers=json_header
            )
            assert res.status_code == 403

    # can delete all type of user records except system_librarian.
            record_url = url_for('invenio_records_rest.ptrn_item',
                                 pid_value=user_pid)

            res = client.delete(record_url)
            assert res.status_code == 204

    # can not create librarians of same libray.
    counter = 1
    for record in [
        {'data': librarian_saxon, 'role': 'librarian'},
    ]:
        counter += 1
        data = record['data']
        data['roles'] = [record['role']]
        data['barcode'] = 'barcode' + str(counter)
        data['email'] = str(counter) + '@domain.com'
        with mock.patch('rero_ils.modules.patrons.api.'
                        'send_reset_password_instructions'):
            res, _ = postdata(
                client,
                post_entrypoint,
                data
            )
            assert res.status_code == 403

    system_librarian['roles'] = ['system_librarian']
    system_librarian['barcode'] = 'barcode'
    system_librarian['email'] = '*****@*****.**'
    with mock.patch('rero_ils.modules.patrons.api.'
                    'send_reset_password_instructions'):
        res, _ = postdata(
            client,
            post_entrypoint,
            system_librarian,
        )
        assert res.status_code == 403

    # can update all type of user records except system_librarian.
    record_url = url_for('invenio_records_rest.ptrn_item',
                         pid_value=system_librarian_martigny_no_email.pid)
    system_librarian_martigny_no_email['first_name'] = 'New Name'
    res = client.put(
        record_url,
        data=json.dumps(system_librarian_martigny_no_email),
        headers=json_header
    )
    assert res.status_code == 403

    # can delete all type of user records except system_librarian.
    sys_librarian_pid = system_librarian_martigny_no_email.get('pid')
    record_url = url_for('invenio_records_rest.ptrn_item',
                         pid_value=sys_librarian_pid)

    res = client.delete(record_url)
    assert res.status_code == 403