lb_rs/model/
api.rs

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