From 52861bff24bbd0e9f3df84c1e781d8eb6a179844 Mon Sep 17 00:00:00 2001 From: kiwec Date: Tue, 10 Dec 2024 11:30:27 +0100 Subject: [PATCH] Allow anonymous Git LFS access for public repositories --- internal/route/lfs/route.go | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/internal/route/lfs/route.go b/internal/route/lfs/route.go index 5ed7a6377..96f1b9a79 100644 --- a/internal/route/lfs/route.go +++ b/internal/route/lfs/route.go @@ -48,17 +48,13 @@ func RegisterRoutes(r *macaron.Router) { // authenticate tries to authenticate user via HTTP Basic Auth. It first tries to authenticate // as plain username and password, then use username as access token if previous step failed. func authenticate(store Store) macaron.Handler { - askCredentials := func(w http.ResponseWriter) { - w.Header().Set("Lfs-Authenticate", `Basic realm="Git LFS"`) - responseJSON(w, http.StatusUnauthorized, responseError{ - Message: "Credentials needed", - }) - } - return func(c *macaron.Context) { + // dummy user to allow for unauthenticated read requests to public repositories + anonUser := database.User{ID: 0, Name: "Anonymous"} + username, password := authutil.DecodeBasic(c.Req.Header) if username == "" { - askCredentials(c.Resp) + c.Map(&anonUser) return } @@ -87,7 +83,7 @@ func authenticate(store Store) macaron.Handler { user, err = context.AuthenticateByToken(store, c.Req.Context(), password) if err != nil { if database.IsErrAccessTokenNotExist(err) { - askCredentials(c.Resp) + c.Map(&anonUser) } else { c.Status(http.StatusInternalServerError) log.Error("Failed to authenticate by access token via password: %v", err) @@ -137,6 +133,14 @@ func authorize(store Store, mode database.AccessMode) macaron.Handler { Private: repo.IsPrivate, }, ) { + if actor.ID == 0 { + c.Resp.Header().Set("Lfs-Authenticate", `Basic realm="Git LFS"`) + responseJSON(c.Resp, http.StatusUnauthorized, responseError{ + Message: "Credentials needed", + }) + return + } + c.Status(http.StatusNotFound) return }