75 lines
2.9 KiB
Go
75 lines
2.9 KiB
Go
package canvas
|
|
|
|
import (
|
|
"encoding/json"
|
|
"infinite-canvas/backend/internal/assets"
|
|
"strings"
|
|
"testing"
|
|
|
|
"infinite-canvas/backend/internal/model"
|
|
)
|
|
|
|
func TestCanvasShareTokenHashDoesNotExposeToken(t *testing.T) {
|
|
token := "example-share-token"
|
|
first := canvasShareTokenHash(token)
|
|
if first == token || first != canvasShareTokenHash(token) || len(first) != 64 {
|
|
t.Fatalf("unexpected token hash: %q", first)
|
|
}
|
|
}
|
|
|
|
func TestPublicCanvasProjectScrubsSecretsAndRewritesResources(t *testing.T) {
|
|
payload := map[string]any{
|
|
"id": "project-1", "title": "公开画布", "chatSessions": []any{map[string]any{"secret": "chat"}},
|
|
"nodes": []any{map[string]any{
|
|
"id": "node-1", "type": "image", "title": "镜头", "position": map[string]any{"x": 1, "y": 2}, "width": 320, "height": 240,
|
|
"metadata": map[string]any{
|
|
"content": "data:image/png;base64,secret", "storageKey": "resource:resource_123", "prompt": "保留提示词",
|
|
"apiKey": "secret", "taskId": "task-1", "skillSnapshot": map[string]any{"apiKey": "nested-secret", "name": "技能"},
|
|
},
|
|
}},
|
|
"connections": []any{},
|
|
}
|
|
raw, _ := json.Marshal(payload)
|
|
project := &model.CanvasProject{ID: "project-1", Title: "公开画布", PayloadJSON: string(raw)}
|
|
public, resources, err := publicCanvasProject(project, "share-token")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
encoded, _ := json.Marshal(public)
|
|
text := string(encoded)
|
|
for _, forbidden := range []string{"data:image", "secret", "task-1", `"secret":"chat"`} {
|
|
if strings.Contains(text, forbidden) {
|
|
t.Fatalf("public payload leaked %q: %s", forbidden, text)
|
|
}
|
|
}
|
|
if !strings.Contains(text, "保留提示词") || !strings.Contains(text, "/api/public/canvas-shares/share-token/resources/resource_123/file") {
|
|
t.Fatalf("public payload lost expected data: %s", text)
|
|
}
|
|
if !resources["resource_123"] {
|
|
t.Fatal("referenced resource was not authorized")
|
|
}
|
|
}
|
|
|
|
func TestCanvasResourceIDRejectsInvalidValues(t *testing.T) {
|
|
for _, value := range []string{"resource:", "resource:../secret", "/api/resources/a%2Fb/file", "resource:" + strings.Repeat("a", 81)} {
|
|
if got := assets.ResourceID(value); got != "" {
|
|
t.Fatalf("expected invalid resource id for %q, got %q", value, got)
|
|
}
|
|
}
|
|
if got := assets.ResourceID("/api/resources/abc_123/file"); got != "abc_123" {
|
|
t.Fatalf("unexpected resource id: %q", got)
|
|
}
|
|
}
|
|
|
|
func TestPublicCanvasProjectDropsUnmanagedMediaURL(t *testing.T) {
|
|
payload := `{"id":"p","nodes":[{"id":"n","type":"image","title":"image","position":{"x":0,"y":0},"width":10,"height":10,"metadata":{"content":"https://tracker.example/image.png","prompt":"public prompt"}}],"connections":[]}`
|
|
public, _, err := publicCanvasProject(&model.CanvasProject{ID: "p", PayloadJSON: payload}, "share-token")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
encoded, _ := json.Marshal(public)
|
|
if strings.Contains(string(encoded), "tracker.example") || !strings.Contains(string(encoded), "public prompt") {
|
|
t.Fatalf("unexpected public payload: %s", encoded)
|
|
}
|
|
}
|