Skip to content

Commit

Permalink
chore: migrate /siteup
Browse files Browse the repository at this point in the history
  • Loading branch information
seaerchin committed Jun 5, 2024
1 parent 9f616d8 commit f0db8a6
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 90 deletions.
66 changes: 13 additions & 53 deletions support/routes/v2/isobot/index.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
import { App, ExpressReceiver } from "@slack/bolt"
import { RequestHandler } from "express"

import { Whitelist } from "@database/models"
import config from "@root/config/config"
import logger from "@root/logger/logger"
import WhitelistService from "@root/services/identity/WhitelistService"
import type { DnsCheckerResponse } from "@root/types/dnsChecker"

import BotService, { SlackPayload } from "./ops/botService"
import BotService from "./ops/botService"

const botService = new BotService(
new WhitelistService({ repository: Whitelist })
Expand All @@ -23,55 +21,8 @@ const bot = new App({
receiver: botReceiver,
})

const handleWhitelistEmails: RequestHandler<
{},
{ message: string },
SlackPayload,
{},
{}
> = async (req, res) => {
const slackTimestamp = req.headers["x-slack-request-timestamp"] as string
const slackSig = req.headers["x-slack-signature"] as string

if (!slackTimestamp || !slackSig)
return res.send({ message: "Missing header/signature" })

const isVerifiedMessage = botService.verifySignature(
slackSig,
slackTimestamp,
req.body
)
if (!isVerifiedMessage) return res.send({ message: "Invalid signature" })

try {
await botService.whitelistEmails(req.body)
return res.send({ message: "Emails whitelisted successfully" })
} catch (e) {
logger.error({ error: e })
return res.send({ message: "Failed to whitelist emails" })
}
}

const handleDnsChecker: RequestHandler<
never,
DnsCheckerResponse | { message: string },
SlackPayload,
unknown,
never
> = async (req, res) => {
const validatedDomain = botService.getValidatedDomain(req.body)
if (!validatedDomain)
return res.status(200).send({
message: `Sorry, \`${req.body.text}\` is not a valid domain name. Please try again with a valid one instead.`,
})

return botService
.dnsChecker(req.body)
.map((response) => res.status(200).send(response))
}

// TODO: add in validation for user once downstream is merged
bot.command("/siteup", async ({ payload, respond, ack }) => {
bot.command("/whitelist", async ({ payload, respond, ack }) => {
await ack()

try {
Expand All @@ -83,5 +34,14 @@ bot.command("/siteup", async ({ payload, respond, ack }) => {
}
})

// bot.command("/siteup", handleDnsChecker)
// bot.command("/whitelist-emails", handleWhitelistEmails)
bot.command("/siteup", async ({ payload, respond, ack }) => {
await ack()

const validatedDomain = botService.getValidatedDomain(payload.text)
if (!validatedDomain)
return respond(
`Sorry, \`${payload.text}\` is not a valid domain name. Please try again with a valid one instead.`
)

return botService.dnsChecker(payload).map((response) => respond(response))
})
54 changes: 17 additions & 37 deletions support/routes/v2/isobot/ops/botService.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import dns from "node:dns/promises"

import { SlashCommand } from "@slack/bolt"
import { ResultAsync, okAsync } from "neverthrow"

import {
Expand All @@ -12,10 +13,6 @@ import logger from "@root/logger/logger"
import WhitelistService from "@root/services/identity/WhitelistService"
import { DnsCheckerResponse } from "@root/types/dnsChecker"

// Slack only gives us 3 seconds to respond, but usually DNS resolution is fast,
// so we will give it 2 seconds before we give up
const DNS_TIMEOUT = 2000

class BotService {
whitelistService: WhitelistService

Expand All @@ -24,21 +21,13 @@ class BotService {
}

private checkCname(domain: string) {
return ResultAsync.fromPromise(
Promise.race([
dns.resolveCname(domain),
new Promise<null>((_, reject) =>
setTimeout(() => reject(null), DNS_TIMEOUT)
),
]),
() => {
logger.info({
message: "Error resolving CNAME",
meta: { domain, method: "checkCname" },
})
return new Error()
}
)
return ResultAsync.fromPromise(dns.resolveCname(domain), () => {
logger.info({
message: "Error resolving CNAME",
meta: { domain, method: "checkCname" },
})
return new Error()
})
.andThen((cname) => {
if (!cname || cname.length === 0) {
return okAsync(null)
Expand All @@ -50,21 +39,13 @@ class BotService {
}

private checkA(domain: string) {
return ResultAsync.fromPromise(
Promise.race([
dns.resolve4(domain),
new Promise<null>((_, reject) =>
setTimeout(() => reject(null), DNS_TIMEOUT)
),
]),
() => {
logger.info({
message: "Error resolving A record",
meta: { domain, method: "checkA" },
})
return new Error()
}
)
return ResultAsync.fromPromise(dns.resolve4(domain), () => {
logger.info({
message: "Error resolving A record",
meta: { domain, method: "checkA" },
})
return new Error()
})
.andThen((a) => {
if (!a || a.length === 0) {
return okAsync(null)
Expand Down Expand Up @@ -119,8 +100,7 @@ class BotService {
await this.whitelistService.addWhitelist(emails)
}

getValidatedDomain(payload: SlackPayload) {
const { text: domain } = payload
getValidatedDomain(domain: string) {
const DOMAIN_NAME_REGEX = /^[a-zA-Z0-9][a-zA-Z0-9-]{0,61}[a-zA-Z0-9](?:\.[a-zA-Z]{2,})+$/

if (!DOMAIN_NAME_REGEX.test(domain)) {
Expand Down Expand Up @@ -296,7 +276,7 @@ class BotService {
return this.getSlackMessage(response)
}

dnsChecker(payload: SlackPayload) {
dnsChecker(payload: SlashCommand) {
// Step 1: Get the domain name provided by the user
const { user_name: user, channel_name: channel, text: domain } = payload
logger.info({
Expand Down

0 comments on commit f0db8a6

Please sign in to comment.