scufflecloud_core_cedar/models/
organization.rs

1use core_db_types::models::{
2    Organization, OrganizationId, OrganizationInvitation, OrganizationInvitationId, OrganizationMember, Policy, PolicyId,
3    Project, ProjectId, Role, RoleId, ServiceAccount, ServiceAccountId, ServiceAccountToken, ServiceAccountTokenId,
4};
5use ext_traits::OptionExt;
6
7use crate::macros::{cedar_entity, cedar_entity_id};
8use crate::{CedarIdentifiable, EntityTypeName, JsonEntityUid, entity_type_name};
9
10cedar_entity!(Organization, OrganizationId);
11
12cedar_entity!(Project, ProjectId);
13
14cedar_entity!(Policy, PolicyId);
15
16cedar_entity!(Role, RoleId);
17
18impl crate::CedarIdentifiable for OrganizationMember {
19    const ENTITY_TYPE: EntityTypeName = entity_type_name!("OrganizationMember");
20
21    fn entity_id(&self) -> cedar_policy::EntityId {
22        cedar_policy::EntityId::new(format!("{}:{}", self.organization_id.ulid(), self.user_id.ulid()))
23    }
24}
25
26impl crate::CedarEntity for OrganizationMember {
27    async fn parents(&self, _: &impl core_traits::Global) -> Result<impl IntoIterator<Item = JsonEntityUid>, tonic::Status> {
28        Ok(std::iter::once(self.organization_id.entity_uid()))
29    }
30}
31
32cedar_entity_id!(ServiceAccount, ServiceAccountId);
33
34impl crate::CedarEntity for ServiceAccount {
35    async fn parents(&self, _: &impl core_traits::Global) -> Result<impl IntoIterator<Item = JsonEntityUid>, tonic::Status> {
36        Ok(std::iter::once(self.organization_id.entity_uid()).chain(self.project_id.map(|id| id.entity_uid())))
37    }
38}
39
40cedar_entity!(ServiceAccountToken, ServiceAccountTokenId);
41
42cedar_entity_id!(OrganizationInvitation, OrganizationInvitationId);
43
44impl crate::CedarEntity for OrganizationInvitation {
45    async fn additional_attributes(
46        &self,
47        global: &impl core_traits::Global,
48    ) -> Result<impl serde::Serialize, tonic::Status> {
49        #[derive(serde_derive::Serialize)]
50        struct AdditionalAttrs {
51            organization: Organization,
52        }
53
54        Ok(AdditionalAttrs {
55            organization: global
56                .organization_loader()
57                .load(self.organization_id)
58                .await
59                .ok()
60                .into_tonic_internal_err("failed to query organization")?
61                .into_tonic_not_found("organization not found")?,
62        })
63    }
64}