Sign in

Search issue titles and bodies, change requests and comments. Private repositories you cannot read are not included.

vole
Clone

Read only, no credentials:

https://rodent.software/git/vole.git

Write over SSH with a registered key:

git clone ssh://git@0.0.0.0:2222/vole.git

A free and open-source forge that lives in your Git repo.

Let instance admins read every repository

381d6aac38ab785d879fa82a6b8397ce6f543bab · Keenan Nemetz · 14d ago · parent 074ae160

Let instance admins read every repository

An instance administrator can already rewrite any repository's ACL, so hiding its content only hides what they govern. Raise them to at least read in the web and SSH paths, preserving any higher explicit role, and enforce the read rule on SSH upload-pack, where any authenticated key could previously clone a private repository by name. Anonymous HTTP clone still answers 404 because it carries no identity.

Group the admin surface into Repositories and Users tabs with a shared header, and teach Page.Section to mark the active tab.

server/admin_web_test.go +37

@@ -3,6 +3,7 @@ package server_test
3 3 import (
4 4 "net/url"
5 5 "os"
6 "path/filepath"
6 7 "strings"
7 8 "testing"
8 9 )
@@ -31,6 +32,9 @@ func TestAdminAccessEditor(t *testing.T) {
31 32 if resp.StatusCode != 200 {
32 33 t.Fatalf("access page = %d:\n%s", resp.StatusCode, body)
33 34 }
35 if !strings.Contains(body, `class="admin-tabs"`) || !strings.Contains(body, `href="/admin" aria-current="page"`) {
36 t.Fatalf("access page is missing the active admin tab:\n%s", body)
37 }
34 38 for _, want := range []string{"Default role", "Approvals required", "wilbur", "Runner"} {
35 39 if !strings.Contains(body, want) {
36 40 t.Fatalf("access page does not show %q:\n%s", want, body)
@@ -116,6 +120,39 @@ func TestAdminAccessEditor(t *testing.T) {
116 120 }
117 121 }
118 122
123 func TestInstanceAdminCanBrowsePrivateRepoWithoutACLEntry(t *testing.T) {
124 t.Parallel()
125 f := browserFixture(t)
126
127 pub, _ := keypair(t, filepath.Join(f.cfg.DataDir, "id_operator"))
128 op, err := f.srv.Identity.Create("operator", pub, "test")
129 if err != nil {
130 t.Fatal(err)
131 }
132
133 // The operator is not in the repository ACL, so before the instance-admin
134 // grant the repository is absent, exactly as it is for any other stranger.
135 _, cookie := f.browserSession(t, op.Name)
136 if resp, _ := f.browserGet(t, "/r/"+f.repo, cookie); resp.StatusCode != 404 {
137 t.Fatalf("non-admin without a role = %d, want 404", resp.StatusCode)
138 }
139
140 if _, err := f.srv.Identity.SetAdmin(op.Name, true, "test"); err != nil {
141 t.Fatal(err)
142 }
143 sess, cookie := f.browserSession(t, op.Name)
144 if sess == nil {
145 t.Fatal("no session")
146 }
147 resp, body := f.browserGet(t, "/r/"+f.repo, cookie)
148 if resp.StatusCode != 200 {
149 t.Fatalf("instance admin without a role = %d, want 200:\n%s", resp.StatusCode, body)
150 }
151 if !strings.Contains(body, f.repo) {
152 t.Fatalf("repository page does not name %q:\n%s", f.repo, body)
153 }
154 }
155
119 156 func TestAdminAccessRequiresInstanceAdmin(t *testing.T) {
120 157 t.Parallel()
121 158 f := browserFixture(t)