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