Your Name 40848ffdb5
Some checks failed
Lint / build (20) (push) Has been cancelled
Playwright Tests / test (push) Has been cancelled
fix: stabilize dingtalk login and image sizing
2026-05-11 14:24:34 +08:00

73 lines
2.1 KiB
TypeScript

import { NextResponse } from "next/server";
import { getAuthSettings } from "@/lib/db/queries";
const normalizeCallbackUrl = (value: string | null) => {
if (!value) return "/";
try {
const parsed = new URL(value, "https://local.invalid");
if (parsed.origin !== "https://local.invalid") return "/";
return `${parsed.pathname}${parsed.search}${parsed.hash}` || "/";
} catch {
return "/";
}
};
const encodeState = (payload: { org: string; callbackUrl: string }) => {
return `v1.${Buffer.from(JSON.stringify(payload), "utf8").toString(
"base64url",
)}`;
};
export async function GET(request: Request) {
const settings = await getAuthSettings();
if (!settings.isDingTalkEnabled) {
return NextResponse.json(
{ error: "DingTalk login is not enabled" },
{ status: 400 },
);
}
const urlObj = new URL(request.url);
const orgName = urlObj.searchParams.get("org");
const organizations = settings.dingTalkOrganizations ?? [];
const selectedOrg = orgName
? organizations.find((org) => org.name === orgName)
: organizations[0];
const appKey = selectedOrg?.appKey ?? settings.dingTalkAppKey;
if (!appKey) {
return NextResponse.json(
{ error: "DingTalk appKey is not configured" },
{ status: 400 },
);
}
// 动态构建回调地址
// 优先使用 AUTH_URL 环境变量,确保使用正确的公网域名
const requestUrl = new URL(request.url);
const baseUrl = process.env.AUTH_URL || requestUrl.origin;
const redirectUri = `${baseUrl}/dingtalk-callback.html`;
// state 中保存组织和登录后的回跳地址,回调接口仍兼容旧的纯组织名 state。
const state = encodeState({
org: orgName || selectedOrg?.name || "default",
callbackUrl: normalizeCallbackUrl(urlObj.searchParams.get("callbackUrl")),
});
// 钉钉 OAuth 2.0 授权地址
const url =
`https://login.dingtalk.com/oauth2/auth?` +
`redirect_uri=${encodeURIComponent(redirectUri)}&` +
`response_type=code&` +
`client_id=${encodeURIComponent(appKey)}&` +
`scope=openid&` +
`state=${encodeURIComponent(state)}&` +
`prompt=consent`;
return NextResponse.redirect(url);
}