Example #1
0
    def test_installation_custom_fields(self):
        installation = Installation(
            app_id="A111",
            enterprise_id="E111",
            team_id="T111",
            user_id="U111",
            bot_id="B111",
            bot_token="xoxb-111",
            bot_scopes=["chat:write"],
            bot_user_id="U222",
        )
        self.assertIsNotNone(installation)

        installation.set_custom_value("service_user_id", "XYZ123")
        # the same names in custom_values are ignored
        installation.set_custom_value("app_id", "A222")
        self.assertEqual(installation.get_custom_value("service_user_id"),
                         "XYZ123")
        self.assertEqual(installation.to_dict().get("service_user_id"),
                         "XYZ123")
        self.assertEqual(installation.to_dict().get("app_id"), "A111")

        bot = installation.to_bot()
        self.assertEqual(bot.app_id, "A111")
        self.assertEqual(bot.get_custom_value("service_user_id"), "XYZ123")

        self.assertEqual(bot.to_dict().get("app_id"), "A111")
        self.assertEqual(bot.to_dict().get("service_user_id"), "XYZ123")
Example #2
0
 def save(self, installation: Installation):
     i = installation.to_dict()
     i["client_id"] = self.client_id
     SlackInstallation(**i).save()
     b = installation.to_bot().to_dict()
     b["client_id"] = self.client_id
     SlackBot(**b).save()
Example #3
0
    def save(self, installation: Installation):
        i = installation.to_dict()
        if is_naive(i['installed_at']):
            i['installed_at'] = make_aware(i['installed_at'])
        if 'bot_token_expires_at' in i and i[
                'bot_token_expires_at'] is not None and is_naive(
                    i['bot_token_expires_at']):
            i['bot_token_expires_at'] = make_aware(i['bot_token_expires_at'])
        if 'user_token_expires_at' in i and i[
                'user_token_expires_at'] is not None and is_naive(
                    i['user_token_expires_at']):
            i['user_token_expires_at'] = make_aware(i['user_token_expires_at'])
        i['client_id'] = self.client_id
        row_to_update = (SlackInstallation.objects.filter(
            client_id=self.client_id).filter(
                enterprise_id=installation.enterprise_id).filter(
                    team_id=installation.team_id).filter(
                        installed_at=i['installed_at']).first())
        if row_to_update is not None:
            for key, value in i.items():
                setattr(row_to_update, key, value)
            row_to_update.save()
        else:
            SlackInstallation(**i).save()

        self.save_bot(installation.to_bot())
Example #4
0
 async def async_save(self, installation: Installation):
     async with Database(self.database_url) as database:
         async with database.transaction():
             i = installation.to_dict()
             i["client_id"] = self.client_id
             await database.execute(self.installations.insert(), i)
             b = installation.to_bot().to_dict()
             b["client_id"] = self.client_id
             await database.execute(self.bots.insert(), b)
Example #5
0
    def test_installation(self):
        installation = Installation(
            app_id="A111",
            enterprise_id="E111",
            team_id="T111",
            user_id="U111",
            bot_id="B111",
            bot_token="xoxb-111",
            bot_scopes=["chat:write"],
            bot_user_id="U222",
        )
        self.assertIsNotNone(installation)
        self.assertEqual(installation.app_id, "A111")

        self.assertIsNotNone(installation.to_bot())
        self.assertIsNotNone(installation.to_bot().app_id, "A111")

        self.assertIsNotNone(installation.to_dict())
        self.assertEqual(installation.to_dict().get("app_id"), "A111")
Example #6
0
 def save(self, installation: Installation):
     i = installation.to_dict()
     if is_naive(i["installed_at"]):
         i["installed_at"] = make_aware(i["installed_at"])
     i["client_id"] = self.client_id
     SlackInstallation(**i).save()
     b = installation.to_bot().to_dict()
     if is_naive(b["installed_at"]):
         b["installed_at"] = make_aware(b["installed_at"])
     b["client_id"] = self.client_id
     SlackBot(**b).save()
Example #7
0
    def perform_user_token_rotation(  # type: ignore
            self,
            *,
            installation: Installation,
            minutes_before_expiration: int = 120,  # 2 hours by default
    ) -> Optional[Installation]:
        """Performs user token rotation if the underlying user token is expired / expiring.

        Args:
            installation: the current installation data
            minutes_before_expiration: the minutes before the token expiration

        Returns:
            None if no rotation is necessary for now.
        """
        if installation.user_token_expires_at is None:
            return None
        if installation.user_token_expires_at > time(
        ) + minutes_before_expiration * 60:
            return None

        try:
            refresh_response = self.client.oauth_v2_access(
                client_id=self.client_id,
                client_secret=self.client_secret,
                grant_type="refresh_token",
                refresh_token=installation.user_refresh_token,
            )

            if refresh_response.get("token_type") != "user":
                return None

            refreshed_installation = Installation(
                **installation.to_dict())  # type: ignore
            refreshed_installation.user_token = refresh_response.get(
                "access_token")
            refreshed_installation.user_refresh_token = refresh_response.get(
                "refresh_token")
            refreshed_installation.user_token_expires_at = int(time()) + int(
                refresh_response.get("expires_in"))
            return refreshed_installation

        except SlackApiError as e:
            raise SlackTokenRotationError(e)
Example #8
0
    def perform_token_rotation(  # type: ignore
            self,
            *,
            installation: Installation,
            minutes_before_expiration: int = 120,  # 2 hours by default
    ) -> Optional[Installation]:
        """Performs token rotation if the underlying tokens (bot / user) are expired / expiring.

        Args:
            installation: the current installation data
            minutes_before_expiration: the minutes before the token expiration

        Returns:
            None if no rotation is necessary for now.
        """

        # TODO: make the following two calls in parallel for better performance

        # bot
        rotated_bot: Optional[
            Bot] = self.perform_bot_token_rotation(  # type: ignore
                bot=installation.to_bot(),
                minutes_before_expiration=minutes_before_expiration,
            )

        # user
        rotated_installation: Optional[
            Installation] = self.perform_user_token_rotation(  # type: ignore
                installation=installation,
                minutes_before_expiration=minutes_before_expiration,
            )

        if rotated_bot is not None:
            if rotated_installation is None:
                rotated_installation = Installation(
                    **installation.to_dict())  # type: ignore
            rotated_installation.bot_token = rotated_bot.bot_token
            rotated_installation.bot_refresh_token = rotated_bot.bot_refresh_token
            rotated_installation.bot_token_expires_at = rotated_bot.bot_token_expires_at

        return rotated_installation