Skip to content

Developer Notes

Ananyobrata Pal edited this page Sep 18, 2024 · 10 revisions

Development Overview

The Frappe Slack Connector App is built on top of the Frappe framework and integrates with Slack's API via Slack's own Bolt framework.

Key Components

New doctypes and few customisations are made to current doctypes from frappe/hrms to implement the functionality.

1. DocTypes

  • Slack Settings: Stores Slack API credentials and configuration, like time to send attendance updates. Stores the last sent attendance date and the message ts (unique timestamp) in hidden fields to refer it afterwards for late ERP leave submissions for the day.
  • Slack User Meta: Maps and stores Frappe users to Slack user IDs
  • Leave Application: Provides hooks to include Slack-specific behaviour

2. Slack API Integration

  • Uses slack-bolt python library for communication with Slack API
  • Uses OAuth2 flow for Slack workspace authorization
  • Using traditional webhook approach instead of Socket Mode
  • Using bolt kit ui framework to create Slack user interfaces.

3. Background Jobs

  • Daily reminder job: Sends daily notifications about employees on leave. A background job is run in the all scheduler event, since it is hard to precisely get the timing right. Checks if it should run the attendance notification, or just returns otherwise.

API Endpoints

These APIs can be consumed from the Frappe frontend for achieving various related features.

  • /api/method/frappe_slack_connector.api.auth.connect_slack: This endpoint is used to connect a user with Slack
  • /api/method/frappe_slack_connector.api.test_slack_channel.test_channel: A test message is sent using this route to the mentioned channel
  • /api/method/frappe_slack_connector.api.attendance_summary.attendance_channel: Used to trigger daily attendance message setup using scheduler.

Note: for debugging attendance_channel function better use bench execute frappe_slack_connector.api.attendance_summary.send_notification that doesn't check if the attendance notification was already sent earlier.

Webhook Handlers

These webhooks are set to enable Slack to communicate with our Frappe backend.

  • /api/method/frappe_slack_connector.api.slack_interactions.event: Processes incoming Slack events, this is used as an entry-point for all slack related events. Dispatches the correct handler based on action_id or callback_id specified by Slack during invocation.
  • /api/method/frappe_slack_connector.api.slash_leave.slash_leave: Webhook url for /apply-leave command, provides the functionality to create and handle new leave requests.

Configuration

Ensure the following instance variables are set for the app to work correctly:

  • SLACK_BOT_TOKEN: This is the most important parameter, Frappe controls the slack bot using this token provided in slack app dashboard.
  • SLACK_CHANNEL_ID: The channel id is the one where attendance updates are to be sent every working day.
  • SLACK_SIGNATURE: The secret key that is used to digitally sign the requests by slack, this is used to verify that request originated from slack itself.
  • SLACK_APP_TOKEN: Provision has been set for future use, not required now.

Security

The Frappe-Slack Connector app utilizes Slack's signing secret to authenticate incoming requests, ensuring they originate from Slack. This process involves Slack creating a unique signature for each request using the signing secret, which is then included in the request headers along with a timestamp.

When the app receives a request, it recreates the signature using the same method as Slack, combining the request body, timestamp, and the app's stored signing secret. The app then compares this recreated signature with the one provided in the request headers. If they match, it confirms the request's authenticity. This verification process is crucial for maintaining the security of the integration, preventing unauthorized access or tampering with the app's functionality.

It's important to keep the signing secret secure and implement additional safeguards, such as checking the request's timestamp to prevent replay attacks. We implemented a time check to prevent replay attacks (e.g., reject requests older than 5 minutes). And used constant-time comparison (hmac.compare_digest()) to prevent timing attacks.

For more details, read Slack docs

NOTE: Keep your signing secret secure and never expose it publicly.

Debugging

Errors from Frappe are handled and shown in Slack UI. Apart from that, internal errors are logged in Error Log List that you can access from the awesomebar in frappe navbar. (You can invoke it with Cmd + G)
For more indulged debugging, you can use vscode-debugger that comes with our own frappe manager.

Known Issues and Limitations

  • Be mindful of Slack API rate limits, requests may fail if a lot of requests are made concurrently
  • In case Slack is unable to connect with Frappe, due to firewall or other restrictions, things can break with status code 417 Expectation Failed and curl-error/dispatch-failed if it is unable to correctly invoke the method. Make sure the application is hosted and is publicly accessible from Slack.

Future Improvements

  • Add timesheet integration
  • Better slack events routing
  • Better documentation