Allowlist.Check now takes ctx: when the caller authenticated with their own Gitea PAT (pass-through, v0.12.0), it skips the static GITEA_MCP_ALLOWED_OWNERS check entirely — Gitea's own permission model already gates that caller's access more precisely than a coarse owner-name list can. The static list still applies unchanged for the shared static-token/JWT path, where it's the only defense against the service token's blast radius. Mechanical: every tool call site already had ctx in scope, so this is a signature-only change at 41 call sites, no other tool behavior changes. Closes the "Deferred" item from #59. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
38 lines
883 B
Go
38 lines
883 B
Go
package allowlist
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
|
|
"git.d-ma.be/mathias/gitea-mcp/internal/gitea"
|
|
)
|
|
|
|
type Allowlist struct {
|
|
owners map[string]struct{}
|
|
}
|
|
|
|
func New(owners []string) *Allowlist {
|
|
m := make(map[string]struct{}, len(owners))
|
|
for _, o := range owners {
|
|
m[o] = struct{}{}
|
|
}
|
|
return &Allowlist{owners: m}
|
|
}
|
|
|
|
// Check gates owner access to the static list — except for a caller
|
|
// authenticated with their own Gitea PAT (pass-through, gitea-mcp#59), whose
|
|
// access Gitea's own permission model already gates more precisely than a
|
|
// coarse owner name list ever could.
|
|
func (a *Allowlist) Check(ctx context.Context, owner string) error {
|
|
if owner == "" {
|
|
return fmt.Errorf("owner required")
|
|
}
|
|
if _, ok := gitea.TokenFromContext(ctx); ok {
|
|
return nil
|
|
}
|
|
if _, ok := a.owners[owner]; !ok {
|
|
return fmt.Errorf("owner %q not in allowlist", owner)
|
|
}
|
|
return nil
|
|
}
|