Module slack_sdk.oauth.installation_store
Sub-modules
slack_sdk.oauth.installation_store.amazon_s3
slack_sdk.oauth.installation_store.async_cacheable_installation_store
slack_sdk.oauth.installation_store.async_installation_store
slack_sdk.oauth.installation_store.cacheable_installation_store
slack_sdk.oauth.installation_store.file
slack_sdk.oauth.installation_store.installation_store
-
Slack installation data store …
slack_sdk.oauth.installation_store.internals
slack_sdk.oauth.installation_store.models
slack_sdk.oauth.installation_store.sqlalchemy
slack_sdk.oauth.installation_store.sqlite3
Classes
class Bot (*, app_id: Optional[str] = None, enterprise_id: Optional[str] = None, enterprise_name: Optional[str] = None, team_id: Optional[str] = None, team_name: Optional[str] = None, bot_token: str, bot_id: str, bot_user_id: str, bot_scopes: Union[str, Sequence[str]] = '', bot_refresh_token: Optional[str] = None, bot_token_expires_in: Optional[int] = None, bot_token_expires_at: Union[int, datetime.datetime, str, ForwardRef(None)] = None, is_enterprise_install: Optional[bool] = False, installed_at: Union[float, datetime.datetime, str], custom_values: Optional[Dict[str, Any]] = None)
-
Expand source code
class Bot: app_id: Optional[str] enterprise_id: Optional[str] enterprise_name: Optional[str] team_id: Optional[str] team_name: Optional[str] bot_token: str bot_id: str bot_user_id: str bot_scopes: Sequence[str] # only when token rotation is enabled bot_refresh_token: Optional[str] # only when token rotation is enabled bot_token_expires_at: Optional[int] is_enterprise_install: bool installed_at: float custom_values: Dict[str, Any] def __init__( self, *, app_id: Optional[str] = None, # org / workspace enterprise_id: Optional[str] = None, enterprise_name: Optional[str] = None, team_id: Optional[str] = None, team_name: Optional[str] = None, # bot bot_token: str, bot_id: str, bot_user_id: str, bot_scopes: Union[str, Sequence[str]] = "", # only when token rotation is enabled bot_refresh_token: Optional[str] = None, # only when token rotation is enabled bot_token_expires_in: Optional[int] = None, # only for duplicating this object # only when token rotation is enabled bot_token_expires_at: Optional[Union[int, datetime, str]] = None, is_enterprise_install: Optional[bool] = False, # timestamps # The expected value type is float but the internals handle other types too # for str values, we support only ISO datetime format. installed_at: Union[float, datetime, str], # custom values custom_values: Optional[Dict[str, Any]] = None, ): self.app_id = app_id self.enterprise_id = enterprise_id self.enterprise_name = enterprise_name self.team_id = team_id self.team_name = team_name self.bot_token = bot_token self.bot_id = bot_id self.bot_user_id = bot_user_id if isinstance(bot_scopes, str): self.bot_scopes = bot_scopes.split(",") if len(bot_scopes) > 0 else [] else: self.bot_scopes = bot_scopes self.bot_refresh_token = bot_refresh_token if bot_token_expires_at is not None: self.bot_token_expires_at = _timestamp_to_type(bot_token_expires_at, int) elif bot_token_expires_in is not None: self.bot_token_expires_at = int(time()) + bot_token_expires_in else: self.bot_token_expires_at = None self.is_enterprise_install = is_enterprise_install or False self.installed_at = _timestamp_to_type(installed_at, float) self.custom_values = custom_values if custom_values is not None else {} def set_custom_value(self, name: str, value: Any): self.custom_values[name] = value def get_custom_value(self, name: str) -> Optional[Any]: return self.custom_values.get(name) def to_dict(self) -> Dict[str, Any]: standard_values = { "app_id": self.app_id, "enterprise_id": self.enterprise_id, "enterprise_name": self.enterprise_name, "team_id": self.team_id, "team_name": self.team_name, "bot_token": self.bot_token, "bot_id": self.bot_id, "bot_user_id": self.bot_user_id, "bot_scopes": ",".join(self.bot_scopes) if self.bot_scopes else None, "bot_refresh_token": self.bot_refresh_token, "bot_token_expires_at": datetime.utcfromtimestamp(self.bot_token_expires_at) if self.bot_token_expires_at is not None else None, "is_enterprise_install": self.is_enterprise_install, "installed_at": datetime.utcfromtimestamp(self.installed_at), } # prioritize standard_values over custom_values # when the same keys exist in both return {**self.custom_values, **standard_values}
Class variables
var app_id : Optional[str]
var bot_id : str
var bot_refresh_token : Optional[str]
var bot_scopes : Sequence[str]
var bot_token : str
var bot_token_expires_at : Optional[int]
var bot_user_id : str
var custom_values : Dict[str, Any]
var enterprise_id : Optional[str]
var enterprise_name : Optional[str]
var installed_at : float
var is_enterprise_install : bool
var team_id : Optional[str]
var team_name : Optional[str]
Methods
def get_custom_value(self, name: str) ‑> Optional[Any]
def set_custom_value(self, name: str, value: Any)
def to_dict(self) ‑> Dict[str, Any]
class FileInstallationStore (*, base_dir: str = '/Users/kazuhiro.sera/.bolt-app-installation', historical_data_enabled: bool = True, client_id: Optional[str] = None, logger: logging.Logger = <Logger slack_sdk.oauth.installation_store.file (WARNING)>)
-
The installation store interface.
The minimum required methods are:
- save(installation)
- find_installation(enterprise_id, team_id, user_id, is_enterprise_install)
If you would like to properly handle app uninstallations and token revocations, the following methods should be implemented.
- delete_installation(enterprise_id, team_id, user_id)
- delete_all(enterprise_id, team_id)
If your app needs only bot scope installations, the simpler way to implement would be:
- save(installation)
- find_bot(enterprise_id, team_id, is_enterprise_install)
- delete_bot(enterprise_id, team_id)
- delete_all(enterprise_id, team_id)
Expand source code
class FileInstallationStore(InstallationStore, AsyncInstallationStore): def __init__( self, *, base_dir: str = str(Path.home()) + "/.bolt-app-installation", historical_data_enabled: bool = True, client_id: Optional[str] = None, logger: Logger = logging.getLogger(__name__), ): self.base_dir = base_dir self.historical_data_enabled = historical_data_enabled self.client_id = client_id if self.client_id is not None: self.base_dir = f"{self.base_dir}/{self.client_id}" self._logger = logger @property def logger(self) -> Logger: if self._logger is None: self._logger = logging.getLogger(__name__) return self._logger async def async_save(self, installation: Installation): return self.save(installation) async def async_save_bot(self, bot: Bot): return self.save_bot(bot) def save(self, installation: Installation): none = "none" e_id = installation.enterprise_id or none t_id = installation.team_id or none team_installation_dir = f"{self.base_dir}/{e_id}-{t_id}" self._mkdir(team_installation_dir) self.save_bot(installation.to_bot()) if self.historical_data_enabled: history_version: str = str(installation.installed_at) # per workspace entity: str = json.dumps(installation.__dict__) with open(f"{team_installation_dir}/installer-latest", "w") as f: f.write(entity) with open(f"{team_installation_dir}/installer-{history_version}", "w") as f: f.write(entity) # per workspace per user u_id = installation.user_id or none entity: str = json.dumps(installation.__dict__) with open(f"{team_installation_dir}/installer-{u_id}-latest", "w") as f: f.write(entity) with open(f"{team_installation_dir}/installer-{u_id}-{history_version}", "w") as f: f.write(entity) else: u_id = installation.user_id or none installer_filepath = f"{team_installation_dir}/installer-{u_id}-latest" with open(installer_filepath, "w") as f: entity: str = json.dumps(installation.__dict__) f.write(entity) def save_bot(self, bot: Bot): if bot.bot_token is None: self.logger.debug("Skipped saving a new row because of the absense of bot token in it") return none = "none" e_id = bot.enterprise_id or none t_id = bot.team_id or none team_installation_dir = f"{self.base_dir}/{e_id}-{t_id}" self._mkdir(team_installation_dir) if self.historical_data_enabled: history_version: str = str(bot.installed_at) entity: str = json.dumps(bot.__dict__) with open(f"{team_installation_dir}/bot-latest", "w") as f: f.write(entity) with open(f"{team_installation_dir}/bot-{history_version}", "w") as f: f.write(entity) else: with open(f"{team_installation_dir}/bot-latest", "w") as f: entity: str = json.dumps(bot.__dict__) f.write(entity) async def async_find_bot( self, *, enterprise_id: Optional[str], team_id: Optional[str], is_enterprise_install: Optional[bool] = False, ) -> Optional[Bot]: return self.find_bot( enterprise_id=enterprise_id, team_id=team_id, is_enterprise_install=is_enterprise_install, ) def find_bot( self, *, enterprise_id: Optional[str], team_id: Optional[str], is_enterprise_install: Optional[bool] = False, ) -> Optional[Bot]: none = "none" e_id = enterprise_id or none t_id = team_id or none if is_enterprise_install: t_id = none bot_filepath = f"{self.base_dir}/{e_id}-{t_id}/bot-latest" try: with open(bot_filepath) as f: data = json.loads(f.read()) return Bot(**data) except FileNotFoundError as e: message = f"Installation data missing for enterprise: {e_id}, team: {t_id}: {e}" self.logger.debug(message) return None async def async_find_installation( self, *, enterprise_id: Optional[str], team_id: Optional[str], user_id: Optional[str] = None, is_enterprise_install: Optional[bool] = False, ) -> Optional[Installation]: return self.find_installation( enterprise_id=enterprise_id, team_id=team_id, user_id=user_id, is_enterprise_install=is_enterprise_install, ) def find_installation( self, *, enterprise_id: Optional[str], team_id: Optional[str], user_id: Optional[str] = None, is_enterprise_install: Optional[bool] = False, ) -> Optional[Installation]: none = "none" e_id = enterprise_id or none t_id = team_id or none if is_enterprise_install: t_id = none installation_filepath = f"{self.base_dir}/{e_id}-{t_id}/installer-latest" if user_id is not None: installation_filepath = f"{self.base_dir}/{e_id}-{t_id}/installer-{user_id}-latest" try: installation: Optional[Installation] = None with open(installation_filepath) as f: data = json.loads(f.read()) installation = Installation(**data) has_user_installation = user_id is not None and installation is not None no_bot_token_installation = installation is not None and installation.bot_token is None should_find_bot_installation = has_user_installation or no_bot_token_installation if should_find_bot_installation: # Retrieve the latest bot token, just in case # See also: https://github.com/slackapi/bolt-python/issues/664 latest_bot_installation = self.find_bot( enterprise_id=enterprise_id, team_id=team_id, is_enterprise_install=is_enterprise_install, ) if latest_bot_installation is not None and installation.bot_token != latest_bot_installation.bot_token: # NOTE: this logic is based on the assumption that every single installation has bot scopes # If you need to installation patterns without bot scopes in the same S3 bucket, # please fork this code and implement your own logic. installation.bot_id = latest_bot_installation.bot_id installation.bot_user_id = latest_bot_installation.bot_user_id installation.bot_token = latest_bot_installation.bot_token installation.bot_scopes = latest_bot_installation.bot_scopes installation.bot_refresh_token = latest_bot_installation.bot_refresh_token installation.bot_token_expires_at = latest_bot_installation.bot_token_expires_at return installation except FileNotFoundError as e: message = f"Installation data missing for enterprise: {e_id}, team: {t_id}: {e}" self.logger.debug(message) return None async def async_delete_bot(self, *, enterprise_id: Optional[str], team_id: Optional[str]) -> None: return self.delete_bot(enterprise_id=enterprise_id, team_id=team_id) def delete_bot(self, *, enterprise_id: Optional[str], team_id: Optional[str]) -> None: none = "none" e_id = enterprise_id or none t_id = team_id or none filepath_glob = f"{self.base_dir}/{e_id}-{t_id}/bot-*" self._delete_by_glob(e_id, t_id, filepath_glob) async def async_delete_installation( self, *, enterprise_id: Optional[str], team_id: Optional[str], user_id: Optional[str] = None, ) -> None: return self.delete_installation(enterprise_id=enterprise_id, team_id=team_id, user_id=user_id) def delete_installation( self, *, enterprise_id: Optional[str], team_id: Optional[str], user_id: Optional[str] = None, ) -> None: none = "none" e_id = enterprise_id or none t_id = team_id or none if user_id is not None: filepath_glob = f"{self.base_dir}/{e_id}-{t_id}/installer-{user_id}-*" else: filepath_glob = f"{self.base_dir}/{e_id}-{t_id}/installer-*" self._delete_by_glob(e_id, t_id, filepath_glob) def _delete_by_glob(self, e_id: str, t_id: str, filepath_glob: str): for filepath in glob.glob(filepath_glob): try: os.remove(filepath) except FileNotFoundError as e: message = f"Failed to delete installation data for enterprise: {e_id}, team: {t_id}: {e}" self.logger.warning(message) @staticmethod def _mkdir(path: Union[str, Path]): if isinstance(path, str): path = Path(path) path.mkdir(parents=True, exist_ok=True)
Ancestors
Instance variables
prop logger : logging.Logger
-
Expand source code
@property def logger(self) -> Logger: if self._logger is None: self._logger = logging.getLogger(__name__) return self._logger
Inherited members
class Installation (*, app_id: Optional[str] = None, enterprise_id: Optional[str] = None, enterprise_name: Optional[str] = None, enterprise_url: Optional[str] = None, team_id: Optional[str] = None, team_name: Optional[str] = None, bot_token: Optional[str] = None, bot_id: Optional[str] = None, bot_user_id: Optional[str] = None, bot_scopes: Union[str, Sequence[str]] = '', bot_refresh_token: Optional[str] = None, bot_token_expires_in: Optional[int] = None, bot_token_expires_at: Union[int, datetime.datetime, str, ForwardRef(None)] = None, user_id: str, user_token: Optional[str] = None, user_scopes: Union[str, Sequence[str]] = '', user_refresh_token: Optional[str] = None, user_token_expires_in: Optional[int] = None, user_token_expires_at: Union[int, datetime.datetime, str, ForwardRef(None)] = None, incoming_webhook_url: Optional[str] = None, incoming_webhook_channel: Optional[str] = None, incoming_webhook_channel_id: Optional[str] = None, incoming_webhook_configuration_url: Optional[str] = None, is_enterprise_install: Optional[bool] = False, token_type: Optional[str] = None, installed_at: Union[float, datetime.datetime, str, ForwardRef(None)] = None, custom_values: Optional[Dict[str, Any]] = None)
-
Expand source code
class Installation: app_id: Optional[str] enterprise_id: Optional[str] enterprise_name: Optional[str] enterprise_url: Optional[str] team_id: Optional[str] team_name: Optional[str] bot_token: Optional[str] bot_id: Optional[str] bot_user_id: Optional[str] bot_scopes: Optional[Sequence[str]] bot_refresh_token: Optional[str] # only when token rotation is enabled # only when token rotation is enabled # Unix time (seconds): only when token rotation is enabled bot_token_expires_at: Optional[int] user_id: str user_token: Optional[str] user_scopes: Optional[Sequence[str]] user_refresh_token: Optional[str] # only when token rotation is enabled # Unix time (seconds): only when token rotation is enabled user_token_expires_at: Optional[int] incoming_webhook_url: Optional[str] incoming_webhook_channel: Optional[str] incoming_webhook_channel_id: Optional[str] incoming_webhook_configuration_url: Optional[str] is_enterprise_install: bool token_type: Optional[str] installed_at: float custom_values: Dict[str, Any] def __init__( self, *, app_id: Optional[str] = None, # org / workspace enterprise_id: Optional[str] = None, enterprise_name: Optional[str] = None, enterprise_url: Optional[str] = None, team_id: Optional[str] = None, team_name: Optional[str] = None, # bot bot_token: Optional[str] = None, bot_id: Optional[str] = None, bot_user_id: Optional[str] = None, bot_scopes: Union[str, Sequence[str]] = "", bot_refresh_token: Optional[str] = None, # only when token rotation is enabled # only when token rotation is enabled bot_token_expires_in: Optional[int] = None, # only for duplicating this object # only when token rotation is enabled bot_token_expires_at: Optional[Union[int, datetime, str]] = None, # installer user_id: str, user_token: Optional[str] = None, user_scopes: Union[str, Sequence[str]] = "", user_refresh_token: Optional[str] = None, # only when token rotation is enabled # only when token rotation is enabled user_token_expires_in: Optional[int] = None, # only for duplicating this object # only when token rotation is enabled user_token_expires_at: Optional[Union[int, datetime, str]] = None, # incoming webhook incoming_webhook_url: Optional[str] = None, incoming_webhook_channel: Optional[str] = None, incoming_webhook_channel_id: Optional[str] = None, incoming_webhook_configuration_url: Optional[str] = None, # org app is_enterprise_install: Optional[bool] = False, token_type: Optional[str] = None, # timestamps # The expected value type is float but the internals handle other types too # for str values, we supports only ISO datetime format. installed_at: Optional[Union[float, datetime, str]] = None, # custom values custom_values: Optional[Dict[str, Any]] = None, ): self.app_id = app_id self.enterprise_id = enterprise_id self.enterprise_name = enterprise_name self.enterprise_url = enterprise_url self.team_id = team_id self.team_name = team_name self.bot_token = bot_token self.bot_id = bot_id self.bot_user_id = bot_user_id if isinstance(bot_scopes, str): self.bot_scopes = bot_scopes.split(",") if len(bot_scopes) > 0 else [] else: self.bot_scopes = bot_scopes self.bot_refresh_token = bot_refresh_token if bot_token_expires_at is not None: self.bot_token_expires_at = _timestamp_to_type(bot_token_expires_at, int) elif bot_token_expires_in is not None: self.bot_token_expires_at = int(time()) + bot_token_expires_in else: self.bot_token_expires_at = None self.user_id = user_id self.user_token = user_token if isinstance(user_scopes, str): self.user_scopes = user_scopes.split(",") if len(user_scopes) > 0 else [] else: self.user_scopes = user_scopes self.user_refresh_token = user_refresh_token if user_token_expires_at is not None: self.user_token_expires_at = _timestamp_to_type(user_token_expires_at, int) elif user_token_expires_in is not None: self.user_token_expires_at = int(time()) + user_token_expires_in else: self.user_token_expires_at = None self.incoming_webhook_url = incoming_webhook_url self.incoming_webhook_channel = incoming_webhook_channel self.incoming_webhook_channel_id = incoming_webhook_channel_id self.incoming_webhook_configuration_url = incoming_webhook_configuration_url self.is_enterprise_install = is_enterprise_install or False self.token_type = token_type if installed_at is None: self.installed_at = datetime.now().timestamp() else: self.installed_at = _timestamp_to_type(installed_at, float) self.custom_values = custom_values if custom_values is not None else {} def to_bot(self) -> Bot: return Bot( app_id=self.app_id, enterprise_id=self.enterprise_id, enterprise_name=self.enterprise_name, team_id=self.team_id, team_name=self.team_name, bot_token=self.bot_token, bot_id=self.bot_id, bot_user_id=self.bot_user_id, bot_scopes=self.bot_scopes, bot_refresh_token=self.bot_refresh_token, bot_token_expires_at=self.bot_token_expires_at, is_enterprise_install=self.is_enterprise_install, installed_at=self.installed_at, custom_values=self.custom_values, ) def set_custom_value(self, name: str, value: Any): self.custom_values[name] = value def get_custom_value(self, name: str) -> Optional[Any]: return self.custom_values.get(name) def to_dict(self) -> Dict[str, Any]: standard_values = { "app_id": self.app_id, "enterprise_id": self.enterprise_id, "enterprise_name": self.enterprise_name, "enterprise_url": self.enterprise_url, "team_id": self.team_id, "team_name": self.team_name, "bot_token": self.bot_token, "bot_id": self.bot_id, "bot_user_id": self.bot_user_id, "bot_scopes": ",".join(self.bot_scopes) if self.bot_scopes else None, "bot_refresh_token": self.bot_refresh_token, "bot_token_expires_at": datetime.utcfromtimestamp(self.bot_token_expires_at) if self.bot_token_expires_at is not None else None, "user_id": self.user_id, "user_token": self.user_token, "user_scopes": ",".join(self.user_scopes) if self.user_scopes else None, "user_refresh_token": self.user_refresh_token, "user_token_expires_at": datetime.utcfromtimestamp(self.user_token_expires_at) if self.user_token_expires_at is not None else None, "incoming_webhook_url": self.incoming_webhook_url, "incoming_webhook_channel": self.incoming_webhook_channel, "incoming_webhook_channel_id": self.incoming_webhook_channel_id, "incoming_webhook_configuration_url": self.incoming_webhook_configuration_url, "is_enterprise_install": self.is_enterprise_install, "token_type": self.token_type, "installed_at": datetime.utcfromtimestamp(self.installed_at), } # prioritize standard_values over custom_values # when the same keys exist in both return {**self.custom_values, **standard_values}
Class variables
var app_id : Optional[str]
var bot_id : Optional[str]
var bot_refresh_token : Optional[str]
var bot_scopes : Optional[Sequence[str]]
var bot_token : Optional[str]
var bot_token_expires_at : Optional[int]
var bot_user_id : Optional[str]
var custom_values : Dict[str, Any]
var enterprise_id : Optional[str]
var enterprise_name : Optional[str]
var enterprise_url : Optional[str]
var incoming_webhook_channel : Optional[str]
var incoming_webhook_channel_id : Optional[str]
var incoming_webhook_configuration_url : Optional[str]
var incoming_webhook_url : Optional[str]
var installed_at : float
var is_enterprise_install : bool
var team_id : Optional[str]
var team_name : Optional[str]
var token_type : Optional[str]
var user_id : str
var user_refresh_token : Optional[str]
var user_scopes : Optional[Sequence[str]]
var user_token : Optional[str]
var user_token_expires_at : Optional[int]
Methods
def get_custom_value(self, name: str) ‑> Optional[Any]
def set_custom_value(self, name: str, value: Any)
def to_bot(self) ‑> Bot
def to_dict(self) ‑> Dict[str, Any]
class InstallationStore
-
The installation store interface.
The minimum required methods are:
- save(installation)
- find_installation(enterprise_id, team_id, user_id, is_enterprise_install)
If you would like to properly handle app uninstallations and token revocations, the following methods should be implemented.
- delete_installation(enterprise_id, team_id, user_id)
- delete_all(enterprise_id, team_id)
If your app needs only bot scope installations, the simpler way to implement would be:
- save(installation)
- find_bot(enterprise_id, team_id, is_enterprise_install)
- delete_bot(enterprise_id, team_id)
- delete_all(enterprise_id, team_id)
Expand source code
class InstallationStore: """The installation store interface. The minimum required methods are: * save(installation) * find_installation(enterprise_id, team_id, user_id, is_enterprise_install) If you would like to properly handle app uninstallations and token revocations, the following methods should be implemented. * delete_installation(enterprise_id, team_id, user_id) * delete_all(enterprise_id, team_id) If your app needs only bot scope installations, the simpler way to implement would be: * save(installation) * find_bot(enterprise_id, team_id, is_enterprise_install) * delete_bot(enterprise_id, team_id) * delete_all(enterprise_id, team_id) """ @property def logger(self) -> Logger: raise NotImplementedError() def save(self, installation: Installation): """Saves an installation data""" raise NotImplementedError() def save_bot(self, bot: Bot): """Saves a bot installation data""" raise NotImplementedError() def find_bot( self, *, enterprise_id: Optional[str], team_id: Optional[str], is_enterprise_install: Optional[bool] = False, ) -> Optional[Bot]: """Finds a bot scope installation per workspace / org""" raise NotImplementedError() def find_installation( self, *, enterprise_id: Optional[str], team_id: Optional[str], user_id: Optional[str] = None, is_enterprise_install: Optional[bool] = False, ) -> Optional[Installation]: """Finds a relevant installation for the given IDs. If the user_id is absent, this method may return the latest installation in the workspace / org. """ raise NotImplementedError() def delete_bot( self, *, enterprise_id: Optional[str], team_id: Optional[str], ) -> None: """Deletes a bot scope installation per workspace / org""" raise NotImplementedError() def delete_installation( self, *, enterprise_id: Optional[str], team_id: Optional[str], user_id: Optional[str] = None, ) -> None: """Deletes an installation that matches the given IDs""" raise NotImplementedError() def delete_all( self, *, enterprise_id: Optional[str], team_id: Optional[str], ): """Deletes all installation data for the given workspace / org""" self.delete_bot(enterprise_id=enterprise_id, team_id=team_id) self.delete_installation(enterprise_id=enterprise_id, team_id=team_id)
Subclasses
- AmazonS3InstallationStore
- CacheableInstallationStore
- FileInstallationStore
- SQLAlchemyInstallationStore
- SQLite3InstallationStore
Instance variables
prop logger : logging.Logger
-
Expand source code
@property def logger(self) -> Logger: raise NotImplementedError()
Methods
def delete_all(self, *, enterprise_id: Optional[str], team_id: Optional[str])
-
Deletes all installation data for the given workspace / org
def delete_bot(self, *, enterprise_id: Optional[str], team_id: Optional[str]) ‑> None
-
Deletes a bot scope installation per workspace / org
def delete_installation(self, *, enterprise_id: Optional[str], team_id: Optional[str], user_id: Optional[str] = None) ‑> None
-
Deletes an installation that matches the given IDs
def find_bot(self, *, enterprise_id: Optional[str], team_id: Optional[str], is_enterprise_install: Optional[bool] = False) ‑> Optional[Bot]
-
Finds a bot scope installation per workspace / org
def find_installation(self, *, enterprise_id: Optional[str], team_id: Optional[str], user_id: Optional[str] = None, is_enterprise_install: Optional[bool] = False) ‑> Optional[Installation]
-
Finds a relevant installation for the given IDs. If the user_id is absent, this method may return the latest installation in the workspace / org.
def save(self, installation: Installation)
-
Saves an installation data
def save_bot(self, bot: Bot)
-
Saves a bot installation data