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 UpsertDebugInfoRequest {
500    pub debug_info: DebugInfo,
501}
502
503#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
504pub enum UpsertDebugInfoError {
505    NotPermissioned,
506}
507
508impl Request for UpsertDebugInfoRequest {
509    type Response = ();
510    type Error = UpsertDebugInfoError;
511    const METHOD: Method = Method::POST;
512    const ROUTE: &'static str = "/upsert-debug-info";
513}
514
515#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
516pub struct AdminDisappearAccountRequest {
517    pub username: String,
518}
519
520#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
521pub enum AdminDisappearAccountError {
522    NotPermissioned,
523    UserNotFound,
524}
525
526impl Request for AdminDisappearAccountRequest {
527    type Response = ();
528    type Error = AdminDisappearAccountError;
529    const METHOD: Method = Method::DELETE;
530    const ROUTE: &'static str = "/admin-disappear-account";
531}
532
533#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
534pub struct AdminDisappearFileRequest {
535    pub id: Uuid,
536}
537
538#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
539pub enum AdminDisappearFileError {
540    NotPermissioned,
541    FileNonexistent,
542    RootModificationInvalid,
543}
544
545impl Request for AdminDisappearFileRequest {
546    type Response = ();
547    type Error = AdminDisappearFileError;
548    const METHOD: Method = Method::DELETE;
549    const ROUTE: &'static str = "/admin-disappear-file";
550}
551
552#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
553pub struct AdminValidateAccountRequest {
554    pub username: String,
555}
556
557#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone, Default)]
558pub struct AdminValidateAccount {
559    pub tree_validation_failures: Vec<ValidationFailure>,
560    pub documents_missing_size: Vec<Uuid>,
561    pub documents_missing_content: Vec<Uuid>,
562}
563
564impl AdminValidateAccount {
565    pub fn is_empty(&self) -> bool {
566        self.tree_validation_failures.is_empty()
567            && self.documents_missing_content.is_empty()
568            && self.documents_missing_size.is_empty()
569    }
570}
571
572#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
573pub enum AdminValidateAccountError {
574    NotPermissioned,
575    UserNotFound,
576}
577
578impl Request for AdminValidateAccountRequest {
579    type Response = AdminValidateAccount;
580    type Error = AdminValidateAccountError;
581    const METHOD: Method = Method::GET;
582    const ROUTE: &'static str = "/admin-validate-account";
583}
584
585#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
586pub struct AdminValidateServerRequest {}
587
588#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone, Default)]
589pub struct AdminValidateServer {
590    // accounts
591    pub users_with_validation_failures: HashMap<Username, AdminValidateAccount>,
592    // index integrity
593    pub usernames_mapped_to_wrong_accounts: HashMap<String, String>,
594    // mapped username -> account username
595    pub usernames_mapped_to_nonexistent_accounts: HashMap<String, Owner>,
596    pub usernames_unmapped_to_accounts: HashSet<String>,
597    pub owners_mapped_to_unowned_files: HashMap<Owner, HashSet<Uuid>>,
598    pub owners_mapped_to_nonexistent_files: HashMap<Owner, HashSet<Uuid>>,
599    pub owners_unmapped_to_owned_files: HashMap<Owner, HashSet<Uuid>>,
600    pub owners_unmapped: HashSet<Owner>,
601    pub sharees_mapped_to_unshared_files: HashMap<Owner, HashSet<Uuid>>,
602    pub sharees_mapped_to_nonexistent_files: HashMap<Owner, HashSet<Uuid>>,
603    pub sharees_mapped_for_owned_files: HashMap<Owner, HashSet<Uuid>>,
604    pub sharees_mapped_for_deleted_files: HashMap<Owner, HashSet<Uuid>>,
605    pub sharees_unmapped_to_shared_files: HashMap<Owner, HashSet<Uuid>>,
606    pub sharees_unmapped: HashSet<Owner>,
607    pub files_mapped_as_parent_to_non_children: HashMap<Uuid, HashSet<Uuid>>,
608    pub files_mapped_as_parent_to_nonexistent_children: HashMap<Uuid, HashSet<Uuid>>,
609    pub files_mapped_as_parent_to_self: HashSet<Uuid>,
610    pub files_unmapped_as_parent_to_children: HashMap<Uuid, HashSet<Uuid>>,
611    pub files_unmapped_as_parent: HashSet<Uuid>,
612    pub sizes_mapped_for_files_without_hmac: HashSet<Uuid>,
613    pub sizes_mapped_for_nonexistent_files: HashSet<Uuid>,
614    pub sizes_unmapped_for_files_with_hmac: HashSet<Uuid>,
615    // document presence
616    pub files_with_hmacs_and_no_contents: HashSet<Uuid>,
617}
618
619#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
620pub enum AdminValidateServerError {
621    NotPermissioned,
622}
623
624impl Request for AdminValidateServerRequest {
625    type Response = AdminValidateServer;
626    type Error = AdminValidateServerError;
627    const METHOD: Method = Method::GET;
628    const ROUTE: &'static str = "/admin-validate-server";
629}
630
631#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
632pub struct AdminListUsersRequest {
633    pub filter: Option<AccountFilter>,
634}
635
636#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
637pub enum AccountFilter {
638    Premium,
639    AppStorePremium,
640    StripePremium,
641    GooglePlayPremium,
642}
643
644#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
645pub struct AdminListUsersResponse {
646    pub users: Vec<Username>,
647}
648
649#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
650pub enum AdminListUsersError {
651    NotPermissioned,
652}
653
654impl Request for AdminListUsersRequest {
655    type Response = AdminListUsersResponse;
656    type Error = AdminListUsersError;
657    const METHOD: Method = Method::GET;
658    const ROUTE: &'static str = "/admin-list-users";
659}
660
661#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
662pub struct AdminGetAccountInfoRequest {
663    pub identifier: AccountIdentifier,
664}
665
666#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
667pub enum AccountIdentifier {
668    PublicKey(PublicKey),
669    Username(Username),
670}
671
672#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
673pub struct AdminGetAccountInfoResponse {
674    pub account: AccountInfo,
675}
676
677#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
678pub struct AccountInfo {
679    pub username: String,
680    pub root: Uuid,
681    pub payment_platform: Option<PaymentPlatform>,
682    pub usage: String,
683}
684
685#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
686pub enum AdminGetAccountInfoError {
687    UserNotFound,
688    NotPermissioned,
689}
690
691impl Request for AdminGetAccountInfoRequest {
692    type Response = AdminGetAccountInfoResponse;
693    type Error = AdminGetAccountInfoError;
694    const METHOD: Method = Method::GET;
695    const ROUTE: &'static str = "/admin-get-account-info";
696}
697
698#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
699pub struct AdminFileInfoRequest {
700    pub id: Uuid,
701}
702
703#[derive(Serialize, Deserialize, Debug, Clone)]
704pub struct AdminFileInfoResponse {
705    pub file: ServerMeta,
706    pub ancestors: Vec<ServerMeta>,
707    pub descendants: Vec<ServerMeta>,
708}
709
710#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
711pub enum AdminFileInfoError {
712    NotPermissioned,
713    FileNonexistent,
714}
715
716impl Request for AdminFileInfoRequest {
717    type Response = AdminFileInfoResponse;
718    type Error = AdminFileInfoError;
719    const METHOD: Method = Method::GET;
720    const ROUTE: &'static str = "/admin-file-info";
721}
722
723#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
724pub enum AdminSetUserTierInfo {
725    Stripe {
726        customer_id: String,
727        customer_name: Uuid,
728        payment_method_id: String,
729        last_4: String,
730        subscription_id: String,
731        expiration_time: UnixTimeMillis,
732        account_state: StripeAccountState,
733    },
734
735    GooglePlay {
736        purchase_token: String,
737        expiration_time: UnixTimeMillis,
738        account_state: GooglePlayAccountState,
739    },
740
741    AppStore {
742        account_token: String,
743        original_transaction_id: String,
744        expiration_time: UnixTimeMillis,
745        account_state: AppStoreAccountState,
746    },
747
748    Free,
749}
750
751#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
752pub struct AdminSetUserTierRequest {
753    pub username: String,
754    pub info: AdminSetUserTierInfo,
755}
756
757#[derive(Serialize, Deserialize, Debug, Clone)]
758pub struct AdminSetUserTierResponse {}
759
760#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
761pub enum AdminSetUserTierError {
762    UserNotFound,
763    NotPermissioned,
764    ExistingRequestPending,
765}
766
767impl Request for AdminSetUserTierRequest {
768    type Response = AdminSetUserTierResponse;
769    type Error = AdminSetUserTierError;
770    const METHOD: Method = Method::POST;
771    const ROUTE: &'static str = "/admin-set-user-tier";
772}
773
774// number of milliseconds that have elapsed since the unix epoch
775pub type UnixTimeMillis = u64;
776
777#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Clone, Copy)]
778pub enum ServerIndex {
779    OwnedFiles,
780    SharedFiles,
781    FileChildren,
782}
783
784#[derive(Serialize, Deserialize, Debug, Clone)]
785pub struct AdminRebuildIndexRequest {
786    pub index: ServerIndex,
787}
788
789#[derive(Serialize, Deserialize, Debug, Clone)]
790pub enum AdminRebuildIndexError {
791    NotPermissioned,
792}
793
794impl Request for AdminRebuildIndexRequest {
795    type Response = ();
796    type Error = AdminRebuildIndexError;
797    const METHOD: Method = Method::POST;
798    const ROUTE: &'static str = "/admin-rebuild-index";
799}
800
801#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
802pub enum StripeAccountState {
803    Ok,
804    InvoiceFailed,
805    Canceled,
806}
807
808#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
809pub enum GooglePlayAccountState {
810    Ok,
811    Canceled,
812    GracePeriod,
813    OnHold,
814}
815
816#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
817pub enum AppStoreAccountState {
818    Ok,
819    GracePeriod,
820    FailedToRenew,
821    Expired,
822}
823
824impl FromStr for StripeAccountState {
825    type Err = ();
826
827    fn from_str(s: &str) -> Result<Self, Self::Err> {
828        match s {
829            "Ok" => Ok(StripeAccountState::Ok),
830            "Canceled" => Ok(StripeAccountState::Canceled),
831            "InvoiceFailed" => Ok(StripeAccountState::InvoiceFailed),
832            _ => Err(()),
833        }
834    }
835}
836
837impl FromStr for GooglePlayAccountState {
838    type Err = ();
839
840    fn from_str(s: &str) -> Result<Self, Self::Err> {
841        match s {
842            "Ok" => Ok(GooglePlayAccountState::Ok),
843            "Canceled" => Ok(GooglePlayAccountState::Canceled),
844            "GracePeriod" => Ok(GooglePlayAccountState::GracePeriod),
845            "OnHold" => Ok(GooglePlayAccountState::OnHold),
846            _ => Err(()),
847        }
848    }
849}
850
851impl FromStr for AppStoreAccountState {
852    type Err = ();
853
854    fn from_str(s: &str) -> Result<Self, Self::Err> {
855        match s {
856            "Ok" => Ok(AppStoreAccountState::Ok),
857            "Expired" => Ok(AppStoreAccountState::Expired),
858            "GracePeriod" => Ok(AppStoreAccountState::GracePeriod),
859            "FailedToRenew" => Ok(AppStoreAccountState::FailedToRenew),
860            _ => Err(()),
861        }
862    }
863}