From 95405fa3aaa5ce744a7daeac3516285a6da0bdfb Mon Sep 17 00:00:00 2001 From: Craig Colegrove <34786857+giarc3@users.noreply.github.com> Date: Mon, 1 Jul 2024 12:50:38 -0700 Subject: [PATCH] Prepare 3.0 (#321) --- .github/workflows/ci.yaml | 3 +- .github/workflows/release.yaml | 9 +++++ CHANGELOG.md | 8 +++-- Cargo.toml | 7 ++-- benches/ironoxide_bench.rs | 6 +++- flake.lock | 58 +++++++------------------------ rust-toolchain.toml | 2 +- src/document.rs | 36 ++++++++++--------- src/document/advanced.rs | 12 +++---- src/group.rs | 43 +++++++++++++---------- src/internal/user_api.rs | 4 +-- src/internal/user_api/requests.rs | 1 - src/lib.rs | 3 +- src/policy.rs | 8 ++--- src/prelude.rs | 2 ++ src/search.rs | 9 ++--- src/user.rs | 37 ++++++++++++-------- 17 files changed, 124 insertions(+), 124 deletions(-) create mode 100644 .github/workflows/release.yaml diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 9b8d48f9..6ccfc5e5 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -7,6 +7,7 @@ on: pull_request: schedule: - cron: "0 14 * * 1" # Mondays at 2pm UTC + workflow_dispatch: null jobs: cargo-test: @@ -36,7 +37,7 @@ jobs: features: default # MSRV - os: ubuntu-22.04 - toolchain: 1.74.0 + toolchain: 1.75.0 features: default steps: - uses: actions/checkout@v4 diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml new file mode 100644 index 00000000..27e17ed1 --- /dev/null +++ b/.github/workflows/release.yaml @@ -0,0 +1,9 @@ +name: Rust Release + +on: + workflow_dispatch: null + +jobs: + rust-release: + uses: IronCoreLabs/workflows/.github/workflows/rust-release.yaml@rust-release-v1 + secrets: inherit diff --git a/CHANGELOG.md b/CHANGELOG.md index 46ab1274..1c3d478f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,9 +1,11 @@ # Changelog -## 3.0.0 (Unreleased) +## 3.0.0 -- `itertools` will be updated to the latest version and re-exported for use in public functions. - - After this change, updates to `itertools` will not automatically be breaking changes. +- [[#321](https://github.com/IronCoreLabs/ironoxide/issues/321)] + - Bump MSRV to 1.75.0. + - Upgrade dependencies. This includes an update to `itertools`, which is part of the public API. + - Re-export `itertools::EitherOrBoth`. Updates to `itertools` will not automatically be considered breaking changes going forward. ## 2.1.0 diff --git a/Cargo.toml b/Cargo.toml index 182efc95..e806163e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ironoxide" -version = "2.1.0" +version = "3.0.0" authors = ["IronCore Labs "] readme = "README.md" license = "AGPL-3.0-only" @@ -16,10 +16,9 @@ keywords = [ ] description = "A pure-Rust SDK for accessing IronCore's privacy platform" edition = "2021" -rust-version = "1.74.0" +rust-version = "1.75.0" [dependencies] -async-trait = "0.1.21" base64 = "0.22" base64-serde = "0.7" bytes = "1" @@ -68,8 +67,8 @@ protobuf-codegen = "3.0" [features] beta = ["ironcore-search-helpers"] blocking = [] -# NOTE: ironoxide requires a TLS implementation. Choose one of the following +# NOTE: ironoxide requires a TLS implementation. Choose one of the following # enable to use statically compiled openssl on supported OpenSSL platforms; use with 'default-features = false' tls-vendored-openssl = ["reqwest/native-tls-vendored"] # enable to use rustls-tls; use with 'default-features = false' diff --git a/benches/ironoxide_bench.rs b/benches/ironoxide_bench.rs index fdc38789..bbd663e3 100644 --- a/benches/ironoxide_bench.rs +++ b/benches/ironoxide_bench.rs @@ -15,7 +15,11 @@ lazy_static! { "prod" => "prod", _ => panic!("IRONCORE_ENV can only be set to `stage` or `prod` when running the benchmarks.") }, - _ => "stage", + _ => { + // The core code defaults to `prod`, so we have to set this so the API_URL is set correctly. + std::env::set_var("IRONCORE_ENV", "stage"); + "stage" + }, } .to_string(); } diff --git a/flake.lock b/flake.lock index 57b575fb..da024174 100644 --- a/flake.lock +++ b/flake.lock @@ -5,29 +5,11 @@ "systems": "systems" }, "locked": { - "lastModified": 1705309234, - "narHash": "sha256-uNRRNRKmJyCRC/8y1RqBkqWBLM034y4qN7EprSdmgyA=", + "lastModified": 1710146030, + "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", "owner": "numtide", "repo": "flake-utils", - "rev": "1ef2e671c3b0c19053962c07dbda38332dcebf26", - "type": "github" - }, - "original": { - "owner": "numtide", - "repo": "flake-utils", - "type": "github" - } - }, - "flake-utils_2": { - "inputs": { - "systems": "systems_2" - }, - "locked": { - "lastModified": 1705309234, - "narHash": "sha256-uNRRNRKmJyCRC/8y1RqBkqWBLM034y4qN7EprSdmgyA=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "1ef2e671c3b0c19053962c07dbda38332dcebf26", + "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a", "type": "github" }, "original": { @@ -38,11 +20,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1708807242, - "narHash": "sha256-sRTRkhMD4delO/hPxxi+XwLqPn8BuUq6nnj4JqLwOu0=", + "lastModified": 1719254875, + "narHash": "sha256-ECni+IkwXjusHsm9Sexdtq8weAq/yUyt1TWIemXt3Ko=", "owner": "nixos", "repo": "nixpkgs", - "rev": "73de017ef2d18a04ac4bfd0c02650007ccb31c2a", + "rev": "2893f56de08021cffd9b6b6dfc70fd9ccd51eb60", "type": "github" }, "original": { @@ -54,11 +36,11 @@ }, "nixpkgs_2": { "locked": { - "lastModified": 1706487304, - "narHash": "sha256-LE8lVX28MV2jWJsidW13D2qrHU/RUUONendL2Q/WlJg=", + "lastModified": 1718428119, + "narHash": "sha256-WdWDpNaq6u1IPtxtYHHWpl5BmabtpmLnMAx0RdJ/vo8=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "90f456026d284c22b3e3497be980b2e47d0b28ac", + "rev": "e6cea36f83499eb4e9cd184c8a8e823296b50ad5", "type": "github" }, "original": { @@ -77,15 +59,14 @@ }, "rust-overlay": { "inputs": { - "flake-utils": "flake-utils_2", "nixpkgs": "nixpkgs_2" }, "locked": { - "lastModified": 1708999822, - "narHash": "sha256-X55GxqI3oDEfqy38Pt7xyypYNly4bkd/RajFE+FGn+A=", + "lastModified": 1719454714, + "narHash": "sha256-MojqG0lyUINkEk0b3kM2drsU5vyaF8DFZe/FAlZVOGs=", "owner": "oxalica", "repo": "rust-overlay", - "rev": "1a618c62479a6896ac497aaa0d969c6bd8e24911", + "rev": "d1c527659cf076ecc4b96a91c702d080b213801e", "type": "github" }, "original": { @@ -108,21 +89,6 @@ "repo": "default", "type": "github" } - }, - "systems_2": { - "locked": { - "lastModified": 1681028828, - "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", - "owner": "nix-systems", - "repo": "default", - "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", - "type": "github" - }, - "original": { - "owner": "nix-systems", - "repo": "default", - "type": "github" - } } }, "root": "root", diff --git a/rust-toolchain.toml b/rust-toolchain.toml index d4020a9a..8753cc83 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,4 +1,4 @@ [toolchain] profile = "default" -channel = "1.76.0" +channel = "1.79.0" components = ["rust-src", "rust-analyzer"] diff --git a/src/document.rs b/src/document.rs index c76319dd..7794087f 100644 --- a/src/document.rs +++ b/src/document.rs @@ -15,7 +15,7 @@ use crate::{ user::UserId, Result, }; -use async_trait::async_trait; +use futures::Future; use itertools::{Either, EitherOrBoth, Itertools}; pub mod advanced; @@ -131,7 +131,6 @@ impl Default for DocumentEncryptOpts { /// # Key Terms /// - ID - The ID representing a document. It must be unique within the document's segment and will **not** be encrypted. /// - Name - The human-readable name of a document. It does not need to be unique and will **not** be encrypted. -#[async_trait] pub trait DocumentOps { /// Encrypts the provided document bytes. /// @@ -159,11 +158,11 @@ pub trait DocumentOps { /// # Ok(()) /// # } /// ``` - async fn document_encrypt( + fn document_encrypt( &self, document_data: Vec, encrypt_opts: &DocumentEncryptOpts, - ) -> Result; + ) -> impl Future> + Send; /// Decrypts an IronCore encrypted document. /// @@ -188,7 +187,10 @@ pub trait DocumentOps { /// # Ok(()) /// # } /// ``` - async fn document_decrypt(&self, encrypted_document: &[u8]) -> Result; + fn document_decrypt( + &self, + encrypted_document: &[u8], + ) -> impl Future> + Send; /// Lists metadata for all of the encrypted documents that the calling user can read or decrypt. /// @@ -202,7 +204,7 @@ pub trait DocumentOps { /// let documents: Vec = document_data.result().to_vec(); /// # Ok(()) /// # } - async fn document_list(&self) -> Result; + fn document_list(&self) -> impl Future> + Send; /// Returns the metadata for an encrypted document. /// @@ -222,7 +224,10 @@ pub trait DocumentOps { /// # Ok(()) /// # } /// ``` - async fn document_get_metadata(&self, id: &DocumentId) -> Result; + fn document_get_metadata( + &self, + id: &DocumentId, + ) -> impl Future> + Send; /// Returns the document ID from the bytes of an encrypted document. /// @@ -267,11 +272,11 @@ pub trait DocumentOps { /// # Ok(()) /// # } /// ``` - async fn document_update_bytes( + fn document_update_bytes( &self, id: &DocumentId, new_document_data: Vec, - ) -> Result; + ) -> impl Future> + Send; /// Modifies or removes a document's name. /// @@ -293,11 +298,11 @@ pub trait DocumentOps { /// # Ok(()) /// # } /// ``` - async fn document_update_name( + fn document_update_name( &self, id: &DocumentId, name: Option<&DocumentName>, - ) -> Result; + ) -> impl Future> + Send; /// Grants decryption access to a document for the provided users and/or groups. /// @@ -326,11 +331,11 @@ pub trait DocumentOps { /// # Ok(()) /// # } /// ``` - async fn document_grant_access( + fn document_grant_access( &self, document_id: &DocumentId, grant_list: &[UserOrGroup], - ) -> Result; + ) -> impl Future> + Send; /// Revokes decryption access to a document for the provided users and/or groups. /// @@ -359,14 +364,13 @@ pub trait DocumentOps { /// # Ok(()) /// # } /// ``` - async fn document_revoke_access( + fn document_revoke_access( &self, document_id: &DocumentId, revoke_list: &[UserOrGroup], - ) -> Result; + ) -> impl Future> + Send; } -#[async_trait] impl DocumentOps for crate::IronOxide { async fn document_encrypt( &self, diff --git a/src/document/advanced.rs b/src/document/advanced.rs index ae8d0f3d..a6a0bdec 100644 --- a/src/document/advanced.rs +++ b/src/document/advanced.rs @@ -11,7 +11,7 @@ use crate::{ internal::add_optional_timeout, Result, SdkOperation, }; -use async_trait::async_trait; +use futures::Future; use itertools::EitherOrBoth; /// IronOxide Advanced Document Operations @@ -19,7 +19,6 @@ use itertools::EitherOrBoth; /// # Key Terms /// - EDEKs - Encrypted document encryption keys produced by unmanaged document encryption and required for unmanaged /// document decryption. -#[async_trait] pub trait DocumentAdvancedOps { /// Encrypts the provided document bytes without being managed by the IronCore service. /// @@ -31,11 +30,11 @@ pub trait DocumentAdvancedOps { /// - `data` - Bytes of the document to encrypt /// - `encrypt_opts` - Document encryption parameters. Default values are provided with /// [DocumentEncryptOpts::default()](../struct.DocumentEncryptOpts.html#method.default). - async fn document_encrypt_unmanaged( + fn document_encrypt_unmanaged( &self, data: Vec, encrypt_opts: &DocumentEncryptOpts, - ) -> Result; + ) -> impl Future> + Send; /// Decrypts a document not managed by the IronCore service. /// @@ -47,14 +46,13 @@ pub trait DocumentAdvancedOps { /// # Arguments /// - `encrypted_data` - Bytes of the encrypted document /// - `encrypted_deks` - EDEKs associated with the encrypted document - async fn document_decrypt_unmanaged( + fn document_decrypt_unmanaged( &self, encrypted_data: &[u8], encrypted_deks: &[u8], - ) -> Result; + ) -> impl Future> + Send; } -#[async_trait] impl DocumentAdvancedOps for crate::IronOxide { async fn document_encrypt_unmanaged( &self, diff --git a/src/group.rs b/src/group.rs index 443a2334..38d86075 100644 --- a/src/group.rs +++ b/src/group.rs @@ -12,7 +12,7 @@ use crate::{ user::UserId, IronOxideErr, Result, }; -use async_trait::async_trait; +use futures::Future; use vec1::Vec1; /// Options for group creation. @@ -172,7 +172,6 @@ impl Default for GroupCreateOpts { /// - Rotation - Changing a group's private key while leaving its public key unchanged. This can be accomplished by calling /// [group_rotate_private_key](trait.GroupOps.html#tymethod.group_rotate_private_key). -#[async_trait] pub trait GroupOps { /// Creates a group. /// @@ -195,7 +194,10 @@ pub trait GroupOps { /// # Ok(()) /// # } /// ``` - async fn group_create(&self, group_create_opts: &GroupCreateOpts) -> Result; + fn group_create( + &self, + group_create_opts: &GroupCreateOpts, + ) -> impl Future> + Send; /// Gets the full metadata for a group. /// @@ -215,7 +217,10 @@ pub trait GroupOps { /// # Ok(()) /// # } /// ``` - async fn group_get_metadata(&self, id: &GroupId) -> Result; + fn group_get_metadata( + &self, + id: &GroupId, + ) -> impl Future> + Send; /// Lists all of the groups that the current user is an admin or a member of. /// @@ -229,7 +234,7 @@ pub trait GroupOps { /// # Ok(()) /// # } /// ``` - async fn group_list(&self) -> Result; + fn group_list(&self) -> impl Future> + Send; /// Modifies or removes a group's name. /// @@ -251,11 +256,11 @@ pub trait GroupOps { /// # Ok(()) /// # } /// ``` - async fn group_update_name( + fn group_update_name( &self, id: &GroupId, name: Option<&GroupName>, - ) -> Result; + ) -> impl Future> + Send; /// Rotates a group's private key while leaving its public key unchanged. /// @@ -279,7 +284,10 @@ pub trait GroupOps { /// # Ok(()) /// # } /// ``` - async fn group_rotate_private_key(&self, id: &GroupId) -> Result; + fn group_rotate_private_key( + &self, + id: &GroupId, + ) -> impl Future> + Send; /// Adds members to a group. /// @@ -307,11 +315,11 @@ pub trait GroupOps { /// # Errors /// This operation supports partial success. If the request succeeds, then the resulting `GroupAccessEditResult` /// will indicate which additions succeeded and which failed, and it will provide an explanation for each failure. - async fn group_add_members( + fn group_add_members( &self, id: &GroupId, users: &[UserId], - ) -> Result; + ) -> impl Future> + Send; /// Removes members from a group. /// @@ -339,11 +347,11 @@ pub trait GroupOps { /// # Errors /// This operation supports partial success. If the request succeeds, then the resulting `GroupAccessEditResult` /// will indicate which removals succeeded and which failed, and it will provide an explanation for each failure. - async fn group_remove_members( + fn group_remove_members( &self, id: &GroupId, revoke_list: &[UserId], - ) -> Result; + ) -> impl Future> + Send; /// Adds administrators to a group. /// @@ -371,11 +379,11 @@ pub trait GroupOps { /// # Errors /// This operation supports partial success. If the request succeeds, then the resulting `GroupAccessEditResult` /// will indicate which additions succeeded and which failed, and it will provide an explanation for each failure. - async fn group_add_admins( + fn group_add_admins( &self, id: &GroupId, users: &[UserId], - ) -> Result; + ) -> impl Future> + Send; /// Removes administrators from a group. /// @@ -403,11 +411,11 @@ pub trait GroupOps { /// # Errors /// This operation supports partial success. If the request succeeds, then the resulting `GroupAccessEditResult` /// will indicate which removals succeeded and which failed, and it will provide an explanation for each failure. - async fn group_remove_admins( + fn group_remove_admins( &self, id: &GroupId, revoke_list: &[UserId], - ) -> Result; + ) -> impl Future> + Send; /// Deletes a group. /// @@ -430,10 +438,9 @@ pub trait GroupOps { /// # Ok(()) /// # } /// ``` - async fn group_delete(&self, id: &GroupId) -> Result; + fn group_delete(&self, id: &GroupId) -> impl Future> + Send; } -#[async_trait] impl GroupOps for crate::IronOxide { async fn group_create(&self, opts: &GroupCreateOpts) -> Result { let standard_opts = opts.clone().standardize(self.device.auth().account_id())?; diff --git a/src/internal/user_api.rs b/src/internal/user_api.rs index 9f408ded..580c2997 100644 --- a/src/internal/user_api.rs +++ b/src/internal/user_api.rs @@ -55,7 +55,7 @@ impl TryFrom<&str> for UserId { /// /// # Requirements /// - Must be greater than 0. -/// - Must be less than or equal to `i64::max_value()`. +/// - Must be less than or equal to `i64::MAX`. #[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] pub struct DeviceId(pub(crate) u64); impl DeviceId { @@ -70,7 +70,7 @@ impl TryFrom for DeviceId { // Validate the range of the device ID to always be positive, but also be // less than i64 (i.e. no high bit set) for compatibility with other // languages (i.e. Java) - if device_id < 1 || device_id > (i64::max_value() as u64) { + if device_id < 1 || device_id > (i64::MAX as u64) { Err(IronOxideErr::ValidationError( "device_id".to_string(), format!("'{device_id}' must be a number greater than 0"), diff --git a/src/internal/user_api/requests.rs b/src/internal/user_api/requests.rs index b662faf4..b27437b8 100644 --- a/src/internal/user_api/requests.rs +++ b/src/internal/user_api/requests.rs @@ -388,7 +388,6 @@ pub mod device_add { pub struct DeviceAddResponse { #[serde(rename = "id")] pub device_id: DeviceId, - pub device_public_key: PublicKey, pub name: Option, #[serde(with = "time::serde::rfc3339")] pub created: OffsetDateTime, diff --git a/src/lib.rs b/src/lib.rs index 65058ff5..909cfb2e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -214,6 +214,7 @@ pub mod common { pub use crate::internal::{ DeviceContext, DeviceSigningKeyPair, PrivateKey, PublicKey, SdkOperation, }; + pub use itertools::EitherOrBoth; } /// IronOxide SDK configuration @@ -307,7 +308,7 @@ impl InitAndRotationCheck { } /// Convenience constructor to make an InitAndRotationCheck::RotationNeeded from an IronOxide - /// and an EitherOrBoth> directly. + /// and an `EitherOrBoth>` directly. pub fn new_rotation_needed( io: T, rotations_needed: EitherOrBoth>, diff --git a/src/policy.rs b/src/policy.rs index d3a3f6c6..5d65961e 100644 --- a/src/policy.rs +++ b/src/policy.rs @@ -3,7 +3,7 @@ //! Policies are a list of rules which map data labels to a list of users/groups. This allows the //! separation of concerns when it comes to labeling data vs defining who to encrypt to. //! -//! Policies are defined using the ironcore admin console: https://admin.ironcorelabs.com/policy +//! Policies are defined using the ironcore admin console: //! and are stored on the server. This allows a policy to be updated independently of any application code. //! //! Data labeling is provided in three dimensions (category, sensitivity, dataSubject). @@ -78,11 +78,11 @@ //! # } //! ``` //! If the current user of the sdk is "alice@ironcorelabs" and the PolicyGrant above is evaluated, it will match the -//! second-to-last rule in the example policy above and will return users: [joe@ironcorelabs, alice@ironcorelabs] and -//! groups [group_alice@ironcorelabs, data_recovery"] +//! second-to-last rule in the example policy above and will return users: `[joe@ironcorelabs, alice@ironcorelabs]` and +//! groups `[group_alice@ironcorelabs, data_recovery"]` //! //! The PolicyGrant `PolicyGrant::new(None, None, None, None)` will match the last rule in the example and will return -//! the group \[data_recovery\] +//! the group `[data_recovery]` //! use crate::{internal::user_api::UserId, IronOxideErr, Result}; use regex::Regex; diff --git a/src/prelude.rs b/src/prelude.rs index 303565e0..6b996dd4 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -5,6 +5,8 @@ pub use crate::{ common::*, config::*, document::advanced::*, document::*, group::*, policy::*, user::*, InitAndRotationCheck, IronOxide, IronOxideErr, PrivateKeyRotationCheckResult, }; +#[doc(no_inline)] +pub use itertools::EitherOrBoth; #[cfg(feature = "blocking")] #[doc(no_inline)] diff --git a/src/search.rs b/src/search.rs index a7fd4215..0c9f5611 100644 --- a/src/search.rs +++ b/src/search.rs @@ -22,7 +22,7 @@ use crate::{ internal::take_lock, IronOxide, IronOxideErr, Result, }; -use async_trait::async_trait; +use futures::Future; pub use ironcore_search_helpers::transliterate_string; use ironcore_search_helpers::{ generate_hashes_for_string, generate_hashes_for_string_with_padding, @@ -69,13 +69,14 @@ impl EncryptedBlindIndexSalt { } ///Trait which gives the ability to create a blind index. -#[async_trait] pub trait BlindIndexSearchInitialize { ///Create an index and encrypt it to the provided group_id. - async fn create_blind_index(&self, group_id: &GroupId) -> Result; + fn create_blind_index( + &self, + group_id: &GroupId, + ) -> impl Future> + Send; } -#[async_trait] impl BlindIndexSearchInitialize for IronOxide { async fn create_blind_index(&self, group_id: &GroupId) -> Result { let salt = { diff --git a/src/user.rs b/src/user.rs index f6953f0b..e8cea987 100644 --- a/src/user.rs +++ b/src/user.rs @@ -12,7 +12,7 @@ use crate::{ internal::{add_optional_timeout, user_api, OUR_REQUEST}, IronOxide, Result, }; -use async_trait::async_trait; +use futures::Future; use recrypt::api::Recrypt; use std::{collections::HashMap, convert::TryInto}; @@ -75,7 +75,6 @@ impl Default for UserCreateOpts { /// - Password - The string used to encrypt and escrow a user's private key. /// - Rotation - Changing a user's private key while leaving their public key unchanged. This can be accomplished by calling /// [user_rotate_private_key](trait.UserOps.html#tymethod.user_rotate_private_key). -#[async_trait] pub trait UserOps { /// Creates a user. /// @@ -98,12 +97,12 @@ pub trait UserOps { /// # Ok(()) /// # } /// ``` - async fn user_create( + fn user_create( jwt: &Jwt, password: &str, user_create_opts: &UserCreateOpts, timeout: Option, - ) -> Result; + ) -> impl Future> + Send; /// Generates a new device for the user specified in the JWT. /// @@ -132,12 +131,12 @@ pub trait UserOps { /// # Ok(()) /// # } /// ``` - async fn generate_new_device( + fn generate_new_device( jwt: &Jwt, password: &str, device_create_options: &DeviceCreateOpts, timeout: Option, - ) -> Result; + ) -> impl Future> + Send; /// Verifies the existence of a user using a JWT to identify their user record. /// @@ -158,10 +157,10 @@ pub trait UserOps { /// # Ok(()) /// # } /// ``` - async fn user_verify( + fn user_verify( jwt: &Jwt, timeout: Option, - ) -> Result>; + ) -> impl Future>> + Send; /// Lists all of the devices for the current user. /// @@ -175,7 +174,7 @@ pub trait UserOps { /// # Ok(()) /// # } /// ``` - async fn user_list_devices(&self) -> Result; + fn user_list_devices(&self) -> impl Future> + Send; /// Gets users' public keys given their IDs. /// @@ -203,7 +202,10 @@ pub trait UserOps { /// # Ok(()) /// # } /// ``` - async fn user_get_public_key(&self, users: &[UserId]) -> Result>; + fn user_get_public_key( + &self, + users: &[UserId], + ) -> impl Future>> + Send; /// Rotates the current user's private key while leaving their public key the same. /// @@ -226,7 +228,10 @@ pub trait UserOps { /// # Ok(()) /// # } /// ``` - async fn user_rotate_private_key(&self, password: &str) -> Result; + fn user_rotate_private_key( + &self, + password: &str, + ) -> impl Future> + Send; /// Deletes a device. /// @@ -249,7 +254,10 @@ pub trait UserOps { /// # Ok(()) /// # } /// ``` - async fn user_delete_device(&self, device_id: Option<&DeviceId>) -> Result; + fn user_delete_device( + &self, + device_id: Option<&DeviceId>, + ) -> impl Future> + Send; /// Change the password for the user /// @@ -270,14 +278,13 @@ pub trait UserOps { /// # Ok(()) /// # } /// ``` - async fn user_change_password( + fn user_change_password( &self, current_password: &str, new_password: &str, - ) -> Result; + ) -> impl Future> + Send; } -#[async_trait] impl UserOps for IronOxide { async fn user_create( jwt: &Jwt,