MCPcopy Create free account
hub / github.com/Qinbf/groundmap / POST

Function POST

web/app/api/commit/route.ts:15–55  ·  view source on GitHub ↗
(req: NextRequest)

Source from the content-addressed store, hash-verified

13export const dynamic = "force-dynamic";
14
15export async function POST(req: NextRequest) {
16 // CSRF 兜底:拒绝跨站发起的写请求(本地工具语境,详见 lib/permissions.isSameOrigin)
17 if (!isSameOrigin(req)) {
18 return NextResponse.json({ error: "csrf_blocked" }, { status: 403 });
19 }
20
21 let body: { files?: string[]; message?: string };
22 try {
23 body = await req.json();
24 } catch {
25 return NextResponse.json({ error: "invalid_json" }, { status: 400 });
26 }
27
28 const { files, message } = body;
29 if (!files || !Array.isArray(files) || files.length === 0) {
30 return NextResponse.json({ error: "missing_files" }, { status: 400 });
31 }
32 if (!files.every((f) => typeof f === "string")) {
33 return NextResponse.json({ error: "invalid_files" }, { status: 400 });
34 }
35 if (!message || typeof message !== "string") {
36 return NextResponse.json({ error: "missing_message" }, { status: 400 });
37 }
38
39 // 逐个文件校验权限:路径白名单 + 现有文件 frontmatter 锁
40 for (const f of files) {
41 const perm = await checkWritePermissionAsync(f);
42 if (!perm.allowed) {
43 return NextResponse.json(
44 { error: "permission_denied", path: f, reason: perm.reason },
45 { status: 403 },
46 );
47 }
48 }
49
50 const result = await gitAddAndCommit(files, message);
51 if (!result.ok) {
52 return NextResponse.json(result, { status: 500 });
53 }
54 return NextResponse.json(result);
55}

Callers

nothing calls this directly

Calls 3

isSameOriginFunction · 0.90
gitAddAndCommitFunction · 0.90

Tested by

no test coverage detected