mirror of
https://github.com/TautvydasDerzinskas/Thingport.git
synced 2026-10-21 22:22:24 -05:00
fix: allow preview image uploads on plain HTTP origins
This commit is contained in:
1 parent
20c41359dc
commit
6e569a9e82
4 files changed
+25
-3
No files matched your search
@@ -38,6 +38,7 @@ import TagInput from "../../components/TagInput";
|
||||
import DescriptionEditor from "./DescriptionEditor";
|
||||
import { translateCategoryDisplay } from "../../utils/translateCategoryDisplay";
|
||||
import { buildCategoryTree, flattenCategoryTree } from "../../utils/categoryTree";
|
||||
import { newLocalId } from "../../utils/localId";
|
||||
|
||||
type ImageItem =
|
||||
{ kind: "existing"; id: string; url: string } | { kind: "new"; localId: string; file: File; previewUrl: string };
|
||||
@@ -124,7 +125,7 @@ export default function EditModelModal({ print, onClose, onUnauthorized, onUpdat
|
||||
const newItems: ImageItem[] = Array.from(fileList).map((file) => {
|
||||
const previewUrl = URL.createObjectURL(file);
|
||||
createdUrlsRef.current.push(previewUrl);
|
||||
return { kind: "new", localId: crypto.randomUUID(), file, previewUrl };
|
||||
return { kind: "new", localId: newLocalId(), file, previewUrl };
|
||||
});
|
||||
setImages((prev) => [...prev, ...newItems]);
|
||||
markDirty();
|
||||
@@ -152,7 +153,7 @@ export default function EditModelModal({ print, onClose, onUnauthorized, onUpdat
|
||||
if (!fileList?.length) return;
|
||||
const newItems: PlateItem[] = Array.from(fileList).map((file) => ({
|
||||
kind: "new",
|
||||
localId: crypto.randomUUID(),
|
||||
localId: newLocalId(),
|
||||
file,
|
||||
}));
|
||||
setPlateItems((prev) => [...prev, ...newItems]);
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
// SHA-256 works with crypto.subtle, avoiding an MD5 dependency. https://docs.gravatar.com/general/hash/
|
||||
export async function gravatarUrl(email: string, size = 128): Promise<string> {
|
||||
// crypto.subtle is missing on plain-HTTP origins; callers then fall back to initials.
|
||||
export async function gravatarUrl(email: string, size = 128): Promise<string | undefined> {
|
||||
if (!crypto.subtle) return undefined;
|
||||
const normalized = email.trim().toLowerCase();
|
||||
const data = new TextEncoder().encode(normalized);
|
||||
const hashBuffer = await crypto.subtle.digest("SHA-256", data);
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
import { afterEach, describe, expect, it, vi } from "vitest";
|
||||
import { newLocalId } from "./localId";
|
||||
|
||||
describe("newLocalId", () => {
|
||||
afterEach(() => vi.unstubAllGlobals());
|
||||
|
||||
it("works without crypto.randomUUID (insecure HTTP origins)", () => {
|
||||
vi.stubGlobal("crypto", { getRandomValues: crypto.getRandomValues.bind(crypto) });
|
||||
const a = newLocalId();
|
||||
expect(a).toMatch(/^[0-9a-f]{32}$/);
|
||||
expect(newLocalId()).not.toBe(a);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,6 @@
|
||||
// crypto.randomUUID only exists in secure contexts, and self-hosted instances are often plain HTTP on a LAN.
|
||||
export function newLocalId(): string {
|
||||
if (typeof crypto.randomUUID === "function") return crypto.randomUUID();
|
||||
const bytes = crypto.getRandomValues(new Uint8Array(16));
|
||||
return Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("");
|
||||
}
|
||||
Reference in new issue
Block a user