mirror of
https://github.com/multica-ai/multica.git
synced 2026-07-26 04:25:46 +02:00
fix: avoid persisting signed draft attachment urls
Co-authored-by: multica-agent <github@multica.ai>
This commit is contained in:
@@ -490,10 +490,17 @@ describe("CreateIssueModal", () => {
|
||||
expect.objectContaining({
|
||||
id: "11111111-2222-3333-4444-555555555555",
|
||||
filename: "shot.png",
|
||||
download_url: "",
|
||||
}),
|
||||
],
|
||||
});
|
||||
});
|
||||
const draftAttachmentsCall = mockSetDraft.mock.calls.find(
|
||||
([patch]) => Array.isArray(patch.attachments),
|
||||
)?.[0] as { attachments?: Array<{ download_url: string }> } | undefined;
|
||||
expect(draftAttachmentsCall?.attachments?.[0]?.download_url).not.toContain(
|
||||
"Signature=",
|
||||
);
|
||||
});
|
||||
|
||||
it("reuses draft attachments after reopening manual create so pasted images can render and bind", async () => {
|
||||
@@ -509,7 +516,7 @@ describe("CreateIssueModal", () => {
|
||||
uploader_id: "user-1",
|
||||
filename: "shot.png",
|
||||
url: "https://cdn.example.test/shot.png",
|
||||
download_url: "https://cdn.example.test/shot.png?Signature=fresh",
|
||||
download_url: "",
|
||||
markdown_url: "https://multica-api.copilothub.ai/api/attachments/11111111-2222-3333-4444-555555555555/download",
|
||||
content_type: "image/png",
|
||||
size_bytes: 123,
|
||||
|
||||
@@ -18,7 +18,7 @@ import {
|
||||
} from "lucide-react";
|
||||
import { cn } from "@multica/ui/lib/utils";
|
||||
import { toast } from "sonner";
|
||||
import type { Issue, IssueStatus, IssuePriority, IssueAssigneeType } from "@multica/core/types";
|
||||
import type { Issue, IssueStatus, IssuePriority, IssueAssigneeType, Attachment } from "@multica/core/types";
|
||||
import { contentReferencesAttachment } from "@multica/core/types";
|
||||
import {
|
||||
DialogContent,
|
||||
@@ -58,6 +58,17 @@ import { PillButton } from "../common/pill-button";
|
||||
import { IssuePickerModal } from "./issue-picker-modal";
|
||||
import { useT } from "../i18n";
|
||||
|
||||
function toDraftAttachment(attachment: Attachment): Attachment {
|
||||
return {
|
||||
...attachment,
|
||||
// `download_url` is minted for the current API response and may be a
|
||||
// short-lived signed URL. Drafts survive across dialog closes and app
|
||||
// restarts, so persist only durable fields and let render/download paths
|
||||
// re-resolve through id/markdown_url when needed.
|
||||
download_url: "",
|
||||
};
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// ManualCreatePanel — manual-mode body of the create-issue dialog. Renders
|
||||
// DialogContent + everything inside; the surrounding `<Dialog>` is owned by
|
||||
@@ -156,7 +167,7 @@ export function ManualCreatePanel({
|
||||
useIssueDraftStore.getState().draft.attachments ?? [];
|
||||
const attachments = currentAttachments.some((a) => a.id === result.id)
|
||||
? currentAttachments
|
||||
: [...currentAttachments, result];
|
||||
: [...currentAttachments, toDraftAttachment(result)];
|
||||
setDraft({ attachments });
|
||||
}
|
||||
return result;
|
||||
|
||||
Reference in New Issue
Block a user