From 71b716edbad44f3810003430ca06a07b99980efd Mon Sep 17 00:00:00 2001 From: R3D347HR4Y Date: Mon, 15 Jun 2026 11:10:14 +0200 Subject: [PATCH] feat(office): add display name support for public share sessions - Updated publicOfficeSessionRequest to include a new DisplayName field. - Modified PublicEditorConfig to accept and utilize the display name for editor configuration. - Implemented editorLabelPath function to determine the correct file name for single-file public shares. - Added unit tests for editor label path and build editor config functionalities. --- internal/api/office/public_handlers.go | 13 ++++--- internal/api/office/public_share.go | 3 +- internal/api/office/service.go | 20 ++++++++-- internal/api/office/service_test.go | 51 ++++++++++++++++++++++++++ 4 files changed, 77 insertions(+), 10 deletions(-) create mode 100644 internal/api/office/service_test.go diff --git a/internal/api/office/public_handlers.go b/internal/api/office/public_handlers.go index 081468b..b313d48 100644 --- a/internal/api/office/public_handlers.go +++ b/internal/api/office/public_handlers.go @@ -26,11 +26,12 @@ func (h *Handler) RegisterPublicShareRoutes(r chi.Router) { } type publicOfficeSessionRequest struct { - Path string `json:"path"` - Mode string `json:"mode"` - Password string `json:"password"` - GuestID string `json:"guest_id"` - GuestName string `json:"guest_name"` + Path string `json:"path"` + Mode string `json:"mode"` + Password string `json:"password"` + GuestID string `json:"guest_id"` + GuestName string `json:"guest_name"` + DisplayName string `json:"display_name"` } func publicSharePassword(r *http.Request) string { @@ -73,7 +74,7 @@ func (h *Handler) PublicShareSession(w http.ResponseWriter, r *http.Request) { if mode == "edit" && !nextcloud.PublicShareCanUpdate(perms) { mode = "view" } - cfg, err := h.svc.PublicEditorConfig(r.Context(), token, req.Path, mode, password, req.GuestID, req.GuestName) + cfg, err := h.svc.PublicEditorConfig(r.Context(), token, req.Path, mode, password, req.GuestID, req.GuestName, strings.TrimSpace(req.DisplayName)) if err != nil { h.logger.Error("public editor config", "error", err) apivalidate.WriteInternal(w, r) diff --git a/internal/api/office/public_share.go b/internal/api/office/public_share.go index 1a7be35..6367fa9 100644 --- a/internal/api/office/public_share.go +++ b/internal/api/office/public_share.go @@ -15,7 +15,7 @@ type PublicShareAccess struct { Password string } -func (s *Service) PublicEditorConfig(ctx context.Context, token, filePath, mode, password, guestID, guestName string) (map[string]any, error) { +func (s *Service) PublicEditorConfig(ctx context.Context, token, filePath, mode, password, guestID, guestName, displayName string) (map[string]any, error) { token = strings.TrimSpace(token) filePath = normalizePath(filePath) if token == "" || filePath == "" { @@ -51,6 +51,7 @@ func (s *Service) PublicEditorConfig(ctx context.Context, token, filePath, mode, config, err := buildEditorConfig(buildEditorConfigInput{ filePath: filePath, + displayName: displayName, mode: mode, editorUserID: editorUserID, userName: guestName, diff --git a/internal/api/office/service.go b/internal/api/office/service.go index 6ce5f51..bbd3c95 100644 --- a/internal/api/office/service.go +++ b/internal/api/office/service.go @@ -102,6 +102,7 @@ func (s *Service) SaveDocument(ctx context.Context, ncUser, filePath string, bod type buildEditorConfigInput struct { filePath string + displayName string mode string editorUserID string userName string @@ -110,13 +111,26 @@ type buildEditorConfigInput struct { callbackURL string } +// editorLabelPath picks the name used for OnlyOffice fileType/documentType/title. +// Single-file public shares use WebDAV path "/" — displayName carries the real filename. +func editorLabelPath(filePath, displayName string) string { + if ext := path.Ext(filePath); ext != "" { + return filePath + } + if name := strings.TrimSpace(displayName); name != "" { + return name + } + return filePath +} + func buildEditorConfig(in buildEditorConfigInput) (map[string]any, error) { - docType := documentType(in.filePath) + labelPath := editorLabelPath(in.filePath, in.displayName) + docType := documentType(labelPath) edit := in.mode == "edit" document := map[string]any{ - "fileType": fileExt(in.filePath), + "fileType": fileExt(labelPath), "key": in.documentKey, - "title": path.Base(in.filePath), + "title": path.Base(labelPath), "url": in.downloadURL, "permissions": map[string]any{ "comment": true, diff --git a/internal/api/office/service_test.go b/internal/api/office/service_test.go new file mode 100644 index 0000000..083d3b6 --- /dev/null +++ b/internal/api/office/service_test.go @@ -0,0 +1,51 @@ +package office + +import "testing" + +func TestEditorLabelPath(t *testing.T) { + t.Parallel() + tests := []struct { + filePath string + displayName string + want string + }{ + {filePath: "/docs/report.xlsx", displayName: "", want: "/docs/report.xlsx"}, + {filePath: "/docs/report.xlsx", displayName: "other.docx", want: "/docs/report.xlsx"}, + {filePath: "/", displayName: "testtable.xlsx", want: "testtable.xlsx"}, + {filePath: "/", displayName: "", want: "/"}, + } + for _, tc := range tests { + got := editorLabelPath(tc.filePath, tc.displayName) + if got != tc.want { + t.Errorf("editorLabelPath(%q, %q) = %q, want %q", tc.filePath, tc.displayName, got, tc.want) + } + } +} + +func TestBuildEditorConfigSingleFileShareSpreadsheet(t *testing.T) { + t.Parallel() + cfg, err := buildEditorConfig(buildEditorConfigInput{ + filePath: "/", + displayName: "testtable.xlsx", + mode: "edit", + documentKey: "key", + downloadURL: "http://example/doc", + callbackURL: "http://example/cb", + }) + if err != nil { + t.Fatalf("buildEditorConfig: %v", err) + } + if cfg["documentType"] != "cell" { + t.Fatalf("documentType = %v, want cell", cfg["documentType"]) + } + doc, ok := cfg["document"].(map[string]any) + if !ok { + t.Fatalf("document missing") + } + if doc["fileType"] != "xlsx" { + t.Fatalf("fileType = %v, want xlsx", doc["fileType"]) + } + if doc["title"] != "testtable.xlsx" { + t.Fatalf("title = %v, want testtable.xlsx", doc["title"]) + } +}