Skip to content

Commit

Permalink
feat(golinks): work on interactivity features for Slack integration
Browse files Browse the repository at this point in the history
Just the bare bones for the moment, alongside some GitHub OAuth hacks.

Signed-off-by: Andrei Jiroh Halili <[email protected]>
  • Loading branch information
ajhalili2006 committed Jul 23, 2024
1 parent 98bdfea commit bae6577
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 42 deletions.
35 changes: 5 additions & 30 deletions apps/golinks-v2/src/api/github.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@ export async function githubAuth(context: Context) {
const appId = context.env.GITHUB_OAUTH_ID;
const appSecret = context.env.GITHUB_OAUTH_SECRET;
const redirect_uri = `${context.env.BASE_URL}/auth/github/callback`;
const adapter = new PrismaD1(context.env.golinks);
const prisma = new PrismaClient({ adapter });
const { slack_id, slack_team, state, client_id } = context.req.query();
if (client_id == "slack") {
const requestState = encodeURIComponent(
Expand All @@ -19,18 +17,6 @@ export async function githubAuth(context: Context) {
state,
}),
);
const github = await prisma.gitHubOAuthChallenge
.create({
data: {
challenge: state,
metadata: JSON.stringify({ slack_team, slack_id }),
},
})
.catch((err) => {
console.error(err);
return context.newResponse("Something gone wrong on the backend");
});
console.log(`[db] ${github}`);
return context.redirect(
`https://github.com/login/oauth/authorize?client_id=${appId}&redirect_uri=${redirect_uri}&state=${requestState}&scope=read:user,user:email`,
);
Expand All @@ -45,8 +31,8 @@ export async function githubOAuthCallback(context: Context) {
const { state, code, error, error_description, error_uri } = context.req.query();
let payload = {
code,
client_id: context.env.GITHUB_OAUTH_ID,
client_secret: context.env.GITHUB_OAUTH_SECRET,
client_id: appId,
client_secret: appSecret,
redirect_uri,
state,
grant_type: "authorization_code",
Expand All @@ -69,20 +55,9 @@ https://go.andreijiroh.xyz/feedback/oauth-bug with the details above`;
return context.newResponse("OAuth flow was aborted because the auth code is invalid.", 400);
}
const ticket = generateSlug(12);
then((result) => {
const dbResult = prisma.gitHubOAuthChallenge.update({
where: {
challenge: stateJson.challenge,
},
data: {
code: ticket,
username,
userId: id,
},
});
console.log(`[prisma-client] ${JSON.stringify(dbResult)}`);
const prompt = `Here's your ticket code for requesting your API key: ${ticket}

console.log(`[prisma-client] ${JSON.stringify(dbResult)}`);
const prompt = `Here's your ticket code for requesting your API key: ${ticket}
Present this back to the bot by pressing "Enter code" in the message`;
});
}
67 changes: 60 additions & 7 deletions apps/golinks-v2/src/api/slack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ type SlackSlashCommand = {
};

async function helpMessage(context: Context, params: SlackSlashCommand) {
const challenge = await generateChallenge(context.env.golinks);
const challenge = generateSlug(24);
const githubAuthUrl = `${context.env.BASE_URL}/auth/github?client_id=slack&slack_team=${params.team_id}&slack_id=${params.user_id}&state=${challenge}`;
const templateJson = {
blocks: [
Expand Down Expand Up @@ -97,7 +97,7 @@ async function helpMessage(context: Context, params: SlackSlashCommand) {
type: "context",
elements: [
{
text: "If something go wrong, <https://go.andreijiroh.xyz/feedback/slackbot|please file a new issue> or ping @ajhalili2006 on the fediverse.",
text: "If something go wrong, <https://go.andreijiroh.xyz/feedback/slackbot|please file a new issue> or ping @ajhalili2006 on the fediverse (or here in the Slack if he's here).",
type: "mrkdwn",
},
],
Expand Down Expand Up @@ -160,6 +160,48 @@ function authChallengePrompt(context: Context, params: SlackSlashCommand) {
};
}

async function sneakyWIPScreen(context: Context, params: SlackSlashCommand) {
const blocks = {
type: "modal",
close: {
type: "plain_text",
text: "Close",
emoji: true,
},
title: {
type: "plain_text",
text: "You're a bit sneaky!",
emoji: true,
},
blocks: [
{
type: "section",
text: {
type: "mrkdwn",
text: "This feature is currently under development and working on stablizing this for you to use them soon. ",
},
},
{
type: "section",
text: {
type: "mrkdwn",
text: ":speech_balloon: *Send feedback*\nWe want to know your experience with our Slack integration for @ajhalili2006's golinks service.",
},
accessory: {
type: "button",
text: {
type: "plain_text",
text: "Open in GitHub",
emoji: true,
},
url: "https://go.andreijiroh.xyz/feedback/slack-integration",
},
},
],
};
return context.json(blocks);
}

/**
* Handle requests for OAuth-based app installation
* @param context
Expand Down Expand Up @@ -193,24 +235,28 @@ export async function slackOAuthCallback(context: Context) {
return context.json({ ok: false, error: result.error }, api.status);
}

const team = lookupBotToken(
const team = await lookupBotToken(
context.env.golinks,
result.is_enterprise_install == true ? result.enterprise.id : result.team.id,
result.is_enterprise_install,
);
console.log(`[prisma-client] ${JSON.stringify(team)}`);

if (!team) {
if (team == null) {
const deploy = await addBotToken(
context.env.golinks,
result.is_enterprise_install == true ? result.enterprise.id : result.team.id,
result.is_enterprise_install,
);
console.log(`[db] ${deploy}`);
} else {
const deploy = await updateBotToken(
context.env.golinks,
result.is_enterprise_install == true ? result.enterprise.id : result.team.id,
result.is_enterprise_install,
result.team.id,
result.access_token,
result.is_enterprise_install == true ? result.enterprise.id : false,
);
console.log(`[db] ${deploy}`);
}
return context.newResponse(`Installation success! Try it now with "/go help" command.`);
} catch (err) {
Expand Down Expand Up @@ -273,7 +319,14 @@ export async function handleSlackCommand(context: Context) {
return context.newResponse("Unsupported command");
}

export async function handleSlackInteractivity(context: Context) {}
export async function handleSlackInteractivity(context: Context) {
const authToken = await context.req.query("token");
const data = await context.req.parseBody();
const headers = await context.req.header()
await console.log(`[slack-interactivity] data:`, data);
await console.log(`[slack-interactivity] headers:`, headers);
return await sneakyWIPScreen(context, data);
}

/**
* Validate request timestamps to ensure that we don't received forged requests
Expand Down
3 changes: 2 additions & 1 deletion apps/golinks-v2/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import { DeprecatedGoLinkPage } from "pages/deprecated-link";
import { CommitHash, PingPong } from "api/meta";
import { prettyJSON } from "hono/pretty-json";
import { generateNewIssueUrl, handleOldUrls } from "lib/utils";
import { handleSlackCommand, slackOAuth, slackOAuthCallback } from "api/slack";
import { handleSlackCommand, handleSlackInteractivity, slackOAuth, slackOAuthCallback } from "api/slack";
import { githubAuth } from "api/github";

// Start a Hono app
Expand Down Expand Up @@ -75,6 +75,7 @@ openapi.post("/api/discord-invites", DiscordInviteLinkCreate);
openapi.get("/api/ping", PingPong);
openapi.get("/api/commit", CommitHash);
app.post("/api/slack/slash-commands/:command", async (c) => handleSlackCommand(c));
app.post("/api/slack/interactivity-feed", async (c) => handleSlackInteractivity(c));

// Slack bot and slash commands
app.get("/slack", async (c) => slackOAuth(c));
Expand Down
13 changes: 9 additions & 4 deletions apps/golinks-v2/src/lib/auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { PrismaClient } from "@prisma/client";
import { Context, Next } from "hono";
import { EnvBindings, Env } from "types";
import { generateSlug } from "./utils";
import { add } from "date-fns";
import { error } from "console";

export async function adminApiKeyAuth(c: Context, next: Next) {
Expand Down Expand Up @@ -65,7 +66,7 @@ export async function addBotToken(db: EnvBindings<Env>["golinks"], teamId: strin
const result = await prisma.slackBotToken.create({
data: {
teamId,
enterprise_install,
enterprise_install: enterprise_install !== undefined ? enterprise_install : false,
token,
},
});
Expand Down Expand Up @@ -121,17 +122,21 @@ export async function getUserInfoAndGenerateTicket(token: string, context: Conte
}
}

export async function generateChallenge(db: EnvBindings<Env>["golinks"], metadata) {
export async function addNewChallenge(db: EnvBindings<Env>["golinks"], challenge, metadata) {
const adapter = new PrismaD1(db);
const prisma = new PrismaClient({ adapter });
const newchallenge = generateSlug(24);
try {
const result = await prisma.gitHubOAuthChallenge.create({
data: {
challenge: newchallenge,
challenge,
metadata,
expires_on: add(Date(), {
minutes: 15,
}),
},
});
console.log(`[dbops] ${result}`);
return result;
} catch (error) {
console.error(error);
return Promise.reject(Error(error));
Expand Down

0 comments on commit bae6577

Please sign in to comment.