Skip to main content

lb_rs/model/
api.rs

1use crate::model::ValidationFailure;
2use crate::model::account::{Account, Username};
3use crate::model::crypto::*;
4use crate::model::file_metadata::{DocumentHmac, FileDiff, Owner};
5use crate::model::signed_file::SignedFile;
6use crate::service::debug::DebugInfo;
7use http::Method;
8use libsecp256k1::PublicKey;
9use serde::de::DeserializeOwned;
10use serde::{Deserialize, Serialize};
11use std::collections::{HashMap, HashSet};
12use std::fmt::Debug;
13use std::str::FromStr;
14use uuid::Uuid;
15
16use super::server_meta::ServerMeta;
17use super::signed_meta::SignedMeta;
18
19pub const FREE_TIER_USAGE_SIZE: u64 = 25000000;
20pub const PREMIUM_TIER_USAGE_SIZE: u64 = 30000000000;
21/// a fee of 1000 bytes allows 1000 file creations under the free tier.
22pub const METADATA_FEE: u64 = 1000;
23
24pub trait Request: Serialize + 'static {
25    type Response: Debug + DeserializeOwned + Clone;
26    type Error: Debug + DeserializeOwned + Clone;
27    const METHOD: Method;
28    const ROUTE: &'static str;
29}
30
31#[derive(Serialize, Deserialize, Debug, Clone)]
32pub struct RequestWrapper<T: Request> {
33    pub signed_request: ECSigned<T>,
34    pub client_version: String,
35}
36
37#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
38pub enum ErrorWrapper<E> {
39    Endpoint(E),
40    ClientUpdateRequired,
41    InvalidAuth,
42    ExpiredAuth,
43    InternalError,
44    BadRequest,
45}
46
47#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)]
48pub struct UpsertRequestV2 {
49    pub updates: Vec<FileDiff<SignedMeta>>,
50}
51
52impl Request for UpsertRequestV2 {
53    type Response = ();
54
55    type Error = UpsertError;
56    const METHOD: Method = Method::POST;
57    const ROUTE: &'static str = "/upsert-file-metadata-v2";
58}
59
60#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
61pub enum UpsertError {
62    /// Arises during a call to upsert, when the caller does not have the correct old version of the
63    /// File they're trying to modify
64    OldVersionIncorrect,
65
66    /// Arises during a call to upsert, when the old file is not known to the server
67    OldFileNotFound,
68
69    /// Arises during a call to upsert, when the caller suggests that a file is new, but the id already
70    /// exists
71    OldVersionRequired,
72
73    /// Arises during a call to upsert, when the person making the request is not an owner of the file
74    /// or has not signed the update
75    NotPermissioned,
76
77    /// Arises during a call to upsert, when a diff's new.id != old.id
78    DiffMalformed,
79
80    /// Metas in upsert cannot contain changes to digest
81    HmacModificationInvalid,
82
83    /// Metas in upsert cannot contain changes to doc size
84    SizeModificationInvalid,
85
86    RootModificationInvalid,
87
88    /// Found update to a deleted file
89    DeletedFileUpdated,
90
91    /// Over the User's Tier Limit
92    UsageIsOverDataCap,
93
94    /// Other misc validation failures
95    Validation(ValidationFailure),
96}
97
98#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)]
99pub struct ChangeDocRequestV2 {
100    pub diff: FileDiff<SignedMeta>,
101    pub new_content: EncryptedDocument,
102}
103
104#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
105pub enum ChangeDocError {
106    HmacMissing,
107    NewSizeIncorrect,
108    DocumentNotFound,
109    DocumentDeleted,
110    NotPermissioned,
111    OldVersionIncorrect,
112    DiffMalformed,
113    UsageIsOverDataCap,
114}
115
116impl Request for ChangeDocRequestV2 {
117    type Response = ();
118    type Error = ChangeDocError;
119    const METHOD: Method = Method::PUT;
120    const ROUTE: &'static str = "/change-document-content-v2";
121}
122
123#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
124pub struct GetDocRequest {
125    pub id: Uuid,
126    pub hmac: DocumentHmac,
127}
128
129#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
130pub struct GetDocumentResponse {
131    pub content: EncryptedDocument,
132}
133
134#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
135pub enum GetDocumentError {
136    DocumentNotFound,
137    NotPermissioned,
138    BandwidthExceeded,
139}
140
141impl Request for GetDocRequest {
142    type Response = GetDocumentResponse;
143    type Error = GetDocumentError;
144    const METHOD: Method = Method::GET;
145    const ROUTE: &'static str = "/get-document";
146}
147
148#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
149pub struct GetPublicKeyRequest {
150    pub username: String,
151}
152
153#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
154pub struct GetPublicKeyResponse {
155    pub key: PublicKey,
156}
157
158#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
159pub enum GetPublicKeyError {
160    InvalidUsername,
161    UserNotFound,
162}
163
164impl Request for GetPublicKeyRequest {
165    type Response = GetPublicKeyResponse;
166    type Error = GetPublicKeyError;
167    const METHOD: Method = Method::GET;
168    const ROUTE: &'static str = "/get-public-key";
169}
170
171#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
172pub struct GetUsernameRequest {
173    pub key: PublicKey,
174}
175
176#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
177pub struct GetUsernameResponse {
178    pub username: String,
179}
180
181#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
182pub enum GetUsernameError {
183    UserNotFound,
184}
185
186impl Request for GetUsernameRequest {
187    type Response = GetUsernameResponse;
188    type Error = GetUsernameError;
189    const METHOD: Method = Method::GET;
190    const ROUTE: &'static str = "/get-username";
191}
192
193#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
194pub struct GetUsageRequest {}
195
196#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
197pub struct GetUsageResponse {
198    pub usages: Vec<FileUsage>,
199    pub cap: u64,
200}
201
202impl GetUsageResponse {
203    pub fn sum_server_usage(&self) -> u64 {
204        self.usages.iter().map(|usage| usage.size_bytes).sum()
205    }
206}
207
208#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone, Copy)]
209pub struct FileUsage {
210    pub file_id: Uuid,
211    pub size_bytes: u64,
212}
213
214#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
215pub enum GetUsageError {
216    UserNotFound,
217}
218
219impl Request for GetUsageRequest {
220    type Response = GetUsageResponse;
221    type Error = GetUsageError;
222    const METHOD: Method = Method::GET;
223    const ROUTE: &'static str = "/get-usage";
224}
225
226#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
227pub struct GetFileIdsRequest {}
228
229#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
230pub struct GetFileIdsResponse {
231    pub ids: HashSet<Uuid>,
232}
233
234#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
235pub enum GetFileIdsError {
236    UserNotFound,
237}
238
239impl Request for GetFileIdsRequest {
240    type Response = GetFileIdsResponse;
241    type Error = GetFileIdsError;
242    const METHOD: Method = Method::GET;
243    const ROUTE: &'static str = "/get-file-ids";
244}
245
246#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
247pub struct GetUpdatesRequestV2 {
248    pub since_metadata_version: u64,
249}
250
251#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)]
252pub struct GetUpdatesResponse {
253    pub as_of_metadata_version: u64,
254    pub file_metadata: Vec<SignedFile>,
255}
256
257#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)]
258pub struct GetUpdatesResponseV2 {
259    pub as_of_metadata_version: u64,
260    pub file_metadata: Vec<SignedMeta>,
261}
262
263#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
264pub enum GetUpdatesError {
265    UserNotFound,
266}
267
268impl Request for GetUpdatesRequestV2 {
269    type Response = GetUpdatesResponseV2;
270    type Error = GetUpdatesError;
271    const METHOD: Method = Method::GET;
272    const ROUTE: &'static str = "/get-updates-v2";
273}
274
275#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)]
276pub struct NewAccountRequestV2 {
277    pub username: Username,
278    pub public_key: PublicKey,
279    pub root_folder: SignedMeta,
280}
281
282impl NewAccountRequestV2 {
283    pub fn new(account: &Account, root_folder: &SignedMeta) -> Self {
284        let root_folder = root_folder.clone();
285        NewAccountRequestV2 {
286            username: account.username.clone(),
287            public_key: account.public_key(),
288            root_folder,
289        }
290    }
291}
292
293impl Request for NewAccountRequestV2 {
294    type Response = NewAccountResponse;
295    type Error = NewAccountError;
296    const METHOD: Method = Method::POST;
297    const ROUTE: &'static str = "/new-account-v2";
298}
299
300#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
301pub struct NewAccountResponse {
302    pub last_synced: u64,
303}
304
305#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
306pub enum NewAccountError {
307    UsernameTaken,
308    PublicKeyTaken,
309    InvalidUsername,
310    FileIdTaken,
311    Disabled,
312    RateLimited,
313}
314
315#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
316pub struct GetBuildInfoRequest {}
317
318#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
319pub enum GetBuildInfoError {}
320
321#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
322pub struct GetBuildInfoResponse {
323    pub build_version: String,
324    pub git_commit_hash: String,
325}
326
327impl Request for GetBuildInfoRequest {
328    type Response = GetBuildInfoResponse;
329    type Error = GetBuildInfoError;
330    const METHOD: Method = Method::GET;
331    const ROUTE: &'static str = "/get-build-info";
332}
333
334#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
335pub struct DeleteAccountRequest {}
336
337#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
338pub enum DeleteAccountError {
339    UserNotFound,
340}
341
342impl Request for DeleteAccountRequest {
343    type Response = ();
344    type Error = DeleteAccountError;
345    const METHOD: Method = Method::DELETE;
346    const ROUTE: &'static str = "/delete-account";
347}
348
349#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
350pub enum PaymentMethod {
351    NewCard { number: String, exp_year: i32, exp_month: i32, cvc: String },
352    OldCard,
353}
354
355#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
356pub enum StripeAccountTier {
357    Premium(PaymentMethod),
358}
359
360#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
361pub struct UpgradeAccountStripeRequest {
362    pub account_tier: StripeAccountTier,
363}
364
365#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
366pub struct UpgradeAccountStripeResponse {}
367
368#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
369pub enum UpgradeAccountStripeError {
370    OldCardDoesNotExist,
371    AlreadyPremium,
372    CardDecline,
373    InsufficientFunds,
374    TryAgain,
375    CardNotSupported,
376    ExpiredCard,
377    InvalidCardNumber,
378    InvalidCardExpYear,
379    InvalidCardExpMonth,
380    InvalidCardCvc,
381    ExistingRequestPending,
382    UserNotFound,
383}
384
385impl Request for UpgradeAccountStripeRequest {
386    type Response = UpgradeAccountStripeResponse;
387    type Error = UpgradeAccountStripeError;
388    const METHOD: Method = Method::POST;
389    const ROUTE: &'static str = "/upgrade-account-stripe";
390}
391
392#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
393pub struct UpgradeAccountGooglePlayRequest {
394    pub purchase_token: String,
395    pub account_id: String,
396}
397
398#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
399pub struct UpgradeAccountGooglePlayResponse {}
400
401#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
402pub enum UpgradeAccountGooglePlayError {
403    AlreadyPremium,
404    InvalidPurchaseToken,
405    ExistingRequestPending,
406    UserNotFound,
407}
408
409impl Request for UpgradeAccountGooglePlayRequest {
410    type Response = UpgradeAccountGooglePlayResponse;
411    type Error = UpgradeAccountGooglePlayError;
412    const METHOD: Method = Method::POST;
413    const ROUTE: &'static str = "/upgrade-account-google-play";
414}
415
416#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
417pub struct UpgradeAccountAppStoreRequest {
418    pub original_transaction_id: String,
419    pub app_account_token: String,
420}
421
422#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
423pub struct UpgradeAccountAppStoreResponse {}
424
425#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
426pub enum UpgradeAccountAppStoreError {
427    AppStoreAccountAlreadyLinked,
428    AlreadyPremium,
429    InvalidAuthDetails,
430    ExistingRequestPending,
431    UserNotFound,
432}
433
434impl Request for UpgradeAccountAppStoreRequest {
435    type Response = UpgradeAccountAppStoreResponse;
436    type Error = UpgradeAccountAppStoreError;
437    const METHOD: Method = Method::POST;
438    const ROUTE: &'static str = "/upgrade-account-app-store";
439}
440
441#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
442pub struct CancelSubscriptionRequest {}
443
444#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
445pub struct CancelSubscriptionResponse {}
446
447#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
448pub enum CancelSubscriptionError {
449    NotPremium,
450    AlreadyCanceled,
451    UsageIsOverFreeTierDataCap,
452    UserNotFound,
453    ExistingRequestPending,
454    CannotCancelForAppStore,
455}
456
457impl Request for CancelSubscriptionRequest {
458    type Response = CancelSubscriptionResponse;
459    type Error = CancelSubscriptionError;
460    const METHOD: Method = Method::DELETE;
461    const ROUTE: &'static str = "/cancel-subscription";
462}
463
464#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
465pub struct GetSubscriptionInfoRequest {}
466
467#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
468pub struct SubscriptionInfo {
469    pub payment_platform: PaymentPlatform,
470    pub period_end: UnixTimeMillis,
471}
472
473#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
474#[serde(tag = "tag")]
475pub enum PaymentPlatform {
476    Stripe { card_last_4_digits: String },
477    GooglePlay { account_state: GooglePlayAccountState },
478    AppStore { account_state: AppStoreAccountState },
479}
480
481#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
482pub struct GetSubscriptionInfoResponse {
483    pub subscription_info: Option<SubscriptionInfo>,
484}
485
486#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
487pub enum GetSubscriptionInfoError {
488    UserNotFound,
489}
490
491impl Request for GetSubscriptionInfoRequest {
492    type Response = GetSubscriptionInfoResponse;
493    type Error = GetSubscriptionInfoError;
494    const METHOD: Method = Method::GET;
495    const ROUTE: &'static str = "/get-subscription-info";
496}
497
498#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
499pub struct GetSubscriptionInfoRequestV2 {}
500
501#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
502pub struct SubscriptionInfoV2 {
503    pub payment_platform: PaymentPlatformV2,
504    pub period_end: UnixTimeMillis,
505}
506
507#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
508pub enum PaymentPlatformV2 {
509    Stripe { card_last_4_digits: String },
510    GooglePlay { account_state: GooglePlayAccountState },
511    AppStore { account_state: AppStoreAccountState },
512}
513
514#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
515pub struct GetSubscriptionInfoResponseV2 {
516    pub subscription_info: Option<SubscriptionInfoV2>,
517}
518
519impl Request for GetSubscriptionInfoRequestV2 {
520    type Response = GetSubscriptionInfoResponseV2;
521    type Error = GetSubscriptionInfoError;
522    const METHOD: Method = Method::GET;
523    const ROUTE: &'static str = "/get-subscription-info-v2";
524}
525
526impl From<PaymentPlatformV2> for PaymentPlatform {
527    fn from(v: PaymentPlatformV2) -> Self {
528        match v {
529            PaymentPlatformV2::Stripe { card_last_4_digits } => {
530                PaymentPlatform::Stripe { card_last_4_digits }
531            }
532            PaymentPlatformV2::GooglePlay { account_state } => {
533                PaymentPlatform::GooglePlay { account_state }
534            }
535            PaymentPlatformV2::AppStore { account_state } => {
536                PaymentPlatform::AppStore { account_state }
537            }
538        }
539    }
540}
541
542impl From<SubscriptionInfoV2> for SubscriptionInfo {
543    fn from(v: SubscriptionInfoV2) -> Self {
544        SubscriptionInfo { payment_platform: v.payment_platform.into(), period_end: v.period_end }
545    }
546}
547
548#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
549pub struct UpsertDebugInfoRequest {
550    pub debug_info: DebugInfo,
551}
552
553#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
554pub enum UpsertDebugInfoError {
555    NotPermissioned,
556}
557
558impl Request for UpsertDebugInfoRequest {
559    type Response = ();
560    type Error = UpsertDebugInfoError;
561    const METHOD: Method = Method::POST;
562    const ROUTE: &'static str = "/upsert-debug-info";
563}
564
565#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
566pub struct AdminDisappearAccountRequest {
567    pub username: String,
568}
569
570#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
571pub enum AdminDisappearAccountError {
572    NotPermissioned,
573    UserNotFound,
574}
575
576impl Request for AdminDisappearAccountRequest {
577    type Response = ();
578    type Error = AdminDisappearAccountError;
579    const METHOD: Method = Method::DELETE;
580    const ROUTE: &'static str = "/admin-disappear-account";
581}
582
583#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
584pub struct AdminDisappearFileRequest {
585    pub id: Uuid,
586}
587
588#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
589pub enum AdminDisappearFileError {
590    NotPermissioned,
591    FileNonexistent,
592    RootModificationInvalid,
593}
594
595impl Request for AdminDisappearFileRequest {
596    type Response = ();
597    type Error = AdminDisappearFileError;
598    const METHOD: Method = Method::DELETE;
599    const ROUTE: &'static str = "/admin-disappear-file";
600}
601
602#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
603pub struct AdminValidateAccountRequest {
604    pub username: String,
605}
606
607#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone, Default)]
608pub struct AdminValidateAccount {
609    pub tree_validation_failures: Vec<ValidationFailure>,
610    pub documents_missing_size: Vec<Uuid>,
611    pub documents_missing_content: Vec<Uuid>,
612}
613
614impl AdminValidateAccount {
615    pub fn is_empty(&self) -> bool {
616        self.tree_validation_failures.is_empty()
617            && self.documents_missing_content.is_empty()
618            && self.documents_missing_size.is_empty()
619    }
620}
621
622#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
623pub enum AdminValidateAccountError {
624    NotPermissioned,
625    UserNotFound,
626}
627
628impl Request for AdminValidateAccountRequest {
629    type Response = AdminValidateAccount;
630    type Error = AdminValidateAccountError;
631    const METHOD: Method = Method::GET;
632    const ROUTE: &'static str = "/admin-validate-account";
633}
634
635#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
636pub struct AdminValidateServerRequest {}
637
638#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone, Default)]
639pub struct AdminValidateServer {
640    // accounts
641    pub users_with_validation_failures: HashMap<Username, AdminValidateAccount>,
642    // index integrity
643    pub usernames_mapped_to_wrong_accounts: HashMap<String, String>,
644    // mapped username -> account username
645    pub usernames_mapped_to_nonexistent_accounts: HashMap<String, Owner>,
646    pub usernames_unmapped_to_accounts: HashSet<String>,
647    pub owners_mapped_to_unowned_files: HashMap<Owner, HashSet<Uuid>>,
648    pub owners_mapped_to_nonexistent_files: HashMap<Owner, HashSet<Uuid>>,
649    pub owners_unmapped_to_owned_files: HashMap<Owner, HashSet<Uuid>>,
650    pub owners_unmapped: HashSet<Owner>,
651    pub sharees_mapped_to_unshared_files: HashMap<Owner, HashSet<Uuid>>,
652    pub sharees_mapped_to_nonexistent_files: HashMap<Owner, HashSet<Uuid>>,
653    pub sharees_mapped_for_owned_files: HashMap<Owner, HashSet<Uuid>>,
654    pub sharees_mapped_for_deleted_files: HashMap<Owner, HashSet<Uuid>>,
655    pub sharees_unmapped_to_shared_files: HashMap<Owner, HashSet<Uuid>>,
656    pub sharees_unmapped: HashSet<Owner>,
657    pub files_mapped_as_parent_to_non_children: HashMap<Uuid, HashSet<Uuid>>,
658    pub files_mapped_as_parent_to_nonexistent_children: HashMap<Uuid, HashSet<Uuid>>,
659    pub files_mapped_as_parent_to_self: HashSet<Uuid>,
660    pub files_unmapped_as_parent_to_children: HashMap<Uuid, HashSet<Uuid>>,
661    pub files_unmapped_as_parent: HashSet<Uuid>,
662    pub sizes_mapped_for_files_without_hmac: HashSet<Uuid>,
663    pub sizes_mapped_for_nonexistent_files: HashSet<Uuid>,
664    pub sizes_unmapped_for_files_with_hmac: HashSet<Uuid>,
665    // document presence
666    pub files_with_hmacs_and_no_contents: HashSet<Uuid>,
667}
668
669#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
670pub enum AdminValidateServerError {
671    NotPermissioned,
672}
673
674impl Request for AdminValidateServerRequest {
675    type Response = AdminValidateServer;
676    type Error = AdminValidateServerError;
677    const METHOD: Method = Method::GET;
678    const ROUTE: &'static str = "/admin-validate-server";
679}
680
681#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
682pub struct AdminListUsersRequest {
683    pub filter: Option<AccountFilter>,
684}
685
686#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
687pub enum AccountFilter {
688    Premium,
689    AppStorePremium,
690    StripePremium,
691    GooglePlayPremium,
692}
693
694#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
695pub struct AdminListUsersResponse {
696    pub users: Vec<Username>,
697}
698
699#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
700pub enum AdminListUsersError {
701    NotPermissioned,
702}
703
704impl Request for AdminListUsersRequest {
705    type Response = AdminListUsersResponse;
706    type Error = AdminListUsersError;
707    const METHOD: Method = Method::GET;
708    const ROUTE: &'static str = "/admin-list-users";
709}
710
711#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
712pub struct AdminGetAccountInfoRequest {
713    pub identifier: AccountIdentifier,
714}
715
716#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
717pub enum AccountIdentifier {
718    PublicKey(PublicKey),
719    Username(Username),
720}
721
722#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
723pub struct AdminGetAccountInfoResponse {
724    pub account: AccountInfo,
725}
726
727#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
728pub struct AccountInfo {
729    pub username: String,
730    pub root: Uuid,
731    pub payment_platform: Option<PaymentPlatform>,
732    pub usage: String,
733}
734
735#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
736pub enum AdminGetAccountInfoError {
737    UserNotFound,
738    NotPermissioned,
739}
740
741impl Request for AdminGetAccountInfoRequest {
742    type Response = AdminGetAccountInfoResponse;
743    type Error = AdminGetAccountInfoError;
744    const METHOD: Method = Method::GET;
745    const ROUTE: &'static str = "/admin-get-account-info";
746}
747
748#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
749pub struct AdminFileInfoRequest {
750    pub id: Uuid,
751}
752
753#[derive(Serialize, Deserialize, Debug, Clone)]
754pub struct AdminFileInfoResponse {
755    pub file: ServerMeta,
756    pub ancestors: Vec<ServerMeta>,
757    pub descendants: Vec<ServerMeta>,
758}
759
760#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
761pub enum AdminFileInfoError {
762    NotPermissioned,
763    FileNonexistent,
764}
765
766impl Request for AdminFileInfoRequest {
767    type Response = AdminFileInfoResponse;
768    type Error = AdminFileInfoError;
769    const METHOD: Method = Method::GET;
770    const ROUTE: &'static str = "/admin-file-info";
771}
772
773#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
774pub enum AdminSetUserTierInfo {
775    Stripe {
776        customer_id: String,
777        customer_name: Uuid,
778        payment_method_id: String,
779        last_4: String,
780        subscription_id: String,
781        expiration_time: UnixTimeMillis,
782        account_state: StripeAccountState,
783    },
784
785    GooglePlay {
786        purchase_token: String,
787        expiration_time: UnixTimeMillis,
788        account_state: GooglePlayAccountState,
789    },
790
791    AppStore {
792        account_token: String,
793        original_transaction_id: String,
794        expiration_time: UnixTimeMillis,
795        account_state: AppStoreAccountState,
796    },
797
798    Free,
799}
800
801#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
802pub struct AdminSetUserTierRequest {
803    pub username: String,
804    pub info: AdminSetUserTierInfo,
805}
806
807#[derive(Serialize, Deserialize, Debug, Clone)]
808pub struct AdminSetUserTierResponse {}
809
810#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
811pub enum AdminSetUserTierError {
812    UserNotFound,
813    NotPermissioned,
814    ExistingRequestPending,
815}
816
817impl Request for AdminSetUserTierRequest {
818    type Response = AdminSetUserTierResponse;
819    type Error = AdminSetUserTierError;
820    const METHOD: Method = Method::POST;
821    const ROUTE: &'static str = "/admin-set-user-tier";
822}
823
824// number of milliseconds that have elapsed since the unix epoch
825pub type UnixTimeMillis = u64;
826
827#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Clone, Copy)]
828pub enum ServerIndex {
829    OwnedFiles,
830    SharedFiles,
831    FileChildren,
832}
833
834#[derive(Serialize, Deserialize, Debug, Clone)]
835pub struct AdminRebuildIndexRequest {
836    pub index: ServerIndex,
837}
838
839#[derive(Serialize, Deserialize, Debug, Clone)]
840pub enum AdminRebuildIndexError {
841    NotPermissioned,
842}
843
844impl Request for AdminRebuildIndexRequest {
845    type Response = ();
846    type Error = AdminRebuildIndexError;
847    const METHOD: Method = Method::POST;
848    const ROUTE: &'static str = "/admin-rebuild-index";
849}
850
851#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
852pub enum StripeAccountState {
853    Ok,
854    InvoiceFailed,
855    Canceled,
856}
857
858#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
859pub enum GooglePlayAccountState {
860    Ok,
861    Canceled,
862    GracePeriod,
863    OnHold,
864}
865
866#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
867pub enum AppStoreAccountState {
868    Ok,
869    GracePeriod,
870    FailedToRenew,
871    Expired,
872}
873
874impl FromStr for StripeAccountState {
875    type Err = ();
876
877    fn from_str(s: &str) -> Result<Self, Self::Err> {
878        match s {
879            "Ok" => Ok(StripeAccountState::Ok),
880            "Canceled" => Ok(StripeAccountState::Canceled),
881            "InvoiceFailed" => Ok(StripeAccountState::InvoiceFailed),
882            _ => Err(()),
883        }
884    }
885}
886
887impl FromStr for GooglePlayAccountState {
888    type Err = ();
889
890    fn from_str(s: &str) -> Result<Self, Self::Err> {
891        match s {
892            "Ok" => Ok(GooglePlayAccountState::Ok),
893            "Canceled" => Ok(GooglePlayAccountState::Canceled),
894            "GracePeriod" => Ok(GooglePlayAccountState::GracePeriod),
895            "OnHold" => Ok(GooglePlayAccountState::OnHold),
896            _ => Err(()),
897        }
898    }
899}
900
901impl FromStr for AppStoreAccountState {
902    type Err = ();
903
904    fn from_str(s: &str) -> Result<Self, Self::Err> {
905        match s {
906            "Ok" => Ok(AppStoreAccountState::Ok),
907            "Expired" => Ok(AppStoreAccountState::Expired),
908            "GracePeriod" => Ok(AppStoreAccountState::GracePeriod),
909            "FailedToRenew" => Ok(AppStoreAccountState::FailedToRenew),
910            _ => Err(()),
911        }
912    }
913}