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