1use crate::ServerError::ClientError;
2use crate::billing::app_store_client::AppStoreClient;
3use crate::billing::billing_model::BillingPlatform;
4use crate::billing::google_play_client::GooglePlayClient;
5use crate::billing::stripe_client::StripeClient;
6use crate::document_service::DocumentService;
7use crate::schema::{Account, ServerDb};
8use crate::utils::username_is_valid;
9use crate::{RequestContext, ServerError, ServerState};
10use db_rs::Db;
11use lb_rs::model::account::Username;
12use lb_rs::model::api::NewAccountError::{FileIdTaken, PublicKeyTaken, UsernameTaken};
13use lb_rs::model::api::{
14 AccountFilter, AccountIdentifier, AccountInfo, AdminDisappearAccountError,
15 AdminDisappearAccountRequest, AdminGetAccountInfoError, AdminGetAccountInfoRequest,
16 AdminGetAccountInfoResponse, AdminListUsersError, AdminListUsersRequest,
17 AdminListUsersResponse, DeleteAccountError, DeleteAccountRequest, FileUsage, GetPublicKeyError,
18 GetPublicKeyRequest, GetPublicKeyResponse, GetUsageError, GetUsageRequest, GetUsageResponse,
19 GetUsernameError, GetUsernameRequest, GetUsernameResponse, METADATA_FEE, NewAccountError,
20 NewAccountRequestV2, NewAccountResponse, PaymentPlatform,
21};
22use lb_rs::model::clock::get_time;
23use lb_rs::model::file_like::FileLike;
24use lb_rs::model::file_metadata::Owner;
25use lb_rs::model::server_meta::IntoServerMeta;
26use lb_rs::model::server_tree::ServerTree;
27use lb_rs::model::tree_like::TreeLike;
28use lb_rs::model::usage::bytes_to_human;
29use libsecp256k1::PublicKey;
30use std::collections::HashSet;
31use std::fmt::Debug;
32use std::ops::DerefMut;
33use tracing::warn;
34
35impl<S, A, G, D> ServerState<S, A, G, D>
36where
37 S: StripeClient,
38 A: AppStoreClient,
39 G: GooglePlayClient,
40 D: DocumentService,
41{
42 pub async fn new_account_v2(
46 &self, mut context: RequestContext<NewAccountRequestV2>,
47 ) -> Result<NewAccountResponse, ServerError<NewAccountError>> {
48 context.request.username = context.request.username.to_lowercase();
49 let request = &context.request;
50
51 tracing::info!("new-account attempt username: {}", request.username);
52
53 if !username_is_valid(&request.username) {
54 return Err(ClientError(NewAccountError::InvalidUsername));
55 }
56
57 if !&self.config.features.new_accounts {
58 return Err(ClientError(NewAccountError::Disabled));
59 }
60
61 let root = request.root_folder.clone();
62 let now = get_time().0 as u64;
63 let root = root.add_time(now);
64
65 let mut db = self.index_db.lock().await;
66 let handle = db.begin_transaction()?;
67
68 if let Some(ip) = context.ip {
69 if !self.can_create_account(ip.ip()).await {
70 return Err(ClientError(NewAccountError::RateLimited));
71 }
72 }
73
74 if db.accounts.get().contains_key(&Owner(request.public_key)) {
75 return Err(ClientError(PublicKeyTaken));
76 }
77
78 if db.usernames.get().contains_key(&request.username) {
79 return Err(ClientError(UsernameTaken));
80 }
81
82 if db.metas.get().contains_key(root.id()) {
83 return Err(ClientError(FileIdTaken));
84 }
85
86 if self.config.features.new_account_rate_limit {
87 if let Some(ip) = context.ip {
88 self.did_create_account(ip.ip()).await;
89 }
90 }
91
92 let username = &request.username;
93 let account = Account { username: username.clone(), billing_info: Default::default() };
94
95 let owner = Owner(request.public_key);
96
97 let mut owned_files = HashSet::new();
98 owned_files.insert(*root.id());
99
100 db.accounts.insert(owner, account)?;
101 db.usernames.insert(username.clone(), owner)?;
102 db.owned_files.insert(owner, *root.id())?;
103 db.shared_files.create_key(owner)?;
104 db.file_children.create_key(*root.id())?;
105 db.metas.insert(*root.id(), root.clone())?;
106
107 handle.drop_safely()?;
108
109 Ok(NewAccountResponse { last_synced: root.version })
110 }
111
112 pub async fn get_public_key(
113 &self, context: RequestContext<GetPublicKeyRequest>,
114 ) -> Result<GetPublicKeyResponse, ServerError<GetPublicKeyError>> {
115 let request = &context.request;
116 self.public_key_from_username(&request.username).await
117 }
118
119 pub async fn public_key_from_username(
120 &self, username: &str,
121 ) -> Result<GetPublicKeyResponse, ServerError<GetPublicKeyError>> {
122 self.index_db
123 .lock()
124 .await
125 .usernames
126 .get()
127 .get(username)
128 .map(|owner| Ok(GetPublicKeyResponse { key: owner.0 }))
129 .unwrap_or(Err(ClientError(GetPublicKeyError::UserNotFound)))
130 }
131
132 pub async fn get_username(
133 &self, context: RequestContext<GetUsernameRequest>,
134 ) -> Result<GetUsernameResponse, ServerError<GetUsernameError>> {
135 self.username_from_public_key(context.request.key).await
136 }
137
138 pub async fn username_from_public_key(
139 &self, key: PublicKey,
140 ) -> Result<GetUsernameResponse, ServerError<GetUsernameError>> {
141 self.index_db
142 .lock()
143 .await
144 .accounts
145 .get()
146 .get(&Owner(key))
147 .map(|account| Ok(GetUsernameResponse { username: account.username.clone() }))
148 .unwrap_or(Err(ClientError(GetUsernameError::UserNotFound)))
149 }
150
151 pub async fn get_usage(
152 &self, context: RequestContext<GetUsageRequest>,
153 ) -> Result<GetUsageResponse, ServerError<GetUsageError>> {
154 let mut lock = self.index_db.lock().await;
155 let db = lock.deref_mut();
156
157 let cap = Self::get_cap(db, &context.public_key)?;
158 let owner = Owner(context.public_key);
159
160 let mut tree = ServerTree::new(
161 owner,
162 &mut db.owned_files,
163 &mut db.shared_files,
164 &mut db.file_children,
165 &mut db.metas,
166 )?
167 .to_lazy();
168
169 let usages = tree
170 .ids()
171 .into_iter()
172 .filter_map(|file_id| {
173 if tree.calculate_deleted(&file_id).unwrap_or(true) {
174 return None;
175 }
176 let file = tree.find(&file_id).ok()?;
177 if file.owner() != owner {
178 return None;
179 }
180 let file_size = file.doc_size().unwrap_or(0) as u64;
181 Some(FileUsage { file_id, size_bytes: file_size + METADATA_FEE })
182 })
183 .collect();
184
185 Ok(GetUsageResponse { usages, cap })
186 }
187
188 pub fn get_cap(
189 db: &ServerDb, public_key: &PublicKey,
190 ) -> Result<u64, ServerError<GetUsageHelperError>> {
191 Ok(db
192 .accounts
193 .get()
194 .get(&Owner(*public_key))
195 .ok_or(ServerError::ClientError(GetUsageHelperError::UserNotFound))?
196 .billing_info
197 .data_cap())
198 }
199
200 pub async fn delete_account(
201 &self, context: RequestContext<DeleteAccountRequest>,
202 ) -> Result<(), ServerError<DeleteAccountError>> {
203 self.delete_account_helper(&context.public_key, false)
204 .await?;
205
206 Ok(())
207 }
208
209 pub async fn admin_disappear_account(
210 &self, context: RequestContext<AdminDisappearAccountRequest>,
211 ) -> Result<(), ServerError<AdminDisappearAccountError>> {
212 let owner = {
213 let db = &self.index_db.lock().await;
214
215 if !Self::is_admin::<AdminDisappearAccountError>(
216 db,
217 &context.public_key,
218 &self.config.admin.admins,
219 )? {
220 return Err(ClientError(AdminDisappearAccountError::NotPermissioned));
221 }
222
223 let admin_username = db
224 .accounts
225 .get()
226 .get(&Owner(context.public_key))
227 .cloned()
228 .map(|account| account.username)
229 .unwrap_or_else(|| "~unknown~".to_string());
230
231 warn!("admin {} is disappearing account {}", admin_username, context.request.username);
232
233 *db.usernames
234 .get()
235 .get(&context.request.username)
236 .ok_or(ClientError(AdminDisappearAccountError::UserNotFound))?
237 };
238
239 self.delete_account_helper(&owner.0, true).await?;
240
241 Ok(())
242 }
243
244 pub async fn admin_list_users(
245 &self, context: RequestContext<AdminListUsersRequest>,
246 ) -> Result<AdminListUsersResponse, ServerError<AdminListUsersError>> {
247 let (db, request) = (&self.index_db.lock().await, &context.request);
248
249 if !Self::is_admin::<AdminListUsersError>(
250 db,
251 &context.public_key,
252 &self.config.admin.admins,
253 )? {
254 return Err(ClientError(AdminListUsersError::NotPermissioned));
255 }
256
257 let mut users: Vec<String> = vec![];
258
259 for account in db.accounts.get().values() {
260 match &request.filter {
261 Some(filter) => match filter {
262 AccountFilter::Premium => {
263 if account.billing_info.is_premium() {
264 users.push(account.username.clone());
265 }
266 }
267 AccountFilter::AppStorePremium => match account.billing_info.billing_platform {
268 Some(BillingPlatform::AppStore(_)) if account.billing_info.is_premium() => {
269 users.push(account.username.clone());
270 }
271 _ => {}
272 },
273 AccountFilter::StripePremium => match account.billing_info.billing_platform {
274 Some(BillingPlatform::Stripe(_)) if account.billing_info.is_premium() => {
275 users.push(account.username.clone());
276 }
277 _ => {}
278 },
279 AccountFilter::GooglePlayPremium => match account.billing_info.billing_platform
280 {
281 Some(BillingPlatform::GooglePlay(_))
282 if account.billing_info.is_premium() =>
283 {
284 users.push(account.username.clone());
285 }
286 _ => {}
287 },
288 },
289 None => users.push(account.username.clone()),
290 }
291 }
292
293 Ok(AdminListUsersResponse { users })
294 }
295
296 pub async fn admin_get_account_info(
297 &self, context: RequestContext<AdminGetAccountInfoRequest>,
298 ) -> Result<AdminGetAccountInfoResponse, ServerError<AdminGetAccountInfoError>> {
299 let (mut lock, request) = (self.index_db.lock().await, &context.request);
300 let db = lock.deref_mut();
301
302 if !Self::is_admin::<AdminGetAccountInfoError>(
303 db,
304 &context.public_key,
305 &self.config.admin.admins,
306 )? {
307 return Err(ClientError(AdminGetAccountInfoError::NotPermissioned));
308 }
309
310 let owner = match &request.identifier {
311 AccountIdentifier::PublicKey(public_key) => Owner(*public_key),
312 AccountIdentifier::Username(user) => *db
313 .usernames
314 .get()
315 .get(user)
316 .ok_or(ClientError(AdminGetAccountInfoError::UserNotFound))?,
317 };
318
319 let account = db
320 .accounts
321 .get()
322 .get(&owner)
323 .ok_or(ClientError(AdminGetAccountInfoError::UserNotFound))?
324 .clone();
325
326 let mut maybe_root = None;
327 if let Some(owned_ids) = db.owned_files.get().get(&owner) {
328 for id in owned_ids {
329 if let Some(meta) = db.metas.get().get(id) {
330 if meta.is_root() {
331 maybe_root = Some(*meta.id());
332 }
333 } else {
334 return Err(internal!(
335 "Nonexistent file indexed as owned, id: {}, owner: {:?}",
336 id,
337 owner
338 ));
339 }
340 }
341 } else {
342 return Err(internal!("Owned files not indexed for user, owner: {:?}", owner));
343 }
344 let root = if let Some(root) = maybe_root {
345 root
346 } else {
347 return Err(internal!("User root not found, owner: {:?}", owner));
348 };
349
350 let payment_platform = account
351 .billing_info
352 .billing_platform
353 .map(|billing_platform| match billing_platform {
354 BillingPlatform::Stripe(user_info) => {
355 PaymentPlatform::Stripe { card_last_4_digits: user_info.last_4 }
356 }
357 BillingPlatform::GooglePlay(user_info) => {
358 PaymentPlatform::GooglePlay { account_state: user_info.account_state }
359 }
360 BillingPlatform::AppStore(user_info) => {
361 PaymentPlatform::AppStore { account_state: user_info.account_state }
362 }
363 });
364
365 let mut tree = ServerTree::new(
366 owner,
367 &mut db.owned_files,
368 &mut db.shared_files,
369 &mut db.file_children,
370 &mut db.metas,
371 )?
372 .to_lazy();
373
374 let usage = tree.calculate_usage(owner)?;
375
376 let usage_str = bytes_to_human(usage);
377
378 Ok(AdminGetAccountInfoResponse {
379 account: AccountInfo {
380 username: account.username,
381 root,
382 payment_platform,
383 usage: usage_str,
384 },
385 })
386 }
387
388 pub async fn delete_account_helper(
389 &self, public_key: &PublicKey, free_username: bool,
390 ) -> Result<(), ServerError<DeleteAccountHelperError>> {
391 let mut docs_to_delete = Vec::new();
392
393 {
394 let mut lock = self.index_db.lock().await;
395 let db = lock.deref_mut();
396 let tx = db.begin_transaction()?;
397
398 let mut tree = ServerTree::new(
399 Owner(*public_key),
400 &mut db.owned_files,
401 &mut db.shared_files,
402 &mut db.file_children,
403 &mut db.metas,
404 )?
405 .to_lazy();
406 let metas_to_delete = tree.ids();
407
408 for id in metas_to_delete.clone() {
409 if !tree.calculate_deleted(&id)? {
410 let meta = tree.find(&id)?;
411 if meta.is_document() && &(meta.owner().0) == public_key {
412 if let Some(hmac) = meta.document_hmac() {
413 docs_to_delete.push((*meta.id(), *hmac));
414 }
415 }
416 }
417 }
418 db.owned_files.clear_key(&Owner(*public_key))?;
419 db.shared_files.clear_key(&Owner(*public_key))?;
420 db.last_seen.remove(&Owner(*public_key))?;
421
422 for id in metas_to_delete {
423 if let Some(meta) = db.metas.get().get(&id) {
424 if &(meta.owner().0) == public_key {
425 for user_access_key in meta.user_access_keys() {
426 let sharee = Owner(user_access_key.encrypted_for);
427 db.shared_files.remove(&sharee, meta.id())?;
428 }
429 db.metas.remove(&id)?;
430 db.file_children.clear_key(&id)?;
431 }
432 }
433 }
434
435 if free_username {
436 let username = db
437 .accounts
438 .remove(&Owner(*public_key))?
439 .ok_or(ClientError(DeleteAccountHelperError::UserNotFound))?
440 .username;
441 db.usernames.remove(&username)?;
442 }
443
444 tx.drop_safely()?;
445 drop(lock);
446 }
447
448 for (id, version) in docs_to_delete {
449 self.document_service.delete(&id, &version).await?;
450 }
451 Ok(())
452 }
453
454 pub fn is_admin<E: Debug>(
455 db: &ServerDb, public_key: &PublicKey, admins: &HashSet<Username>,
456 ) -> Result<bool, ServerError<E>> {
457 let is_admin = match db.accounts.get().get(&Owner(*public_key)) {
458 None => false,
459 Some(account) => admins.contains(&account.username),
460 };
461
462 Ok(is_admin)
463 }
464}
465
466#[derive(Debug)]
467pub enum GetUsageHelperError {
468 UserNotFound,
469}
470
471#[derive(Debug)]
472pub enum DeleteAccountHelperError {
473 UserNotFound,
474}