From 822c730cd6d091957385062692ea72c711442a2a Mon Sep 17 00:00:00 2001 From: lix-2026 Date: Wed, 15 Apr 2026 03:35:49 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20=E6=94=B6=E5=8F=A3=20onlyoffice=20c?= =?UTF-8?q?allback=20=E6=9C=AC=E5=9C=B0=E7=B1=BB=E5=9E=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 去掉 callback 写回链中的宽泛 any 访问,改为最小资产/权限类型 - 复用 documentId/workspaceId/mimeType 局部变量,保持回调写回逻辑更稳定可读 --- .../src/app/api/onlyoffice/callback/route.ts | 37 +++++++++++++------ 1 file changed, 26 insertions(+), 11 deletions(-) diff --git a/wolai-frontend/src/app/api/onlyoffice/callback/route.ts b/wolai-frontend/src/app/api/onlyoffice/callback/route.ts index 33204470..fe640616 100644 --- a/wolai-frontend/src/app/api/onlyoffice/callback/route.ts +++ b/wolai-frontend/src/app/api/onlyoffice/callback/route.ts @@ -22,6 +22,16 @@ type OnlyOfficeCallbackBody = { key?: string; }; +type OnlyOfficeAssetRecord = { + document_id?: string | null; + workspace_id?: string | null; + mime_type?: string | null; +}; + +type OnlyOfficePermission = { + permission?: string | null; +}; + const normalizeSecret = (raw: string) => { const trimmed = String(raw || "").trim(); if (!trimmed) return ""; @@ -98,18 +108,23 @@ export async function POST(request: Request) { "dev-user"; const client = getConvexHttpClient(); - const asset = await client.query(api.mediaAssets.getById, { userId, id: assetId }); + const asset = (await client.query(api.mediaAssets.getById, { userId, id: assetId })) as + | OnlyOfficeAssetRecord + | null; if (!asset) { return NextResponse.json({ error: 1 }); } + const documentId = String(asset.document_id || "").trim(); + const workspaceId = String(asset.workspace_id || "").trim() || null; + const mimeType = String(asset.mime_type || "").trim() || "application/octet-stream"; // 只读权限:不允许通过 ONLYOFFICE 回调写回 try { - const perm = await client.query(api.documents.getPermissionForUser, { + const perm = (await client.query(api.documents.getPermissionForUser, { userId, - id: String((asset as any).document_id || ""), - }); - if (!perm || (perm as any).permission !== "edit") { + id: documentId, + })) as OnlyOfficePermission | null; + if (!perm || perm.permission !== "edit") { return NextResponse.json({ error: 1 }); } } catch { @@ -131,7 +146,7 @@ export async function POST(request: Request) { const uploadRes = await fetch(uploadUrl, { method: "POST", - headers: { "Content-Type": asset.mime_type || "application/octet-stream" }, + headers: { "Content-Type": mimeType }, body: buf, }); @@ -147,7 +162,7 @@ export async function POST(request: Request) { const bridgeContext = buildDocumentBridgeContextWithActor({ request, - workspaceId: String((asset as any).workspace_id || "").trim() || null, + workspaceId, actor: { actorType: "service", actorId: userId, @@ -163,15 +178,15 @@ export async function POST(request: Request) { name: "media.assets.replace_storage", payload: { assetId, - documentId: String((asset as any).document_id || "").trim(), - workspaceId: String((asset as any).workspace_id || "").trim() || null, + documentId, + workspaceId, storageId, userId, } satisfies MediaAssetReplaceStoragePayload, context: bridgeContext, target: { - workspaceId: String((asset as any).workspace_id || "").trim() || null, - pageId: String((asset as any).document_id || "").trim() || null, + workspaceId, + pageId: documentId || null, }, reason: "ONLYOFFICE 回调写回附件存储", refs: [`onlyoffice:asset:${assetId}`],