ricecoder_teams/
access.rs1use std::collections::HashMap;
3use std::sync::Arc;
4
5use ricecoder_permissions::{AuditLogger, PermissionManager};
6use tokio::sync::RwLock;
7
8use crate::error::Result;
9use crate::models::{AuditLogEntry, TeamRole};
10
11pub struct AccessControlManager {
13 #[allow(dead_code)]
15 permission_manager: Arc<PermissionManager>,
16 audit_logger: Arc<AuditLogger>,
18 member_roles: Arc<RwLock<HashMap<String, HashMap<String, TeamRole>>>>,
20}
21
22impl AccessControlManager {
23 pub fn new(permission_manager: Arc<PermissionManager>, audit_logger: Arc<AuditLogger>) -> Self {
25 AccessControlManager {
26 permission_manager,
27 audit_logger,
28 member_roles: Arc::new(RwLock::new(HashMap::new())),
29 }
30 }
31
32 pub async fn assign_role(&self, team_id: &str, member_id: &str, role: TeamRole) -> Result<()> {
34 let mut roles = self.member_roles.write().await;
36 let team_roles = roles
37 .entry(team_id.to_string())
38 .or_insert_with(HashMap::new);
39 team_roles.insert(member_id.to_string(), role);
40
41 tracing::info!(
43 team_id = %team_id,
44 member_id = %member_id,
45 role = %role.as_str(),
46 "Assigning role to team member"
47 );
48
49 let tool_name = format!("team:{}:assign_role", team_id);
51 let context = format!("Assigned role {} to member {}", role.as_str(), member_id);
52 let _ =
53 self.audit_logger
54 .log_execution(tool_name, Some(member_id.to_string()), Some(context));
55
56 Ok(())
57 }
58
59 pub async fn check_permission(
61 &self,
62 member_id: &str,
63 action: &str,
64 resource: &str,
65 ) -> Result<bool> {
66 tracing::info!(
69 member_id = %member_id,
70 action = %action,
71 resource = %resource,
72 "Checking permission"
73 );
74
75 Ok(true)
77 }
78
79 pub async fn grant_admin_permissions(&self, member_id: &str) -> Result<()> {
81 let permissions = vec!["create_standards", "modify_standards", "delete_standards"];
83
84 for permission in permissions {
85 tracing::info!(
86 member_id = %member_id,
87 permission = %permission,
88 "Granting admin permission"
89 );
90 }
91
92 Ok(())
93 }
94
95 pub async fn grant_member_permissions(&self, member_id: &str) -> Result<()> {
97 let permissions = vec!["view_standards", "apply_standards"];
99
100 for permission in permissions {
101 tracing::info!(
102 member_id = %member_id,
103 permission = %permission,
104 "Granting member permission"
105 );
106 }
107
108 Ok(())
109 }
110
111 pub async fn grant_viewer_permissions(&self, member_id: &str) -> Result<()> {
113 let permissions = vec!["view_standards"];
115
116 for permission in permissions {
117 tracing::info!(
118 member_id = %member_id,
119 permission = %permission,
120 "Granting viewer permission"
121 );
122 }
123
124 Ok(())
125 }
126
127 pub async fn revoke_access(&self, team_id: &str, member_id: &str) -> Result<()> {
129 let mut roles = self.member_roles.write().await;
131 if let Some(team_roles) = roles.get_mut(team_id) {
132 team_roles.remove(member_id);
133 }
134
135 tracing::info!(
136 team_id = %team_id,
137 member_id = %member_id,
138 "Revoking access"
139 );
140
141 let tool_name = format!("team:{}:revoke_access", team_id);
143 let context = format!("Revoked access for member {}", member_id);
144 let _ =
145 self.audit_logger
146 .log_execution(tool_name, Some(member_id.to_string()), Some(context));
147
148 Ok(())
149 }
150
151 pub async fn get_audit_log(&self, team_id: &str) -> Result<Vec<AuditLogEntry>> {
153 tracing::info!(team_id = %team_id, "Retrieving audit log");
155
156 let entries = self
158 .audit_logger
159 .entries()
160 .map_err(crate::error::TeamError::PermissionsError)?;
161
162 let team_entries: Vec<AuditLogEntry> = entries
164 .into_iter()
165 .filter(|entry| entry.tool.contains(&format!("team:{}", team_id)))
166 .map(|entry| AuditLogEntry {
167 id: entry.id,
168 team_id: team_id.to_string(),
169 user_id: entry.agent.unwrap_or_default(),
170 action: entry.action.to_string(),
171 resource: entry.tool,
172 result: entry.result.to_string(),
173 timestamp: entry.timestamp,
174 })
175 .collect();
176
177 Ok(team_entries)
178 }
179
180 pub async fn get_member_role(
182 &self,
183 team_id: &str,
184 member_id: &str,
185 ) -> Result<Option<TeamRole>> {
186 let roles = self.member_roles.read().await;
187 Ok(roles
188 .get(team_id)
189 .and_then(|team_roles| team_roles.get(member_id).copied()))
190 }
191
192 pub async fn has_role(&self, team_id: &str, member_id: &str, role: TeamRole) -> Result<bool> {
194 let member_role = self.get_member_role(team_id, member_id).await?;
195 Ok(member_role == Some(role))
196 }
197}
198
199impl Default for AccessControlManager {
200 fn default() -> Self {
201 let permission_manager = Arc::new(PermissionManager::new());
203 let audit_logger = Arc::new(AuditLogger::new());
204 Self::new(permission_manager, audit_logger)
205 }
206}