Add public OnlyOffice download endpoint to bypass auth middleware 401 issue
All checks were successful
Automated Container Build / build-and-push (push) Successful in 1m20s
All checks were successful
Automated Container Build / build-and-push (push) Successful in 1m20s
This commit is contained in:
parent
a0353445d9
commit
fd991a1d4b
3 changed files with 39 additions and 1 deletions
|
|
@ -78,6 +78,39 @@ func (h *OnlyOfficeHandler) Callback(c *fiber.Ctx) error {
|
|||
return c.JSON(fiber.Map{"error": 0})
|
||||
}
|
||||
|
||||
// DownloadForEditor serves a file to the OnlyOffice Document Server.
|
||||
// This is a public endpoint that validates the download token manually,
|
||||
// bypassing the auth middleware (which can fail when requests are proxied
|
||||
// through Next.js rewrites).
|
||||
func (h *OnlyOfficeHandler) DownloadForEditor(c *fiber.Ctx) error {
|
||||
path := c.Query("path")
|
||||
token := c.Query("token")
|
||||
|
||||
if path == "" {
|
||||
return c.Status(400).JSON(fiber.Map{"error": "path required"})
|
||||
}
|
||||
|
||||
// Validate the download token
|
||||
if err := middleware.ValidateDownloadToken(token, h.Config.JWTSecret, ""); err != nil {
|
||||
return c.Status(401).JSON(fiber.Map{"error": "unauthorized"})
|
||||
}
|
||||
|
||||
// Jail the path to the storage directory
|
||||
cleaned := filepath.Clean(path)
|
||||
if filepath.IsAbs(cleaned) || cleaned == ".." || len(cleaned) > 2 && cleaned[:3] == ".." + string(filepath.Separator) {
|
||||
return c.Status(403).JSON(fiber.Map{"error": "invalid path"})
|
||||
}
|
||||
|
||||
fullPath := filepath.Join(h.Config.StorageDir, cleaned)
|
||||
|
||||
info, err := os.Stat(fullPath)
|
||||
if err != nil || info.IsDir() {
|
||||
return c.Status(404).JSON(fiber.Map{"error": "file not found"})
|
||||
}
|
||||
|
||||
return c.SendFile(fullPath)
|
||||
}
|
||||
|
||||
// CreateBlank creates an empty document for Docs or Slides mode
|
||||
func (h *OnlyOfficeHandler) CreateBlank(c *fiber.Ctx) error {
|
||||
req := new(struct {
|
||||
|
|
|
|||
|
|
@ -138,6 +138,9 @@ func main() {
|
|||
|
||||
// OnlyOffice callback (public but validates query token)
|
||||
public.Post("/onlyoffice/callback", onlyOfficeHandler.Callback)
|
||||
// OnlyOffice file download (public but validates query token — bypasses auth middleware
|
||||
// since requests come from the Document Server via Next.js proxy which can drop query params)
|
||||
public.Get("/onlyoffice/download", onlyOfficeHandler.DownloadForEditor)
|
||||
|
||||
// Auth routes (with brute force protection)
|
||||
auth := app.Group("/api/auth")
|
||||
|
|
|
|||
|
|
@ -41,9 +41,11 @@ export default function OnlyOfficeEditor({ file, type, onClose }: OnlyOfficeEdit
|
|||
// It's on the default bridge network and can reach the Unraid host IP, but NOT
|
||||
// the public domain (hairpin NAT) or Docker DNS names (different network).
|
||||
// Port 5827 is the frontend container (which proxies /api/* to the backend).
|
||||
// We use dedicated public endpoints that validate tokens manually, bypassing
|
||||
// the auth middleware which fails when requests come through the Next.js proxy.
|
||||
const INTERNAL_URL = 'http://192.168.50.81:5827/api';
|
||||
|
||||
const fileUrl = `${INTERNAL_URL}/files/download/${encodeURIComponent(file.path)}?token=${downloadToken}`;
|
||||
const fileUrl = `${INTERNAL_URL}/public/onlyoffice/download?path=${encodeURIComponent(file.path)}&token=${downloadToken}`;
|
||||
const callbackUrl = `${INTERNAL_URL}/public/onlyoffice/callback?path=${encodeURIComponent(file.path)}&token=${downloadToken}`;
|
||||
|
||||
const baseConfig: any = {
|
||||
|
|
|
|||
Reference in a new issue