security sections are fully functional

This commit is contained in:
2026-05-07 15:06:45 +02:00
parent 5e60b814ed
commit 53aa5cbbf5
20 changed files with 946 additions and 41 deletions
+35 -11
View File
@@ -60,18 +60,41 @@ func (h *GitHTTPHandler) ServeGit(w http.ResponseWriter, r *http.Request) {
}
// Authenticate and enforce permission checks.
// Priority: user account → deploy key → anonymous (public repos only).
var authedUser string
user, authed := h.basicAuth(r)
if authed {
authedUser = user
// Push requires write or admin permission.
if service == "git-receive-pack" && !HasPermission(h.db, &repo, user, "write") {
http.Error(w, "forbidden: you do not have write access to this repository", http.StatusForbidden)
return
}
// Pull on a private repo requires at least read permission.
if repo.IsPrivate && !HasPermission(h.db, &repo, user, "read") {
http.Error(w, "forbidden: you do not have read access to this repository", http.StatusForbidden)
var authedReadOnly bool
if _, p, hasAuth := r.BasicAuth(); hasAuth {
if user, ok := h.basicAuth(r); ok {
authedUser = user
// User account: enforce member permissions.
if service == "git-receive-pack" && !HasPermission(h.db, &repo, user, "write") {
http.Error(w, "forbidden: you do not have write access to this repository", http.StatusForbidden)
return
}
if repo.IsPrivate && !HasPermission(h.db, &repo, user, "read") {
http.Error(w, "forbidden: you do not have read access to this repository", http.StatusForbidden)
return
}
} else if rdOnly, ok := AuthenticateDeployKey(h.db, repo.ID, p); ok {
// Deploy key: the password field carries the raw token; username is ignored.
authedUser = "deploy-key"
authedReadOnly = rdOnly
if service == "git-receive-pack" && rdOnly {
http.Error(w, "forbidden: this deploy key is read-only", http.StatusForbidden)
return
}
} else if _, repoID, hasWrite, ok := LookupAccessToken(h.db, p); ok && repoID == repo.ID {
// Access token used as git credential (username ignored, password = token).
authedUser = "access-token"
if service == "git-receive-pack" && !hasWrite {
http.Error(w, "forbidden: this access token has read-only scope", http.StatusForbidden)
return
}
} else {
// Credentials provided but invalid.
w.Header().Set("WWW-Authenticate", `Basic realm="ForgeBucket"`)
http.Error(w, "invalid credentials", http.StatusUnauthorized)
return
}
} else if service == "git-receive-pack" || repo.IsPrivate {
@@ -79,6 +102,7 @@ func (h *GitHTTPHandler) ServeGit(w http.ResponseWriter, r *http.Request) {
http.Error(w, "authentication required", http.StatusUnauthorized)
return
}
_ = authedReadOnly
// Build PATH_INFO: /{reponame}.git/{suffix}
// Strip the /{owner}/{repoGit} prefix from the raw URL path to get the suffix.