Skip to content

Commit 497faf2

Browse files
committed
feat: Add Turnstile verification to issue creation endpoint
1 parent ae9d192 commit 497faf2

File tree

1 file changed

+34
-2
lines changed

1 file changed

+34
-2
lines changed

src/issue.ts

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ type GithubEnv = {
88
GITHUB_CLIENT_ID: string;
99
GITHUB_APP_PRIVATE_KEY: string;
1010
GITHUB_INSTALLATION_ID: string;
11+
TURNSTILE_SECRET_KEY: string;
1112
};
1213

1314
type GithubIssue = {
@@ -121,26 +122,57 @@ const getInstallationAccessToken = async (
121122
return data.token;
122123
};
123124

125+
const verifyTurnstile = async (token: string, secretKey: string) => {
126+
const url = "https://challenges.cloudflare.com/turnstile/v0/siteverify";
127+
const formData = new FormData();
128+
formData.append("secret", secretKey);
129+
formData.append("response", token);
130+
131+
try {
132+
const result = await fetch(url, {
133+
body: formData,
134+
method: "POST",
135+
});
136+
const outcome = (await result.json()) as { success: boolean };
137+
return outcome.success;
138+
} catch (err) {
139+
return false;
140+
}
141+
};
142+
124143
const app = new Hono()
125144
.post(
126145
"/",
127146
zValidator(
128-
"form",
147+
"json",
129148
z.object({
130149
title: z.string(),
131150
body: z.string(),
132151
labels: z.array(z.string()),
152+
turnstileToken: z.string().optional(),
133153
}),
134154
),
135155
async (c) => {
136-
const { title, body, labels } = c.req.valid("form");
156+
const { title, body, labels, turnstileToken } = c.req.valid("json");
137157

138158
const {
139159
GITHUB_CLIENT_ID,
140160
GITHUB_APP_PRIVATE_KEY,
141161
GITHUB_INSTALLATION_ID,
162+
TURNSTILE_SECRET_KEY,
142163
} = env<GithubEnv>(c);
143164

165+
// Verify Turnstile token if provided
166+
if (turnstileToken) {
167+
const isValid = await verifyTurnstile(
168+
turnstileToken,
169+
TURNSTILE_SECRET_KEY,
170+
);
171+
if (!isValid) {
172+
return c.json({ error: "Invalid Turnstile verification" }, 400);
173+
}
174+
}
175+
144176
// base64 encoded private key to utf8, not using buffer
145177
const privateKey = atob(GITHUB_APP_PRIVATE_KEY);
146178

0 commit comments

Comments
 (0)