Skip to content

Commit

Permalink
Authenticate with OAuth (allowing for multiple teams/workspaces) πŸ‘ͺπŸ‘©β€πŸ‘©β€¦
Browse files Browse the repository at this point in the history
β€¦πŸ‘¨β€πŸ‘©β€πŸ‘§β€πŸ‘§
  • Loading branch information
connorads committed Jun 9, 2020
1 parent b5322c3 commit 4af3c9e
Show file tree
Hide file tree
Showing 7 changed files with 123 additions and 47 deletions.
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"author": "Connor Adams",
"license": "MIT",
"scripts": {
"lint": "yarn tsc --noEmit && eslint . src/** test/**",
"lint": "yarn tsc --noEmit && eslint . src/*.ts src/storage/*.ts test/*.ts",
"db:install": "serverless plugin install --name serverless-dynamodb-local && serverless dynamodb install",
"db:start": "serverless dynamodb start",
"test": "jest",
Expand Down Expand Up @@ -36,7 +36,7 @@
"webpack-cli": "^3.3.11"
},
"dependencies": {
"@slack/bolt": "^2.0.1",
"@slack/bolt": "^2.1.1",
"@types/aws-serverless-express": "^3.3.3",
"aws-lambda": "^1.0.6",
"aws-sdk": "^2.673.0",
Expand Down
30 changes: 27 additions & 3 deletions serverless.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,11 @@ provider:
runtime: nodejs12.x
environment:
SLACK_SIGNING_SECRET: ${env:SLACK_SIGNING_SECRET}
SLACK_BOT_TOKEN: ${env:SLACK_BOT_TOKEN}
SLACK_CLIENT_ID: ${env:SLACK_CLIENT_ID}
SLACK_CLIENT_SECRET: ${env:SLACK_CLIENT_SECRET}
STATE_SECRET: ${env:STATE_SECRET}
RESOURCES_TABLE_NAME: ${self:custom.resourcesTableName}
INSTALLATIONS_TABLE_NAME: ${self:custom.installationsTableName}
iamRoleStatements:
- Effect: Allow
Action:
Expand All @@ -23,14 +26,21 @@ provider:
- dynamodb:DeleteItem
Resource:
- "Fn::GetAtt": [resourcesTable, Arn]
- "Fn::GetAtt": [installationsTable, Arn]

functions:
slack-events-handler:
handler: src/index.handler
slack-handler:
handler: src/slack.handler
events:
- http:
method: post
path: /slack/events
- http:
method: get
path: /slack/install
- http:
method: get
path: /slack/oauth_redirect

resources:
Resources:
Expand All @@ -51,10 +61,24 @@ resources:
ProvisionedThroughput:
ReadCapacityUnits: 5
WriteCapacityUnits: 5
installationsTable:
Type: AWS::DynamoDB::Table
Properties:
TableName: ${self:custom.installationsTableName}
AttributeDefinitions:
- AttributeName: Team
AttributeType: S
KeySchema:
- AttributeName: Team
KeyType: HASH
ProvisionedThroughput:
ReadCapacityUnits: 5
WriteCapacityUnits: 5

custom:
stage: ${opt:stage, self:provider.stage}
resourcesTableName: ${self:custom.stage}-lockbot-resources
installationsTableName: ${self:custom.stage}-lockbot-installations
dynamodb:
stages:
- dev # https://bit.ly/35WR0TT
40 changes: 36 additions & 4 deletions src/index.ts β†’ src/slack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,48 @@ import { APIGatewayProxyEvent, Context } from "aws-lambda";
import * as awsServerlessExpress from "aws-serverless-express";
import * as env from "env-var";
import LockBot, { Response, Destination } from "./lock-bot";
import DynamoDBLockRepo from "./dynamodb-lock-repo";
import DynamoDBLockRepo from "./storage/dynamodb-lock-repo";

const documentClient = new DocumentClient();

const installationsTableName = env
.get("INSTALLATIONS_TABLE_NAME")
.required()
.asString();

const expressReceiver = new ExpressReceiver({
signingSecret: env.get("SLACK_SIGNING_SECRET").required().asString(),
clientId: env.get("SLACK_CLIENT_ID").required().asString(),
clientSecret: env.get("SLACK_CLIENT_SECRET").required().asString(),
stateSecret: env.get("STATE_SECRET").required().asString(),
scopes: ["commands"],
processBeforeResponse: true,
installationStore: {
storeInstallation: async (installation) => {
await documentClient
.put({
TableName: installationsTableName,
Item: {
Team: installation.team.id,
Installation: installation,
},
})
.promise();
},
fetchInstallation: async (installQuery) => {
const result = await documentClient
.get({
TableName: installationsTableName,
Key: { Team: installQuery.teamId },
})
.promise();
return Promise.resolve(result.Item?.Installation);
},
},
});

const app = new App({
token: env.get("SLACK_BOT_TOKEN").required().asString(),
receiver: expressReceiver,
processBeforeResponse: true,
});

const getResponseType = (destination: Destination) => {
Expand Down Expand Up @@ -76,7 +108,7 @@ const handle = (getResponse: (command: SlashCommand) => Promise<Response>) => {

const lockBot = new LockBot(
new DynamoDBLockRepo(
new DocumentClient(),
documentClient,
env.get("RESOURCES_TABLE_NAME").required().asString()
)
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { DocumentClient } from "aws-sdk/clients/dynamodb";
import { LockRepo } from "./lock-bot";
import { LockRepo } from "../lock-bot";

export default class DynamoDBLockRepo implements LockRepo {
constructor(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { LockRepo } from "./lock-bot";
import { LockRepo } from "../lock-bot";

export default class InMemoryLockRepo implements LockRepo {
private readonly lockMap: Map<string, string> = new Map();
Expand Down
4 changes: 2 additions & 2 deletions test/test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import DynamoDB, { DocumentClient } from "aws-sdk/clients/dynamodb";
import LockBot, { Response } from "../src/lock-bot";
import InMemoryLockRepo from "../src/in-memory-lock-repo";
import DynamoDBLockRepo from "../src/dynamodb-lock-repo";
import InMemoryLockRepo from "../src/storage/in-memory-lock-repo";
import DynamoDBLockRepo from "../src/storage/dynamodb-lock-repo";

let lockBot: LockBot;
const runAllTests = () => {
Expand Down
88 changes: 54 additions & 34 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -973,14 +973,15 @@
dependencies:
type-detect "4.0.8"

"@slack/bolt@^2.0.1":
version "2.0.1"
resolved "https://registry.yarnpkg.com/@slack/bolt/-/bolt-2.0.1.tgz#f19ac1102964b0dd04f8aa480af266e8bd3b20f3"
integrity sha512-EOhsVTcgw/VGloblGBUMyt+ll1lTA2o0ZO9u5BKM00X+C6HHmg7S1ZAco61KFmvTZELuWInWEX1ye4fDGarfXg==
"@slack/bolt@^2.1.1":
version "2.1.1"
resolved "https://registry.yarnpkg.com/@slack/bolt/-/bolt-2.1.1.tgz#310e14d989e35916aeae9d5a1bea1162df564b50"
integrity sha512-6Bpv1jiQx9XcbeYfGhldJghA2EzxnforvQ8nlDLLg276oLh2qIEJ2mx2GemOTjTv0bQsX1J9cFp480D8jhlk5g==
dependencies:
"@slack/logger" "^2.0.0"
"@slack/types" "^1.5.0"
"@slack/web-api" "^5.8.0"
"@slack/oauth" "^1.1.0"
"@slack/types" "^1.6.0"
"@slack/web-api" "^5.9.0"
"@types/express" "^4.16.1"
"@types/node" ">=10"
"@types/promise.allsettled" "^1.0.3"
Expand All @@ -998,15 +999,27 @@
dependencies:
"@types/node" ">=8.9.0"

"@slack/types@^1.2.1", "@slack/types@^1.5.0":
"@slack/oauth@^1.1.0":
version "1.1.0"
resolved "https://registry.yarnpkg.com/@slack/oauth/-/oauth-1.1.0.tgz#68967f3ae92941132bad773e263976ebd6d9fad5"
integrity sha512-v4yawvn9DCmWO0HXXnWxjmwVikLkoZKjCU042o6UES5u0FroYX8ozs+xWbueO8lb7YYqSKPsIX6A6nlbR4pUyA==
dependencies:
"@slack/logger" "^2.0.0"
"@slack/web-api" "^5.7.0"
"@types/jsonwebtoken" "^8.3.7"
"@types/node" ">=6.0.0"
jsonwebtoken "^8.5.1"
lodash.isstring "^4.0.1"

"@slack/types@^1.2.1", "@slack/types@^1.6.0":
version "1.6.0"
resolved "https://registry.yarnpkg.com/@slack/types/-/types-1.6.0.tgz#7b5f08db824d9853cbf6c2de1c08865ba6ce346f"
integrity sha512-SrrAD/ZxDN4szQ35V/mY2TvKSyGsUWP8def1C8NMg9AvdYG0VyaL5f+Dd6jw8STosMFXd3zqjekMowT9LB9/IQ==

"@slack/web-api@^5.8.0":
version "5.8.1"
resolved "https://registry.yarnpkg.com/@slack/web-api/-/web-api-5.8.1.tgz#90daba7ee2fb5a928a5d34c57fff0cf9ba5ada8c"
integrity sha512-MONzkjWOXV39Dejo8B9WSl/F0dxcVh9wyeW6R0jf6T6BhwN4f24iErYtTh19g+MRhb0oiyeKfnFsJTSKQulfDA==
"@slack/web-api@^5.7.0", "@slack/web-api@^5.9.0":
version "5.9.0"
resolved "https://registry.yarnpkg.com/@slack/web-api/-/web-api-5.9.0.tgz#13ce1eecc405c3972e6037d54338344d7859a3b5"
integrity sha512-gIRvuA9wGtp4S/Zc+zfT59IaGHYzNxjob2QxoJlc3JZ3BLuPMa6Lw81YBV0xutJvUVFPX2ytW27KAUakvi5ZMA==
dependencies:
"@slack/logger" ">=1.0.0 <3.0.0"
"@slack/types" "^1.2.1"
Expand Down Expand Up @@ -1115,9 +1128,9 @@
integrity sha512-EaObqwIvayI5a8dCzhFrjKzVwKLxjoG9T6Ppd5CEo07LRKfQ8Yokw54r5+Wq7FaBQ+yXRvQAYPrHwya1/UFt9g==

"@types/express-serve-static-core@*":
version "4.17.6"
resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.17.6.tgz#ec825455acb075e7fc804f4f7b7734e043003f43"
integrity sha512-U2oynuRIB17GIbEdvjFrrEACOy7GQkzsX7bPEBz1H41vZYEU4j0fLL97sawmHDwHUXpUQDBMHIyM9vejqP9o1A==
version "4.17.7"
resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.17.7.tgz#dfe61f870eb549dc6d7e12050901847c7d7e915b"
integrity sha512-EMgTj/DF9qpgLXyc+Btimg+XoH7A2liE8uKul8qSmMTHCeNYzydDKFdsJskDvw42UsesCnhO63dO0Grbj8J4Dw==
dependencies:
"@types/node" "*"
"@types/qs" "*"
Expand Down Expand Up @@ -1187,25 +1200,32 @@
resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee"
integrity sha1-7ihweulOEdK4J7y+UnC86n8+ce4=

"@types/jsonwebtoken@^8.3.7":
version "8.5.0"
resolved "https://registry.yarnpkg.com/@types/jsonwebtoken/-/jsonwebtoken-8.5.0.tgz#2531d5e300803aa63279b232c014acf780c981c5"
integrity sha512-9bVao7LvyorRGZCw0VmH/dr7Og+NdjYSsKAxB43OQoComFbBgsEpoR9JW6+qSq/ogwVBg8GI2MfAlk4SYI4OLg==
dependencies:
"@types/node" "*"

"@types/lodash@^4.14.123":
version "4.14.150"
resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.150.tgz#649fe44684c3f1fcb6164d943c5a61977e8cf0bd"
integrity sha512-kMNLM5JBcasgYscD9x/Gvr6lTAv2NVgsKtet/hm93qMyf/D1pt+7jeEZklKJKxMVmXjxbRVQQGfqDSfipYCO6w==

"@types/mime@*":
version "2.0.1"
resolved "https://registry.yarnpkg.com/@types/mime/-/mime-2.0.1.tgz#dc488842312a7f075149312905b5e3c0b054c79d"
integrity sha512-FwI9gX75FgVBJ7ywgnq/P7tw+/o1GUbtP0KzbtusLigAOgIgNISRK0ZPl4qertvXSIE8YbsVJueQ90cDt9YYyw==
version "2.0.2"
resolved "https://registry.yarnpkg.com/@types/mime/-/mime-2.0.2.tgz#857a118d8634c84bba7ae14088e4508490cd5da5"
integrity sha512-4kPlzbljFcsttWEq6aBW0OZe6BDajAmyvr2xknBG92tejQnvdGtT9+kXSZ580DqpxY9qG2xeQVF9Dq0ymUTo5Q==

"@types/minimatch@*":
version "3.0.3"
resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d"
integrity sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==

"@types/node@*", "@types/node@>=10", "@types/node@>=8.9.0":
version "13.13.5"
resolved "https://registry.yarnpkg.com/@types/node/-/node-13.13.5.tgz#96ec3b0afafd64a4ccea9107b75bf8489f0e5765"
integrity sha512-3ySmiBYJPqgjiHA7oEaIo2Rzz0HrOZ7yrNO5HWyaE5q0lQ3BppDZ3N53Miz8bw2I7gh1/zir2MGVZBvpb1zq9g==
"@types/node@*", "@types/node@>=10", "@types/node@>=6.0.0", "@types/node@>=8.9.0":
version "14.0.11"
resolved "https://registry.yarnpkg.com/@types/node/-/node-14.0.11.tgz#61d4886e2424da73b7b25547f59fdcb534c165a3"
integrity sha512-lCvvI24L21ZVeIiyIUHZ5Oflv1hhHQ5E1S25IRlKIXaRkVgmXpJMI3wUJkmym2bTbCe+WoIibQnMVAU3FguaOg==

"@types/normalize-package-data@^2.4.0":
version "2.4.0"
Expand All @@ -1228,9 +1248,9 @@
integrity sha512-b/IFHHTkYkTqu41IH9UtpICwqrpKj2oNlb4KHPzFQDMiz+h1BgAeATeO0/XTph4+UkH9W2U0E4B4j64KWOovag==

"@types/qs@*":
version "6.9.2"
resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.2.tgz#faab98ec4f96ee72c829b7ec0983af4f4d343113"
integrity sha512-a9bDi4Z3zCZf4Lv1X/vwnvbbDYSNz59h3i3KdyuYYN+YrLjSeJD0dnphdULDfySvUv6Exy/O0K6wX/kQpnPQ+A==
version "6.9.3"
resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.3.tgz#b755a0934564a200d3efdf88546ec93c369abd03"
integrity sha512-7s9EQWupR1fTc2pSMtXRQ9w9gLOcrJn+h7HOXw4evxyvVqMi4f+q7d2tnFe3ng3SNHjtK+0EzGMGFUQX4/AQRA==

"@types/range-parser@*":
version "1.2.3"
Expand All @@ -1243,9 +1263,9 @@
integrity sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==

"@types/serve-static@*":
version "1.13.3"
resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.13.3.tgz#eb7e1c41c4468272557e897e9171ded5e2ded9d1"
integrity sha512-oprSwp094zOglVrXdlo/4bAHtKTAxX6VT8FOZlBKrmyLbNvE1zxZyJ6yikMVtHIvwP45+ZQGJn+FdXGKTozq0g==
version "1.13.4"
resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.13.4.tgz#6662a93583e5a6cabca1b23592eb91e12fa80e7c"
integrity sha512-jTDt0o/YbpNwZbQmE/+2e+lfjJEJJR0I3OFaKQKPWkASkCoW3i6fsUnqudSMcNAfbtmADGu8f4MV4q+GqULmug==
dependencies:
"@types/express-serve-static-core" "*"
"@types/mime" "*"
Expand Down Expand Up @@ -5639,9 +5659,9 @@ is-builtin-module@^3.0.0:
builtin-modules "^3.0.0"

is-callable@^1.1.4, is-callable@^1.1.5:
version "1.1.5"
resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.5.tgz#f7e46b596890456db74e7f6e976cb3273d06faab"
integrity sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q==
version "1.2.0"
resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.0.tgz#83336560b54a38e35e3a2df7afd0454d691468bb"
integrity sha512-pyVD9AaGLxtg6srb2Ng6ynWJqkHU9bEM087AKck0w8QwDarTfNcpIYoU8x8Hv2Icm8u6kFJM18Dag8lyqGkviw==

is-ci@^1.0.10:
version "1.2.1"
Expand Down Expand Up @@ -5855,11 +5875,11 @@ is-redirect@^1.0.0:
integrity sha1-HQPd7VO9jbDzDCbk+V02/HyH3CQ=

is-regex@^1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.5.tgz#39d589a358bf18967f726967120b8fc1aed74eae"
integrity sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ==
version "1.1.0"
resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.0.tgz#ece38e389e490df0dc21caea2bd596f987f767ff"
integrity sha512-iI97M8KTWID2la5uYXlkbSDQIg4F6o1sYboZKKTDpnDQMLtUL86zxhgDet3Q2SriaYsyGqZ6Mn2SjbRKeLHdqw==
dependencies:
has "^1.0.3"
has-symbols "^1.0.1"

is-regexp@^1.0.0:
version "1.0.0"
Expand Down

0 comments on commit 4af3c9e

Please sign in to comment.