adk_auth/
permission.rs

1//! Permission types for access control.
2
3use serde::{Deserialize, Serialize};
4
5/// Permission for accessing tools or agents.
6#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
7pub enum Permission {
8    /// Access to a specific tool by name.
9    Tool(String),
10    /// Access to all tools (wildcard).
11    AllTools,
12    /// Access to a specific agent by name.
13    Agent(String),
14    /// Access to all agents (wildcard).
15    AllAgents,
16}
17
18impl Permission {
19    /// Create a tool permission.
20    pub fn tool(name: impl Into<String>) -> Self {
21        Permission::Tool(name.into())
22    }
23
24    /// Create an agent permission.
25    pub fn agent(name: impl Into<String>) -> Self {
26        Permission::Agent(name.into())
27    }
28
29    /// Check if this permission matches a specific resource.
30    pub fn matches(&self, resource_type: &str, resource_name: &str) -> bool {
31        match self {
32            Permission::Tool(name) => resource_type == "tool" && name == resource_name,
33            Permission::AllTools => resource_type == "tool",
34            Permission::Agent(name) => resource_type == "agent" && name == resource_name,
35            Permission::AllAgents => resource_type == "agent",
36        }
37    }
38
39    /// Check if this permission covers another permission.
40    pub fn covers(&self, other: &Permission) -> bool {
41        match (self, other) {
42            // AllTools covers all tool permissions
43            (Permission::AllTools, Permission::Tool(_)) => true,
44            (Permission::AllTools, Permission::AllTools) => true,
45            // AllAgents covers all agent permissions
46            (Permission::AllAgents, Permission::Agent(_)) => true,
47            (Permission::AllAgents, Permission::AllAgents) => true,
48            // Exact match
49            (a, b) => a == b,
50        }
51    }
52}
53
54impl std::fmt::Display for Permission {
55    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
56        match self {
57            Permission::Tool(name) => write!(f, "tool:{}", name),
58            Permission::AllTools => write!(f, "tool:*"),
59            Permission::Agent(name) => write!(f, "agent:{}", name),
60            Permission::AllAgents => write!(f, "agent:*"),
61        }
62    }
63}
64
65#[cfg(test)]
66mod tests {
67    use super::*;
68
69    #[test]
70    fn test_permission_matches() {
71        let tool_perm = Permission::Tool("search".into());
72        assert!(tool_perm.matches("tool", "search"));
73        assert!(!tool_perm.matches("tool", "other"));
74        assert!(!tool_perm.matches("agent", "search"));
75
76        let all_tools = Permission::AllTools;
77        assert!(all_tools.matches("tool", "anything"));
78        assert!(!all_tools.matches("agent", "anything"));
79    }
80
81    #[test]
82    fn test_permission_covers() {
83        let all_tools = Permission::AllTools;
84        let specific_tool = Permission::Tool("search".into());
85
86        assert!(all_tools.covers(&specific_tool));
87        assert!(all_tools.covers(&Permission::AllTools));
88        assert!(!specific_tool.covers(&Permission::AllTools));
89        assert!(specific_tool.covers(&Permission::Tool("search".into())));
90    }
91
92    #[test]
93    fn test_permission_display() {
94        assert_eq!(Permission::Tool("search".into()).to_string(), "tool:search");
95        assert_eq!(Permission::AllTools.to_string(), "tool:*");
96        assert_eq!(Permission::Agent("assistant".into()).to_string(), "agent:assistant");
97        assert_eq!(Permission::AllAgents.to_string(), "agent:*");
98    }
99}