This repo holds some of our membership automation. It listens to webhooks from the main site and updates slack and google groups membership as well as updating access cards. It also listens to slack commands like /membership which allows us to customize that list based on the slack user that issued it, whether they're a board member, have an active subscription, etc.
Quite a bit of the code runs using event sourcing. The MembershipAggregate is the main entry point for a lot of the functionality as it decides based on subscription updates if someone is a member or not. Various projectors update models in the database and various reactors do things like send emails when needed.
Usually, you don't delete events from the database, but it can be useful to do so in the event of deprecation of events or fixing badly stored events. Sometimes, when that happens, the version numbers for the aggregate get out of wack. Here is a helper command to fix that:
php artisan event-sourcing:fix-aggregate-versionThe webhooks Laravel server can be run locally to test and build new functionality. The easiest way to do this is using Sail, which is a docker compose wrapper built into the Laravel ecosystem.
It's worth noting that by its very nature, the webhooks system depends heavily on external services, and is not particularly useful on its own. Sail will stand up the core dependencies needed to run the Laravel server, but you'll need to either mock or connect other dev services for features you want to test, including the denhac.org Wordpress server (the source of all our user data and APIs), slack (for testing slack commands and notifications), quickbooks and stripe (for financial automations). You don't need to provide these services to get the core server running, but that functionality won't work.
- Have docker, composer, and php installed on your system
cd $ProjectDircomposer install --ignore-platform-reqscp ./.env.sail.example ./.env:
- OR: Update the following values in the
.envfileDB_HOST=mysqlREDIS_HOST=redisMAIL_HOST=mailpit
sail up -dsail artisan key:generatesail artisan migratesail artisan db:seed- Profit
Any externally hosted services (eg, slack) that you want to connect to your locally hosted dev server will need a way to reach your server.
There are many services available these days that let you quickly establish secure tunnels and reverse proxies to expose your development environment to the internet. These include tailscale funnels (free), cloudflare tunnels (free), and ngrok (freemium)
You'll need a slack workspace where you have permission to install and manage apps, and won't disrupt anyone if something goes awry.
You can create a free workspace for yourself, such as dev-denhac-<your-username>
- While signed into a slack account with access to your test workspace, go to api.slack.com/apps and click
Create New App. - Select
From Scratch - Give your app a name such as
Membership Botand select your test workspace. ClickCreate App. - Select the
Slash Commandsfeature. - Enter
/membershipfor the command - Add the webhook url. This will be
<your.ngrok.hostname>/slack/membership. - Complete the slash command setup
- Enable "Interactivity". This is required for the modals to function.
- Under "Features", open the "Interactivity & Shortcuts" tab
- Set the interactivity toggle to on
- Scroll down to "Select Menus" and enter
<your.ngrok.hostname>/slack/optionsin the "Options Load URL". - Failure to complete these steps may result in the
/membershipcommand not loading a modal, or having an empty options list.
- Install the app into your workspace
- In the app dashboard's sidebar, find the
Install Apptab - Click
Install to Workspaceand agree to installation - The bot should now show up under
Appsin your slack workspace
- Configure secrets. In your
<application_root>/.env, add:
SLACK_SPACEBOT_API_TOKEN=the "Bot User OAuth Token" from the "OAuth & Permissions" tab- This token is used to sign requests that we send to slack, such as the ones that create and update the modals.
- Note that the membership command uses the
SPACEBOTvariables, not theMANAGEMENTones.
SLACK_SPACEBOT_API_SIGNING_SECRET=The "Signing Secret" from the "App Credentials" section under the "Basic Information" tab.- This secret is used to verify that requests to the
/slack/*endpoints were in fact sent by slack (and originate from our workspace).
- This secret is used to verify that requests to the
- Test the integration
- Send
\membershipin#generalor some other channel - If you get something like
\membership is not a valid command, the bot was not configured properly in slack, or it was not added to your workspace - If you get `/membership failed with the error "dispatch_failed", you have successfully installed the app, but it's not able to reach your webhook server. Verify that ngrok and the dev server are running, and that the domain name in the app configuration is accurate.
- If you get
I don't recognize you. If you're a member in good standing, please contact access@denhac.org., it's working but your slack user isn't associated with a customer in the database! Assuming you've already run[sail] artisan db:seed, checkstorage/logs/laravel.logfor a recent line likeMembership command invoked by unknown user. Run[sail] artisan dbto get a database shell, and executeUPDATE customers SET slack_id = '<your slack id>' WHERE id = 1;. This will attach your slack ID to a user with permissions to perform all the slack actions.