Skip to content

Commit

Permalink
Fix #1427 Add apps.manifest.* & tooling.tokens.rotate API support (#1430
Browse files Browse the repository at this point in the history
)
  • Loading branch information
seratch authored Nov 21, 2023
1 parent ed02c65 commit 3e2d7e8
Show file tree
Hide file tree
Showing 5 changed files with 473 additions and 7 deletions.
200 changes: 200 additions & 0 deletions integration_tests/web/test_app_manifest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,200 @@
import os
import unittest

from slack_sdk.web import WebClient


class TestWebClient(unittest.TestCase):
"""Runs integration tests with real Slack API"""

def setUp(self):
pass

def tearDown(self):
pass

def test_operations(self):
token = os.environ["SLACK_SDK_TEST_TOOLING_TOKEN"] # xoxe.xoxp-...
client = WebClient(token)
client.apps_manifest_validate(manifest=STR_MANIFEST)
client.apps_manifest_validate(manifest=DICT_MANIFEST)

response = client.apps_manifest_create(manifest=STR_MANIFEST)
app_id = response["app_id"]
try:
client.apps_manifest_update(app_id=app_id, manifest=DICT_MANIFEST)
client.apps_manifest_export(app_id=app_id)
finally:
client.apps_manifest_delete(app_id=app_id)


STR_MANIFEST = """{
"display_information": {
"name": "manifest-sandbox"
},
"features": {
"app_home": {
"home_tab_enabled": true,
"messages_tab_enabled": false,
"messages_tab_read_only_enabled": false
},
"bot_user": {
"display_name": "manifest-sandbox",
"always_online": true
},
"shortcuts": [
{
"name": "message one",
"type": "message",
"callback_id": "m",
"description": "message"
},
{
"name": "global one",
"type": "global",
"callback_id": "g",
"description": "global"
}
],
"slash_commands": [
{
"command": "/hey",
"url": "https://www.example.com/",
"description": "What's up?",
"usage_hint": "What's up?",
"should_escape": true
}
],
"unfurl_domains": [
"example.com"
]
},
"oauth_config": {
"redirect_urls": [
"https://www.example.com/foo"
],
"scopes": {
"user": [
"search:read",
"channels:read",
"groups:read",
"mpim:read"
],
"bot": [
"commands",
"incoming-webhook",
"app_mentions:read",
"links:read"
]
}
},
"settings": {
"allowed_ip_address_ranges": [
"123.123.123.123/32"
],
"event_subscriptions": {
"request_url": "https://www.example.com/slack/events",
"user_events": [
"member_joined_channel"
],
"bot_events": [
"app_mention",
"link_shared"
]
},
"interactivity": {
"is_enabled": true,
"request_url": "https://www.example.com/",
"message_menu_options_url": "https://www.example.com/"
},
"org_deploy_enabled": true,
"socket_mode_enabled": false,
"token_rotation_enabled": true
}
}
"""

DICT_MANIFEST = {
"display_information": {
"name": "manifest-sandbox"
},
"features": {
"app_home": {
"home_tab_enabled": True,
"messages_tab_enabled": False,
"messages_tab_read_only_enabled": False
},
"bot_user": {
"display_name": "manifest-sandbox",
"always_online": True
},
"shortcuts": [
{
"name": "message one",
"type": "message",
"callback_id": "m",
"description": "message"
},
{
"name": "global one",
"type": "global",
"callback_id": "g",
"description": "global"
}
],
"slash_commands": [
{
"command": "/hey",
"url": "https://www.example.com/",
"description": "What's up?",
"usage_hint": "What's up?",
"should_escape": True
}
],
"unfurl_domains": [
"example.com"
]
},
"oauth_config": {
"redirect_urls": [
"https://www.example.com/foo"
],
"scopes": {
"user": [
"search:read",
"channels:read",
"groups:read",
"mpim:read"
],
"bot": [
"commands",
"incoming-webhook",
"app_mentions:read",
"links:read"
]
}
},
"settings": {
"allowed_ip_address_ranges": [
"123.123.123.123/32"
],
"event_subscriptions": {
"request_url": "https://www.example.com/slack/events",
"user_events": [
"member_joined_channel"
],
"bot_events": [
"app_mention",
"link_shared"
]
},
"interactivity": {
"is_enabled": True,
"request_url": "https://www.example.com/",
"message_menu_options_url": "https://www.example.com/"
},
"org_deploy_enabled": True,
"socket_mode_enabled": False,
"token_rotation_enabled": True
}
}
85 changes: 85 additions & 0 deletions slack_sdk/web/async_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -1928,6 +1928,91 @@ async def apps_uninstall(
kwargs.update({"client_id": client_id, "client_secret": client_secret})
return await self.api_call("apps.uninstall", params=kwargs)

async def apps_manifest_create(
self,
*,
manifest: Union[str, Dict[str, Any]],
**kwargs,
) -> AsyncSlackResponse:
"""Create an app from an app manifest
https://api.slack.com/methods/apps.manifest.create
"""
if isinstance(manifest, str):
kwargs.update({"manifest": manifest})
else:
kwargs.update({"manifest": json.dumps(manifest)})
return await self.api_call("apps.manifest.create", params=kwargs)

async def apps_manifest_delete(
self,
*,
app_id: str,
**kwargs,
) -> AsyncSlackResponse:
"""Permanently deletes an app created through app manifests
https://api.slack.com/methods/apps.manifest.delete
"""
kwargs.update({"app_id": app_id})
return await self.api_call("apps.manifest.delete", params=kwargs)

async def apps_manifest_export(
self,
*,
app_id: str,
**kwargs,
) -> AsyncSlackResponse:
"""Export an app manifest from an existing app
https://api.slack.com/methods/apps.manifest.export
"""
kwargs.update({"app_id": app_id})
return await self.api_call("apps.manifest.export", params=kwargs)

async def apps_manifest_update(
self,
*,
app_id: str,
manifest: Union[str, Dict[str, Any]],
**kwargs,
) -> AsyncSlackResponse:
"""Update an app from an app manifest
https://api.slack.com/methods/apps.manifest.update
"""
if isinstance(manifest, str):
kwargs.update({"manifest": manifest})
else:
kwargs.update({"manifest": json.dumps(manifest)})
kwargs.update({"app_id": app_id})
return await self.api_call("apps.manifest.update", params=kwargs)

async def apps_manifest_validate(
self,
*,
manifest: Union[str, Dict[str, Any]],
app_id: Optional[str] = None,
**kwargs,
) -> AsyncSlackResponse:
"""Validate an app manifest
https://api.slack.com/methods/apps.manifest.validate
"""
if isinstance(manifest, str):
kwargs.update({"manifest": manifest})
else:
kwargs.update({"manifest": json.dumps(manifest)})
kwargs.update({"app_id": app_id})
return await self.api_call("apps.manifest.validate", params=kwargs)

async def tooling_tokens_rotate(
self,
*,
refresh_token: str,
**kwargs,
) -> AsyncSlackResponse:
"""Exchanges a refresh token for a new app configuration token
https://api.slack.com/methods/tooling.tokens.rotate
"""
kwargs.update({"refresh_token": refresh_token})
return await self.api_call("tooling.tokens.rotate", params=kwargs)

async def auth_revoke(
self,
*,
Expand Down
85 changes: 85 additions & 0 deletions slack_sdk/web/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -1919,6 +1919,91 @@ def apps_uninstall(
kwargs.update({"client_id": client_id, "client_secret": client_secret})
return self.api_call("apps.uninstall", params=kwargs)

def apps_manifest_create(
self,
*,
manifest: Union[str, Dict[str, Any]],
**kwargs,
) -> SlackResponse:
"""Create an app from an app manifest
https://api.slack.com/methods/apps.manifest.create
"""
if isinstance(manifest, str):
kwargs.update({"manifest": manifest})
else:
kwargs.update({"manifest": json.dumps(manifest)})
return self.api_call("apps.manifest.create", params=kwargs)

def apps_manifest_delete(
self,
*,
app_id: str,
**kwargs,
) -> SlackResponse:
"""Permanently deletes an app created through app manifests
https://api.slack.com/methods/apps.manifest.delete
"""
kwargs.update({"app_id": app_id})
return self.api_call("apps.manifest.delete", params=kwargs)

def apps_manifest_export(
self,
*,
app_id: str,
**kwargs,
) -> SlackResponse:
"""Export an app manifest from an existing app
https://api.slack.com/methods/apps.manifest.export
"""
kwargs.update({"app_id": app_id})
return self.api_call("apps.manifest.export", params=kwargs)

def apps_manifest_update(
self,
*,
app_id: str,
manifest: Union[str, Dict[str, Any]],
**kwargs,
) -> SlackResponse:
"""Update an app from an app manifest
https://api.slack.com/methods/apps.manifest.update
"""
if isinstance(manifest, str):
kwargs.update({"manifest": manifest})
else:
kwargs.update({"manifest": json.dumps(manifest)})
kwargs.update({"app_id": app_id})
return self.api_call("apps.manifest.update", params=kwargs)

def apps_manifest_validate(
self,
*,
manifest: Union[str, Dict[str, Any]],
app_id: Optional[str] = None,
**kwargs,
) -> SlackResponse:
"""Validate an app manifest
https://api.slack.com/methods/apps.manifest.validate
"""
if isinstance(manifest, str):
kwargs.update({"manifest": manifest})
else:
kwargs.update({"manifest": json.dumps(manifest)})
kwargs.update({"app_id": app_id})
return self.api_call("apps.manifest.validate", params=kwargs)

def tooling_tokens_rotate(
self,
*,
refresh_token: str,
**kwargs,
) -> SlackResponse:
"""Exchanges a refresh token for a new app configuration token
https://api.slack.com/methods/tooling.tokens.rotate
"""
kwargs.update({"refresh_token": refresh_token})
return self.api_call("tooling.tokens.rotate", params=kwargs)

def auth_revoke(
self,
*,
Expand Down
Loading

0 comments on commit 3e2d7e8

Please sign in to comment.