def test_authorize_conflicts(self): oauth_settings = OAuthSettings( client_id="111.222", client_secret="valid", installation_store=FileInstallationStore(), state_store=FileOAuthStateStore(expiration_seconds=120), ) # no error with this App(signing_secret="valid", oauth_settings=oauth_settings) def authorize() -> AuthorizeResult: return AuthorizeResult(enterprise_id="E111", team_id="T111") with pytest.raises(BoltError): App( signing_secret="valid", authorize=authorize, oauth_settings=oauth_settings, ) oauth_flow = OAuthFlow(settings=oauth_settings) # no error with this App(signing_secret="valid", oauth_flow=oauth_flow) with pytest.raises(BoltError): App(signing_secret="valid", authorize=authorize, oauth_flow=oauth_flow)
def test_installation_store_conflicts(self): store1 = FileInstallationStore() store2 = FileInstallationStore() app = App( signing_secret="valid", oauth_settings=OAuthSettings( client_id="111.222", client_secret="valid", installation_store=store1, ), installation_store=store2, ) assert app.installation_store is store1 app = App( signing_secret="valid", oauth_flow=OAuthFlow(settings=OAuthSettings( client_id="111.222", client_secret="valid", installation_store=store1, )), installation_store=store2, ) assert app.installation_store is store1 app = App( signing_secret="valid", oauth_flow=OAuthFlow(settings=OAuthSettings( client_id="111.222", client_secret="valid", )), installation_store=store1, ) assert app.installation_store is store1
def test_token_verification_enabled_False(self): App( signing_secret="valid", client=self.web_client, token_verification_enabled=False, ) App( signing_secret="valid", token="xoxb-invalid", token_verification_enabled=False, ) assert self.mock_received_requests.get("/auth.test") is None
def test_invalid_message_events(self): app = App(client=self.web_client, signing_secret=self.signing_secret) def handle(): pass # valid app.event("message")(handle) with pytest.raises(ValueError): app.event("message.channels")(handle) with pytest.raises(ValueError): app.event("message.groups")(handle) with pytest.raises(ValueError): app.event("message.im")(handle) with pytest.raises(ValueError): app.event("message.mpim")(handle) with pytest.raises(ValueError): app.event(re.compile("message\\..*"))(handle) with pytest.raises(ValueError): app.event({"type": "message.channels"})(handle) with pytest.raises(ValueError): app.event({"type": re.compile("message\\..*")})(handle)
def test_uninstallation_and_revokes(self): app = App(client=self.web_client, signing_secret=self.signing_secret) app._client = WebClient(token="uninstalled-revoked", base_url=self.mock_api_server_base_url) @app.event("app_uninstalled") def handler1(say: Say): say(channel="C111", text="What's up?") @app.event("tokens_revoked") def handler2(say: Say): say(channel="C111", text="What's up?") app_uninstalled_body = { "token": "verification_token", "team_id": "T111", "enterprise_id": "E111", "api_app_id": "A111", "event": { "type": "app_uninstalled" }, "type": "event_callback", "event_id": "Ev111", "event_time": 1599616881, } timestamp, body = str(int(time())), json.dumps(app_uninstalled_body) request: BoltRequest = BoltRequest(body=body, headers=self.build_headers( timestamp, body)) response = app.dispatch(request) assert response.status == 200 tokens_revoked_body = { "token": "verification_token", "team_id": "T111", "enterprise_id": "E111", "api_app_id": "A111", "event": { "type": "tokens_revoked", "tokens": { "oauth": ["UXXXXXXXX"], "bot": ["UXXXXXXXX"] }, }, "type": "event_callback", "event_id": "Ev111", "event_time": 1599616881, } timestamp, body = str(int(time())), json.dumps(tokens_revoked_body) request: BoltRequest = BoltRequest(body=body, headers=self.build_headers( timestamp, body)) response = app.dispatch(request) assert response.status == 200 assert self.mock_received_requests["/auth.test"] == 1 sleep(1) # wait a bit after auto ack() assert self.mock_received_requests["/chat.postMessage"] == 2
def build_app(self, callback_id: str): app = App(client=self.web_client, signing_secret=self.signing_secret) app.step(callback_id=callback_id, edit=edit, save=save, execute=execute) return app
def test_interactions(self): app = App(client=self.web_client) result = {"shortcut": False, "command": False} @app.shortcut("do-something") def shortcut_handler(ack): result["shortcut"] = True ack() @app.command("/hello-socket-mode") def command_handler(ack): result["command"] = True ack() handler = SocketModeHandler( app_token="xapp-A111-222-xyz", app=app, trace_enabled=True, ) try: handler.client.wss_uri = "ws://localhost:3012/link" handler.connect() assert handler.client.is_connected() is True time.sleep(2) # wait for the message receiver handler.client.send_message("foo") time.sleep(2) assert result["shortcut"] is True assert result["command"] is True finally: handler.client.close()
def __init__(self, channel=None): """Initializes the Slack channel handler. Args: channel: Slack channel where logs are sent """ # super(SlackChannelHandler, self).__init__() super().__init__() # set the channel self.set_channel(channel) if not self.channel: raise ValueError('Must supply a "channel" in the logging configuration.') # obtain access token access_token = os.environ.get('SLACK_BOT_TOKEN') if not access_token: raise ValueError('Environmental variable, "SLACK_BOT_TOKEN", is not set.') # obtain signing secret signing_secret = os.environ.get('SLACK_SIGNING_SECRET') if not signing_secret: raise ValueError('Environmental variable, "SLACK_SIGNING_SECRET", is not set.') # authenticate and get slack client app = App(token=access_token, signing_secret=signing_secret) self.client = app.client
def test_valid_multi_auth_secret_absence(self): with pytest.raises(BoltError): App( signing_secret="valid", oauth_settings=OAuthSettings(client_id="111.222", client_secret=None), )
def test_valid_multi_auth(self): app = App( signing_secret="valid", oauth_settings=OAuthSettings(client_id="111.222", client_secret="valid"), ) assert app != None
def test_listener_registration_error(self): app = App(signing_secret="valid", client=self.web_client) with pytest.raises(BoltError): app.action({ "type": "invalid_type", "action_id": "a" })(self.simple_listener)
def test_handle_callback(self): oauth_flow = OAuthFlow( client=WebClient(base_url=self.mock_api_server_base_url), settings=OAuthSettings( client_id="111.222", client_secret="xxx", scopes=["chat:write", "commands"], installation_store=FileInstallationStore(), state_store=FileOAuthStateStore(expiration_seconds=120), success_url="https://www.example.com/completion", failure_url="https://www.example.com/failure", ), ) state = oauth_flow.issue_new_state(None) req = BoltRequest( body="", query=f"code=foo&state={state}", headers={ "cookie": [f"{oauth_flow.settings.state_cookie_name}={state}"] }, ) resp = oauth_flow.handle_callback(req) assert resp.status == 200 assert "https://www.example.com/completion" in resp.body app = App(signing_secret="signing_secret", oauth_flow=oauth_flow) global_shortcut_body = { "type": "shortcut", "token": "verification_token", "action_ts": "111.111", "team": { "id": "T111", "domain": "workspace-domain", "enterprise_id": "E111", "enterprise_name": "Org Name", }, "user": { "id": "W111", "username": "******", "team_id": "T111" }, "callback_id": "test-shortcut", "trigger_id": "111.111.xxxxxx", } body = f"payload={quote(json.dumps(global_shortcut_body))}" timestamp = str(int(time())) signature_verifier = SignatureVerifier("signing_secret") headers = { "content-type": ["application/x-www-form-urlencoded"], "x-slack-signature": [ signature_verifier.generate_signature(body=body, timestamp=timestamp) ], "x-slack-request-timestamp": [timestamp], } request = BoltRequest(body=body, headers=headers) response = app.dispatch(request) assert response.status == 200 assert self.mock_received_requests["/auth.test"] == 1
def test_app_home_opened(self): app = App( client=self.web_client, signing_secret=self.signing_secret, installation_store=OrgAppInstallationStore(), ) event_payload = { "token": "verification-token", "team_id": "T111", "enterprise_id": "E111", "api_app_id": "A111", "event": { "type": "app_home_opened", "user": "******", "channel": "D111", "tab": "messages", "event_ts": "1606810927.510671", }, "type": "event_callback", "event_id": "Ev111", "event_time": 1606810927, "authorizations": [{ "enterprise_id": "E111", "team_id": None, "user_id": "W111", "is_bot": True, "is_enterprise_install": True, }], "is_ext_shared_channel": False, } result = Result() @app.event("app_home_opened") def handle_app_mention(body): assert body == event_payload result.called = True timestamp, body = str(int(time())), json.dumps(event_payload) request: BoltRequest = BoltRequest(body=body, headers=self.build_headers( timestamp, body)) response = app.dispatch(request) assert response.status == 200 # auth.test API call must be skipped assert self.mock_received_requests["/auth.test"] == 1 sleep(1) # wait a bit after auto ack() assert result.called is True
def test_valid_multi_auth_oauth_flow(self): oauth_flow = OAuthFlow(settings=OAuthSettings( client_id="111.222", client_secret="valid", installation_store=FileInstallationStore(), state_store=FileOAuthStateStore(expiration_seconds=120), )) app = App(signing_secret="valid", oauth_flow=oauth_flow) assert app != None
def test_message(self): app = App( client=self.web_client, signing_secret=self.signing_secret, installation_store=OrgAppInstallationStore(), ) event_payload = { "token": "verification-token", "team_id": "T111", "enterprise_id": "E111", "api_app_id": "A111", "event": { "client_msg_id": "0186b75a-2ad4-4f36-8ccc-18608b0ac5d1", "type": "message", "text": "<@W222>", "user": "******", "ts": "1606810819.000800", "team": "T111", "channel": "C111", "event_ts": "1606810819.000800", "channel_type": "channel", }, "type": "event_callback", "event_id": "Ev111", "event_time": 1606810819, "authed_users": [], "authorizations": [ { "enterprise_id": "E111", "team_id": None, "user_id": "W222", "is_bot": True, "is_enterprise_install": True, } ], "is_ext_shared_channel": False, "event_context": "1-message-T111-C111", } result = Result() @app.event("message") def handle_app_mention(body): assert body == event_payload result.called = True timestamp, body = str(int(time())), json.dumps(event_payload) request: BoltRequest = BoltRequest( body=body, headers=self.build_headers(timestamp, body) ) response = app.dispatch(request) assert response.status == 200 # auth.test API call must be skipped assert_auth_test_count(self, 1) sleep(1) # wait a bit after auto ack() assert result.called is True
def main(event, context): # Using SLACK_BOT_TOKEN environment variable app = App() slack_api_id = os.environ['SLACK_API_ID'].replace('-', '_') env_prefix = os.environ['ENV_PREFIX'] base_url = os.environ['{}_SLACK_CONNECTOR_{}_GATEWAY_URL'.format( env_prefix, slack_api_id)] # Set Slack API base URL to the URL of slack-connector application gateway. app.client.base_url = "{}/".format(base_url) print("received message with id: {}".format(event["data"]["ID"])) print("Slack api base URL: {}".format(app.client.base_url)) print("sending notification to channel: {}".format( os.environ['NOTIFICATION_SLACK_CHANNEL'])) # Get cloud events data. msg = json.loads(base64.b64decode(event["data"]["Data"])) try: # Deliver message to the channel. result = app.client.chat_postMessage( channel=os.environ['NOTIFICATION_SLACK_CHANNEL'], text="oom found in <{}|{}> prowjob.".format( msg["url"], msg["job_name"]), username="******", icon_url= "https://www.stickpng.com/img/download/580b57fbd9996e24bc43bdf6", blocks=[{ "type": "context", "elements": [{ "type": "mrkdwn", "text": "OutOfMemory event" }] }, { "type": "header", "text": { "type": "plain_text", "text": "OOM event found" } }, { "type": "section", "text": { "type": "mrkdwn", "text": "@here, OutOfMemory event found in <{}|{}> prowjob.". format(msg["url"], msg["job_name"]) } }]) assert result["ok"] print("sent notification for message id: {}".format( event["data"]["ID"])) except SlackApiError as e: assert result["ok"] is False print(f"Got an error: {e.response['error']}") print("failed sent notification for message id: {}".format( event["data"]["ID"]))
def test_stable_auto_ack(self): app = App(client=self.web_client) @app.event("reaction_added") def handle_app_mention(): raise Exception("Something wrong!") for _ in range(10): request: BoltRequest = BoltRequest( body=self.valid_reaction_added_body, mode="socket_mode") response = app.dispatch(request) assert response.status == 200
def create_app(): app = App(token=os.environ.get("SLACK_BOT_TOKEN"), signing_secret=os.environ.get("SLACK_SIGNING_SECRET")) actions.set_routes(app) commands.set_routes(app) events.set_routes(app) messages.set_routes(app) shortcuts.set_routes(app) views.set_routes(app) return app
def test_no_installation_store(self): self.web_client.token = valid_token app = App( client=self.web_client, signing_secret=self.signing_secret, ) with pytest.raises(BoltError): app.default_tokens_revoked_event_listener() with pytest.raises(BoltError): app.default_app_uninstalled_event_listener() with pytest.raises(BoltError): app.enable_token_revocation_listeners()
def test_self_events(self): app = App( client=self.web_client, signing_secret=self.signing_secret, authorize=authorize, ) event_body = { "token": "verification_token", "team_id": "T_SOURCE", "enterprise_id": "E_SOURCE", "api_app_id": "A111", "event": { "type": "reaction_added", "user": "******", # bot_user_id "item": { "type": "message", "channel": "C111", "ts": "1599529504.000400", }, "reaction": "heart_eyes", "item_user": "******", "event_ts": "1599616881.000800", }, "type": "event_callback", "event_id": "Ev111", "event_time": 1599616881, "authorizations": [ { "enterprise_id": "E_INSTALLED", "team_id": "T_INSTALLED", "user_id": "W111", "is_bot": True, "is_enterprise_install": False, } ], } @app.event("reaction_added") def handle_app_mention(say): say("What's up?") timestamp, body = str(int(time())), json.dumps(event_body) request: BoltRequest = BoltRequest( body=body, headers=self.build_headers(timestamp, body) ) response = app.dispatch(request) assert response.status == 200 assert_auth_test_count(self, 1) sleep(1) # wait a bit after auto ack() # The listener should not be executed assert self.mock_received_requests.get("/chat.postMessage") is None
def test_installation_store_bot_only_oauth_flow(self): app = App( client=self.web_client, signing_secret=self.signing_secret, oauth_flow=OAuthFlow(settings=self.oauth_settings_bot_only), ) app.event("app_mention")(self.handle_app_mention) response = app.dispatch(self.build_app_mention_request()) assert response.status == 200 assert_auth_test_count(self, 1) sleep(1) # wait a bit after auto ack() assert self.mock_received_requests["/chat.postMessage"] == 1
def build_process_before_response_app(self, callback_id: str): app = App( client=self.web_client, signing_secret=self.signing_secret, process_before_response=True, ) app.step( callback_id=callback_id, edit=[edit_ack, edit_lazy], save=[save_ack, save_lazy], execute=[execute_ack, execute_lazy], ) return app
def test_installation_store_bot_only_default(self): app = App( client=self.web_client, signing_secret=self.signing_secret, installation_store=MemoryInstallationStore(), ) app.event("app_mention")(self.handle_app_mention) response = app.dispatch(self.build_app_mention_request()) assert response.status == 200 assert self.mock_received_requests["/auth.test"] == 1 sleep(1) # wait a bit after auto ack() assert self.mock_received_requests["/chat.postMessage"] == 1
def test_self_events(self): app = App(client=self.web_client) @app.event("reaction_added") def handle_app_mention(say): say("What's up?") request: BoltRequest = BoltRequest(body=event_body, mode="socket_mode") response = app.dispatch(request) assert response.status == 200 assert_auth_test_count(self, 1) sleep(1) # wait a bit after auto ack() # The listener should not be executed assert self.mock_received_requests.get("/chat.postMessage") is None
def test_none_body(self): app = App(signing_secret="valid", client=self.web_client) req = BoltRequest(body=None, headers={}, mode="http") response = app.dispatch(req) # request verification failure assert response.status == 401 assert response.body == '{"error": "invalid request"}' req = BoltRequest(body=None, headers={}, mode="socket_mode") response = app.dispatch(req) # request verification is skipped for Socket Mode assert response.status == 404 assert response.body == '{"error": "unhandled request"}'
def test_default(self): app = App(client=self.web_client, signing_secret=self.signing_secret) timestamp, body = str(int(time())), json.dumps(event_body) request: BoltRequest = BoltRequest(body=body, headers=self.build_headers( timestamp, body)) response = app.dispatch(request) assert response.status == 200 assert ( response.body == """{"challenge": "3eZbrw1aBm2rZgRNFdxV2595E9CY3gmdALWMmHkvFXO7tYXAYM8P"}""" ) assert_auth_test_count(self, 0)
def test_disabled(self): app = App( client=self.web_client, signing_secret=self.signing_secret, url_verification_enabled=False, ) timestamp, body = str(int(time())), json.dumps(event_body) request: BoltRequest = BoltRequest(body=body, headers=self.build_headers( timestamp, body)) response = app.dispatch(request) assert response.status == 404 assert response.body == """{"error": "unhandled request"}""" assert_auth_test_count(self, 0)
def test_message_subtypes_3(self): app = App(client=self.web_client, signing_secret=self.signing_secret) app._client = WebClient(token="uninstalled-revoked", base_url=self.mock_api_server_base_url) @app.event("message") def handler1(event): assert event["subtype"] == "file_share" timestamp, body = str(int(time())), json.dumps( self.message_file_share_body) request: BoltRequest = BoltRequest(body=body, headers=self.build_headers( timestamp, body)) response = app.dispatch(request) assert response.status == 200
def test_default(self): app = App(client=self.web_client, signing_secret=self.signing_secret) @app.event("reaction_added") def handle_app_mention(say): say("What's up?") timestamp, body = str(int(time())), json.dumps(event_body) request: BoltRequest = BoltRequest(body=body, headers=self.build_headers( timestamp, body)) response = app.dispatch(request) assert response.status == 200 assert_auth_test_count(self, 1) sleep(1) # wait a bit after auto ack() assert self.mock_received_requests.get("/chat.postMessage") == 1
def test_ssl_check(self): app = App(client=self.web_client, signing_secret=self.signing_secret) timestamp, body = str(int(time())), "token=random&ssl_check=1" request: BoltRequest = BoltRequest( body=body, query={}, headers={ "content-type": ["application/x-www-form-urlencoded"], "x-slack-signature": [self.generate_signature(body, timestamp)], "x-slack-request-timestamp": [timestamp], }, ) response = app.dispatch(request) assert response.status == 200 assert response.body == ""