예제 #1
0
def test_get_credentials(mock_google_env):
    goauth = GoogleOAuth(database=None)
    with mock.patch.object(goauth, "authenticate", return_value="patched_access_token"):
        credentials = goauth.get_credentials()

    assert credentials.client_id == "test_client_id"
    assert credentials.client_secret == "test_client_secret"
    assert credentials.token == "patched_access_token"
예제 #2
0
def test_poll_for_initial_access_token(mock_google_env, mock_empty_database):
    goauth = GoogleOAuth(database=mock_empty_database)

    device = {
        "device_code": "device_code",
        "verification_url": "some-google-device-url",
        "expires_in": time.time() + 3600,
        "user_code": "ABCD-EFGH",
    }

    with mock.patch.object(
        goauth, "_request_initial_access_token", return_value={"expires_in": 3600}
    ):
        token_data = goauth.poll_for_initial_access_token(device)
    assert token_data == {"expires_in": time.time() + 3600}
예제 #3
0
def test_ask_for_access(mock_google_env):
    goauth = GoogleOAuth(database=None)

    device = {
        "device_code": "device_code",
        "verification_url": "some-google-device-url",
        "expires_in": 3600,
        "user_code": "ABCD-EFGH",
    }

    token_data = {"access_token": "new_access_token"}

    with requests_mock.mock() as m, mock.patch.object(
        goauth, "poll_for_initial_access_token", return_value=token_data
    ):
        m.post(goauth.GOOGLE_OAUTH_ACCESS_URL, json=device)

        token = goauth.ask_for_access()

        assert token == "new_access_token"
예제 #4
0
def test_request_initial_access_token(mock_google_env):
    goauth = GoogleOAuth(database=None)

    device = {
        "device_code": "device_code",
        "verification_url": "some-google-device-url",
        "expires_in": 3600,
        "user_code": "ABCD-EFGH",
    }

    expected_data = {
        "access_token": "initial_access_token",
        "refresh_token": "refresh_token",
        "expires_in": 3600,
        # TODO (felix): What else?
        "token_type": "Bearer",
    }

    with requests_mock.mock() as m:
        m.post(goauth.GOOGLE_OAUTH_POLL_URL, json=expected_data)

        token_data = goauth._request_initial_access_token(device)
        assert token_data == expected_data
예제 #5
0
def crawl(module_id: str,
          app,
          calendars: List[str],
          max_items: int = DEFAULT_MAX_ITEMS) -> None:

    # TODO (felix): Get rid of this, it's only needed to store the oauth token
    # in GoogleOAuth for the current module.
    object_key = f"module.{module_id}.data"

    try:
        credentials = GoogleOAuth(app.extensions["database"], SCOPES,
                                  object_key).get_credentials()
    except ConnectionError:
        raise CrawlerDataError("Unable to connect to Google API")
    if not credentials:
        raise CrawlerDataError("Unable to authenticate to Google API")

    # Get the current time to store in the calender events list in the database
    now = time.time()

    LOGGER.info("Requesting calendar list from Google API")
    service = googleapiclient.discovery.build(API_SERVICE_NAME,
                                              API_VERSION,
                                              credentials=credentials)

    try:
        calendar_list = service.calendarList().list().execute()
    except RefreshError:
        # Google responds with a RefreshError when the token is invalid as it
        # would try to refresh the token if the necessary fields are set
        # which we haven't)
        raise CrawlerDataError(
            "Could not retrieve calendar list. Maybe flirror doesn't have "
            "the permission to access your calendar.")

    calendar_items = calendar_list.get("items")

    cals_filtered = [
        ci for ci in calendar_items if ci["summary"].lower() in calendars
    ]
    if not cals_filtered:
        raise CrawlerDataError(
            "None of the provided calendars matched the list I got from Google: {}"
            .format(calendars))

    all_events = []
    for cal_item in cals_filtered:
        # Call the calendar API
        _now = "{}Z".format(
            datetime.utcnow().isoformat())  # 'Z' indicates UTC time
        LOGGER.info(
            "Requesting upcoming %d events for calendar '%s'",
            max_items,
            cal_item["summary"],
        )
        events_result = (service.events().list(
            calendarId=cal_item["id"],
            timeMin=_now,
            maxResults=max_items,
            singleEvents=True,
            orderBy="startTime",
        ).execute())
        events = events_result.get("items", [])
        if not events:
            LOGGER.warning(
                "Could not find any upcoming events for calendar '%s",
                cal_item["summary"],
            )
        for event in events:
            all_events.append(_parse_event_data(event))

    # Sort the events from multiple calendars
    all_events = sorted(all_events, key=lambda k: k["start"])

    event_data = {"_timestamp": now, "events": all_events[:max_items]}
    app.store_module_data(module_id, event_data)