mirror of
https://github.com/hex248/ob248.com.git
synced 2026-02-07 18:23:04 +00:00
wakatime serverless setup
This commit is contained in:
64
api/wakatime/oauth/start.ts
Normal file
64
api/wakatime/oauth/start.ts
Normal file
@@ -0,0 +1,64 @@
|
||||
import type { IncomingMessage, ServerResponse } from "node:http";
|
||||
import {
|
||||
assertSetupSecret,
|
||||
buildRedirectUri,
|
||||
getClientIp,
|
||||
getRequiredEnv,
|
||||
isRateLimited,
|
||||
isSetupEnabled,
|
||||
json,
|
||||
makeState,
|
||||
} from "../_shared.ts";
|
||||
|
||||
export default async function handler(
|
||||
req: IncomingMessage,
|
||||
res: ServerResponse & {
|
||||
status: (code: number) => { json: (payload: unknown) => void };
|
||||
},
|
||||
) {
|
||||
if (req.method !== "GET") {
|
||||
json(res, 405, { error: "Method not allowed" });
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isSetupEnabled()) {
|
||||
json(res, 403, { error: "Setup route disabled" });
|
||||
return;
|
||||
}
|
||||
|
||||
const ip = getClientIp(req);
|
||||
if (isRateLimited(`oauth-start:${ip}`, 20)) {
|
||||
json(res, 429, { error: "Too many requests" });
|
||||
return;
|
||||
}
|
||||
|
||||
const url = new URL(req.url ?? "", "https://localhost");
|
||||
const setupSecret = url.searchParams.get("setup_secret") ?? undefined;
|
||||
if (!assertSetupSecret(setupSecret)) {
|
||||
json(res, 401, { error: "Unauthorized setup request" });
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const clientId = getRequiredEnv("WAKATIME_CLIENT_ID");
|
||||
const setupSecretValue = getRequiredEnv("WAKATIME_SETUP_SECRET");
|
||||
const redirectUri = buildRedirectUri(req);
|
||||
const state = makeState(setupSecretValue);
|
||||
|
||||
const authorizeUrl = new URL("https://wakatime.com/oauth/authorize");
|
||||
authorizeUrl.searchParams.set("client_id", clientId);
|
||||
authorizeUrl.searchParams.set("response_type", "code");
|
||||
authorizeUrl.searchParams.set("redirect_uri", redirectUri);
|
||||
authorizeUrl.searchParams.set("scope", "read_stats email");
|
||||
authorizeUrl.searchParams.set("state", state);
|
||||
|
||||
res.statusCode = 302;
|
||||
res.setHeader("Location", authorizeUrl.toString());
|
||||
res.end();
|
||||
} catch (error) {
|
||||
json(res, 500, {
|
||||
error: "Failed to build OAuth authorize URL",
|
||||
detail: error instanceof Error ? error.message : "unknown_error",
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user