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.

Allow opt-in open registration

f920a9f12c4ff12e4f47497a084f0201d8914181 · Keenan Nemetz · 15d ago · parent 6c84d387

Allow opt-in open registration

Add open_registration, off by default and effective only with an HTTPS public_url. /register creates an account and its first passkey without an administrator; the account row is written only after the WebAuthn ceremony succeeds, so an abandoned registration reserves no name.

New accounts start with no repository-specific ACL entries. Add self-service SSH key management on the Account page so a registered contributor can add the key needed to push to their contributor namespace.

Cover registration enablement, name validation, deferred account creation, and self-service key add/remove in tests, and document the policy.

server/server.go +7

@@ -99,6 +99,8 @@ func New(cfg *config.Config, binPath string, log *slog.Logger) (*Server, error)
99 99 wp.Logger = func(format string, args ...any) { log.Warn(fmt.Sprintf(format, args...)) }
100 100 if wp.Auth != nil && !wp.Auth.Enabled() {
101 101 log.Info("browser login disabled", "reason", wp.Auth.Disabled)
102 } else if cfg.OpenRegistration {
103 log.Info("open registration enabled", "url", cfg.BaseURL()+"/register")
102 104 }
103 105
104 106 s := &Server{
@@ -139,6 +141,9 @@ func (s *Server) routes() *http.ServeMux {
139 141
140 142 mux.HandleFunc("GET /{$}", w.IndexPage)
141 143 mux.HandleFunc("GET /login", w.LoginPage)
144 mux.HandleFunc("GET /register", w.RegisterPage)
145 mux.HandleFunc("POST /auth/register/begin", w.RegisterBegin)
146 mux.HandleFunc("POST /auth/register/finish", w.RegisterFinish)
142 147 mux.HandleFunc("POST /auth/login/begin", w.LoginBegin)
143 148 mux.HandleFunc("POST /auth/login/finish", w.LoginFinish)
144 149 mux.HandleFunc("POST /logout", w.Logout)
@@ -146,6 +151,8 @@ func (s *Server) routes() *http.ServeMux {
146 151 mux.HandleFunc("POST /auth/invite/begin", w.InviteBegin)
147 152 mux.HandleFunc("POST /auth/invite/finish", w.InviteFinish)
148 153 mux.HandleFunc("GET /account", w.AccountPage)
154 mux.HandleFunc("POST /account/keys", w.AddAccountKey)
155 mux.HandleFunc("POST /account/keys/remove", w.RemoveAccountKey)
149 156 mux.HandleFunc("POST /account/passkeys/begin", w.AddPasskeyBegin)
150 157 mux.HandleFunc("POST /account/passkeys/finish", w.AddPasskeyFinish)
151 158 mux.HandleFunc("GET /auth.js", w.AuthJS)