Skip to main content

alibi_core/store/
org_extensions.rs

1//! Optional organization team and persisted-role storage contracts.
2use crate::error::{AuthError, AuthResult};
3use crate::types::{
4    AddTeamMemberResult, CreateOrganizationRole, CreateTeam, OrganizationRole,
5    OrganizationRoleSelector, Team, TeamMember, UpdateOrganizationRole, UpdateTeam,
6};
7use async_trait::async_trait;
8use base64::{Engine, engine::general_purpose::URL_SAFE_NO_PAD};
9use sha2::{Digest, Sha256};
10
11#[async_trait]
12pub trait TeamStore: Send + Sync {
13    async fn create_team(&self, _data: CreateTeam) -> AuthResult<Team> {
14        Err(unsupported())
15    }
16    async fn get_team(
17        &self,
18        _organization_id: Option<&str>,
19        _team_id: &str,
20    ) -> AuthResult<Option<Team>> {
21        Err(unsupported())
22    }
23    async fn list_teams(&self, _organization_id: &str) -> AuthResult<Vec<Team>> {
24        Err(unsupported())
25    }
26    async fn update_team(
27        &self,
28        _organization_id: &str,
29        _team_id: &str,
30        _update: UpdateTeam,
31    ) -> AuthResult<Team> {
32        Err(unsupported())
33    }
34    /// Remove the scoped team, its memberships, and its IDs from pending invitations atomically.
35    async fn delete_team(&self, _organization_id: &str, _team_id: &str) -> AuthResult<bool> {
36        Err(unsupported())
37    }
38    async fn get_team_member(
39        &self,
40        _team_id: &str,
41        _user_id: &str,
42    ) -> AuthResult<Option<TeamMember>> {
43        Err(unsupported())
44    }
45    /// Existing membership is idempotent, including when the capacity has since been reached.
46    /// `maximum` is a raw Source Number bound to the durable seat predicate;
47    /// custom stores must not round or cap it. Integer callers migrate to
48    /// `Some(3.0)`; `None` retains unlimited admission.
49    async fn add_team_member(
50        &self,
51        _team_id: &str,
52        _user_id: &str,
53        _maximum: Option<f64>,
54    ) -> AuthResult<AddTeamMemberResult> {
55        Err(unsupported())
56    }
57    async fn remove_team_member(&self, _team_id: &str, _user_id: &str) -> AuthResult<usize> {
58        Err(unsupported())
59    }
60    async fn list_team_members(&self, _team_id: &str) -> AuthResult<Vec<TeamMember>> {
61        Err(unsupported())
62    }
63    async fn list_user_teams(&self, _user_id: &str) -> AuthResult<Vec<Team>> {
64        Err(unsupported())
65    }
66}
67
68#[async_trait]
69pub trait OrganizationRoleStore: Send + Sync {
70    async fn create_organization_role(
71        &self,
72        _data: CreateOrganizationRole,
73    ) -> AuthResult<OrganizationRole> {
74        Err(unsupported())
75    }
76    async fn get_organization_role(
77        &self,
78        _organization_id: &str,
79        _selector: &OrganizationRoleSelector,
80    ) -> AuthResult<Option<OrganizationRole>> {
81        Err(unsupported())
82    }
83    async fn list_organization_roles(
84        &self,
85        _organization_id: &str,
86    ) -> AuthResult<Vec<OrganizationRole>> {
87        Err(unsupported())
88    }
89    /// Count all roles in the organization independently of the list query limit.
90    async fn count_organization_roles(&self, _organization_id: &str) -> AuthResult<usize> {
91        Err(unsupported())
92    }
93    /// Check exact comma-separated membership roles in the configured adapter page.
94    /// The organization and role substring predicates are applied before pagination.
95    async fn has_organization_role_members(
96        &self,
97        _organization_id: &str,
98        _role: &str,
99    ) -> AuthResult<bool> {
100        Err(unsupported())
101    }
102    async fn update_organization_role(
103        &self,
104        _organization_id: &str,
105        _selector: &OrganizationRoleSelector,
106        _update: UpdateOrganizationRole,
107    ) -> AuthResult<OrganizationRole> {
108        Err(unsupported())
109    }
110    async fn delete_organization_role(
111        &self,
112        _organization_id: &str,
113        _selector: &OrganizationRoleSelector,
114    ) -> AuthResult<bool> {
115        Err(unsupported())
116    }
117}
118
119fn unsupported() -> AuthError {
120    AuthError::NotImplemented(
121        "Organization extension storage is not supported by this store".to_owned(),
122    )
123}
124
125/// # Errors
126///
127/// Returns an error if the membership identifiers cannot be serialized.
128pub fn team_membership_key(team_id: &str, user_id: &str) -> AuthResult<String> {
129    Ok(URL_SAFE_NO_PAD.encode(Sha256::digest(serde_json::to_vec(&[team_id, user_id])?)))
130}