Skip to main content

coven/
store_joining.rs

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/// The two parts of device joining that are not a plain sync command: minting
15/// an invitation, which pairs a membership admission with the attempt's transport
16/// bundle, and reading the join journal the database holds. Every other step is
17/// a command on [`StoreSync`], which its caller issues there.
18#[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}