1use crate::store_membership::StoreMembership;
2use crate::store_sync::{StoreSync, SyncError};
3use coven_database::StoreDatabase;
4use coven_protocol::membership::MemberRole;
5
6#[derive(Debug, thiserror::Error)]
7pub enum DeviceAdmissionError {
8 #[error("sync: {0}")]
9 Sync(#[from] SyncError),
10 #[error("device invitation: {0}")]
11 DeviceInvite(#[from] coven_domain::joining::DeviceInviteError),
12}
13
14#[derive(Clone)]
19pub(crate) struct StoreJoining {
20 database: StoreDatabase,
21 membership: StoreMembership,
22 sync: StoreSync,
23}
24
25impl StoreJoining {
26 pub(crate) fn new(
27 database: StoreDatabase,
28 membership: StoreMembership,
29 sync: StoreSync,
30 ) -> Self {
31 Self {
32 database,
33 membership,
34 sync,
35 }
36 }
37
38 pub(crate) async fn begin_invite(
39 &self,
40 request: &coven_domain::joining::DevicePairingRequest,
41 role: MemberRole,
42 ) -> Result<coven_domain::joining::DeviceJoinInvite, DeviceAdmissionError> {
43 let admission = self
44 .membership
45 .admit(request.public_key(), request.provider_account_email(), role)
46 .await?;
47 let bundle = self
48 .sync
49 .begin_device_join_bundle(request.public_key())
50 .await?;
51 Ok(coven_domain::joining::DeviceJoinInvite::new(
52 admission, bundle,
53 )?)
54 }
55
56 pub(crate) async fn status(
57 &self,
58 attempt_id: crate::DeviceJoinAttemptId,
59 role: crate::DeviceJoinRole,
60 ) -> Result<Option<crate::DeviceJoinStatus>, SyncError> {
61 Ok(self.database.device_join_status(attempt_id, role).await?)
62 }
63
64 pub(crate) async fn resumable_actions(
65 &self,
66 ) -> Result<Vec<crate::DeviceJoinAction>, SyncError> {
67 Ok(self.database.device_join_actions().await?)
68 }
69}