Esempio n. 1
0
def test_link_orcid_auth_callback(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"],
        expires_in="1212",
        refresh_token="ABC1235"))

    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.NONE)
    client.login(test_user)
    User.update(name=name).execute()
    resp = client.get("/link")
    state = session['oauth_state']
    resp = client.get(f"/auth?state={state}")
    assert resp.status_code == 302, "If the user is already affiliated, the user should be redirected ..."
    assert "profile" in resp.location, "redirection to 'profile' showing the ORCID"

    u = User.get(id=test_user.id)
    orcidtoken = OrcidToken.get(user=u)
    assert u.orcid == "ABC-123-456-789"
    assert orcidtoken.access_token == "ABC123"
    if name:
        assert u.name == name, "The user name should be changed"
    else:
        assert u.name == "NEW TEST", "the user name should be set from record coming from ORCID"
Esempio n. 2
0
def test_scheduled_tasks(app, mocker):
    """Test scheduled tasks."""
    org = app.data["org"]
    task = Task.create(org=org, task_type=TaskType.AFFILIATION)
    rq = app.extensions["rq2"]
    s = rq.get_scheduler()
    s.run(burst=True)
    task = Task.get(task.id)
    utils.process_tasks.queue()
    task = Task.get(task.id)
    assert task.expires_at is not None
    task.expires_at = utils.datetime(1988, 1, 1)
    task.save()
    utils.process_tasks.queue()
    assert Task.select().where(Task.id == task.id).count() == 0

    Organisation.update(webhook_enabled=True,
                        email_notifications_enabled=True).execute()
    User.update(orcid_updated_at=utils.date.today().replace(day=1) -
                utils.timedelta(days=1)).execute()
    send_email = mocker.patch("orcid_hub.utils.send_email")
    utils.send_orcid_update_summary.queue(org_id=org.id)
    send_email.assert_called()
Esempio n. 3
0
def test_org_webhook_api(client, mocker):
    """Test Organisation webhooks."""
    mocker.patch.object(
        utils.requests,
        "post",
        lambda *args, **kwargs: Mock(
            status_code=201,
            json=lambda: dict(
                access_token="ABC123", refresh_token="REFRESH_ME", expires_in=123456789
            ),
        ),
    )

    mockput = mocker.patch.object(utils.requests, "put")
    mockdelete = mocker.patch.object(utils.requests, "delete")

    org = client.data["org"]
    admin = org.tech_contact

    send_email = mocker.patch("orcid_hub.utils.send_email")

    api_client = Client.get(org=org)

    resp = client.post(
        "/oauth/token",
        data=dict(
            grant_type="client_credentials",
            client_id=api_client.client_id,
            client_secret=api_client.client_secret,
            scope="/webhook",
        ),
    )

    assert resp.status_code == 200
    data = json.loads(resp.data)
    api_client = Client.get(client_id="CLIENT_ID")
    token = Token.select().where(Token.user == admin, Token._scopes == "/webhook").first()

    assert data["access_token"] == token.access_token
    assert data["expires_in"] == client.application.config["OAUTH2_PROVIDER_TOKEN_EXPIRES_IN"]
    assert data["token_type"] == token.token_type

    client.access_token = token.access_token

    resp = client.put("/api/v1/webhook/INCORRECT-WEBHOOK-URL")
    assert resp.status_code == 415
    assert json.loads(resp.data) == {
        "error": "Invalid call-back URL",
        "message": "Invalid call-back URL: INCORRECT-WEBHOOK-URL",
    }

    # 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

    # 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 = client.put("/api/v1/webhook/http%3A%2F%2FCALL-BACK")
    assert resp.status_code == 200

    resp = client.put(
        "/api/v1/webhook/http%3A%2F%2FCALL-BACK",
        data=dict(enabled=True, url="https://CALL-BACK.edu/callback"),
    )
    assert resp.status_code == 201

    server_name = client.application.config["SERVER_NAME"]
    mockput.assert_has_calls(
        [
            call(
                "https://api.sandbox.orcid.org/1001-0001-0001-0001/webhook/"
                f"https%3A%2F%2F{server_name}%2Fservices%2F21%2Fupdated",
                headers={
                    "Accept": "application/json",
                    "Authorization": "Bearer ABC123",
                    "Content-Length": "0",
                },
            ),
            call(
                "https://api.sandbox.orcid.org/0000-0000-0000-00X3/webhook/"
                f"https%3A%2F%2F{server_name}%2Fservices%2F22%2Fupdated",
                headers={
                    "Accept": "application/json",
                    "Authorization": "Bearer ABC123",
                    "Content-Length": "0",
                },
            ),
            call(
                "https://api.sandbox.orcid.org/0000-0000-0000-11X2/webhook/"
                f"https%3A%2F%2F{server_name}%2Fservices%2F30%2Fupdated",
                headers={
                    "Accept": "application/json",
                    "Authorization": "Bearer ABC123",
                    "Content-Length": "0",
                },
            ),
        ]
    )

    q = OrcidToken.select().where(OrcidToken.org == org, OrcidToken.scopes == "/webhook")
    assert q.exists()
    assert q.count() == 1
    orcid_token = q.first()
    assert orcid_token.access_token == "ABC123"
    assert orcid_token.refresh_token == "REFRESH_ME"
    assert orcid_token.expires_in == 123456789
    assert orcid_token.scopes == "/webhook"

    # deactivate:

    resp = client.delete("/api/v1/webhook/http%3A%2F%2FCALL-BACK")
    assert resp.status_code == 200
    assert "job-id" in resp.json

    # activate with all options:
    mockput.reset_mock()
    resp = client.put(
        "/api/v1/webhook",
        data={
            "enabled": True,
            "append-orcid": True,
            "apikey": "APIKEY123",
            "email-notifications-enabled": True,
            "notification-email": "*****@*****.**",
        },
    )
    server_name = client.application.config["SERVER_NAME"]
    mockput.assert_has_calls(
        [
            call(
                "https://api.sandbox.orcid.org/1001-0001-0001-0001/webhook/"
                f"https%3A%2F%2F{server_name}%2Fservices%2F21%2Fupdated",
                headers={
                    "Accept": "application/json",
                    "Authorization": "Bearer ABC123",
                    "Content-Length": "0",
                },
            ),
            call(
                "https://api.sandbox.orcid.org/0000-0000-0000-00X3/webhook/"
                f"https%3A%2F%2F{server_name}%2Fservices%2F22%2Fupdated",
                headers={
                    "Accept": "application/json",
                    "Authorization": "Bearer ABC123",
                    "Content-Length": "0",
                },
            ),
            call(
                "https://api.sandbox.orcid.org/0000-0000-0000-11X2/webhook/"
                f"https%3A%2F%2F{server_name}%2Fservices%2F30%2Fupdated",
                headers={
                    "Accept": "application/json",
                    "Authorization": "Bearer ABC123",
                    "Content-Length": "0",
                },
            ),
        ]
    )

    # Link other org to the users
    org2 = Organisation.select().where(Organisation.id != org.id).first()
    UserOrg.insert_many([dict(user_id=u.id, org_id=org2.id) for u in org.users]).execute()
    org2.webhook_enabled = True
    org2.save()
    resp = client.delete("/api/v1/webhook")

    mockput.reset_mock()
    resp = client.put(
        "/api/v1/webhook",
        data={
            "enabled": False,
            "url": "https://CALL-BACK.edu/callback",
            "append-orcid": False,
            "email-notifications-enabled": True,
            "notification-email": "*****@*****.**",
        },
    )
    mockput.assert_not_called()

    # Test update summary:
    User.update(
        orcid_updated_at=datetime.date.today().replace(day=1) - datetime.timedelta(days=15)
    ).execute()
    send_email.reset_mock()
    utils.send_orcid_update_summary()
    send_email.assert_called_once()
    client.logout()