feat: open file original in a new tab via authenticated direct link
The file viewer's preview is now a real link (target=_blank) to the original, instead of fetching it into a blob. A navigation can't send the auth header, so the access token rides in the query — the auth middleware accepts ?access_token= as a fallback, but only for GET, so a crafted link can't drive a mutation. GetContent gains an ?inline=1 toggle (Content-Disposition: inline) so the tab views the original instead of downloading it; download stays the default. Documented in openapi.yaml; TestMediaQueryTokenAuth covers GET-with-query-token (200), missing token (401) and query-token rejected on a non-GET (401). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -762,6 +762,32 @@ func TestBulkTagAutoRule(t *testing.T) {
|
||||
assert.ElementsMatch(t, []string{"outdoor", "nature"}, names)
|
||||
}
|
||||
|
||||
// TestMediaQueryTokenAuth verifies the ?access_token= fallback: it authenticates
|
||||
// a GET (so media can be opened via a plain link/new tab) but is rejected for a
|
||||
// non-GET, and a missing token is still 401.
|
||||
func TestMediaQueryTokenAuth(t *testing.T) {
|
||||
if testing.Short() {
|
||||
t.Skip("skipping integration test in short mode")
|
||||
}
|
||||
|
||||
h := setupSuite(t)
|
||||
token := h.login("admin", "admin")
|
||||
file := h.uploadJPEG(token, "q.jpg")
|
||||
fileID := file["id"].(string)
|
||||
|
||||
// GET with token in the query, no Authorization header → 200.
|
||||
resp := h.do("GET", "/files/"+fileID+"/content?access_token="+token, nil, "", "")
|
||||
require.Equal(t, http.StatusOK, resp.StatusCode, resp.String())
|
||||
|
||||
// No token anywhere → 401.
|
||||
resp = h.do("GET", "/files/"+fileID+"/content", nil, "", "")
|
||||
require.Equal(t, http.StatusUnauthorized, resp.StatusCode)
|
||||
|
||||
// Query token must NOT authorize a state-changing (non-GET) request → 401.
|
||||
resp = h.do("DELETE", "/files/"+fileID+"?access_token="+token, nil, "", "")
|
||||
require.Equal(t, http.StatusUnauthorized, resp.StatusCode, resp.String())
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Security regression tests
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user