diff --git a/cmd/server/main.go b/cmd/server/main.go index cb9fc7e..34bf520 100644 --- a/cmd/server/main.go +++ b/cmd/server/main.go @@ -101,6 +101,7 @@ func main() { r.Get("/public/{token}/download", nodeH.PublicDownload) r.Get("/public/{token}/nodes/{id}", nodeH.PublicChildMeta) r.Get("/public/{token}/nodes/{id}/download", nodeH.PublicChildDownload) + r.Get("/public/{token}/nodes/{id}/office", nodeH.PublicOfficeInfo) srv := &http.Server{ Addr: ":" + cfg.ServerPort, diff --git a/internal/handler/node.go b/internal/handler/node.go index 2921fe8..f445a80 100644 --- a/internal/handler/node.go +++ b/internal/handler/node.go @@ -7,6 +7,7 @@ import ( "html" "io" "net/http" + "net/url" "path/filepath" "strconv" "strings" @@ -398,6 +399,12 @@ func (h *NodeHandler) PublicChildMeta(w http.ResponseWriter, r *http.Request) { return } token := chi.URLParam(r, "token") + if node.NodeType == model.NodeTypeOfficeDocument { + if officeID := officeIDFromNode(node); officeID != "" { + http.Redirect(w, r, h.publicOfficeURL(token, node.ID, officeID), http.StatusFound) + return + } + } if node.NodeType == model.NodeTypeFile { h.renderPublicPreview(w, node, h.publicNodeURL(token, node.ID)+"/download") return @@ -414,6 +421,23 @@ func (h *NodeHandler) PublicChildMeta(w http.ResponseWriter, r *http.Request) { h.renderPublicUnavailable(w, node) } +func (h *NodeHandler) PublicOfficeInfo(w http.ResponseWriter, r *http.Request) { + node, ok := h.publicNodeByID(w, r) + if !ok { + return + } + officeID := officeIDFromNode(node) + if node.NodeType != model.NodeTypeOfficeDocument || officeID == "" { + writeError(w, http.StatusBadRequest, "node is not an office document") + return + } + writeJSON(w, http.StatusOK, map[string]string{ + "node_id": node.ID, + "office_id": officeID, + "title": node.Title, + }) +} + func (h *NodeHandler) PublicChildDownload(w http.ResponseWriter, r *http.Request) { node, ok := h.publicNodeByID(w, r) if !ok { @@ -552,6 +576,11 @@ func (h *NodeHandler) renderPublicFolder(w http.ResponseWriter, r *http.Request, } kind := publicKind(child) href := h.publicNodeURL(token, child.ID) + if child.NodeType == model.NodeTypeOfficeDocument { + if officeID := officeIDFromNode(&child); officeID != "" { + href = h.publicOfficeURL(token, child.ID, officeID) + } + } b.WriteString(``) b.WriteString(`` + html.EscapeString(kind) + ``) b.WriteString(`` + html.EscapeString(title) + ``) @@ -619,6 +648,23 @@ func (h *NodeHandler) publicNodeURL(token, nodeID string) string { return h.publicURL(token) + "/nodes/" + nodeID } +func (h *NodeHandler) publicOfficeURL(token, nodeID, officeID string) string { + values := url.Values{} + values.Set("files_token", token) + values.Set("node_id", nodeID) + return strings.TrimRight(h.cfg.PublicBaseURL, "/") + "/office/public/" + url.PathEscape(officeID) + "?" + values.Encode() +} + +func officeIDFromNode(node *model.Node) string { + if node == nil || node.ExternalURL == nil { + return "" + } + if match := strings.TrimPrefix(*node.ExternalURL, "/office/"); match != *node.ExternalURL { + return strings.TrimSpace(match) + } + return "" +} + func publicKind(node model.Node) string { switch node.NodeType { case model.NodeTypeFolder: