alibi_core/store/contracts/
organization.rs1use crate::{
2 AuthError, AuthResult, CreateInvitation, CreateMember, CreateOrganization, Invitation,
3 InvitationStatus, Member, Organization, UpdateOrganization,
4};
5use async_trait::async_trait;
6#[derive(Debug, Clone, Default)]
8pub struct ListOrganizationMembersParams {
9 pub organization_id: String,
11 pub limit: Option<usize>,
13 pub offset: Option<usize>,
15 pub sort_by: Option<String>,
17 pub sort_direction: Option<String>,
19 pub filter_field: Option<String>,
21 pub filter_value: Option<String>,
23 pub filter_operator: Option<String>,
25}
26
27#[derive(Debug, Clone, Default)]
30pub struct MemberPageQuery {
31 pub organization_id: String,
32 pub limit: Option<f64>,
33 pub offset: Option<f64>,
34 pub sort_by: Option<String>,
35 pub sort_direction: Option<String>,
36 pub filter_field: Option<String>,
37 pub filter_value: Option<String>,
38 pub filter_operator: Option<String>,
39}
40
41#[async_trait]
42pub trait OrganizationStore: Send + Sync {
43 async fn create_organization(&self, org: CreateOrganization) -> AuthResult<Organization>;
44 async fn get_organization_by_id(&self, id: &str) -> AuthResult<Option<Organization>>;
45 async fn get_organization_by_slug(&self, slug: &str) -> AuthResult<Option<Organization>>;
46 async fn list_organizations_by_ids(&self, ids: &[String]) -> AuthResult<Vec<Organization>>;
51 async fn update_organization(
52 &self,
53 id: &str,
54 update: UpdateOrganization,
55 ) -> AuthResult<Organization>;
56 async fn patch_organization_if_present(
63 &self,
64 _id: &str,
65 _update: UpdateOrganization,
66 ) -> AuthResult<Option<Organization>> {
67 Err(AuthError::NotImplemented(
68 "Organization patches are not supported by this store".into(),
69 ))
70 }
71 async fn update_organization_if_present(
75 &self,
76 _id: &str,
77 _update: UpdateOrganization,
78 ) -> AuthResult<Option<Organization>> {
79 Err(AuthError::NotImplemented(
80 "Optional organization updates are not supported by this store".into(),
81 ))
82 }
83 async fn delete_organization(&self, id: &str) -> AuthResult<()>;
87 async fn list_user_organizations(&self, user_id: &str) -> AuthResult<Vec<Organization>>;
88}
89
90#[async_trait]
91pub trait MemberStore: Send + Sync {
92 async fn create_member(&self, member: CreateMember) -> AuthResult<Member>;
93 async fn get_member(&self, organization_id: &str, user_id: &str) -> AuthResult<Option<Member>>;
94 async fn get_member_by_id(&self, id: &str) -> AuthResult<Option<Member>>;
95 async fn update_member_role(&self, member_id: &str, role: &str) -> AuthResult<Member>;
96 async fn update_member_role_if_present(
99 &self,
100 _member_id: &str,
101 _role: &str,
102 ) -> AuthResult<Option<Member>> {
103 Err(AuthError::NotImplemented(
104 "Optional member role updates are not supported by this store".into(),
105 ))
106 }
107 async fn delete_member(&self, member_id: &str) -> AuthResult<()>;
108 async fn delete_member_with_context(
113 &self,
114 _member_id: &str,
115 _organization_id: &str,
116 _user_id: &str,
117 _remove_team_members: bool,
118 ) -> AuthResult<()> {
119 Err(AuthError::NotImplemented(
120 "Contextual member deletion is not supported by this store".into(),
121 ))
122 }
123 async fn list_organization_members_page(
126 &self,
127 _organization_id: &str,
128 _limit: usize,
129 ) -> AuthResult<Vec<Member>> {
130 Err(AuthError::NotImplemented(
131 "Unsorted member pages are not supported by this store".into(),
132 ))
133 }
134 async fn list_organization_members(&self, org_id: &str) -> AuthResult<Vec<Member>>;
135 async fn query_organization_members(
138 &self,
139 params: &ListOrganizationMembersParams,
140 ) -> AuthResult<(Vec<Member>, usize)>;
141 async fn query_organization_members_page(
143 &self,
144 _params: &MemberPageQuery,
145 ) -> AuthResult<(Vec<Member>, usize)> {
146 Err(AuthError::NotImplemented(
147 "Raw numeric member pages are not supported by this store".into(),
148 ))
149 }
150 async fn count_organization_members(&self, org_id: &str) -> AuthResult<i64>;
151 async fn count_organization_owners(&self, org_id: &str) -> AuthResult<i64>;
152}
153
154#[derive(Debug, Clone, Default, PartialEq, Eq)]
157pub struct InvitationCreateOptions {
158 pub id: Option<String>,
159 pub status: Option<InvitationStatus>,
160 pub created_at: Option<chrono::DateTime<chrono::Utc>>,
161}
162
163#[async_trait]
164pub trait InvitationStore: Send + Sync {
165 async fn create_invitation_with_options(
166 &self,
167 invitation: CreateInvitation,
168 options: InvitationCreateOptions,
169 ) -> AuthResult<Invitation> {
170 if options == InvitationCreateOptions::default() {
171 self.create_invitation(invitation).await
172 } else {
173 Err(AuthError::NotImplemented(
174 "Invitation creation overrides are not supported by this store".into(),
175 ))
176 }
177 }
178
179 async fn pending_invitation_page(
181 &self,
182 _org_id: &str,
183 _email: Option<&str>,
184 ) -> AuthResult<Vec<Invitation>> {
185 Err(AuthError::NotImplemented(
186 "Pending invitation pages are not supported by this store".into(),
187 ))
188 }
189 async fn update_invitation_expiry(
191 &self,
192 _id: &str,
193 _expires_at: chrono::DateTime<chrono::Utc>,
194 ) -> AuthResult<Invitation> {
195 Err(AuthError::NotImplemented(
196 "Invitation expiry updates are not supported by this store".into(),
197 ))
198 }
199
200 async fn create_invitation(&self, invitation: CreateInvitation) -> AuthResult<Invitation>;
201 async fn get_invitation_by_id(&self, id: &str) -> AuthResult<Option<Invitation>>;
202 async fn get_pending_invitation(
203 &self,
204 org_id: &str,
205 email: &str,
206 ) -> AuthResult<Option<Invitation>>;
207 async fn update_invitation_status(
208 &self,
209 id: &str,
210 status: InvitationStatus,
211 ) -> AuthResult<Invitation>;
212 async fn update_invitation_status_if_status(
216 &self,
217 _id: &str,
218 _expected: InvitationStatus,
219 _status: InvitationStatus,
220 ) -> AuthResult<Option<Invitation>> {
221 Err(AuthError::NotImplemented(
222 "Conditional invitation updates are not supported by this store".into(),
223 ))
224 }
225 async fn list_organization_invitations(&self, org_id: &str) -> AuthResult<Vec<Invitation>>;
226 async fn count_pending_organization_invitations(&self, org_id: &str) -> AuthResult<i64>;
228 async fn list_user_invitations(&self, email: &str) -> AuthResult<Vec<Invitation>>;
229 async fn accept_invitation_with_teams(
231 &self,
232 _invitation_id: &str,
233 _user_id: &str,
234 _session_token: &str,
235 _team_limits: &[(String, Option<f64>)],
236 _membership_limit: Option<usize>,
237 ) -> AuthResult<Option<(Invitation, Member)>> {
238 Err(AuthError::NotImplemented(
239 "Atomic invitation acceptance is not supported by this store".to_owned(),
240 ))
241 }
242 async fn update_invitation_team_ids(
243 &self,
244 _id: &str,
245 _team_ids: Option<String>,
246 ) -> AuthResult<Invitation> {
247 Err(AuthError::NotImplemented(
248 "Invitation team updates are not supported by this store".to_owned(),
249 ))
250 }
251}