diff --git a/frontend/src/components/files/ListingItem.vue b/frontend/src/components/files/ListingItem.vue index 48afee03..337a2d55 100644 --- a/frontend/src/components/files/ListingItem.vue +++ b/frontend/src/components/files/ListingItem.vue @@ -94,7 +94,7 @@ export default { // reload the image when the file is replaced const key = Date.parse(this.modified); - return `${baseURL}/api/preview/thumb/${path}?auth=${this.jwt}&inline=true&k=${key}`; + return `${baseURL}/api/preview/thumb/${path}?k=${key}&inline=true`; }, isThumbsEnabled() { return enableThumbs; diff --git a/frontend/src/utils/auth.js b/frontend/src/utils/auth.js index c174d772..31cb57c4 100644 --- a/frontend/src/utils/auth.js +++ b/frontend/src/utils/auth.js @@ -12,6 +12,8 @@ export function parseToken(token) { const data = JSON.parse(Base64.decode(parts[1])); + document.cookie = `auth=${token}; path=/`; + localStorage.setItem("jwt", token); store.commit("setJWT", token); store.commit("setUser", data.user); @@ -81,6 +83,8 @@ export async function signup(username, password) { } export function logout() { + document.cookie = "auth=; expires=Thu, 01 Jan 1970 00:00:01 GMT; path=/"; + store.commit("setJWT", ""); store.commit("setUser", null); localStorage.setItem("jwt", null); diff --git a/frontend/src/views/files/Listing.vue b/frontend/src/views/files/Listing.vue index e3c8c253..23f6afa5 100644 --- a/frontend/src/views/files/Listing.vue +++ b/frontend/src/views/files/Listing.vue @@ -414,7 +414,7 @@ export default { window.removeEventListener("scroll", this.scrollEvent); window.removeEventListener("resize", this.windowsResize); - if (!this.user.perm.create) return; + if (this.user && !this.user.perm.create) return; document.removeEventListener("dragover", this.preventDefault); document.removeEventListener("dragenter", this.dragEnter); document.removeEventListener("dragleave", this.dragLeave); diff --git a/frontend/src/views/files/Preview.vue b/frontend/src/views/files/Preview.vue index 73600567..3fb23a5b 100644 --- a/frontend/src/views/files/Preview.vue +++ b/frontend/src/views/files/Preview.vue @@ -175,11 +175,9 @@ export default { if (this.req.type === "image" && !this.fullSize) { return `${baseURL}/api/preview/big${url.encodePath( this.req.path - )}?auth=${this.jwt}&k=${key}`; + )}?k=${key}`; } - return `${baseURL}/api/raw${url.encodePath(this.req.path)}?auth=${ - this.jwt - }&k=${key}`; + return `${baseURL}/api/raw${url.encodePath(this.req.path)}?k=${key}`; }, raw() { return `${this.previewUrl}&inline=true`; @@ -257,7 +255,7 @@ export default { if (this.req.subtitles) { this.subtitles = this.req.subtitles.map( - (sub) => `${baseURL}/api/raw${sub}?auth=${this.jwt}&inline=true` + (sub) => `${baseURL}/api/raw${sub}?inline=true` ); } diff --git a/http/auth.go b/http/auth.go index c73897c2..b90f926f 100644 --- a/http/auth.go +++ b/http/auth.go @@ -48,11 +48,16 @@ func (e extractor) ExtractToken(r *http.Request) (string, error) { } auth := r.URL.Query().Get("auth") - if auth == "" { - return "", request.ErrNoTokenInRequest + if auth != "" && strings.Count(auth, ".") == 2 { + return auth, nil } - return auth, nil + cookie, _ := r.Cookie("auth") + if cookie != nil && strings.Count(cookie.Value, ".") == 2 { + return cookie.Value, nil + } + + return "", request.ErrNoTokenInRequest } func withUser(fn handleFunc) handleFunc { diff --git a/http/data.go b/http/data.go index fd24f066..84c2ef41 100644 --- a/http/data.go +++ b/http/data.go @@ -49,7 +49,7 @@ func (d *data) Check(path string) bool { func handle(fn handleFunc, prefix string, store *storage.Storage, server *settings.Server) http.Handler { handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.Header().Set("Cache-Control", "no-cache") + w.Header().Set("Cache-Control", "no-cache, no-store, must-revalidate") settings, err := store.Settings.Get() if err != nil { diff --git a/http/preview.go b/http/preview.go index 562562ff..b2a4bdb1 100644 --- a/http/preview.go +++ b/http/preview.go @@ -79,6 +79,11 @@ func handleImagePreview(w http.ResponseWriter, r *http.Request, imgSvc ImgServic return errToStatus(err), err } + isFresh := checkEtag(w, r, file.ModTime.Unix(), file.Size) + if isFresh { + return http.StatusNotModified, nil + } + cacheKey := previewCacheKey(file.Path, file.ModTime.Unix(), previewSize) cachedFile, ok, err := fileCache.Load(r.Context(), cacheKey) if err != nil { diff --git a/http/raw.go b/http/raw.go index b9ac8159..09ac329c 100644 --- a/http/raw.go +++ b/http/raw.go @@ -204,6 +204,11 @@ func rawDirHandler(w http.ResponseWriter, r *http.Request, d *data, file *files. } func rawFileHandler(w http.ResponseWriter, r *http.Request, file *files.FileInfo) (int, error) { + isFresh := checkEtag(w, r, file.ModTime.Unix(), file.Size) + if isFresh { + return http.StatusNotModified, nil + } + fd, err := file.Fs.Open(file.Path) if err != nil { return http.StatusInternalServerError, err diff --git a/http/static.go b/http/static.go index 3febd656..8fad9815 100644 --- a/http/static.go +++ b/http/static.go @@ -2,6 +2,7 @@ package http import ( "encoding/json" + "fmt" "io/fs" "log" "net/http" @@ -109,6 +110,9 @@ func getStaticHandlers(store *storage.Storage, server *settings.Server, assetsFs return http.StatusNotFound, nil } + const maxAge = 86400 // 1 day + w.Header().Set("Cache-Control", fmt.Sprintf("public, max-age=%v", maxAge)) + if d.settings.Branding.Files != "" { if strings.HasPrefix(r.URL.Path, "img/") { fPath := filepath.Join(d.settings.Branding.Files, r.URL.Path) diff --git a/http/utils.go b/http/utils.go index c1c3fa65..48ae2f40 100644 --- a/http/utils.go +++ b/http/utils.go @@ -3,6 +3,7 @@ package http import ( "encoding/json" "errors" + "fmt" "net/http" "net/url" "os" @@ -66,3 +67,11 @@ func stripPrefix(prefix string, h http.Handler) http.Handler { h.ServeHTTP(w, r2) }) } + +func checkEtag(w http.ResponseWriter, r *http.Request, fTime, fSize int64) bool { + etag := fmt.Sprintf("%x%x", fTime, fSize) + w.Header().Set("Cache-Control", "private") + w.Header().Set("Etag", etag) + + return r.Header.Get("If-None-Match") == etag +}