sos_net/pairing/
enrollment.rs1use crate::{
3 pairing::{Error, Result},
4 NetworkAccount,
5};
6use sos_account::Account;
7use sos_backend::{BackendTarget, ServerOrigins};
8use sos_client_storage::{
9 ClientAccountStorage, ClientBaseStorage, ClientStorage,
10};
11use sos_core::{
12 crypto::AccessKey, AccountId, Origin, PublicIdentity, RemoteOrigins,
13};
14use sos_login::device::DeviceSigner;
15use sos_protocol::{network_client::HttpClient, SyncClient};
16use sos_signer::ed25519::BoxedEd25519Signer;
17use std::collections::HashSet;
18
19pub struct DeviceEnrollment {
25 account_id: AccountId,
27 storage: ClientStorage,
29 client: HttpClient,
31 public_identity: Option<PublicIdentity>,
36 device_vault: Vec<u8>,
38 account_name: String,
40 servers: HashSet<Origin>,
42}
43
44impl DeviceEnrollment {
45 pub(crate) async fn new(
47 target: BackendTarget,
48 account_id: AccountId,
49 account_name: String,
50 origin: Origin,
51 device_signer: DeviceSigner,
52 device_vault: Vec<u8>,
53 servers: HashSet<Origin>,
54 ) -> Result<Self> {
55 let target = target.with_account_id(&account_id);
56 match &target {
57 BackendTarget::FileSystem(paths) => {
58 #[cfg(debug_assertions)]
59 sos_core::Paths::scaffold(paths.documents_dir()).await?;
60 paths.ensure().await?;
61 }
62 BackendTarget::Database(_, _) => {}
63 }
64
65 let accounts = target.list_accounts().await?;
66 if accounts
67 .iter()
68 .find(|a| a.account_id() == &account_id)
69 .is_some()
70 {
71 return Err(Error::EnrollAccountExists(account_id));
72 }
73
74 let storage = ClientStorage::new_account(
75 target,
76 &account_id,
77 account_name.clone(),
78 )
79 .await?;
80 let device_signing_key = device_signer.clone();
81 let device: BoxedEd25519Signer = device_signing_key.into();
82 let client =
83 HttpClient::new(account_id, origin, device, String::new())?;
84 Ok(Self {
85 account_id,
86 storage,
87 client,
88 public_identity: None,
89 device_vault,
90 account_name,
91 servers,
92 })
93 }
94
95 pub fn account_id(&self) -> &AccountId {
97 &self.account_id
98 }
99
100 pub fn public_identity(&self) -> Option<&PublicIdentity> {
105 self.public_identity.as_ref()
106 }
107
108 pub async fn fetch_account(&mut self) -> Result<()> {
110 let create_set = self.client.fetch_account().await?;
112
113 self.storage.import_account(&create_set).await?;
115
116 self.storage.create_device_vault(&self.device_vault).await?;
119
120 self.add_origin_servers().await?;
124
125 self.public_identity = Some(PublicIdentity::new(
128 self.account_id,
129 self.account_name.clone(),
130 ));
131
132 Ok(())
133 }
134
135 pub async fn finish(&self, key: &AccessKey) -> Result<NetworkAccount> {
137 self.public_identity
138 .as_ref()
139 .ok_or_else(|| Error::AccountNotFetched)?;
140
141 let mut account = NetworkAccount::new_unauthenticated(
142 self.account_id,
143 self.storage.backend_target().clone(),
144 Default::default(),
145 )
146 .await?;
147
148 account.sign_in(key).await?;
150
151 account.set_account_name(self.account_name.clone()).await?;
153
154 Ok(account)
155 }
156
157 async fn add_origin_servers(&self) -> Result<()> {
159 let mut origins = ServerOrigins::new(
160 self.storage.backend_target().clone(),
161 &self.account_id,
162 );
163 for server in &self.servers {
164 origins.add_server(server.clone()).await?;
165 }
166 Ok(())
167 }
168}