mirror of
https://github.com/lukaszraczylo/traefik-llmgateway.git
synced 2026-10-15 05:29:28 +00:00
feat(admin): expose group provider/model access
GET /admin/api/usage's group rows now carry the group's configured Providers/Models/MCPServers/Agents (GroupConfig, llmgateway.go), echoed exactly as configured -- never resolved/expanded to the full catalog server-side. Empty/unset stays omitted (omitempty), matching GroupConfig's own JSON convention and group.allowsX's empty-means-all semantics (auth.go): the dashboard can tell 'restricted to these N' apart from 'unrestricted' without the payload growing with catalog size. groupSummary (auth.go) gains providers/models/mcpServers/agents, carried through from authStore.snapshot unchanged. adminUsageEntryView (admin.go) gains the matching JSON fields, populated only for group entries -- a user or the total scope row never carries them, mirroring GroupName's own user-only convention. The Usage view's group accordion (webui/UsageView.vue) renders an Access block above the existing stat grid: Badge chips for explicit providers, ModelChip for explicit models (both shadcn/existing components, no hand-rolled chips), or muted 'All providers'/'All models' text when unrestricted. Display-only this round -- not wired into the user/group search filter. types/api.ts's AdminUsageEntryView mirrors the new optional fields. Tests: admin_test.go's new table-driven TestAdminUsage_GroupAccessLists covers a restricted group's exact lists, an unrestricted group's empty/omitted lists, and that a user/total row never carries them.
This commit is contained in:
@@ -415,11 +415,25 @@ func (g *Gateway) serveAdminOverview(w http.ResponseWriter) {
|
||||
// tokensPerDay/tokensPerMonth pair (v0.2 data-layer task, tokens-in/
|
||||
// tokens-out split) — a client wanting the combined total sums the two
|
||||
// itself.
|
||||
//
|
||||
// Providers/Models/MCPServers/Agents (group-access-display task) are set
|
||||
// only for a group entry — a user or the total entry never populates them,
|
||||
// same convention as GroupName's own "user-only" field above, mirrored.
|
||||
// Each carries the group's GroupConfig list exactly as configured: omitted
|
||||
// (nil) means every provider/model/MCP server/agent is allowed
|
||||
// (group.allowsX's own empty-list-matches-anything contract, auth.go) —
|
||||
// this is never resolved/expanded to the full catalog here, so the
|
||||
// dashboard can tell "explicitly restricted to these N" apart from
|
||||
// "unrestricted" without the payload growing with catalog size.
|
||||
type adminUsageEntryView struct {
|
||||
Limits *LimitsConfig `json:"limits,omitempty"`
|
||||
Kind string `json:"kind"`
|
||||
ID string `json:"id"`
|
||||
GroupName string `json:"groupName,omitempty"`
|
||||
Providers []string `json:"providers,omitempty"`
|
||||
Models []string `json:"models,omitempty"`
|
||||
MCPServers []string `json:"mcpServers,omitempty"`
|
||||
Agents []string `json:"agents,omitempty"`
|
||||
RequestsPerMinute int64 `json:"requestsPerMinute"`
|
||||
RequestsPerDay int64 `json:"requestsPerDay"`
|
||||
TokensInPerDay int64 `json:"tokensInPerDay"`
|
||||
@@ -500,6 +514,10 @@ func (g *Gateway) buildAdminUsage() adminUsageResponse {
|
||||
groups := make([]adminUsageEntryView, len(groupUsage))
|
||||
for i, su := range groupUsage {
|
||||
groups[i] = usageEntryView(su, groupSummaries[i].limits)
|
||||
groups[i].Providers = groupSummaries[i].providers
|
||||
groups[i].Models = groupSummaries[i].models
|
||||
groups[i].MCPServers = groupSummaries[i].mcpServers
|
||||
groups[i].Agents = groupSummaries[i].agents
|
||||
}
|
||||
total := usageEntryView(totalUsage, nil)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user