marky

Lightweight bookmarking + plaintext archive
Log | Files | Refs | README | LICENSE

commit 63f80483bda23dccd216fc52115244e2915f4b46
parent 34edc2496071e3fde781072bbc97f00ec9f5de58
Author: David Eisinger <[email protected]>
Date:   Thu,  9 Oct 2025 14:20:46 -0400

Get rid of legacy username

Diffstat:
Minternal/api.go | 78++++++++++++++++++------------------------------------------------------------
Minternal/user_route_test.go | 24+++++++++++++++---------
2 files changed, 33 insertions(+), 69 deletions(-)

diff --git a/internal/api.go b/internal/api.go @@ -367,13 +367,18 @@ func NewHandlerWithConfig(db *DB, cfg HandlerConfig) (http.Handler, error) { return } } - if p != "" { - // If the path is a single segment ending with a trailing dot, treat it - // as an invalid username route and return 404. - if !strings.Contains(p, "/") && strings.HasSuffix(p, ".") { - http.NotFound(w, r) - return - } + if p != "" { + // Only allow static/page handling for GET/HEAD; other methods 404 here + if r.Method != http.MethodGet && r.Method != http.MethodHead { + http.NotFound(w, r) + return + } + // If the path is a single segment ending with a trailing dot, treat it + // as an invalid username route and return 404. + if !strings.Contains(p, "/") && strings.HasSuffix(p, ".") { + http.NotFound(w, r) + return + } // New user page route: /u:{username} if strings.HasPrefix(p, "u:") { uname := strings.TrimPrefix(p, "u:") @@ -471,62 +476,15 @@ func NewHandlerWithConfig(db *DB, cfg HandlerConfig) (http.Handler, error) { return } } - } - // Legacy username route: "/{username}" → serve user page when user exists - if !strings.Contains(p, "/") && !strings.Contains(p, ".") { - if u, err := db.GetUserByUsername(r.Context(), p); err == nil && u != nil { - if html, err := RenderPage("user.html", cfg); err == nil { - // Initial embed for legacy route - if isOwnerAuthorized(r, u, db) { - items, err := db.ListBookmarks(r.Context(), u.ID, 50, 0) - if err == nil { - resp := make([]bookmarkResponse, 0, len(items)) - for i := range items { - resp = append(resp, toRespWithArchive(r.Context(), db, &items[i])) - } - if b, err := json.Marshal(resp); err == nil { - inject := []byte("<script>window.MARKY_INITIAL={view:'self',user:" + strconv.Quote(u.Username) + ",results:" + string(b) + "}</script>\n") - marker := []byte("<script src=\"/app.js\"></script>") - if i := bytes.Index(html, marker); i >= 0 { - out := make([]byte, 0, len(html)+len(inject)) - out = append(out, html[:i]...) - out = append(out, inject...) - out = append(out, html[i:]...) - html = out - } - } - } - } else { - items, err := db.ListPublicBookmarks(r.Context(), u.ID, 50, 0) - if err == nil { - resp := make([]bookmarkResponse, 0, len(items)) - for i := range items { - resp = append(resp, toRespWithArchive(r.Context(), db, &items[i])) - } - if b, err := json.Marshal(resp); err == nil { - inject := []byte("<script>window.MARKY_INITIAL={view:'public',user:" + strconv.Quote(u.Username) + ",results:" + string(b) + "}</script>\n") - marker := []byte("<script src=\"/app.js\"></script>") - if i := bytes.Index(html, marker); i >= 0 { - out := make([]byte, 0, len(html)+len(inject)) - out = append(out, html[:i]...) - out = append(out, inject...) - out = append(out, html[i:]...) - html = out - } - } - } - } - w.Header().Set("Content-Type", "text/html; charset=utf-8") - _, _ = w.Write(html) - return - } - } + } + // Legacy username route removed: any non-file single segment (not feeds) 404s + if !strings.Contains(p, "/") && !strings.Contains(p, ".") && !strings.HasPrefix(p, "u:") { http.NotFound(w, r) return } - } - static.ServeHTTP(w, r) - }) + } + static.ServeHTTP(w, r) + }) // Shared handler for JSON and RSS bookmarksHandler := func(w http.ResponseWriter, r *http.Request) { diff --git a/internal/user_route_test.go b/internal/user_route_test.go @@ -26,13 +26,19 @@ func TestUsernameRoute404WhenMissing(t *testing.T) { t.Fatalf("expected 404 for /nouser, got %d", resp.StatusCode) } - // Create a user and verify /alice returns 200 (serves SPA index) - _, err = db.CreateUser(t.Context(), "alice", "pw") - if err != nil { - t.Fatalf("create user: %v", err) - } - resp2, _ := http.Get(srv.URL + "/alice") - if resp2.StatusCode != http.StatusOK { - t.Fatalf("expected 200 for /alice, got %d", resp2.StatusCode) - } + // Create a user + _, err = db.CreateUser(t.Context(), "alice", "pw") + if err != nil { + t.Fatalf("create user: %v", err) + } + // Legacy /{username} route removed: should 404 + resp2, _ := http.Get(srv.URL + "/alice") + if resp2.StatusCode != http.StatusNotFound { + t.Fatalf("expected 404 for /alice, got %d", resp2.StatusCode) + } + // New route /u:{username} should serve the page + resp3, _ := http.Get(srv.URL + "/u:alice") + if resp3.StatusCode != http.StatusOK { + t.Fatalf("expected 200 for /u:alice, got %d", resp3.StatusCode) + } }