API keys for server scope: edges, server alerts and orgs can be scripted

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
VeillaxandClaude Sonnet 5.5 committed 2026-10-27 16:54:14 -06:00
1 parent 39659f0144
commit 1c2a5b71bd
6 files changed
+232 -9

No files matched your search

+17 -2
View File
@@ -54,6 +54,9 @@ func (s *Server) principalFrom(r *http.Request) *principal {
if k.ID == parts[1] && hmac.Equal([]byte(k.Hash), []byte(sha(parts[2]))) {
k.LastUsed = time.Now()
kc := *k
if k.OrgID == "" { // a server key acts as a server administrator
return &principal{Key: &kc, User: User{Email: "apikey:" + k.Name, ServerAdmin: true}}
}
return &principal{Key: &kc}
}
}
@@ -73,14 +76,23 @@ func (s *Server) withUser(fn func(http.ResponseWriter, *http.Request, *principal
}
}
// serverKey reports whether the caller authenticated with a server-level API key.
func (p *principal) serverKey() bool { return p.Key != nil && p.Key.OrgID == "" }
// withServerAdmin lets signed-in server administrators and server API keys through.
func (s *Server) withServerAdmin(fn func(http.ResponseWriter, *http.Request, *principal)) http.HandlerFunc {
return s.withUser(func(w http.ResponseWriter, r *http.Request, p *principal) {
return func(w http.ResponseWriter, r *http.Request) {
p := s.principalFrom(r)
if p == nil || (p.User.ID == "" && !p.serverKey()) {
fail(w, 401, errors.New("Sign in to continue."))
return
}
if !p.User.ServerAdmin {
fail(w, 403, errors.New("server administrators only"))
return
}
fn(w, r, p)
})
}
}
// orgCtx is the caller's standing inside one org.
@@ -107,6 +119,9 @@ func (s *Server) withOrg(needAdmin bool, fn func(http.ResponseWriter, *http.Requ
if org != nil {
c.Org = *org
switch {
case p.serverKey():
allowed, c.Admin = true, true
c.Actor = "apikey:" + p.Key.Name
case p.Key != nil:
allowed = p.Key.OrgID == org.ID
c.Admin = allowed