chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,129 @@
|
||||
package scopes
|
||||
|
||||
import "github.com/github/github-mcp-server/pkg/inventory"
|
||||
|
||||
// ToolScopeMap maps tool names to their scope requirements.
|
||||
type ToolScopeMap map[string]*ToolScopeInfo
|
||||
|
||||
// ToolScopeInfo contains scope information for a single tool.
|
||||
type ToolScopeInfo struct {
|
||||
// RequiredScopes contains the scopes that are directly required by this tool.
|
||||
RequiredScopes []string
|
||||
|
||||
// AcceptedScopes contains all scopes that satisfy the requirements (including parent scopes).
|
||||
AcceptedScopes []string
|
||||
}
|
||||
|
||||
// globalToolScopeMap is populated from inventory when SetToolScopeMapFromInventory is called
|
||||
var globalToolScopeMap ToolScopeMap
|
||||
|
||||
// SetToolScopeMapFromInventory builds and stores a tool scope map from an inventory.
|
||||
// This should be called after building the inventory to make scopes available for middleware.
|
||||
func SetToolScopeMapFromInventory(inv *inventory.Inventory) {
|
||||
globalToolScopeMap = GetToolScopeMapFromInventory(inv)
|
||||
}
|
||||
|
||||
// SetGlobalToolScopeMap sets the global tool scope map directly.
|
||||
// This is useful for testing when you don't have a full inventory.
|
||||
func SetGlobalToolScopeMap(m ToolScopeMap) {
|
||||
globalToolScopeMap = m
|
||||
}
|
||||
|
||||
// GetToolScopeMap returns the global tool scope map.
|
||||
// Returns an empty map if SetToolScopeMapFromInventory hasn't been called yet.
|
||||
func GetToolScopeMap() (ToolScopeMap, error) {
|
||||
if globalToolScopeMap == nil {
|
||||
return make(ToolScopeMap), nil
|
||||
}
|
||||
return globalToolScopeMap, nil
|
||||
}
|
||||
|
||||
// GetToolScopeInfo returns scope information for a specific tool from the global scope map.
|
||||
func GetToolScopeInfo(toolName string) (*ToolScopeInfo, error) {
|
||||
m, err := GetToolScopeMap()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return m[toolName], nil
|
||||
}
|
||||
|
||||
// GetToolScopeMapFromInventory builds a tool scope map from an inventory.
|
||||
// This extracts scope information from ServerTool.RequiredScopes and ServerTool.AcceptedScopes.
|
||||
func GetToolScopeMapFromInventory(inv *inventory.Inventory) ToolScopeMap {
|
||||
result := make(ToolScopeMap)
|
||||
|
||||
// Get all tools from the inventory (both enabled and disabled)
|
||||
// We need all tools for scope checking purposes
|
||||
allTools := inv.AllTools()
|
||||
for i := range allTools {
|
||||
tool := &allTools[i]
|
||||
if len(tool.RequiredScopes) > 0 || len(tool.AcceptedScopes) > 0 {
|
||||
result[tool.Tool.Name] = &ToolScopeInfo{
|
||||
RequiredScopes: tool.RequiredScopes,
|
||||
AcceptedScopes: tool.AcceptedScopes,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// HasAcceptedScope checks if any of the provided user scopes satisfy the tool's requirements.
|
||||
func (t *ToolScopeInfo) HasAcceptedScope(userScopes ...string) bool {
|
||||
if t == nil || len(t.AcceptedScopes) == 0 {
|
||||
return true // No scopes required
|
||||
}
|
||||
|
||||
userScopeSet := make(map[string]bool)
|
||||
for _, scope := range userScopes {
|
||||
userScopeSet[scope] = true
|
||||
}
|
||||
|
||||
for _, scope := range t.AcceptedScopes {
|
||||
if userScopeSet[scope] {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// MissingScopes returns the required scopes that are not present in the user's scopes.
|
||||
func (t *ToolScopeInfo) MissingScopes(userScopes ...string) []string {
|
||||
if t == nil || len(t.RequiredScopes) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Create a set of user scopes for O(1) lookup
|
||||
userScopeSet := make(map[string]bool, len(userScopes))
|
||||
for _, s := range userScopes {
|
||||
userScopeSet[s] = true
|
||||
}
|
||||
|
||||
// Check if any accepted scope is present
|
||||
hasAccepted := false
|
||||
for _, scope := range t.AcceptedScopes {
|
||||
if userScopeSet[scope] {
|
||||
hasAccepted = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if hasAccepted {
|
||||
return nil // User has sufficient scopes
|
||||
}
|
||||
|
||||
// Return required scopes as the minimum needed
|
||||
missing := make([]string, len(t.RequiredScopes))
|
||||
copy(missing, t.RequiredScopes)
|
||||
return missing
|
||||
}
|
||||
|
||||
// GetRequiredScopesSlice returns the required scopes as a slice of strings.
|
||||
func (t *ToolScopeInfo) GetRequiredScopesSlice() []string {
|
||||
if t == nil {
|
||||
return nil
|
||||
}
|
||||
scopes := make([]string, len(t.RequiredScopes))
|
||||
copy(scopes, t.RequiredScopes)
|
||||
return scopes
|
||||
}
|
||||
Reference in New Issue
Block a user