Skip to content

Conversation

@devSuryansh
Copy link
Contributor

@devSuryansh devSuryansh commented Nov 10, 2025

Summary

Implements a new Slack slash command /apps that lists all apps installed in the workspace, addressing issue #3344.

Changes Made

  • Added /apps command handler in slack_handlers.py
  • Updated help command to include the new /apps option
  • Implemented comprehensive error handling for API permission issues
  • Added test coverage for both successful responses and error scenarios
  • Provides helpful fallback guidance when admin API access is unavailable

Implementation Details

  • Uses Slack's admin.apps.list API to retrieve workspace apps
  • Sends results via direct message to keep workspace clean
  • Gracefully handles missing_scope and other API errors
  • Maintains consistent error messaging and logging patterns

Testing

  • Added test_slack_command_apps with mock API responses
  • Tests both successful app listing and permission error scenarios
  • All existing Slack command tests continue to pass

Usage

Users can now run /apps in any Slack channel where the bot is installed to receive a DM with a list of all workspace apps.

Fixes #3344

Summary by CodeRabbit

  • New Features
    • Introduced /apps command to display admin-approved applications available in your workspace with detailed app information
  • Documentation & Improvements
    • Updated help text to document the new /apps command in Basic Commands section
    • Refined /report command data handling for improved accuracy

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 10, 2025

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Walkthrough

A new /apps Slack command is implemented to display installed apps in a workspace. The handler fetches admin-approved apps via Slack API with fallback messaging for permission errors, records activity logs, and extends help documentation. Corresponding test coverage validates the command flow, mocking, and response assertions.

Changes

Cohort / File(s) Summary
New /apps command handler
website/views/slack_handlers.py
Added command handler for "/apps" that constructs workspace-specific DM, fetches admin-approved apps from Slack API (up to 20), displays per-app details, and falls back to guidance text on permission errors or API failures. Logs activity with command details.
Extended help documentation
website/views/slack_handlers.py
Updated "/help" command to include "/apps" in the Basic Commands list.
Text extraction adjustment
website/views/slack_handlers.py
Minor initialization of local text variable in "/report" command branch.
Test coverage for /apps command
website/tests/test_slack.py
New test test_slack_command_apps validates command flow with mocked Slack WebClient, simulates permission error from admin API, and asserts team_info calls, DM creation, message posting, HTTP 200 response with "apps" in text, and SlackBotActivity record creation.

Sequence Diagram

sequenceDiagram
    actor User
    participant SlackHandler as /apps Handler
    participant SlackAPI as Slack API
    participant DB as Database
    participant Slack as Slack Workspace

    User->>SlackHandler: /apps command
    SlackHandler->>SlackAPI: team_info()
    SlackAPI-->>SlackHandler: team data
    SlackHandler->>SlackAPI: admin.apps.list()
    alt Admin permissions available
        SlackAPI-->>SlackHandler: apps list
        SlackHandler->>SlackHandler: format app details (up to 20)
        rect rgb(200, 220, 255)
            Note over SlackHandler: Build DM with app details
        end
    else Permission error or API failure
        SlackAPI-->>SlackHandler: error
        rect rgb(255, 220, 200)
            Note over SlackHandler: Fall back to guidance text
        end
    end
    SlackHandler->>Slack: open DM & post message
    Slack-->>SlackHandler: message sent
    SlackHandler->>DB: record SlackBotActivity
    DB-->>SlackHandler: activity logged
    SlackHandler-->>User: HTTP 200 response
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • API integration: Verify correct Slack API calls (team_info, admin.apps.list) and error handling paths
  • Data formatting: Confirm app details extraction and 20-app limit enforcement
  • Activity logging: Ensure SlackBotActivity record is correctly created with command metadata
  • Test coverage: Validate mocking strategy, assertion coverage, and permission error simulation
  • Help text consistency: Verify documentation updates are complete and accurate

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically describes the main change: adding a new Slack /apps command to list installed workspace apps, making it immediately clear to reviewers scanning history.
Linked Issues check ✅ Passed The pull request fully implements the objectives from issue #3344: adds the /apps Slack slash command and lists all apps installed in the workspace via Slack's admin.apps.list API.
Out of Scope Changes check ✅ Passed All changes are directly related to implementing the /apps command. The minor text extraction adjustment in /report and help text updates are supporting changes within scope.

Tip

📝 Customizable high-level summaries are now available!

You can now customize how CodeRabbit generates the high-level summary in your pull requests — including its content, structure, tone, and formatting.

  • Provide custom instructions to shape the summary (bullet lists, tables, contributor stats, etc.).
  • Use high_level_summary_in_walkthrough to move the summary from the description to the walkthrough section.

Example:

"Create a concise high-level summary as a bullet-point list. Then include a Markdown table showing lines added and removed by each contributing author."


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Comment on lines +874 to +877
{
"response_type": "ephemeral",
"text": f"Sorry, there was an error retrieving the apps list: {str(e)}",
}

Check warning

Code scanning / CodeQL

Information exposure through an exception Medium

Stack trace information
flows to this location and may be exposed to an external user.
@devSuryansh devSuryansh marked this pull request as ready for review November 10, 2025 18:51
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (1)
website/views/slack_handlers.py (1)

869-878: Critical: Information exposure through exception message.

The exception message at line 876 includes str(e), which can expose stack traces and internal implementation details to users. This is a security concern flagged by CodeQL and was previously identified.

Apply this diff to prevent information leakage:

             except Exception as e:
                 activity.success = False
                 activity.error_message = str(e)
                 activity.save()
                 return JsonResponse(
                     {
                         "response_type": "ephemeral",
-                        "text": f"Sorry, there was an error retrieving the apps list: {str(e)}",
+                        "text": "Sorry, there was an error retrieving the apps list. Please try again later.",
                     }
                 )
🧹 Nitpick comments (2)
website/views/slack_handlers.py (1)

869-869: Narrow the exception handling scope.

Catching broad Exception can mask unexpected errors and make debugging difficult. Consider catching specific exceptions or logging unexpected errors for monitoring.

Apply this diff to improve exception specificity:

-            except Exception as e:
+            except (SlackApiError, KeyError, ValueError) as e:
                 activity.success = False
                 activity.error_message = str(e)
                 activity.save()
                 return JsonResponse(
                     {
                         "response_type": "ephemeral",
                         "text": "Sorry, there was an error retrieving the apps list. Please try again later.",
                     }
                 )

Note: If other unexpected exceptions occur, they will now propagate to Django's error handling middleware where they can be properly logged.

website/tests/test_slack.py (1)

133-183: Comprehensive test with good error scenario coverage.

The test effectively validates the /apps command flow including permission error handling. The mock setup correctly simulates a missing_scope error from the admin API, which is the most likely failure case.

One minor improvement: the unused mock_verify parameter (line 135) could be prefixed with an underscore to explicitly indicate it's intentionally unused.

Apply this diff to follow Python conventions for unused parameters:

     @patch("website.views.slack_handlers.verify_slack_signature", return_value=True)
     @patch("website.views.slack_handlers.WebClient")
-    def test_slack_command_apps(self, mock_webclient, mock_verify):
+    def test_slack_command_apps(self, mock_webclient, _mock_verify):
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Knowledge base: Disabled due to Reviews -> Disable Knowledge Base setting

📥 Commits

Reviewing files that changed from the base of the PR and between 0668a4a and 6e12b04.

📒 Files selected for processing (2)
  • website/tests/test_slack.py (1 hunks)
  • website/views/slack_handlers.py (2 hunks)
🧰 Additional context used
🪛 GitHub Check: CodeQL
website/views/slack_handlers.py

[warning] 874-877: Information exposure through an exception
Stack trace information flows to this location and may be exposed to an external user.

🪛 Ruff (0.14.3)
website/tests/test_slack.py

135-135: Unused method argument: mock_verify

(ARG002)

website/views/slack_handlers.py

820-820: Local variable api_error is assigned to but never used

Remove assignment to unused variable api_error

(F841)


869-869: Do not catch blind exception: Exception

(BLE001)


876-876: Use explicit conversion flag

Replace with conversion flag

(RUF010)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Run Tests
🔇 Additional comments (2)
website/views/slack_handlers.py (2)

724-724: LGTM! Help command properly updated.

The /apps command has been correctly added to the Basic Commands list in the help message.


881-881: LGTM! Minor refactor improves readability.

Extracting the text variable before the conditional check is a good practice that improves code clarity.

Comment on lines +746 to +819
elif command == "/apps":
try:
# Get basic workspace info
team_info = workspace_client.team_info()
team_name = team_info.get("team", {}).get("name", "Unknown Workspace")

# Create the message blocks
apps_blocks = [
{
"type": "header",
"text": {"type": "plain_text", "text": f"📱 Apps in {team_name}", "emoji": True},
},
{"type": "divider"},
]

# Try to get app list using admin API (requires elevated permissions)
try:
apps_response = workspace_client.api_call("admin.apps.approved.list", params={"limit": 100})

if apps_response.get("ok") and apps_response.get("approved_apps"):
apps = apps_response["approved_apps"]

apps_blocks.append(
{
"type": "section",
"text": {"type": "mrkdwn", "text": f"*Total Apps Installed:* {len(apps)}"},
}
)

# List each app (limit to first 20 to avoid message size limits)
for app in apps[:20]:
app_info = app.get("app", {})
app_name = app_info.get("name", "Unknown App")
app_id = app_info.get("id", "N/A")

apps_blocks.append(
{"type": "section", "text": {"type": "mrkdwn", "text": f"• *{app_name}* (`{app_id}`)"}}
)

if len(apps) > 20:
apps_blocks.append(
{
"type": "context",
"elements": [{"type": "mrkdwn", "text": f"_Showing 20 of {len(apps)} apps_"}],
}
)
else:
# Fallback: Show guidance when admin permissions aren't available
apps_blocks.extend(
[
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "⚠️ *Limited Access*\n\n"
"This bot doesn't have admin permissions to list all workspace apps.",
},
},
{"type": "divider"},
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "*Alternative ways to view installed apps:*\n\n"
"1️⃣ Click on your workspace name (top left)\n"
"2️⃣ Select *Settings & administration*\n"
"3️⃣ Choose *Manage apps*\n"
"4️⃣ You'll see all installed and available apps\n\n"
"Or visit: https://slack.com/apps/manage",
},
},
]
)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Remove unused variable and verify API endpoint compatibility.

The /apps command implementation looks solid overall with good error handling structure. However, the api_error variable at line 820 is assigned but never used.

Note: The admin.apps.approved.list API requires the admin.apps:read OAuth scope. Ensure workspace admins are informed about this requirement.

Apply this diff to remove the unused variable:

-                except SlackApiError as api_error:
+                except SlackApiError:
                     # If admin API not available, provide helpful information

Run the following script to verify the admin API endpoint usage across the codebase:


🏁 Script executed:

#!/bin/bash
# Search for other admin API calls to ensure consistency
rg -n "admin\.apps" --type=py -C3

Length of output: 622


I need to examine the exception handler around line 820 and verify if the api_error variable is truly unused.


🏁 Script executed:

#!/bin/bash
# Extract lines 815-830 to see the complete exception handler
sed -n '815,830p' website/views/slack_handlers.py

Length of output: 720


🏁 Script executed:

#!/bin/bash
# Search for any usage of api_error variable after line 760 in the file
rg -n "api_error" website/views/slack_handlers.py -A5 -B5

Length of output: 450


I need to verify the OAuth scope requirement mentioned in the review comment.


🌐 Web query:

Slack admin.apps.approved.list API OAuth scope requirement

💡 Result:

The admin.apps.approved.list method requires the admin.apps:read (an admin.*) OAuth scope. The scope must be granted via an OAuth install performed by an Enterprise Grid admin/owner on the entire org (not an individual workspace). [1][2]

Sources:
[1] Slack API method docs — admin.apps.approved.list.
[2] Slack scope docs — admin.apps:read.


Remove the unused api_error variable at line 820.

The admin.apps.approved.list method requires the admin.apps:read OAuth scope, which your comment already documents. The verification confirms this endpoint is used only once in the codebase at line 763, so the implementation is consistent.

Apply this diff:

-                except SlackApiError as api_error:
+                except SlackApiError:
                     # If admin API not available, provide helpful information

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In website/views/slack_handlers.py around lines 746-819 (and the unused
declaration at line ~820), there's an unused variable api_error left after the
admin.apps.approved.list call; remove the api_error variable declaration and any
references to it so the code no longer defines or uses that unused variable,
then run lint/tests to ensure no remaining references.

@github-project-automation github-project-automation bot moved this from Backlog to Ready in 📌 OWASP BLT Project Board Nov 10, 2025
@github-actions github-actions bot added unresolved-conversations: 2 PR has 2 unresolved conversations files-changed: 2 PR changes 2 files labels Nov 16, 2025
Copy link
Collaborator

@DonnieBLT DonnieBLT left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

one tweak - see the conversations

@DonnieBLT DonnieBLT added the d15 label Nov 16, 2025
@devSuryansh devSuryansh marked this pull request as draft November 16, 2025 10:05
…P-BLT#3344)

Implements a new Slack slash command that lists all apps installed in the workspace using the admin.apps.list API. The command includes error handling for permission issues and provides helpful guidance when API access is unavailable. Includes comprehensive test coverage for both success and error scenarios.
@devSuryansh devSuryansh force-pushed the feat/slack-apps-command branch from 41f4e58 to 19917c4 Compare November 16, 2025 10:05
@github-actions
Copy link
Contributor

👋 Hi @devSuryansh!

This pull request needs a peer review before it can be merged. Please request a review from a team member who is not:

  • The PR author
  • DonnieBLT
  • coderabbit
  • copilot

Once a valid peer review is submitted, this check will pass automatically. Thank you!

@devSuryansh devSuryansh deleted the feat/slack-apps-command branch November 16, 2025 10:21
@devSuryansh
Copy link
Contributor Author

one tweak - see the conversations

@DonnieBLT I've reviewed the changes requested and made all the changes. You can check out my new PR #4842.
Thanks :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

files-changed: 2 PR changes 2 files unresolved-conversations: 2 PR has 2 unresolved conversations

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

add an /apps slack command to list all apps installed in slack

2 participants