def test_brwreq_accept_decline_extension_only_librarian(
        client, testdata, json_headers, users):
    """Test that only librarian can accept or decline an extension."""

    tests = [_accept_extension_action, _decline_extension_action]
    for action in tests:
        user_login(client, "librarian", users)

        # create request
        brwreq, brwreq_pid = _create_on_loan_brwreq_with_pending_extension(
            "1", client, json_headers)

        loan_end_date = arrow.utcnow() + timedelta(days=15)
        data = dict(loan_end_date=loan_end_date.date().isoformat())

        # accept/decline

        # anonymous, forbidden
        user_logout(client)
        res = action(brwreq_pid, data, client, json_headers)
        assert res.status_code == 401

        # patron, forbidden
        user_login(client, "patron1", users)
        res = action(brwreq_pid, data, client, json_headers)
        assert res.status_code == 403

        # librarian, success
        user_login(client, "librarian", users)
        res = action(brwreq_pid, data, client, json_headers)
        assert res.status_code == 200
def test_brwreq_request_extension_only_owner(client, testdata, json_headers,
                                             users):
    """Test that patron can request extension only for his own loan."""
    user_login(client, "librarian", users)

    brwreq, brwreq_pid = _create_on_loan_brwreq_random_dates(
        "1", client, json_headers)

    # anonymous, forbidden
    user_logout(client)
    res = _request_extension_action(brwreq_pid, client, json_headers)
    assert res.status_code == 401

    # patron2 is not the owner, forbidden
    user_login(client, "patron2", users)
    res = _request_extension_action(brwreq_pid, client, json_headers)
    assert res.status_code == 403

    # patron1 is the owner, success
    user_login(client, "patron1", users)
    res = _request_extension_action(brwreq_pid, client, json_headers)
    assert res.status_code == 200
    extension = res.get_json()["metadata"]["patron_loan"]["extension"]
    assert extension["status"] == "PENDING"
    assert extension["request_date"] == arrow.now().date().isoformat()

    # create a new one with patron2 owner, librarian can request extension
    user_login(client, "librarian", users)
    brwreq, brwreq_pid = _create_on_loan_brwreq_random_dates(
        "2", client, json_headers)
    res = _request_extension_action(brwreq_pid, client, json_headers)
    assert res.status_code == 200
    assert extension["status"] == "PENDING"
    assert extension["request_date"] == arrow.now().date().isoformat()
예제 #3
0
def test_stats_downloads_views_permissions(client, json_headers, users,
                                           testdata, mocker):
    """Test permissions on downloads/views stats."""

    # mock record_viewed signal because travis timed out and the signal does
    # not need to be tested here
    mocker.patch("invenio_app_ils.signals.record_viewed.send", )

    url_open_access = url_for("ils_document_stats.docid_stats",
                              pid_value="docid-open-access")
    url_closed_access = url_for("ils_document_stats.docid_stats",
                                pid_value="docid-closed-access")
    params = {}
    params["event"] = "record-view"

    # permission for librarian
    user_login(client, "librarian", users)
    res = client.post(url_open_access,
                      headers=json_headers,
                      data=json.dumps(params))
    assert res.status_code == 202

    res = client.post(url_closed_access,
                      headers=json_headers,
                      data=json.dumps(params))
    assert res.status_code == 202

    user_logout(client)

    # permission for patron
    user_login(client, "patron1", users)

    res = client.post(url_open_access,
                      headers=json_headers,
                      data=json.dumps(params))
    assert res.status_code == 202

    res = client.post(url_closed_access,
                      headers=json_headers,
                      data=json.dumps(params))
    assert res.status_code == 403

    user_logout(client)

    # permission for unauthenticated user
    res = client.post(url_open_access,
                      headers=json_headers,
                      data=json.dumps(params))
    assert res.status_code == 202

    res = client.post(url_closed_access,
                      headers=json_headers,
                      data=json.dumps(params))
    assert res.status_code == 401
def test_most_loaned_permissions(client, json_headers, users, testdata):
    """Test that only the backoffice is able to list the most loaned items."""
    url = url_for("invenio_app_ils_circulation_stats.most-loaned")
    tests = [
        ("admin", 200),
        ("librarian", 200),
        ("patron1", 403),
        ("anonymous", 401),
    ]
    for username, status in tests:
        user_login(client, username, users)
        res = client.get(url, headers=json_headers)
        assert res.status_code == status
        user_logout(client)
def test_anonymization(app, client, json_headers, users, testdata):
    """Test anonymization of a user."""
    # Anonymize patron
    patron_pid = users["patron3"].id

    check_user_exists(patron_pid)
    cancel_active_loans(patron_pid, client, users)
    anonymize_patron_data(patron_pid)
    check_user_deleted(patron_pid)

    user_login(client, "admin", users)
    check_user_activity(app, patron_pid, client, json_headers)
    user_logout(client)

    # Anonymize librarian
    librarian_pid = users["librarian"].id

    check_user_exists(librarian_pid)
    cancel_active_loans(librarian_pid, client, users)
    anonymize_patron_data(librarian_pid)
    check_user_deleted(librarian_pid)

    # Anonymize patron while logged in
    patron_pid = users["patron2"].id
    user_login(client, "patron2", users)

    check_user_exists(patron_pid)
    cancel_active_loans(patron_pid, client, users)
    anonymize_patron_data(patron_pid)
    check_user_deleted(patron_pid)

    # It should fail when anonymizing patron with active loans
    patron_pid = users["patron1"].id
    check_user_exists(patron_pid)
    with pytest.raises(AnonymizationActiveLoansError):
        assert anonymize_patron_data(patron_pid)
예제 #6
0
def test_loan_update_date(client, json_headers, users, testdata):
    """Test the edition of the dates on a loan."""
    pid = testdata["loans"][4]["pid"]  # Item on loan

    # Patron cannot update loan
    user_login(client, "patron1", users)
    res = _post_loan_update(client, json_headers, pid)
    assert res.status_code == 403
    user_logout(client)

    # Librarian can
    user_login(client, "librarian", users)
    old_loan = _load_result(client.get(_url_loan(pid), headers=json_headers))
    res = _post_loan_update(client, json_headers, pid)
    assert res.status_code == 202
    new_loan = _load_result(res)
    assert old_loan["updated"] < new_loan["updated"]  # Liveness check

    # Update both values
    start_date = "2020-01-01"
    end_date = _today(+1)
    res = _post_loan_update(client, json_headers, pid,
                            start_date=start_date,
                            end_date=end_date)
    assert res.status_code == 202
    new_loan_meta = _load_result(res)["metadata"]
    assert new_loan_meta["start_date"] == start_date
    assert new_loan_meta["end_date"] == end_date

    # Start date after today
    start_date = _today(+2)
    end_date = _today(+3)
    res = _post_loan_update(client, json_headers, pid,
                            start_date=start_date,
                            end_date=end_date)
    assert res.status_code == 400

    # No relative constraints on non-active loans
    pid = testdata["loans"][3]["pid"]  # Pending
    res = _post_loan_update(client, json_headers, pid,
                            request_start_date=start_date,
                            request_expire_date=end_date)
    assert res.status_code == 202
    new_loan_meta = _load_result(res)["metadata"]
    assert new_loan_meta["request_start_date"] == start_date
    assert new_loan_meta["request_expire_date"] == end_date

    # Negative date range
    start_date = "2000-02-01"
    end_date = "2000-01-01"
    res = _post_loan_update(client, json_headers, pid,
                            request_start_date=start_date,
                            request_expire_date=end_date)
    assert res.status_code == 400

    # Illegal combination of parameters
    start_date = _today(-2)
    end_date = _today(+2)
    res = _post_loan_update(client, json_headers, pid,
                            start_date=start_date,
                            end_date=end_date,
                            request_start_date=start_date,
                            request_expire_date=end_date)
    assert res.status_code == 400
예제 #7
0
def test_email_on_overdue_loans(app_with_mail, db, users, testdata, mocker,
                                client, json_headers):
    """Test that an email is sent for a loan that is overdue."""
    mocker.patch(
        "invenio_app_ils.patrons.api.Patron.get_patron",
        return_value=Patron(users["patron1"].id),
    )

    def prepare_data():
        """Prepare data."""
        days = current_app.config[
            "ILS_CIRCULATION_MAIL_OVERDUE_REMINDER_INTERVAL"]
        loans = testdata["loans"]

        recs = []
        now = arrow.utcnow()

        def new_end_date(loan, date):
            loan["end_date"] = date.date().isoformat()
            loan["state"] = "ITEM_ON_LOAN"
            loan.commit()
            recs.append(loan)

        # overdue loans
        date = now - timedelta(days=days)
        new_end_date(loans[0], date)

        date = now - timedelta(days=days * 2)
        new_end_date(loans[1], date)

        # not overdue
        date = now - timedelta(days=-1)
        new_end_date(loans[2], date)

        # not overdue or overdue but not to be notified
        remaining_not_overdue = loans[3:]
        for loan in remaining_not_overdue:
            days = random.choice([-1, 0, 1])
            date = now - timedelta(days=days)
            new_end_date(loan, date)
        db.session.commit()

        indexer = RecordIndexer()
        for rec in recs:
            indexer.index(rec)

        current_search.flush_and_refresh(index="*")

    user_login(client, "librarian", users)

    # test individual overdue loan
    prepare_data()
    loans = testdata["loans"]

    email_url = url_for(
        "invenio_app_ils_circulation.loanid_email",
        pid_value=loans[0]["pid"],
    )

    res = client.post(email_url, headers=json_headers)
    assert res.status_code == 202

    # test individual not overdue loan
    email_url = url_for(
        "invenio_app_ils_circulation.loanid_email",
        pid_value=loans[2]["pid"],
    )

    res = client.post(email_url, headers=json_headers)
    assert res.status_code == 400

    user_logout(client)

    # test all loans
    with app_with_mail.extensions["mail"].record_messages() as outbox:
        assert len(outbox) == 0
        send_overdue_loans_mail_reminder.apply_async()
        assert len(outbox) == 2