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