diff --git a/CHANGELOG.md b/CHANGELOG.md index 0e105042..1b2f2692 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## 0.20.0 + +- [[#119](https://github.com/IronCoreLabs/ironoxide/pull/119)] + - Add `Clone`, `Debug`, `Eq`, `Hash`, and `PartialEq` to almost all public structs. + - Depend on a specific commit hash of itertools + ## 0.19.1 - [[#120](https://github.com/IronCoreLabs/ironoxide/pull/120)] diff --git a/Cargo.toml b/Cargo.toml index 45aa9478..19899450 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ironoxide" -version = "0.19.1" +version = "0.20.0" authors = ["IronCore Labs "] readme = "README.md" license = "AGPL-3.0-only" @@ -24,11 +24,12 @@ rand = "~0.6" rand_chacha = "~0.1" regex = "~1.3" ring = { version= "~0.16", features = ["std"] } -recrypt = "~0.9.2" +recrypt = "~0.10" url= "~2.1.0" reqwest = {version="~0.10.0", features = ["json"]} hex = "~0.3" -itertools = "~0.8" +# itertools 0.8.2++ - remove on next release +itertools = {git = "https://github.com/rust-itertools/itertools", rev = "c83cc48ffe39b96b7c6797b7b31752e840b373bb"} futures = "~0.3.1" quick-error = "~1.2" lazy_static = "~1.4" diff --git a/build.rs b/build.rs index 2e0b7d01..b392b026 100644 --- a/build.rs +++ b/build.rs @@ -1,4 +1,3 @@ -extern crate protobuf_codegen_pure; use std::{ env, fs::File, diff --git a/src/crypto/aes.rs b/src/crypto/aes.rs index 3f36d99c..c336b7e2 100644 --- a/src/crypto/aes.rs +++ b/src/crypto/aes.rs @@ -83,7 +83,7 @@ impl EncryptedMasterKey { dest } } -#[derive(Debug, Clone)] +#[derive(Clone, Debug)] pub struct AesEncryptedValue { aes_iv: [u8; AES_IV_LEN], ciphertext: Vec, diff --git a/src/document/mod.rs b/src/document/mod.rs index 5dfcc229..9e4c3bfb 100644 --- a/src/document/mod.rs +++ b/src/document/mod.rs @@ -20,16 +20,16 @@ use itertools::{Either, EitherOrBoth, Itertools}; pub mod advanced; /// Optional parameters that can be provided when encrypting a new document. -#[derive(Debug, PartialEq, Clone)] +#[derive(Clone, Debug, Eq, Hash, PartialEq)] pub struct DocumentEncryptOpts { id: Option, name: Option, // at least one user/group must be included either explicitly or via a policy grants: EitherOrBoth, } -#[derive(Debug, PartialEq, Clone)] /// Explicit users/groups that should have access to decrypt a document. +#[derive(Clone, Debug, Eq, Hash, PartialEq)] pub struct ExplicitGrant { grant_to_author: bool, grants: Vec, diff --git a/src/group.rs b/src/group.rs index 0640b4f6..60c2f4fc 100644 --- a/src/group.rs +++ b/src/group.rs @@ -11,8 +11,8 @@ use crate::{ }; use vec1::Vec1; -#[derive(Clone)] /// Options for group creation. +#[derive(Clone, Debug, Eq, Hash, PartialEq)] pub struct GroupCreateOpts { // unique id of a group within a segment. If none, the server will assign an id. id: Option, diff --git a/src/internal/document_api/mod.rs b/src/internal/document_api/mod.rs index c08261bc..1ff74a81 100644 --- a/src/internal/document_api/mod.rs +++ b/src/internal/document_api/mod.rs @@ -46,7 +46,7 @@ const HEADER_META_LENGTH_LENGTH: usize = 2; const CURRENT_DOCUMENT_ID_VERSION: u8 = 2; /// Document ID. Unique within the segment. Must match the regex `^[a-zA-Z0-9_.$#|@/:;=+'-]+$` -#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] pub struct DocumentId(pub(crate) String); impl DocumentId { pub fn id(&self) -> &str { @@ -74,7 +74,7 @@ impl TryFrom for DocumentId { } /// (unencrypted) name of a document. Construct via `try_from(&str)` -#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] pub struct DocumentName(pub(crate) String); impl DocumentName { pub fn name(&self) -> &String { @@ -92,7 +92,7 @@ impl TryFrom<&str> for DocumentName { struct DocHeaderPacked(Vec); /// Represents a parsed document header which is decoded from JSON -#[derive(Debug, Serialize, Deserialize, PartialEq)] +#[derive(Debug, PartialEq, Serialize, Deserialize)] struct DocumentHeader { #[serde(rename = "_did_")] document_id: DocumentId, @@ -161,7 +161,7 @@ fn parse_document_parts( } /// Represents the reason a document can be viewed by the requesting user. -#[derive(Serialize, Deserialize, Debug, Clone, Hash, PartialEq, Eq)] +#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub enum AssociationType { /// User created the document @@ -173,7 +173,7 @@ pub enum AssociationType { } /// Represents a User struct which is returned from doc get to show the IDs of users the document is visible to -#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] +#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] pub struct VisibleUser { id: UserId, } @@ -184,7 +184,7 @@ impl VisibleUser { } /// Represents a Group struct which is returned from doc get to show the IDs and names of groups the document is visible to -#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] +#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] pub struct VisibleGroup { id: GroupId, name: Option, @@ -201,7 +201,7 @@ impl VisibleGroup { /// Single document's (abbreviated) metadata. Returned as part of a `DocumentListResult`. /// /// If you want full metadata for a document, see `DocumentMetadataResult` -#[derive(Clone, Debug)] +#[derive(Clone, Debug, Eq, Hash, PartialEq)] pub struct DocumentListMeta(DocumentListApiResponseItem); impl DocumentListMeta { pub fn id(&self) -> &DocumentId { @@ -222,7 +222,7 @@ impl DocumentListMeta { } /// Metadata for each of the documents that the current user has access to decrypt. -#[derive(Debug)] +#[derive(Clone, Debug, Eq, Hash, PartialEq)] pub struct DocumentListResult { result: Vec, } @@ -233,7 +233,7 @@ impl DocumentListResult { } /// Full metadata for a document. -#[derive(Clone)] +#[derive(Clone, Debug, Eq, Hash, PartialEq)] pub struct DocumentMetadataResult(DocumentMetaApiResponse); impl DocumentMetadataResult { pub fn id(&self) -> &DocumentId { @@ -273,7 +273,7 @@ impl DocumentMetadataResult { /// - `encrypted_data` - Bytes of encrypted document content /// - `encrypted_deks` - List of encrypted document encryption keys (EDEK) of users/groups that have been granted access to `encrypted_data` /// - `access_errs` - Users and groups that could not be granted access -#[derive(Debug)] +#[derive(Clone, Debug, Eq, Hash, PartialEq)] pub struct DocumentEncryptUnmanagedResult { id: DocumentId, encrypted_data: Vec, @@ -329,7 +329,7 @@ impl DocumentEncryptUnmanagedResult { /// - `encrypted_data` - Bytes of encrypted document content /// - `grants` - Users and groups that have access to decrypt the `encrypted_data` /// - `access_errs` - Users and groups that could not be granted access -#[derive(Debug)] +#[derive(Clone, Debug, Eq, Hash, PartialEq)] pub struct DocumentEncryptResult { id: DocumentId, name: Option, @@ -363,7 +363,7 @@ impl DocumentEncryptResult { } } /// Result of decrypting a document. Includes minimal metadata as well as the decrypted bytes. -#[derive(Debug, PartialEq, Clone)] +#[derive(Clone, Debug, Eq, Hash, PartialEq)] pub struct DocumentDecryptResult { id: DocumentId, name: Option, @@ -390,7 +390,7 @@ impl DocumentDecryptResult { } /// A failure to edit the access list of a document. -#[derive(Debug, Clone)] +#[derive(Clone, Debug, Eq, Hash, PartialEq)] pub struct DocAccessEditErr { /// User or group whose access was to be granted/revoked pub user_or_group: UserOrGroup, @@ -409,7 +409,7 @@ impl DocAccessEditErr { /// Result of granting or revoking access to a document. Both grant and revoke support partial /// success. -#[derive(Debug)] +#[derive(Clone, Debug, Eq, Hash, PartialEq)] pub struct DocumentAccessResult { succeeded: Vec, failed: Vec, @@ -433,11 +433,11 @@ impl DocumentAccessResult { &self.failed } } -#[derive(Clone, PartialEq, Debug)] +#[derive(Clone, Debug, Eq, Hash, PartialEq)] struct DecryptedData(Vec); /// Result of successful unmanaged decryption -#[derive(Clone, PartialEq, Debug)] +#[derive(Clone, Debug, Eq, Hash, PartialEq)] pub struct DocumentDecryptUnmanagedResult { id: DocumentId, access_via: UserOrGroup, @@ -462,7 +462,7 @@ impl DocumentDecryptUnmanagedResult { } /// Either a user or a group. Allows for containing both. -#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] +#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] #[serde(rename_all = "camelCase", tag = "type")] pub enum UserOrGroup { User { id: UserId }, @@ -785,7 +785,7 @@ fn recrypt_document( /// Once decrypted, the DEK serves as a symmetric encryption key. /// /// It can also be useful to think of an EDEK as representing a "document access grant" to a user/group. -#[derive(Debug, Clone, PartialEq)] +#[derive(Clone, Debug, Eq, Hash, PartialEq)] pub struct EncryptedDek { grant_to: WithKey, encrypted_dek_data: recrypt::api::EncryptedValue, @@ -859,7 +859,7 @@ impl TryFrom<&EncryptedDek> for EncryptedDekP { /// Result of recrypt encryption. Contains the encrypted DEKs and the encrypted (user) data. /// `RecryptionResult` is an intermediate value as it cannot be serialized to bytes directly. /// To serialize to bytes, first construct an `EncryptedDoc` -#[derive(Debug, Clone)] +#[derive(Clone, Debug)] struct RecryptionResult { edeks: Vec, encrypted_data: AesEncryptedValue, diff --git a/src/internal/document_api/requests.rs b/src/internal/document_api/requests.rs index 12596e2e..7b6ccda6 100644 --- a/src/internal/document_api/requests.rs +++ b/src/internal/document_api/requests.rs @@ -14,19 +14,19 @@ use crate::internal::{ use chrono::{DateTime, Utc}; use std::convert::{TryFrom, TryInto}; -#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] +#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] pub struct Association { #[serde(rename = "type")] pub typ: AssociationType, } -#[derive(Deserialize, Debug, Clone, PartialEq)] +#[derive(Clone, Debug, Eq, Hash, PartialEq, Deserialize)] pub struct DocumentVisibility { pub users: Vec, pub groups: Vec, } -#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] #[serde(rename_all = "camelCase", tag = "type")] pub enum UserOrGroupWithKey { #[serde(rename_all = "camelCase")] @@ -55,7 +55,7 @@ impl From for UserOrGroup { } } -#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct AccessGrant { pub(crate) user_or_group: UserOrGroupWithKey, @@ -121,7 +121,7 @@ impl From<&AccessGrant> for UserOrGroup { } } -#[derive(Deserialize, Debug, Clone, PartialEq)] +#[derive(Clone, Debug, Eq, Hash, PartialEq, Deserialize)] #[serde(rename_all = "camelCase")] pub struct DocumentMetaApiResponse { pub id: DocumentId, @@ -136,12 +136,12 @@ pub struct DocumentMetaApiResponse { pub mod document_list { use super::*; - #[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] + #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct DocumentListApiResponse { pub result: Vec, } - #[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] + #[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] pub struct DocumentListApiResponseItem { pub id: DocumentId, pub name: Option, @@ -198,7 +198,7 @@ pub mod edek_transform { .await } - #[derive(Serialize, Debug, Clone, Deserialize, PartialEq)] + #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct EdekTransformResponse { pub(in crate::internal::document_api) user_or_group: UserOrGroup, @@ -214,20 +214,20 @@ pub mod document_create { }; use std::convert::TryInto; - #[derive(Serialize, Debug, Clone, Deserialize, PartialEq)] + #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct DocumentCreateValue { pub(crate) name: Option, pub(crate) shared_with: Vec, } - #[derive(Serialize, Debug, Clone, PartialEq)] + #[derive(Clone, Debug, PartialEq, Serialize)] pub struct DocumentCreateRequest { pub(crate) id: DocumentId, pub(crate) value: DocumentCreateValue, } - #[derive(Deserialize, Debug, Clone)] + #[derive(Clone, Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct DocumentCreateResponse { pub(crate) id: DocumentId, @@ -273,7 +273,7 @@ pub mod policy_get { pub(crate) const SUBSTITUTE_ID_QUERY_PARAM: &str = "substituteId"; - #[derive(Deserialize, Debug, Clone)] + #[derive(Clone, Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct PolicyResponse { pub(crate) users_and_groups: Vec, @@ -318,7 +318,7 @@ pub mod policy_get { pub mod document_update { use super::*; - #[derive(Serialize, Debug, Clone, PartialEq)] + #[derive(Clone, Debug, PartialEq, Serialize)] struct DocumentUpdateRequest<'a> { name: Option<&'a DocumentName>, } @@ -354,20 +354,20 @@ pub mod document_access { user_api::UserId, }; - #[derive(Deserialize, Debug)] + #[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] struct SuccessRes { pub(crate) user_or_group: UserOrGroupAccess, } - #[derive(Deserialize, Debug)] + #[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] struct FailRes { pub(crate) user_or_group: UserOrGroupAccess, pub(crate) error_message: String, } - #[derive(Deserialize, Serialize, Debug)] + #[derive(Debug, Serialize, Deserialize)] #[serde(tag = "type", rename_all = "camelCase")] pub enum UserOrGroupAccess { User { id: String }, @@ -402,7 +402,7 @@ pub mod document_access { } } - #[derive(Deserialize, Debug)] + #[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct DocumentAccessResponse { succeeded_ids: Vec, @@ -430,7 +430,7 @@ pub mod document_access { } } - #[derive(Serialize, Debug)] + #[derive(Debug, Serialize)] #[serde(rename_all = "camelCase")] pub struct DocumentGrantAccessRequest { /// Granting user's public key @@ -438,7 +438,7 @@ pub mod document_access { to: Vec, } - #[derive(Serialize, Debug)] + #[derive(Debug, Serialize)] #[serde(rename_all = "camelCase")] pub struct DocumentRevokeAccessRequest { user_or_groups: Vec, diff --git a/src/internal/group_api/mod.rs b/src/internal/group_api/mod.rs index 44b3b698..802f9287 100644 --- a/src/internal/group_api/mod.rs +++ b/src/internal/group_api/mod.rs @@ -51,7 +51,7 @@ impl GroupCreateOptsStd { } /// Group ID. Unique within a segment. Must match the regex `^[a-zA-Z0-9_.$#|@/:;=+'-]+$` -#[derive(Debug, PartialEq, Eq, Hash, Serialize, Deserialize, Clone)] +#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] pub struct GroupId(pub(crate) String); impl GroupId { pub fn id(&self) -> &str { @@ -82,7 +82,7 @@ impl TryFrom<&str> for GroupId { } /// Group's user-assigned name. (non-unique) -#[derive(PartialEq, Debug, Serialize, Deserialize, Clone)] +#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] pub struct GroupName(pub(crate) String); impl GroupName { pub fn name(&self) -> &String { @@ -104,7 +104,7 @@ impl TryFrom<&str> for GroupName { } /// List of (abbreviated) groups for which the requesting user is either an admin or member. -#[derive(Debug)] +#[derive(Clone, Debug, Eq, Hash, PartialEq)] pub struct GroupListResult { result: Vec, } @@ -118,7 +118,7 @@ impl GroupListResult { } } /// Abbreviated group information. -#[derive(Clone, Debug)] +#[derive(Clone, Debug, Eq, Hash, PartialEq)] pub struct GroupMetaResult { id: GroupId, name: Option, @@ -165,7 +165,7 @@ impl GroupMetaResult { } } -#[derive(Debug, Clone, PartialEq)] +#[derive(Clone, Debug, Eq, Hash, PartialEq)] pub struct GroupCreateResult { id: GroupId, name: Option, @@ -227,7 +227,7 @@ impl GroupCreateResult { } } /// Group information. -#[derive(Debug)] +#[derive(Clone, Debug, Eq, Hash, PartialEq)] pub struct GroupGetResult { id: GroupId, name: Option, @@ -293,7 +293,7 @@ impl GroupGetResult { } /// Failure to make the requested change to a group's membership or administrators. -#[derive(Debug, Clone)] +#[derive(Clone, Debug, Eq, Hash, PartialEq)] pub struct GroupAccessEditErr { user: UserId, error: String, @@ -312,7 +312,7 @@ impl GroupAccessEditErr { } /// Result from requesting changes to a group's membership or administrators. Partial success is supported. -#[derive(Debug)] +#[derive(Clone, Debug, Eq, Hash, PartialEq)] pub struct GroupAccessEditResult { succeeded: Vec, failed: Vec, @@ -530,7 +530,7 @@ pub async fn group_create( resp.try_into() } -#[derive(Debug, Clone)] +#[derive(Clone, Debug, Eq, Hash, PartialEq)] pub struct GroupUpdatePrivateKeyResult { id: GroupId, needs_rotation: bool, diff --git a/src/internal/group_api/requests.rs b/src/internal/group_api/requests.rs index 59adc479..781e0576 100644 --- a/src/internal/group_api/requests.rs +++ b/src/internal/group_api/requests.rs @@ -18,14 +18,14 @@ use std::{ convert::{TryFrom, TryInto}, }; -#[derive(Serialize, Deserialize, Debug, Clone, Hash, PartialEq, Eq)] +#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub enum Permission { Member, Admin, } -#[derive(Deserialize, Serialize, Debug, Clone, PartialEq)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct GroupBasicApiResponse { pub(crate) id: GroupId, @@ -56,7 +56,7 @@ impl TryFrom for GroupMetaResult { } } -#[derive(Deserialize, Debug, Clone, PartialEq)] +#[derive(Clone, Debug, PartialEq, Deserialize)] #[serde(rename_all = "camelCase")] pub struct GroupGetApiResponse { pub(crate) id: GroupId, @@ -95,7 +95,7 @@ impl TryFrom for GroupGetResult { } } -#[derive(Deserialize, Debug, Clone, PartialEq)] +#[derive(Clone, Debug, PartialEq, Deserialize)] #[serde(rename_all = "camelCase")] pub struct GroupCreateApiResponse { pub(in crate::internal) id: GroupId, @@ -130,14 +130,14 @@ impl TryFrom for GroupCreateResult { } } -#[derive(Serialize, Debug, PartialEq)] +#[derive(Debug, PartialEq, Serialize)] pub struct GroupAdmin { pub(in crate::internal) user: User, #[serde(flatten)] pub(in crate::internal) encrypted_msg: EncryptedOnceValue, } -#[derive(Serialize, Debug, PartialEq)] +#[derive(Debug, PartialEq, Serialize)] #[serde(rename_all = "camelCase")] pub struct GroupMember { pub(in crate::internal) user_id: UserId, @@ -145,27 +145,27 @@ pub struct GroupMember { pub(in crate::internal) user_master_public_key: PublicKey, } -#[derive(Serialize, Debug, PartialEq)] +#[derive(Debug, PartialEq, Serialize)] #[serde(rename_all = "camelCase")] pub struct User { pub(in crate::internal) user_id: UserId, pub(in crate::internal) user_master_public_key: PublicKey, } -#[derive(Deserialize, Debug)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct SuccessRes { pub(crate) user_id: UserId, } -#[derive(Deserialize, Debug)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct FailRes { pub(crate) user_id: UserId, pub(crate) error_message: String, } -#[derive(Deserialize, Debug)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct GroupUserEditResponse { pub(crate) succeeded_ids: Vec, @@ -175,7 +175,7 @@ pub struct GroupUserEditResponse { pub mod group_list { use super::*; - #[derive(Deserialize, Debug, Clone)] + #[derive(Clone, Debug, Deserialize)] pub struct GroupListResponse { pub result: Vec, } @@ -276,14 +276,14 @@ pub mod group_update_private_key { use super::*; use internal::{group_api::GroupUpdatePrivateKeyResult, rest::json::AugmentationFactor}; - #[derive(Serialize, Debug)] + #[derive(Debug, Serialize)] #[serde(rename_all = "camelCase")] pub struct GroupUpdatePrivateKeyRequest { admins: Vec, augmentation_factor: AugmentationFactor, } - #[derive(Deserialize, PartialEq, Debug)] + #[derive(Debug, PartialEq, Deserialize)] #[serde(rename_all = "camelCase")] pub struct GroupUpdatePrivateKeyResponse { group_key_id: u64, @@ -351,7 +351,7 @@ pub mod group_delete { pub mod group_update { use super::*; - #[derive(Serialize, Debug, Clone, PartialEq)] + #[derive(Clone, Debug, PartialEq, Serialize)] struct GroupUpdateRequest<'a> { name: Option<&'a GroupName>, } @@ -447,13 +447,13 @@ pub mod group_add_admin { pub mod group_remove_entity { use super::*; - #[derive(Serialize, Debug, Clone, PartialEq)] + #[derive(Clone, Debug, PartialEq, Serialize)] #[serde(rename_all = "camelCase")] struct GroupEntityId<'a> { user_id: &'a UserId, } - #[derive(Serialize, Debug, Clone, PartialEq)] + #[derive(Clone, Debug, PartialEq, Serialize)] struct GroupEntityRemoveRequest<'a> { users: Vec>, } diff --git a/src/internal/mod.rs b/src/internal/mod.rs index 56d793eb..bd3be7d1 100644 --- a/src/internal/mod.rs +++ b/src/internal/mod.rs @@ -46,7 +46,7 @@ lazy_static! { pub static ref OUR_REQUEST: IronCoreRequest = IronCoreRequest::new(URL_STRING.as_str()); } -#[derive(Debug, PartialEq, Clone, Copy)] +#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] pub enum RequestErrorCode { UserVerify, UserCreate, @@ -76,7 +76,7 @@ pub enum RequestErrorCode { } /// Public SDK operations -#[derive(Debug, Clone, PartialEq, Eq, Hash, Copy)] +#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] pub enum SdkOperation { InitializeSdk, InitializeSdkCheckRotation, @@ -302,7 +302,7 @@ pub mod auth_v2 { } ///Structure that contains all the info needed to make a signed API request from a device. -#[derive(Debug, Clone, Serialize, Deserialize)] +#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct RequestAuth { ///The user's given id, which uniquely identifies them inside the segment. @@ -348,7 +348,7 @@ impl RequestAuth { } /// Account's device context. Needed to initialize the Sdk with a set of device keys. See `IronOxide.initialize()` -#[derive(Debug, Clone, Serialize, Deserialize)] +#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct DeviceContext { #[serde(flatten)] @@ -410,8 +410,7 @@ impl From for DeviceContext { } } -// Note: Equality is not provided to protect the security of the device private key. -#[derive(Debug, Clone)] +#[derive(Clone, Debug, Eq, Hash, PartialEq)] pub struct DeviceAddResult { /// The user's given id, which uniquely identifies them inside the segment. account_id: UserId, @@ -497,7 +496,7 @@ impl From for Vec { /// Represents an asymmetric public key that wraps the underlying bytes /// of the key. -#[derive(PartialEq, Debug, Clone)] +#[derive(Clone, Debug, Eq, Hash, PartialEq)] pub struct PublicKey(RecryptPublicKey); impl From for PublicKey { @@ -555,7 +554,7 @@ impl PublicKey { /// Represents an asymmetric private key that wraps the underlying bytes /// of the key. -#[derive(Debug, Clone)] +#[derive(Clone, Debug, Eq, Hash, PartialEq)] pub struct PrivateKey(RecryptPrivateKey); impl PrivateKey { const BYTES_SIZE: usize = RecryptPrivateKey::ENCODED_SIZE_BYTES; @@ -618,14 +617,10 @@ impl PrivateKey { augmenting_key: &AugmentationFactor, error_fn: F, ) -> Result { - use recrypt::Revealed; let zero: RecryptPrivateKey = RecryptPrivateKey::new([0u8; 32]); - if Revealed(augmenting_key.clone().into()) == Revealed(zero) { + if RecryptPrivateKey::from(augmenting_key.clone()) == zero { Err(error_fn("Augmenting key cannot be zero".into())) - } - // These clones can be removed once https://github.com/IronCoreLabs/recrypt-rs/issues/91 is fixed - // result of the augmentation would be zero - else if Revealed(augmenting_key.clone().into()) == Revealed(self.clone().0) { + } else if RecryptPrivateKey::from(augmenting_key.clone()) == self.0 { Err(error_fn( "PrivateKey augmentation failed with a zero value".into(), )) @@ -675,7 +670,7 @@ impl From for RecryptPrivateKey { } /// Public/Private asymmetric keypair that is used for decryption/encryption. -#[derive(Clone)] +#[derive(Clone, Debug, Eq, Hash, PartialEq)] pub struct KeyPair { public_key: PublicKey, private_key: PrivateKey, @@ -699,7 +694,7 @@ impl KeyPair { /// Signing keypair specific to a device. Used to sign all requests to the IronCore API /// endpoints. Needed to create a `DeviceContext`. -#[derive(Debug, Clone)] +#[derive(Clone, Debug, Eq, Hash, PartialEq)] pub struct DeviceSigningKeyPair(RecryptSigningKeypair); impl From<&DeviceSigningKeyPair> for RecryptSigningKeypair { fn from(dsk: &DeviceSigningKeyPair) -> RecryptSigningKeypair { @@ -722,12 +717,6 @@ impl TryFrom<&[u8]> for DeviceSigningKeyPair { } } -impl PartialEq for DeviceSigningKeyPair { - fn eq(&self, other: &DeviceSigningKeyPair) -> bool { - self.0.bytes().to_vec() == other.0.bytes().to_vec() - } -} - impl Serialize for DeviceSigningKeyPair { fn serialize(&self, serializer: S) -> Result where @@ -774,7 +763,7 @@ impl DeviceSigningKeyPair { /// "sub" : unique_user_id /// }); /// -#[derive(Debug, PartialEq, Serialize, Clone)] +#[derive(Clone, Debug, PartialEq, Serialize)] pub struct Jwt(String); impl TryFrom<&str> for Jwt { type Error = IronOxideErr; @@ -813,7 +802,7 @@ impl TryFrom<&str> for Password { } } -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug, Eq, Hash, PartialEq)] pub struct WithKey { pub(crate) id: T, pub(crate) public_key: PublicKey, @@ -1159,14 +1148,13 @@ pub(crate) mod tests { #[test] fn private_key_augmentation_is_augment_minus() { - use recrypt::Revealed; let p1 = gen_priv_key(); let p2 = gen_priv_key(); let p3 = p1.clone().0.augment_minus(&p2.clone().0); let aug_p = p1.augment_user(&AugmentationFactor(p2)).unwrap(); - assert_eq!(Revealed(aug_p.0), Revealed(p3)) + assert_eq!(aug_p.0, p3) } #[test] @@ -1264,13 +1252,10 @@ pub(crate) mod tests { let result = augment_private_key_with_retry(&recrypt_mock, &curr_priv_key).unwrap(); assert_eq!( - recrypt::Revealed((result.clone().0).0), - recrypt::Revealed(RecryptPrivateKey::new(expected_priv_key_bytes)) + (result.0).0, + RecryptPrivateKey::new(expected_priv_key_bytes) ); - assert_eq!( - recrypt::Revealed(((result.1).0).0), - recrypt::Revealed(good_re_private_key) - ) + assert_eq!(((result.1).0).0, good_re_private_key) } #[test] fn augment_private_key_with_retry_retries_only_once() { @@ -1305,10 +1290,7 @@ pub(crate) mod tests { // the augmentation will result in zero, causing the function to retry. let result = gen_plaintext_and_aug_with_retry(&recrypt_mock, &bad_private_key.into()).unwrap(); - assert_eq!( - recrypt::Revealed(result.0), - recrypt::Revealed(good_plaintext) - ); + assert_eq!(result.0, good_plaintext); } #[test] diff --git a/src/internal/rest.rs b/src/internal/rest.rs index 6c05d296..2f9a9477 100644 --- a/src/internal/rest.rs +++ b/src/internal/rest.rs @@ -35,7 +35,7 @@ lazy_static! { }; } -#[derive(Debug, Serialize, Deserialize, PartialEq)] +#[derive(Debug, PartialEq, Serialize, Deserialize)] pub struct ServerError { message: String, code: u32, @@ -176,7 +176,7 @@ impl<'a> Authorization<'a> { /// We sign over: `/api/1/users?id=abcABC012_.%24%23%7C%40%2F%3A%3B%3D%2B'-` /// /// Anyone wanting to verify this signature will need to be able to match this exact encoding. -#[derive(Debug, Clone)] +#[derive(Clone, Debug)] pub struct SignatureUrlString(String); impl SignatureUrlString { @@ -297,7 +297,7 @@ impl<'a> HeaderIronCoreRequestSig<'a> { } ///A struct which holds the basic info that will be needed for making requests to an ironcore service. Currently just the base_url. -#[derive(Debug, Clone, Serialize, Deserialize, Copy)] +#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] pub struct IronCoreRequest { base_url: &'static str, } @@ -850,7 +850,7 @@ pub mod json { base64_serde_type!(pub Base64Standard, base64::STANDARD); - #[derive(Serialize, Deserialize, PartialEq, Debug, Clone)] + #[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] pub struct PublicKey { #[serde(with = "Base64Standard")] pub x: Vec, @@ -879,7 +879,7 @@ pub mod json { } } - #[derive(Serialize, Debug, PartialEq)] + #[derive(Debug, PartialEq, Serialize)] #[serde(rename_all = "camelCase")] pub struct TransformKey { ephemeral_public_key: PublicKey, @@ -909,7 +909,7 @@ pub mod json { } } - #[derive(Serialize, Deserialize, PartialEq, Debug, Clone)] + #[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct EncryptedOnceValue { #[serde(with = "Base64Standard")] @@ -923,7 +923,7 @@ pub mod json { public_signing_key: Vec, } - #[derive(Serialize, Deserialize, PartialEq, Debug)] + #[derive(Debug, PartialEq, Serialize, Deserialize)] pub struct AugmentationFactor(#[serde(with = "Base64Standard")] pub Vec); impl From for AugmentationFactor { @@ -932,7 +932,7 @@ pub mod json { } } - #[derive(Serialize, Deserialize, PartialEq, Debug, Clone)] + #[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct TransformedEncryptedValue { #[serde(flatten)] @@ -940,7 +940,7 @@ pub mod json { transform_blocks: Vec, } - #[derive(Serialize, Deserialize, PartialEq, Debug, Clone)] + #[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct TransformBlock { #[serde(with = "Base64Standard")] diff --git a/src/internal/user_api/mod.rs b/src/internal/user_api/mod.rs index 2ac11fe7..86ab0f58 100644 --- a/src/internal/user_api/mod.rs +++ b/src/internal/user_api/mod.rs @@ -17,7 +17,7 @@ use std::{ mod requests; /// ID of a user. Unique with in a segment. Must match the regex `^[a-zA-Z0-9_.$#|@/:;=+'-]+$` -#[derive(PartialEq, Debug, Serialize, Deserialize, Clone, Eq, Hash)] +#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] pub struct UserId(pub(crate) String); impl UserId { pub fn id(&self) -> &str { @@ -43,7 +43,7 @@ impl TryFrom<&str> for UserId { } /// Device ID type. Validates that the provided ID is greater than 0 -#[derive(Clone, Serialize, Deserialize, PartialEq, Debug)] +#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] pub struct DeviceId(pub(crate) u64); impl DeviceId { pub fn id(&self) -> &u64 { @@ -68,7 +68,7 @@ impl TryFrom for DeviceId { } /// Device name type. Validates that the provided name isn't an empty string -#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] pub struct DeviceName(pub(crate) String); impl DeviceName { pub fn name(&self) -> &String { @@ -83,7 +83,7 @@ impl TryFrom<&str> for DeviceName { } /// Keypair for a newly created user -#[derive(Debug)] +#[derive(Clone, Debug, Eq, Hash, PartialEq)] pub struct UserCreateResult { user_public_key: PublicKey, // does the private key of this key pair need to be rotated? @@ -119,7 +119,7 @@ pub struct DeviceAdd { } /// IDs and public key for existing user on verify result -#[derive(Debug)] +#[derive(Clone, Debug, Eq, Hash, PartialEq)] pub struct UserResult { account_id: UserId, segment_id: usize, @@ -144,8 +144,8 @@ impl UserResult { } } -#[derive(Debug)] /// Devices for a user, sorted by the device id +#[derive(Clone, Debug, Eq, Hash, PartialEq)] pub struct UserDeviceListResult { result: Vec, } @@ -159,8 +159,8 @@ impl UserDeviceListResult { } } -#[derive(Clone, PartialEq, Debug)] /// Metadata about a user device +#[derive(Clone, Debug, Eq, Hash, PartialEq)] pub struct UserDevice { id: DeviceId, name: Option, @@ -236,7 +236,7 @@ pub async fn user_create( .try_into() } -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Clone, Debug, Eq, Hash, PartialEq)] pub struct EncryptedPrivateKey(Vec); impl EncryptedPrivateKey { @@ -245,7 +245,7 @@ impl EncryptedPrivateKey { } } -#[derive(Debug, Clone)] +#[derive(Clone, Debug, Eq, Hash, PartialEq)] pub struct UserUpdatePrivateKeyResult { user_master_private_key: EncryptedPrivateKey, needs_rotation: bool, diff --git a/src/internal/user_api/requests.rs b/src/internal/user_api/requests.rs index cbb04048..fae04e44 100644 --- a/src/internal/user_api/requests.rs +++ b/src/internal/user_api/requests.rs @@ -18,7 +18,7 @@ use chrono::{DateTime, Utc}; use std::convert::TryFrom; use crate::internal::auth_v2::AuthV2Builder; -#[derive(Serialize, Deserialize, PartialEq, Debug)] +#[derive(Debug, PartialEq, Serialize, Deserialize)] pub struct EncryptedPrivateKey(#[serde(with = "Base64Standard")] pub Vec); impl From for EncryptedPrivateKey { @@ -47,7 +47,7 @@ pub mod user_verify { use super::*; - #[derive(Deserialize, PartialEq, Debug)] + #[derive(Debug, PartialEq, Deserialize)] #[serde(rename_all = "camelCase")] pub struct UserVerifyResponse { pub(crate) id: String, @@ -133,7 +133,7 @@ pub mod user_get { use super::*; use crate::internal::group_api::GroupId; - #[derive(Deserialize, PartialEq, Debug)] + #[derive(Debug, PartialEq, Deserialize)] #[serde(rename_all = "camelCase")] pub struct CurrentUserResponse { pub(in crate::internal) current_key_id: u64, @@ -162,14 +162,14 @@ pub mod user_update_private_key { use super::*; use internal::{rest::json::AugmentationFactor, user_api::UserUpdatePrivateKeyResult}; - #[derive(Serialize, Debug)] + #[derive(Debug, Serialize)] #[serde(rename_all = "camelCase")] pub struct UserUpdatePrivateKey { user_private_key: EncryptedPrivateKey, augmentation_factor: AugmentationFactor, } - #[derive(Deserialize, PartialEq, Debug)] + #[derive(Debug, PartialEq, Deserialize)] #[serde(rename_all = "camelCase")] pub struct UserUpdatePrivateKeyResponse { current_key_id: u64, @@ -217,7 +217,7 @@ pub mod user_create { use super::*; - #[derive(Deserialize, PartialEq, Debug)] + #[derive(Debug, PartialEq, Deserialize)] #[serde(rename_all = "camelCase")] pub struct UserCreateResponse { id: String, @@ -228,7 +228,7 @@ pub mod user_create { needs_rotation: bool, } - #[derive(Serialize, Debug)] + #[derive(Debug, Serialize)] #[serde(rename_all = "camelCase")] struct UserCreateReq { user_public_key: PublicKey, @@ -312,7 +312,7 @@ pub mod device_add { use super::*; - #[derive(Serialize, Debug)] + #[derive(Debug, Serialize)] #[serde(rename_all = "camelCase")] pub struct DeviceAddReq { pub timestamp: u64, @@ -322,14 +322,14 @@ pub mod device_add { pub user_public_key: PublicKey, } - #[derive(Serialize, Debug)] + #[derive(Debug, Serialize)] #[serde(rename_all = "camelCase")] pub struct Device { pub transform_key: TransformKey, pub name: Option, } - #[derive(Deserialize, Debug)] + #[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct DeviceAddResponse { #[serde(rename = "id")] @@ -373,7 +373,7 @@ pub mod device_list { use super::*; - #[derive(Deserialize, PartialEq, Debug)] + #[derive(Debug, PartialEq, Deserialize)] #[serde(rename_all = "camelCase")] pub struct DeviceListItem { #[serde(rename = "id")] @@ -384,7 +384,7 @@ pub mod device_list { is_current_device: bool, } - #[derive(Deserialize, PartialEq, Debug)] + #[derive(Debug, PartialEq, Deserialize)] pub struct DeviceListResponse { pub(in crate::internal) result: Vec, } diff --git a/src/lib.rs b/src/lib.rs index 9f5f991d..65a88de0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -111,7 +111,7 @@ pub mod config { use std::time::Duration; /// Top-level configuration object for IronOxide. - #[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] + #[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] pub struct IronOxideConfig { /// See [PolicyCachingConfig](struct.PolicyCachingConfig.html) pub policy_caching: PolicyCachingConfig, @@ -124,7 +124,7 @@ pub mod config { /// Since policies are evaluated by the webservice, caching the result can greatly speed /// up encrypting a document with a [PolicyGrant](../policy/struct.PolicyGrant.html). There is no expiration of the cache, so /// if you want to clear it at runtime, call [IronOxide::clear_policy_cache()](../struct.IronOxide.html#method.clear_policy_cache). - #[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] + #[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] pub struct PolicyCachingConfig { /// maximum number of policy evaluations that will be cached by the SDK. /// If the maximum number is exceeded, the cache will be cleared prior to storing the next entry @@ -173,6 +173,7 @@ impl fmt::Debug for IronOxide { } /// Result of calling `initialize_check_rotation` +#[derive(Clone, Debug, Eq, Hash, PartialEq)] pub enum InitAndRotationCheck { /// Initialization succeeded, and no requests for private key rotations were present NoRotationNeeded(T), @@ -204,6 +205,7 @@ impl InitAndRotationCheck { const BYTES_BEFORE_RESEEDING: u64 = 1024 * 1024; /// Provides soft rotation capabilities for user and group keys +#[derive(Clone, Debug, Eq, Hash, PartialEq)] pub struct PrivateKeyRotationCheckResult { pub rotations_needed: EitherOrBoth>, } diff --git a/src/policy.rs b/src/policy.rs index b786ee54..a53700f3 100644 --- a/src/policy.rs +++ b/src/policy.rs @@ -85,7 +85,7 @@ use std::convert::TryFrom; /// rule may generate any number of users/groups. /// /// `substitute_user` replaces `%USER%` in a matched policy rule. -#[derive(Debug, PartialEq, Eq, Clone, Hash)] +#[derive(Clone, Debug, Eq, Hash, PartialEq)] pub struct PolicyGrant { category: Option, sensitivity: Option, @@ -137,7 +137,7 @@ impl Default for PolicyGrant { macro_rules! policy_field { ($t: ident, $l: literal) => { - #[derive(Debug, PartialEq, Eq, Hash, Clone)] + #[derive(Clone, Debug, Eq, Hash, PartialEq)] pub struct $t(pub(crate) String); impl TryFrom<&str> for $t { diff --git a/src/user.rs b/src/user.rs index 1e6c5e93..9f7cd160 100644 --- a/src/user.rs +++ b/src/user.rs @@ -14,7 +14,7 @@ use recrypt::api::Recrypt; use std::{collections::HashMap, convert::TryInto}; /// Optional parameters for creating a new device instance. -#[derive(Debug, PartialEq, Clone)] +#[derive(Clone, Debug, Eq, Hash, PartialEq)] pub struct DeviceCreateOpts { device_name: Option, } @@ -31,6 +31,7 @@ impl Default for DeviceCreateOpts { } /// Options that can be specified at when calling [`user_create`](trait.UserOps.html#tymethod.user_create). +#[derive(Clone, Debug, Eq, Hash, PartialEq)] pub struct UserCreateOpts { // see docs on `new` needs_rotation: bool,