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")
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()
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())
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)
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")
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()
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)
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