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.

Identify accounts by their registered name

62576fa8157d431dcf2d360f3ebe481de77bda03 · Keenan Nemetz · 14d ago · parent 642e5994

Identify accounts by their registered name

Drop the internal account id and display name. Users, keys, passkeys,
invites, sessions, ACL entries, approvals, locks and CI records now all
use the registered name as the single identity.

The roster migrates in place: old id-keyed tables are rebuilt around the
name, and access-rule/lock references are rewritten through the same
mapping. Display-name editing and whoami --id are removed.

server/ssh/runner.go +15−19

@@ -122,11 +122,10 @@ type runnerReply struct {
122 122 Run *runnerJob `json:"run,omitempty"`
123 123 OK bool `json:"ok"`
124 124 Lease int `json:"lease,omitempty"`
125 // Who am I: the account this channel authenticated as. A runner answers "ping" with
126 // this so it can say whose results it will be reporting, and so a --repos filter can
127 // be checked against what the account may run.
128 Account string `json:"account,omitempty"`
129 Name string `json:"name,omitempty"`
125 // Who am I: the account name this channel authenticated as. A runner answers
126 // "ping" with this so it can say whose results it will be reporting, and so a
127 // --repos filter can be checked against what the account may run.
128 Name string `json:"name,omitempty"`
130 129 // Repos are the repositories this account may run jobs for, sent with "ping" so
131 130 // a runner started with --repos can find out at startup that its filter matches
132 131 // nothing — a typo it would otherwise discover as a permanently idle runner —
@@ -135,7 +134,7 @@ type runnerReply struct {
135 134 }
136 135
137 136 // serveRunner answers one runner session until it disconnects.
138 func (s *Server) serveRunner(ch xssh.Channel, user, accountID string) {
137 func (s *Server) serveRunner(ch xssh.Channel, user string) {
139 138 defer ch.Close()
140 139 cfg := s.cfg
141 140 if cfg.Runs == nil {
@@ -144,7 +143,7 @@ func (s *Server) serveRunner(ch xssh.Channel, user, accountID string) {
144 143 }
145 144 dec := json.NewDecoder(ch)
146 145 enc := json.NewEncoder(ch)
147 owner := accountID
146 owner := user
148 147 // Presence is one row per channel: a pool of three runners on one account is
149 148 // three rows, and the row goes away when the channel does. Nothing else records
150 149 // that a runner exists, so this is what the runners page shows.
@@ -153,7 +152,7 @@ func (s *Server) serveRunner(ch xssh.Channel, user, accountID string) {
153 152 _ = enc.Encode(runnerReply{Op: "error", Error: err.Error()})
154 153 return
155 154 }
156 if err := cfg.Runs.TouchSession(sessionID, accountID, nil, time.Now().UTC()); err != nil {
155 if err := cfg.Runs.TouchSession(sessionID, user, nil, time.Now().UTC()); err != nil {
157 156 cfg.Log.Warn("runner: cannot record the session", "user", user, "err", err)
158 157 }
159 158 defer cfg.Runs.DropSession(sessionID)
@@ -177,7 +176,7 @@ func (s *Server) serveRunner(ch xssh.Channel, user, accountID string) {
177 176 // on: running a job executes that repository's code, which is a bigger
178 177 // power than writing to it.
179 178 if reposAt.IsZero() || now.Sub(reposAt) > eligibleFor {
180 list, err := s.runnableRepos(accountID)
179 list, err := s.runnableRepos(user)
181 180 if err != nil {
182 181 _ = enc.Encode(runnerReply{Op: "lease", Error: err.Error()})
183 182 continue
@@ -223,7 +222,7 @@ func (s *Server) serveRunner(ch xssh.Channel, user, accountID string) {
223 222 // say "waiting for work" instead of showing a runner that vanished. The
224 223 // labels ride along, because a runner waiting for the wrong kind of work
225 224 // is exactly what this row is for.
226 _ = cfg.Runs.TouchSession(sessionID, accountID, req.Labels, time.Now().UTC())
225 _ = cfg.Runs.TouchSession(sessionID, user, req.Labels, time.Now().UTC())
227 226 _ = enc.Encode(runnerReply{Op: "lease", OK: true})
228 227 continue
229 228 }
@@ -254,7 +253,7 @@ func (s *Server) serveRunner(ch xssh.Channel, user, accountID string) {
254 253 case "heartbeat":
255 254 // Liveness only: the lease is what a heartbeat buys. Presence is refreshed
256 255 // here too, so a long build does not make its runner look gone.
257 _ = cfg.Runs.TouchSession(sessionID, accountID, nil, time.Now().UTC())
256 _ = cfg.Runs.TouchSession(sessionID, user, nil, time.Now().UTC())
258 257 ok, err := cfg.Runs.Heartbeat(req.Run, owner, cfg.Lease, time.Now().UTC())
259 258 if err != nil {
260 259 _ = enc.Encode(runnerReply{Op: "heartbeat", Error: err.Error()})
@@ -312,7 +311,7 @@ func (s *Server) serveRunner(ch xssh.Channel, user, accountID string) {
312 311 "the record for %s is attempt %d but this runner holds attempt %d",
313 312 run.ID, rec.Attempt, run.Attempts)})
314 313 continue
315 case rec.Signer != accountID:
314 case rec.Signer != user:
316 315 _ = enc.Encode(runnerReply{Op: "finish", Error: fmt.Sprintf(
317 316 "the record for %s was reported by another account; %s cannot finish it",
318 317 run.ID, user)})
@@ -374,13 +373,10 @@ func (s *Server) serveRunner(ch xssh.Channel, user, accountID string) {
374 373 _ = enc.Encode(runnerReply{Op: "finish", OK: ok})
375 374
376 375 case "ping":
377 reply := runnerReply{Op: "ping", OK: true, Account: accountID}
378 if acct, aerr := cfg.Identity.Find(accountID); aerr == nil && acct != nil {
379 reply.Name = acct.Name
380 }
376 reply := runnerReply{Op: "ping", OK: true, Name: user}
381 377 // What this account may run, so a runner started with --repos can say at
382 378 // startup that its filter matches nothing rather than idling in silence.
383 if granted, gerr := s.runnableRepos(accountID); gerr == nil {
379 if granted, gerr := s.runnableRepos(user); gerr == nil {
384 380 reply.Repos = granted
385 381 } else {
386 382 cfg.Log.Warn("runner: cannot list runnable repositories", "user", user, "err", gerr)
@@ -394,7 +390,7 @@ func (s *Server) serveRunner(ch xssh.Channel, user, accountID string) {
394 390 }
395 391
396 392 // runnableRepos lists the repositories this account may execute jobs for.
397 func (s *Server) runnableRepos(accountID string) ([]string, error) {
393 func (s *Server) runnableRepos(name string) ([]string, error) {
398 394 repos, err := s.cfg.Repos.List()
399 395 if err != nil {
400 396 return nil, err
@@ -409,7 +405,7 @@ func (s *Server) runnableRepos(accountID string) ([]string, error) {
409 405 // job executes that repository's code, and a result from an account the
410 406 // repository will not count is only worth refusing here rather than after
411 407 // the build.
412 if a.CanReport(accountID) {
408 if a.CanReport(name) {
413 409 out = append(out, m.Name)
414 410 }
415 411 }