diff options
Diffstat (limited to 'src/authorization/entities.rs')
| -rw-r--r-- | src/authorization/entities.rs | 145 |
1 files changed, 0 insertions, 145 deletions
diff --git a/src/authorization/entities.rs b/src/authorization/entities.rs deleted file mode 100644 index 050f6f26..00000000 --- a/src/authorization/entities.rs +++ /dev/null @@ -1,145 +0,0 @@ -use crate::gitlab::Api; -use serde::Serialize; -use std::collections::HashSet; -use std::future::Future; -use std::pin::Pin; - -type BoxFuture<'a, T> = Pin<Box<dyn Future<Output = T> + 'a>>; - -// Cedar entity structures -// Note: We define custom types instead of using cedar_policy::Entity directly because: -// 1. Cedar's Entity type is for runtime use, not JSON serialization -// 2. These types ensure our JSON output matches Cedar's expected format exactly -// 3. The #[serde(rename)] attributes handle Cedar's specific field naming requirements -#[derive(Debug, Serialize)] -pub struct CedarEntity { - pub uid: CedarUid, - pub attrs: serde_json::Value, - pub parents: Vec<CedarParent>, -} - -#[derive(Debug, Serialize)] -pub struct CedarUid { - #[serde(rename = "type")] - pub entity_type: String, - pub id: String, -} - -#[derive(Debug, Serialize)] -pub struct CedarParent { - #[serde(rename = "type")] - pub parent_type: String, - pub id: String, -} - -pub struct EntitiesRepository { - api: Api, -} - -impl EntitiesRepository { - pub fn new(api: Api) -> EntitiesRepository { - EntitiesRepository { api } - } - - pub async fn all( - &self, - project_path: String, - ) -> Result<Vec<CedarEntity>, Box<dyn std::error::Error>> { - let mut entities = Vec::new(); - let mut groups = HashSet::new(); - - let project = self.api.get_project(&project_path).await?; - - entities.push(CedarEntity { - uid: CedarUid { - entity_type: "Project".to_string(), - id: project.id.to_string(), - }, - attrs: serde_json::json!({ - "name": project.name, - "path": project.path, - "full_path": format!("{}/{}", project.namespace.full_path, project.path), - }), - parents: if project.namespace.kind == "group" { - vec![CedarParent { - parent_type: "Group".to_string(), - id: project.namespace.id.to_string(), - }] - } else { - vec![] - }, - }); - - for member in self.api.get_project_members(project.id).await? { - if member.state == "active" { - entities.push(CedarEntity { - uid: CedarUid { - entity_type: "User".to_string(), - id: member.id.to_string(), - }, - attrs: serde_json::json!({ - "username": member.username, - "access_level": member.access_level, - }), - parents: vec![], - }); - } - } - - if project.namespace.kind == "group" { - self.fetch_hierarchy(project.namespace.id, &mut entities, &mut groups) - .await?; - } - - Ok(entities) - } - - /// Validates that the entities can be parsed by Cedar - pub fn is_valid(entities: &[CedarEntity]) -> Result<(), Box<dyn std::error::Error>> { - let json = serde_json::to_string(entities)?; - cedar_policy::Entities::from_json_str(&json, None)?; - Ok(()) - } - - fn fetch_hierarchy<'a>( - &'a self, - group_id: u64, - entities: &'a mut Vec<CedarEntity>, - groups: &'a mut HashSet<u64>, - ) -> BoxFuture<'a, Result<(), Box<dyn std::error::Error>>> { - Box::pin(async move { - if groups.contains(&group_id) { - return Ok(()); - } - - groups.insert(group_id); - - let group = self.api.get_group(group_id).await?; - - let parents = if let Some(parent_id) = group.parent_id { - self.fetch_hierarchy(parent_id, entities, groups).await?; - vec![CedarParent { - parent_type: "Group".to_string(), - id: parent_id.to_string(), - }] - } else { - vec![] - }; - - entities.push(CedarEntity { - uid: CedarUid { - entity_type: "Group".to_string(), - id: group.id.to_string(), - }, - attrs: serde_json::json!({ - "name": group.name, - "path": group.path, - "full_path": group.full_path, - }), - parents, - }); - - Ok(()) - }) - } -} |
