Exemple #1
0
    def _get_authenticator(self, config: Mapping[str, Any]):
        # Added to maintain backward compatibility with previous versions
        if "api_token" in config:
            return TokenAuthenticator(config["api_token"])

        credentials = config.get("credentials")
        credentials_title = credentials.get("option_title")
        if credentials_title == "Default OAuth2.0 authorization":
            # We can get `refresh_token` only if the token rotation function is enabled for the Slack Oauth Application.
            # If it is disabled, then we use the generated `access_token`, which acts without expiration.
            # https://api.slack.com/authentication/rotation
            if credentials.get("refresh_token", "").strip():
                return Oauth2Authenticator(
                    token_refresh_endpoint=
                    "https://slack.com/api/oauth.v2.access",
                    client_id=credentials["client_id"],
                    client_secret=credentials["client_secret"],
                    refresh_token=credentials["refresh_token"],
                )
            return TokenAuthenticator(credentials["access_token"])
        elif credentials_title == "API Token Credentials":
            return TokenAuthenticator(credentials["api_token"])
        else:
            raise Exception(
                f"No supported option_title: {credentials_title} specified. See spec.json for references"
            )
Exemple #2
0
    def check_connection(self, logger, config) -> Tuple[bool, any]:
        try:
            authenticator = TokenAuthenticator(config["api_token"])
            url = f"{ZenloopStream.url_base}surveys"

            session = requests.get(url, headers=authenticator.get_auth_header())
            session.raise_for_status()
            return True, None
        except Exception as error:
            return False, f"Unable to connect to Zenloop API with the provided credentials - {error}"
Exemple #3
0
    def get_access_token(self):
        credentials = self.config.get("credentials")
        if credentials:
            auth_type = credentials.get("auth_type")
            if auth_type == "OAuth2.0":
                return TokenAuthenticator(credentials.get("access_token"))
            return TokenAuthenticator(credentials.get("token"))

        # support the old config
        if "access_token" in self.config:
            return TokenAuthenticator(self.config.get("access_token"))
def test_token_authenticator():
    """
    Should match passed in token, no matter how many times token is retrieved.
    """
    token_auth = TokenAuthenticator(token="test-token")
    header1 = token_auth.get_auth_header()
    header2 = token_auth.get_auth_header()

    prepared_request = requests.PreparedRequest()
    prepared_request.headers = {}
    token_auth(prepared_request)

    assert {"Authorization": "Bearer test-token"} == prepared_request.headers
    assert {"Authorization": "Bearer test-token"} == header1
    assert {"Authorization": "Bearer test-token"} == header2
Exemple #5
0
 def login(self) -> TokenAuthenticator:
     data = {"grant_type": "client_credentials"}
     auth = requests.auth.HTTPBasicAuth(self.username, self.password)
     response = requests.post(self.url, auth=auth, data=data)
     response.raise_for_status()
     self.access_token = response.json()["access_token"]
     return TokenAuthenticator(self.access_token)
Exemple #6
0
 def streams(self, config: Mapping[str, Any]) -> List[Stream]:
     args = {
         "api_token": TokenAuthenticator(token=config["api_token"]),
         "date_from": config["date_from"],
         "survey_id": config.get("survey_id"),
         "survey_group_id": config.get("survey_group_id"),
     }
     return [Surveys(**args), Answers(**args), SurveyGroups(**args), AnswersSurveyGroup(**args)]
Exemple #7
0
 def check_connection(self, logger, config) -> Tuple[bool, any]:
     auth = TokenAuthenticator(token=config["api_key"])
     for table in config["tables"]:
         try:
             Helpers.get_first_row(auth, config["base_id"], table)
         except Exception as e:
             return False, str(e)
     return True, None
Exemple #8
0
    def streams(self, config: Mapping[str, Any]) -> List[Stream]:

        stream_kwargs = {
            "authenticator": TokenAuthenticator(config["api_token"]),
            "workspace": config["workspace"],
            "start_date": config["start_date"],
        }

        return [Members(**stream_kwargs), Workspace(**stream_kwargs)]
Exemple #9
0
 def discover(self, logger: AirbyteLogger, config) -> AirbyteCatalog:
     streams = []
     auth = TokenAuthenticator(token=config["api_key"])
     for table in config["tables"]:
         record = Helpers.get_first_row(auth, config["base_id"], table)
         json_schema = Helpers.get_json_schema(record)
         airbyte_stream = Helpers.get_airbyte_stream(table, json_schema)
         streams.append(airbyte_stream)
     return AirbyteCatalog(streams=streams)
Exemple #10
0
 def check_connection(self, logger, config) -> Tuple[bool, any]:
     try:
         authenticator = TokenAuthenticator(config["user_auth_key"], "Basic")
         stream = Apps(authenticator=authenticator, config=config)
         records = stream.read_records(sync_mode=SyncMode.full_refresh)
         next(records)
         return True, None
     except requests.exceptions.RequestException as e:
         return False, e
Exemple #11
0
 def streams(self, config: Mapping[str, Any]) -> List[Stream]:
     auth = TokenAuthenticator(token=config["api_key"])
     return [
         Companies(authenticator=auth),
         Locations(authenticator=auth),
         Products(authenticator=auth),
         Invoices(authenticator=auth),
         Shipments(authenticator=auth, start_date=config["start_date"]),
     ]
Exemple #12
0
    def streams(self, config: Mapping[str, Any]) -> List[Stream]:
        AirbyteLogger().log("INFO", f"Using start_date: {config['start_date']}")

        authenticator = TokenAuthenticator(config["user_auth_key"], "Basic")
        args = {"authenticator": authenticator, "config": config}
        apps = Apps(**args)
        args = {"parent": apps, **args}

        return [apps, Devices(**args), Notifications(**args), Outcomes(**args)]
Exemple #13
0
    def get_auth(config: Mapping[str, Any]) -> AuthBase:

        credential = config.get("credentials", {})
        auth_type = credential.get("auth_type")
        if auth_type == "Oauth":
            # scopes needed for all currently supported streams:
            scopes = [
                "CUSTOMERS_READ",
                "EMPLOYEES_READ",
                "ITEMS_READ",
                "MERCHANT_PROFILE_READ",
                "ORDERS_READ",
                "PAYMENTS_READ",
                "TIMECARDS_READ",
                # OAuth Permissions:
                # https://developer.squareup.com/docs/oauth-api/square-permissions
                # https://developer.squareup.com/reference/square/enums/OAuthPermission
                # "DISPUTES_READ",
                # "GIFTCARDS_READ",
                # "INVENTORY_READ",
                # "INVOICES_READ",
                # "TIMECARDS_SETTINGS_READ",
                # "LOYALTY_READ",
                # "ONLINE_STORE_SITE_READ",
                # "ONLINE_STORE_SNIPPETS_READ",
                # "SUBSCRIPTIONS_READ",
            ]

            auth = Oauth2AuthenticatorSquare(
                token_refresh_endpoint="https://connect.squareup.com/oauth2/token",
                client_secret=credential.get("client_secret"),
                client_id=credential.get("client_id"),
                refresh_token=credential.get("refresh_token"),
                scopes=scopes,
                expires_in_name="expires_at",
            )
        elif auth_type == "Apikey":
            auth = TokenAuthenticator(token=credential.get("api_key"))
        elif not auth_type and config.get("api_key"):
            auth = TokenAuthenticator(token=config.get("api_key"))
        else:
            raise Exception(f"Invalid auth type: {auth_type}")

        return auth
Exemple #14
0
    def _get_authenticator(api_key):
        """
        Returns a TokenAuthenticator.

        The API token is concatenated with `:x` and the resulting string is base-64 encoded.
        See https://documentation.bamboohr.com/docs#authentication
        """
        return TokenAuthenticator(token=base64.b64encode(
            f"{api_key}:x".encode("utf-8")).decode("utf-8"),
                                  auth_method="Basic")
Exemple #15
0
    def get_auth(self) -> TokenAuthenticator:
        """Return the TokenAuthenticator object with access_token."""

        # the old config supports for backward capability
        access_token = self.config.get("access_token")
        if not access_token:
            # the new config supports `OAuth2.0`
            access_token = self.config["credentials"]["access_token"]

        return TokenAuthenticator(token=access_token)
Exemple #16
0
 def check_connection(self, logger, config) -> Tuple[bool, any]:
     try:
         authenticator = TokenAuthenticator(config["access_token"])
         records = RoutingSettings(
             authenticator=authenticator).read_records(
                 sync_mode=SyncMode.full_refresh)
         next(records)
         return True, None
     except Exception as error:
         return False, f"Unable to connect to Zendesk Chat API with the provided credentials - {error}"
Exemple #17
0
 def get_authenticator(
         cls, config: Mapping[str, Any]) -> BasicApiTokenAuthenticator:
     if config["auth_method"]["auth_method"] == "access_token":
         return TokenAuthenticator(
             token=config["auth_method"]["access_token"])
     elif config["auth_method"]["auth_method"] == "api_token":
         return BasicApiTokenAuthenticator(
             config["auth_method"]["email"],
             config["auth_method"]["api_token"])
     raise SourceZendeskException(
         f"Not implemented authorization method: {config['auth_method']}")
Exemple #18
0
 def check_connection(self, logger, config) -> Tuple[bool, any]:
     try:
         workspace_stream = Workspace(
             authenticator=TokenAuthenticator(token=config["api_token"]),
             workspace=config["workspace"],
         )
         next(
             workspace_stream.read_records(sync_mode=SyncMode.full_refresh))
         return True, None
     except Exception as e:
         return False, f"Please check that your API key and workspace name are entered correctly: {repr(e)}"
Exemple #19
0
    def streams(self, config: Mapping[str, Any]) -> List[Stream]:
        AirbyteLogger().log("INFO",
                            f"Using start_date: {config['start_date']}")

        authenticator = TokenAuthenticator(config["access_token"])
        args = {"authenticator": authenticator, "config": config}

        pages = Pages(**args)
        blocks = Blocks(parent=pages, **args)

        return [Users(**args), Databases(**args), pages, blocks]
Exemple #20
0
 def streams(self, config: Mapping[str, Any]) -> List[Stream]:
     auth = TokenAuthenticator(token=config["api_key"])
     streams = []
     for table in config["tables"]:
         record = Helpers.get_first_row(auth, config["base_id"], table)
         json_schema = Helpers.get_json_schema(record)
         stream = AirtableStream(base_id=config["base_id"],
                                 table_name=table,
                                 authenticator=auth,
                                 schema=json_schema)
         streams.append(stream)
     return streams
Exemple #21
0
 def check_connection(self, logger, config) -> Tuple[bool, any]:
     """
     Makes a request to the /ping endpoint, which validates that the authentication credentials are appropriate.
     API Docs: https://docs.withorb.com/reference/ping
     """
     auth_header = TokenAuthenticator(token=config["api_key"]).get_auth_header()
     ping_url = ORB_API_BASE_URL + "ping"
     ping_response = requests.get(ping_url, headers=auth_header)
     try:
         ping_response.raise_for_status()
         return True, None
     except Exception as e:
         return False, e
Exemple #22
0
 def get_first_row(auth: TokenAuthenticator, base_id: str, table: str) -> Dict[str, Any]:
     url = f"https://api.airtable.com/v0/{base_id}/{table}?pageSize=1"
     try:
         response = requests.get(url, headers=auth.get_auth_header())
         response.raise_for_status()
     except requests.exceptions.HTTPError as e:
         if e.response.status_code == 401:
             raise Exception("Invalid API key")
         elif e.response.status_code == 404:
             raise Exception(f"Table '{table}' not found")
         else:
             raise Exception(f"Error getting first row from table {table}: {e}")
     json_response = response.json()
     record = json_response.get("records", [])[0]
     return record
Exemple #23
0
 def streams(self, config: Mapping[str, Any]) -> List[Stream]:
     authenticator = TokenAuthenticator(config["access_token"])
     return [
         Agents(authenticator=authenticator),
         AgentTimelines(authenticator=authenticator,
                        start_date=config["start_date"]),
         Accounts(authenticator=authenticator),
         Chats(authenticator=authenticator),
         Shortcuts(authenticator=authenticator),
         Triggers(authenticator=authenticator),
         Bans(authenticator=authenticator),
         Departments(authenticator=authenticator),
         Goals(authenticator=authenticator),
         Skills(authenticator=authenticator),
         Roles(authenticator=authenticator),
         RoutingSettings(authenticator=authenticator),
     ]
Exemple #24
0
    def read_records(
        self,
        sync_mode: SyncMode,
        cursor_field: List[str] = None,
        stream_slice: Mapping[str, Any] = None,
        stream_state: Mapping[str, Any] = None,
    ) -> Iterable[Mapping[str, Any]]:
        # OneSignal needs different auth token for each app, so we inject it
        # right before read records request.
        # Note: The _session.auth can be replaced when HttpStream provided
        # some ways to get its request authenticator in the future
        token = self._auth_token
        if stream_slice:
            token = stream_slice.get("rest_api_key", token)
        self._session.auth = TokenAuthenticator(token, "Basic")

        return super().read_records(sync_mode, cursor_field, stream_slice,
                                    stream_state)
Exemple #25
0
    def streams(self, config: Mapping[str, Any]) -> List[Stream]:
        authenticator = TokenAuthenticator(token=config["api_key"])
        lookback_window = config.get("lookback_window_days")
        string_event_properties_keys = config.get("string_event_properties_keys")
        numeric_event_properties_keys = config.get("numeric_event_properties_keys")

        if not self.input_keys_mutually_exclusive(string_event_properties_keys, numeric_event_properties_keys):
            raise ValueError("Supplied property keys for string and numeric valued property values must be mutually exclusive.")

        start_date_str = config.get("start_date")
        start_date = pendulum.parse(start_date_str) if start_date_str else None
        return [
            Customers(authenticator=authenticator, lookback_window_days=lookback_window, start_date=start_date),
            Subscriptions(authenticator=authenticator, lookback_window_days=lookback_window, start_date=start_date),
            Plans(authenticator=authenticator, lookback_window_days=lookback_window, start_date=start_date),
            CreditsLedgerEntries(
                authenticator=authenticator,
                lookback_window_days=lookback_window,
                start_date=start_date,
                string_event_properties_keys=string_event_properties_keys,
                numeric_event_properties_keys=numeric_event_properties_keys,
            ),
        ]
Exemple #26
0
    def get_authenticator(
            cls, config: Mapping[str, Any]) -> BasicApiTokenAuthenticator:

        # old authentication flow support
        auth_old = config.get("auth_method")
        if auth_old:
            if auth_old.get("auth_method") == "api_token":
                return BasicApiTokenAuthenticator(
                    config["auth_method"]["email"],
                    config["auth_method"]["api_token"])
        # new authentication flow
        auth = config.get("credentials")
        if auth:
            if auth.get("credentials") == "oauth2.0":
                return TokenAuthenticator(
                    token=config["credentials"]["access_token"])
            elif auth.get("credentials") == "api_token":
                return BasicApiTokenAuthenticator(
                    config["credentials"]["email"],
                    config["credentials"]["api_token"])
            else:
                raise SourceZendeskException(
                    f"Not implemented authorization method: {config['credentials']}"
                )
Exemple #27
0
def test_get_first_row_invalid_api_key(base_id, table):
    with pytest.raises(Exception):
        auth = TokenAuthenticator("invalid_api_key")
        Helpers.get_first_row(auth, base_id, table)
Exemple #28
0
def test_requests_native_token_authenticator():
    stream = StubBasicReadHttpStream(
        authenticator=TokenAuthenticator("test-token"))
    assert isinstance(stream.authenticator, NoAuth)
    assert isinstance(stream._session.auth, TokenAuthenticator)