updated debugging and scoped path (#1198)
This commit is contained in:
1 parent
7baf2653e0
commit
2d2a3d7707
3 files changed
+76
-40
No files matched your search
+38
-35
@@ -7,6 +7,7 @@ import (
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
@@ -49,7 +50,21 @@ func onlyofficeClientConfigGetHandler(w http.ResponseWriter, r *http.Request, d
|
||||
return http.StatusBadRequest, errors.New("missing required parameters: path + source/hash are required")
|
||||
}
|
||||
themeMode := utils.Ternary(d.user.DarkMode, "dark", "light")
|
||||
|
||||
var sourceInfo settings.Source
|
||||
var ok bool
|
||||
if d.fileInfo.Hash != "" {
|
||||
sourceInfo, ok = settings.Config.Server.SourceMap[source]
|
||||
if !ok {
|
||||
logger.Error("OnlyOffice: source not found")
|
||||
return http.StatusInternalServerError, fmt.Errorf("source not found")
|
||||
}
|
||||
} else {
|
||||
sourceInfo, ok = settings.Config.Server.NameToSource[source]
|
||||
if !ok {
|
||||
logger.Error("OnlyOffice: source not found")
|
||||
return http.StatusInternalServerError, fmt.Errorf("source not found")
|
||||
}
|
||||
}
|
||||
if d.fileInfo.Hash == "" {
|
||||
// Build file info based on whether this is a share or regular request
|
||||
// Regular user request - need to resolve scope
|
||||
@@ -58,27 +73,20 @@ func onlyofficeClientConfigGetHandler(w http.ResponseWriter, r *http.Request, d
|
||||
logger.Errorf("OnlyOffice: source %s not available for user %s: %v", source, d.user.Username, scopeErr)
|
||||
return http.StatusForbidden, fmt.Errorf("source %s is not available", source)
|
||||
}
|
||||
resolvedPath := utils.JoinPathAsUnix(userScope, path)
|
||||
logger.Debugf("OnlyOffice user request: resolved path=%s", resolvedPath)
|
||||
|
||||
indexPath := utils.JoinPathAsUnix(userScope, path)
|
||||
logger.Debugf("OnlyOffice user request: resolved path=%s", indexPath)
|
||||
fileInfo, err := files.FileInfoFaster(iteminfo.FileOptions{
|
||||
Path: resolvedPath,
|
||||
Path: indexPath,
|
||||
Modify: d.user.Permissions.Modify,
|
||||
Source: source,
|
||||
Expand: false,
|
||||
})
|
||||
if err != nil {
|
||||
logger.Errorf("OnlyOffice: failed to get file info for source=%s, path=%s: %v", source, resolvedPath, err)
|
||||
logger.Errorf("OnlyOffice: failed to get file info for source=%s, path=%s: %v", source, indexPath, err)
|
||||
return errToStatus(err), err
|
||||
}
|
||||
d.fileInfo = *fileInfo
|
||||
} else {
|
||||
// is a share, use the file info from the share middleware
|
||||
sourceInfo, ok := settings.Config.Server.SourceMap[d.share.Source]
|
||||
if !ok {
|
||||
logger.Error("OnlyOffice: source from share not found")
|
||||
return http.StatusInternalServerError, fmt.Errorf("source not found for share")
|
||||
}
|
||||
source = sourceInfo.Name
|
||||
// path is index path, so we build from share path
|
||||
path = utils.JoinPathAsUnix(d.share.Path, path)
|
||||
@@ -92,7 +100,7 @@ func onlyofficeClientConfigGetHandler(w http.ResponseWriter, r *http.Request, d
|
||||
}
|
||||
|
||||
// Determine file type and editing permissions
|
||||
fileType := getFileExtension(d.fileInfo.Name)
|
||||
fileType := strings.TrimPrefix(filepath.Ext(d.fileInfo.Name), ".")
|
||||
canEdit := iteminfo.CanEditOnlyOffice(d.user.Permissions.Modify, fileType)
|
||||
canEditMode := utils.Ternary(canEdit, "edit", "view")
|
||||
if d.fileInfo.Hash != "" {
|
||||
@@ -111,7 +119,7 @@ func onlyofficeClientConfigGetHandler(w http.ResponseWriter, r *http.Request, d
|
||||
}
|
||||
|
||||
// Generate document ID for OnlyOffice
|
||||
documentId, err := getOnlyOfficeId(source, path)
|
||||
documentId, err := getOnlyOfficeId(d.fileInfo.RealPath)
|
||||
if err != nil {
|
||||
logger.Errorf("OnlyOffice: failed to generate document ID for source=%s, path=%s: %v", source, path, err)
|
||||
return http.StatusNotFound, fmt.Errorf("failed to generate document ID: %v", err)
|
||||
@@ -166,15 +174,6 @@ func onlyofficeClientConfigGetHandler(w http.ResponseWriter, r *http.Request, d
|
||||
return renderJSON(w, r, clientConfig)
|
||||
}
|
||||
|
||||
// getFileExtension extracts file extension from filename
|
||||
func getFileExtension(filename string) string {
|
||||
parts := strings.Split(filename, ".")
|
||||
if len(parts) < 2 {
|
||||
return ""
|
||||
}
|
||||
return parts[len(parts)-1]
|
||||
}
|
||||
|
||||
// buildOnlyOfficeDownloadURL constructs the download URL that OnlyOffice server will use to fetch the file
|
||||
func buildOnlyOfficeDownloadURL(source, path, hash, token string) string {
|
||||
// Determine base URL (internal URL takes priority for OnlyOffice server communication)
|
||||
@@ -254,6 +253,21 @@ func onlyofficeCallbackHandler(w http.ResponseWriter, r *http.Request, d *reques
|
||||
logger.Errorf("OnlyOffice callback missing required parameters: source=%s, path=%s", source, path)
|
||||
return http.StatusBadRequest, errors.New("missing required parameters: path + source/hash are required")
|
||||
}
|
||||
var sourceInfo settings.Source
|
||||
var ok bool
|
||||
if d.fileInfo.Hash != "" {
|
||||
sourceInfo, ok = settings.Config.Server.SourceMap[source]
|
||||
if !ok {
|
||||
logger.Error("OnlyOffice: source not found")
|
||||
return http.StatusInternalServerError, fmt.Errorf("source not found")
|
||||
}
|
||||
} else {
|
||||
sourceInfo, ok = settings.Config.Server.NameToSource[source]
|
||||
if !ok {
|
||||
logger.Error("OnlyOffice: source not found")
|
||||
return http.StatusInternalServerError, fmt.Errorf("source not found")
|
||||
}
|
||||
}
|
||||
|
||||
if d.fileInfo.Hash == "" {
|
||||
// Regular user request - need to resolve scope
|
||||
@@ -264,12 +278,6 @@ func onlyofficeCallbackHandler(w http.ResponseWriter, r *http.Request, d *reques
|
||||
}
|
||||
path = utils.JoinPathAsUnix(userScope, path)
|
||||
} else {
|
||||
// is a share, use the file info from the share middleware
|
||||
sourceInfo, ok := settings.Config.Server.SourceMap[d.share.Source]
|
||||
if !ok {
|
||||
logger.Error("OnlyOffice: source from share not found")
|
||||
return http.StatusInternalServerError, fmt.Errorf("source not found for share")
|
||||
}
|
||||
source = sourceInfo.Name
|
||||
// path is index path, so we build from share path
|
||||
path = utils.JoinPathAsUnix(d.share.Path, path)
|
||||
@@ -339,12 +347,7 @@ func onlyofficeCallbackHandler(w http.ResponseWriter, r *http.Request, d *reques
|
||||
return renderJSON(w, r, resp)
|
||||
}
|
||||
|
||||
func getOnlyOfficeId(source, path string) (string, error) {
|
||||
idx := indexing.GetIndex(source)
|
||||
if idx == nil {
|
||||
return "", fmt.Errorf("source not found")
|
||||
}
|
||||
realpath, _, _ := idx.GetRealPath(path)
|
||||
func getOnlyOfficeId(realpath string) (string, error) {
|
||||
// error is intentionally ignored in order treat errors
|
||||
// the same as a cache-miss
|
||||
cachedDocumentKey, ok := utils.OnlyOfficeCache.Get(realpath).(string)
|
||||
|
||||
@@ -104,6 +104,36 @@ export default {
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getInternalUrlInfo() {
|
||||
if (this.clientConfig && this.clientConfig.document && this.clientConfig.document.url) {
|
||||
try {
|
||||
const docUrlOrigin = new URL(this.clientConfig.document.url).origin;
|
||||
const windowOrigin = window.location.origin;
|
||||
|
||||
if (docUrlOrigin !== windowOrigin) {
|
||||
return {
|
||||
isSet: true,
|
||||
message: `${docUrlOrigin}`
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
isSet: false,
|
||||
message: "Not set, using window.location"
|
||||
};
|
||||
}
|
||||
} catch (e) {
|
||||
return {
|
||||
isSet: false,
|
||||
message: "⚠️ Error parsing document URL"
|
||||
};
|
||||
}
|
||||
}
|
||||
return {
|
||||
isSet: false,
|
||||
message: "Analyzing..."
|
||||
};
|
||||
},
|
||||
|
||||
close() {
|
||||
const current = window.location.pathname;
|
||||
const newpath = removeLastDir(current);
|
||||
@@ -137,7 +167,7 @@ export default {
|
||||
<div style="margin-bottom: 15px; padding: 10px; background: #f5f5f5; border-radius: 4px;">
|
||||
<strong>Configuration:</strong><br/>
|
||||
OnlyOffice URL: ${this.onlyOfficeUrl}<br/>
|
||||
Internal URL: Check server logs<br/>
|
||||
Internal URL: ${this.getInternalUrlInfo().message}<br/>
|
||||
Base URL: ${baseURL}<br/>
|
||||
Source: ${this.source}<br/>
|
||||
Path: ${this.path}<br/>
|
||||
@@ -175,6 +205,7 @@ export default {
|
||||
|
||||
const filename = this.path.split('/').pop() || "";
|
||||
const isShare = getters.isShare();
|
||||
const internalUrlInfo = this.getInternalUrlInfo();
|
||||
|
||||
// Build config details if available
|
||||
let configDetailsHtml = "";
|
||||
@@ -196,9 +227,8 @@ export default {
|
||||
Callback URL: ${editor && editor.callbackUrl ? editor.callbackUrl.substring(0, 80) + '...' : 'N/A'}<br/>
|
||||
<br/>
|
||||
<strong>Network Flow:</strong><br/>
|
||||
Browser ↔ OnlyOffice: ${this.onlyOfficeUrl}<br/>
|
||||
Browser (${window.location.origin}) ↔ OnlyOffice: ${this.onlyOfficeUrl}<br/>
|
||||
OnlyOffice → FileBrowser: ${downloadDomain}<br/>
|
||||
OnlyOffice → FileBrowser: ${callbackDomain}<br/>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
@@ -234,7 +264,7 @@ export default {
|
||||
<div style="margin-bottom: 15px; padding: 10px; background: #f5f5f5; border-radius: 4px;">
|
||||
<strong>Basic Configuration:</strong><br/>
|
||||
OnlyOffice URL: ${this.onlyOfficeUrl}<br/>
|
||||
Internal URL: Check server logs<br/>
|
||||
Internal URL: ${internalUrlInfo.message}<br/>
|
||||
Base URL: ${baseURL}<br/>
|
||||
Source: ${this.source}<br/>
|
||||
Path: ${this.path}<br/>
|
||||
@@ -372,6 +402,9 @@ export default {
|
||||
errorMsg += "<strong>Error Code -4:</strong> Document download failed<br/>";
|
||||
errorMsg += "• Authentication may have expired<br/>";
|
||||
errorMsg += "• Check download URL accessibility<br/>";
|
||||
if (!this.getInternalUrlInfo().isSet) {
|
||||
errorMsg += "• <strong>Suggestion:</strong> consider adding `server.internalUrl` if your OnlyOffice service is on the same network as FileBrowser<br/>";
|
||||
}
|
||||
} else {
|
||||
errorMsg += `<strong>Error Code:</strong> ${errorInfo || 'Unknown error'}<br/>`;
|
||||
errorMsg += "• Check browser console for detailed error messages<br/>";
|
||||
|
||||
@@ -19,7 +19,7 @@ async function globalSetup() {
|
||||
await page.locator('button[aria-label="File-Actions"]').click();
|
||||
await page.locator('button[aria-label="Share"]').click();
|
||||
await page.locator('button[aria-label="Share-Confirm"]').click();
|
||||
await page.waitForResponse(response => response.url().includes('/api/share') && response.status() === 200);
|
||||
await page.waitForResponse(response => response.status() === 200);
|
||||
await expect(page.locator("div[aria-label='share-prompt'] .card-content table tbody tr:not(:has(th))")).toHaveCount(1);
|
||||
const shareHash = await page.locator("div[aria-label='share-prompt'] .card-content table tbody tr:not(:has(th)) td").first().textContent();
|
||||
if (!shareHash) {
|
||||
|
||||
Reference in new issue
Block a user