Skip to content

Commit f3f1455

Browse files
committed
Add v1.0 compatible mode to #148 Org-wide App support
1 parent 0603e0f commit f3f1455

File tree

12 files changed

+162
-10
lines changed

12 files changed

+162
-10
lines changed

scripts/run_tests.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ else
2020
black slack_bolt/ tests/ \
2121
&& pytest \
2222
&& pip install -e ".[adapter]" \
23-
&& pip install -U pytype \
23+
&& pip install -U pip setuptools wheel pytype \
2424
&& pytype slack_bolt/
2525
else
2626
black slack_bolt/ tests/ && pytest

slack_bolt/adapter/aws_lambda/lambda_s3_oauth_flow.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,9 @@ def __init__(
6262
# the settings may already have pre-defined authorize.
6363
# In this case, the /slack/events endpoint doesn't work along with the OAuth flow.
6464
settings.authorize = InstallationStoreAuthorize(
65-
logger=logger, installation_store=settings.installation_store
65+
logger=logger,
66+
installation_store=settings.installation_store,
67+
bot_only=settings.installation_store_bot_only,
6668
)
6769

6870
OAuthFlow.__init__(self, client=client, logger=logger, settings=settings)

slack_bolt/app/app.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,8 @@ def __init__(
7979
# for multi-workspace apps
8080
authorize: Optional[Callable[..., AuthorizeResult]] = None,
8181
installation_store: Optional[InstallationStore] = None,
82+
# for v1.0.x compatibility
83+
installation_store_bot_only: bool = False,
8284
# for the OAuth flow
8385
oauth_settings: Optional[OAuthSettings] = None,
8486
oauth_flow: Optional[OAuthFlow] = None,
@@ -96,6 +98,7 @@ def __init__(
9698
:param authorize: The function to authorize an incoming request from Slack
9799
by checking if there is a team/user in the installation data.
98100
:param installation_store: The module offering save/find operations of installation data
101+
:param installation_store_bot_only: Use InstallationStore#find_bot if True (Default: False)
99102
:param oauth_settings: The settings related to Slack app installation flow (OAuth flow)
100103
:param oauth_flow: Manually instantiated slack_bolt.oauth.OAuthFlow.
101104
This is always prioritized over oauth_settings.
@@ -140,6 +143,7 @@ def __init__(
140143
self._authorize = InstallationStoreAuthorize(
141144
installation_store=self._installation_store,
142145
logger=self._framework_logger,
146+
bot_only=installation_store_bot_only,
143147
)
144148

145149
self._oauth_flow: Optional[OAuthFlow] = None

slack_bolt/app/async_app.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ def __init__(
9090
client: Optional[AsyncWebClient] = None,
9191
# for multi-workspace apps
9292
installation_store: Optional[AsyncInstallationStore] = None,
93+
installation_store_bot_only: bool = False,
9394
authorize: Optional[Callable[..., Awaitable[AuthorizeResult]]] = None,
9495
# for the OAuth flow
9596
oauth_settings: Optional[AsyncOAuthSettings] = None,
@@ -106,6 +107,7 @@ def __init__(
106107
:param token: The bot access token required only for single-workspace app.
107108
:param client: The singleton slack_sdk.web.async_client.AsyncWebClient instance for this app.
108109
:param installation_store: The module offering save/find operations of installation data
110+
:param installation_store_bot_only: Use InstallationStore#find_bot if True (Default: False)
109111
:param authorize: The function to authorize an incoming request from Slack
110112
by checking if there is a team/user in the installation data.
111113
:param oauth_settings: The settings related to Slack app installation flow (OAuth flow)
@@ -155,6 +157,7 @@ def __init__(
155157
self._async_authorize = AsyncInstallationStoreAuthorize(
156158
installation_store=self._async_installation_store,
157159
logger=self._framework_logger,
160+
bot_only=installation_store_bot_only,
158161
)
159162

160163
self._async_oauth_flow: Optional[AsyncOAuthFlow] = None

slack_bolt/authorization/async_authorize.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -91,19 +91,24 @@ async def __call__(
9191

9292

9393
class AsyncInstallationStoreAuthorize(AsyncAuthorize):
94-
authorize_result_cache: Dict[str, AuthorizeResult] = {}
94+
authorize_result_cache: Dict[str, AuthorizeResult]
9595
find_installation_available: Optional[bool]
9696

9797
def __init__(
9898
self,
9999
*,
100100
logger: Logger,
101101
installation_store: AsyncInstallationStore,
102+
# For v1.0.x compatibility and people who still want its simplicity
103+
# use only InstallationStore#find_bot(enterprise_id, team_id)
104+
bot_only: bool = False,
102105
cache_enabled: bool = False,
103106
):
104107
self.logger = logger
105108
self.installation_store = installation_store
109+
self.bot_only = bot_only
106110
self.cache_enabled = cache_enabled
111+
self.authorize_result_cache = {}
107112
self.find_installation_available = None
108113

109114
async def __call__(
@@ -123,7 +128,7 @@ async def __call__(
123128
bot_token: Optional[str] = None
124129
user_token: Optional[str] = None
125130

126-
if self.find_installation_available:
131+
if not self.bot_only and self.find_installation_available:
127132
# since v1.1, this is the default way
128133
try:
129134
installation: Optional[
@@ -153,7 +158,7 @@ async def __call__(
153158
except NotImplementedError as _:
154159
self.find_installation_available = False
155160

156-
if not self.find_installation_available:
161+
if self.bot_only or not self.find_installation_available:
157162
# Use find_bot to get bot value (legacy)
158163
bot: Optional[Bot] = await self.installation_store.async_find_bot(
159164
enterprise_id=enterprise_id,

slack_bolt/authorization/authorize.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -90,19 +90,25 @@ def __call__(
9090

9191

9292
class InstallationStoreAuthorize(Authorize):
93-
authorize_result_cache: Dict[str, AuthorizeResult] = {}
93+
authorize_result_cache: Dict[str, AuthorizeResult]
94+
bot_only: bool
9495
find_installation_available: bool
9596

9697
def __init__(
9798
self,
9899
*,
99100
logger: Logger,
100101
installation_store: InstallationStore,
102+
# For v1.0.x compatibility and people who still want its simplicity
103+
# use only InstallationStore#find_bot(enterprise_id, team_id)
104+
bot_only: bool = False,
101105
cache_enabled: bool = False,
102106
):
103107
self.logger = logger
104108
self.installation_store = installation_store
109+
self.bot_only = bot_only
105110
self.cache_enabled = cache_enabled
111+
self.authorize_result_cache = {}
106112
self.find_installation_available = hasattr(
107113
installation_store, "find_installation"
108114
)
@@ -119,7 +125,7 @@ def __call__(
119125
bot_token: Optional[str] = None
120126
user_token: Optional[str] = None
121127

122-
if self.find_installation_available:
128+
if not self.bot_only and self.find_installation_available:
123129
# since v1.1, this is the default way
124130
try:
125131
installation: Optional[
@@ -149,7 +155,7 @@ def __call__(
149155
except NotImplementedError as _:
150156
self.find_installation_available = False
151157

152-
if not self.find_installation_available:
158+
if self.bot_only or not self.find_installation_available:
153159
# Use find_bot to get bot value (legacy)
154160
bot: Optional[Bot] = self.installation_store.find_bot(
155161
enterprise_id=enterprise_id,

slack_bolt/oauth/async_oauth_flow.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ def sqlite3(
110110
# state parameter related configurations
111111
state_cookie_name: str = OAuthStateUtils.default_cookie_name,
112112
state_expiration_seconds: int = OAuthStateUtils.default_expiration_seconds,
113+
installation_store_bot_only: bool = False,
113114
client: Optional[AsyncWebClient] = None,
114115
logger: Optional[Logger] = None,
115116
) -> "AsyncOAuthFlow":
@@ -140,6 +141,7 @@ def sqlite3(
140141
installation_store=SQLite3InstallationStore(
141142
database=database, client_id=client_id, logger=logger,
142143
),
144+
installation_store_bot_only=installation_store_bot_only,
143145
# state parameter related configurations
144146
state_store=SQLite3OAuthStateStore(
145147
database=database,

slack_bolt/oauth/async_oauth_settings.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ class AsyncOAuthSettings:
3939
authorization_url: str # default: https://slack.com/oauth/v2/authorize
4040
# Installation Management
4141
installation_store: AsyncInstallationStore
42+
installation_store_bot_only: bool
4243
authorize: AsyncAuthorize
4344
# state parameter related configurations
4445
state_store: AsyncOAuthStateStore
@@ -69,6 +70,7 @@ def __init__(
6970
authorization_url: Optional[str] = None,
7071
# Installation Management
7172
installation_store: Optional[AsyncInstallationStore] = None,
73+
installation_store_bot_only: bool = False,
7274
# state parameter related configurations
7375
state_store: Optional[AsyncOAuthStateStore] = None,
7476
state_cookie_name: str = OAuthStateUtils.default_cookie_name,
@@ -90,6 +92,7 @@ def __init__(
9092
:param failure_url: Set a complete URL if you want to redirect end-users when an installation fails.
9193
:param authorization_url: Set a URL if you want to customize the URL https://slack.com/oauth/v2/authorize
9294
:param installation_store: Specify the instance of InstallationStore (Default: FileInstallationStore)
95+
:param installation_store_bot_only: Use AsyncInstallationStore#find_bot if True (Default: False)
9396
:param state_store: Specify the instance of InstallationStore (Default: FileOAuthStateStore)
9497
:param state_cookie_name: The cookie name that is set for installers' browser. (Default: slack-app-oauth-state)
9598
:param state_expiration_seconds: The seconds that the state value is alive (Default: 600 seconds)
@@ -129,8 +132,11 @@ def __init__(
129132
self.installation_store = (
130133
installation_store or get_or_create_default_installation_store(client_id)
131134
)
135+
self.installation_store_bot_only = installation_store_bot_only
132136
self.authorize = AsyncInstallationStoreAuthorize(
133-
logger=logger, installation_store=self.installation_store,
137+
logger=logger,
138+
installation_store=self.installation_store,
139+
bot_only=self.installation_store_bot_only,
134140
)
135141
# state parameter related configurations
136142
self.state_store = state_store or FileOAuthStateStore(

slack_bolt/oauth/oauth_flow.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ def sqlite3(
105105
# state parameter related configurations
106106
state_cookie_name: str = OAuthStateUtils.default_cookie_name,
107107
state_expiration_seconds: int = OAuthStateUtils.default_expiration_seconds,
108+
installation_store_bot_only: bool = False,
108109
client: Optional[WebClient] = None,
109110
logger: Optional[Logger] = None,
110111
) -> "OAuthFlow":
@@ -135,6 +136,7 @@ def sqlite3(
135136
installation_store=SQLite3InstallationStore(
136137
database=database, client_id=client_id, logger=logger,
137138
),
139+
installation_store_bot_only=installation_store_bot_only,
138140
# state parameter related configurations
139141
state_store=SQLite3OAuthStateStore(
140142
database=database,

slack_bolt/oauth/oauth_settings.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ class OAuthSettings:
3434
authorization_url: str # default: https://slack.com/oauth/v2/authorize
3535
# Installation Management
3636
installation_store: InstallationStore
37+
installation_store_bot_only: bool
3738
authorize: Authorize
3839
# state parameter related configurations
3940
state_store: OAuthStateStore
@@ -64,6 +65,7 @@ def __init__(
6465
authorization_url: Optional[str] = None,
6566
# Installation Management
6667
installation_store: Optional[InstallationStore] = None,
68+
installation_store_bot_only: bool = False,
6769
# state parameter related configurations
6870
state_store: Optional[OAuthStateStore] = None,
6971
state_cookie_name: str = OAuthStateUtils.default_cookie_name,
@@ -85,6 +87,7 @@ def __init__(
8587
:param failure_url: Set a complete URL if you want to redirect end-users when an installation fails.
8688
:param authorization_url: Set a URL if you want to customize the URL https://slack.com/oauth/v2/authorize
8789
:param installation_store: Specify the instance of InstallationStore (Default: FileInstallationStore)
90+
:param installation_store_bot_only: Use InstallationStore#find_bot if True (Default: False)
8891
:param state_store: Specify the instance of InstallationStore (Default: FileOAuthStateStore)
8992
:param state_cookie_name: The cookie name that is set for installers' browser. (Default: slack-app-oauth-state)
9093
:param state_expiration_seconds: The seconds that the state value is alive (Default: 600 seconds)
@@ -123,8 +126,11 @@ def __init__(
123126
self.installation_store = (
124127
installation_store or get_or_create_default_installation_store(client_id)
125128
)
129+
self.installation_store_bot_only = installation_store_bot_only
126130
self.authorize = InstallationStoreAuthorize(
127-
logger=logger, installation_store=self.installation_store,
131+
logger=logger,
132+
installation_store=self.installation_store,
133+
bot_only=self.installation_store_bot_only,
128134
)
129135
# state parameter related configurations
130136
self.state_store = state_store or FileOAuthStateStore(

0 commit comments

Comments
 (0)