Esempio n. 1
0
def test_link_orcid_auth_callback_with_affiliation(name, mocker, client):
    """Test ORCID callback - the user authorized the organisation access to the ORCID profile."""
    mocker.patch(
        "requests_oauthlib.OAuth2Session.fetch_token", lambda self, *args, **
        kwargs: dict(name="NEW TEST",
                     access_token="ABC123",
                     orcid="ABC-123-456-789",
                     scope=['/read-limited,/activities/update'],
                     expires_in="1212",
                     refresh_token="ABC1235"))
    m = mocker.patch("orcid_hub.orcid_client.MemberAPIV3")
    mocker.patch("orcid_hub.orcid_client.SourceClientId")

    org = Organisation.get(name="THE ORGANISATION")
    test_user = User.create(name=name,
                            email="*****@*****.**",
                            organisation=org,
                            orcid="ABC123",
                            confirmed=True)

    UserOrg.create(user=test_user,
                   org=org,
                   affiliations=(Affiliation.EMP | Affiliation.EDU))

    client.login(test_user)
    resp = client.get("/link")
    state = session['oauth_state']

    resp = client.get(f"/auth?state={state}")
    api_mock = m.return_value
    test_user = User.get(test_user.id)
    assert test_user.orcid == "ABC-123-456-789"

    orcid_token = OrcidToken.get(user=test_user, org=org)
    assert orcid_token.access_token == "ABC123"

    api_mock.create_or_update_affiliation.assert_has_calls([
        call(affiliation=Affiliation.EDU, initial=True),
        call(affiliation=Affiliation.EMP, initial=True),
    ])

    # User with no Affiliation, should get flash warning.
    user_org = UserOrg.get(user=test_user, org=org)
    user_org.affiliations = Affiliation.NONE
    user_org.save()
    orcid_token.delete_instance()

    assert OrcidToken.select().where(OrcidToken.user == test_user,
                                     OrcidToken.org == org).count() == 0
    resp = client.get(f"/auth?state={state}")
    assert resp.status_code == 302
    assert b"<!DOCTYPE HTML" in resp.data, "Expected HTML content"
    assert "profile" in resp.location, "redirection to 'profile' showing the ORCID"
    assert OrcidToken.select().where(OrcidToken.user == test_user,
                                     OrcidToken.org == org).count() == 1

    get_person = mocker.patch("requests_oauthlib.OAuth2Session.get",
                              return_value=Mock(status_code=200))
    resp = client.get("/profile", follow_redirects=True)
    assert b"can create and update research activities" in resp.data
    get_person.assert_called_once()

    get_person = mocker.patch("requests_oauthlib.OAuth2Session.get",
                              return_value=Mock(status_code=401))
    resp = client.get("/profile", follow_redirects=True)
    assert b"you'll be taken to ORCID to create or sign into your ORCID record" in resp.data
    get_person.assert_called_once()
Esempio n. 2
0
def test_member_api_v3(app, mocker):
    """Test MemberAPI extension and wrapper of ORCID API."""
    mocker.patch.multiple("orcid_hub.app.logger",
                          error=DEFAULT,
                          exception=DEFAULT,
                          info=DEFAULT)
    org = Organisation.get(name="THE ORGANISATION")
    user = User.create(orcid="1001-0001-0001-0001",
                       name="TEST USER 123",
                       email="*****@*****.**",
                       organisation=org,
                       confirmed=True)
    UserOrg.create(user=user, org=org, affiliation=Affiliation.EDU)

    api = MemberAPIV3(user=user)
    assert api.api_client.configuration.access_token is None or api.api_client.configuration.access_token == ''

    api = MemberAPIV3(user=user, org=org)
    assert api.api_client.configuration.access_token is None or api.api_client.configuration.access_token == ''

    api = MemberAPIV3(user=user, org=org, access_token="ACCESS000")
    assert api.api_client.configuration.access_token == 'ACCESS000'

    OrcidToken.create(access_token="ACCESS123",
                      user=user,
                      org=org,
                      scopes="/read-limited,/activities/update",
                      expires_in='121')
    api = MemberAPIV3(user=user, org=org)
    assert api.api_client.configuration.access_token == "ACCESS123"

    # Test API call auditing:
    request_mock = mocker.patch.object(
        api.api_client.rest_client.pool_manager, "request",
        MagicMock(return_value=Mock(data=b"""{"mock": "data"}""", status=200)))

    api.get_record()

    request_mock.assert_called_with(
        "GET",
        "https://api.sandbox.orcid.org/v3.0/1001-0001-0001-0001",
        fields=None,
        preload_content=False,
        timeout=None,
        headers={
            "Accept": "application/json",
            "Content-Type": "application/json",
            "User-Agent": "Swagger-Codegen/1.0.0/python",
            "Authorization": "Bearer ACCESS123"
        })

    api_call = OrcidApiCall.select().first()
    assert api_call.response == '{"mock": "data"}'
    assert api_call.url == "https://api.sandbox.orcid.org/v3.0/1001-0001-0001-0001"

    create = mocker.patch.object(OrcidApiCall,
                                 "create",
                                 side_effect=Exception("FAILURE"))
    api.get_record()
    create.assert_called()
    app.logger.exception.assert_called_with(
        "Failed to create API call log entry.")

    # Handling of get_record
    call_api = mocker.patch.object(api.api_client,
                                   "call_api",
                                   side_effect=v3.rest.ApiException(
                                       reason="FAILURE", status=401))
    delete = mocker.patch.object(OrcidToken, "delete")
    with pytest.raises(v3.rest.ApiException):
        api.get_record()
    call_api.assert_called_once()
    delete.assert_called_once()

    call_api = mocker.patch.object(api.api_client,
                                   "call_api",
                                   side_effect=v3.rest.ApiException(
                                       reason="FAILURE 999", status=999))
    with pytest.raises(v3.rest.ApiException):
        api.get_record()
    app.logger.error.assert_called_with(
        "ApiException Occurred: (999)\nReason: FAILURE 999\n")

    call_api = mocker.patch.object(api.api_client,
                                   "call_api",
                                   side_effect=v3.rest.ApiException(
                                       reason="FAILURE", status=401))
    with pytest.raises(v3.rest.ApiException):
        api.get_record()
    app.logger.error.assert_called()
    call_api.assert_called_once()

    call_api = mocker.patch.object(api.api_client,
                                   "call_api",
                                   return_value=(
                                       Mock(data=b"""{"mock": "data"}"""),
                                       200,
                                       [],
                                   ))
    api.get_record()
    call_api.assert_called_with(f"/v3.0/{user.orcid}",
                                "GET",
                                _preload_content=False,
                                auth_settings=["orcid_auth"],
                                header_params={"Accept": "application/json"},
                                response_type=None)

    # Failed logging:
    request_mock = mocker.patch("orcid_api_v3.rest.RESTClientObject.request",
                                return_value=Mock(data=None, status_code=200))
Esempio n. 3
0
def test_proxy_get_profile(app_req_ctx):
    """Test the echo endpoint."""
    user = User.get(email="*****@*****.**")
    token = Token.get(user=user)
    orcid_id = "0000-0000-0000-00X3"

    with app_req_ctx(
            f"/orcid/api/v1.23/{orcid_id}",
            headers=dict(authorization=f"Bearer {token.access_token}")
    ) as ctx, patch("orcid_hub.apis.requests.Session.send") as mocksend:
        mockresp = MagicMock(status_code=200)
        mockresp.raw.stream = lambda *args, **kwargs: iter(
            [b"""{"data": "TEST"}"""])
        mockresp.raw.headers = {
            "Server": "TEST123",
            "Content-Type": "application/json;charset=UTF-8",
            "Transfer-Encoding": "chunked",
            "Connection": "keep-alive",
            "Access-Control-Allow-Origin": "*",
            "Cache-Control": "no -cache, no-store, max-age=0, must-revalidate",
            "Pragma": "no-cache",
            "Expires": "0",
        }
        mocksend.return_value = mockresp
        resp = ctx.app.full_dispatch_request()
        assert resp.status_code == 200
        args, kwargs = mocksend.call_args
        assert kwargs["stream"]
        assert args[0].url == f"https://api.sandbox.orcid.org/v1.23/{orcid_id}"
        assert args[0].headers[
            "Authorization"] == "Bearer ORCID-TEST-ACCESS-TOKEN"

        data = json.loads(resp.data)
        assert data == {"data": "TEST"}

    with app_req_ctx(
            f"/orcid/api/v1.23/{orcid_id}",
            headers=dict(authorization=f"Bearer {token.access_token}"),
            method="POST",
            data=b"""{"data": "REQUEST"}""") as ctx, patch(
                "orcid_hub.apis.requests.Session.send") as mocksend:
        mockresp = MagicMock(status_code=201)
        mockresp.raw.stream = lambda *args, **kwargs: iter(
            [b"""{"data": "TEST"}"""])
        mockresp.raw.headers = {
            "Server": "TEST123",
            "Content-Type": "application/json;charset=UTF-8",
            "Transfer-Encoding": "chunked",
            "Connection": "keep-alive",
            "Access-Control-Allow-Origin": "*",
            "Cache-Control": "no -cache, no-store, max-age=0, must-revalidate",
            "Pragma": "no-cache",
            "Expires": "0",
        }
        mocksend.return_value = mockresp
        resp = ctx.app.full_dispatch_request()
        assert resp.status_code == 201
        args, kwargs = mocksend.call_args
        assert kwargs["stream"]
        assert args[0].url == f"https://api.sandbox.orcid.org/v1.23/{orcid_id}"
        assert args[0].headers[
            "Authorization"] == "Bearer ORCID-TEST-ACCESS-TOKEN"

        data = json.loads(resp.data)
        assert data == {"data": "TEST"}

    # malformatted ORCID ID:
    with app_req_ctx(
            "/orcid/api/v1.23/NOT-ORCID-ID/PATH",
            headers=dict(authorization=f"Bearer {token.access_token}")) as ctx:
        resp = ctx.app.full_dispatch_request()
        assert resp.status_code == 415

    # no ORCID access token
    with app_req_ctx(
            "/orcid/api/v1.23/0000-0000-0000-11X2/PATH",
            headers=dict(authorization=f"Bearer {token.access_token}")) as ctx:
        resp = ctx.app.full_dispatch_request()
        assert resp.status_code == 403
Esempio n. 4
0
def test_is_emp_or_edu_record_present(app, mocker):
    """Test 'is_emp_or_edu_record_present' method."""
    mocker.patch.multiple("orcid_hub.app.logger",
                          error=DEFAULT,
                          exception=DEFAULT,
                          info=DEFAULT)
    org = Organisation.get(name="THE ORGANISATION")
    user = User.create(orcid="1001-0001-0001-0001",
                       name="TEST USER 123",
                       email="*****@*****.**",
                       organisation=org,
                       confirmed=True)
    UserOrg.create(user=user, org=org, affiliation=Affiliation.EDU)

    api = MemberAPIV3(user=user, org=org)
    test_responses = [
        None, """{"mock": "data"}""", """{
            "employment-summary": [{"source": {"source-client-id": {"path": "CLIENT000"}}, "put-code": 123}],
            "education-summary": [{"source": {"source-client-id": {"path": "CLIENT000"}}, "put-code": 456}]
        }""", """{"employment-summary": [], "education-summary": []}"""
    ]

    for data in test_responses:
        with patch.object(v3.api_client.ApiClient,
                          "call_api",
                          return_value=Mock(data=data)) as call_api:
            api.is_emp_or_edu_record_present(Affiliation.EDU)
            call_api.assert_called_with("/v3.0/{orcid}/educations",
                                        "GET",
                                        {"orcid": "1001-0001-0001-0001"}, [],
                                        {"Accept": "application/json"},
                                        _preload_content=False,
                                        _request_timeout=None,
                                        _return_http_data_only=True,
                                        async_req=None,
                                        auth_settings=["orcid_auth"],
                                        body=None,
                                        collection_formats={},
                                        files={},
                                        post_params=[],
                                        response_type="EducationsSummaryV30")
            api.is_emp_or_edu_record_present(Affiliation.EMP)
            call_api.assert_called_with("/v3.0/{orcid}/employments",
                                        "GET",
                                        {"orcid": "1001-0001-0001-0001"}, [],
                                        {"Accept": "application/json"},
                                        _preload_content=False,
                                        _request_timeout=None,
                                        _return_http_data_only=True,
                                        async_req=None,
                                        auth_settings=["orcid_auth"],
                                        body=None,
                                        collection_formats={},
                                        files={},
                                        post_params=[],
                                        response_type="EmploymentsSummaryV30")

    with patch.object(v3.api_client.ApiClient,
                      "call_api",
                      side_effect=ApiException(reason="FAILURE",
                                               status=401)) as call_api:
        api.is_emp_or_edu_record_present(Affiliation.EDU)
        app.logger.error.assert_called_with(
            "For TEST USER 123 ([email protected]) while checking for employment "
            "and education records, Encountered Exception: (401)\nReason: FAILURE\n"
        )

    with patch.object(v3.api_client.ApiClient,
                      "call_api",
                      side_effect=Exception("EXCEPTION")) as call_api:
        api.is_emp_or_edu_record_present(Affiliation.EDU)
        app.logger.exception.assert_called_with(
            "Failed to verify presence of employment or education record.")
Esempio n. 5
0
def test_orcid_login_callback_admin_flow(patch, patch2, request_ctx):
    """Test login from orcid callback function for Organisation Technical contact."""
    org = Organisation.create(
        name="THE ORGANISATION:test_orcid_login_callback_admin_flow",
        tuakiri_name="THE ORGANISATION:test_orcid_login_callback_admin_flow",
        confirmed=False,
        orcid_client_id="CLIENT ID",
        orcid_secret="Client Secret",
        city="CITY",
        country="COUNTRY",
        disambiguated_id="ID",
        disambiguation_source="RINGGOLD",
        is_email_sent=True)
    u = User.create(
        email="*****@*****.**",
        roles=Role.TECHNICAL,
        orcid="123",
        confirmed=False,
        organisation=org)
    UserOrg.create(user=u, org=org, is_admin=True)
    token = utils.generate_confirmation_token(email=u.email, org=org.name)

    with request_ctx() as resp:
        request.args = {"invitation_token": token, "state": "xyz"}
        session['oauth_state'] = "xyz"
        resp = authcontroller.orcid_login_callback(request)
        assert resp.status_code == 302
        assert resp.location.startswith("/")
    with request_ctx() as respx:
        request.args = {"invitation_token": token, "state": "xyzabc"}
        session['oauth_state'] = "xyz"
        respx = authcontroller.orcid_login_callback(request)
        assert respx.status_code == 302
        assert respx.location.startswith("/")
    with request_ctx() as resp:
        request.args = {"invitation_token": token, "state": "xyz", "error": "access_denied"}
        session['oauth_state'] = "xyz"
        resp = authcontroller.orcid_login_callback(request)
        assert resp.status_code == 302
        assert resp.location.startswith("/")
    with request_ctx() as ct:
        token = utils.generate_confirmation_token(email=u.email, org=None)
        request.args = {"invitation_token": token, "state": "xyz"}
        session['oauth_state'] = "xyz"
        ctxx = authcontroller.orcid_login_callback(request)
        assert ctxx.status_code == 302
        assert ctxx.location.startswith("/")
    with request_ctx() as ctxxx:
        request.args = {"invitation_token": token, "state": "xyzabc"}
        session['oauth_state'] = "xyz"
        ctxxx = authcontroller.orcid_login_callback(request)
        assert ctxxx.status_code == 302
        assert ctxxx.location.startswith("/")
    with request_ctx() as cttxx:
        request.args = {"invitation_token": token, "state": "xyz", "error": "access_denied"}
        session['oauth_state'] = "xyz"
        cttxx = authcontroller.orcid_login_callback(request)
        assert cttxx.status_code == 302
        assert cttxx.location.startswith("/")
    with request_ctx() as ct:
        token = utils.generate_confirmation_token(email=u.email, org=None)
        request.args = {"invitation_token": token, "state": "xyz"}
        session['oauth_state'] = "xyz"
        ct = authcontroller.orcid_login_callback(request)
        assert ct.status_code == 302
        assert ct.location.startswith("/")
    with request_ctx():
        request.args = {"invitation_token": None, "state": "xyz"}
        session['oauth_state'] = "xyz"
        ct = authcontroller.orcid_login_callback(request)
        assert ct.status_code == 302
        assert ct.location.startswith("/")
    with request_ctx():
        # Test case for catching general exception: invitation token here is integer, so an exception will be thrown.
        request.args = {"invitation_token": 123, "state": "xyz"}
        session['oauth_state'] = "xyz"
        ct = authcontroller.orcid_login_callback(request)
        assert ct.status_code == 302
        assert ct.location.startswith("/")
    with request_ctx():
        # User login via orcid, where organisation is not confirmed.
        u.orcid = "123"
        u.save()
        request.args = {"invitation_token": None, "state": "xyz-about"}
        session['oauth_state'] = "xyz-about"
        resp = authcontroller.orcid_login_callback(request)
        assert resp.status_code == 302
        assert resp.location.startswith("/about")
    with request_ctx():
        # User login via orcid, where organisation is confirmed, so showing viewmembers page.
        org.tech_contact = u
        org.confirmed = True
        org.save()
        request.args = {"invitation_token": None, "state": "xyz"}
        session['oauth_state'] = "xyz"
        resp = authcontroller.orcid_login_callback(request)
        assert resp.status_code == 302
        assert resp.location.startswith("/admin/viewmembers/")
    with request_ctx():
        # User login via orcid, where organisation is not confirmed and user is tech, so showing confirm org page.
        org.confirmed = False
        org.save()
        request.args = {"invitation_token": None, "state": "xyz"}
        session['oauth_state'] = "xyz"
        resp = authcontroller.orcid_login_callback(request)
        assert resp.status_code == 302
        assert resp.location.startswith("/confirm/organisation")
Esempio n. 6
0
def test_affiliation_api(client):
    """Test affiliation API in various formats."""
    resp = client.post(
        "/oauth/token",
        content_type="application/x-www-form-urlencoded",
        data=
        b"grant_type=client_credentials&client_id=TEST0-ID&client_secret=TEST0-SECRET"
    )
    data = json.loads(resp.data)
    access_token = data["access_token"]
    resp = client.post(
        "/api/v1.0/affiliations/?filename=TEST42.csv",
        headers=dict(authorization=f"Bearer {access_token}"),
        content_type="text/csv",
        data=
        b"First Name,Last Name,email,Organisation,Affiliation Type,Role,Department,Start Date,"
        b"End Date,City,State,Country,Disambiguated Id,Disambiguated Source\n"
        b"Researcher,Par,[email protected],Royal Org1,Staff,Programme Guide - "
        b"ORCID,Research Funding,2016-09,,Wellington,SATE,NZ,,\n"
        b"Roshan,Pawar,[email protected],Royal Org1,Staff,AAA,Research "
        b"Funding,2016-09,,Wellington,SATE,NZ,,\n"
        b"Roshan,Pawar,[email protected],Royal Org1,Student,BBB,Research "
        b"Funding,2016-09,,Wellington,SATE,New Zealand,,")
    data = json.loads(resp.data)
    assert data["filename"] == "TEST42.csv"
    assert data["task-type"] == "AFFILIATION"
    assert len(data["records"]) == 3
    task_id = data["id"]

    resp = client.get("/api/v1.0/tasks",
                      headers=dict(authorization=f"Bearer {access_token}"))
    tasks = json.loads(resp.data)
    assert tasks[0]["id"] == task_id

    task_copy = copy.deepcopy(data)
    del (task_copy["id"])
    task_copy["filename"] = "TASK-COPY.csv"
    resp = client.post("/api/v1.0/affiliations/",
                       headers=dict(authorization=f"Bearer {access_token}"),
                       content_type="application/json",
                       data=json.dumps(task_copy))
    assert Task.select().count() == 2

    for r in data["records"]:
        del (r["id"])
        r["city"] = "TEST000"
    resp = client.post(f"/api/v1.0/affiliations/{task_id}",
                       headers=dict(authorization=f"Bearer {access_token}"),
                       content_type="application/json",
                       data=json.dumps(data))
    data = json.loads(resp.data)
    assert len(data["records"]) == 3
    # should get a new set of records

    del (data["records"][2])
    resp = client.post(f"/api/v1.0/affiliations/{task_id}",
                       headers=dict(authorization=f"Bearer {access_token}"),
                       content_type="application/json",
                       data=json.dumps(data))
    new_data = json.loads(resp.data)
    assert len(new_data["records"]) == 2

    incorrect_data = copy.deepcopy(data)
    incorrect_data["records"].insert(0, {
        "first-name": "TEST000 FN",
        "last-name": "TEST000 LN",
    })
    resp = client.post(f"/api/v1.0/affiliations/{task_id}",
                       headers=dict(authorization=f"Bearer {access_token}"),
                       content_type="application/json",
                       data=json.dumps(incorrect_data))
    data = json.loads(resp.data)
    assert resp.status_code == 422
    assert data["error"] == "Validation error."

    resp = client.get(f"/api/v1.0/affiliations/{task_id}",
                      headers=dict(authorization=f"Bearer {access_token}"))
    data = json.loads(resp.data)
    incorrect_data = copy.deepcopy(data)
    incorrect_data["records"].insert(
        0, {
            "email": "*****@*****.**",
            "first-name": "TEST000 FN",
            "last-name": "TEST000 LN",
        })
    resp = client.post(f"/api/v1.0/affiliations/{task_id}",
                       headers=dict(authorization=f"Bearer {access_token}"),
                       content_type="application/json",
                       data=json.dumps(incorrect_data))
    data = json.loads(resp.data)
    assert resp.status_code == 422
    assert data["error"] == "Validation error."

    resp = client.get(f"/api/v1.0/affiliations/{task_id}",
                      headers=dict(authorization=f"Bearer {access_token}"))
    data = json.loads(resp.data)
    new_data = copy.deepcopy(data)
    new_data["records"].insert(
        0, {
            "email": "*****@*****.**",
            "first-name": "TEST000 FN",
            "last-name": "TEST000 LN",
            "affiliation-type": "staff",
            "city": "TEST000"
        })
    resp = client.post(f"/api/v1.0/affiliations/{task_id}",
                       headers=dict(authorization=f"Bearer {access_token}"),
                       content_type="application/json",
                       data=json.dumps(new_data))
    data = json.loads(resp.data)
    assert resp.status_code == 200
    assert len(data["records"]) == 3

    resp = client.put(f"/api/v1.0/affiliations/{task_id}",
                      headers=dict(authorization=f"Bearer {access_token}"),
                      content_type="application/json",
                      data=json.dumps(data))
    data = json.loads(resp.data)
    assert resp.status_code == 200
    assert len(data["records"]) == 3

    resp = client.get(f"/api/v1.0/affiliations/{task_id}",
                      headers=dict(authorization=f"Bearer {access_token}"))
    data = json.loads(resp.data)
    new_data = copy.deepcopy(data)
    for i, r in enumerate(new_data["records"]):
        new_data["records"][i] = {"id": r["id"], "is-active": True}
    resp = client.patch(f"/api/v1.0/affiliations/{task_id}",
                        headers=dict(authorization=f"Bearer {access_token}"),
                        content_type="application/json",
                        data=json.dumps(new_data))
    data = json.loads(resp.data)
    assert resp.status_code == 200
    assert len(data["records"]) == 3
    assert all(r["is-active"] for r in data["records"])
    assert all(r["city"] == "TEST000" for r in data["records"])

    resp = client.head(f"/api/v1.0/affiliations/{task_id}",
                       headers=dict(authorization=f"Bearer {access_token}"))
    assert "Last-Modified" in resp.headers

    resp = client.head("/api/v1.0/affiliations/999999999",
                       headers=dict(authorization=f"Bearer {access_token}"))
    assert resp.status_code == 404

    resp = client.get("/api/v1.0/affiliations/999999999",
                      headers=dict(authorization=f"Bearer {access_token}"))
    assert resp.status_code == 404

    resp = client.patch("/api/v1.0/affiliations/999999999",
                        headers=dict(authorization=f"Bearer {access_token}"),
                        content_type="application/json",
                        data=json.dumps(new_data))
    assert resp.status_code == 404

    resp = client.delete(f"/api/v1.0/affiliations/{task_id}",
                         headers=dict(authorization=f"Bearer {access_token}"))
    assert Task.select().count() == 1

    resp = client.delete(f"/api/v1.0/affiliations/{task_id}",
                         headers=dict(authorization=f"Bearer {access_token}"))
    assert resp.status_code == 404

    other_user = User.get(email="*****@*****.**")
    other_task = Task.create(created_by=other_user,
                             org=other_user.organisation,
                             filename="OTHER.csv",
                             task_type=TaskType.AFFILIATION)

    resp = client.head(f"/api/v1.0/affiliations/{other_task.id}",
                       headers=dict(authorization=f"Bearer {access_token}"))
    assert resp.status_code == 403

    resp = client.get(f"/api/v1.0/affiliations/{other_task.id}",
                      headers=dict(authorization=f"Bearer {access_token}"))
    assert resp.status_code == 403

    resp = client.patch(f"/api/v1.0/affiliations/{other_task.id}",
                        headers=dict(authorization=f"Bearer {access_token}"),
                        content_type="application/json",
                        data=json.dumps(new_data))
    assert resp.status_code == 403

    resp = client.delete(f"/api/v1.0/affiliations/{other_task.id}",
                         headers=dict(authorization=f"Bearer {access_token}"))
    assert resp.status_code == 403

    resp = client.patch(f"/api/v1.0/affiliations/{task_id}",
                        headers=dict(authorization=f"Bearer {access_token}"),
                        content_type="application/json",
                        data=b'')
    assert resp.status_code == 400

    resp = client.post("/api/v1.0/affiliations/?filename=TEST42.csv",
                       headers=dict(authorization=f"Bearer {access_token}",
                                    accept="text/yaml"),
                       content_type="text/yaml",
                       data="""task-type: AFFILIATION
filename: TEST42.yml
records:
- affiliation-type: student
  city: Wellington
  country: NZ
  department: Research Funding
  email: [email protected]
  first-name: Roshan
  last-name: Pawar
  organisation: Royal Org1
  role: BBB
  start-date: 2016-09
- affiliation-type: staff
  city: Wellington
  country: NZ
  department: Research Funding
  email: [email protected]
  first-name: Roshan
  last-name: Pawar
  organisation: Royal Org1
  role: AAA
  start-date: 2016-09
- affiliation-type: staff
  city: Wellington
  country: NZ
  department: Research Funding
  email: [email protected]
  first-name: Researcher
  is-active: false
  last-name: Par
  organisation: Royal Org1
  role: Programme Guide - ORCID
  start-date: 2016-09
""")
    data = json.loads(resp.data)
    assert data["filename"] == "TEST42.yml"
    assert data["task-type"] == "AFFILIATION"
    assert len(data["records"]) == 3
    task_id = data["id"]
    task = Task.get(id=task_id)
    assert task.affiliation_records.count() == 3
Esempio n. 7
0
def test_drop_tables(models):
    drop_tables()
    assert not User.table_exists()
    # assert not Organisation.table_exists()
    assert not UserOrg.table_exists()
Esempio n. 8
0
def test_sso_loging_with_external_sp(client, mocker):
    """Test with EXTERNAL_SP."""
    data = {
        "Auedupersonsharedtoken": "ABC123",
        "Sn": "LAST NAME/SURNAME/FAMILY NAME",
        'Givenname': "FIRST NAME/GIVEN NAME",
        "Mail": "[email protected];[email protected]",
        "O": client.data["org"].name,
        "Displayname": "TEST USER #42",
        "Unscoped-Affiliation": "staff",
        "Eppn": "*****@*****.**"
    }

    client.application.config["EXTERNAL_SP"] = "https://exernal.ac.nz/SP"

    resp = client.get("/sso/login")
    assert resp.status_code == 302
    assert urlparse(resp.location).path == '/'

    resp = client.get("/index")
    assert b"https://exernal.ac.nz/SP" in resp.data

    get = mocker.patch(
        "requests.get",
        return_value=Mock(content=zlib.compress(b"""{"GARBAGE": 123}""")))
    resp = client.get("/sso/login", follow_redirects=True)
    assert b"500" in resp.data
    get.assert_called_once()

    get = mocker.patch(
        "requests.get",
        return_value=Mock(content=zlib.compress(json.dumps(data).encode())))

    resp = client.get("/sso/login", follow_redirects=True)
    get.assert_called_once()
    assert b"TEST USER #42" in resp.data
    assert b"*****@*****.**" in resp.data
    u = User.get(email="*****@*****.**")
    assert u.name == "TEST USER #42"

    resp = client.logout(follow_redirects=False)
    data["Unscoped-Affiliation"] = "NONSENSE"
    data["Mail"] = "*****@*****.**"
    data["Eppn"] = "*****@*****.**"
    get = mocker.patch(
        "requests.get",
        return_value=Mock(content=zlib.compress(json.dumps(data).encode())))
    resp = client.get("/index")
    resp = client.get("/sso/login", follow_redirects=True)
    assert b"NONSENSE" in resp.data

    resp = client.logout(follow_redirects=False)
    data["O"] = "A BRAND NEW ORGANISATION"
    get = mocker.patch(
        "requests.get",
        return_value=Mock(content=zlib.compress(json.dumps(data).encode())))
    resp = client.get("/index")
    resp = client.get("/sso/login", follow_redirects=True)
    assert b"Your organisation (A BRAND NEW ORGANISATION) is not yet using the Hub" in resp.data

    resp = client.logout(follow_redirects=False)
    data["O"] = "A COMPLETELY BRAND NEW ORGANISATION"
    get = mocker.patch(
        "requests.get",
        return_value=Mock(content=zlib.compress(json.dumps(data).encode())))
    mocker.patch("orcid_hub.models.Organisation.save",
                 side_effect=Exception("FAILURE"))
    resp = client.get("/index")
    resp = client.get("/sso/login", follow_redirects=True)
    assert b"FAILURE" in resp.data
Esempio n. 9
0
def test_test_database(models):
    """Test of the consitency of the test database."""
    assert Organisation.select().count() == 14
    assert User.select().count() == 95
    assert OrcidToken.select().count() == 76
    assert AffiliationRecord.select().count() == 10
    assert AffiliationExternalId.select().count() == 10
    assert FundingRecord.select().count() == 10
    assert FundingContributor.select().count() == 10
    assert FundingInvitee.select().count() == 10
    assert ExternalId.select().count() == 10
    assert WorkRecord.select().count() == 10
    assert WorkContributor.select().count() == 10
    assert WorkExternalId.select().count() == 10
    assert WorkInvitee.select().count() == 10
    assert PeerReviewRecord.select().count() == 10
    assert PeerReviewExternalId.select().count() == 10
    assert PeerReviewInvitee.select().count() == 10
    assert PropertyRecord.select().where(
        PropertyRecord.type == "URL").count() == 10
    assert PropertyRecord.select().where(
        PropertyRecord.type == "NAME").count() == 10
    assert PropertyRecord.select().where(
        PropertyRecord.type == "KEYWORD").count() == 10
    assert Task.select().count() == 30
    assert UserOrgAffiliation.select().count() == 30

    assert User.get(id=43).admin_for.count() == 10
    assert User.get(id=1).admin_for.count() == 0
    assert User.get(id=42).admin_for.count() > 0
    assert User.get(id=2).organisations.count() > 0
    assert Organisation.get(id=1).admins.count() == 2
    assert Organisation.get(id=5).users.count() > 0
    assert Organisation.get(id=5).admins.count() > 0
    assert User.select().where(User.orcid == User.get(
        email="*****@*****.**").orcid).count() == 3
    assert len(User.get(email="*****@*****.**").org_links) == 3

    user = User.get(email="*****@*****.**")
    available_organisations = user.available_organisations
    assert available_organisations.count() == 14

    admin = User.create(email="*****@*****.**",
                        organisation=user.organisation,
                        confirmed=True,
                        first_name="TEST",
                        last_name="ADMIN",
                        roles=Role.ADMIN)
    ui = UserInvitation.create(email=user.email,
                               invitee=user,
                               inviter=admin,
                               token="TOKEN-123")
    admin.delete_instance()
    ui = UserInvitation.get(ui.id)
    assert ui.inviter_id is None
    user.delete_instance()
    assert not UserInvitation.select().where(
        UserInvitation.id == ui.id).exists()

    org = Organisation.select().limit(1).first()
    user = User.select().limit(1).first()
    ot = OrcidToken.create(user=user, org=org, scopes="S1,S2,S3")
Esempio n. 10
0
def test_user_roles(models):
    user = User(name="Test User ABC123",
                first_name="ABC",
                last_name="123",
                email="*****@*****.**",
                confirmed=True,
                roles=Role.ADMIN | Role.RESEARCHER)

    assert user.has_role(Role.ADMIN)
    assert user.has_role("ADMIN")
    assert user.has_role(Role.RESEARCHER)
    assert user.has_role("RESEARCHER")
    assert user.has_role(Role.RESEARCHER | Role.ADMIN)
    assert user.has_role(4)
    assert user.has_role(2)

    assert not user.has_role(Role.SUPERUSER)
    assert not user.has_role("SUPERUSER")
    assert not user.has_role(1)

    assert not user.has_role("NOT A ROLE")
    assert not user.has_role(~(1 | 2 | 4 | 8 | 16))

    assert not user.has_role(1.1234)
Esempio n. 11
0
def test_user_org_link_org_constraint(models):
    user = User.select().limit(1).first()
    from peewee import IntegrityError
    with pytest.raises(IntegrityError):
        UserOrg.create(user=user, org_id=999999)
Esempio n. 12
0
def test_user_uuid():
    u = User(email="*****@*****.**")
    assert str(u.uuid) == "8428e5f6-38c6-530f-8339-9aeffb99e022"
Esempio n. 13
0
def models(testdb):

    Organisation.insert_many((dict(name="Organisation #%d" % i,
                                   tuakiri_name="Organisation #%d" % i,
                                   orcid_client_id="client-%d" % i,
                                   orcid_secret="secret-%d" % i,
                                   confirmed=(i % 2 == 0))
                              for i in range(10))).execute()

    User.insert_many(
        (dict(name="Test User #%d" % i,
              first_name="Test_%d" % i,
              last_name="User_%d" % i,
              email="user%d@org%d.org.nz" % (i, i * 4 % 10),
              confirmed=(i % 3 != 0),
              roles=Role.SUPERUSER if i % 42 == 0 else Role.ADMIN if i %
              13 == 0 else Role.RESEARCHER) for i in range(60))).execute()

    User.insert_many((dict(name="Test User with ORCID ID 'ABC-123' #%d" % i,
                           orcid="ABC-123",
                           first_name="Test_%d" % i,
                           last_name="User_%d" % i,
                           email="user_the_same_id_%d@org%d.org.nz" % (i, i),
                           confirmed=True,
                           organisation=(i + 1),
                           roles=Role.RESEARCHER)
                      for i in range(3))).execute()

    UserOrg.insert_many(
        dict(user=u.id, org=u.organisation_id)
        for u in User.select().where(User.orcid == "ABC-123")).execute()

    UserOrg.insert_many(
        dict(is_admin=((u + o) % 23 == 0), user=u, org=o)
        for (u, o) in product(range(2, 60, 4), range(2, 10))
        if not UserOrg.select().where(UserOrg.user == u, UserOrg.org ==
                                      o).exists()).execute()

    UserOrg.insert_many(
        (dict(is_admin=True, user=43, org=o) for o in range(1, 11))).execute()

    OrcidToken.insert_many((dict(user=User.get(id=1),
                                 org=Organisation.get(id=1),
                                 scopes="/read-limited",
                                 access_token="Test_%d" % i)
                            for i in range(60))).execute()

    UserOrgAffiliation.insert_many((dict(user=User.get(id=1),
                                         organisation=Organisation.get(id=1),
                                         department_name="Test_%d" % i,
                                         department_city="Test_%d" % i,
                                         role_title="Test_%d" % i,
                                         path="Test_%d" % i,
                                         put_code="%d" % i)
                                    for i in range(30))).execute()

    Task.insert_many((dict(org=Organisation.get(id=1),
                           created_by=User.get(id=1),
                           updated_by=User.get(id=1),
                           filename="Test_%d" % i,
                           task_type=0) for i in range(30))).execute()

    AffiliationRecord.insert_many((dict(is_active=False,
                                        task=Task.get(id=1),
                                        put_code=90,
                                        local_id="Test_%d" % i,
                                        status="Test_%d" % i,
                                        first_name="Test_%d" % i,
                                        last_name="Test_%d" % i,
                                        email="Test_%d" % i,
                                        orcid="123112311231%d" % i,
                                        organisation="Test_%d" % i,
                                        affiliation_type="Test_%d" % i,
                                        role="Test_%d" % i,
                                        department="Test_%d" % i,
                                        city="Test_%d" % i,
                                        region="Test_%d" % i,
                                        country="Test_%d" % i,
                                        disambiguated_id="Test_%d" % i,
                                        disambiguation_source="Test_%d" % i)
                                   for i in range(10))).execute()

    record = AffiliationRecord.get()
    AffiliationExternalId.insert_many((dict(record=record,
                                            type="Test1_%d" % i,
                                            value="Test1_%d" % i,
                                            url="Test1_%d" % i,
                                            relationship="Test1_%d" % i)
                                       for i in range(10))).execute()

    PropertyRecord.insert_many((dict(type="URL",
                                     is_active=False,
                                     task=Task.get(id=1),
                                     put_code=90,
                                     status="Test_%d" % i,
                                     first_name="Test_%d" % i,
                                     last_name="Test_%d" % i,
                                     email="Test_%d" % i,
                                     orcid="123112311231%d" % i,
                                     name="Test_%d" % i,
                                     value="Test_%d" % i,
                                     visibility="Test_%d" % i,
                                     display_index=i)
                                for i in range(10))).execute()

    PropertyRecord.insert_many((dict(type="NAME",
                                     is_active=False,
                                     task=Task.get(id=1),
                                     put_code=90,
                                     status="Test_%d" % i,
                                     first_name="Test_%d" % i,
                                     last_name="Test_%d" % i,
                                     email="Test_%d" % i,
                                     orcid="123112311231%d" % i,
                                     value="Test_%d" % i,
                                     visibility="Test_%d" % i,
                                     display_index=i)
                                for i in range(10))).execute()

    PropertyRecord.insert_many((dict(type="KEYWORD",
                                     is_active=False,
                                     task=Task.get(id=1),
                                     put_code=90,
                                     status="Test_%d" % i,
                                     first_name="Test_%d" % i,
                                     last_name="Test_%d" % i,
                                     email="Test_%d" % i,
                                     orcid="123112311231%d" % i,
                                     value="Test_%d" % i,
                                     visibility="Test_%d" % i,
                                     display_index=i)
                                for i in range(10))).execute()

    FundingRecord.insert_many(
        (dict(task=Task.get(id=1),
              title="Test_%d" % i,
              translated_title="Test_%d" % i,
              translated_title_language_code="Test_%d" % i,
              type="Test_%d" % i,
              organization_defined_type="Test_%d" % i,
              short_description="Test_%d" % i,
              amount="Test_%d" % i,
              currency="Test_%d" % i,
              org_name="Test_%d" % i,
              city="Test_%d" % i,
              region="Test_%d" % i,
              country="Test_%d" % i,
              disambiguated_id="Test_%d" % i,
              disambiguation_source="Test_%d" % i,
              is_active=False,
              status="Test_%d" % i) for i in range(10))).execute()

    record = FundingRecord.get()
    FundingContributor.insert_many((dict(record=record,
                                         orcid="123112311231%d" % i,
                                         name="Test_%d" % i,
                                         role="Test_%d" % i)
                                    for i in range(10))).execute()

    FundingInvitee.insert_many((dict(record=record,
                                     orcid="123112311231%d" % i,
                                     first_name="Test_%d" % i,
                                     last_name="Test_%d" % i,
                                     put_code=i,
                                     status="Test_%d" % i,
                                     identifier="%d" % i,
                                     visibility="Test_%d" % i,
                                     email="Test_%d" % i)
                                for i in range(10))).execute()

    ExternalId.insert_many((dict(record=record,
                                 type="Test_%d" % i,
                                 value="Test_%d" % i,
                                 url="Test_%d" % i,
                                 relationship="Test_%d" % i)
                            for i in range(10))).execute()

    task = Task.get()
    PeerReviewRecord.insert_many(
        (dict(task=task,
              review_group_id="issn:1212_%d" % i,
              reviewer_role="reviewer_%d" % i,
              review_url="xyz_%d" % i,
              review_type="REVIEW_%d" % i,
              subject_external_id_type="doi_%d" % i,
              subject_external_id_value="1212_%d" % i,
              subject_external_id_url="url/SELF_%d" % i,
              subject_external_id_relationship="SELF_%d" % i,
              subject_container_name="Journal title_%d" % i,
              subject_type="JOURNAL_ARTICLE_%d" % i,
              subject_name_title="name_%d" % i,
              subject_name_subtitle="subtitle_%d" % i,
              subject_name_translated_title_lang_code="en",
              subject_name_translated_title="sdsd_%d" % i,
              subject_url="url_%d" % i,
              convening_org_name="THE ORGANISATION_%d" % i,
              convening_org_city="auckland_%d" % i,
              convening_org_region="auckland_%d" % i,
              convening_org_country="nz_%d" % i,
              convening_org_disambiguated_identifier="123_%d" % i,
              convening_org_disambiguation_source="1212_%d" % i,
              is_active=False) for i in range(10))).execute()

    record = PeerReviewRecord.get()
    PeerReviewExternalId.insert_many((dict(record=record,
                                           type="Test1_%d" % i,
                                           value="Test1_%d" % i,
                                           url="Test1_%d" % i,
                                           relationship="Test1_%d" % i)
                                      for i in range(10))).execute()

    PeerReviewInvitee.insert_many((dict(record=record,
                                        orcid="1231123112311%d" % i,
                                        first_name="Test1_%d" % i,
                                        last_name="Test1_%d" % i,
                                        put_code=i,
                                        status="Test1_%d" % i,
                                        identifier="1%d" % i,
                                        visibility="PUBLIC",
                                        email="Test1_%d" % i)
                                   for i in range(10))).execute()

    WorkRecord.insert_many((dict(task=task,
                                 title="Test_%d" % i,
                                 subtitle="Test_%d" % i,
                                 translated_title="Test_%d" % i,
                                 translated_title_language_code="Test_%d" % i,
                                 journal_title="Test_%d" % i,
                                 short_description="Test_%d" % i,
                                 citation_type="Test_%d" % i,
                                 citation_value="Test_%d" % i,
                                 type="Test_%d" % i,
                                 url="Test_%d" % i,
                                 language_code="Test_%d" % i,
                                 country="Test_%d" % i,
                                 is_active=False,
                                 status="Test_%d" % i)
                            for i in range(10))).execute()

    record = WorkRecord.get()
    WorkContributor.insert_many((dict(record=record,
                                      orcid="123112311231%d" % i,
                                      name="Test_%d" % i,
                                      contributor_sequence="%d" % i,
                                      role="Test_%d" % i)
                                 for i in range(10))).execute()

    WorkExternalId.insert_many((dict(record=record,
                                     type="Test_%d" % i,
                                     value="Test_%d" % i,
                                     url="Test_%d" % i,
                                     relationship="Test_%d" % i)
                                for i in range(10))).execute()

    WorkInvitee.insert_many((dict(record=record,
                                  orcid="123112311231%d" % i,
                                  first_name="Test_%d" % i,
                                  last_name="Test_%d" % i,
                                  put_code=i,
                                  status="Test_%d" % i,
                                  identifier="%d" % i,
                                  visibility="Test_%d" % i,
                                  email="Test_%d" % i)
                             for i in range(10))).execute()

    yield testdb
Esempio n. 14
0
def test_create_or_update_resource(app, mocker):
    """Test research resources."""
    mocker.patch.multiple("orcid_hub.app.logger",
                          error=DEFAULT,
                          exception=DEFAULT,
                          info=DEFAULT)
    org = Organisation.get(name="THE ORGANISATION")
    user = User.create(orcid="1001-0001-0001-0001",
                       name="TEST USER 123",
                       email="*****@*****.**",
                       organisation=org,
                       confirmed=True)
    UserOrg.create(user=user, org=org, affiliation=Affiliation.EDU)

    api = MemberAPIV3(user=user, org=org, access_token="ACCESS000")
    assert api.api_client.configuration.access_token == 'ACCESS000'

    OrcidToken.create(access_token="ACCESS123",
                      user=user,
                      org=org,
                      scopes="/read-limited,/activities/update",
                      expires_in='121')
    api = MemberAPIV3(user=user, org=org)
    assert api.api_client.configuration.access_token == "ACCESS123"

    # Test API call auditing:
    request_mock = mocker.patch.object(
        api.api_client.rest_client.pool_manager, "request",
        MagicMock(return_value=Mock(headers=HTTPHeaderDict({
            'Server':
            'nginx/1.10.0',
            'Date':
            'Wed, 26 Jun 2019 05:26:32 GMT',
            'Content-Type':
            'application/json;charset=UTF-8',
            'Content-Length':
            '0',
            'Connection':
            'keep-alive',
            'Access-Control-Allow-Origin':
            '*',
            'Cache-Control':
            'no-cache, no-store, max-age=0, must-revalidate',
            'Pragma':
            'no-cache',
            'Expires':
            '0',
            'X-XSS-Protection':
            '1; mode=block',
            'X-Frame-Options':
            'DENY',
            'X-Content-Type-Options':
            'nosniff',
            'Location':
            f'http://api.sandbox.orcid.org/v3.0/{user.orcid}/research-resource/2052'
        }),
                                    data=b'',
                                    status=201)))

    hosts = [
        dict(
            name="TEST HOST",
            city="Auckland",
            country="NZ",
            disambiguated_id="3232",
            disambiguation_source="RINGGOLD",
        )
    ]
    external_ids = [dict(value="ABC123", type="agr", relationship="self")]

    put_code, orcid, created, _ = api.create_or_update_resource(
        title="TEST",
        hosts=hosts,
        external_ids=external_ids,
        items=[{
            "name": "TEST",
            "type": "equipment",
            "hosts": hosts,
            "external_ids": external_ids,
        }],
        display_index=999,
        visibility="public",
    )

    request_mock.assert_called_once()
    assert put_code == 2052
    assert orcid == user.orcid
Esempio n. 15
0
def test_create_tables(models):
    drop_tables()
    create_tables()
    assert User.table_exists()
    assert Organisation.table_exists()
    assert UserOrg.table_exists()
Esempio n. 16
0
def test_webhook_registration(client):
    """Test webhook registration."""
    test_client = client
    user = User.get(email="*****@*****.**")
    test_client.login(user)
    org = user.organisation
    orcid_id = "0000-0000-0000-00X3"
    client = Client.get(org=org)

    resp = test_client.post("/oauth/token",
                            method="POST",
                            data=dict(grant_type="client_credentials",
                                      client_id=client.client_id,
                                      client_secret=client.client_secret,
                                      scope="/webhook"))
    assert resp.status_code == 200
    data = json.loads(resp.data)
    token = Token.get(user=user, _scopes="/webhook")
    client = Client.get(client_id="CLIENT_ID")
    token = Token.get(client=client)
    assert data["access_token"] == token.access_token
    assert data["expires_in"] == test_client.application.config[
        "OAUTH2_PROVIDER_TOKEN_EXPIRES_IN"]
    assert data["token_type"] == token.token_type
    # prevously created access token should be removed

    resp = test_client.put(
        "/api/v1.0/INCORRECT/webhook/http%3A%2F%2FCALL-BACK",
        headers=dict(authorization=f"Bearer {token.access_token}"))
    assert resp.status_code == 415
    assert json.loads(resp.data)["error"] == "Missing or invalid ORCID iD."

    resp = test_client.put(
        "/api/v1.0/0000-0001-8228-7153/webhook/http%3A%2F%2FCALL-BACK",
        headers=dict(authorization=f"Bearer {token.access_token}"))
    assert resp.status_code == 404
    assert json.loads(resp.data)["error"] == "Invalid ORCID iD."

    resp = test_client.put(
        f"/api/v1.0/{orcid_id}/webhook/INCORRECT-WEBHOOK-URL",
        headers=dict(authorization=f"Bearer {token.access_token}"))
    assert resp.status_code == 415
    assert json.loads(resp.data) == {
        "error": "Invalid call-back URL",
        "message": "Invalid call-back URL: INCORRECT-WEBHOOK-URL"
    }

    with patch("orcid_hub.utils.requests.post") as mockpost, patch(
            "orcid_hub.utils.requests.put") as mockput:
        # Access toke request resp:
        mockresp = MagicMock(status_code=201)
        mockresp.json.return_value = {
            "access_token": "ACCESS-TOKEN-123",
            "token_type": "bearer",
            "refresh_token": "REFRESH-TOKEN-123",
            "expires_in": 99999,
            "scope": "/webhook",
            "orcid": None
        }
        mockpost.return_value = mockresp
        # Webhook registration response:
        mockresp = MagicMock(status_code=201, data=b'')
        mockresp.headers = {
            "Server": "TEST123",
            "Connection": "keep-alive",
            "Pragma": "no-cache",
            "Expires": "0",
        }
        mockput.return_value = mockresp
        resp = test_client.put(
            f"/api/v1.0/{orcid_id}/webhook/http%3A%2F%2FCALL-BACK",
            headers=dict(authorization=f"Bearer {token.access_token}"))

        assert resp.status_code == 201
        args, kwargs = mockpost.call_args
        assert args[0] == "https://sandbox.orcid.org/oauth/token"
        assert kwargs["data"] == {
            "client_id": "APP-12345678",
            "client_secret": "CLIENT-SECRET",
            "scope": "/webhook",
            "grant_type": "client_credentials"
        }
        assert kwargs["headers"] == {"Accept": "application/json"}

        args, kwargs = mockput.call_args
        assert args[
            0] == "https://api.sandbox.orcid.org/0000-0000-0000-00X3/webhook/http%3A%2F%2FCALL-BACK"
        assert kwargs["headers"] == {
            "Accept": "application/json",
            "Authorization": "Bearer ACCESS-TOKEN-123",
            "Content-Length": "0"
        }

        q = OrcidToken.select().where(OrcidToken.org == org,
                                      OrcidToken.scope == "/webhook")
        assert q.count() == 1
        orcid_token = q.first()
        assert orcid_token.access_token == "ACCESS-TOKEN-123"
        assert orcid_token.refresh_token == "REFRESH-TOKEN-123"
        assert orcid_token.expires_in == 99999
        assert orcid_token.scope == "/webhook"

    with patch("orcid_hub.utils.requests.delete") as mockdelete:
        # Webhook deletion response:
        mockresp = MagicMock(status_code=204, data=b'')
        mockresp.headers = {
            "Seresper": "TEST123",
            "Connection": "keep-alive",
            "Location": "TEST-LOCATION",
            "Pragma": "no-cache",
            "Expires": "0",
        }
        mockdelete.return_value = mockresp
        resp = test_client.delete(
            f"/api/v1.0/{orcid_id}/webhook/http%3A%2F%2FCALL-BACK",
            headers=dict(authorization=f"Bearer {token.access_token}"))
        assert resp.status_code == 204
        assert urlparse(
            resp.location
        ).path == f"/api/v1.0/{orcid_id}/webhook/http://TEST-LOCATION"

        args, kwargs = mockput.call_args
        assert args[
            0] == "https://api.sandbox.orcid.org/0000-0000-0000-00X3/webhook/http%3A%2F%2FCALL-BACK"
        assert kwargs["headers"] == {
            "Accept": "application/json",
            "Authorization": "Bearer ACCESS-TOKEN-123",
            "Content-Length": "0"
        }

        q = OrcidToken.select().where(OrcidToken.org == org,
                                      OrcidToken.scope == "/webhook")
        assert q.count() == 1
        token = q.first()
        assert token.access_token == "ACCESS-TOKEN-123"
        assert token.refresh_token == "REFRESH-TOKEN-123"
        assert token.expires_in == 99999
        assert token.scope == "/webhook"
Esempio n. 17
0
def test_user_and_token_api(app_req_ctx, resource, version):
    """Test the echo endpoint."""
    user = User.get(email="*****@*****.**")
    org2_user = User.get(email="*****@*****.**")
    with app_req_ctx(f"/api/{version}/{resource}/ABC123",
                     headers=dict(authorization="Bearer TEST")) as ctx:
        resp = ctx.app.full_dispatch_request()
        assert resp.status_code == 400
        data = json.loads(resp.data)
        assert "error" in data
        assert "incorrect identifier" in data["error"].lower()
    with app_req_ctx(f"/api/{version}/{resource}/0000-0000-0000-0000",
                     headers=dict(authorization="Bearer TEST")) as ctx:
        resp = ctx.app.full_dispatch_request()
        assert resp.status_code == 400
        data = json.loads(resp.data)
        assert "error" in data
        assert "incorrect identifier" in data["error"].lower()
    with app_req_ctx(f"/api/{version}/{resource}/[email protected]",
                     headers=dict(authorization="Bearer TEST")) as ctx:
        resp = ctx.app.full_dispatch_request()
        assert resp.status_code == 404
        data = json.loads(resp.data)
        assert "error" in data
        assert "not found" in data["error"].lower()
    with app_req_ctx(f"/api/{version}/{resource}/0000-0000-0000-0001",
                     headers=dict(authorization="Bearer TEST")) as ctx:
        resp = ctx.app.full_dispatch_request()
        assert resp.status_code == 404
        data = json.loads(resp.data)
        assert "error" in data
        assert "not found" in data["error"].lower()
    for identifier in [
            user.email,
            user.orcid,
    ]:
        with app_req_ctx(f"/api/{version}/{resource}/{identifier}",
                         headers=dict(authorization="Bearer TEST")) as ctx:
            resp = ctx.app.full_dispatch_request()
            data = json.loads(resp.data)
            assert resp.status_code == 200
            data = json.loads(resp.data)
            if resource == "users":
                assert data["email"] == user.email
                assert data["eppn"] == user.eppn
                assert data["orcid"] == user.orcid
            else:
                token = OrcidToken.get(user_id=user.id)
                assert data["access_token"] == token.access_token
    if resource == "users":  # test user listing
        with app_req_ctx(f"/api/{version}/{resource}",
                         headers=dict(authorization="Bearer TEST")) as ctx:
            resp = ctx.app.full_dispatch_request()
            data = json.loads(resp.data)
            assert resp.status_code == 200
            data = json.loads(resp.data)
            assert len(data) == 11
        with app_req_ctx(f"/api/{version}/{resource}?page=2&page_size=3",
                         headers=dict(authorization="Bearer TEST")) as ctx:
            resp = ctx.app.full_dispatch_request()
            data = json.loads(resp.data)
            assert resp.status_code == 200
            data = json.loads(resp.data)
            assert len(data) == 3
        with app_req_ctx(f"/api/{version}/{resource}?page_size=3",
                         headers=dict(authorization="Bearer TEST")) as ctx:
            resp = ctx.app.full_dispatch_request()
            data = json.loads(resp.data)
            assert resp.status_code == 200
            data = json.loads(resp.data)
            assert len(data) == 3
        with app_req_ctx(f"/api/{version}/{resource}?page=42",
                         headers=dict(authorization="Bearer TEST")) as ctx:
            resp = ctx.app.full_dispatch_request()
            data = json.loads(resp.data)
            assert resp.status_code == 200
            data = json.loads(resp.data)
            assert len(data) == 0
        with app_req_ctx(f"/api/{version}/{resource}?from_date=ABCD",
                         headers=dict(authorization="Bearer TEST")) as ctx:
            resp = ctx.app.full_dispatch_request()
            data = json.loads(resp.data)
            assert resp.status_code == 422
        with app_req_ctx(f"/api/{version}/{resource}?from_date=2018-01-01",
                         headers=dict(authorization="Bearer TEST")) as ctx:
            resp = ctx.app.full_dispatch_request()
            data = json.loads(resp.data)
            assert resp.status_code == 200
            data = json.loads(resp.data)
            assert len(data) == 4
        with app_req_ctx(f"/api/{version}/{resource}?to_date=2018-01-01",
                         headers=dict(authorization="Bearer TEST")) as ctx:
            resp = ctx.app.full_dispatch_request()
            data = json.loads(resp.data)
            assert resp.status_code == 200
            data = json.loads(resp.data)
            assert len(data) == 7
        with app_req_ctx(
                f"/api/{version}/{resource}?from_date=2017-12-20&to_date=2017-12-21",
                headers=dict(authorization="Bearer TEST")) as ctx:
            resp = ctx.app.full_dispatch_request()
            data = json.loads(resp.data)
            assert resp.status_code == 200
            data = json.loads(resp.data)
            assert len(data) == 2

    if resource == "tokens":
        user2 = User.get(email="*****@*****.**")
        for identifier in [
                user2.email,
                user2.orcid,
        ]:
            with app_req_ctx(f"/api/{version}/tokens/{identifier}",
                             headers=dict(authorization="Bearer TEST")) as ctx:
                resp = ctx.app.full_dispatch_request()
                assert resp.status_code == 404
                data = json.loads(resp.data)
                assert "error" in data

    with app_req_ctx(f"/api/{version}/{resource}/{org2_user.email}",
                     headers=dict(authorization="Bearer TEST")) as ctx:
        resp = ctx.app.full_dispatch_request()
        assert resp.status_code == 404
        data = json.loads(resp.data)
        assert "error" in data
Esempio n. 18
0
def test_onboard_org(client):
    """Test to organisation onboarding."""
    org = Organisation.create(name="THE ORGANISATION:test_onboard_org",
                              tuakiri_name="THE ORGANISATION:test_onboard_org",
                              confirmed=False,
                              orcid_client_id="CLIENT ID",
                              orcid_secret="Client Secret",
                              city="CITY",
                              country="COUNTRY",
                              disambiguated_id="ID",
                              disambiguation_source="RINGGOLD",
                              is_email_sent=True)
    u = User.create(email="*****@*****.**",
                    name="TEST USER",
                    roles=Role.TECHNICAL,
                    orcid="123",
                    confirmed=True,
                    organisation=org)
    second_user = User.create(email="*****@*****.**",
                              name="TEST USER",
                              roles=Role.ADMIN,
                              orcid="1243",
                              confirmed=True,
                              organisation=org)
    UserOrg.create(user=second_user, org=org, is_admin=True)
    org_info = OrgInfo.create(name="A NEW ORGANISATION",
                              tuakiri_name="A NEW ORGANISATION")
    org.tech_contact = u
    org_info.save()
    org.save()

    client.login_root()
    with patch("orcid_hub.utils.send_email"):
        resp = client.post("/invite/organisation",
                           data=dict(org_name="A NEW ORGANISATION",
                                     org_email="*****@*****.**"),
                           follow_redirects=True)
        assert User.select().where(
            User.email == "*****@*****.**").exists()
        resp = client.post("/invite/organisation",
                           data=dict(org_name="A NEW ORGANISATION",
                                     org_email="*****@*****.**",
                                     tech_contact='y'),
                           follow_redirects=True)
        assert User.select().where(
            User.email == "*****@*****.**").exists()
    org = Organisation.get(name="A NEW ORGANISATION")
    user = User.get(email="*****@*****.**")
    assert user.name is None
    assert org.tech_contact == user
    client.logout()

    resp = client.login(user,
                        **{
                            "Sn": "TECHNICAL",
                            "Givenname": "CONTACT",
                            "Displayname": "Test User",
                            "shib_O": "NEW ORGANISATION"
                        },
                        follow_redirects=True)
    user = User.get(email="*****@*****.**")
    org = user.organisation
    assert user.is_tech_contact_of(org)
    resp = client.get("/confirm/organisation")
    assert resp.status_code == 200
    org = Organisation.get(org.id)
    assert b"<!DOCTYPE html>" in resp.data, "Expected HTML content"
    assert b"Take me to ORCID to obtain my Client ID and Client Secret" in resp.data

    with patch("orcid_hub.authcontroller.requests") as requests:
        requests.post.return_value = Mock(data=b'XXXX', status_code=200)
        resp = client.post("/confirm/organisation",
                           data={
                               "orcid_client_id": "APP-1234567890ABCDEF",
                               "orcid_secret":
                               "12345678-1234-1234-1234-1234567890ab",
                               "country": "NZ",
                               "city": "Auckland",
                               "disambiguated_id": "XYZ123",
                               "disambiguation_source": "RINGGOLD",
                               "name": org.name,
                               "email": user.email,
                           })
    assert resp.status_code == 302
    url = urlparse(resp.location).path
    assert url == "/link"
    resp = client.get(url)
    client.logout()
    org = Organisation.get(org.id)
    assert org.disambiguated_id == "XYZ123"
    assert org.disambiguation_source == "RINGGOLD"
    assert org.orcid_client_id == "APP-1234567890ABCDEF"
    assert org.orcid_secret == "12345678-1234-1234-1234-1234567890ab"

    user = User.get(email="*****@*****.**")
    resp = client.login(user,
                        **{
                            "Sn": "NEW ORGANISATION",
                            "Givenname": "ADMINISTRATOR",
                            "Displayname": "Admin User",
                            "shib_O": "NEW ORGANISATION"
                        },
                        follow_redirects=True)
    assert b"Take me to ORCID to allow A NEW ORGANISATION permission to access my ORCID record" in resp.data
    resp = client.get("/confirm/organisation")
    assert resp.status_code == 302
    assert urlparse(resp.location).path == "/admin/viewmembers/"

    resp = client.get("/admin/viewmembers/")
    assert b"*****@*****.**" in resp.data

    resp = client.get("/admin/viewmembers/export/csv/")
    assert resp.headers["Content-Type"] == "text/csv; charset=utf-8"
    assert b"*****@*****.**" in resp.data
    assert b"*****@*****.**" in resp.data
Esempio n. 19
0
def test_process_tasks(request_ctx):
    """Test expiration data setting and deletion of the exprired tasks."""
    org = Organisation.get(name="TEST0")
    super_user = User.get(email="*****@*****.**")
    with patch("orcid_hub.utils.send_email") as send_email, request_ctx(
            "/") as ctx:
        login_user(super_user)
        # flake8: noqa
        task = Task.load_from_csv(
            """First name	Last name	email address	Organisation	Campus/Department	City	Course or Job title\tStart date	End date	Student/Staff\tCountry
    FNA	LBA	[email protected]	TEST1	Research Funding	Wellington	Programme Manager - ORCID	2016-09		Staff\tNew Zealand
    """,
            filename="TEST_TASK.tsv",
            org=org)
        Task.update(created_at=datetime(1999, 1, 1),
                    updated_at=datetime(1999, 1, 1)).execute()
        utils.process_tasks()
        assert Task.select().count() == 1
        assert not Task.select().where(Task.expires_at.is_null()).exists()
        send_email.assert_called_once()
        task = Task.select().first()
        args, kwargs = send_email.call_args
        assert "email/task_expiration.html" in args
        assert kwargs["error_count"] == 0
        hostname = ctx.request.host
        assert kwargs["export_url"].endswith(
            f"//{hostname}/admin/affiliationrecord/export/csv/?task_id={task.id}"
        )
        assert kwargs["recipient"] == (
            super_user.name,
            super_user.email,
        )
        assert kwargs["subject"] == "Batch process task is about to expire"
        assert kwargs["task"] == task

        # After the second go everything should be deleted
        utils.process_tasks()
        assert Task.select().count() == 0

        # Funding processing task:
        task = Task.create(created_at=datetime(1999, 1, 1),
                           org=org,
                           filename="FUNDING.json",
                           created_by=super_user,
                           updated_by=super_user,
                           task_type=TaskType.FUNDING.value)

        Task.update(updated_at=datetime(1999, 1, 1)).execute()
        assert Task.select().where(Task.expires_at.is_null()).count() == 1
        utils.process_tasks()
        assert Task.select().count() == 1
        assert Task.select().where(Task.expires_at.is_null()).count() == 0
        utils.process_tasks()
        assert Task.select().count() == 0
        args, kwargs = send_email.call_args
        assert "email/task_expiration.html" in args
        assert kwargs["error_count"] == 0
        hostname = ctx.request.host
        assert kwargs["export_url"].endswith(
            f"//{hostname}/admin/fundingrecord/export/csv/?task_id={task.id}")
        assert kwargs["recipient"] == (
            super_user.name,
            super_user.email,
        )
        assert kwargs["subject"] == "Batch process task is about to expire"
        assert kwargs["task"] == task

        # Incorrect task type:
        task = Task.create(created_at=datetime(1999, 1, 1),
                           org=org,
                           filename="ERROR.err",
                           created_by=super_user,
                           updated_by=super_user,
                           task_type=-12345)

        Task.update(updated_at=datetime(1999, 1, 1)).execute()
        with pytest.raises(Exception,
                           message="Unexpeced task type: -12345 (ERROR.err)."):
            utils.process_tasks()
        task.delete().execute()

        # Cover case with an exterenal SP:
        with patch("orcid_hub.utils.EXTERNAL_SP", "SOME.EXTERNAL.SP"):
            Task.create(created_at=datetime(1999, 1, 1),
                        org=org,
                        filename="FILE.file",
                        created_by=super_user,
                        updated_by=super_user)
            Task.update(updated_at=datetime(1999, 1, 1)).execute()
            assert Task.select().count() == 1
            utils.process_tasks()
            utils.process_tasks()
            assert Task.select().count() == 0