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/vole.git

Write over SSH with a registered key:

git clone ssh://git@rodent.software:2222/vole.git

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

Add the instance access editor and repository danger zone

2973f7274b3c569de6018239ac8c90df98c38a1b · Keenan Nemetz · 15d ago · parent 1948358f

Add the instance access editor and repository danger zone

Instance admins get /admin: a repository list and a per-repository ACL editor for
default role, per-account roles, protected branches, approvals, checks, and
runners. The editor reads repositories directly instead of through the read
rule, because an instance admin may not have a role in the repository they are
administering. Everything else still hides behind a 404.

Repository admins get rename and delete on the settings page behind typed
confirmation. Both go through the instance operations that also move the index,
queue, LFS namespace, and locks, carry CSRF, and are audited.

server/server.go +7

@@ -112,6 +112,8 @@ func New(cfg *config.Config, binPath string, log *slog.Logger) (*Server, error)
112 112 LFS: inst.LFS, Locks: inst.Locks, Proxy: proxy, SSH: ssh, Web: wp, Log: log,
113 113 }
114 114 wp.AllowCI = s.allowContributorCI
115 wp.RenameRepo = inst.RenameRepo
116 wp.DeleteRepo = inst.DeleteRepo
115 117 // Sites are opt-in: without a pages domain there is no host to serve them on,
116 118 // and an instance that never wanted them pays no processes for the idea.
117 119 if cfg.PagesDomain != "" {
@@ -163,6 +165,9 @@ func (s *Server) routes() *http.ServeMux {
163 165 mux.HandleFunc("POST /account/passkeys/finish", w.AddPasskeyFinish)
164 166 mux.HandleFunc("GET /auth.js", w.AuthJS)
165 167 mux.HandleFunc("GET /runners", w.RunnersPage)
168 mux.HandleFunc("GET /admin", w.AdminPage)
169 mux.HandleFunc("GET /admin/repos/{name}/access", w.AdminAccessPage)
170 mux.HandleFunc("POST /admin/repos/{name}/access", w.SaveAdminAccess)
166 171 mux.HandleFunc("GET /r/{name}", w.Overview)
167 172 mux.HandleFunc("GET /r/{name}/activity", w.Activity)
168 173 mux.HandleFunc("GET /r/{name}/code", w.Code)
@@ -201,6 +206,8 @@ func (s *Server) routes() *http.ServeMux {
201 206 mux.HandleFunc("GET /r/{name}/locks", w.LocksPage)
202 207 mux.HandleFunc("GET /r/{name}/settings", w.SettingsPage)
203 208 mux.HandleFunc("POST /r/{name}/settings", w.SaveSettings)
209 mux.HandleFunc("POST /r/{name}/settings/rename", w.RenameRepository)
210 mux.HandleFunc("POST /r/{name}/settings/delete", w.DeleteRepository)
204 211 mux.HandleFunc("GET /r/{name}/releases", w.Releases)
205 212 mux.HandleFunc("GET /r/{name}/releases/{tag...}", w.ReleaseView)
206 213 mux.HandleFunc("GET /r/{name}/releases/{tag}/archive.tar", w.ReleaseTar)