ikurotime / gitgud

public
main / internal/interface/web/git_handler.go
1.2 KB · Go Raw
 1package web
 2
 3import (
 4	"errors"
 5	"net/http"
 6	"strings"
 7
 8	"github.com/go-chi/chi"
 9
10	"gitgud/internal/domain"
11)
12
13func (h *Handlers) gitHTTP(w http.ResponseWriter, r *http.Request) {
14	owner := chi.URLParam(r, "owner")
15	repoName := strings.TrimSuffix(chi.URLParam(r, "repo"), ".git")
16
17	isPush := strings.HasSuffix(r.URL.Path, "git-receive-pack") ||
18		r.URL.Query().Get("service") == "git-receive-pack"
19
20	user := h.basicAuthUser(r)
21
22	allow, needAuth, remoteUser, err := h.gitAccess.Authorize(r.Context(), owner, repoName, isPush, user)
23	if needAuth {
24		requireBasicAuth(w)
25		return
26	}
27	if err != nil {
28		if errors.Is(err, domain.ErrPermission) {
29			http.Error(w, "forbidden", http.StatusForbidden)
30			return
31		}
32		http.NotFound(w, r)
33		return
34	}
35	if !allow {
36		http.NotFound(w, r)
37		return
38	}
39
40	h.gitBackend.Handler(remoteUser).ServeHTTP(w, r)
41}
42
43func (h *Handlers) basicAuthUser(r *http.Request) *domain.User {
44	username, password, ok := r.BasicAuth()
45	if !ok {
46		return nil
47	}
48	u, err := h.users.Authenticate(r.Context(), username, password)
49	if err != nil {
50		return nil
51	}
52	return u
53}
54
55func requireBasicAuth(w http.ResponseWriter) {
56	w.Header().Set("WWW-Authenticate", `Basic realm="gitgud"`)
57	http.Error(w, "authentication required", http.StatusUnauthorized)
58}