From 380bb2013f25f41cb1ef27c6514a8d09694296eb Mon Sep 17 00:00:00 2001 From: sug Date: Wed, 9 Oct 2024 11:10:12 +0200 Subject: [PATCH] [tutasdk] sdk should be able to make service calls * NOTE: Compressed String not yet supported! * RustGenerator should produce service files * EntityFacade should be able to encrypt entities * CreateSession ( without offline login and 2FA ) * NativeRestClient based on `hyper` to use in non-mobile ( desktop ) devices --- buildSrc/RustGenerator.js | 83 +- tuta-sdk/rust/Cargo.lock | 887 ++++++++++- tuta-sdk/rust/sdk/Cargo.toml | 32 +- tuta-sdk/rust/sdk/examples/create_session.rs | 31 + tuta-sdk/rust/sdk/src/crypto/aes.rs | 5 +- tuta-sdk/rust/sdk/src/crypto/crypto_facade.rs | 53 +- .../rust/sdk/src/crypto/key_encryption.rs | 2 +- tuta-sdk/rust/sdk/src/crypto/mod.rs | 4 +- tuta-sdk/rust/sdk/src/crypto_entity_client.rs | 13 +- tuta-sdk/rust/sdk/src/custom_id.rs | 2 +- tuta-sdk/rust/sdk/src/element_value.rs | 300 ++-- tuta-sdk/rust/sdk/src/entities/accounting.rs | 6 +- tuta-sdk/rust/sdk/src/entities/base.rs | 6 +- .../rust/sdk/src/entities/entity_facade.rs | 992 +++++++++++- tuta-sdk/rust/sdk/src/entities/mod.rs | 20 +- tuta-sdk/rust/sdk/src/entities/monitor.rs | 48 +- tuta-sdk/rust/sdk/src/entities/storage.rs | 78 +- tuta-sdk/rust/sdk/src/entities/sys.rs | 1332 +++++++++++------ tuta-sdk/rust/sdk/src/entities/tutanota.rs | 690 ++++++--- tuta-sdk/rust/sdk/src/entities/usage.rs | 48 +- tuta-sdk/rust/sdk/src/entity_client.rs | 6 + tuta-sdk/rust/sdk/src/instance_mapper.rs | 27 +- tuta-sdk/rust/sdk/src/json_serializer.rs | 20 +- tuta-sdk/rust/sdk/src/key_loader_facade.rs | 28 +- tuta-sdk/rust/sdk/src/lib.rs | 148 +- tuta-sdk/rust/sdk/src/login/credentials.rs | 16 +- tuta-sdk/rust/sdk/src/login/login_facade.rs | 10 +- tuta-sdk/rust/sdk/src/login/mod.rs | 2 +- tuta-sdk/rust/sdk/src/mail_facade.rs | 2 +- tuta-sdk/rust/sdk/src/metamodel.rs | 21 +- tuta-sdk/rust/sdk/src/net/mod.rs | 3 + .../rust/sdk/src/net/native_rest_client.rs | 111 ++ tuta-sdk/rust/sdk/src/net/uri.rs | 61 + tuta-sdk/rust/sdk/src/net/vec_body.rs | 51 + tuta-sdk/rust/sdk/src/rest_client.rs | 30 +- tuta-sdk/rust/sdk/src/rest_error.rs | 16 +- tuta-sdk/rust/sdk/src/services/accounting.rs | 11 + tuta-sdk/rust/sdk/src/services/base.rs | 6 + tuta-sdk/rust/sdk/src/services/generator.rs | 77 + tuta-sdk/rust/sdk/src/services/gossip.rs | 6 + tuta-sdk/rust/sdk/src/services/mod.rs | 143 ++ tuta-sdk/rust/sdk/src/services/monitor.rs | 21 + .../rust/sdk/src/services/service_executor.rs | 650 ++++++++ tuta-sdk/rust/sdk/src/services/storage.rs | 30 + tuta-sdk/rust/sdk/src/services/sys.rs | 408 +++++ .../rust/sdk/src/services/test_services.rs | 216 +++ tuta-sdk/rust/sdk/src/services/tutanota.rs | 168 +++ tuta-sdk/rust/sdk/src/services/usage.rs | 20 + tuta-sdk/rust/sdk/src/type_model_provider.rs | 26 +- tuta-sdk/rust/sdk/src/typed_entity_client.rs | 2 +- tuta-sdk/rust/sdk/src/user_facade.rs | 2 +- .../rust/sdk/src/util/entity_test_utils.rs | 9 +- tuta-sdk/rust/sdk/src/util/mod.rs | 18 +- tuta-sdk/rust/sdk/src/util/test_utils.rs | 44 +- tuta-sdk/rust/sdk/tests/download_mail_test.rs | 138 +- tuta-sdk/rust/sdk/tests/test_rest_client.rs | 1 + 56 files changed, 5970 insertions(+), 1210 deletions(-) create mode 100644 tuta-sdk/rust/sdk/examples/create_session.rs create mode 100644 tuta-sdk/rust/sdk/src/net/mod.rs create mode 100644 tuta-sdk/rust/sdk/src/net/native_rest_client.rs create mode 100644 tuta-sdk/rust/sdk/src/net/uri.rs create mode 100644 tuta-sdk/rust/sdk/src/net/vec_body.rs create mode 100644 tuta-sdk/rust/sdk/src/services/accounting.rs create mode 100644 tuta-sdk/rust/sdk/src/services/base.rs create mode 100644 tuta-sdk/rust/sdk/src/services/generator.rs create mode 100644 tuta-sdk/rust/sdk/src/services/gossip.rs create mode 100644 tuta-sdk/rust/sdk/src/services/mod.rs create mode 100644 tuta-sdk/rust/sdk/src/services/monitor.rs create mode 100644 tuta-sdk/rust/sdk/src/services/service_executor.rs create mode 100644 tuta-sdk/rust/sdk/src/services/storage.rs create mode 100644 tuta-sdk/rust/sdk/src/services/sys.rs create mode 100644 tuta-sdk/rust/sdk/src/services/test_services.rs create mode 100644 tuta-sdk/rust/sdk/src/services/tutanota.rs create mode 100644 tuta-sdk/rust/sdk/src/services/usage.rs diff --git a/buildSrc/RustGenerator.js b/buildSrc/RustGenerator.js index 0190cd9e28a3..af9d1cf9ed07 100644 --- a/buildSrc/RustGenerator.js +++ b/buildSrc/RustGenerator.js @@ -13,7 +13,7 @@ import { AssociationType, Type } from "../src/common/api/common/EntityConstants. */ export function generateRustType({ type, modelName }) { let typeName = mapTypeName(type.name, modelName) - let buf = `#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + let buf = `#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct ${typeName} {\n` for (let [valueName, valueProperties] of Object.entries(type.values)) { const rustType = rustValueType(valueName, type, valueProperties) @@ -59,20 +59,81 @@ pub struct ${typeName} {\n` if (type.encrypted || Object.values(type.values).some((v) => v.encrypted)) { buf += `\tpub _finalIvs: HashMap,\n` } + buf += "}" + buf += ` +impl Entity for ${typeName} { + fn type_ref() -> TypeRef { + TypeRef { + app: "${modelName}", + type_: "${typeName}", + } + } +} +` + + return buf + "\n\n" +} - buf += "\n\n" +export function generateRustServiceDefinition(appName, appVersion, services) { + let imports = new Set([ + "#![allow(unused_imports, dead_code, unused_variables)]", + "use crate::ApiCallError;", + "use crate::entities::Entity;", + "use crate::services::{PostService, GetService, PutService, DeleteService, Service, Executor, ExtraServiceParams};", + "use crate::rest_client::HttpMethod;", + "use crate::services::hidden::Nothing;", + ]) + const code = services + .map((s) => { + let serviceDefinition = ` +pub struct ${s.name}; - buf += `impl Entity for ${typeName} {\n` - buf += "\tfn type_ref() -> TypeRef {\n" - buf += `\t\tTypeRef {\n` - buf += `\t\t\tapp: "${modelName}",\n` - buf += `\t\t\ttype_: "${typeName}",\n` - buf += `\t\t}\n` - buf += "\t}\n" - buf += "}" +crate::service_impl!(base, ${s.name}, "${appName}/${s.name.toLowerCase()}", ${appVersion}); +` + + function getTypeRef(dataType) { + if (dataType) { + return `Some(${dataType}::type_ref())` + } else { + return "None" + } + } + + function addImports(appName, input, output) { + if (input) { + imports.add(`use crate::entities::${appName}::${input};`) + } + if (output) { + imports.add(`use crate::entities::${appName}::${output};`) + } + } + + function makeImpl(name, input, output) { + addImports(appName, input, output) + return `crate::service_impl!(${name}, ${s.name}, ${input ?? "()"}, ${output ?? "()"});\n` + } + + if (s.bodyTypes.POST_IN || s.bodyTypes.POST_OUT) { + serviceDefinition += makeImpl("POST", s.bodyTypes.POST_IN, s.bodyTypes.POST_OUT) + } + + if (s.bodyTypes.GET_IN || s.bodyTypes.GET_OUT) { + serviceDefinition += makeImpl("GET", s.bodyTypes.GET_IN, s.bodyTypes.GET_OUT) + } + + if (s.bodyTypes.PUT_IN || s.bodyTypes.PUT_OUT) { + serviceDefinition += makeImpl("PUT", s.bodyTypes.PUT_IN, s.bodyTypes.PUT_OUT) + } + + if (s.bodyTypes.DELETE_IN || s.bodyTypes.DELETE_OUT) { + serviceDefinition += makeImpl("DELETE", s.bodyTypes.DELETE_IN, s.bodyTypes.DELETE_OUt) + } - return buf + return serviceDefinition + }) + .join("\n") + return Array.from(imports).join("\n") + code } /** diff --git a/tuta-sdk/rust/Cargo.lock b/tuta-sdk/rust/Cargo.lock index c51bb7d64892..db2ca7c2c948 100644 --- a/tuta-sdk/rust/Cargo.lock +++ b/tuta-sdk/rust/Cargo.lock @@ -29,6 +29,15 @@ dependencies = [ "zeroize", ] +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + [[package]] name = "android_liblog-sys" version = "0.1.4" @@ -168,12 +177,45 @@ dependencies = [ "syn", ] +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + [[package]] name = "autocfg" version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" +[[package]] +name = "aws-lc-rs" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdd82dba44d209fddb11c190e0a94b78651f95299598e472215667417a03ff1d" +dependencies = [ + "aws-lc-sys", + "mirai-annotations", + "paste", + "zeroize", +] + +[[package]] +name = "aws-lc-sys" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df7a4168111d7eb622a31b214057b8509c0a7e1794f44c546d742330dc793972" +dependencies = [ + "bindgen", + "cc", + "cmake", + "dunce", + "fs_extra", + "libc", + "paste", +] + [[package]] name = "backtrace" version = "0.3.73" @@ -219,6 +261,29 @@ dependencies = [ "serde", ] +[[package]] +name = "bindgen" +version = "0.69.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a00dc851838a2120612785d195287475a3ac45514741da670b735818822129a0" +dependencies = [ + "bitflags", + "cexpr", + "clang-sys", + "itertools", + "lazy_static", + "lazycell", + "log 0.4.22", + "prettyplease", + "proc-macro2", + "quote", + "regex", + "rustc-hash", + "shlex", + "syn", + "which", +] + [[package]] name = "bitflags" version = "2.5.0" @@ -260,9 +325,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.6.0" +version = "1.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" +checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3" [[package]] name = "camino" @@ -307,13 +372,28 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.98" +version = "1.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41c270e7540d725e65ac7f1b212ac8ce349719624d7bcff99f8e2e488e8cf03f" +checksum = "07b1695e2c7e8fc85310cde85aeaab7e3097f593c91d209d3f9df76c928100f0" dependencies = [ "jobserver", "libc", - "once_cell", + "shlex", +] + +[[package]] +name = "cesu8" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" + +[[package]] +name = "cexpr" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" +dependencies = [ + "nom", ] [[package]] @@ -333,6 +413,17 @@ dependencies = [ "zeroize", ] +[[package]] +name = "clang-sys" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" +dependencies = [ + "glob", + "libc", + "libloading", +] + [[package]] name = "clap" version = "4.5.9" @@ -373,6 +464,15 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4b82cf0babdbd58558212896d1a4272303a57bdb245c2bf1147185fb45640e70" +[[package]] +name = "cmake" +version = "0.1.51" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb1e43aa7fd152b1f968787f7dbcdeb306d1867ff373c69955211876c053f91a" +dependencies = [ + "cc", +] + [[package]] name = "colorchoice" version = "1.0.1" @@ -389,6 +489,16 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "combine" +version = "4.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" +dependencies = [ + "bytes", + "memchr", +] + [[package]] name = "const-hex" version = "1.12.0" @@ -408,6 +518,22 @@ version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" +[[package]] +name = "core-foundation" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + [[package]] name = "cpufeatures" version = "0.2.12" @@ -461,7 +587,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" dependencies = [ "cfg-if", - "hashbrown", + "hashbrown 0.14.5", "lock_api", "once_cell", "parking_lot_core", @@ -511,12 +637,40 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56ce8c6da7551ec6c462cbaf3bfbc75131ebbfa1c944aeaa9dab51ca1c5f0c3b" +[[package]] +name = "either" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "errno" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + [[package]] name = "fiat-crypto" version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + [[package]] name = "fragile" version = "2.0.0" @@ -532,6 +686,12 @@ dependencies = [ "autocfg", ] +[[package]] +name = "fs_extra" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" + [[package]] name = "futures" version = "0.3.30" @@ -665,18 +825,49 @@ dependencies = [ "scroll", ] +[[package]] +name = "h2" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "524e8ac6999421f49a846c2d4411f337e53497d8ec55d67753beffa43c5d9205" +dependencies = [ + "atomic-waker", + "bytes", + "fnv", + "futures-core", + "futures-sink", + "http", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + [[package]] name = "hashbrown" version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" +[[package]] +name = "hashbrown" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" + [[package]] name = "heck" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" +[[package]] +name = "hermit-abi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" + [[package]] name = "hex" version = "0.4.3" @@ -704,6 +895,131 @@ dependencies = [ "digest", ] +[[package]] +name = "home" +version = "0.5.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" +dependencies = [ + "windows-sys 0.52.0", +] + +[[package]] +name = "http" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" +dependencies = [ + "bytes", + "http", +] + +[[package]] +name = "http-body-util" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" +dependencies = [ + "bytes", + "futures-util", + "http", + "http-body", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" + +[[package]] +name = "httpdate" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" + +[[package]] +name = "hyper" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50dfd22e0e76d0f662d429a5f80fcaf3855009297eab6a0a9f8543834744ba05" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "h2", + "http", + "http-body", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "smallvec", + "tokio", + "want", +] + +[[package]] +name = "hyper-rustls" +version = "0.27.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08afdbb5c31130e3034af566421053ab03787c640246a446327f550d11bcb333" +dependencies = [ + "futures-util", + "http", + "hyper", + "hyper-util", + "log 0.4.22", + "rustls", + "rustls-native-certs 0.8.0", + "rustls-pki-types", + "rustls-platform-verifier", + "tokio", + "tokio-rustls", + "tower-service", +] + +[[package]] +name = "hyper-util" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41296eb09f183ac68eec06e03cdbea2e759633d4067b2f6552fc2e009bcad08b" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "http", + "http-body", + "hyper", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", +] + +[[package]] +name = "indexmap" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" +dependencies = [ + "equivalent", + "hashbrown 0.15.0", +] + [[package]] name = "inout" version = "0.1.3" @@ -720,12 +1036,41 @@ version = "1.70.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800" +[[package]] +name = "itertools" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" +[[package]] +name = "jni" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6df18c2e3db7e453d3c6ac5b3e9d5182664d28788126d39b91f2d1e22b017ec" +dependencies = [ + "cesu8", + "combine", + "jni-sys", + "log 0.4.22", + "thiserror", + "walkdir", +] + +[[package]] +name = "jni-sys" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" + [[package]] name = "jobserver" version = "0.1.31" @@ -741,21 +1086,43 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" dependencies = [ - "spin", + "spin 0.5.2", ] +[[package]] +name = "lazycell" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" + [[package]] name = "libc" version = "0.2.155" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" +[[package]] +name = "libloading" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4" +dependencies = [ + "cfg-if", + "windows-targets 0.48.5", +] + [[package]] name = "libm" version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" +[[package]] +name = "linux-raw-sys" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" + [[package]] name = "lock_api" version = "0.4.12" @@ -838,16 +1205,32 @@ dependencies = [ "adler", ] +[[package]] +name = "mio" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" +dependencies = [ + "libc", + "wasi", + "windows-sys 0.48.0", +] + +[[package]] +name = "mirai-annotations" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9be0862c1b3f26a88803c4a49de6889c10e608b3ee9344e6ef5b45fb37ad3d1" + [[package]] name = "mockall" -version = "0.12.1" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43766c2b5203b10de348ffe19f7e54564b64f3d6018ff7648d1e2d6d3a0f0a48" +checksum = "d4c28b3fb6d753d28c20e826cd46ee611fda1cf3cde03a443a974043247c065a" dependencies = [ "cfg-if", "downcast", "fragile", - "lazy_static", "mockall_derive", "predicates", "predicates-tree", @@ -855,9 +1238,9 @@ dependencies = [ [[package]] name = "mockall_derive" -version = "0.12.1" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af7cbce79ec385a1d4f54baa90a76401eb15d9cab93685f62e7e9f942aa00ae2" +checksum = "341014e7f530314e9a1fdbc7400b244efea7122662c96bfa248c31da5bfb2020" dependencies = [ "cfg-if", "proc-macro2", @@ -887,6 +1270,16 @@ dependencies = [ "minimal-lexical", ] +[[package]] +name = "num-bigint" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +dependencies = [ + "num-integer", + "num-traits", +] + [[package]] name = "num-bigint-dig" version = "0.8.4" @@ -940,6 +1333,16 @@ dependencies = [ "libm", ] +[[package]] +name = "num_cpus" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" +dependencies = [ + "hermit-abi", + "libc", +] + [[package]] name = "num_threads" version = "0.1.7" @@ -964,6 +1367,12 @@ version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +[[package]] +name = "openssl-probe" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" + [[package]] name = "oslog" version = "0.2.0" @@ -985,7 +1394,7 @@ dependencies = [ "libc", "redox_syscall", "smallvec", - "windows-targets 0.52.5", + "windows-targets 0.52.6", ] [[package]] @@ -1128,6 +1537,16 @@ dependencies = [ "termtree", ] +[[package]] +name = "prettyplease" +version = "0.2.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "479cf940fbbb3426c32c5d5176f62ad57549a0bb84773423ba8be9d089f5faba" +dependencies = [ + "proc-macro2", + "syn", +] + [[package]] name = "proc-macro2" version = "1.0.83" @@ -1210,12 +1629,50 @@ dependencies = [ "bitflags", ] +[[package]] +name = "regex" +version = "1.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + [[package]] name = "regex-syntax" version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" +[[package]] +name = "ring" +version = "0.17.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" +dependencies = [ + "cc", + "cfg-if", + "getrandom", + "libc", + "spin 0.9.8", + "untrusted", + "windows-sys 0.52.0", +] + [[package]] name = "rsa" version = "0.9.6" @@ -1242,6 +1699,12 @@ version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + [[package]] name = "rustc_version" version = "0.4.0" @@ -1251,12 +1714,139 @@ dependencies = [ "semver", ] +[[package]] +name = "rustix" +version = "0.38.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.52.0", +] + +[[package]] +name = "rustls" +version = "0.23.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "415d9944693cb90382053259f89fbb077ea730ad7273047ec63b19bc9b160ba8" +dependencies = [ + "aws-lc-rs", + "log 0.4.22", + "once_cell", + "ring", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-native-certs" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5bfb394eeed242e909609f56089eecfe5fda225042e8b171791b9c95f5931e5" +dependencies = [ + "openssl-probe", + "rustls-pemfile", + "rustls-pki-types", + "schannel", + "security-framework", +] + +[[package]] +name = "rustls-native-certs" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcaf18a4f2be7326cd874a5fa579fae794320a0f388d365dca7e480e55f83f8a" +dependencies = [ + "openssl-probe", + "rustls-pemfile", + "rustls-pki-types", + "schannel", + "security-framework", +] + +[[package]] +name = "rustls-pemfile" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "rustls-pki-types" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e696e35370c65c9c541198af4543ccd580cf17fc25d8e05c5a242b202488c55" + +[[package]] +name = "rustls-platform-verifier" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afbb878bdfdf63a336a5e63561b1835e7a8c91524f51621db870169eac84b490" +dependencies = [ + "core-foundation", + "core-foundation-sys", + "jni", + "log 0.4.22", + "once_cell", + "rustls", + "rustls-native-certs 0.7.3", + "rustls-platform-verifier-android", + "rustls-webpki", + "security-framework", + "security-framework-sys", + "webpki-roots", + "winapi", +] + +[[package]] +name = "rustls-platform-verifier-android" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f87165f0995f63a9fbeea62b64d10b4d9d8e78ec6d7d51fb2125fda7bb36788f" + +[[package]] +name = "rustls-webpki" +version = "0.102.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" +dependencies = [ + "aws-lc-rs", + "ring", + "rustls-pki-types", + "untrusted", +] + [[package]] name = "ryu" version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "schannel" +version = "0.1.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01227be5826fa0690321a2ba6c5cd57a19cf3f6a09e76973b58e61de6ab9d1c1" +dependencies = [ + "windows-sys 0.59.0", +] + [[package]] name = "scopeguard" version = "1.2.0" @@ -1283,6 +1873,30 @@ dependencies = [ "syn", ] +[[package]] +name = "security-framework" +version = "2.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c627723fd09706bacdb5cf41499e95098555af3c3c29d014dc3c458ef6be11c0" +dependencies = [ + "bitflags", + "core-foundation", + "core-foundation-sys", + "libc", + "num-bigint", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea4a292869320c0272d7bc55a5a6aafaff59b4f63404a003887b679a2e05b4b6" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "semver" version = "1.0.23" @@ -1294,9 +1908,9 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.202" +version = "1.0.210" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "226b61a0d411b2ba5ff6d7f73a476ac4f8bb900373459cd00fab8512828ba395" +checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" dependencies = [ "serde_derive", ] @@ -1312,9 +1926,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.202" +version = "1.0.210" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6048858004bcff69094cd972ed40a32500f153bd3be9f716b2eed2e8217c4838" +checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" dependencies = [ "proc-macro2", "quote", @@ -1343,6 +1957,12 @@ dependencies = [ "digest", ] +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + [[package]] name = "signature" version = "2.2.0" @@ -1392,12 +2012,28 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b7c388c1b5e93756d0c740965c41e8822f866621d41acbdf6336a6a168f8840c" +[[package]] +name = "socket2" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + [[package]] name = "spin" version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" + [[package]] name = "spki" version = "0.7.3" @@ -1428,9 +2064,9 @@ checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" [[package]] name = "syn" -version = "2.0.65" +version = "2.0.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2863d96a84c6439701d7a38f9de935ec562c8832cc55d1dde0f513b52fad106" +checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed" dependencies = [ "proc-macro2", "quote", @@ -1454,18 +2090,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.61" +version = "1.0.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709" +checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.61" +version = "1.0.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" +checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3" dependencies = [ "proc-macro2", "quote", @@ -1512,8 +2148,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba4f4a02a7a80d6f274636f0aa95c7e383b912d41fe721a31f29e29698585a4a" dependencies = [ "backtrace", + "bytes", + "libc", + "mio", + "num_cpus", "pin-project-lite", + "socket2", "tokio-macros", + "windows-sys 0.48.0", ] [[package]] @@ -1527,6 +2169,30 @@ dependencies = [ "syn", ] +[[package]] +name = "tokio-rustls" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" +dependencies = [ + "rustls", + "rustls-pki-types", + "tokio", +] + +[[package]] +name = "tokio-util" +version = "0.7.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", +] + [[package]] name = "toml" version = "0.5.11" @@ -1536,6 +2202,37 @@ dependencies = [ "serde", ] +[[package]] +name = "tower-service" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" + +[[package]] +name = "tracing" +version = "0.1.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +dependencies = [ + "pin-project-lite", + "tracing-core", +] + +[[package]] +name = "tracing-core" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +dependencies = [ + "once_cell", +] + +[[package]] +name = "try-lock" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + [[package]] name = "tuta-sdk" version = "0.1.0" @@ -1551,6 +2248,10 @@ dependencies = [ "futures", "hkdf", "hmac", + "http-body-util", + "hyper", + "hyper-rustls", + "hyper-util", "log 0.4.22", "minicbor", "mockall", @@ -1561,6 +2262,7 @@ dependencies = [ "rand", "rand_core", "rsa", + "rustls", "serde", "serde_bytes", "serde_json", @@ -1568,6 +2270,7 @@ dependencies = [ "simple_logger", "thiserror", "tokio", + "tuta-sdk", "uniffi", "zeroize", ] @@ -1728,6 +2431,12 @@ dependencies = [ "weedle2", ] +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + [[package]] name = "utf8parse" version = "0.2.2" @@ -1740,12 +2449,40 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +[[package]] +name = "webpki-roots" +version = "0.26.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "841c67bff177718f1d4dfefde8d8f0e78f9b6589319ba88312f567fc5841a958" +dependencies = [ + "rustls-pki-types", +] + [[package]] name = "weedle2" version = "5.0.0" @@ -1754,6 +2491,49 @@ dependencies = [ "nom", ] +[[package]] +name = "which" +version = "4.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" +dependencies = [ + "either", + "home", + "once_cell", + "rustix", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" +dependencies = [ + "windows-sys 0.48.0", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + [[package]] name = "windows-sys" version = "0.48.0" @@ -1769,7 +2549,16 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.5", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", ] [[package]] @@ -1789,18 +2578,18 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm 0.52.5", - "windows_aarch64_msvc 0.52.5", - "windows_i686_gnu 0.52.5", + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", "windows_i686_gnullvm", - "windows_i686_msvc 0.52.5", - "windows_x86_64_gnu 0.52.5", - "windows_x86_64_gnullvm 0.52.5", - "windows_x86_64_msvc 0.52.5", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", ] [[package]] @@ -1811,9 +2600,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_msvc" @@ -1823,9 +2612,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_aarch64_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_i686_gnu" @@ -1835,15 +2624,15 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_gnu" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" [[package]] name = "windows_i686_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_msvc" @@ -1853,9 +2642,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_i686_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_x86_64_gnu" @@ -1865,9 +2654,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnu" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnullvm" @@ -1877,9 +2666,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_msvc" @@ -1889,9 +2678,9 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "windows_x86_64_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "zeroize" diff --git a/tuta-sdk/rust/sdk/Cargo.toml b/tuta-sdk/rust/sdk/Cargo.toml index a46378d60b7a..37c55cc0ae35 100644 --- a/tuta-sdk/rust/sdk/Cargo.toml +++ b/tuta-sdk/rust/sdk/Cargo.toml @@ -1,13 +1,13 @@ [package] +edition = "2021" name = "tuta-sdk" version = "0.1.0" -edition = "2021" [dependencies] async-trait = "0.1.77" serde = { version = "1.0.201", features = ["derive"] } serde_json = "1.0.117" -minicbor = { version = "0.24.2" , features = ["std", "alloc"]} +minicbor = { version = "0.24.2", features = ["std", "alloc"] } thiserror = "1.0.60" base64 = "0.22.1" aes = { version = "0.8.4", features = ["zeroize"] } @@ -27,11 +27,22 @@ rsa = "0.9.6" rand_core = { version = "0.6.4", features = ["getrandom"] } serde_bytes = "0.11.14" futures = "0.3.30" -mockall_double = "0.3.1" log = "0.4.22" simple_logger = "5.0.0" uniffi = { git = "https://github.com/mozilla/uniffi-rs.git", rev = "13a1c559cb3708eeca40dcf95dc8b3ccccf3b88c" } + +# dependency required for using mocks +mockall = { version = "0.13.0", optional = true } +mockall_double = { version = "0.3.1", optional = true } + +# only used for the native rest client +hyper = { version = "1.4.1", features = ["client"], optional = true } +hyper-util = { version = "0.1.9", features = ["full"], optional = true } +http-body-util = { version = "0.1.2", optional = true } +hyper-rustls = { version = "0.27.3", features = ["ring", "http2", "rustls-platform-verifier"], optional = true } +rustls = { version = "*", optional = true } + [target.'cfg(target_os = "android")'.dependencies] android_log = "0.1.3" @@ -43,10 +54,14 @@ uniffi = { git = "https://github.com/mozilla/uniffi-rs.git", rev = "13a1c559cb37 "build", ] } + +[features] +net = ["dep:hyper", "dep:hyper-util", "dep:http-body-util", "dep:hyper-rustls", "dep:rustls"] + [dev-dependencies] -mockall = "0.12.1" -rand = "0.8.5" -tokio = { version = "1.38.0", features = ["rt", "macros"] } +tuta-sdk = { path = ".", features = ["net", "mockall", "mockall_double"] } +rand = { version = "0.8.5" } +tokio = { version = "1.38.0", features = ["rt", "rt-multi-thread", "macros"] } [lib] crate-type = ["cdylib", "staticlib", "lib"] @@ -64,3 +79,8 @@ must_use_candidate = "warn" unused_async = "warn" implicit_clone = "warn" explicit_iter_loop = "warn" + +[[example]] +name = "create_session" +path = "examples/create_session.rs" +required-features = ["net"] \ No newline at end of file diff --git a/tuta-sdk/rust/sdk/examples/create_session.rs b/tuta-sdk/rust/sdk/examples/create_session.rs new file mode 100644 index 000000000000..ac77b98fd804 --- /dev/null +++ b/tuta-sdk/rust/sdk/examples/create_session.rs @@ -0,0 +1,31 @@ +use std::error::Error; +use std::sync::Arc; +use tutasdk::net::native_rest_client::NativeRestClient; +use tutasdk::Sdk; + +fn main() -> Result<(), Box> { + let mut runtime_builder = tokio::runtime::Builder::new_current_thread(); + let runtime_builder = runtime_builder.enable_all(); + let Ok(runtime) = runtime_builder.build() else { + panic!("could not initialize tokio runtime"); + }; + + runtime.block_on(async_main()) +} + +async fn async_main() -> Result<(), Box> { + let rest_client = Arc::new(NativeRestClient::try_new().unwrap()); + + // this test expect local server with matching model versions to be live at: http://localhost:9000 + let sdk = Sdk::new( + "http://localhost:9000".to_string(), + rest_client.clone(), + tutasdk::CLIENT_VERSION.to_owned(), + ); + + sdk.create_session("map-free@tutanota.de", "map") + .await + .map(|_| ())?; + + Ok(()) +} diff --git a/tuta-sdk/rust/sdk/src/crypto/aes.rs b/tuta-sdk/rust/sdk/src/crypto/aes.rs index 13d5965d123f..a7e1bac6046a 100644 --- a/tuta-sdk/rust/sdk/src/crypto/aes.rs +++ b/tuta-sdk/rust/sdk/src/crypto/aes.rs @@ -142,7 +142,6 @@ trait AesKey: Clone { /// An initialisation vector for AES encryption pub struct Iv([u8; IV_BYTE_SIZE]); -#[cfg(test)] impl Clone for Iv { /// Clone the initialization vector /// @@ -166,6 +165,10 @@ impl Iv { fn from_slice(slice: &[u8]) -> Option { Self::from_bytes(slice).ok() } + + pub fn get_inner(&self) -> &[u8; IV_BYTE_SIZE] { + &self.0 + } } #[derive(thiserror::Error, Debug)] diff --git a/tuta-sdk/rust/sdk/src/crypto/crypto_facade.rs b/tuta-sdk/rust/sdk/src/crypto/crypto_facade.rs index bd5ffc473fa3..2e9ceabfceba 100644 --- a/tuta-sdk/rust/sdk/src/crypto/crypto_facade.rs +++ b/tuta-sdk/rust/sdk/src/crypto/crypto_facade.rs @@ -1,22 +1,23 @@ -use std::sync::Arc; - -use zeroize::Zeroizing; - use crate::crypto::aes::Iv; use crate::crypto::ecc::EccPublicKey; use crate::crypto::key::{AsymmetricKeyPair, GenericAesKey, KeyLoadError}; use crate::crypto::randomizer_facade::RandomizerFacade; use crate::crypto::rsa::{RSAEccKeyPair, RSAEncryptionError}; use crate::crypto::tuta_crypt::{PQError, PQMessage}; +use crate::crypto::Aes256Key; use crate::element_value::{ElementValue, ParsedEntity}; use crate::entities::sys::BucketKey; use crate::generated_id::GeneratedId; use crate::instance_mapper::InstanceMapper; -#[mockall_double::double] +#[cfg_attr(test, mockall_double::double)] use crate::key_loader_facade::KeyLoaderFacade; use crate::metamodel::TypeModel; use crate::util::ArrayCastingError; use crate::IdTuple; +use base64::prelude::BASE64_URL_SAFE_NO_PAD; +use base64::Engine; +use std::sync::Arc; +use zeroize::Zeroizing; /// The name of the field that contains the session key encrypted /// by the owner group's key in an entity @@ -32,13 +33,14 @@ const BUCKET_KEY_FIELD: &str = "bucketKey"; #[derive(uniffi::Object)] pub struct CryptoFacade { - key_loader_facade: Arc, + key_loader_facade: Option>, instance_mapper: Arc, randomizer_facade: RandomizerFacade, } /// Session key that encrypts an entity and the same key encrypted with the owner group. /// owner_enc_session_key is stored on entities to avoid public key encryption on subsequent loads. +#[derive(Clone)] pub struct ResolvedSessionKey { pub session_key: GenericAesKey, pub owner_enc_session_key: Vec, @@ -47,7 +49,7 @@ pub struct ResolvedSessionKey { #[cfg_attr(test, mockall::automock)] impl CryptoFacade { pub fn new( - key_loader_facade: Arc, + key_loader_facade: Option>, instance_mapper: Arc, randomizer_facade: RandomizerFacade, ) -> Self { @@ -99,6 +101,10 @@ impl CryptoFacade { let group_key: GenericAesKey = self .key_loader_facade + .as_ref() + .ok_or(KeyLoadError { + reason: "not logged in yet".to_string(), + })? .load_sym_group_key(owner_group, owner_key_version, None) .await?; @@ -168,6 +174,10 @@ impl CryptoFacade { // TODO: authenticate let versioned_key = self .key_loader_facade + .as_ref() + .ok_or(KeyLoadError { + reason: "not logged in yet".to_string(), + })? .get_current_sym_group_key(owner_group) .await?; @@ -198,6 +208,10 @@ impl CryptoFacade { { let keypair = self .key_loader_facade + .as_ref() + .ok_or(KeyLoadError { + reason: "not logged in yet".to_string(), + })? .load_key_pair(key_group, bucket_key.recipientKeyVersion) .await?; match keypair { @@ -310,14 +324,14 @@ impl<'a> EntityOwnerKeyData<'a> { entity: &'a ParsedEntity, ) -> Result, SessionKeyResolutionError> { macro_rules! get_nullable_field { - ($entity:expr, $field:expr, $type:tt) => { - match $entity.get($field) { - Some(ElementValue::$type(q)) => Ok(Some(q)), - None | Some(ElementValue::Null) => Ok(None), // none = not present on type, null = present on type but null - Some(actual) => Err(SessionKeyResolutionError { reason: format!("field `{}` is not the expected type, got {} instead", $field, actual.type_variant_name()) }) - } - }; - } + ($entity:expr, $field:expr, $type:tt) => { + match $entity.get($field) { + Some(ElementValue::$type(q)) => Ok(Some(q)), + None | Some(ElementValue::Null) => Ok(None), // none = not present on type, null = present on type but null + Some(actual) => Err(SessionKeyResolutionError { reason: format!("field `{}` is not the expected type, got {} instead", $field, actual.type_variant_name()) }), + } + }; + } let owner_enc_session_key = get_nullable_field!(entity, OWNER_ENC_SESSION_FIELD, Bytes)?; let owner_key_version = @@ -332,7 +346,7 @@ impl<'a> EntityOwnerKeyData<'a> { } } -#[derive(thiserror::Error, Debug)] +#[derive(thiserror::Error, Debug, Clone)] #[error("Session key resolution failure: {reason}")] pub struct SessionKeyResolutionError { reason: String, @@ -602,7 +616,7 @@ mod test { .once(); CryptoFacade { - key_loader_facade: Arc::new(key_loader), + key_loader_facade: Some(Arc::new(key_loader)), instance_mapper: Arc::new(InstanceMapper::new()), randomizer_facade, } @@ -636,3 +650,8 @@ mod test { } } } + +pub fn create_auth_verifier(user_passphrase_key: Aes256Key) -> String { + let sha_user_passphrase = crate::crypto::sha::sha256(user_passphrase_key.as_bytes()); + BASE64_URL_SAFE_NO_PAD.encode(sha_user_passphrase) +} diff --git a/tuta-sdk/rust/sdk/src/crypto/key_encryption.rs b/tuta-sdk/rust/sdk/src/crypto/key_encryption.rs index 6602ee448fbe..7b8088d84b38 100644 --- a/tuta-sdk/rust/sdk/src/crypto/key_encryption.rs +++ b/tuta-sdk/rust/sdk/src/crypto/key_encryption.rs @@ -115,7 +115,7 @@ mod tests { use crate::crypto::ecc::EccKeyPair; use crate::crypto::key::{AsymmetricKeyPair, GenericAesKey}; use crate::crypto::randomizer_facade::test_util::make_thread_rng_facade; - use crate::crypto::{Aes256Key, Iv, PQKeyPairs}; + use crate::crypto::{aes::Iv, Aes256Key, PQKeyPairs}; use crate::entities::sys::KeyPair; use crate::util::test_utils::generate_random_string; diff --git a/tuta-sdk/rust/sdk/src/crypto/mod.rs b/tuta-sdk/rust/sdk/src/crypto/mod.rs index 17b5337d809d..52d6027a3a8b 100644 --- a/tuta-sdk/rust/sdk/src/crypto/mod.rs +++ b/tuta-sdk/rust/sdk/src/crypto/mod.rs @@ -4,8 +4,6 @@ #[allow(unused_imports)] pub use aes::Aes128Key; -#[cfg(test)] -pub use aes::Iv; pub use aes::PlaintextAndIv; #[allow(unused_imports)] pub use aes::{Aes256Key, AES_256_KEY_SIZE, IV_BYTE_SIZE}; @@ -15,7 +13,7 @@ pub use sha::sha256; #[allow(unused_imports)] pub use tuta_crypt::PQKeyPairs; -mod aes; +pub mod aes; mod sha; diff --git a/tuta-sdk/rust/sdk/src/crypto_entity_client.rs b/tuta-sdk/rust/sdk/src/crypto_entity_client.rs index c3a21ad43b27..4d8583ffe7a1 100644 --- a/tuta-sdk/rust/sdk/src/crypto_entity_client.rs +++ b/tuta-sdk/rust/sdk/src/crypto_entity_client.rs @@ -1,8 +1,8 @@ -#[mockall_double::double] +#[cfg_attr(test, mockall_double::double)] use crate::crypto::crypto_facade::CryptoFacade; use crate::entities::entity_facade::EntityFacade; use crate::entities::Entity; -#[mockall_double::double] +#[cfg_attr(test, mockall_double::double)] use crate::entity_client::EntityClient; use crate::entity_client::IdType; use crate::instance_mapper::InstanceMapper; @@ -18,6 +18,12 @@ pub struct CryptoEntityClient { instance_mapper: Arc, } +impl CryptoEntityClient { + pub fn get_crypto_facade(&self) -> &Arc { + &self.crypto_facade + } +} + #[cfg_attr(test, mockall::automock)] impl CryptoEntityClient { pub fn new( @@ -33,6 +39,7 @@ impl CryptoEntityClient { instance_mapper, } } + pub async fn load, ID: IdType>( &self, id: &ID, @@ -95,7 +102,7 @@ impl CryptoEntityClient { mod tests { use crate::crypto::crypto_facade::{MockCryptoFacade, ResolvedSessionKey}; use crate::crypto::key::GenericAesKey; - use crate::crypto::{Aes256Key, Iv}; + use crate::crypto::{aes::Iv, Aes256Key}; use crate::crypto_entity_client::CryptoEntityClient; use crate::date::DateTime; use crate::entities::entity_facade::EntityFacadeImpl; diff --git a/tuta-sdk/rust/sdk/src/custom_id.rs b/tuta-sdk/rust/sdk/src/custom_id.rs index 2bee02076092..6f324e1eeec4 100644 --- a/tuta-sdk/rust/sdk/src/custom_id.rs +++ b/tuta-sdk/rust/sdk/src/custom_id.rs @@ -6,7 +6,7 @@ use std::fmt::{Debug, Display, Formatter}; pub const CUSTOM_ID_STRUCT_NAME: &str = "CustomId"; /// An ID that uses arbitrary data encoded in base64 -#[derive(Clone, Default, PartialEq, PartialOrd)] +#[derive(Clone, Default, Eq, PartialEq, PartialOrd)] #[repr(transparent)] pub struct CustomId(pub String); diff --git a/tuta-sdk/rust/sdk/src/element_value.rs b/tuta-sdk/rust/sdk/src/element_value.rs index bb173a05f276..88832e31fb0b 100644 --- a/tuta-sdk/rust/sdk/src/element_value.rs +++ b/tuta-sdk/rust/sdk/src/element_value.rs @@ -8,119 +8,199 @@ use std::collections::HashMap; /// Primitive value types used by entity/instance types #[derive(uniffi::Enum, Debug, Serialize, Deserialize, PartialEq, Clone)] pub enum ElementValue { - Null, - String(String), - Number(i64), - Bytes(Vec), - Date(DateTime), - Bool(bool), - // Names are prefixed with 'Id' to avoid name collision in Kotlin - IdGeneratedId(GeneratedId), - IdCustomId(CustomId), - IdTupleId(IdTuple), - Dict(HashMap), - Array(Vec), + Null, + String(String), + Number(i64), + Bytes(Vec), + Date(DateTime), + Bool(bool), + // Names are prefixed with 'Id' to avoid name collision in Kotlin + IdGeneratedId(GeneratedId), + IdCustomId(CustomId), + IdTupleId(IdTuple), + Dict(HashMap), + Array(Vec), } pub type ParsedEntity = HashMap; impl ElementValue { - pub fn assert_number(&self) -> i64 { - match self { - ElementValue::Number(number) => *number, - _ => panic!("Invalid type"), - } - } - - pub fn assert_string(&self) -> String { - self.assert_str().to_string() - } - - pub fn assert_array(&self) -> Vec { - match self { - ElementValue::Array(value) => value.clone(), - _ => panic!("Invalid type"), - } - } - - pub fn assert_bytes(&self) -> Vec { - match self { - ElementValue::Bytes(value) => value.clone(), - _ => panic!( - "Invalid type, expected bytes, got: {}", - self.type_variant_name() - ), - } - } - - pub fn assert_dict(&self) -> HashMap { - match self { - ElementValue::Dict(value) => value.clone(), - _ => panic!("Invalid type"), - } - } - - pub fn assert_array_ref(&self) -> &Vec { - match self { - ElementValue::Array(value) => value, - _ => panic!("Invalid type"), - } - } - - pub fn assert_dict_ref(&self) -> &HashMap { - match self { - ElementValue::Dict(value) => value, - _ => panic!("Invalid type"), - } - } - - pub fn assert_str(&self) -> &str { - match self { - ElementValue::String(value) => value, - _ => panic!("Invalid type"), - } - } - - pub fn assert_generated_id(&self) -> &GeneratedId { - match self { - ElementValue::IdGeneratedId(value) => value, - _ => panic!("Invalid type"), - } - } - pub fn assert_tuple_id(&self) -> &IdTuple { - match self { - ElementValue::IdTupleId(value) => value, - _ => panic!("Invalid type"), - } - } - - pub fn assert_date(&self) -> &DateTime { - match self { - ElementValue::Date(value) => value, - _ => panic!("Invalid type"), - } - } - - pub fn assert_bool(&self) -> bool { - match self { - ElementValue::Bool(value) => *value, - _ => panic!("Invalid type"), - } - } - - pub(crate) fn type_variant_name(&self) -> &'static str { - match self { - Self::Null => "Null", - Self::String(_) => "String", - Self::Number(_) => "Number", - Self::Bytes(_) => "Bytes", - Self::Date(_) => "Date", - Self::Bool(_) => "Bool", - Self::IdGeneratedId(_) => "IdGeneratedId", - Self::IdCustomId(_) => "IdCustomId", - Self::IdTupleId(_) => "IdTupleId", - Self::Dict(_) => "Dict", - Self::Array(_) => "Array", - } - } + pub fn assert_number(&self) -> i64 { + match self { + ElementValue::Number(number) => *number, + _ => panic!("Invalid type"), + } + } + + pub fn assert_string(&self) -> String { + self.assert_str().to_string() + } + + pub fn assert_array(&self) -> Vec { + match self { + ElementValue::Array(value) => value.clone(), + _ => panic!("Invalid type"), + } + } + + pub fn assert_bytes(&self) -> Vec { + match self { + ElementValue::Bytes(value) => value.clone(), + _ => panic!( + "Invalid type, expected bytes, got: {}", + self.type_variant_name() + ), + } + } + + pub fn assert_dict(&self) -> HashMap { + match self { + ElementValue::Dict(value) => value.clone(), + _ => panic!("Invalid type"), + } + } + + pub fn assert_array_ref(&self) -> &Vec { + match self { + ElementValue::Array(value) => value, + _ => panic!("Invalid type"), + } + } + + pub fn assert_dict_ref(&self) -> &HashMap { + match self { + ElementValue::Dict(value) => value, + _ => panic!("Invalid type"), + } + } + + pub fn assert_dict_mut_ref(&mut self) -> &mut HashMap { + match self { + ElementValue::Dict(value) => value, + _ => panic!("Invalid type"), + } + } + + pub fn assert_str(&self) -> &str { + match self { + ElementValue::String(value) => value, + _ => panic!("Invalid type"), + } + } + + pub fn assert_generated_id(&self) -> &GeneratedId { + match self { + ElementValue::IdGeneratedId(value) => value, + _ => panic!("Invalid type"), + } + } + pub fn assert_tuple_id(&self) -> &IdTuple { + match self { + ElementValue::IdTupleId(value) => value, + _ => panic!("Invalid type"), + } + } + + pub fn assert_custom_id(&self) -> &CustomId { + match self { + ElementValue::IdCustomId(value) => value, + _ => panic!("Invalid type"), + } + } + + pub fn assert_date(&self) -> &DateTime { + match self { + ElementValue::Date(value) => value, + _ => panic!("Invalid type"), + } + } + + pub fn assert_bool(&self) -> bool { + match self { + ElementValue::Bool(value) => *value, + _ => panic!("Invalid type"), + } + } + + pub(crate) fn type_variant_name(&self) -> &'static str { + match self { + Self::Null => "Null", + Self::String(_) => "String", + Self::Number(_) => "Number", + Self::Bytes(_) => "Bytes", + Self::Date(_) => "Date", + Self::Bool(_) => "Bool", + Self::IdGeneratedId(_) => "IdGeneratedId", + Self::IdCustomId(_) => "IdCustomId", + Self::IdTupleId(_) => "IdTupleId", + Self::Dict(_) => "Dict", + Self::Array(_) => "Array", + } + } +} + +impl From<()> for ElementValue { + fn from(value: ()) -> Self { + Self::Null + } +} + +impl From for ElementValue { + fn from(value: String) -> Self { + Self::String(value) + } } + +impl From for ElementValue { + fn from(value: i64) -> Self { + Self::Number(value) + } +} + +impl From> for ElementValue { + fn from(value: Vec) -> Self { + Self::Bytes(value) + } +} + +impl From for ElementValue { + fn from(value: DateTime) -> Self { + Self::Date(value) + } +} + +impl From for ElementValue { + fn from(value: bool) -> Self { + Self::Bool(value) + } +} + +impl From for ElementValue { + fn from(value: GeneratedId) -> Self { + Self::IdGeneratedId(value) + } +} + +impl From for ElementValue { + fn from(value: CustomId) -> Self { + Self::IdCustomId(value) + } +} + +impl From for ElementValue { + fn from(value: IdTuple) -> Self { + Self::IdTupleId(value) + } +} + +impl From> for ElementValue { + fn from(value: HashMap) -> Self { + Self::Dict(value) + } +} + +impl From> for ElementValue { + fn from(value: Vec) -> Self { + Self::Array(value) + } +} \ No newline at end of file diff --git a/tuta-sdk/rust/sdk/src/entities/accounting.rs b/tuta-sdk/rust/sdk/src/entities/accounting.rs index 86f51edd5099..750ce15fbf34 100644 --- a/tuta-sdk/rust/sdk/src/entities/accounting.rs +++ b/tuta-sdk/rust/sdk/src/entities/accounting.rs @@ -2,7 +2,7 @@ use super::*; use serde::{Deserialize, Serialize}; -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct CustomerAccountPosting { pub _id: CustomId, pub amount: i64, @@ -12,7 +12,6 @@ pub struct CustomerAccountPosting { pub valueDate: DateTime, pub _finalIvs: HashMap, } - impl Entity for CustomerAccountPosting { fn type_ref() -> TypeRef { TypeRef { @@ -22,7 +21,7 @@ impl Entity for CustomerAccountPosting { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct CustomerAccountReturn { pub _format: i64, pub _ownerGroup: Option, @@ -35,7 +34,6 @@ pub struct CustomerAccountReturn { pub _errors: Option, pub _finalIvs: HashMap, } - impl Entity for CustomerAccountReturn { fn type_ref() -> TypeRef { TypeRef { diff --git a/tuta-sdk/rust/sdk/src/entities/base.rs b/tuta-sdk/rust/sdk/src/entities/base.rs index 34da086a9db9..1a58f2ef4c60 100644 --- a/tuta-sdk/rust/sdk/src/entities/base.rs +++ b/tuta-sdk/rust/sdk/src/entities/base.rs @@ -2,13 +2,12 @@ use super::*; use serde::{Deserialize, Serialize}; -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct PersistenceResourcePostReturn { pub _format: i64, pub generatedId: Option, pub permissionListId: GeneratedId, } - impl Entity for PersistenceResourcePostReturn { fn type_ref() -> TypeRef { TypeRef { @@ -17,3 +16,6 @@ impl Entity for PersistenceResourcePostReturn { } } } + + + diff --git a/tuta-sdk/rust/sdk/src/entities/entity_facade.rs b/tuta-sdk/rust/sdk/src/entities/entity_facade.rs index 05ccc9d72f41..4614e6b73fa3 100644 --- a/tuta-sdk/rust/sdk/src/entities/entity_facade.rs +++ b/tuta-sdk/rust/sdk/src/entities/entity_facade.rs @@ -1,21 +1,22 @@ -#![allow(unused)] // TODO: Remove this when implementing the crypto entity client -use std::borrow::Borrow; -use std::collections::HashMap; -use std::sync::Arc; - use crate::crypto::crypto_facade::ResolvedSessionKey; use crate::crypto::key::GenericAesKey; -use crate::crypto::PlaintextAndIv; +use crate::crypto::randomizer_facade::RandomizerFacade; +use crate::crypto::{aes::Iv, PlaintextAndIv, IV_BYTE_SIZE}; use crate::date::DateTime; -use crate::element_value::ElementValue::Bool; use crate::element_value::{ElementValue, ParsedEntity}; use crate::entities::Errors; use crate::metamodel::{ - AssociationType, Cardinality, ModelAssociation, ModelValue, TypeModel, ValueType, + AssociationType, Cardinality, ElementType, ModelAssociation, ModelValue, TypeModel, ValueType, }; use crate::type_model_provider::TypeModelProvider; -use crate::util::{array_cast_slice, resolve_default_value}; +use crate::util::array_cast_slice; use crate::ApiCallError; +use base64::prelude::{BASE64_STANDARD, BASE64_URL_SAFE_NO_PAD}; +use base64::Engine; +use minicbor::Encode; +use std::borrow::Borrow; +use std::collections::HashMap; +use std::sync::Arc; /// Provides high level functions to handle encryption/decryption of entities #[derive(uniffi::Object)] @@ -33,6 +34,26 @@ struct MappedValue { error: Option, } +#[derive(Clone)] +enum IvProvider { + Fixed(Iv), + Random, +} +impl IvProvider { + fn provide_iv(&self) -> Iv { + match self { + IvProvider::Random => Iv::from_bytes( + &RandomizerFacade::from_core(rand_core::OsRng) + .generate_random_array::() + .to_vec(), + ) + .unwrap(), + + IvProvider::Fixed(iv) => iv.clone(), + } + } +} + #[cfg_attr(test, mockall::automock)] pub trait EntityFacade: Send + Sync { fn decrypt_and_map( @@ -41,6 +62,13 @@ pub trait EntityFacade: Send + Sync { entity: ParsedEntity, resolved_session_key: ResolvedSessionKey, ) -> Result; + + fn encrypt_and_map_to_literal( + &self, + type_model: &TypeModel, + instance: &ParsedEntity, + sk: Option, + ) -> Result; } impl EntityFacadeImpl { @@ -50,6 +78,234 @@ impl EntityFacadeImpl { } } + fn should_restore_default_value( + model_value: &ModelValue, + value: &ElementValue, + instance: &ParsedEntity, + key: &str, + ) -> bool { + if model_value.encrypted { + if let Some(final_ivs) = Self::get_final_iv_for_key(instance, key) { + return final_ivs.assert_bytes().is_empty() + && value == &ValueType::get_default(&model_value.value_type); + } + } + false + } + + fn encrypt_value( + value_name: &str, + model_value: &ModelValue, + instance_value: &ElementValue, + session_key: &Option, + iv_provider: IvProvider, + ) -> Result { + let value_type = &model_value.value_type; + + if value_name == "_id" || value_name == "_permissions" { + Ok(instance_value.clone()) + } else if >::is_nil(instance_value) { + if model_value.cardinality == Cardinality::ZeroOrOne { + Ok(ElementValue::Null) + } else { + Err(ApiCallError::internal(format!( + "Value {value_name} with cardinality ONE can not be null" + ))) + } + } else if model_value.encrypted { + let iv = iv_provider.provide_iv(); + let bytes = Self::map_value_to_binary(value_type, instance_value) + .expect(&format!("invalid encrypted value {:?}", instance_value)); + let encrypted_data = session_key + .as_ref() + .ok_or(ApiCallError::internal( + "session_key can't be null for encrypted value".to_string(), + ))? + .encrypt_data(bytes.as_slice(), iv) + .expect("Cannot encrypt data"); + Ok(ElementValue::Bytes(encrypted_data)) + } else { + Ok(instance_value.clone()) + } + } + + fn get_final_iv_for_key(instance: &ParsedEntity, key: &str) -> Option { + if let Some(final_ivs) = instance.get("_finalIvs") { + if let Some(array) = final_ivs.assert_dict_ref().get(key) { + return Some(ElementValue::Bytes(array.assert_bytes())); + }; + }; + None + } + + fn map_value_to_db_type(value_type: &ValueType, value: &ElementValue) -> ElementValue { + match value { + ElementValue::Date(d) => ElementValue::String(d.as_millis().to_string()), + ElementValue::Bool(b) => ElementValue::String(if *b { + String::from("1") + } else { + String::from("0") + }), + ElementValue::Number(n) => ElementValue::String(n.to_string()), + other => other.clone(), + } + } + + fn map_value_to_binary(value_type: &ValueType, value: &ElementValue) -> Option> { + if >::is_nil(value) { + return None; + } + match value_type { + ValueType::Bytes => Some(value.assert_bytes()), + ValueType::String => Some(value.assert_string().as_bytes().to_vec()), + ValueType::Number => Some(value.assert_number().to_string().as_bytes().to_vec()), + ValueType::Date => Some( + value + .assert_date() + .as_millis() + .to_string() + .as_bytes() + .to_vec(), + ), + ValueType::Boolean => Some(if value.assert_bool() { b"1" } else { b"0" }.to_vec()), + ValueType::GeneratedId => Some(value.assert_generated_id().0.as_bytes().to_vec()), + ValueType::CustomId => Some(value.assert_custom_id().0.as_bytes().to_vec()), + ValueType::CompressedString => unimplemented!("compressed string"), + } + } + + fn encrypt_and_map_to_literal_with_iv( + &self, + type_model: &TypeModel, + instance: &ParsedEntity, + sk: Option, + random_iv_provider: IvProvider, + ) -> Result { + if type_model.marked_encrypted() && sk.is_none() { + return Err(ApiCallError::InternalSdkError { + error_message: format!( + "Encrypting {}/{} requires a session key!", + type_model.app, type_model.name + ), + }); + } + let mut encrypted = ParsedEntity::new(); + + for (key, model_value) in type_model.values.iter() { + let instance_value = instance + .get(&key.to_string()) + .expect(format!("Can not find key: {key} in instance: {instance:?}").as_str()); + + let encrypted_value: ElementValue; + + if Self::should_restore_default_value(&model_value, instance_value, &instance, &key) { + // restore the default encrypted value because it has not changed + // note: this branch must be checked *before* the one which reuses IVs as this one checks + // the length. + encrypted_value = ElementValue::String("".to_string()); + } else if model_value.encrypted + && model_value.is_final + && Self::get_final_iv_for_key(instance, key).is_some() + { + let final_iv = Iv::from_bytes( + Self::get_final_iv_for_key(instance, key) + .unwrap() + .assert_bytes() + .as_slice(), + ) + .map_err(|err| ApiCallError::internal(format!("iv of illegal size {:?}", err)))?; + encrypted_value = Self::encrypt_value( + key, + model_value, + instance_value, + &sk, + IvProvider::Fixed(final_iv), + )? + } else { + encrypted_value = Self::encrypt_value( + key, + model_value, + instance_value, + &sk, + random_iv_provider.clone(), + )? + } + encrypted.insert(key.to_string(), encrypted_value); + } + + if type_model.element_type == ElementType::Aggregated && encrypted.get("_id").is_none() { + let randomizer = RandomizerFacade::from_core(rand_core::OsRng); + let new_id = randomizer.generate_random_array::<4>(); + + encrypted.insert( + String::from("_id"), + ElementValue::String( + BASE64_URL_SAFE_NO_PAD.encode(BASE64_STANDARD.encode(&new_id)), + ), + ); + } + + for (association_name, association) in type_model.associations.iter() { + if let AssociationType::Aggregation = association.association_type { + let dependency = association.dependency.unwrap_or(type_model.app); + let aggregated_type_model = self + .type_model_provider + .get_type_model(dependency, association.ref_type) + .expect(&format!( + "Cannot find type model for: {:?}", + (dependency, association.ref_type) + )); + let aggregation = association; + let instance_association = instance.get(&association_name.to_string()).unwrap(); + if aggregation.cardinality == Cardinality::ZeroOrOne + && instance_association == &ElementValue::Null + { + encrypted.insert(association_name.to_string(), ElementValue::Null); + } else if instance_association == &ElementValue::Null { + panic!("Undefined attribute {}:{association_name}", type_model.name); + } else if aggregation.cardinality == Cardinality::Any { + let aggregates = instance_association.assert_array(); + let mut encrypted_aggregates = Vec::with_capacity(aggregates.len()); + for aggregate in aggregates.iter() { + let parsed_entity = self.encrypt_and_map_to_literal_with_iv( + aggregated_type_model, + &aggregate.assert_dict(), + sk.clone(), + random_iv_provider.clone(), + )?; + encrypted_aggregates.push(ElementValue::Dict(parsed_entity)); + } + + encrypted.insert( + association_name.to_string(), + ElementValue::Array(encrypted_aggregates), + ); + } else { + let parsed_entity = self.encrypt_and_map_to_literal_with_iv( + aggregated_type_model, + &instance_association.assert_dict(), + sk.clone(), + random_iv_provider.clone(), + )?; + let encrypted_aggregate = ElementValue::Dict(parsed_entity); + encrypted.insert(association_name.to_string(), encrypted_aggregate); + } + } else { + encrypted.insert( + association_name.to_string(), + instance.get(&association_name.to_string()).cloned().ok_or( + ApiCallError::internal(format!( + "could not find association {association_name} on type {}", + type_model.name + )), + )?, + ); + } + } + + Ok(encrypted) + } + fn decrypt_and_map_inner( &self, type_model: &TypeModel, @@ -217,7 +473,7 @@ impl EntityFacadeImpl { // If the value is default-encrypted (empty string) then return default value and // empty IV. When re-encrypting we should put the empty value back to not increase // used storage. - let value = resolve_default_value(&model_value.value_type); + let value = model_value.value_type.get_default(); Ok(MappedValue { value, iv: Some(Vec::new()), @@ -260,7 +516,7 @@ impl EntityFacadeImpl { }) }, Err(err) => Ok(MappedValue { - value: resolve_default_value(&model_value.value_type), + value: model_value.value_type.get_default(), iv: None, error: Some(format!("Failed to decrypt {key}. {err}")), }), @@ -319,7 +575,7 @@ impl EntityFacadeImpl { }) }, }; - Ok(Bool(value)) + Ok(ElementValue::Bool(value)) }, ValueType::CompressedString => unimplemented!("compressed string"), v => unreachable!("Can't parse {v:?} into ElementValue"), @@ -331,7 +587,7 @@ impl EntityFacade for EntityFacadeImpl { fn decrypt_and_map( &self, type_model: &TypeModel, - mut entity: ParsedEntity, + entity: ParsedEntity, resolved_session_key: ResolvedSessionKey, ) -> Result { let mut mapped_decrypted = @@ -342,42 +598,50 @@ impl EntityFacade for EntityFacadeImpl { ); Ok(mapped_decrypted) } + + fn encrypt_and_map_to_literal( + &self, + type_model: &TypeModel, + instance: &ParsedEntity, + sk: Option, + ) -> Result { + self.encrypt_and_map_to_literal_with_iv(type_model, instance, sk, IvProvider::Random) + } } #[cfg(test)] mod tests { - use std::sync::Arc; - - use rand::random; - - use crate::collection; use crate::crypto::crypto_facade::ResolvedSessionKey; use crate::crypto::key::GenericAesKey; - use crate::crypto::{Aes256Key, Iv}; + use crate::crypto::randomizer_facade::RandomizerFacade; + use crate::crypto::{aes::Iv, Aes256Key}; use crate::date::DateTime; - use crate::element_value::ParsedEntity; - use crate::entities::entity_facade::{EntityFacade, EntityFacadeImpl}; + use crate::element_value::{ElementValue, ParsedEntity}; + use crate::entities::entity_facade::{EntityFacade, EntityFacadeImpl, IvProvider}; + use crate::entities::sys::CustomerAccountTerminationRequest; use crate::entities::tutanota::Mail; use crate::entities::Entity; use crate::instance_mapper::InstanceMapper; use crate::json_element::{JsonElement, RawEntity}; use crate::json_serializer::JsonSerializer; + use crate::metamodel::{Cardinality, ModelValue, ValueType}; use crate::type_model_provider::init_type_model_provider; + use crate::util::entity_test_utils::generate_email_entity; + use crate::{collection, ApiCallError}; + use std::collections::{BTreeMap, HashMap}; + use std::sync::Arc; + use std::time::SystemTime; + + const KNOWN_SK: [u8; 32] = [ + 83, 168, 168, 203, 48, 91, 246, 102, 175, 252, 39, 110, 36, 141, 4, 216, 135, 201, 226, + 134, 182, 175, 15, 152, 117, 216, 81, 1, 120, 134, 116, 143, + ]; #[test] fn test_decrypt_mail() { - let sk = GenericAesKey::Aes256( - Aes256Key::from_bytes( - vec![ - 83, 168, 168, 203, 48, 91, 246, 102, 175, 252, 39, 110, 36, 141, 4, 216, 135, - 201, 226, 134, 182, 175, 15, 152, 117, 216, 81, 1, 120, 134, 116, 143, - ] - .as_slice(), - ) - .unwrap(), - ); + let sk = GenericAesKey::Aes256(Aes256Key::from_bytes(KNOWN_SK.as_slice()).unwrap()); let owner_enc_session_key = vec![0, 1, 2]; - let iv = Iv::from_bytes(&random::<[u8; 16]>()).unwrap(); + let iv = Iv::from_bytes(&rand::random::<[u8; 16]>()).unwrap(); let type_model_provider = Arc::new(init_type_model_provider()); let raw_entity: RawEntity = make_json_entity(); let json_serializer = JsonSerializer::new(type_model_provider.clone()); @@ -466,6 +730,656 @@ mod tests { ); } + #[test] + fn encrypt_value_string() { + let model_value = create_model_value(ValueType::String, true, Cardinality::One); + let sk = GenericAesKey::from_bytes(&[rand::random(); 32]).ok(); + let iv = Iv::generate(&RandomizerFacade::from_core(rand_core::OsRng)); + let value = ElementValue::String("this is a string value".to_string()); + + let encrypted_value = EntityFacadeImpl::encrypt_value( + "test", + &model_value, + &value, + &sk, + IvProvider::Fixed(iv.clone()), + ); + + let expected = sk + .unwrap() + .encrypt_data(value.assert_string().as_bytes(), iv) + .unwrap(); + + assert_eq!(expected, encrypted_value.unwrap().assert_bytes().to_vec()) + } + + #[test] + fn encrypt_value_bool() { + let model_value = create_model_value(ValueType::Boolean, true, Cardinality::One); + let sk = GenericAesKey::from_bytes(&[rand::random(); 32]).ok(); + let iv = Iv::generate(&RandomizerFacade::from_core(rand_core::OsRng)); + + { + let value = ElementValue::Bool(true); + + let encrypted_value = EntityFacadeImpl::encrypt_value( + "test", + &model_value, + &value, + &sk, + IvProvider::Fixed(iv.clone()), + ); + + let expected = sk + .clone() + .unwrap() + .encrypt_data("1".as_bytes(), iv.clone()) + .unwrap(); + assert_eq!(expected, encrypted_value.unwrap().assert_bytes().to_vec()) + } + + { + let value = ElementValue::Bool(false); + let encrypted_value = EntityFacadeImpl::encrypt_value( + "test", + &model_value, + &value, + &sk, + IvProvider::Fixed(iv.clone()), + ); + + let expected = sk + .clone() + .unwrap() + .encrypt_data("0".as_bytes(), iv.clone()) + .unwrap(); + assert_eq!(expected, encrypted_value.unwrap().assert_bytes().to_vec()) + } + } + + #[test] + fn encrypt_value_date() { + let model_value = create_model_value(ValueType::Date, true, Cardinality::One); + let sk = GenericAesKey::from_bytes(&[rand::random(); 32]).ok(); + let iv = Iv::generate(&RandomizerFacade::from_core(rand_core::OsRng)); + let value = ElementValue::Date(DateTime::from_system_time(SystemTime::now())); + + let encrypted_value = EntityFacadeImpl::encrypt_value( + "test", + &model_value, + &value, + &sk, + IvProvider::Fixed(iv.clone()), + ); + + let expected = sk + .unwrap() + .encrypt_data(value.assert_date().as_millis().to_string().as_bytes(), iv) + .unwrap(); + + assert_eq!(expected, encrypted_value.unwrap().assert_bytes().to_vec()); + } + + #[test] + fn encrypt_value_bytes() { + let model_value = create_model_value(ValueType::Bytes, true, Cardinality::One); + let sk = GenericAesKey::from_bytes(&[rand::random(); 32]).ok(); + let randomizer_facade = &RandomizerFacade::from_core(rand_core::OsRng); + let iv = Iv::generate(randomizer_facade); + let value = ElementValue::Bytes(randomizer_facade.generate_random_array::<5>().to_vec()); + + let encrypted_value = EntityFacadeImpl::encrypt_value( + "test", + &model_value, + &value, + &sk, + IvProvider::Fixed(iv.clone()), + ); + + let expected = sk + .unwrap() + .encrypt_data(value.assert_bytes().as_slice(), iv) + .unwrap(); + + assert_eq!(expected, encrypted_value.unwrap().assert_bytes().to_vec()); + } + + #[test] + fn encrypt_value_null() { + let sk = GenericAesKey::from_bytes(&[rand::random(); 32]).ok(); + + assert_eq!( + ElementValue::Null, + EntityFacadeImpl::encrypt_value( + "test", + &create_model_value(ValueType::Bytes, true, Cardinality::ZeroOrOne), + &ElementValue::Null, + &sk, + IvProvider::Random, + ) + .unwrap() + ); + assert_eq!( + ElementValue::Null, + EntityFacadeImpl::encrypt_value( + "test", + &create_model_value(ValueType::Date, true, Cardinality::ZeroOrOne), + &ElementValue::Null, + &sk, + IvProvider::Random, + ) + .unwrap() + ); + assert_eq!( + ElementValue::Null, + EntityFacadeImpl::encrypt_value( + "test", + &create_model_value(ValueType::String, true, Cardinality::ZeroOrOne), + &ElementValue::Null, + &sk, + IvProvider::Random, + ) + .unwrap() + ); + assert_eq!( + ElementValue::Null, + EntityFacadeImpl::encrypt_value( + "test", + &create_model_value(ValueType::Boolean, true, Cardinality::ZeroOrOne), + &ElementValue::Null, + &sk, + IvProvider::Random, + ) + .unwrap() + ); + assert_eq!( + ElementValue::Null, + EntityFacadeImpl::encrypt_value( + "test", + &create_model_value(ValueType::Date, true, Cardinality::ZeroOrOne), + &ElementValue::Null, + &sk, + IvProvider::Random, + ) + .unwrap() + ); + assert_eq!( + ElementValue::Null, + EntityFacadeImpl::encrypt_value( + "test", + &create_model_value(ValueType::GeneratedId, true, Cardinality::ZeroOrOne), + &ElementValue::Null, + &sk, + IvProvider::Random, + ) + .unwrap() + ); + assert_eq!( + ElementValue::Null, + EntityFacadeImpl::encrypt_value( + "test", + &create_model_value(ValueType::CustomId, true, Cardinality::ZeroOrOne), + &ElementValue::Null, + &sk, + IvProvider::Random, + ) + .unwrap() + ); + assert_eq!( + ElementValue::Null, + EntityFacadeImpl::encrypt_value( + "test", + &create_model_value(ValueType::CompressedString, true, Cardinality::ZeroOrOne), + &ElementValue::Null, + &sk, + IvProvider::Random, + ) + .unwrap() + ); + assert_eq!( + ElementValue::Null, + EntityFacadeImpl::encrypt_value( + "test", + &create_model_value(ValueType::Number, true, Cardinality::ZeroOrOne), + &ElementValue::Null, + &sk, + IvProvider::Random, + ) + .unwrap() + ); + } + + #[test] + fn encrypt_value_accept_null_id_and_permission() { + let sk = GenericAesKey::from_bytes(&[rand::random(); 32]).ok(); + + assert_eq!( + ElementValue::Null, + EntityFacadeImpl::encrypt_value( + "_id", + &create_model_value(ValueType::GeneratedId, true, Cardinality::One), + &ElementValue::Null, + &sk, + IvProvider::Random, + ) + .unwrap() + ); + + assert_eq!( + ElementValue::Null, + EntityFacadeImpl::encrypt_value( + "_permissions", + &create_model_value(ValueType::CustomId, true, Cardinality::One), + &ElementValue::Null, + &sk, + IvProvider::Random, + ) + .unwrap() + ); + } + + #[test] + fn encrypt_value_do_not_accept_null() { + let sk = GenericAesKey::from_bytes(&[rand::random(); 32]).ok(); + + let value_types = [ + ValueType::Bytes, + ValueType::Boolean, + ValueType::CompressedString, + ValueType::String, + ValueType::Date, + ValueType::GeneratedId, + ValueType::Number, + ValueType::CustomId, + ]; + + for value_type in value_types { + assert_eq!( + Err(ApiCallError::internal( + "Value test with cardinality ONE can not be null".to_string() + )), + EntityFacadeImpl::encrypt_value( + "test", + &create_model_value(value_type, true, Cardinality::One), + &ElementValue::Null, + &sk, + IvProvider::Random, + ) + ); + } + } + + #[test] + fn encrypt_value_convert_unencrypted_date_to_db_type() { + let model_value = create_model_value(ValueType::Date, false, Cardinality::One); + let value = ElementValue::Date(DateTime::from_system_time(SystemTime::now())); + + let mapped_value = EntityFacadeImpl::encrypt_value( + "test", + &model_value, + &value, + &None, + IvProvider::Random, + ); + + assert_eq!(value, mapped_value.unwrap()); + } + + #[test] + fn encrypt_value_convert_unencrypted_bytes_to_db_type() { + let model_value = create_model_value(ValueType::Bytes, false, Cardinality::One); + let value = ElementValue::Bytes(b"test".to_vec()); + + let mapped_value = EntityFacadeImpl::encrypt_value( + "test", + &model_value, + &value, + &None, + IvProvider::Random, + ); + + assert_eq!(value, mapped_value.unwrap()); + } + + #[test] + fn encrypt_value_convert_unencrypted_boolean_to_db_type() { + let model_value = create_model_value(ValueType::Boolean, false, Cardinality::One); + + let true_value = ElementValue::Bool(true); + assert_eq!( + ElementValue::Bool(true), + EntityFacadeImpl::encrypt_value( + "test", + &model_value, + &true_value, + &None, + IvProvider::Random, + ) + .unwrap() + ); + + let false_value = ElementValue::Bool(false); + assert_eq!( + false_value, + EntityFacadeImpl::encrypt_value( + "test", + &model_value, + &false_value, + &None, + IvProvider::Random, + ) + .unwrap() + ); + } + + #[test] + fn encrypt_value_convert_unencrypted_string_to_db_type() { + let model_value = create_model_value(ValueType::String, false, Cardinality::One); + let randomizer_facade = &RandomizerFacade::from_core(rand_core::OsRng); + let value = ElementValue::String("hello".to_string()); + + let mapped_value = EntityFacadeImpl::encrypt_value( + "test", + &model_value, + &value, + &None, + IvProvider::Random, + ); + assert_eq!(value, mapped_value.unwrap()); + } + + #[test] + fn encrypt_value_convert_unencrypted_number_to_db_type() { + let model_value = create_model_value(ValueType::Number, false, Cardinality::One); + let randomizer_facade = &RandomizerFacade::from_core(rand_core::OsRng); + let value = ElementValue::Number(100); + + let mapped_value = EntityFacadeImpl::encrypt_value( + "test", + &model_value, + &value, + &None, + IvProvider::Random, + ); + assert_eq!(value, mapped_value.unwrap()); + } + + #[test] + fn encrypt_value_convert_unencrypted_compressed_string_to_db_type() { + let model_value = create_model_value(ValueType::CompressedString, false, Cardinality::One); + let randomizer_facade = &RandomizerFacade::from_core(rand_core::OsRng); + let value = ElementValue::String("tutanota".to_string()); + + let mapped_value = EntityFacadeImpl::encrypt_value( + "test", + &model_value, + &value, + &None, + IvProvider::Random, + ); + assert_eq!(value, mapped_value.unwrap()); + } + + #[test] + fn encrypt_instance() { + let sk = GenericAesKey::Aes256(Aes256Key::from_bytes(KNOWN_SK.as_slice()).unwrap()); + let owner_enc_session_key = [0, 1, 2]; + let iv = Iv::from_bytes(&rand::random::<[u8; 16]>()).unwrap(); + let type_model_provider = Arc::new(init_type_model_provider()); + + let json_serializer = JsonSerializer::new(type_model_provider.clone()); + let type_ref = Mail::type_ref(); + let type_model = type_model_provider + .get_type_model(type_ref.app, type_ref.type_) + .unwrap(); + + let entity_facade = EntityFacadeImpl::new(Arc::clone(&type_model_provider)); + + let (mut expected_encrypted_mail, raw_mail) = generate_email_entity( + &sk, + &iv, + true, + String::from("Hello, world!"), + String::from("Hanover"), + String::from("Munich"), + ); + + // remove finalIvs for easy comparision + { + expected_encrypted_mail + .remove(&"_finalIvs".to_string()) + .unwrap(); + expected_encrypted_mail + .get_mut("sender") + .unwrap() + .assert_dict_mut_ref() + .remove("_finalIvs") + .unwrap(); + expected_encrypted_mail + .get_mut("firstRecipient") + .unwrap() + .assert_dict_mut_ref() + .remove("_finalIvs") + .unwrap(); + } + + let mut encrypted_mail = entity_facade.encrypt_and_map_to_literal_with_iv( + type_model, + &raw_mail, + Some(sk.clone()), + IvProvider::Fixed(iv.clone()), + ); + + assert_eq!(Ok(expected_encrypted_mail), encrypted_mail); + + // verify every data is preserved as is after decryption + { + let mut original_mail = raw_mail; + let mut encrypted_mail = encrypted_mail.unwrap(); + let instance_mapper = InstanceMapper::new(); + + let mut decrypted_mail = entity_facade + .decrypt_and_map( + type_model, + encrypted_mail.clone(), + ResolvedSessionKey { + session_key: sk.clone(), + owner_enc_session_key: owner_enc_session_key.to_vec(), + }, + ) + .unwrap(); + + // compare all the _finalIvs are initialised with expectedIV + // for simplicity in comparison remove them as well( original_mail don't have _finalIvs ) + verify_final_ivs_and_clear(&iv, &mut decrypted_mail); + + assert_eq!( + Some(&ElementValue::Bytes(owner_enc_session_key.to_vec())), + decrypted_mail.get(&"_ownerEncSessionKey".to_string()), + ); + decrypted_mail.insert("_ownerEncSessionKey".to_string(), ElementValue::Null); + + assert_eq!( + Some(ElementValue::Dict(HashMap::new())), + decrypted_mail.remove("_errors") + ); + + // comparison with sorted fields. only for easy for debugging + assert_eq!( + map_to_string(&original_mail), + map_to_string(&decrypted_mail) + ); + assert_eq!(original_mail, decrypted_mail); + } + } + + #[test] + fn encrypt_unencrypted_to_db_literal() { + let type_model_provider = Arc::new(init_type_model_provider()); + let json_serializer = JsonSerializer::new(type_model_provider.clone()); + let entity_facade = EntityFacadeImpl::new(Arc::clone(&type_model_provider)); + let type_ref = CustomerAccountTerminationRequest::type_ref(); + let type_model = type_model_provider + .get_type_model(type_ref.app, type_ref.type_) + .unwrap(); + let sk = GenericAesKey::from_bytes(rand::random::<[u8; 32]>().as_slice()).unwrap(); + + let dummy_date = DateTime::from_system_time(SystemTime::now()); + let instance: RawEntity = collection! { + "_format" => JsonElement::String("0".to_string()), + "_id" => JsonElement::Array(vec![JsonElement::String("O1RT2Dj--3-0".to_string()); 2]), + "_ownerGroup" => JsonElement::Null, + "_permissions" => JsonElement::String("O2TT2Aj--2-1".to_string()), + "terminationDate" => JsonElement::String(dummy_date.as_millis().to_string()), + "terminationRequestDate" => JsonElement::String(dummy_date.as_millis().to_string()), + "customer" => JsonElement::String("customId".to_string()), + }; + let instance = json_serializer.parse(&type_ref, instance).unwrap(); + + let encrypted_instance = + entity_facade.encrypt_and_map_to_literal(&type_model, &instance, Some(sk.clone())); + + // unencrypted value should be kept as-is + assert_eq!(Ok(instance), encrypted_instance); + } + + #[test] + fn encryption_final_ivs_will_be_reused() { + let type_model_provider = Arc::new(init_type_model_provider()); + let json_serializer = JsonSerializer::new(type_model_provider.clone()); + let entity_facade = EntityFacadeImpl::new(Arc::clone(&type_model_provider)); + let type_ref = Mail::type_ref(); + let type_model = type_model_provider + .get_type_model(type_ref.app, type_ref.type_) + .unwrap(); + let sk = GenericAesKey::from_bytes(rand::random::<[u8; 32]>().as_slice()).unwrap(); + let original_iv = Iv::from_bytes(&rand::random::<[u8; 16]>()).unwrap(); + let new_iv = Iv::from_bytes(&rand::random::<[u8; 16]>()).unwrap(); + + // use two seperate iv + assert_ne!(original_iv.get_inner(), new_iv.get_inner()); + + let (mut encrypted_mail, mut unencrypted_mail) = generate_email_entity( + &sk, + &original_iv, + true, + String::from("Hello, world!"), + String::from("Hanover"), + String::from("Munich"), + ); + + // set separate finalIv for some field + let final_iv_for_subject = [( + "subject".to_string(), + ElementValue::Bytes(new_iv.get_inner().to_vec()), + )] + .into_iter() + .collect::>(); + + unencrypted_mail.insert( + "_finalIvs".to_string(), + ElementValue::Dict(final_iv_for_subject), + ); + + let mut encrypted_mail = entity_facade + .encrypt_and_map_to_literal_with_iv( + type_model, + &unencrypted_mail, + Some(sk.clone()), + IvProvider::Fixed(original_iv.clone()), + ) + .unwrap(); + + let encrypted_subject = encrypted_mail.get("subject").unwrap(); + let subject_and_iv = sk + .decrypt_data_and_iv(&encrypted_subject.assert_bytes()) + .unwrap(); + + assert_eq!( + Ok("Hello, world!".to_string()), + String::from_utf8(subject_and_iv.data) + ); + assert_eq!(new_iv.get_inner(), &subject_and_iv.iv); + + // other fields should be encrypted with origin_iv + let encrypted_recipient_name = encrypted_mail + .get("firstRecipient") + .unwrap() + .assert_dict() + .get("name") + .unwrap() + .assert_bytes(); + let recipient_and_iv = sk.decrypt_data_and_iv(&encrypted_recipient_name).unwrap(); + assert_eq!(original_iv.get_inner().to_vec(), recipient_and_iv.iv) + } + + #[test] + #[ignore = "todo: Right now we will anyway try to encrypt the default value even for final fields.\ + This is however not intended. We skip the implementation because we did not need it for service call?"] + fn empty_final_iv_and_default_value_should_be_preserved() { + let type_model_provider = Arc::new(init_type_model_provider()); + let json_serializer = JsonSerializer::new(type_model_provider.clone()); + let entity_facade = EntityFacadeImpl::new(Arc::clone(&type_model_provider)); + let type_ref = Mail::type_ref(); + let type_model = type_model_provider + .get_type_model(type_ref.app, type_ref.type_) + .unwrap(); + let sk = GenericAesKey::from_bytes(rand::random::<[u8; 32]>().as_slice()).unwrap(); + let iv = Iv::from_bytes(&rand::random::<[u8; 16]>()).unwrap(); + + let default_subject = String::from(""); + let (mut encrypted_mail, mut unencrypted_mail) = generate_email_entity( + &sk, + &iv, + true, + default_subject.clone(), + String::from("Hanover"), + String::from("Munich"), + ); + + let mut encrypted_mail = entity_facade + .encrypt_and_map_to_literal_with_iv( + type_model, + &unencrypted_mail, + Some(sk.clone()), + IvProvider::Fixed(iv.clone()), + ) + .unwrap(); + + let encrypted_subject = encrypted_mail.get("subject").unwrap().assert_bytes(); + assert_eq!(default_subject.as_bytes(), encrypted_subject.as_slice()); + } + + fn map_to_string(map: &HashMap) -> String { + let mut out = String::new(); + let sorted_map: BTreeMap = map.clone().into_iter().collect(); + for (key, value) in sorted_map.iter() { + match value { + ElementValue::Dict(aggregate) => { + out.push_str(&format!("{}: {}\n", key, map_to_string(aggregate))) + }, + _ => out.push_str(&format!("{}: {:?}\n", key, value)), + } + } + out + } + + fn verify_final_ivs_and_clear(iv: &Iv, instance: &mut ParsedEntity) { + for (name, value) in instance.iter_mut() { + match value { + ElementValue::Dict(value_map) if name == "_finalIvs" => { + for (_n, actual_iv) in value_map.iter() { + assert_eq!(iv.get_inner(), actual_iv.assert_bytes().as_slice()); + } + value_map.clear(); + }, + + ElementValue::Dict(value_map) => verify_final_ivs_and_clear(iv, value_map), + _ => {}, + } + } + } + fn make_json_entity() -> RawEntity { collection! { "sentDate"=> JsonElement::Null, @@ -592,4 +1506,18 @@ mod tests { ), "sets"=> JsonElement::Array(vec![]),} } + + fn create_model_value( + value_type: ValueType, + encrypted: bool, + cardinality: Cardinality, + ) -> ModelValue { + ModelValue { + id: 426, + value_type, + cardinality, + is_final: true, + encrypted, + } + } } diff --git a/tuta-sdk/rust/sdk/src/entities/mod.rs b/tuta-sdk/rust/sdk/src/entities/mod.rs index 1d6e17180250..fd9392988f2f 100644 --- a/tuta-sdk/rust/sdk/src/entities/mod.rs +++ b/tuta-sdk/rust/sdk/src/entities/mod.rs @@ -9,15 +9,15 @@ use crate::generated_id::GeneratedId; pub use crate::IdTuple; use crate::TypeRef; -pub(crate) mod accounting; -pub(crate) mod base; -pub(crate) mod entity_facade; -pub(crate) mod gossip; -pub(crate) mod monitor; -pub(crate) mod storage; -pub(crate) mod sys; -pub(crate) mod tutanota; -pub(crate) mod usage; +pub mod accounting; +pub mod base; +pub mod entity_facade; +pub mod gossip; +pub mod monitor; +pub mod storage; +pub mod sys; +pub mod tutanota; +pub mod usage; /// `'static` on trait bound is fine here because Entity does not contain any non-static references. /// See https://doc.rust-lang.org/rust-by-example/scope/lifetime/static_lifetime.html#trait-bound @@ -30,7 +30,7 @@ pub trait Entity: 'static { /// to the same exact value. For that we need to use the same initialization /// vector. /// FinalIv holds such an IV for a specific field. -#[derive(Clone, Serialize, Deserialize, Debug)] +#[derive(Clone, Serialize, Deserialize, Debug, PartialEq)] #[serde(transparent)] pub struct FinalIv(#[serde(with = "serde_bytes")] Vec); diff --git a/tuta-sdk/rust/sdk/src/entities/monitor.rs b/tuta-sdk/rust/sdk/src/entities/monitor.rs index bdb789086b51..fcb946d0ad9a 100644 --- a/tuta-sdk/rust/sdk/src/entities/monitor.rs +++ b/tuta-sdk/rust/sdk/src/entities/monitor.rs @@ -2,7 +2,7 @@ use super::*; use serde::{Deserialize, Serialize}; -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct ApprovalMail { pub _format: i64, pub _id: IdTuple, @@ -13,7 +13,6 @@ pub struct ApprovalMail { pub text: String, pub customer: Option, } - impl Entity for ApprovalMail { fn type_ref() -> TypeRef { TypeRef { @@ -23,13 +22,15 @@ impl Entity for ApprovalMail { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct CounterValue { pub _id: CustomId, pub counterId: GeneratedId, pub value: i64, } - impl Entity for CounterValue { fn type_ref() -> TypeRef { TypeRef { @@ -39,7 +40,10 @@ impl Entity for CounterValue { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct ErrorReportData { pub _id: CustomId, pub additionalInfo: String, @@ -52,7 +56,6 @@ pub struct ErrorReportData { pub userId: Option, pub userMessage: Option, } - impl Entity for ErrorReportData { fn type_ref() -> TypeRef { TypeRef { @@ -62,13 +65,15 @@ impl Entity for ErrorReportData { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct ErrorReportFile { pub _id: CustomId, pub content: String, pub name: String, } - impl Entity for ErrorReportFile { fn type_ref() -> TypeRef { TypeRef { @@ -78,14 +83,16 @@ impl Entity for ErrorReportFile { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct ReadCounterData { pub _format: i64, pub columnName: Option, pub counterType: i64, pub rowName: String, } - impl Entity for ReadCounterData { fn type_ref() -> TypeRef { TypeRef { @@ -95,13 +102,15 @@ impl Entity for ReadCounterData { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct ReadCounterReturn { pub _format: i64, pub value: Option, pub counterValues: Vec, } - impl Entity for ReadCounterReturn { fn type_ref() -> TypeRef { TypeRef { @@ -111,13 +120,15 @@ impl Entity for ReadCounterReturn { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct ReportErrorIn { pub _format: i64, pub data: ErrorReportData, pub files: Vec, } - impl Entity for ReportErrorIn { fn type_ref() -> TypeRef { TypeRef { @@ -127,7 +138,10 @@ impl Entity for ReportErrorIn { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct WriteCounterData { pub _format: i64, pub column: GeneratedId, @@ -135,7 +149,6 @@ pub struct WriteCounterData { pub row: String, pub value: i64, } - impl Entity for WriteCounterData { fn type_ref() -> TypeRef { TypeRef { @@ -144,3 +157,6 @@ impl Entity for WriteCounterData { } } } + + + diff --git a/tuta-sdk/rust/sdk/src/entities/storage.rs b/tuta-sdk/rust/sdk/src/entities/storage.rs index 718a2295cd78..358d4020042d 100644 --- a/tuta-sdk/rust/sdk/src/entities/storage.rs +++ b/tuta-sdk/rust/sdk/src/entities/storage.rs @@ -2,14 +2,13 @@ use super::*; use serde::{Deserialize, Serialize}; -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct BlobAccessTokenPostIn { pub _format: i64, pub archiveDataType: Option, pub read: Option, pub write: Option, } - impl Entity for BlobAccessTokenPostIn { fn type_ref() -> TypeRef { TypeRef { @@ -19,12 +18,14 @@ impl Entity for BlobAccessTokenPostIn { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct BlobAccessTokenPostOut { pub _format: i64, pub blobAccessInfo: BlobServerAccessInfo, } - impl Entity for BlobAccessTokenPostOut { fn type_ref() -> TypeRef { TypeRef { @@ -34,7 +35,10 @@ impl Entity for BlobAccessTokenPostOut { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct BlobArchiveRef { pub _format: i64, pub _id: IdTuple, @@ -42,7 +46,6 @@ pub struct BlobArchiveRef { pub _permissions: GeneratedId, pub archive: GeneratedId, } - impl Entity for BlobArchiveRef { fn type_ref() -> TypeRef { TypeRef { @@ -52,14 +55,16 @@ impl Entity for BlobArchiveRef { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct BlobGetIn { pub _format: i64, pub archiveId: GeneratedId, pub blobId: Option, pub blobIds: Vec, } - impl Entity for BlobGetIn { fn type_ref() -> TypeRef { TypeRef { @@ -69,12 +74,14 @@ impl Entity for BlobGetIn { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct BlobId { pub _id: CustomId, pub blobId: GeneratedId, } - impl Entity for BlobId { fn type_ref() -> TypeRef { TypeRef { @@ -84,12 +91,14 @@ impl Entity for BlobId { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct BlobPostOut { pub _format: i64, pub blobReferenceToken: String, } - impl Entity for BlobPostOut { fn type_ref() -> TypeRef { TypeRef { @@ -99,14 +108,16 @@ impl Entity for BlobPostOut { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct BlobReadData { pub _id: CustomId, pub archiveId: GeneratedId, pub instanceListId: Option, pub instanceIds: Vec, } - impl Entity for BlobReadData { fn type_ref() -> TypeRef { TypeRef { @@ -116,7 +127,10 @@ impl Entity for BlobReadData { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct BlobReferenceDeleteIn { pub _format: i64, pub archiveDataType: i64, @@ -124,7 +138,6 @@ pub struct BlobReferenceDeleteIn { pub instanceListId: Option, pub blobs: Vec, } - impl Entity for BlobReferenceDeleteIn { fn type_ref() -> TypeRef { TypeRef { @@ -134,7 +147,10 @@ impl Entity for BlobReferenceDeleteIn { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct BlobReferencePutIn { pub _format: i64, pub archiveDataType: i64, @@ -142,7 +158,6 @@ pub struct BlobReferencePutIn { pub instanceListId: Option, pub referenceTokens: Vec, } - impl Entity for BlobReferencePutIn { fn type_ref() -> TypeRef { TypeRef { @@ -152,14 +167,16 @@ impl Entity for BlobReferencePutIn { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct BlobServerAccessInfo { pub _id: CustomId, pub blobAccessToken: String, pub expires: DateTime, pub servers: Vec, } - impl Entity for BlobServerAccessInfo { fn type_ref() -> TypeRef { TypeRef { @@ -169,12 +186,14 @@ impl Entity for BlobServerAccessInfo { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct BlobServerUrl { pub _id: CustomId, pub url: String, } - impl Entity for BlobServerUrl { fn type_ref() -> TypeRef { TypeRef { @@ -184,12 +203,14 @@ impl Entity for BlobServerUrl { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct BlobWriteData { pub _id: CustomId, pub archiveOwnerGroup: GeneratedId, } - impl Entity for BlobWriteData { fn type_ref() -> TypeRef { TypeRef { @@ -199,12 +220,14 @@ impl Entity for BlobWriteData { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct InstanceId { pub _id: CustomId, pub instanceId: Option, } - impl Entity for InstanceId { fn type_ref() -> TypeRef { TypeRef { @@ -213,3 +236,6 @@ impl Entity for InstanceId { } } } + + + diff --git a/tuta-sdk/rust/sdk/src/entities/sys.rs b/tuta-sdk/rust/sdk/src/entities/sys.rs index aa37018a7564..e125ad7a01fd 100644 --- a/tuta-sdk/rust/sdk/src/entities/sys.rs +++ b/tuta-sdk/rust/sdk/src/entities/sys.rs @@ -2,7 +2,7 @@ use super::*; use serde::{Deserialize, Serialize}; -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct AccountingInfo { pub _format: i64, pub _id: GeneratedId, @@ -30,7 +30,6 @@ pub struct AccountingInfo { pub _errors: Option, pub _finalIvs: HashMap, } - impl Entity for AccountingInfo { fn type_ref() -> TypeRef { TypeRef { @@ -40,7 +39,10 @@ impl Entity for AccountingInfo { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct AdminGroupKeyAuthenticationData { pub _id: CustomId, #[serde(with = "serde_bytes")] @@ -48,7 +50,6 @@ pub struct AdminGroupKeyAuthenticationData { pub version: i64, pub userGroup: GeneratedId, } - impl Entity for AdminGroupKeyAuthenticationData { fn type_ref() -> TypeRef { TypeRef { @@ -58,14 +59,16 @@ impl Entity for AdminGroupKeyAuthenticationData { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct AdminGroupKeyRotationPostIn { pub _format: i64, pub adminGroupKeyAuthenticationDataList: Vec, pub adminGroupKeyData: GroupKeyRotationData, pub userGroupKeyData: UserGroupKeyRotationData, } - impl Entity for AdminGroupKeyRotationPostIn { fn type_ref() -> TypeRef { TypeRef { @@ -75,12 +78,14 @@ impl Entity for AdminGroupKeyRotationPostIn { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct AdministratedGroupsRef { pub _id: CustomId, pub items: GeneratedId, } - impl Entity for AdministratedGroupsRef { fn type_ref() -> TypeRef { TypeRef { @@ -90,7 +95,10 @@ impl Entity for AdministratedGroupsRef { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct AffiliatePartnerKpiMonthSummary { pub _id: CustomId, pub commission: i64, @@ -100,7 +108,6 @@ pub struct AffiliatePartnerKpiMonthSummary { pub totalFree: i64, pub totalPaid: i64, } - impl Entity for AffiliatePartnerKpiMonthSummary { fn type_ref() -> TypeRef { TypeRef { @@ -110,7 +117,10 @@ impl Entity for AffiliatePartnerKpiMonthSummary { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct AffiliatePartnerKpiServiceGetOut { pub _format: i64, pub accumulatedCommission: i64, @@ -118,7 +128,6 @@ pub struct AffiliatePartnerKpiServiceGetOut { pub promotionId: String, pub kpis: Vec, } - impl Entity for AffiliatePartnerKpiServiceGetOut { fn type_ref() -> TypeRef { TypeRef { @@ -128,7 +137,10 @@ impl Entity for AffiliatePartnerKpiServiceGetOut { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct AlarmInfo { pub _id: CustomId, pub alarmIdentifier: String, @@ -136,7 +148,6 @@ pub struct AlarmInfo { pub calendarRef: CalendarEventRef, pub _finalIvs: HashMap, } - impl Entity for AlarmInfo { fn type_ref() -> TypeRef { TypeRef { @@ -146,7 +157,10 @@ impl Entity for AlarmInfo { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct AlarmNotification { pub _id: CustomId, pub eventEnd: DateTime, @@ -159,7 +173,6 @@ pub struct AlarmNotification { pub user: GeneratedId, pub _finalIvs: HashMap, } - impl Entity for AlarmNotification { fn type_ref() -> TypeRef { TypeRef { @@ -169,14 +182,16 @@ impl Entity for AlarmNotification { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct AlarmServicePost { pub _format: i64, pub alarmNotifications: Vec, pub _errors: Option, pub _finalIvs: HashMap, } - impl Entity for AlarmServicePost { fn type_ref() -> TypeRef { TypeRef { @@ -186,12 +201,14 @@ impl Entity for AlarmServicePost { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct ArchiveRef { pub _id: CustomId, pub archiveId: GeneratedId, } - impl Entity for ArchiveRef { fn type_ref() -> TypeRef { TypeRef { @@ -201,7 +218,10 @@ impl Entity for ArchiveRef { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct ArchiveType { pub _id: CustomId, pub active: ArchiveRef, @@ -209,7 +229,6 @@ pub struct ArchiveType { #[serde(rename = "type")] pub r#type: TypeInfo, } - impl Entity for ArchiveType { fn type_ref() -> TypeRef { TypeRef { @@ -219,7 +238,10 @@ impl Entity for ArchiveType { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct AuditLogEntry { pub _format: i64, pub _id: IdTuple, @@ -238,7 +260,6 @@ pub struct AuditLogEntry { pub _errors: Option, pub _finalIvs: HashMap, } - impl Entity for AuditLogEntry { fn type_ref() -> TypeRef { TypeRef { @@ -248,12 +269,14 @@ impl Entity for AuditLogEntry { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct AuditLogRef { pub _id: CustomId, pub items: GeneratedId, } - impl Entity for AuditLogRef { fn type_ref() -> TypeRef { TypeRef { @@ -263,7 +286,10 @@ impl Entity for AuditLogRef { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct AuthenticatedDevice { pub _id: CustomId, pub authType: i64, @@ -271,7 +297,6 @@ pub struct AuthenticatedDevice { pub deviceKey: Vec, pub deviceToken: String, } - impl Entity for AuthenticatedDevice { fn type_ref() -> TypeRef { TypeRef { @@ -281,7 +306,10 @@ impl Entity for AuthenticatedDevice { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct Authentication { pub _id: CustomId, pub accessToken: Option, @@ -289,7 +317,6 @@ pub struct Authentication { pub externalAuthToken: Option, pub userId: GeneratedId, } - impl Entity for Authentication { fn type_ref() -> TypeRef { TypeRef { @@ -299,12 +326,14 @@ impl Entity for Authentication { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct AutoLoginDataDelete { pub _format: i64, pub deviceToken: String, } - impl Entity for AutoLoginDataDelete { fn type_ref() -> TypeRef { TypeRef { @@ -314,13 +343,15 @@ impl Entity for AutoLoginDataDelete { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct AutoLoginDataGet { pub _format: i64, pub deviceToken: String, pub userId: GeneratedId, } - impl Entity for AutoLoginDataGet { fn type_ref() -> TypeRef { TypeRef { @@ -330,13 +361,15 @@ impl Entity for AutoLoginDataGet { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct AutoLoginDataReturn { pub _format: i64, #[serde(with = "serde_bytes")] pub deviceKey: Vec, } - impl Entity for AutoLoginDataReturn { fn type_ref() -> TypeRef { TypeRef { @@ -346,12 +379,14 @@ impl Entity for AutoLoginDataReturn { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct AutoLoginPostReturn { pub _format: i64, pub deviceToken: String, } - impl Entity for AutoLoginPostReturn { fn type_ref() -> TypeRef { TypeRef { @@ -361,14 +396,16 @@ impl Entity for AutoLoginPostReturn { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct Blob { pub _id: CustomId, pub archiveId: GeneratedId, pub blobId: GeneratedId, pub size: i64, } - impl Entity for Blob { fn type_ref() -> TypeRef { TypeRef { @@ -378,12 +415,14 @@ impl Entity for Blob { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct BlobReferenceTokenWrapper { pub _id: CustomId, pub blobReferenceToken: String, } - impl Entity for BlobReferenceTokenWrapper { fn type_ref() -> TypeRef { TypeRef { @@ -393,7 +432,10 @@ impl Entity for BlobReferenceTokenWrapper { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct Booking { pub _area: i64, pub _format: i64, @@ -408,7 +450,6 @@ pub struct Booking { pub paymentMonths: i64, pub items: Vec, } - impl Entity for Booking { fn type_ref() -> TypeRef { TypeRef { @@ -418,7 +459,10 @@ impl Entity for Booking { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct BookingItem { pub _id: CustomId, pub currentCount: i64, @@ -429,7 +473,6 @@ pub struct BookingItem { pub priceType: i64, pub totalInvoicedCount: i64, } - impl Entity for BookingItem { fn type_ref() -> TypeRef { TypeRef { @@ -439,12 +482,14 @@ impl Entity for BookingItem { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct BookingsRef { pub _id: CustomId, pub items: GeneratedId, } - impl Entity for BookingsRef { fn type_ref() -> TypeRef { TypeRef { @@ -454,12 +499,14 @@ impl Entity for BookingsRef { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct BootstrapFeature { pub _id: CustomId, pub feature: i64, } - impl Entity for BootstrapFeature { fn type_ref() -> TypeRef { TypeRef { @@ -469,14 +516,16 @@ impl Entity for BootstrapFeature { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct Braintree3ds2Request { pub _id: CustomId, pub bin: String, pub clientToken: String, pub nonce: String, } - impl Entity for Braintree3ds2Request { fn type_ref() -> TypeRef { TypeRef { @@ -486,13 +535,15 @@ impl Entity for Braintree3ds2Request { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct Braintree3ds2Response { pub _id: CustomId, pub clientToken: String, pub nonce: String, } - impl Entity for Braintree3ds2Response { fn type_ref() -> TypeRef { TypeRef { @@ -502,7 +553,10 @@ impl Entity for Braintree3ds2Response { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct BrandingDomainData { pub _format: i64, pub domain: String, @@ -515,7 +569,6 @@ pub struct BrandingDomainData { pub systemAdminPubKeyVersion: i64, pub systemAdminPublicProtocolVersion: i64, } - impl Entity for BrandingDomainData { fn type_ref() -> TypeRef { TypeRef { @@ -525,12 +578,14 @@ impl Entity for BrandingDomainData { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct BrandingDomainDeleteData { pub _format: i64, pub domain: String, } - impl Entity for BrandingDomainDeleteData { fn type_ref() -> TypeRef { TypeRef { @@ -540,12 +595,14 @@ impl Entity for BrandingDomainDeleteData { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct BrandingDomainGetReturn { pub _format: i64, pub certificateInfo: Option, } - impl Entity for BrandingDomainGetReturn { fn type_ref() -> TypeRef { TypeRef { @@ -555,12 +612,14 @@ impl Entity for BrandingDomainGetReturn { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct Bucket { pub _id: CustomId, pub bucketPermissions: GeneratedId, } - impl Entity for Bucket { fn type_ref() -> TypeRef { TypeRef { @@ -570,7 +629,10 @@ impl Entity for Bucket { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct BucketKey { pub _id: CustomId, #[serde(with = "serde_bytes")] @@ -583,7 +645,6 @@ pub struct BucketKey { pub bucketEncSessionKeys: Vec, pub keyGroup: Option, } - impl Entity for BucketKey { fn type_ref() -> TypeRef { TypeRef { @@ -593,7 +654,10 @@ impl Entity for BucketKey { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct BucketPermission { pub _format: i64, pub _id: IdTuple, @@ -614,7 +678,6 @@ pub struct BucketPermission { pub r#type: i64, pub group: GeneratedId, } - impl Entity for BucketPermission { fn type_ref() -> TypeRef { TypeRef { @@ -624,13 +687,15 @@ impl Entity for BucketPermission { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct CalendarEventRef { pub _id: CustomId, pub elementId: CustomId, pub listId: GeneratedId, } - impl Entity for CalendarEventRef { fn type_ref() -> TypeRef { TypeRef { @@ -640,7 +705,10 @@ impl Entity for CalendarEventRef { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct CertificateInfo { pub _id: CustomId, pub expiryDate: Option, @@ -649,7 +717,6 @@ pub struct CertificateInfo { pub r#type: i64, pub certificate: Option, } - impl Entity for CertificateInfo { fn type_ref() -> TypeRef { TypeRef { @@ -659,7 +726,10 @@ impl Entity for CertificateInfo { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct Challenge { pub _id: CustomId, #[serde(rename = "type")] @@ -667,7 +737,6 @@ pub struct Challenge { pub otp: Option, pub u2f: Option, } - impl Entity for Challenge { fn type_ref() -> TypeRef { TypeRef { @@ -677,7 +746,10 @@ impl Entity for Challenge { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct ChangeKdfPostIn { pub _format: i64, pub kdfVersion: i64, @@ -691,7 +763,6 @@ pub struct ChangeKdfPostIn { #[serde(with = "serde_bytes")] pub verifier: Vec, } - impl Entity for ChangeKdfPostIn { fn type_ref() -> TypeRef { TypeRef { @@ -701,7 +772,10 @@ impl Entity for ChangeKdfPostIn { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct ChangePasswordPostIn { pub _format: i64, pub code: Option, @@ -718,7 +792,6 @@ pub struct ChangePasswordPostIn { #[serde(with = "serde_bytes")] pub verifier: Vec, } - impl Entity for ChangePasswordPostIn { fn type_ref() -> TypeRef { TypeRef { @@ -728,14 +801,16 @@ impl Entity for ChangePasswordPostIn { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct Chat { pub _id: CustomId, pub recipient: GeneratedId, pub sender: GeneratedId, pub text: String, } - impl Entity for Chat { fn type_ref() -> TypeRef { TypeRef { @@ -745,13 +820,15 @@ impl Entity for Chat { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct CloseSessionServicePost { pub _format: i64, pub accessToken: String, pub sessionId: IdTuple, } - impl Entity for CloseSessionServicePost { fn type_ref() -> TypeRef { TypeRef { @@ -761,14 +838,16 @@ impl Entity for CloseSessionServicePost { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct CreateCustomerServerPropertiesData { pub _format: i64, #[serde(with = "serde_bytes")] pub adminGroupEncSessionKey: Vec, pub adminGroupKeyVersion: i64, } - impl Entity for CreateCustomerServerPropertiesData { fn type_ref() -> TypeRef { TypeRef { @@ -778,12 +857,14 @@ impl Entity for CreateCustomerServerPropertiesData { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct CreateCustomerServerPropertiesReturn { pub _format: i64, pub id: GeneratedId, } - impl Entity for CreateCustomerServerPropertiesReturn { fn type_ref() -> TypeRef { TypeRef { @@ -793,7 +874,10 @@ impl Entity for CreateCustomerServerPropertiesReturn { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct CreateSessionData { pub _format: i64, #[serde(with = "serde_bytes")] @@ -805,7 +889,6 @@ pub struct CreateSessionData { pub recoverCodeVerifier: Option, pub user: Option, } - impl Entity for CreateSessionData { fn type_ref() -> TypeRef { TypeRef { @@ -815,14 +898,16 @@ impl Entity for CreateSessionData { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct CreateSessionReturn { pub _format: i64, pub accessToken: String, pub challenges: Vec, pub user: GeneratedId, } - impl Entity for CreateSessionReturn { fn type_ref() -> TypeRef { TypeRef { @@ -832,7 +917,10 @@ impl Entity for CreateSessionReturn { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct CreditCard { pub _id: CustomId, pub cardHolderName: String, @@ -842,7 +930,6 @@ pub struct CreditCard { pub number: String, pub _finalIvs: HashMap, } - impl Entity for CreditCard { fn type_ref() -> TypeRef { TypeRef { @@ -852,13 +939,15 @@ impl Entity for CreditCard { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct CustomDomainCheckGetIn { pub _format: i64, pub domain: String, pub customer: Option, } - impl Entity for CustomDomainCheckGetIn { fn type_ref() -> TypeRef { TypeRef { @@ -868,7 +957,10 @@ impl Entity for CustomDomainCheckGetIn { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct CustomDomainCheckGetOut { pub _format: i64, pub checkResult: i64, @@ -876,7 +968,6 @@ pub struct CustomDomainCheckGetOut { pub missingRecords: Vec, pub requiredRecords: Vec, } - impl Entity for CustomDomainCheckGetOut { fn type_ref() -> TypeRef { TypeRef { @@ -886,13 +977,15 @@ impl Entity for CustomDomainCheckGetOut { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct CustomDomainData { pub _format: i64, pub domain: String, pub catchAllMailGroup: Option, } - impl Entity for CustomDomainData { fn type_ref() -> TypeRef { TypeRef { @@ -902,13 +995,15 @@ impl Entity for CustomDomainData { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct CustomDomainReturn { pub _format: i64, pub validationResult: i64, pub invalidDnsRecords: Vec, } - impl Entity for CustomDomainReturn { fn type_ref() -> TypeRef { TypeRef { @@ -918,7 +1013,10 @@ impl Entity for CustomDomainReturn { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct Customer { pub _format: i64, pub _id: GeneratedId, @@ -947,7 +1045,6 @@ pub struct Customer { pub whitelabelChildren: Option, pub whitelabelParent: Option, } - impl Entity for Customer { fn type_ref() -> TypeRef { TypeRef { @@ -957,13 +1054,15 @@ impl Entity for Customer { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct CustomerAccountTerminationPostIn { pub _format: i64, pub terminationDate: Option, pub surveyData: Option, } - impl Entity for CustomerAccountTerminationPostIn { fn type_ref() -> TypeRef { TypeRef { @@ -973,12 +1072,14 @@ impl Entity for CustomerAccountTerminationPostIn { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct CustomerAccountTerminationPostOut { pub _format: i64, pub terminationRequest: IdTuple, } - impl Entity for CustomerAccountTerminationPostOut { fn type_ref() -> TypeRef { TypeRef { @@ -988,7 +1089,10 @@ impl Entity for CustomerAccountTerminationPostOut { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct CustomerAccountTerminationRequest { pub _format: i64, pub _id: IdTuple, @@ -998,7 +1102,6 @@ pub struct CustomerAccountTerminationRequest { pub terminationRequestDate: DateTime, pub customer: GeneratedId, } - impl Entity for CustomerAccountTerminationRequest { fn type_ref() -> TypeRef { TypeRef { @@ -1008,7 +1111,10 @@ impl Entity for CustomerAccountTerminationRequest { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct CustomerInfo { pub _format: i64, pub _id: IdTuple, @@ -1043,7 +1149,6 @@ pub struct CustomerInfo { pub takeoverCustomer: Option, pub terminationRequest: Option, } - impl Entity for CustomerInfo { fn type_ref() -> TypeRef { TypeRef { @@ -1053,7 +1158,10 @@ impl Entity for CustomerInfo { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct CustomerProperties { pub _format: i64, pub _id: GeneratedId, @@ -1066,7 +1174,6 @@ pub struct CustomerProperties { pub notificationMailTemplates: Vec, pub smallLogo: Option, } - impl Entity for CustomerProperties { fn type_ref() -> TypeRef { TypeRef { @@ -1076,7 +1183,10 @@ impl Entity for CustomerProperties { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct CustomerServerProperties { pub _format: i64, pub _id: GeneratedId, @@ -1094,7 +1204,6 @@ pub struct CustomerServerProperties { pub _errors: Option, pub _finalIvs: HashMap, } - impl Entity for CustomerServerProperties { fn type_ref() -> TypeRef { TypeRef { @@ -1104,13 +1213,15 @@ impl Entity for CustomerServerProperties { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct DateWrapper { pub _id: CustomId, pub date: DateTime, pub _finalIvs: HashMap, } - impl Entity for DateWrapper { fn type_ref() -> TypeRef { TypeRef { @@ -1120,12 +1231,14 @@ impl Entity for DateWrapper { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct DebitServicePutData { pub _format: i64, pub invoice: Option, } - impl Entity for DebitServicePutData { fn type_ref() -> TypeRef { TypeRef { @@ -1135,7 +1248,10 @@ impl Entity for DebitServicePutData { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct DeleteCustomerData { pub _format: i64, #[serde(with = "serde_bytes")] @@ -1146,7 +1262,6 @@ pub struct DeleteCustomerData { pub customer: GeneratedId, pub surveyData: Option, } - impl Entity for DeleteCustomerData { fn type_ref() -> TypeRef { TypeRef { @@ -1156,7 +1271,10 @@ impl Entity for DeleteCustomerData { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct DnsRecord { pub _id: CustomId, pub subdomain: Option, @@ -1164,7 +1282,6 @@ pub struct DnsRecord { pub r#type: i64, pub value: String, } - impl Entity for DnsRecord { fn type_ref() -> TypeRef { TypeRef { @@ -1174,7 +1291,10 @@ impl Entity for DnsRecord { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct DomainInfo { pub _id: CustomId, pub domain: String, @@ -1182,7 +1302,6 @@ pub struct DomainInfo { pub catchAllMailGroup: Option, pub whitelabelConfig: Option, } - impl Entity for DomainInfo { fn type_ref() -> TypeRef { TypeRef { @@ -1192,12 +1311,14 @@ impl Entity for DomainInfo { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct DomainMailAddressAvailabilityData { pub _format: i64, pub mailAddress: String, } - impl Entity for DomainMailAddressAvailabilityData { fn type_ref() -> TypeRef { TypeRef { @@ -1207,12 +1328,14 @@ impl Entity for DomainMailAddressAvailabilityData { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct DomainMailAddressAvailabilityReturn { pub _format: i64, pub available: bool, } - impl Entity for DomainMailAddressAvailabilityReturn { fn type_ref() -> TypeRef { TypeRef { @@ -1222,12 +1345,14 @@ impl Entity for DomainMailAddressAvailabilityReturn { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct DomainsRef { pub _id: CustomId, pub items: GeneratedId, } - impl Entity for DomainsRef { fn type_ref() -> TypeRef { TypeRef { @@ -1237,7 +1362,10 @@ impl Entity for DomainsRef { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct EmailSenderListElement { pub _id: CustomId, pub field: i64, @@ -1247,7 +1375,6 @@ pub struct EmailSenderListElement { pub value: String, pub _finalIvs: HashMap, } - impl Entity for EmailSenderListElement { fn type_ref() -> TypeRef { TypeRef { @@ -1257,7 +1384,10 @@ impl Entity for EmailSenderListElement { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct EntityEventBatch { pub _format: i64, pub _id: IdTuple, @@ -1265,7 +1395,6 @@ pub struct EntityEventBatch { pub _permissions: GeneratedId, pub events: Vec, } - impl Entity for EntityEventBatch { fn type_ref() -> TypeRef { TypeRef { @@ -1275,7 +1404,10 @@ impl Entity for EntityEventBatch { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct EntityUpdate { pub _id: CustomId, pub application: String, @@ -1285,7 +1417,6 @@ pub struct EntityUpdate { #[serde(rename = "type")] pub r#type: String, } - impl Entity for EntityUpdate { fn type_ref() -> TypeRef { TypeRef { @@ -1295,14 +1426,16 @@ impl Entity for EntityUpdate { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct SysException { pub _id: CustomId, pub msg: String, #[serde(rename = "type")] pub r#type: String, } - impl Entity for SysException { fn type_ref() -> TypeRef { TypeRef { @@ -1312,7 +1445,10 @@ impl Entity for SysException { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct ExternalPropertiesReturn { pub _format: i64, pub accountType: i64, @@ -1320,7 +1456,6 @@ pub struct ExternalPropertiesReturn { pub bigLogo: Option, pub smallLogo: Option, } - impl Entity for ExternalPropertiesReturn { fn type_ref() -> TypeRef { TypeRef { @@ -1330,7 +1465,10 @@ impl Entity for ExternalPropertiesReturn { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct ExternalUserReference { pub _format: i64, pub _id: IdTuple, @@ -1339,7 +1477,6 @@ pub struct ExternalUserReference { pub user: GeneratedId, pub userGroup: GeneratedId, } - impl Entity for ExternalUserReference { fn type_ref() -> TypeRef { TypeRef { @@ -1349,12 +1486,14 @@ impl Entity for ExternalUserReference { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct Feature { pub _id: CustomId, pub feature: i64, } - impl Entity for Feature { fn type_ref() -> TypeRef { TypeRef { @@ -1364,7 +1503,10 @@ impl Entity for Feature { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct File { pub _id: CustomId, #[serde(with = "serde_bytes")] @@ -1372,7 +1514,6 @@ pub struct File { pub mimeType: String, pub name: String, } - impl Entity for File { fn type_ref() -> TypeRef { TypeRef { @@ -1382,12 +1523,14 @@ impl Entity for File { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct GeneratedIdWrapper { pub _id: CustomId, pub value: GeneratedId, } - impl Entity for GeneratedIdWrapper { fn type_ref() -> TypeRef { TypeRef { @@ -1397,7 +1540,10 @@ impl Entity for GeneratedIdWrapper { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct GiftCard { pub _format: i64, pub _id: IdTuple, @@ -1414,7 +1560,6 @@ pub struct GiftCard { pub _errors: Option, pub _finalIvs: HashMap, } - impl Entity for GiftCard { fn type_ref() -> TypeRef { TypeRef { @@ -1424,7 +1569,10 @@ impl Entity for GiftCard { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct GiftCardCreateData { pub _format: i64, #[serde(with = "serde_bytes")] @@ -1437,7 +1585,6 @@ pub struct GiftCardCreateData { pub _errors: Option, pub _finalIvs: HashMap, } - impl Entity for GiftCardCreateData { fn type_ref() -> TypeRef { TypeRef { @@ -1447,12 +1594,14 @@ impl Entity for GiftCardCreateData { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct GiftCardCreateReturn { pub _format: i64, pub giftCard: IdTuple, } - impl Entity for GiftCardCreateReturn { fn type_ref() -> TypeRef { TypeRef { @@ -1462,12 +1611,14 @@ impl Entity for GiftCardCreateReturn { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct GiftCardDeleteData { pub _format: i64, pub giftCard: IdTuple, } - impl Entity for GiftCardDeleteData { fn type_ref() -> TypeRef { TypeRef { @@ -1477,14 +1628,16 @@ impl Entity for GiftCardDeleteData { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct GiftCardGetReturn { pub _format: i64, pub maxPerPeriod: i64, pub period: i64, pub options: Vec, } - impl Entity for GiftCardGetReturn { fn type_ref() -> TypeRef { TypeRef { @@ -1494,12 +1647,14 @@ impl Entity for GiftCardGetReturn { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct GiftCardOption { pub _id: CustomId, pub value: i64, } - impl Entity for GiftCardOption { fn type_ref() -> TypeRef { TypeRef { @@ -1509,7 +1664,10 @@ impl Entity for GiftCardOption { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct GiftCardRedeemData { pub _format: i64, pub countryCode: String, @@ -1517,7 +1675,6 @@ pub struct GiftCardRedeemData { pub keyHash: Vec, pub giftCardInfo: GeneratedId, } - impl Entity for GiftCardRedeemData { fn type_ref() -> TypeRef { TypeRef { @@ -1527,7 +1684,10 @@ impl Entity for GiftCardRedeemData { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct GiftCardRedeemGetReturn { pub _format: i64, pub message: String, @@ -1536,7 +1696,6 @@ pub struct GiftCardRedeemGetReturn { pub _errors: Option, pub _finalIvs: HashMap, } - impl Entity for GiftCardRedeemGetReturn { fn type_ref() -> TypeRef { TypeRef { @@ -1546,12 +1705,14 @@ impl Entity for GiftCardRedeemGetReturn { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct GiftCardsRef { pub _id: CustomId, pub items: GeneratedId, } - impl Entity for GiftCardsRef { fn type_ref() -> TypeRef { TypeRef { @@ -1561,7 +1722,10 @@ impl Entity for GiftCardsRef { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct Group { pub _format: i64, pub _id: GeneratedId, @@ -1588,7 +1752,6 @@ pub struct Group { pub storageCounter: Option, pub user: Option, } - impl Entity for Group { fn type_ref() -> TypeRef { TypeRef { @@ -1598,7 +1761,10 @@ impl Entity for Group { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct GroupInfo { pub _format: i64, pub _id: IdTuple, @@ -1620,7 +1786,6 @@ pub struct GroupInfo { pub _errors: Option, pub _finalIvs: HashMap, } - impl Entity for GroupInfo { fn type_ref() -> TypeRef { TypeRef { @@ -1630,7 +1795,10 @@ impl Entity for GroupInfo { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct GroupKey { pub _format: i64, pub _id: IdTuple, @@ -1645,7 +1813,6 @@ pub struct GroupKey { pub keyPair: Option, pub pubAdminGroupEncGKey: Option, } - impl Entity for GroupKey { fn type_ref() -> TypeRef { TypeRef { @@ -1655,7 +1822,10 @@ impl Entity for GroupKey { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct GroupKeyRotationData { pub _id: CustomId, #[serde(with = "serde_bytes")] @@ -1669,7 +1839,6 @@ pub struct GroupKeyRotationData { pub groupMembershipUpdateData: Vec, pub keyPair: Option, } - impl Entity for GroupKeyRotationData { fn type_ref() -> TypeRef { TypeRef { @@ -1679,13 +1848,15 @@ impl Entity for GroupKeyRotationData { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct GroupKeyRotationInfoGetOut { pub _format: i64, pub userOrAdminGroupKeyRotationScheduled: bool, pub groupKeyUpdates: Vec, } - impl Entity for GroupKeyRotationInfoGetOut { fn type_ref() -> TypeRef { TypeRef { @@ -1695,12 +1866,14 @@ impl Entity for GroupKeyRotationInfoGetOut { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct GroupKeyRotationPostIn { pub _format: i64, pub groupKeyUpdates: Vec, } - impl Entity for GroupKeyRotationPostIn { fn type_ref() -> TypeRef { TypeRef { @@ -1710,7 +1883,10 @@ impl Entity for GroupKeyRotationPostIn { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct GroupKeyUpdate { pub _format: i64, pub _id: IdTuple, @@ -1726,7 +1902,6 @@ pub struct GroupKeyUpdate { pub _errors: Option, pub _finalIvs: HashMap, } - impl Entity for GroupKeyUpdate { fn type_ref() -> TypeRef { TypeRef { @@ -1736,7 +1911,10 @@ impl Entity for GroupKeyUpdate { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct GroupKeyUpdateData { pub _id: CustomId, #[serde(with = "serde_bytes")] @@ -1746,7 +1924,6 @@ pub struct GroupKeyUpdateData { pub sessionKeyEncGroupKeyVersion: i64, pub pubEncBucketKeyData: PubEncKeyData, } - impl Entity for GroupKeyUpdateData { fn type_ref() -> TypeRef { TypeRef { @@ -1756,12 +1933,14 @@ impl Entity for GroupKeyUpdateData { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct GroupKeyUpdatesRef { pub _id: CustomId, pub list: GeneratedId, } - impl Entity for GroupKeyUpdatesRef { fn type_ref() -> TypeRef { TypeRef { @@ -1771,12 +1950,14 @@ impl Entity for GroupKeyUpdatesRef { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct GroupKeysRef { pub _id: CustomId, pub list: GeneratedId, } - impl Entity for GroupKeysRef { fn type_ref() -> TypeRef { TypeRef { @@ -1786,7 +1967,10 @@ impl Entity for GroupKeysRef { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct GroupMember { pub _format: i64, pub _id: IdTuple, @@ -1797,7 +1981,6 @@ pub struct GroupMember { pub user: GeneratedId, pub userGroupInfo: IdTuple, } - impl Entity for GroupMember { fn type_ref() -> TypeRef { TypeRef { @@ -1807,7 +1990,10 @@ impl Entity for GroupMember { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct GroupMembership { pub _id: CustomId, pub admin: bool, @@ -1821,7 +2007,6 @@ pub struct GroupMembership { pub groupInfo: IdTuple, pub groupMember: IdTuple, } - impl Entity for GroupMembership { fn type_ref() -> TypeRef { TypeRef { @@ -1831,7 +2016,10 @@ impl Entity for GroupMembership { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct GroupMembershipKeyData { pub _id: CustomId, pub groupKeyVersion: i64, @@ -1840,7 +2028,6 @@ pub struct GroupMembershipKeyData { pub symKeyVersion: i64, pub group: GeneratedId, } - impl Entity for GroupMembershipKeyData { fn type_ref() -> TypeRef { TypeRef { @@ -1850,7 +2037,10 @@ impl Entity for GroupMembershipKeyData { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct GroupMembershipUpdateData { pub _id: CustomId, #[serde(with = "serde_bytes")] @@ -1858,7 +2048,6 @@ pub struct GroupMembershipUpdateData { pub userKeyVersion: i64, pub userId: GeneratedId, } - impl Entity for GroupMembershipUpdateData { fn type_ref() -> TypeRef { TypeRef { @@ -1868,7 +2057,10 @@ impl Entity for GroupMembershipUpdateData { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct GroupRoot { pub _format: i64, pub _id: GeneratedId, @@ -1878,7 +2070,6 @@ pub struct GroupRoot { pub externalUserAreaGroupInfos: Option, pub externalUserReferences: GeneratedId, } - impl Entity for GroupRoot { fn type_ref() -> TypeRef { TypeRef { @@ -1888,13 +2079,15 @@ impl Entity for GroupRoot { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct IdTupleWrapper { pub _id: CustomId, pub listElementId: GeneratedId, pub listId: GeneratedId, } - impl Entity for IdTupleWrapper { fn type_ref() -> TypeRef { TypeRef { @@ -1904,7 +2097,10 @@ impl Entity for IdTupleWrapper { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct InstanceSessionKey { pub _id: CustomId, #[serde(with = "serde_bytes")] @@ -1916,7 +2112,6 @@ pub struct InstanceSessionKey { pub symKeyVersion: i64, pub typeInfo: TypeInfo, } - impl Entity for InstanceSessionKey { fn type_ref() -> TypeRef { TypeRef { @@ -1926,7 +2121,10 @@ impl Entity for InstanceSessionKey { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct Invoice { pub _format: i64, pub _id: GeneratedId, @@ -1955,7 +2153,6 @@ pub struct Invoice { pub _errors: Option, pub _finalIvs: HashMap, } - impl Entity for Invoice { fn type_ref() -> TypeRef { TypeRef { @@ -1965,12 +2162,14 @@ impl Entity for Invoice { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct InvoiceDataGetIn { pub _format: i64, pub invoiceNumber: String, } - impl Entity for InvoiceDataGetIn { fn type_ref() -> TypeRef { TypeRef { @@ -1980,7 +2179,10 @@ impl Entity for InvoiceDataGetIn { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct InvoiceDataGetOut { pub _format: i64, pub address: String, @@ -1997,7 +2199,6 @@ pub struct InvoiceDataGetOut { pub vatType: i64, pub items: Vec, } - impl Entity for InvoiceDataGetOut { fn type_ref() -> TypeRef { TypeRef { @@ -2007,7 +2208,10 @@ impl Entity for InvoiceDataGetOut { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct InvoiceDataItem { pub _id: CustomId, pub amount: i64, @@ -2017,7 +2221,6 @@ pub struct InvoiceDataItem { pub startDate: Option, pub totalPrice: i64, } - impl Entity for InvoiceDataItem { fn type_ref() -> TypeRef { TypeRef { @@ -2027,7 +2230,10 @@ impl Entity for InvoiceDataItem { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct InvoiceInfo { pub _format: i64, pub _id: GeneratedId, @@ -2048,7 +2254,6 @@ pub struct InvoiceInfo { pub invoices: GeneratedId, pub paymentErrorInfo: Option, } - impl Entity for InvoiceInfo { fn type_ref() -> TypeRef { TypeRef { @@ -2058,7 +2263,10 @@ impl Entity for InvoiceInfo { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct InvoiceItem { pub _id: CustomId, pub amount: i64, @@ -2071,7 +2279,6 @@ pub struct InvoiceItem { pub r#type: i64, pub _finalIvs: HashMap, } - impl Entity for InvoiceItem { fn type_ref() -> TypeRef { TypeRef { @@ -2081,7 +2288,10 @@ impl Entity for InvoiceItem { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct KeyPair { pub _id: CustomId, #[serde(with = "serde_bytes")] @@ -2097,7 +2307,6 @@ pub struct KeyPair { #[serde(with = "serde_bytes")] pub symEncPrivRsaKey: Option>, } - impl Entity for KeyPair { fn type_ref() -> TypeRef { TypeRef { @@ -2107,7 +2316,10 @@ impl Entity for KeyPair { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct KeyRotation { pub _format: i64, pub _id: IdTuple, @@ -2117,7 +2329,6 @@ pub struct KeyRotation { pub targetKeyVersion: i64, pub adminGroupKeyAuthenticationData: Option, } - impl Entity for KeyRotation { fn type_ref() -> TypeRef { TypeRef { @@ -2127,12 +2338,14 @@ impl Entity for KeyRotation { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct KeyRotationsRef { pub _id: CustomId, pub list: GeneratedId, } - impl Entity for KeyRotationsRef { fn type_ref() -> TypeRef { TypeRef { @@ -2142,12 +2355,14 @@ impl Entity for KeyRotationsRef { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct LocationServiceGetReturn { pub _format: i64, pub country: String, } - impl Entity for LocationServiceGetReturn { fn type_ref() -> TypeRef { TypeRef { @@ -2157,7 +2372,10 @@ impl Entity for LocationServiceGetReturn { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct Login { pub _format: i64, pub _id: IdTuple, @@ -2165,7 +2383,6 @@ pub struct Login { pub _permissions: GeneratedId, pub time: DateTime, } - impl Entity for Login { fn type_ref() -> TypeRef { TypeRef { @@ -2175,13 +2392,15 @@ impl Entity for Login { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct MailAddressAlias { pub _id: CustomId, pub enabled: bool, pub mailAddress: String, } - impl Entity for MailAddressAlias { fn type_ref() -> TypeRef { TypeRef { @@ -2191,12 +2410,14 @@ impl Entity for MailAddressAlias { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct MailAddressAliasGetIn { pub _format: i64, pub targetGroup: GeneratedId, } - impl Entity for MailAddressAliasGetIn { fn type_ref() -> TypeRef { TypeRef { @@ -2206,13 +2427,15 @@ impl Entity for MailAddressAliasGetIn { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct MailAddressAliasServiceData { pub _format: i64, pub mailAddress: String, pub group: GeneratedId, } - impl Entity for MailAddressAliasServiceData { fn type_ref() -> TypeRef { TypeRef { @@ -2222,14 +2445,16 @@ impl Entity for MailAddressAliasServiceData { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct MailAddressAliasServiceDataDelete { pub _format: i64, pub mailAddress: String, pub restore: bool, pub group: GeneratedId, } - impl Entity for MailAddressAliasServiceDataDelete { fn type_ref() -> TypeRef { TypeRef { @@ -2239,7 +2464,10 @@ impl Entity for MailAddressAliasServiceDataDelete { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct MailAddressAliasServiceReturn { pub _format: i64, pub enabledAliases: i64, @@ -2247,7 +2475,6 @@ pub struct MailAddressAliasServiceReturn { pub totalAliases: i64, pub usedAliases: i64, } - impl Entity for MailAddressAliasServiceReturn { fn type_ref() -> TypeRef { TypeRef { @@ -2257,13 +2484,15 @@ impl Entity for MailAddressAliasServiceReturn { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct MailAddressAvailability { pub _id: CustomId, pub available: bool, pub mailAddress: String, } - impl Entity for MailAddressAvailability { fn type_ref() -> TypeRef { TypeRef { @@ -2273,7 +2502,10 @@ impl Entity for MailAddressAvailability { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct MailAddressToGroup { pub _format: i64, pub _id: CustomId, @@ -2281,7 +2513,6 @@ pub struct MailAddressToGroup { pub _permissions: GeneratedId, pub internalGroup: Option, } - impl Entity for MailAddressToGroup { fn type_ref() -> TypeRef { TypeRef { @@ -2291,7 +2522,10 @@ impl Entity for MailAddressToGroup { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct MembershipAddData { pub _format: i64, pub groupKeyVersion: i64, @@ -2301,7 +2535,6 @@ pub struct MembershipAddData { pub group: GeneratedId, pub user: GeneratedId, } - impl Entity for MembershipAddData { fn type_ref() -> TypeRef { TypeRef { @@ -2311,12 +2544,14 @@ impl Entity for MembershipAddData { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct MembershipPutIn { pub _format: i64, pub groupKeyUpdates: Vec, } - impl Entity for MembershipPutIn { fn type_ref() -> TypeRef { TypeRef { @@ -2326,13 +2561,15 @@ impl Entity for MembershipPutIn { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct MembershipRemoveData { pub _format: i64, pub group: GeneratedId, pub user: GeneratedId, } - impl Entity for MembershipRemoveData { fn type_ref() -> TypeRef { TypeRef { @@ -2342,7 +2579,10 @@ impl Entity for MembershipRemoveData { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct MissedNotification { pub _format: i64, pub _id: CustomId, @@ -2359,7 +2599,6 @@ pub struct MissedNotification { pub _errors: Option, pub _finalIvs: HashMap, } - impl Entity for MissedNotification { fn type_ref() -> TypeRef { TypeRef { @@ -2369,12 +2608,14 @@ impl Entity for MissedNotification { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct MultipleMailAddressAvailabilityData { pub _format: i64, pub mailAddresses: Vec, } - impl Entity for MultipleMailAddressAvailabilityData { fn type_ref() -> TypeRef { TypeRef { @@ -2384,12 +2625,14 @@ impl Entity for MultipleMailAddressAvailabilityData { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct MultipleMailAddressAvailabilityReturn { pub _format: i64, pub availabilities: Vec, } - impl Entity for MultipleMailAddressAvailabilityReturn { fn type_ref() -> TypeRef { TypeRef { @@ -2399,14 +2642,16 @@ impl Entity for MultipleMailAddressAvailabilityReturn { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct NotificationInfo { pub _id: CustomId, pub mailAddress: String, pub userId: GeneratedId, pub mailId: Option, } - impl Entity for NotificationInfo { fn type_ref() -> TypeRef { TypeRef { @@ -2416,14 +2661,16 @@ impl Entity for NotificationInfo { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct NotificationMailTemplate { pub _id: CustomId, pub body: String, pub language: String, pub subject: String, } - impl Entity for NotificationMailTemplate { fn type_ref() -> TypeRef { TypeRef { @@ -2433,14 +2680,16 @@ impl Entity for NotificationMailTemplate { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct NotificationSessionKey { pub _id: CustomId, #[serde(with = "serde_bytes")] pub pushIdentifierSessionEncSessionKey: Vec, pub pushIdentifier: IdTuple, } - impl Entity for NotificationSessionKey { fn type_ref() -> TypeRef { TypeRef { @@ -2450,7 +2699,10 @@ impl Entity for NotificationSessionKey { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct OrderProcessingAgreement { pub _format: i64, pub _id: IdTuple, @@ -2467,7 +2719,6 @@ pub struct OrderProcessingAgreement { pub _errors: Option, pub _finalIvs: HashMap, } - impl Entity for OrderProcessingAgreement { fn type_ref() -> TypeRef { TypeRef { @@ -2477,12 +2728,14 @@ impl Entity for OrderProcessingAgreement { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct OtpChallenge { pub _id: CustomId, pub secondFactors: Vec, } - impl Entity for OtpChallenge { fn type_ref() -> TypeRef { TypeRef { @@ -2492,12 +2745,14 @@ impl Entity for OtpChallenge { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct PaymentDataServiceGetData { pub _format: i64, pub clientType: Option, } - impl Entity for PaymentDataServiceGetData { fn type_ref() -> TypeRef { TypeRef { @@ -2507,12 +2762,14 @@ impl Entity for PaymentDataServiceGetData { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct PaymentDataServiceGetReturn { pub _format: i64, pub loginUrl: String, } - impl Entity for PaymentDataServiceGetReturn { fn type_ref() -> TypeRef { TypeRef { @@ -2522,12 +2779,14 @@ impl Entity for PaymentDataServiceGetReturn { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct PaymentDataServicePostData { pub _format: i64, pub braintree3dsResponse: Braintree3ds2Response, } - impl Entity for PaymentDataServicePostData { fn type_ref() -> TypeRef { TypeRef { @@ -2537,7 +2796,10 @@ impl Entity for PaymentDataServicePostData { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct PaymentDataServicePutData { pub _format: i64, pub confirmedCountry: Option, @@ -2553,7 +2815,6 @@ pub struct PaymentDataServicePutData { pub _errors: Option, pub _finalIvs: HashMap, } - impl Entity for PaymentDataServicePutData { fn type_ref() -> TypeRef { TypeRef { @@ -2563,13 +2824,15 @@ impl Entity for PaymentDataServicePutData { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct PaymentDataServicePutReturn { pub _format: i64, pub result: i64, pub braintree3dsRequest: Option, } - impl Entity for PaymentDataServicePutReturn { fn type_ref() -> TypeRef { TypeRef { @@ -2579,14 +2842,16 @@ impl Entity for PaymentDataServicePutReturn { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct PaymentErrorInfo { pub _id: CustomId, pub errorCode: String, pub errorTime: DateTime, pub thirdPartyErrorId: String, } - impl Entity for PaymentErrorInfo { fn type_ref() -> TypeRef { TypeRef { @@ -2596,7 +2861,10 @@ impl Entity for PaymentErrorInfo { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct Permission { pub _format: i64, pub _id: IdTuple, @@ -2618,7 +2886,6 @@ pub struct Permission { pub bucket: Option, pub group: Option, } - impl Entity for Permission { fn type_ref() -> TypeRef { TypeRef { @@ -2628,7 +2895,10 @@ impl Entity for Permission { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct PlanConfiguration { pub _id: CustomId, pub autoResponder: bool, @@ -2642,7 +2912,6 @@ pub struct PlanConfiguration { pub templates: bool, pub whitelabel: bool, } - impl Entity for PlanConfiguration { fn type_ref() -> TypeRef { TypeRef { @@ -2652,7 +2921,10 @@ impl Entity for PlanConfiguration { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct PlanPrices { pub _id: CustomId, pub additionalUserPriceMonthly: i64, @@ -2669,7 +2941,6 @@ pub struct PlanPrices { pub whitelabel: bool, pub planConfiguration: PlanConfiguration, } - impl Entity for PlanPrices { fn type_ref() -> TypeRef { TypeRef { @@ -2679,12 +2950,14 @@ impl Entity for PlanPrices { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct PlanServiceGetOut { pub _format: i64, pub config: PlanConfiguration, } - impl Entity for PlanServiceGetOut { fn type_ref() -> TypeRef { TypeRef { @@ -2694,7 +2967,10 @@ impl Entity for PlanServiceGetOut { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct PriceData { pub _id: CustomId, pub paymentInterval: i64, @@ -2702,7 +2978,6 @@ pub struct PriceData { pub taxIncluded: bool, pub items: Vec, } - impl Entity for PriceData { fn type_ref() -> TypeRef { TypeRef { @@ -2712,7 +2987,10 @@ impl Entity for PriceData { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct PriceItemData { pub _id: CustomId, pub count: i64, @@ -2720,7 +2998,6 @@ pub struct PriceItemData { pub price: i64, pub singleType: bool, } - impl Entity for PriceItemData { fn type_ref() -> TypeRef { TypeRef { @@ -2730,7 +3007,10 @@ impl Entity for PriceItemData { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct PriceRequestData { pub _id: CustomId, pub accountType: Option, @@ -2740,7 +3020,6 @@ pub struct PriceRequestData { pub paymentInterval: Option, pub reactivate: bool, } - impl Entity for PriceRequestData { fn type_ref() -> TypeRef { TypeRef { @@ -2750,13 +3029,15 @@ impl Entity for PriceRequestData { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct PriceServiceData { pub _format: i64, pub date: Option, pub priceRequest: Option, } - impl Entity for PriceServiceData { fn type_ref() -> TypeRef { TypeRef { @@ -2766,7 +3047,10 @@ impl Entity for PriceServiceData { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct PriceServiceReturn { pub _format: i64, pub currentPeriodAddedPrice: Option, @@ -2775,7 +3059,6 @@ pub struct PriceServiceReturn { pub currentPriceThisPeriod: Option, pub futurePriceNextPeriod: Option, } - impl Entity for PriceServiceReturn { fn type_ref() -> TypeRef { TypeRef { @@ -2785,7 +3068,10 @@ impl Entity for PriceServiceReturn { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct PubEncKeyData { pub _id: CustomId, pub protocolVersion: i64, @@ -2796,7 +3082,6 @@ pub struct PubEncKeyData { pub recipientKeyVersion: i64, pub senderKeyVersion: Option, } - impl Entity for PubEncKeyData { fn type_ref() -> TypeRef { TypeRef { @@ -2806,14 +3091,16 @@ impl Entity for PubEncKeyData { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct PublicKeyGetIn { pub _format: i64, pub identifier: String, pub identifierType: i64, pub version: Option, } - impl Entity for PublicKeyGetIn { fn type_ref() -> TypeRef { TypeRef { @@ -2823,7 +3110,10 @@ impl Entity for PublicKeyGetIn { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct PublicKeyGetOut { pub _format: i64, #[serde(with = "serde_bytes")] @@ -2834,7 +3124,6 @@ pub struct PublicKeyGetOut { #[serde(with = "serde_bytes")] pub pubRsaKey: Option>, } - impl Entity for PublicKeyGetOut { fn type_ref() -> TypeRef { TypeRef { @@ -2844,7 +3133,10 @@ impl Entity for PublicKeyGetOut { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct PublicKeyPutIn { pub _format: i64, #[serde(with = "serde_bytes")] @@ -2853,7 +3145,6 @@ pub struct PublicKeyPutIn { pub symEncPrivEccKey: Vec, pub keyGroup: GeneratedId, } - impl Entity for PublicKeyPutIn { fn type_ref() -> TypeRef { TypeRef { @@ -2863,7 +3154,10 @@ impl Entity for PublicKeyPutIn { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct PushIdentifier { pub _area: i64, pub _format: i64, @@ -2885,7 +3179,6 @@ pub struct PushIdentifier { pub _errors: Option, pub _finalIvs: HashMap, } - impl Entity for PushIdentifier { fn type_ref() -> TypeRef { TypeRef { @@ -2895,12 +3188,14 @@ impl Entity for PushIdentifier { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct PushIdentifierList { pub _id: CustomId, pub list: GeneratedId, } - impl Entity for PushIdentifierList { fn type_ref() -> TypeRef { TypeRef { @@ -2910,7 +3205,10 @@ impl Entity for PushIdentifierList { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct ReceivedGroupInvitation { pub _format: i64, pub _id: IdTuple, @@ -2933,7 +3231,6 @@ pub struct ReceivedGroupInvitation { pub _errors: Option, pub _finalIvs: HashMap, } - impl Entity for ReceivedGroupInvitation { fn type_ref() -> TypeRef { TypeRef { @@ -2943,7 +3240,10 @@ impl Entity for ReceivedGroupInvitation { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct RecoverCode { pub _format: i64, pub _id: GeneratedId, @@ -2957,7 +3257,6 @@ pub struct RecoverCode { #[serde(with = "serde_bytes")] pub verifier: Vec, } - impl Entity for RecoverCode { fn type_ref() -> TypeRef { TypeRef { @@ -2967,7 +3266,10 @@ impl Entity for RecoverCode { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct RecoverCodeData { pub _id: CustomId, #[serde(with = "serde_bytes")] @@ -2978,7 +3280,6 @@ pub struct RecoverCodeData { pub userEncRecoveryCode: Vec, pub userKeyVersion: i64, } - impl Entity for RecoverCodeData { fn type_ref() -> TypeRef { TypeRef { @@ -2988,12 +3289,14 @@ impl Entity for RecoverCodeData { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct ReferralCodeGetIn { pub _format: i64, pub referralCode: GeneratedId, } - impl Entity for ReferralCodeGetIn { fn type_ref() -> TypeRef { TypeRef { @@ -3003,11 +3306,13 @@ impl Entity for ReferralCodeGetIn { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct ReferralCodePostIn { pub _format: i64, } - impl Entity for ReferralCodePostIn { fn type_ref() -> TypeRef { TypeRef { @@ -3017,12 +3322,14 @@ impl Entity for ReferralCodePostIn { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct ReferralCodePostOut { pub _format: i64, pub referralCode: GeneratedId, } - impl Entity for ReferralCodePostOut { fn type_ref() -> TypeRef { TypeRef { @@ -3032,13 +3339,15 @@ impl Entity for ReferralCodePostOut { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct RegistrationCaptchaServiceData { pub _format: i64, pub response: String, pub token: String, } - impl Entity for RegistrationCaptchaServiceData { fn type_ref() -> TypeRef { TypeRef { @@ -3048,7 +3357,10 @@ impl Entity for RegistrationCaptchaServiceData { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct RegistrationCaptchaServiceGetData { pub _format: i64, pub businessUseSelected: bool, @@ -3057,7 +3369,6 @@ pub struct RegistrationCaptchaServiceGetData { pub signupToken: Option, pub token: Option, } - impl Entity for RegistrationCaptchaServiceGetData { fn type_ref() -> TypeRef { TypeRef { @@ -3067,14 +3378,16 @@ impl Entity for RegistrationCaptchaServiceGetData { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct RegistrationCaptchaServiceReturn { pub _format: i64, #[serde(with = "serde_bytes")] pub challenge: Option>, pub token: String, } - impl Entity for RegistrationCaptchaServiceReturn { fn type_ref() -> TypeRef { TypeRef { @@ -3084,12 +3397,14 @@ impl Entity for RegistrationCaptchaServiceReturn { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct RegistrationReturn { pub _format: i64, pub authToken: String, } - impl Entity for RegistrationReturn { fn type_ref() -> TypeRef { TypeRef { @@ -3099,14 +3414,16 @@ impl Entity for RegistrationReturn { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct RegistrationServiceData { pub _format: i64, pub source: Option, pub starterDomain: String, pub state: i64, } - impl Entity for RegistrationServiceData { fn type_ref() -> TypeRef { TypeRef { @@ -3116,7 +3433,10 @@ impl Entity for RegistrationServiceData { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct RejectedSender { pub _format: i64, pub _id: IdTuple, @@ -3128,7 +3448,6 @@ pub struct RejectedSender { pub senderIp: String, pub senderMailAddress: String, } - impl Entity for RejectedSender { fn type_ref() -> TypeRef { TypeRef { @@ -3138,12 +3457,14 @@ impl Entity for RejectedSender { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct RejectedSendersRef { pub _id: CustomId, pub items: GeneratedId, } - impl Entity for RejectedSendersRef { fn type_ref() -> TypeRef { TypeRef { @@ -3153,7 +3474,10 @@ impl Entity for RejectedSendersRef { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct RepeatRule { pub _id: CustomId, pub endType: i64, @@ -3164,7 +3488,6 @@ pub struct RepeatRule { pub excludedDates: Vec, pub _finalIvs: HashMap, } - impl Entity for RepeatRule { fn type_ref() -> TypeRef { TypeRef { @@ -3174,14 +3497,16 @@ impl Entity for RepeatRule { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct ResetFactorsDeleteData { pub _format: i64, pub authVerifier: String, pub mailAddress: String, pub recoverCodeVerifier: String, } - impl Entity for ResetFactorsDeleteData { fn type_ref() -> TypeRef { TypeRef { @@ -3191,7 +3516,10 @@ impl Entity for ResetFactorsDeleteData { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct ResetPasswordPostIn { pub _format: i64, pub kdfVersion: i64, @@ -3204,7 +3532,6 @@ pub struct ResetPasswordPostIn { pub verifier: Vec, pub user: GeneratedId, } - impl Entity for ResetPasswordPostIn { fn type_ref() -> TypeRef { TypeRef { @@ -3214,7 +3541,10 @@ impl Entity for ResetPasswordPostIn { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct RootInstance { pub _format: i64, pub _id: IdTuple, @@ -3222,7 +3552,6 @@ pub struct RootInstance { pub _permissions: GeneratedId, pub reference: GeneratedId, } - impl Entity for RootInstance { fn type_ref() -> TypeRef { TypeRef { @@ -3232,12 +3561,14 @@ impl Entity for RootInstance { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct SaltData { pub _format: i64, pub mailAddress: String, } - impl Entity for SaltData { fn type_ref() -> TypeRef { TypeRef { @@ -3247,14 +3578,16 @@ impl Entity for SaltData { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct SaltReturn { pub _format: i64, pub kdfVersion: i64, #[serde(with = "serde_bytes")] pub salt: Vec, } - impl Entity for SaltReturn { fn type_ref() -> TypeRef { TypeRef { @@ -3264,7 +3597,10 @@ impl Entity for SaltReturn { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct SecondFactor { pub _format: i64, pub _id: IdTuple, @@ -3277,7 +3613,6 @@ pub struct SecondFactor { pub r#type: i64, pub u2f: Option, } - impl Entity for SecondFactor { fn type_ref() -> TypeRef { TypeRef { @@ -3287,12 +3622,14 @@ impl Entity for SecondFactor { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct SecondFactorAuthAllowedReturn { pub _format: i64, pub allowed: bool, } - impl Entity for SecondFactorAuthAllowedReturn { fn type_ref() -> TypeRef { TypeRef { @@ -3302,7 +3639,10 @@ impl Entity for SecondFactorAuthAllowedReturn { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct SecondFactorAuthData { pub _format: i64, pub otpCode: Option, @@ -3312,7 +3652,6 @@ pub struct SecondFactorAuthData { pub u2f: Option, pub webauthn: Option, } - impl Entity for SecondFactorAuthData { fn type_ref() -> TypeRef { TypeRef { @@ -3322,12 +3661,14 @@ impl Entity for SecondFactorAuthData { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct SecondFactorAuthDeleteData { pub _format: i64, pub session: IdTuple, } - impl Entity for SecondFactorAuthDeleteData { fn type_ref() -> TypeRef { TypeRef { @@ -3337,12 +3678,14 @@ impl Entity for SecondFactorAuthDeleteData { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct SecondFactorAuthGetData { pub _format: i64, pub accessToken: String, } - impl Entity for SecondFactorAuthGetData { fn type_ref() -> TypeRef { TypeRef { @@ -3352,12 +3695,14 @@ impl Entity for SecondFactorAuthGetData { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct SecondFactorAuthGetReturn { pub _format: i64, pub secondFactorPending: bool, } - impl Entity for SecondFactorAuthGetReturn { fn type_ref() -> TypeRef { TypeRef { @@ -3367,7 +3712,10 @@ impl Entity for SecondFactorAuthGetReturn { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct SecondFactorAuthentication { pub _format: i64, pub _id: IdTuple, @@ -3378,7 +3726,6 @@ pub struct SecondFactorAuthentication { pub service: String, pub verifyCount: i64, } - impl Entity for SecondFactorAuthentication { fn type_ref() -> TypeRef { TypeRef { @@ -3388,7 +3735,10 @@ impl Entity for SecondFactorAuthentication { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct SendRegistrationCodeData { pub _format: i64, pub accountType: i64, @@ -3396,7 +3746,6 @@ pub struct SendRegistrationCodeData { pub language: String, pub mobilePhoneNumber: String, } - impl Entity for SendRegistrationCodeData { fn type_ref() -> TypeRef { TypeRef { @@ -3406,12 +3755,14 @@ impl Entity for SendRegistrationCodeData { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct SendRegistrationCodeReturn { pub _format: i64, pub authToken: String, } - impl Entity for SendRegistrationCodeReturn { fn type_ref() -> TypeRef { TypeRef { @@ -3421,7 +3772,10 @@ impl Entity for SendRegistrationCodeReturn { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct SentGroupInvitation { pub _format: i64, pub _id: IdTuple, @@ -3432,7 +3786,6 @@ pub struct SentGroupInvitation { pub receivedInvitation: Option, pub sharedGroup: GeneratedId, } - impl Entity for SentGroupInvitation { fn type_ref() -> TypeRef { TypeRef { @@ -3442,7 +3795,10 @@ impl Entity for SentGroupInvitation { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct Session { pub _format: i64, pub _id: IdTuple, @@ -3463,7 +3819,6 @@ pub struct Session { pub _errors: Option, pub _finalIvs: HashMap, } - impl Entity for Session { fn type_ref() -> TypeRef { TypeRef { @@ -3473,13 +3828,15 @@ impl Entity for Session { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct SignOrderProcessingAgreementData { pub _format: i64, pub customerAddress: String, pub version: String, } - impl Entity for SignOrderProcessingAgreementData { fn type_ref() -> TypeRef { TypeRef { @@ -3489,13 +3846,15 @@ impl Entity for SignOrderProcessingAgreementData { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct SseConnectData { pub _format: i64, pub identifier: String, pub userIds: Vec, } - impl Entity for SseConnectData { fn type_ref() -> TypeRef { TypeRef { @@ -3505,13 +3864,15 @@ impl Entity for SseConnectData { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct StringConfigValue { pub _id: CustomId, pub name: String, pub value: String, } - impl Entity for StringConfigValue { fn type_ref() -> TypeRef { TypeRef { @@ -3521,12 +3882,14 @@ impl Entity for StringConfigValue { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct StringWrapper { pub _id: CustomId, pub value: String, } - impl Entity for StringWrapper { fn type_ref() -> TypeRef { TypeRef { @@ -3536,7 +3899,10 @@ impl Entity for StringWrapper { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct SurveyData { pub _id: CustomId, pub category: i64, @@ -3544,7 +3910,6 @@ pub struct SurveyData { pub reason: i64, pub version: i64, } - impl Entity for SurveyData { fn type_ref() -> TypeRef { TypeRef { @@ -3554,7 +3919,10 @@ impl Entity for SurveyData { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct SwitchAccountTypePostIn { pub _format: i64, pub accountType: i64, @@ -3565,7 +3933,6 @@ pub struct SwitchAccountTypePostIn { pub referralCode: Option, pub surveyData: Option, } - impl Entity for SwitchAccountTypePostIn { fn type_ref() -> TypeRef { TypeRef { @@ -3575,7 +3942,10 @@ impl Entity for SwitchAccountTypePostIn { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct SystemKeysReturn { pub _format: i64, #[serde(with = "serde_bytes")] @@ -3594,7 +3964,6 @@ pub struct SystemKeysReturn { pub freeGroup: Option, pub premiumGroup: Option, } - impl Entity for SystemKeysReturn { fn type_ref() -> TypeRef { TypeRef { @@ -3604,7 +3973,10 @@ impl Entity for SystemKeysReturn { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct TakeOverDeletedAddressData { pub _format: i64, pub authVerifier: String, @@ -3612,7 +3984,6 @@ pub struct TakeOverDeletedAddressData { pub recoverCodeVerifier: Option, pub targetAccountMailAddress: String, } - impl Entity for TakeOverDeletedAddressData { fn type_ref() -> TypeRef { TypeRef { @@ -3622,13 +3993,15 @@ impl Entity for TakeOverDeletedAddressData { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct TypeInfo { pub _id: CustomId, pub application: String, pub typeId: i64, } - impl Entity for TypeInfo { fn type_ref() -> TypeRef { TypeRef { @@ -3638,14 +4011,16 @@ impl Entity for TypeInfo { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct U2fChallenge { pub _id: CustomId, #[serde(with = "serde_bytes")] pub challenge: Vec, pub keys: Vec, } - impl Entity for U2fChallenge { fn type_ref() -> TypeRef { TypeRef { @@ -3655,7 +4030,10 @@ impl Entity for U2fChallenge { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct U2fKey { pub _id: CustomId, pub appId: String, @@ -3663,7 +4041,6 @@ pub struct U2fKey { pub keyHandle: Vec, pub secondFactor: IdTuple, } - impl Entity for U2fKey { fn type_ref() -> TypeRef { TypeRef { @@ -3673,7 +4050,10 @@ impl Entity for U2fKey { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct U2fRegisteredDevice { pub _id: CustomId, pub appId: String, @@ -3684,7 +4064,6 @@ pub struct U2fRegisteredDevice { #[serde(with = "serde_bytes")] pub publicKey: Vec, } - impl Entity for U2fRegisteredDevice { fn type_ref() -> TypeRef { TypeRef { @@ -3694,14 +4073,16 @@ impl Entity for U2fRegisteredDevice { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct U2fResponseData { pub _id: CustomId, pub clientData: String, pub keyHandle: String, pub signatureData: String, } - impl Entity for U2fResponseData { fn type_ref() -> TypeRef { TypeRef { @@ -3711,7 +4092,10 @@ impl Entity for U2fResponseData { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct UpdatePermissionKeyData { pub _format: i64, #[serde(with = "serde_bytes")] @@ -3720,7 +4104,6 @@ pub struct UpdatePermissionKeyData { pub bucketPermission: IdTuple, pub permission: IdTuple, } - impl Entity for UpdatePermissionKeyData { fn type_ref() -> TypeRef { TypeRef { @@ -3730,12 +4113,14 @@ impl Entity for UpdatePermissionKeyData { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct UpdateSessionKeysPostIn { pub _format: i64, pub ownerEncSessionKeys: Vec, } - impl Entity for UpdateSessionKeysPostIn { fn type_ref() -> TypeRef { TypeRef { @@ -3745,14 +4130,16 @@ impl Entity for UpdateSessionKeysPostIn { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct UpgradePriceServiceData { pub _format: i64, pub campaign: Option, pub date: Option, pub referralCode: Option, } - impl Entity for UpgradePriceServiceData { fn type_ref() -> TypeRef { TypeRef { @@ -3762,7 +4149,10 @@ impl Entity for UpgradePriceServiceData { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct UpgradePriceServiceReturn { pub _format: i64, pub bonusMonthsForYearlyPlan: i64, @@ -3781,7 +4171,6 @@ pub struct UpgradePriceServiceReturn { pub teamsPrices: PlanPrices, pub unlimitedPrices: PlanPrices, } - impl Entity for UpgradePriceServiceReturn { fn type_ref() -> TypeRef { TypeRef { @@ -3791,7 +4180,10 @@ impl Entity for UpgradePriceServiceReturn { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct User { pub _format: i64, pub _id: GeneratedId, @@ -3817,7 +4209,6 @@ pub struct User { pub successfulLogins: GeneratedId, pub userGroup: GroupMembership, } - impl Entity for User { fn type_ref() -> TypeRef { TypeRef { @@ -3827,7 +4218,10 @@ impl Entity for User { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct UserAlarmInfo { pub _format: i64, pub _id: IdTuple, @@ -3840,7 +4234,6 @@ pub struct UserAlarmInfo { pub _errors: Option, pub _finalIvs: HashMap, } - impl Entity for UserAlarmInfo { fn type_ref() -> TypeRef { TypeRef { @@ -3850,12 +4243,14 @@ impl Entity for UserAlarmInfo { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct UserAlarmInfoListType { pub _id: CustomId, pub alarms: GeneratedId, } - impl Entity for UserAlarmInfoListType { fn type_ref() -> TypeRef { TypeRef { @@ -3865,12 +4260,14 @@ impl Entity for UserAlarmInfoListType { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct UserAreaGroups { pub _id: CustomId, pub list: GeneratedId, } - impl Entity for UserAreaGroups { fn type_ref() -> TypeRef { TypeRef { @@ -3880,14 +4277,16 @@ impl Entity for UserAreaGroups { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct UserAuthentication { pub _id: CustomId, pub recoverCode: Option, pub secondFactors: GeneratedId, pub sessions: GeneratedId, } - impl Entity for UserAuthentication { fn type_ref() -> TypeRef { TypeRef { @@ -3897,14 +4296,16 @@ impl Entity for UserAuthentication { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct UserDataDelete { pub _format: i64, pub date: Option, pub restore: bool, pub user: GeneratedId, } - impl Entity for UserDataDelete { fn type_ref() -> TypeRef { TypeRef { @@ -3914,7 +4315,10 @@ impl Entity for UserDataDelete { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct UserExternalAuthInfo { pub _id: CustomId, pub authUpdateCounter: i64, @@ -3924,7 +4328,6 @@ pub struct UserExternalAuthInfo { pub latestSaltHash: Option>, pub variableAuthInfo: GeneratedId, } - impl Entity for UserExternalAuthInfo { fn type_ref() -> TypeRef { TypeRef { @@ -3934,7 +4337,10 @@ impl Entity for UserExternalAuthInfo { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct UserGroupKeyDistribution { pub _format: i64, pub _id: GeneratedId, @@ -3944,7 +4350,6 @@ pub struct UserGroupKeyDistribution { pub distributionEncUserGroupKey: Vec, pub userGroupKeyVersion: i64, } - impl Entity for UserGroupKeyDistribution { fn type_ref() -> TypeRef { TypeRef { @@ -3954,7 +4359,10 @@ impl Entity for UserGroupKeyDistribution { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct UserGroupKeyRotationData { pub _id: CustomId, #[serde(with = "serde_bytes")] @@ -3974,7 +4382,6 @@ pub struct UserGroupKeyRotationData { pub pubAdminGroupEncUserGroupKey: Option, pub recoverCodeData: Option, } - impl Entity for UserGroupKeyRotationData { fn type_ref() -> TypeRef { TypeRef { @@ -3984,12 +4391,14 @@ impl Entity for UserGroupKeyRotationData { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct UserGroupKeyRotationPostIn { pub _format: i64, pub userGroupKeyData: UserGroupKeyRotationData, } - impl Entity for UserGroupKeyRotationPostIn { fn type_ref() -> TypeRef { TypeRef { @@ -3999,7 +4408,10 @@ impl Entity for UserGroupKeyRotationPostIn { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct UserGroupRoot { pub _format: i64, pub _id: GeneratedId, @@ -4009,7 +4421,6 @@ pub struct UserGroupRoot { pub invitations: GeneratedId, pub keyRotations: Option, } - impl Entity for UserGroupRoot { fn type_ref() -> TypeRef { TypeRef { @@ -4019,7 +4430,10 @@ impl Entity for UserGroupRoot { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct VariableExternalAuthInfo { pub _format: i64, pub _id: GeneratedId, @@ -4034,7 +4448,6 @@ pub struct VariableExternalAuthInfo { pub loggedInVerifier: Option>, pub sentCount: i64, } - impl Entity for VariableExternalAuthInfo { fn type_ref() -> TypeRef { TypeRef { @@ -4044,13 +4457,15 @@ impl Entity for VariableExternalAuthInfo { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct VerifyRegistrationCodeData { pub _format: i64, pub authToken: String, pub code: String, } - impl Entity for VerifyRegistrationCodeData { fn type_ref() -> TypeRef { TypeRef { @@ -4060,7 +4475,10 @@ impl Entity for VerifyRegistrationCodeData { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct Version { pub _id: CustomId, pub operation: String, @@ -4069,7 +4487,6 @@ pub struct Version { pub author: GeneratedId, pub authorGroupInfo: IdTuple, } - impl Entity for Version { fn type_ref() -> TypeRef { TypeRef { @@ -4079,7 +4496,10 @@ impl Entity for Version { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct VersionData { pub _format: i64, pub application: String, @@ -4087,7 +4507,6 @@ pub struct VersionData { pub listId: Option, pub typeId: i64, } - impl Entity for VersionData { fn type_ref() -> TypeRef { TypeRef { @@ -4097,7 +4516,10 @@ impl Entity for VersionData { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct VersionInfo { pub _format: i64, pub _id: IdTuple, @@ -4114,7 +4536,6 @@ pub struct VersionInfo { pub author: GeneratedId, pub authorGroupInfo: IdTuple, } - impl Entity for VersionInfo { fn type_ref() -> TypeRef { TypeRef { @@ -4124,12 +4545,14 @@ impl Entity for VersionInfo { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct VersionReturn { pub _format: i64, pub versions: Vec, } - impl Entity for VersionReturn { fn type_ref() -> TypeRef { TypeRef { @@ -4139,7 +4562,10 @@ impl Entity for VersionReturn { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct WebauthnResponseData { pub _id: CustomId, #[serde(with = "serde_bytes")] @@ -4151,7 +4577,6 @@ pub struct WebauthnResponseData { #[serde(with = "serde_bytes")] pub signature: Vec, } - impl Entity for WebauthnResponseData { fn type_ref() -> TypeRef { TypeRef { @@ -4161,13 +4586,15 @@ impl Entity for WebauthnResponseData { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct WebsocketCounterData { pub _format: i64, pub mailGroup: GeneratedId, pub counterValues: Vec, } - impl Entity for WebsocketCounterData { fn type_ref() -> TypeRef { TypeRef { @@ -4177,13 +4604,15 @@ impl Entity for WebsocketCounterData { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct WebsocketCounterValue { pub _id: CustomId, pub count: i64, pub counterId: GeneratedId, } - impl Entity for WebsocketCounterValue { fn type_ref() -> TypeRef { TypeRef { @@ -4193,14 +4622,16 @@ impl Entity for WebsocketCounterValue { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct WebsocketEntityData { pub _format: i64, pub eventBatchId: GeneratedId, pub eventBatchOwner: GeneratedId, pub eventBatch: Vec, } - impl Entity for WebsocketEntityData { fn type_ref() -> TypeRef { TypeRef { @@ -4210,12 +4641,14 @@ impl Entity for WebsocketEntityData { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct WebsocketLeaderStatus { pub _format: i64, pub leaderStatus: bool, } - impl Entity for WebsocketLeaderStatus { fn type_ref() -> TypeRef { TypeRef { @@ -4225,7 +4658,10 @@ impl Entity for WebsocketLeaderStatus { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct WhitelabelChild { pub _format: i64, pub _id: IdTuple, @@ -4242,7 +4678,6 @@ pub struct WhitelabelChild { pub _errors: Option, pub _finalIvs: HashMap, } - impl Entity for WhitelabelChild { fn type_ref() -> TypeRef { TypeRef { @@ -4252,12 +4687,14 @@ impl Entity for WhitelabelChild { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct WhitelabelChildrenRef { pub _id: CustomId, pub items: GeneratedId, } - impl Entity for WhitelabelChildrenRef { fn type_ref() -> TypeRef { TypeRef { @@ -4267,7 +4704,10 @@ impl Entity for WhitelabelChildrenRef { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct WhitelabelConfig { pub _format: i64, pub _id: GeneratedId, @@ -4283,7 +4723,6 @@ pub struct WhitelabelConfig { pub certificateInfo: Option, pub whitelabelRegistrationDomains: Vec, } - impl Entity for WhitelabelConfig { fn type_ref() -> TypeRef { TypeRef { @@ -4293,13 +4732,15 @@ impl Entity for WhitelabelConfig { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct WhitelabelParent { pub _id: CustomId, pub customer: GeneratedId, pub whitelabelChildInParent: IdTuple, } - impl Entity for WhitelabelParent { fn type_ref() -> TypeRef { TypeRef { @@ -4308,3 +4749,6 @@ impl Entity for WhitelabelParent { } } } + + + diff --git a/tuta-sdk/rust/sdk/src/entities/tutanota.rs b/tuta-sdk/rust/sdk/src/entities/tutanota.rs index 87adb1cef3e8..c3661696e98f 100644 --- a/tuta-sdk/rust/sdk/src/entities/tutanota.rs +++ b/tuta-sdk/rust/sdk/src/entities/tutanota.rs @@ -2,7 +2,7 @@ use super::*; use serde::{Deserialize, Serialize}; -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct AttachmentKeyData { pub _id: CustomId, #[serde(with = "serde_bytes")] @@ -11,7 +11,6 @@ pub struct AttachmentKeyData { pub fileSessionKey: Option>, pub file: IdTuple, } - impl Entity for AttachmentKeyData { fn type_ref() -> TypeRef { TypeRef { @@ -21,14 +20,16 @@ impl Entity for AttachmentKeyData { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct Birthday { pub _id: CustomId, pub day: i64, pub month: i64, pub year: Option, } - impl Entity for Birthday { fn type_ref() -> TypeRef { TypeRef { @@ -38,14 +39,16 @@ impl Entity for Birthday { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct Body { pub _id: CustomId, pub compressedText: Option>, pub text: Option, pub _finalIvs: HashMap, } - impl Entity for Body { fn type_ref() -> TypeRef { TypeRef { @@ -55,12 +58,14 @@ impl Entity for Body { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct CalendarDeleteData { pub _format: i64, pub groupRootId: GeneratedId, } - impl Entity for CalendarDeleteData { fn type_ref() -> TypeRef { TypeRef { @@ -70,7 +75,10 @@ impl Entity for CalendarDeleteData { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct CalendarEvent { pub _format: i64, pub _id: IdTuple, @@ -97,7 +105,6 @@ pub struct CalendarEvent { pub _errors: Option, pub _finalIvs: HashMap, } - impl Entity for CalendarEvent { fn type_ref() -> TypeRef { TypeRef { @@ -107,14 +114,16 @@ impl Entity for CalendarEvent { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct CalendarEventAttendee { pub _id: CustomId, pub status: i64, pub address: EncryptedMailAddress, pub _finalIvs: HashMap, } - impl Entity for CalendarEventAttendee { fn type_ref() -> TypeRef { TypeRef { @@ -124,12 +133,14 @@ impl Entity for CalendarEventAttendee { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct CalendarEventIndexRef { pub _id: CustomId, pub list: GeneratedId, } - impl Entity for CalendarEventIndexRef { fn type_ref() -> TypeRef { TypeRef { @@ -139,7 +150,10 @@ impl Entity for CalendarEventIndexRef { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct CalendarEventUidIndex { pub _format: i64, pub _id: IdTuple, @@ -148,7 +162,6 @@ pub struct CalendarEventUidIndex { pub alteredInstances: Vec, pub progenitor: Option, } - impl Entity for CalendarEventUidIndex { fn type_ref() -> TypeRef { TypeRef { @@ -158,7 +171,10 @@ impl Entity for CalendarEventUidIndex { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct CalendarEventUpdate { pub _format: i64, pub _id: IdTuple, @@ -172,7 +188,6 @@ pub struct CalendarEventUpdate { pub _errors: Option, pub _finalIvs: HashMap, } - impl Entity for CalendarEventUpdate { fn type_ref() -> TypeRef { TypeRef { @@ -182,12 +197,14 @@ impl Entity for CalendarEventUpdate { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct CalendarEventUpdateList { pub _id: CustomId, pub list: GeneratedId, } - impl Entity for CalendarEventUpdateList { fn type_ref() -> TypeRef { TypeRef { @@ -197,7 +214,10 @@ impl Entity for CalendarEventUpdateList { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct CalendarGroupRoot { pub _format: i64, pub _id: GeneratedId, @@ -212,7 +232,6 @@ pub struct CalendarGroupRoot { pub _errors: Option, pub _finalIvs: HashMap, } - impl Entity for CalendarGroupRoot { fn type_ref() -> TypeRef { TypeRef { @@ -222,7 +241,10 @@ impl Entity for CalendarGroupRoot { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct CalendarRepeatRule { pub _id: CustomId, pub endType: i64, @@ -233,7 +255,6 @@ pub struct CalendarRepeatRule { pub excludedDates: Vec, pub _finalIvs: HashMap, } - impl Entity for CalendarRepeatRule { fn type_ref() -> TypeRef { TypeRef { @@ -243,7 +264,10 @@ impl Entity for CalendarRepeatRule { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct Contact { pub _format: i64, pub _id: IdTuple, @@ -282,7 +306,6 @@ pub struct Contact { pub _errors: Option, pub _finalIvs: HashMap, } - impl Entity for Contact { fn type_ref() -> TypeRef { TypeRef { @@ -292,7 +315,10 @@ impl Entity for Contact { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct ContactAddress { pub _id: CustomId, pub address: String, @@ -301,7 +327,6 @@ pub struct ContactAddress { pub r#type: i64, pub _finalIvs: HashMap, } - impl Entity for ContactAddress { fn type_ref() -> TypeRef { TypeRef { @@ -311,7 +336,10 @@ impl Entity for ContactAddress { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct ContactCustomDate { pub _id: CustomId, pub customTypeName: String, @@ -320,7 +348,6 @@ pub struct ContactCustomDate { pub r#type: i64, pub _finalIvs: HashMap, } - impl Entity for ContactCustomDate { fn type_ref() -> TypeRef { TypeRef { @@ -330,7 +357,10 @@ impl Entity for ContactCustomDate { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct ContactList { pub _format: i64, pub _id: GeneratedId, @@ -344,7 +374,6 @@ pub struct ContactList { pub _errors: Option, pub _finalIvs: HashMap, } - impl Entity for ContactList { fn type_ref() -> TypeRef { TypeRef { @@ -354,7 +383,10 @@ impl Entity for ContactList { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct ContactListEntry { pub _format: i64, pub _id: IdTuple, @@ -367,7 +399,6 @@ pub struct ContactListEntry { pub _errors: Option, pub _finalIvs: HashMap, } - impl Entity for ContactListEntry { fn type_ref() -> TypeRef { TypeRef { @@ -377,7 +408,10 @@ impl Entity for ContactListEntry { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct ContactListGroupRoot { pub _format: i64, pub _id: GeneratedId, @@ -390,7 +424,6 @@ pub struct ContactListGroupRoot { pub _errors: Option, pub _finalIvs: HashMap, } - impl Entity for ContactListGroupRoot { fn type_ref() -> TypeRef { TypeRef { @@ -400,7 +433,10 @@ impl Entity for ContactListGroupRoot { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct ContactMailAddress { pub _id: CustomId, pub address: String, @@ -409,7 +445,6 @@ pub struct ContactMailAddress { pub r#type: i64, pub _finalIvs: HashMap, } - impl Entity for ContactMailAddress { fn type_ref() -> TypeRef { TypeRef { @@ -419,7 +454,10 @@ impl Entity for ContactMailAddress { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct ContactMessengerHandle { pub _id: CustomId, pub customTypeName: String, @@ -428,7 +466,6 @@ pub struct ContactMessengerHandle { pub r#type: i64, pub _finalIvs: HashMap, } - impl Entity for ContactMessengerHandle { fn type_ref() -> TypeRef { TypeRef { @@ -438,7 +475,10 @@ impl Entity for ContactMessengerHandle { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct ContactPhoneNumber { pub _id: CustomId, pub customTypeName: String, @@ -447,7 +487,6 @@ pub struct ContactPhoneNumber { pub r#type: i64, pub _finalIvs: HashMap, } - impl Entity for ContactPhoneNumber { fn type_ref() -> TypeRef { TypeRef { @@ -457,14 +496,16 @@ impl Entity for ContactPhoneNumber { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct ContactPronouns { pub _id: CustomId, pub language: String, pub pronouns: String, pub _finalIvs: HashMap, } - impl Entity for ContactPronouns { fn type_ref() -> TypeRef { TypeRef { @@ -474,7 +515,10 @@ impl Entity for ContactPronouns { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct ContactRelationship { pub _id: CustomId, pub customTypeName: String, @@ -483,7 +527,6 @@ pub struct ContactRelationship { pub r#type: i64, pub _finalIvs: HashMap, } - impl Entity for ContactRelationship { fn type_ref() -> TypeRef { TypeRef { @@ -493,7 +536,10 @@ impl Entity for ContactRelationship { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct ContactSocialId { pub _id: CustomId, pub customTypeName: String, @@ -502,7 +548,6 @@ pub struct ContactSocialId { pub r#type: i64, pub _finalIvs: HashMap, } - impl Entity for ContactSocialId { fn type_ref() -> TypeRef { TypeRef { @@ -512,7 +557,10 @@ impl Entity for ContactSocialId { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct ContactWebsite { pub _id: CustomId, pub customTypeName: String, @@ -521,7 +569,6 @@ pub struct ContactWebsite { pub url: String, pub _finalIvs: HashMap, } - impl Entity for ContactWebsite { fn type_ref() -> TypeRef { TypeRef { @@ -531,7 +578,10 @@ impl Entity for ContactWebsite { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct ConversationEntry { pub _format: i64, pub _id: IdTuple, @@ -542,7 +592,6 @@ pub struct ConversationEntry { pub mail: Option, pub previous: Option, } - impl Entity for ConversationEntry { fn type_ref() -> TypeRef { TypeRef { @@ -552,7 +601,10 @@ impl Entity for ConversationEntry { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct CreateExternalUserGroupData { pub _id: CustomId, #[serde(with = "serde_bytes")] @@ -562,7 +614,6 @@ pub struct CreateExternalUserGroupData { pub internalUserGroupKeyVersion: i64, pub mailAddress: String, } - impl Entity for CreateExternalUserGroupData { fn type_ref() -> TypeRef { TypeRef { @@ -572,14 +623,16 @@ impl Entity for CreateExternalUserGroupData { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct CreateGroupPostReturn { pub _format: i64, pub group: GeneratedId, pub _errors: Option, pub _finalIvs: HashMap, } - impl Entity for CreateGroupPostReturn { fn type_ref() -> TypeRef { TypeRef { @@ -589,7 +642,10 @@ impl Entity for CreateGroupPostReturn { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct CreateMailFolderData { pub _format: i64, pub folderName: String, @@ -601,7 +657,6 @@ pub struct CreateMailFolderData { pub _errors: Option, pub _finalIvs: HashMap, } - impl Entity for CreateMailFolderData { fn type_ref() -> TypeRef { TypeRef { @@ -611,14 +666,16 @@ impl Entity for CreateMailFolderData { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct CreateMailFolderReturn { pub _format: i64, pub newFolder: IdTuple, pub _errors: Option, pub _finalIvs: HashMap, } - impl Entity for CreateMailFolderReturn { fn type_ref() -> TypeRef { TypeRef { @@ -628,7 +685,10 @@ impl Entity for CreateMailFolderReturn { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct CreateMailGroupData { pub _format: i64, #[serde(with = "serde_bytes")] @@ -638,7 +698,6 @@ pub struct CreateMailGroupData { pub mailEncMailboxSessionKey: Vec, pub groupData: InternalGroupData, } - impl Entity for CreateMailGroupData { fn type_ref() -> TypeRef { TypeRef { @@ -648,7 +707,10 @@ impl Entity for CreateMailGroupData { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct CustomerAccountCreateData { pub _format: i64, pub accountGroupKeyVersion: i64, @@ -673,7 +735,6 @@ pub struct CustomerAccountCreateData { pub userData: UserAccountUserData, pub userGroupData: InternalGroupData, } - impl Entity for CustomerAccountCreateData { fn type_ref() -> TypeRef { TypeRef { @@ -683,13 +744,15 @@ impl Entity for CustomerAccountCreateData { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct DefaultAlarmInfo { pub _id: CustomId, pub trigger: String, pub _finalIvs: HashMap, } - impl Entity for DefaultAlarmInfo { fn type_ref() -> TypeRef { TypeRef { @@ -699,13 +762,15 @@ impl Entity for DefaultAlarmInfo { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct DeleteGroupData { pub _format: i64, pub restore: bool, pub group: GeneratedId, } - impl Entity for DeleteGroupData { fn type_ref() -> TypeRef { TypeRef { @@ -715,13 +780,15 @@ impl Entity for DeleteGroupData { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct DeleteMailData { pub _format: i64, pub folder: Option, pub mails: Vec, } - impl Entity for DeleteMailData { fn type_ref() -> TypeRef { TypeRef { @@ -731,14 +798,16 @@ impl Entity for DeleteMailData { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct DeleteMailFolderData { pub _format: i64, pub folders: Vec, pub _errors: Option, pub _finalIvs: HashMap, } - impl Entity for DeleteMailFolderData { fn type_ref() -> TypeRef { TypeRef { @@ -748,7 +817,10 @@ impl Entity for DeleteMailFolderData { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct DraftAttachment { pub _id: CustomId, #[serde(with = "serde_bytes")] @@ -757,7 +829,6 @@ pub struct DraftAttachment { pub existingFile: Option, pub newFile: Option, } - impl Entity for DraftAttachment { fn type_ref() -> TypeRef { TypeRef { @@ -767,7 +838,10 @@ impl Entity for DraftAttachment { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct DraftCreateData { pub _format: i64, pub conversationType: i64, @@ -779,7 +853,6 @@ pub struct DraftCreateData { pub _errors: Option, pub _finalIvs: HashMap, } - impl Entity for DraftCreateData { fn type_ref() -> TypeRef { TypeRef { @@ -789,12 +862,14 @@ impl Entity for DraftCreateData { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct DraftCreateReturn { pub _format: i64, pub draft: IdTuple, } - impl Entity for DraftCreateReturn { fn type_ref() -> TypeRef { TypeRef { @@ -804,7 +879,10 @@ impl Entity for DraftCreateReturn { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct DraftData { pub _id: CustomId, pub bodyText: String, @@ -822,7 +900,6 @@ pub struct DraftData { pub toRecipients: Vec, pub _finalIvs: HashMap, } - impl Entity for DraftData { fn type_ref() -> TypeRef { TypeRef { @@ -832,14 +909,16 @@ impl Entity for DraftData { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct DraftRecipient { pub _id: CustomId, pub mailAddress: String, pub name: String, pub _finalIvs: HashMap, } - impl Entity for DraftRecipient { fn type_ref() -> TypeRef { TypeRef { @@ -849,7 +928,10 @@ impl Entity for DraftRecipient { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct DraftUpdateData { pub _format: i64, pub draft: IdTuple, @@ -857,7 +939,6 @@ pub struct DraftUpdateData { pub _errors: Option, pub _finalIvs: HashMap, } - impl Entity for DraftUpdateData { fn type_ref() -> TypeRef { TypeRef { @@ -867,14 +948,16 @@ impl Entity for DraftUpdateData { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct DraftUpdateReturn { pub _format: i64, pub attachments: Vec, pub _errors: Option, pub _finalIvs: HashMap, } - impl Entity for DraftUpdateReturn { fn type_ref() -> TypeRef { TypeRef { @@ -884,7 +967,10 @@ impl Entity for DraftUpdateReturn { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct EmailTemplate { pub _format: i64, pub _id: IdTuple, @@ -899,7 +985,6 @@ pub struct EmailTemplate { pub _errors: Option, pub _finalIvs: HashMap, } - impl Entity for EmailTemplate { fn type_ref() -> TypeRef { TypeRef { @@ -909,14 +994,16 @@ impl Entity for EmailTemplate { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct EmailTemplateContent { pub _id: CustomId, pub languageCode: String, pub text: String, pub _finalIvs: HashMap, } - impl Entity for EmailTemplateContent { fn type_ref() -> TypeRef { TypeRef { @@ -926,7 +1013,10 @@ impl Entity for EmailTemplateContent { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct EncryptTutanotaPropertiesData { pub _format: i64, #[serde(with = "serde_bytes")] @@ -934,7 +1024,6 @@ pub struct EncryptTutanotaPropertiesData { pub symKeyVersion: i64, pub properties: GeneratedId, } - impl Entity for EncryptTutanotaPropertiesData { fn type_ref() -> TypeRef { TypeRef { @@ -944,14 +1033,16 @@ impl Entity for EncryptTutanotaPropertiesData { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct EncryptedMailAddress { pub _id: CustomId, pub address: String, pub name: String, pub _finalIvs: HashMap, } - impl Entity for EncryptedMailAddress { fn type_ref() -> TypeRef { TypeRef { @@ -961,14 +1052,16 @@ impl Entity for EncryptedMailAddress { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct EntropyData { pub _format: i64, #[serde(with = "serde_bytes")] pub userEncEntropy: Vec, pub userKeyVersion: i64, } - impl Entity for EntropyData { fn type_ref() -> TypeRef { TypeRef { @@ -978,7 +1071,10 @@ impl Entity for EntropyData { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct ExternalUserData { pub _format: i64, #[serde(with = "serde_bytes")] @@ -1003,7 +1099,6 @@ pub struct ExternalUserData { pub verifier: Vec, pub userGroupData: CreateExternalUserGroupData, } - impl Entity for ExternalUserData { fn type_ref() -> TypeRef { TypeRef { @@ -1013,7 +1108,10 @@ impl Entity for ExternalUserData { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct TutanotaFile { pub _format: i64, pub _id: IdTuple, @@ -1032,7 +1130,6 @@ pub struct TutanotaFile { pub _errors: Option, pub _finalIvs: HashMap, } - impl Entity for TutanotaFile { fn type_ref() -> TypeRef { TypeRef { @@ -1042,7 +1139,10 @@ impl Entity for TutanotaFile { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct FileSystem { pub _format: i64, pub _id: GeneratedId, @@ -1055,7 +1155,6 @@ pub struct FileSystem { pub _errors: Option, pub _finalIvs: HashMap, } - impl Entity for FileSystem { fn type_ref() -> TypeRef { TypeRef { @@ -1065,12 +1164,14 @@ impl Entity for FileSystem { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct GroupInvitationDeleteData { pub _format: i64, pub receivedInvitation: IdTuple, } - impl Entity for GroupInvitationDeleteData { fn type_ref() -> TypeRef { TypeRef { @@ -1080,13 +1181,15 @@ impl Entity for GroupInvitationDeleteData { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct GroupInvitationPostData { pub _format: i64, pub internalKeyData: Vec, pub sharedGroupData: SharedGroupData, } - impl Entity for GroupInvitationPostData { fn type_ref() -> TypeRef { TypeRef { @@ -1096,14 +1199,16 @@ impl Entity for GroupInvitationPostData { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct GroupInvitationPostReturn { pub _format: i64, pub existingMailAddresses: Vec, pub invalidMailAddresses: Vec, pub invitedMailAddresses: Vec, } - impl Entity for GroupInvitationPostReturn { fn type_ref() -> TypeRef { TypeRef { @@ -1113,7 +1218,10 @@ impl Entity for GroupInvitationPostReturn { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct GroupInvitationPutData { pub _format: i64, #[serde(with = "serde_bytes")] @@ -1124,7 +1232,6 @@ pub struct GroupInvitationPutData { pub userGroupKeyVersion: i64, pub receivedInvitation: IdTuple, } - impl Entity for GroupInvitationPutData { fn type_ref() -> TypeRef { TypeRef { @@ -1134,7 +1241,10 @@ impl Entity for GroupInvitationPutData { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct GroupSettings { pub _id: CustomId, pub color: String, @@ -1144,7 +1254,6 @@ pub struct GroupSettings { pub group: GeneratedId, pub _finalIvs: HashMap, } - impl Entity for GroupSettings { fn type_ref() -> TypeRef { TypeRef { @@ -1154,14 +1263,16 @@ impl Entity for GroupSettings { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct Header { pub _id: CustomId, pub compressedHeaders: Option>, pub headers: Option, pub _finalIvs: HashMap, } - impl Entity for Header { fn type_ref() -> TypeRef { TypeRef { @@ -1171,7 +1282,10 @@ impl Entity for Header { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct ImapFolder { pub _id: CustomId, pub lastseenuid: String, @@ -1179,7 +1293,6 @@ pub struct ImapFolder { pub uidvalidity: String, pub syncInfo: GeneratedId, } - impl Entity for ImapFolder { fn type_ref() -> TypeRef { TypeRef { @@ -1189,7 +1302,10 @@ impl Entity for ImapFolder { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct ImapSyncConfiguration { pub _id: CustomId, pub host: String, @@ -1198,7 +1314,6 @@ pub struct ImapSyncConfiguration { pub user: String, pub imapSyncState: Option, } - impl Entity for ImapSyncConfiguration { fn type_ref() -> TypeRef { TypeRef { @@ -1208,7 +1323,10 @@ impl Entity for ImapSyncConfiguration { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct ImapSyncState { pub _format: i64, pub _id: GeneratedId, @@ -1216,7 +1334,6 @@ pub struct ImapSyncState { pub _permissions: GeneratedId, pub folders: Vec, } - impl Entity for ImapSyncState { fn type_ref() -> TypeRef { TypeRef { @@ -1226,7 +1343,10 @@ impl Entity for ImapSyncState { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct InboxRule { pub _id: CustomId, #[serde(rename = "type")] @@ -1235,7 +1355,6 @@ pub struct InboxRule { pub targetFolder: IdTuple, pub _finalIvs: HashMap, } - impl Entity for InboxRule { fn type_ref() -> TypeRef { TypeRef { @@ -1245,7 +1364,10 @@ impl Entity for InboxRule { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct InternalGroupData { pub _id: CustomId, #[serde(with = "serde_bytes")] @@ -1268,7 +1390,6 @@ pub struct InternalGroupData { pub pubRsaKey: Option>, pub adminGroup: Option, } - impl Entity for InternalGroupData { fn type_ref() -> TypeRef { TypeRef { @@ -1278,7 +1399,10 @@ impl Entity for InternalGroupData { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct InternalRecipientKeyData { pub _id: CustomId, pub mailAddress: String, @@ -1288,7 +1412,6 @@ pub struct InternalRecipientKeyData { pub recipientKeyVersion: i64, pub senderKeyVersion: Option, } - impl Entity for InternalRecipientKeyData { fn type_ref() -> TypeRef { TypeRef { @@ -1298,7 +1421,10 @@ impl Entity for InternalRecipientKeyData { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct KnowledgeBaseEntry { pub _format: i64, pub _id: IdTuple, @@ -1313,7 +1439,6 @@ pub struct KnowledgeBaseEntry { pub _errors: Option, pub _finalIvs: HashMap, } - impl Entity for KnowledgeBaseEntry { fn type_ref() -> TypeRef { TypeRef { @@ -1323,13 +1448,15 @@ impl Entity for KnowledgeBaseEntry { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct KnowledgeBaseEntryKeyword { pub _id: CustomId, pub keyword: String, pub _finalIvs: HashMap, } - impl Entity for KnowledgeBaseEntryKeyword { fn type_ref() -> TypeRef { TypeRef { @@ -1339,14 +1466,16 @@ impl Entity for KnowledgeBaseEntryKeyword { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct ListUnsubscribeData { pub _format: i64, pub headers: String, pub recipient: String, pub mail: IdTuple, } - impl Entity for ListUnsubscribeData { fn type_ref() -> TypeRef { TypeRef { @@ -1356,7 +1485,10 @@ impl Entity for ListUnsubscribeData { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct Mail { pub _format: i64, pub _id: IdTuple, @@ -1390,7 +1522,6 @@ pub struct Mail { pub _errors: Option, pub _finalIvs: HashMap, } - impl Entity for Mail { fn type_ref() -> TypeRef { TypeRef { @@ -1400,7 +1531,10 @@ impl Entity for Mail { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct MailAddress { pub _id: CustomId, pub address: String, @@ -1408,7 +1542,6 @@ pub struct MailAddress { pub contact: Option, pub _finalIvs: HashMap, } - impl Entity for MailAddress { fn type_ref() -> TypeRef { TypeRef { @@ -1418,14 +1551,16 @@ impl Entity for MailAddress { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct MailAddressProperties { pub _id: CustomId, pub mailAddress: String, pub senderName: String, pub _finalIvs: HashMap, } - impl Entity for MailAddressProperties { fn type_ref() -> TypeRef { TypeRef { @@ -1435,12 +1570,14 @@ impl Entity for MailAddressProperties { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct MailBag { pub _id: CustomId, pub mails: GeneratedId, } - impl Entity for MailBag { fn type_ref() -> TypeRef { TypeRef { @@ -1450,7 +1587,10 @@ impl Entity for MailBag { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct MailBox { pub _format: i64, pub _id: GeneratedId, @@ -1470,7 +1610,6 @@ pub struct MailBox { pub _errors: Option, pub _finalIvs: HashMap, } - impl Entity for MailBox { fn type_ref() -> TypeRef { TypeRef { @@ -1480,7 +1619,10 @@ impl Entity for MailBox { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct MailDetails { pub _id: CustomId, pub authStatus: i64, @@ -1490,7 +1632,6 @@ pub struct MailDetails { pub recipients: Recipients, pub replyTos: Vec, } - impl Entity for MailDetails { fn type_ref() -> TypeRef { TypeRef { @@ -1500,7 +1641,10 @@ impl Entity for MailDetails { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct MailDetailsBlob { pub _format: i64, pub _id: IdTuple, @@ -1513,7 +1657,6 @@ pub struct MailDetailsBlob { pub _errors: Option, pub _finalIvs: HashMap, } - impl Entity for MailDetailsBlob { fn type_ref() -> TypeRef { TypeRef { @@ -1523,7 +1666,10 @@ impl Entity for MailDetailsBlob { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct MailDetailsDraft { pub _format: i64, pub _id: IdTuple, @@ -1536,7 +1682,6 @@ pub struct MailDetailsDraft { pub _errors: Option, pub _finalIvs: HashMap, } - impl Entity for MailDetailsDraft { fn type_ref() -> TypeRef { TypeRef { @@ -1546,12 +1691,14 @@ impl Entity for MailDetailsDraft { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct MailDetailsDraftsRef { pub _id: CustomId, pub list: GeneratedId, } - impl Entity for MailDetailsDraftsRef { fn type_ref() -> TypeRef { TypeRef { @@ -1561,7 +1708,10 @@ impl Entity for MailDetailsDraftsRef { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct MailFolder { pub _format: i64, pub _id: IdTuple, @@ -1580,7 +1730,6 @@ pub struct MailFolder { pub _errors: Option, pub _finalIvs: HashMap, } - impl Entity for MailFolder { fn type_ref() -> TypeRef { TypeRef { @@ -1590,12 +1739,14 @@ impl Entity for MailFolder { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct MailFolderRef { pub _id: CustomId, pub folders: GeneratedId, } - impl Entity for MailFolderRef { fn type_ref() -> TypeRef { TypeRef { @@ -1605,7 +1756,10 @@ impl Entity for MailFolderRef { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct MailSetEntry { pub _format: i64, pub _id: IdTuple, @@ -1613,7 +1767,6 @@ pub struct MailSetEntry { pub _permissions: GeneratedId, pub mail: IdTuple, } - impl Entity for MailSetEntry { fn type_ref() -> TypeRef { TypeRef { @@ -1623,7 +1776,10 @@ impl Entity for MailSetEntry { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct MailboxGroupRoot { pub _format: i64, pub _id: GeneratedId, @@ -1637,7 +1793,6 @@ pub struct MailboxGroupRoot { pub serverProperties: GeneratedId, pub whitelistRequests: GeneratedId, } - impl Entity for MailboxGroupRoot { fn type_ref() -> TypeRef { TypeRef { @@ -1647,7 +1802,10 @@ impl Entity for MailboxGroupRoot { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct MailboxProperties { pub _format: i64, pub _id: GeneratedId, @@ -1661,7 +1819,6 @@ pub struct MailboxProperties { pub _errors: Option, pub _finalIvs: HashMap, } - impl Entity for MailboxProperties { fn type_ref() -> TypeRef { TypeRef { @@ -1671,7 +1828,10 @@ impl Entity for MailboxProperties { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct MailboxServerProperties { pub _format: i64, pub _id: GeneratedId, @@ -1679,7 +1839,6 @@ pub struct MailboxServerProperties { pub _permissions: GeneratedId, pub whitelistProtectionEnabled: bool, } - impl Entity for MailboxServerProperties { fn type_ref() -> TypeRef { TypeRef { @@ -1689,14 +1848,16 @@ impl Entity for MailboxServerProperties { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct MoveMailData { pub _format: i64, pub mails: Vec, pub sourceFolder: Option, pub targetFolder: IdTuple, } - impl Entity for MoveMailData { fn type_ref() -> TypeRef { TypeRef { @@ -1706,7 +1867,10 @@ impl Entity for MoveMailData { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct NewDraftAttachment { pub _id: CustomId, #[serde(with = "serde_bytes")] @@ -1717,7 +1881,6 @@ pub struct NewDraftAttachment { pub encMimeType: Vec, pub referenceTokens: Vec, } - impl Entity for NewDraftAttachment { fn type_ref() -> TypeRef { TypeRef { @@ -1727,13 +1890,15 @@ impl Entity for NewDraftAttachment { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct NewsId { pub _id: CustomId, pub newsItemId: GeneratedId, pub newsItemName: String, } - impl Entity for NewsId { fn type_ref() -> TypeRef { TypeRef { @@ -1743,12 +1908,14 @@ impl Entity for NewsId { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct NewsIn { pub _format: i64, pub newsItemId: Option, } - impl Entity for NewsIn { fn type_ref() -> TypeRef { TypeRef { @@ -1758,12 +1925,14 @@ impl Entity for NewsIn { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct NewsOut { pub _format: i64, pub newsItemIds: Vec, } - impl Entity for NewsOut { fn type_ref() -> TypeRef { TypeRef { @@ -1773,7 +1942,10 @@ impl Entity for NewsOut { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct NotificationMail { pub _id: CustomId, pub bodyText: String, @@ -1782,7 +1954,6 @@ pub struct NotificationMail { pub recipientName: String, pub subject: String, } - impl Entity for NotificationMail { fn type_ref() -> TypeRef { TypeRef { @@ -1792,7 +1963,10 @@ impl Entity for NotificationMail { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct OutOfOfficeNotification { pub _format: i64, pub _id: GeneratedId, @@ -1803,7 +1977,6 @@ pub struct OutOfOfficeNotification { pub startDate: Option, pub notifications: Vec, } - impl Entity for OutOfOfficeNotification { fn type_ref() -> TypeRef { TypeRef { @@ -1813,7 +1986,10 @@ impl Entity for OutOfOfficeNotification { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct OutOfOfficeNotificationMessage { pub _id: CustomId, pub message: String, @@ -1821,7 +1997,6 @@ pub struct OutOfOfficeNotificationMessage { #[serde(rename = "type")] pub r#type: i64, } - impl Entity for OutOfOfficeNotificationMessage { fn type_ref() -> TypeRef { TypeRef { @@ -1831,12 +2006,14 @@ impl Entity for OutOfOfficeNotificationMessage { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct OutOfOfficeNotificationRecipientList { pub _id: CustomId, pub list: GeneratedId, } - impl Entity for OutOfOfficeNotificationRecipientList { fn type_ref() -> TypeRef { TypeRef { @@ -1846,13 +2023,15 @@ impl Entity for OutOfOfficeNotificationRecipientList { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct PhishingMarkerWebsocketData { pub _format: i64, pub lastId: GeneratedId, pub markers: Vec, } - impl Entity for PhishingMarkerWebsocketData { fn type_ref() -> TypeRef { TypeRef { @@ -1862,12 +2041,14 @@ impl Entity for PhishingMarkerWebsocketData { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct PhotosRef { pub _id: CustomId, pub files: GeneratedId, } - impl Entity for PhotosRef { fn type_ref() -> TypeRef { TypeRef { @@ -1877,12 +2058,14 @@ impl Entity for PhotosRef { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct ReceiveInfoServiceData { pub _format: i64, pub language: String, } - impl Entity for ReceiveInfoServiceData { fn type_ref() -> TypeRef { TypeRef { @@ -1892,14 +2075,16 @@ impl Entity for ReceiveInfoServiceData { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct Recipients { pub _id: CustomId, pub bccRecipients: Vec, pub ccRecipients: Vec, pub toRecipients: Vec, } - impl Entity for Recipients { fn type_ref() -> TypeRef { TypeRef { @@ -1909,7 +2094,10 @@ impl Entity for Recipients { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct RemoteImapSyncInfo { pub _format: i64, pub _id: IdTuple, @@ -1918,7 +2106,6 @@ pub struct RemoteImapSyncInfo { pub seen: bool, pub message: IdTuple, } - impl Entity for RemoteImapSyncInfo { fn type_ref() -> TypeRef { TypeRef { @@ -1928,7 +2115,10 @@ impl Entity for RemoteImapSyncInfo { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct ReportMailPostData { pub _format: i64, #[serde(with = "serde_bytes")] @@ -1936,7 +2126,6 @@ pub struct ReportMailPostData { pub reportType: i64, pub mailId: IdTuple, } - impl Entity for ReportMailPostData { fn type_ref() -> TypeRef { TypeRef { @@ -1946,13 +2135,15 @@ impl Entity for ReportMailPostData { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct ReportedMailFieldMarker { pub _id: CustomId, pub marker: String, pub status: i64, } - impl Entity for ReportedMailFieldMarker { fn type_ref() -> TypeRef { TypeRef { @@ -1962,7 +2153,10 @@ impl Entity for ReportedMailFieldMarker { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct SecureExternalRecipientKeyData { pub _id: CustomId, pub kdfVersion: i64, @@ -1980,7 +2174,6 @@ pub struct SecureExternalRecipientKeyData { pub saltHash: Option>, pub userGroupKeyVersion: i64, } - impl Entity for SecureExternalRecipientKeyData { fn type_ref() -> TypeRef { TypeRef { @@ -1990,7 +2183,10 @@ impl Entity for SecureExternalRecipientKeyData { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct SendDraftData { pub _format: i64, #[serde(with = "serde_bytes")] @@ -2009,7 +2205,6 @@ pub struct SendDraftData { pub secureExternalRecipientKeyData: Vec, pub symEncInternalRecipientKeyData: Vec, } - impl Entity for SendDraftData { fn type_ref() -> TypeRef { TypeRef { @@ -2019,7 +2214,10 @@ impl Entity for SendDraftData { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct SendDraftReturn { pub _format: i64, pub messageId: String, @@ -2027,7 +2225,6 @@ pub struct SendDraftReturn { pub notifications: Vec, pub sentMail: IdTuple, } - impl Entity for SendDraftReturn { fn type_ref() -> TypeRef { TypeRef { @@ -2037,7 +2234,10 @@ impl Entity for SendDraftReturn { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct SharedGroupData { pub _id: CustomId, #[serde(with = "serde_bytes")] @@ -2056,7 +2256,6 @@ pub struct SharedGroupData { pub sharedGroupEncSharedGroupInfoKey: Vec, pub sharedGroupKeyVersion: i64, } - impl Entity for SharedGroupData { fn type_ref() -> TypeRef { TypeRef { @@ -2066,12 +2265,14 @@ impl Entity for SharedGroupData { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct SpamResults { pub _id: CustomId, pub list: GeneratedId, } - impl Entity for SpamResults { fn type_ref() -> TypeRef { TypeRef { @@ -2081,12 +2282,14 @@ impl Entity for SpamResults { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct Subfiles { pub _id: CustomId, pub files: GeneratedId, } - impl Entity for Subfiles { fn type_ref() -> TypeRef { TypeRef { @@ -2096,7 +2299,10 @@ impl Entity for Subfiles { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct SymEncInternalRecipientKeyData { pub _id: CustomId, pub mailAddress: String, @@ -2105,7 +2311,6 @@ pub struct SymEncInternalRecipientKeyData { pub symKeyVersion: i64, pub keyGroup: GeneratedId, } - impl Entity for SymEncInternalRecipientKeyData { fn type_ref() -> TypeRef { TypeRef { @@ -2115,7 +2320,10 @@ impl Entity for SymEncInternalRecipientKeyData { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct TemplateGroupRoot { pub _format: i64, pub _id: GeneratedId, @@ -2129,7 +2337,6 @@ pub struct TemplateGroupRoot { pub _errors: Option, pub _finalIvs: HashMap, } - impl Entity for TemplateGroupRoot { fn type_ref() -> TypeRef { TypeRef { @@ -2139,12 +2346,14 @@ impl Entity for TemplateGroupRoot { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct TranslationGetIn { pub _format: i64, pub lang: String, } - impl Entity for TranslationGetIn { fn type_ref() -> TypeRef { TypeRef { @@ -2154,13 +2363,15 @@ impl Entity for TranslationGetIn { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct TranslationGetOut { pub _format: i64, pub giftCardSubject: String, pub invitationSubject: String, } - impl Entity for TranslationGetOut { fn type_ref() -> TypeRef { TypeRef { @@ -2170,7 +2381,10 @@ impl Entity for TranslationGetOut { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct TutanotaProperties { pub _format: i64, pub _id: GeneratedId, @@ -2196,7 +2410,6 @@ pub struct TutanotaProperties { pub _errors: Option, pub _finalIvs: HashMap, } - impl Entity for TutanotaProperties { fn type_ref() -> TypeRef { TypeRef { @@ -2206,13 +2419,15 @@ impl Entity for TutanotaProperties { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct UpdateMailFolderData { pub _format: i64, pub folder: IdTuple, pub newParent: Option, } - impl Entity for UpdateMailFolderData { fn type_ref() -> TypeRef { TypeRef { @@ -2222,14 +2437,16 @@ impl Entity for UpdateMailFolderData { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct UserAccountCreateData { pub _format: i64, pub date: Option, pub userData: UserAccountUserData, pub userGroupData: InternalGroupData, } - impl Entity for UserAccountCreateData { fn type_ref() -> TypeRef { TypeRef { @@ -2239,7 +2456,10 @@ impl Entity for UserAccountCreateData { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct UserAccountUserData { pub _id: CustomId, #[serde(with = "serde_bytes")] @@ -2284,7 +2504,6 @@ pub struct UserAccountUserData { #[serde(with = "serde_bytes")] pub verifier: Vec, } - impl Entity for UserAccountUserData { fn type_ref() -> TypeRef { TypeRef { @@ -2294,7 +2513,10 @@ impl Entity for UserAccountUserData { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct UserAreaGroupData { pub _id: CustomId, #[serde(with = "serde_bytes")] @@ -2312,7 +2534,6 @@ pub struct UserAreaGroupData { pub userKeyVersion: i64, pub adminGroup: Option, } - impl Entity for UserAreaGroupData { fn type_ref() -> TypeRef { TypeRef { @@ -2322,12 +2543,14 @@ impl Entity for UserAreaGroupData { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct UserAreaGroupDeleteData { pub _format: i64, pub group: GeneratedId, } - impl Entity for UserAreaGroupDeleteData { fn type_ref() -> TypeRef { TypeRef { @@ -2337,12 +2560,14 @@ impl Entity for UserAreaGroupDeleteData { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct UserAreaGroupPostData { pub _format: i64, pub groupData: UserAreaGroupData, } - impl Entity for UserAreaGroupPostData { fn type_ref() -> TypeRef { TypeRef { @@ -2352,7 +2577,10 @@ impl Entity for UserAreaGroupPostData { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct UserSettingsGroupRoot { pub _format: i64, pub _id: GeneratedId, @@ -2368,7 +2596,6 @@ pub struct UserSettingsGroupRoot { pub _errors: Option, pub _finalIvs: HashMap, } - impl Entity for UserSettingsGroupRoot { fn type_ref() -> TypeRef { TypeRef { @@ -2377,3 +2604,6 @@ impl Entity for UserSettingsGroupRoot { } } } + + + diff --git a/tuta-sdk/rust/sdk/src/entities/usage.rs b/tuta-sdk/rust/sdk/src/entities/usage.rs index 30c6ca12856c..29498be13e2e 100644 --- a/tuta-sdk/rust/sdk/src/entities/usage.rs +++ b/tuta-sdk/rust/sdk/src/entities/usage.rs @@ -2,7 +2,7 @@ use super::*; use serde::{Deserialize, Serialize}; -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct UsageTestAssignment { pub _id: CustomId, pub name: String, @@ -11,7 +11,6 @@ pub struct UsageTestAssignment { pub variant: Option, pub stages: Vec, } - impl Entity for UsageTestAssignment { fn type_ref() -> TypeRef { TypeRef { @@ -21,12 +20,14 @@ impl Entity for UsageTestAssignment { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct UsageTestAssignmentIn { pub _format: i64, pub testDeviceId: Option, } - impl Entity for UsageTestAssignmentIn { fn type_ref() -> TypeRef { TypeRef { @@ -36,13 +37,15 @@ impl Entity for UsageTestAssignmentIn { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct UsageTestAssignmentOut { pub _format: i64, pub testDeviceId: GeneratedId, pub assignments: Vec, } - impl Entity for UsageTestAssignmentOut { fn type_ref() -> TypeRef { TypeRef { @@ -52,7 +55,10 @@ impl Entity for UsageTestAssignmentOut { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct UsageTestMetricConfig { pub _id: CustomId, pub name: String, @@ -60,7 +66,6 @@ pub struct UsageTestMetricConfig { pub r#type: i64, pub configValues: Vec, } - impl Entity for UsageTestMetricConfig { fn type_ref() -> TypeRef { TypeRef { @@ -70,13 +75,15 @@ impl Entity for UsageTestMetricConfig { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct UsageTestMetricConfigValue { pub _id: CustomId, pub key: String, pub value: String, } - impl Entity for UsageTestMetricConfigValue { fn type_ref() -> TypeRef { TypeRef { @@ -86,13 +93,15 @@ impl Entity for UsageTestMetricConfigValue { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct UsageTestMetricData { pub _id: CustomId, pub name: String, pub value: String, } - impl Entity for UsageTestMetricData { fn type_ref() -> TypeRef { TypeRef { @@ -102,7 +111,10 @@ impl Entity for UsageTestMetricData { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct UsageTestParticipationIn { pub _format: i64, pub stage: i64, @@ -110,7 +122,6 @@ pub struct UsageTestParticipationIn { pub testId: GeneratedId, pub metrics: Vec, } - impl Entity for UsageTestParticipationIn { fn type_ref() -> TypeRef { TypeRef { @@ -120,7 +131,10 @@ impl Entity for UsageTestParticipationIn { } } -#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug)] + + + +#[derive(uniffi::Record, Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct UsageTestStage { pub _id: CustomId, pub maxPings: i64, @@ -128,7 +142,6 @@ pub struct UsageTestStage { pub name: String, pub metrics: Vec, } - impl Entity for UsageTestStage { fn type_ref() -> TypeRef { TypeRef { @@ -137,3 +150,6 @@ impl Entity for UsageTestStage { } } } + + + diff --git a/tuta-sdk/rust/sdk/src/entity_client.rs b/tuta-sdk/rust/sdk/src/entity_client.rs index 642be21fbb2a..53e07d0dda35 100644 --- a/tuta-sdk/rust/sdk/src/entity_client.rs +++ b/tuta-sdk/rust/sdk/src/entity_client.rs @@ -23,6 +23,12 @@ pub struct EntityClient { type_model_provider: Arc, } +impl EntityClient { + pub fn get_headers_provider(&self) -> &Arc { + &self.auth_headers_provider + } +} + impl EntityClient { #[allow(dead_code)] pub(crate) fn new( diff --git a/tuta-sdk/rust/sdk/src/instance_mapper.rs b/tuta-sdk/rust/sdk/src/instance_mapper.rs index ffdbc9ca7c69..5fbb68f5118e 100644 --- a/tuta-sdk/rust/sdk/src/instance_mapper.rs +++ b/tuta-sdk/rust/sdk/src/instance_mapper.rs @@ -30,7 +30,6 @@ impl InstanceMapper { T::deserialize(de) } - #[allow(unused)] // TODO: Remove this when implementing mutations for entities pub fn serialize_entity( &self, entity: T, @@ -564,36 +563,38 @@ impl Serializer for ElementValueSerializer { Ok(ElementValue::Bool(v)) } - fn serialize_i8(self, _: i8) -> Result { - unsupported("i8") + fn serialize_i8(self, v: i8) -> Result { + Ok(ElementValue::Number(v.into())) } - fn serialize_i16(self, _: i16) -> Result { - unsupported("i16") + fn serialize_i16(self, v: i16) -> Result { + Ok(ElementValue::Number(v.into())) } - fn serialize_i32(self, _: i32) -> Result { - unsupported("i32") + fn serialize_i32(self, v: i32) -> Result { + Ok(ElementValue::Number(v.into())) } fn serialize_i64(self, v: i64) -> Result { Ok(ElementValue::Number(v)) } - fn serialize_u8(self, _: u8) -> Result { - unsupported("u8") + fn serialize_u8(self, v: u8) -> Result { + Ok(ElementValue::Number(v.into())) } - fn serialize_u16(self, _: u16) -> Result { - unsupported("u16") + fn serialize_u16(self, v: u16) -> Result { + Ok(ElementValue::Number(v.into())) } fn serialize_u32(self, v: u32) -> Result { - Ok(ElementValue::Number(v as i64)) + Ok(ElementValue::Number(v.into())) } fn serialize_u64(self, v: u64) -> Result { - Ok(ElementValue::Number(v as i64)) + Ok(ElementValue::Number(v.try_into().map_err(|_| { + SerError(format!("Cannot convert u64 value: `{v}` to Number(i64)")) + })?)) } fn serialize_f32(self, _: f32) -> Result { diff --git a/tuta-sdk/rust/sdk/src/json_serializer.rs b/tuta-sdk/rust/sdk/src/json_serializer.rs index 3cf69efe8948..4422048fae3e 100644 --- a/tuta-sdk/rust/sdk/src/json_serializer.rs +++ b/tuta-sdk/rust/sdk/src/json_serializer.rs @@ -14,7 +14,6 @@ use crate::metamodel::{ AssociationType, Cardinality, ElementType, ModelValue, TypeModel, ValueType, }; use crate::type_model_provider::TypeModelProvider; -use crate::util::resolve_default_value; use crate::{IdTuple, TypeRef}; impl From<&TypeModel> for TypeRef { @@ -78,7 +77,7 @@ impl JsonSerializer { if value_type.encrypted { ElementValue::String(String::new()) } else { - resolve_default_value(&value_type.value_type) + value_type.value_type.get_default() } }, (Cardinality::One | Cardinality::ZeroOrOne, JsonElement::String(s)) @@ -269,14 +268,11 @@ impl JsonSerializer { let serialized_value = self.serialize_value(type_model, &value_name, value_type, value)?; mapped.insert(value_name, serialized_value); - } else if let ElementValue::Null = value { - mapped.insert(value_name, JsonElement::Null); - continue; - } else if let (ElementValue::String(v), true) = (value, value_type.encrypted) { - mapped.insert(value_name, JsonElement::String(v)); - continue; } else { - panic!("Unknown entity elements!! {}", value_name) + mapped.insert( + value_name.to_string(), + self.serialize_value(type_model, value_name.as_str(), value_type, value)?, + ); } } @@ -427,6 +423,11 @@ impl JsonSerializer { ElementValue::String(v), ElementType::Element | ElementType::Aggregated, ) => Ok(JsonElement::String(v)), + ( + ValueType::GeneratedId | ValueType::CustomId, + ElementValue::IdCustomId(v), + ElementType::Element | ElementType::Aggregated, + ) => Ok(JsonElement::String(v.to_string())), ( ValueType::GeneratedId | ValueType::CustomId, ElementValue::IdTupleId(arr), @@ -435,6 +436,7 @@ impl JsonSerializer { JsonElement::String(arr.list_id.into()), JsonElement::String(arr.element_id.into()), ])), + _ => invalid_value(), }; } diff --git a/tuta-sdk/rust/sdk/src/key_loader_facade.rs b/tuta-sdk/rust/sdk/src/key_loader_facade.rs index 143d68e4e24e..288519538ec7 100644 --- a/tuta-sdk/rust/sdk/src/key_loader_facade.rs +++ b/tuta-sdk/rust/sdk/src/key_loader_facade.rs @@ -2,9 +2,9 @@ use crate::crypto::key::{AsymmetricKeyPair, GenericAesKey, KeyLoadError}; use crate::crypto::key_encryption::decrypt_key_pair; use crate::entities::sys::{Group, GroupKey}; use crate::generated_id::GeneratedId; -#[mockall_double::double] +#[cfg_attr(test, mockall_double::double)] use crate::typed_entity_client::TypedEntityClient; -#[mockall_double::double] +#[cfg_attr(test, mockall_double::double)] use crate::user_facade::UserFacade; use crate::util::Versioned; use crate::ListLoadDirection; @@ -254,7 +254,7 @@ mod tests { use super::*; use crate::crypto::randomizer_facade::test_util::make_thread_rng_facade; use crate::crypto::randomizer_facade::RandomizerFacade; - use crate::crypto::{Aes256Key, Iv, PQKeyPairs}; + use crate::crypto::{aes::Iv, Aes256Key, PQKeyPairs}; use crate::custom_id::CustomId; use crate::entities::sys::{GroupKeysRef, GroupMembership, KeyPair}; use crate::key_cache::MockKeyCache; @@ -597,12 +597,12 @@ mod tests { .await .unwrap(); match keypair { - AsymmetricKeyPair::RSAKeyPair(_) => panic!("key_loader_facade.load_key_pair() returned an RSAKeyPair! Expected PQKeyPairs."), - AsymmetricKeyPair::RSAEccKeyPair(_) => panic!("key_loader_facade.load_key_pair() returned an RSAEccKeyPair! Expected PQKeyPairs."), - AsymmetricKeyPair::PQKeyPairs(pq_key_pair) => { - assert_eq!(pq_key_pair, *former_key_pairs_decrypted.get(i).expect("former_key_pairs_decrypted should have FORMER_KEYS keys")) - } - } + AsymmetricKeyPair::RSAKeyPair(_) => panic!("key_loader_facade.load_key_pair() returned an RSAKeyPair! Expected PQKeyPairs."), + AsymmetricKeyPair::RSAEccKeyPair(_) => panic!("key_loader_facade.load_key_pair() returned an RSAEccKeyPair! Expected PQKeyPairs."), + AsymmetricKeyPair::PQKeyPairs(pq_key_pair) => { + assert_eq!(pq_key_pair, *former_key_pairs_decrypted.get(i).expect("former_key_pairs_decrypted should have FORMER_KEYS keys")) + }, + } } } @@ -677,11 +677,11 @@ mod tests { .await .unwrap(); match keypair { - GenericAesKey::Aes128(_) => panic!("key_loader_facade.load_sym_group_key() returned an AES128 key! Expected an AES256 key."), - GenericAesKey::Aes256(returned_group_key) => { - assert_eq!(returned_group_key, *former_keys_decrypted.get(i).expect("former_keys_decrypted should have FORMER_KEYS keys")) - } - } + GenericAesKey::Aes128(_) => panic!("key_loader_facade.load_sym_group_key() returned an AES128 key! Expected an AES256 key."), + GenericAesKey::Aes256(returned_group_key) => { + assert_eq!(returned_group_key, *former_keys_decrypted.get(i).expect("former_keys_decrypted should have FORMER_KEYS keys")) + }, + } } } diff --git a/tuta-sdk/rust/sdk/src/lib.rs b/tuta-sdk/rust/sdk/src/lib.rs index b20f104390bf..005c51355dda 100644 --- a/tuta-sdk/rust/sdk/src/lib.rs +++ b/tuta-sdk/rust/sdk/src/lib.rs @@ -1,3 +1,5 @@ +#![macro_use] + use std::collections::HashMap; use std::error::Error; use std::fmt::{Debug, Display, Formatter}; @@ -8,41 +10,48 @@ use minicbor::{Encode, Encoder}; use serde::{Deserialize, Serialize}; use thiserror::Error; -use rest_client::{RestClient, RestClientError}; - -#[mockall_double::double] +use crate::crypto::crypto_facade::create_auth_verifier; +#[cfg_attr(test, mockall_double::double)] use crate::crypto::crypto_facade::CryptoFacade; +use crate::crypto::key::GenericAesKey; use crate::crypto::randomizer_facade::RandomizerFacade; -#[mockall_double::double] +use crate::crypto::{aes::Iv, Aes256Key}; +#[cfg_attr(test, mockall_double::double)] use crate::crypto_entity_client::CryptoEntityClient; use crate::element_value::ElementValue; use crate::entities::entity_facade::EntityFacadeImpl; +use crate::entities::sys::{CreateSessionData, SaltData}; use crate::entities::tutanota::Mail; -#[mockall_double::double] +#[cfg_attr(test, mockall_double::double)] use crate::entity_client::EntityClient; use crate::entity_client::IdType; use crate::generated_id::GeneratedId; use crate::instance_mapper::InstanceMapper; use crate::json_serializer::{InstanceMapperError, JsonSerializer}; -#[mockall_double::double] +#[cfg_attr(test, mockall_double::double)] use crate::key_cache::KeyCache; -#[mockall_double::double] +#[cfg_attr(test, mockall_double::double)] use crate::key_loader_facade::KeyLoaderFacade; -use crate::login::{Credentials, LoginError, LoginFacade}; +use crate::login::login_facade::{derive_user_passphrase_key, KdfType}; +use crate::login::{CredentialType, Credentials, LoginError, LoginFacade}; use crate::mail_facade::MailFacade; use crate::rest_error::{HttpError, ParseFailureError}; +use crate::services::service_executor::ServiceExecutor; +use crate::services::sys::{SaltService, SessionService}; +use crate::services::ExtraServiceParams; use crate::type_model_provider::{init_type_model_provider, AppName, TypeModelProvider, TypeName}; -#[mockall_double::double] +#[cfg_attr(test, mockall_double::double)] use crate::typed_entity_client::TypedEntityClient; -#[mockall_double::double] +#[cfg_attr(test, mockall_double::double)] use crate::user_facade::UserFacade; +use rest_client::{RestClient, RestClientError}; -mod crypto; +pub mod crypto; mod crypto_entity_client; -mod custom_id; +pub mod custom_id; pub mod date; mod element_value; -mod entities; +pub mod entities; mod entity_client; pub mod generated_id; mod instance_mapper; @@ -54,15 +63,21 @@ mod logging; pub mod login; mod mail_facade; mod metamodel; + +#[cfg(feature = "net")] +pub mod net; pub mod rest_client; mod rest_error; +pub mod services; mod simple_crypto; -mod tutanota_constants; +pub mod tutanota_constants; mod type_model_provider; mod typed_entity_client; mod user_facade; mod util; +pub static CLIENT_VERSION: &str = env!("CARGO_PKG_VERSION"); + uniffi::setup_scaffolding!(); /// A type for an instance/entity from the backend @@ -93,12 +108,11 @@ impl Display for TypeRef { pub struct HeadersProvider { client_version: String, - // In the future we might need to make this one optional to support "not authenticated" state - access_token: String, + access_token: Option, } impl HeadersProvider { - fn new(client_version: String, access_token: String) -> Self { + pub fn new(client_version: String, access_token: Option) -> Self { Self { client_version, access_token, @@ -106,11 +120,16 @@ impl HeadersProvider { } fn provide_headers(&self, model_version: u32) -> HashMap { - HashMap::from([ - ("accessToken".to_string(), self.access_token.clone()), + let mut headers = HashMap::from([ ("cv".to_owned(), self.client_version.clone()), ("v".to_owned(), model_version.to_string()), - ]) + ]); + + if let Some(access_token) = &self.access_token { + headers.insert("accessToken".to_owned(), access_token.to_string()); + } + + headers } } @@ -146,12 +165,11 @@ impl Sdk { client_version, } } - /// Authorizes the SDK's REST requests via inserting `access_token` into the HTTP headers pub async fn login(&self, credentials: Credentials) -> Result, LoginError> { let auth_headers_provider = Arc::new(HeadersProvider::new( self.client_version.clone(), - credentials.access_token.clone(), + Some(credentials.access_token.clone()), )); let entity_client = Arc::new(EntityClient::new( self.rest_client.clone(), @@ -165,7 +183,6 @@ impl Sdk { self.instance_mapper.clone(), )); - // Try to resume session let login_facade = LoginFacade::new(entity_client.clone(), typed_entity_client.clone(), |user| { UserFacade::new(Arc::new(KeyCache::new()), user) @@ -178,7 +195,7 @@ impl Sdk { )); let randomizer = RandomizerFacade::from_core(rand_core::OsRng); let crypto_facade = Arc::new(CryptoFacade::new( - key_loader.clone(), + Some(key_loader.clone()), self.instance_mapper.clone(), randomizer, )); @@ -197,6 +214,77 @@ impl Sdk { crypto_entity_client, })) } + + // not ready yet for production use, only does temporary login for free users without offline. + pub async fn create_session( + &self, + mail_address: &str, + passphrase: &str, + ) -> Result, LoginError> { + let headers_provider = Arc::new(HeadersProvider::new(self.client_version.clone(), None)); + + let crypto_facade = Arc::new(CryptoFacade::new( + None, + self.instance_mapper.clone(), + RandomizerFacade::from_core(rand_core::OsRng), + )); + let entity_facade = Arc::new(EntityFacadeImpl::new(self.type_model_provider.clone())); + + let service_executor = ServiceExecutor::new( + headers_provider.clone(), + crypto_facade, + entity_facade, + self.instance_mapper.clone(), + self.json_serializer.clone(), + self.rest_client.clone(), + self.type_model_provider.clone(), + self.base_url.to_string(), + ); + let salt_get_input: SaltData = SaltData { + _format: 0, + mailAddress: mail_address.to_string(), + }; + let salt_return = service_executor + .get::(salt_get_input, ExtraServiceParams::default()) + .await?; + + let Ok(salt) = salt_return.salt.try_into() else { + return Err(LoginError::InvalidKey { + error_message: "salt has wrong length".to_string(), + }); + }; + + let randomizer = RandomizerFacade::from_core(rand_core::OsRng); + let access_key = Aes256Key::generate(&randomizer); + let user_passphrase_key = derive_user_passphrase_key(KdfType::Argon2id, passphrase, salt); + let auth_verifier = create_auth_verifier(user_passphrase_key.clone()); + let session_data: CreateSessionData = CreateSessionData { + _format: 0, + accessKey: Some(access_key.as_bytes().to_vec()), + authToken: None, + authVerifier: Some(auth_verifier), + clientIdentifier: "Linux Desktop".to_string(), + mailAddress: Some(mail_address.to_string()), + recoverCodeVerifier: None, + user: None, + }; + let encrypted_passphrase_key = GenericAesKey::Aes256(access_key).encrypt_key( + &GenericAesKey::Aes256(user_passphrase_key), + Iv::generate(&randomizer), + ); + let session_data_response = service_executor + .post::(session_data, ExtraServiceParams::default()) + .await?; + + self.login(Credentials { + login: mail_address.to_string(), + user_id: session_data_response.user.clone(), + access_token: session_data_response.accessToken.clone(), + encrypted_passphrase_key, + credential_type: CredentialType::Internal, + }) + .await + } } #[allow(dead_code)] @@ -225,7 +313,7 @@ pub enum ListLoadDirection { } /// A set of keys used to identify an element within a List Element Type -#[derive(uniffi::Record, Debug, PartialEq, Clone, Serialize, Deserialize)] +#[derive(uniffi::Record, Debug, Eq, PartialEq, Clone, Serialize, Deserialize)] pub struct IdTuple { pub list_id: GeneratedId, pub element_id: GeneratedId, @@ -250,7 +338,7 @@ impl Display for IdTuple { } /// Contains an error from the SDK to be handled by the consuming code over the FFI -#[derive(Error, Debug, uniffi::Error)] +#[derive(Error, Debug, uniffi::Error, Eq, PartialEq, Clone)] pub enum ApiCallError { #[error("Rest client error, source: {source}")] RestClient { @@ -267,12 +355,12 @@ pub enum ApiCallError { } impl ApiCallError { - fn internal(message: String) -> ApiCallError { + pub fn internal(message: String) -> ApiCallError { ApiCallError::InternalSdkError { error_message: message, } } - fn internal_with_err(error: E, message: &str) -> ApiCallError { + pub fn internal_with_err(error: E, message: &str) -> ApiCallError { ApiCallError::InternalSdkError { error_message: format!("{}: {}", error, message), } @@ -351,10 +439,10 @@ impl Encode for ElementValue { } #[cfg(test)] mod tests { + use crate::entities::tutanota::Mail; + use crate::serialize_mail; use crate::util::test_utils::create_test_entity; - use super::*; - #[test] fn test_serialize_mail_does_not_panic() { let mail = create_test_entity::(); diff --git a/tuta-sdk/rust/sdk/src/login/credentials.rs b/tuta-sdk/rust/sdk/src/login/credentials.rs index e4f1a9df391f..8871d1fce638 100644 --- a/tuta-sdk/rust/sdk/src/login/credentials.rs +++ b/tuta-sdk/rust/sdk/src/login/credentials.rs @@ -1,16 +1,16 @@ use crate::generated_id::GeneratedId; -#[derive(uniffi::Record)] +#[derive(uniffi::Record, Clone)] pub struct Credentials { - pub login: String, - pub user_id: GeneratedId, - pub access_token: String, - pub encrypted_passphrase_key: Vec, - pub credential_type: CredentialType, + pub login: String, + pub user_id: GeneratedId, + pub access_token: String, + pub encrypted_passphrase_key: Vec, + pub credential_type: CredentialType, } #[derive(uniffi::Enum, Debug, PartialEq, Clone)] pub enum CredentialType { - Internal, - External, + Internal, + External, } diff --git a/tuta-sdk/rust/sdk/src/login/login_facade.rs b/tuta-sdk/rust/sdk/src/login/login_facade.rs index a2a841cc6043..99a9ac730600 100644 --- a/tuta-sdk/rust/sdk/src/login/login_facade.rs +++ b/tuta-sdk/rust/sdk/src/login/login_facade.rs @@ -9,20 +9,20 @@ use crate::crypto::{generate_key_from_passphrase, sha256, Aes256Key}; use crate::element_value::ParsedEntity; use crate::entities::sys::{Session, User}; use crate::entities::Entity; -#[mockall_double::double] +#[cfg_attr(test, mockall_double::double)] use crate::entity_client::EntityClient; use crate::generated_id::{GeneratedId, GENERATED_ID_BYTES_LENGTH}; use crate::login::credentials::Credentials; -#[mockall_double::double] +#[cfg_attr(test, mockall_double::double)] use crate::typed_entity_client::TypedEntityClient; -#[mockall_double::double] +#[cfg_attr(test, mockall_double::double)] use crate::user_facade::UserFacade; use crate::util::{array_cast_slice, BASE64_EXT}; use crate::ApiCallError::InternalSdkError; use crate::{ApiCallError, IdTuple}; /// Error that may occur during login and session creation -#[derive(Error, Debug, uniffi::Error)] +#[derive(Error, Debug, uniffi::Error, Clone, PartialEq)] pub enum LoginError { #[error("InvalidSessionId: {error_message}")] InvalidSessionId { error_message: String }, @@ -201,7 +201,7 @@ mod tests { use crate::crypto::key::GenericAesKey; use crate::crypto::randomizer_facade::RandomizerFacade; - use crate::crypto::{Aes128Key, Aes256Key, Iv}; + use crate::crypto::{aes::Iv, Aes128Key, Aes256Key}; use crate::entities::sys::{GroupMembership, Session, User, UserExternalAuthInfo}; use crate::entities::Entity; use crate::entity_client::MockEntityClient; diff --git a/tuta-sdk/rust/sdk/src/login/mod.rs b/tuta-sdk/rust/sdk/src/login/mod.rs index e9a73453f32f..b165e3ac63a5 100644 --- a/tuta-sdk/rust/sdk/src/login/mod.rs +++ b/tuta-sdk/rust/sdk/src/login/mod.rs @@ -1,5 +1,5 @@ mod credentials; -mod login_facade; +pub(crate) mod login_facade; pub use credentials::*; pub use login_facade::{LoginError, LoginFacade}; diff --git a/tuta-sdk/rust/sdk/src/mail_facade.rs b/tuta-sdk/rust/sdk/src/mail_facade.rs index 498b4934a1e4..6a026d007db2 100644 --- a/tuta-sdk/rust/sdk/src/mail_facade.rs +++ b/tuta-sdk/rust/sdk/src/mail_facade.rs @@ -1,4 +1,4 @@ -#[mockall_double::double] +#[cfg_attr(test, mockall_double::double)] use crate::crypto_entity_client::CryptoEntityClient; use crate::entities::tutanota::Mail; use crate::{ApiCallError, IdTuple}; diff --git a/tuta-sdk/rust/sdk/src/metamodel.rs b/tuta-sdk/rust/sdk/src/metamodel.rs index d1d78840220b..c6d13308bb0d 100644 --- a/tuta-sdk/rust/sdk/src/metamodel.rs +++ b/tuta-sdk/rust/sdk/src/metamodel.rs @@ -1,9 +1,11 @@ use std::collections::HashMap; +use crate::date::DateTime; +use crate::element_value::ElementValue; use serde::Deserialize; /// A kind of element that can appear in the model -#[derive(Deserialize, PartialEq, Clone)] +#[derive(Deserialize, PartialEq, Clone, Debug)] pub enum ElementType { /// Entity referenced by a single id #[serde(rename = "ELEMENT_TYPE")] @@ -34,6 +36,21 @@ pub enum ValueType { CompressedString, } +impl ValueType { + pub fn get_default(&self) -> ElementValue { + match self { + ValueType::String | ValueType::CompressedString => ElementValue::String(String::new()), + ValueType::Number => ElementValue::Number(0), + ValueType::Bytes => ElementValue::Bytes(Vec::new()), + ValueType::Date => ElementValue::Date(DateTime::default()), + ValueType::Boolean => ElementValue::Bool(false), + ValueType::GeneratedId | ValueType::CustomId => { + panic!("{self:?} is not a valid value type") + }, + } + } +} + /// Associations (references and aggregations) have two dimensions: the type they reference and /// their cardinality. #[derive(Deserialize, PartialEq, Clone)] @@ -47,7 +64,7 @@ pub enum Cardinality { } /// Relationships between elements are described as association -#[derive(Deserialize, Clone)] +#[derive(Deserialize, Clone, Eq, PartialEq)] pub enum AssociationType { /// References [ElementType] by id #[serde(rename = "ELEMENT_ASSOCIATION")] diff --git a/tuta-sdk/rust/sdk/src/net/mod.rs b/tuta-sdk/rust/sdk/src/net/mod.rs new file mode 100644 index 000000000000..82ce6e6c4f71 --- /dev/null +++ b/tuta-sdk/rust/sdk/src/net/mod.rs @@ -0,0 +1,3 @@ +pub mod native_rest_client; +mod uri; +mod vec_body; diff --git a/tuta-sdk/rust/sdk/src/net/native_rest_client.rs b/tuta-sdk/rust/sdk/src/net/native_rest_client.rs new file mode 100644 index 000000000000..08336beea795 --- /dev/null +++ b/tuta-sdk/rust/sdk/src/net/native_rest_client.rs @@ -0,0 +1,111 @@ +use crate::net::vec_body::{VecBody, VecBuf}; +use crate::rest_client::{ + HttpMethod, RestClient, RestClientError, RestClientOptions, RestResponse, +}; +use http_body_util::{BodyExt, Full}; +use hyper::body::Incoming; +use hyper::http::HeaderValue; +use hyper::{HeaderMap, Request, Response}; +use hyper_rustls::HttpsConnector; +use hyper_util::client::legacy::connect::HttpConnector; +use hyper_util::client::legacy::Client; +use hyper_util::rt::TokioExecutor; +use std::collections::HashMap; + +pub struct NativeRestClient { + client: Client, VecBody>, +} + +impl NativeRestClient { + pub fn try_new() -> Result { + let _ = rustls::crypto::ring::default_provider().install_default(); + + let https_conn = hyper_rustls::HttpsConnectorBuilder::new() + .with_native_roots()? + .https_or_http() + .enable_all_versions() + .build(); + + let client = Client::builder(TokioExecutor::new()).build(https_conn); + + Ok(NativeRestClient { client }) + } +} + +#[async_trait::async_trait] +impl RestClient for NativeRestClient { + async fn request_binary( + &self, + url: String, + method: HttpMethod, + options: RestClientOptions, + ) -> Result { + let RestClientOptions { headers, body } = options; + let uri = super::uri::Uri::try_from(url.as_str())?; + + let req = Request::builder() + .header(hyper::header::HOST, uri.authority()) + .uri(uri.inner()); + + let mut req = match method { + HttpMethod::GET => req.method("GET"), + HttpMethod::POST => req.method("POST"), + HttpMethod::PUT => req.method("PUT"), + HttpMethod::DELETE => req.method("DELETE"), + }; + + for (header_name, header_value) in headers { + req = req.header(header_name, header_value); + } + + let req: Request = match body { + Some(bytes) => req.body(VecBuf(bytes).into()), + None => req.body(Full::default()), + } + .map_err(|_| RestClientError::InvalidRequest)?; + + let mut res = self + .client + .request(req) + .await + .map_err(|_| RestClientError::NetworkError)?; + + let response_body = read_body(&mut res).await?; + + Ok(RestResponse { + status: res.status().as_u16().into(), + headers: read_headers(res.headers())?, + body: if response_body.is_empty() { + None + } else { + Some(response_body) + }, + }) + } +} + +fn read_headers( + header_map: &HeaderMap, +) -> Result, RestClientError> { + let mut headers = HashMap::new(); + for (name, values) in header_map.iter() { + let name_str = name.as_str(); + let value_str = values + .to_str() + .map_err(|_| RestClientError::InvalidResponse)?; + headers.insert(name_str.to_string(), value_str.to_string()); + } + Ok(headers) +} + +async fn read_body(res: &mut Response) -> Result, RestClientError> { + let mut body: Vec = vec![]; + while let Some(next) = res.frame().await { + let frame = next.map_err(|_| RestClientError::InvalidResponse)?; + if let Some(chunk) = frame.data_ref() { + body.append(&mut chunk.to_vec()); + } + } + + Ok(body) +} diff --git a/tuta-sdk/rust/sdk/src/net/uri.rs b/tuta-sdk/rust/sdk/src/net/uri.rs new file mode 100644 index 000000000000..ffc9a5de4b0d --- /dev/null +++ b/tuta-sdk/rust/sdk/src/net/uri.rs @@ -0,0 +1,61 @@ +use crate::rest_client::RestClientError; + +/// wrapper around hyper::Uri that saves some unwrapping +pub struct Uri(hyper::Uri); + +impl Uri { + pub fn scheme(&self) -> &hyper::http::uri::Scheme { + self.0.scheme().unwrap() + } + + pub fn authority(&self) -> String { + self.0.authority().unwrap().to_string() + } + + pub fn inner(self) -> hyper::Uri { + self.0 + } +} +impl TryFrom<&str> for Uri { + type Error = RestClientError; + + fn try_from(value: &str) -> Result { + let uri = value + .parse::() + .map_err(|_| RestClientError::InvalidURL(value.to_string()))?; + + // it looks like hyper::Uri doesn't accept Urls without an authority + // but with a scheme (like http:///path) so this check could be omitted. + // feels safer this way though. + let Some(_) = uri.authority() else { + return Err(RestClientError::InvalidURL(value.to_string())); + }; + + let (Some("http") | Some("https")) = uri.scheme_str() else { + return Err(RestClientError::InvalidURL(value.to_string())); + }; + + Ok(Self(uri)) + } +} + +#[cfg(test)] +mod tests { + #[test] + fn should_work() { + super::Uri::try_from("http://localhost:8080").unwrap(); + super::Uri::try_from("https://localhost:8080").unwrap(); + super::Uri::try_from("https://localhost.com").unwrap(); + super::Uri::try_from("https://127.0.0.1:123").unwrap(); + super::Uri::try_from("https://localhost.com/path?with=params").unwrap(); + } + + #[test] + fn should_fail() { + // wrong scheme + assert!(super::Uri::try_from("ftp://localhost:8080").is_err()); + // no authority + assert!(super::Uri::try_from("/relative").is_err()); + assert!(super::Uri::try_from("").is_err()); + } +} diff --git a/tuta-sdk/rust/sdk/src/net/vec_body.rs b/tuta-sdk/rust/sdk/src/net/vec_body.rs new file mode 100644 index 000000000000..f4af2537378a --- /dev/null +++ b/tuta-sdk/rust/sdk/src/net/vec_body.rs @@ -0,0 +1,51 @@ +use http_body_util::Full; +use hyper::body::Buf; +pub type VecBody = Full; +pub struct VecBuf(pub Vec); + +impl Into for VecBuf { + fn into(self) -> VecBody { + Full::new(self) + } +} + +/// somewhat stolen from impl Buf for &[u8] +/// also don't know why impl Buf for Vec doesn't come with hyper +impl Buf for VecBuf { + #[inline] + fn remaining(&self) -> usize { + self.0.len() + } + + #[inline] + fn chunk(&self) -> &[u8] { + self.0.as_slice() + } + + #[inline] + fn advance(&mut self, cnt: usize) { + if self.0.len() < cnt { + panic_advance(cnt, self.0.len()); + } + self.0.drain(..cnt); + } + + #[inline] + fn copy_to_slice(&mut self, dst: &mut [u8]) { + if self.0.len() < dst.len() { + panic_advance(dst.len(), self.0.len()); + } + + dst.copy_from_slice(&self.0[..dst.len()]); + self.advance(dst.len()); + } +} + +/// Panic with a nice error message. +#[cold] +fn panic_advance(idx: usize, len: usize) -> ! { + panic!( + "advance out of bounds: the len is {} but advancing by {}", + len, idx + ); +} diff --git a/tuta-sdk/rust/sdk/src/rest_client.rs b/tuta-sdk/rust/sdk/src/rest_client.rs index 96c28fa72a22..ce87da60b0ce 100644 --- a/tuta-sdk/rust/sdk/src/rest_client.rs +++ b/tuta-sdk/rust/sdk/src/rest_client.rs @@ -10,25 +10,27 @@ pub enum HttpMethod { } /// HTTP(S) data inserted by the `RestClient` in its REST requests -#[derive(uniffi::Record)] +#[derive(uniffi::Record, Debug, Eq, PartialEq)] pub struct RestClientOptions { pub headers: HashMap, pub body: Option>, } /// An error thrown by the `RestClient` (the injected HTTP client Kotlin/Swift/JavaScript) -#[derive(Error, Debug, uniffi::Error)] +#[derive(Error, Debug, uniffi::Error, Eq, PartialEq, Clone)] pub enum RestClientError { #[error("Network error")] NetworkError, -} - -/// HTTP(S) data contained within a response from the backend -#[derive(uniffi::Record, Clone)] -pub struct RestResponse { - pub status: u32, - pub headers: HashMap, - pub body: Option>, + #[error("Invalid URL")] + InvalidURL(String), + #[error("Failed handshake")] + FailedHandshake, + #[error("Invalid request")] + InvalidRequest, + #[error("Invalid response")] + InvalidResponse, + #[error("failed tls setup")] + FailedTlsSetup, } /// Provides a Rust SDK level interface for performing REST requests @@ -45,3 +47,11 @@ pub trait RestClient: Send + Sync + 'static { options: RestClientOptions, ) -> Result; } + +/// HTTP(S) data contained within a response from the backend +#[derive(uniffi::Record, Clone)] +pub struct RestResponse { + pub status: u32, + pub headers: HashMap, + pub body: Option>, +} diff --git a/tuta-sdk/rust/sdk/src/rest_error.rs b/tuta-sdk/rust/sdk/src/rest_error.rs index 9d94fac9b6f9..45ffbed257f4 100644 --- a/tuta-sdk/rust/sdk/src/rest_error.rs +++ b/tuta-sdk/rust/sdk/src/rest_error.rs @@ -8,7 +8,7 @@ use thiserror::Error; pub struct ParseFailureError; /// The failed preconditions of a REST request to attempt downgrading an account -#[derive(Error, Debug, uniffi::Enum, Eq, PartialEq)] +#[derive(Error, Debug, uniffi::Enum, Eq, PartialEq, Clone)] pub enum UnsubscribeFailureReason { #[error("TooManyEnabledUsers")] TooManyEnabledUsers, @@ -67,7 +67,7 @@ impl FromStr for UnsubscribeFailureReason { } // legacy, should be deleted after clients older than 3.114 have been disabled. -#[derive(Error, Debug, uniffi::Enum, Eq, PartialEq)] +#[derive(Error, Debug, uniffi::Enum, Eq, PartialEq, Clone)] pub enum BookingFailureReason { #[error("TooManyDomains")] TooManyDomains, @@ -101,7 +101,7 @@ impl FromStr for BookingFailureReason { } /// The failed preconditions of a REST request to attempt setting a whitelabel domain -#[derive(Error, Debug, uniffi::Enum, Eq, PartialEq)] +#[derive(Error, Debug, uniffi::Enum, Eq, PartialEq, Clone)] pub enum DomainFailureReason { // Renamed from FAILURE_CONTACT_FORM_ACTIVE #[error("ContactFormActive")] @@ -134,7 +134,7 @@ impl FromStr for DomainFailureReason { /// The failed preconditions of a REST request to attempt setting a custom domain /// for an email address -#[derive(Error, Debug, uniffi::Enum, Eq, PartialEq)] +#[derive(Error, Debug, uniffi::Enum, Eq, PartialEq, Clone)] pub enum CustomDomainFailureReason { #[error("LimitReached")] LimitReached, @@ -156,7 +156,7 @@ impl FromStr for CustomDomainFailureReason { } /// The failed preconditions of unsuccessful template group operations -#[derive(Error, Debug, uniffi::Enum, Eq, PartialEq)] +#[derive(Error, Debug, uniffi::Enum, Eq, PartialEq, Clone)] pub enum TemplateGroupFailureReason { #[error("BusinessFeatureRequired")] BusinessFeatureRequired, @@ -178,7 +178,7 @@ impl FromStr for TemplateGroupFailureReason { } /// The failed preconditions of unsuccessful usage test operations -#[derive(Error, Debug, uniffi::Enum, Eq, PartialEq)] +#[derive(Error, Debug, uniffi::Enum, Eq, PartialEq, Clone)] pub enum UsageTestFailureReason { #[error("InvalidState")] InvalidState, @@ -209,7 +209,7 @@ impl FromStr for UsageTestFailureReason { } /// The possible failed preconditions when unsuccessfully performing an operation on the backend -#[derive(Error, Debug, uniffi::Enum, Eq, PartialEq)] +#[derive(Error, Debug, uniffi::Enum, Eq, PartialEq, Clone)] pub enum PreconditionFailedReason { #[error("UnsubscribeFailure")] UnsubscribeFailure(#[from] UnsubscribeFailureReason), @@ -262,7 +262,7 @@ impl FromStr for PreconditionFailedReason { } /// The possible error responses from the server -#[derive(Error, Debug, uniffi::Error, Eq, PartialEq)] +#[derive(Error, Debug, uniffi::Error, Eq, PartialEq, Clone)] pub enum HttpError { #[error("Connection lost")] ConnectionError, diff --git a/tuta-sdk/rust/sdk/src/services/accounting.rs b/tuta-sdk/rust/sdk/src/services/accounting.rs new file mode 100644 index 000000000000..2c9647d516c6 --- /dev/null +++ b/tuta-sdk/rust/sdk/src/services/accounting.rs @@ -0,0 +1,11 @@ +#![allow(unused_imports, dead_code, unused_variables)] +use crate::ApiCallError; +use crate::entities::Entity; +use crate::services::{PostService, GetService, PutService, DeleteService, Service, Executor, ExtraServiceParams}; +use crate::rest_client::HttpMethod; +use crate::services::hidden::Nothing; +use crate::entities::accounting::CustomerAccountReturn; +pub struct CustomerAccountService; + +crate::service_impl!(base, CustomerAccountService, "accounting/customeraccountservice", 7); +crate::service_impl!(GET, CustomerAccountService, (), CustomerAccountReturn); diff --git a/tuta-sdk/rust/sdk/src/services/base.rs b/tuta-sdk/rust/sdk/src/services/base.rs new file mode 100644 index 000000000000..213f090e5f55 --- /dev/null +++ b/tuta-sdk/rust/sdk/src/services/base.rs @@ -0,0 +1,6 @@ +#![allow(unused_imports, dead_code, unused_variables)] +use crate::ApiCallError; +use crate::entities::Entity; +use crate::services::{PostService, GetService, PutService, DeleteService, Service, Executor, ExtraServiceParams}; +use crate::rest_client::HttpMethod; +use crate::services::hidden::Nothing; \ No newline at end of file diff --git a/tuta-sdk/rust/sdk/src/services/generator.rs b/tuta-sdk/rust/sdk/src/services/generator.rs new file mode 100644 index 000000000000..23cf597d1f3a --- /dev/null +++ b/tuta-sdk/rust/sdk/src/services/generator.rs @@ -0,0 +1,77 @@ +#[macro_export] +macro_rules! __service_input_type { + (()) => { + $crate::services::hidden::Nothing + }; + ($i:ident) => { + $i + }; +} + +#[macro_export] +macro_rules! __service_input_value { + ($data:tt, ()) => { + None + }; + ($data:tt, $i: tt) => { + Some($data) + }; +} + +#[macro_export] +macro_rules! __service_handle_response { + ($x:expr, $res:expr, ()) => { + return Ok(()); + }; + ($x:expr, $res:expr, $i: tt) => { + return $x.handle_response::($res).await; + }; +} + +#[macro_export] +macro_rules! service_impl { + (base, $service_name: ty, $service_path: expr, $service_version: expr) => { + impl $crate::services::Service for $service_name { + const PATH: &'static str = $service_path; + const VERSION: u32 = $service_version; + } + }; + + (POST, $service_name: ty, $input_type:tt, $output_type:tt) => { + $crate::service_impl!(@internal, $crate::services::PostService, POST, $service_name, $input_type, $output_type); + }; + + (PUT, $service_name: ty, $input_type:tt, $output_type:tt) => { + $crate::service_impl!(@internal, $crate::services::PutService, PUT, $service_name, $input_type, $output_type); + }; + + (GET, $service_name: ty, $input_type:tt, $output_type:tt) => { + $crate::service_impl!(@internal, $crate::services::GetService, GET, $service_name, $input_type, $output_type); + }; + + (DELETE, $service_name: ty, $input_type:tt, $output_type:tt) => { + $crate::service_impl!(@internal, $crate::services::DeleteService, DELETE, $service_name, $input_type, $output_type); + }; + + (@internal, $service_trait: path, $method_name: ident, $service_name: ty, $input_type:tt, $output_type:tt) => { + + #[async_trait::async_trait] + impl $service_trait for $service_name { + type Input = $input_type; + type Output = $output_type; + + async fn $method_name( + x: &impl $crate::services::Executor, + data: $input_type, + params: $crate::services::ExtraServiceParams + ) -> ::core::result::Result { + let res = x.do_request::( + $crate::__service_input_value!(data, $input_type), + $crate::rest_client::HttpMethod::$method_name, + params + ).await?; + $crate::__service_handle_response!(x, res, $output_type); + } + } + }; +} diff --git a/tuta-sdk/rust/sdk/src/services/gossip.rs b/tuta-sdk/rust/sdk/src/services/gossip.rs new file mode 100644 index 000000000000..213f090e5f55 --- /dev/null +++ b/tuta-sdk/rust/sdk/src/services/gossip.rs @@ -0,0 +1,6 @@ +#![allow(unused_imports, dead_code, unused_variables)] +use crate::ApiCallError; +use crate::entities::Entity; +use crate::services::{PostService, GetService, PutService, DeleteService, Service, Executor, ExtraServiceParams}; +use crate::rest_client::HttpMethod; +use crate::services::hidden::Nothing; \ No newline at end of file diff --git a/tuta-sdk/rust/sdk/src/services/mod.rs b/tuta-sdk/rust/sdk/src/services/mod.rs new file mode 100644 index 000000000000..49c882f6786f --- /dev/null +++ b/tuta-sdk/rust/sdk/src/services/mod.rs @@ -0,0 +1,143 @@ +use crate::crypto::key::GenericAesKey; +use crate::services::hidden::Executor; +use crate::ApiCallError; +use std::collections::HashMap; + +pub mod accounting; +pub mod base; +pub mod generator; +pub mod gossip; +pub mod monitor; +pub mod service_executor; +pub mod storage; +pub mod sys; +pub mod tutanota; +pub mod usage; + +#[cfg(test)] +pub mod test_services; + +pub trait Service { + const PATH: &'static str; + const VERSION: u32; +} + +#[async_trait::async_trait] +pub trait GetService: Service { + type Input; + type Output; + + #[allow(non_snake_case)] + async fn GET( + x: &impl Executor, + data: Self::Input, + params: ExtraServiceParams, + ) -> Result; +} + +#[async_trait::async_trait] +pub trait PostService: Service { + type Input; + type Output; + + #[allow(non_snake_case)] + async fn POST( + x: &impl Executor, + data: Self::Input, + params: ExtraServiceParams, + ) -> Result; +} + +#[async_trait::async_trait] +pub trait PutService: Service { + type Input; + type Output; + + #[allow(non_snake_case)] + async fn PUT( + x: &impl Executor, + data: Self::Input, + params: ExtraServiceParams, + ) -> Result; +} + +#[async_trait::async_trait] +pub trait DeleteService: Service { + type Input; + type Output; + + #[allow(non_snake_case)] + async fn DELETE( + x: &impl Executor, + data: Self::Input, + params: ExtraServiceParams, + ) -> Result; +} + +pub enum SuspensionBehavior { + Suspend, + Throw, +} + +#[derive(Default)] +pub struct ExtraServiceParams { + pub query_params: Option>, + pub session_key: Option, + pub extra_headers: Option>, + pub suspension_behavior: Option, + /** override origin for the request */ + pub base_url: Option, +} + +mod hidden { + use crate::entities::Entity; + use crate::rest_client::HttpMethod; + use crate::services::{ExtraServiceParams, Service}; + use crate::{ApiCallError, TypeRef}; + use serde::{Deserialize, Serialize, Serializer}; + + /// Type that allows us to call the executor even + /// if the service doesn't have an input or output. + /// it is unimportable outside of the services module and uninstantiable because the enum + /// has no variants. + /// using this construct prevents anyone outside the services module from trying to obtain + /// the type model of this entity type or to return it from a service call. + /// + /// also thought about just providing impl Entity for () but then we'd have problems with people + /// trying to use that impl by accident and Entity::type_ref returning an Option. + /// also we'd still need a way to actually construct the output when we notice that there's + /// nothing to serialize, and just deciding that Service::Output and () are the same thing + /// doesn't work. + pub enum Nothing {} + impl Entity for Nothing { + fn type_ref() -> TypeRef { + unreachable!() + } + } + + impl Serialize for Nothing { + fn serialize(&self, _serializer: S) -> Result + where + S: Serializer, + { + unreachable!() + } + } + + #[async_trait::async_trait] + pub trait Executor: Sync + Send { + async fn do_request( + &self, + data: Option, + method: HttpMethod, + extra_service_params: ExtraServiceParams, + ) -> Result>, ApiCallError> + where + S: Service, + I: Entity + Serialize + Send; + + async fn handle_response(&self, body: Option>) -> Result + where + O: Entity + Deserialize<'static>; + } +} diff --git a/tuta-sdk/rust/sdk/src/services/monitor.rs b/tuta-sdk/rust/sdk/src/services/monitor.rs new file mode 100644 index 000000000000..8e21549ed79d --- /dev/null +++ b/tuta-sdk/rust/sdk/src/services/monitor.rs @@ -0,0 +1,21 @@ +#![allow(unused_imports, dead_code, unused_variables)] +use crate::ApiCallError; +use crate::entities::Entity; +use crate::services::{PostService, GetService, PutService, DeleteService, Service, Executor, ExtraServiceParams}; +use crate::rest_client::HttpMethod; +use crate::services::hidden::Nothing; +use crate::entities::monitor::WriteCounterData; +use crate::entities::monitor::ReadCounterData; +use crate::entities::monitor::ReadCounterReturn; +use crate::entities::monitor::ReportErrorIn; +pub struct CounterService; + +crate::service_impl!(base, CounterService, "monitor/counterservice", 28); +crate::service_impl!(POST, CounterService, WriteCounterData, ()); +crate::service_impl!(GET, CounterService, ReadCounterData, ReadCounterReturn); + + +pub struct ReportErrorService; + +crate::service_impl!(base, ReportErrorService, "monitor/reporterrorservice", 28); +crate::service_impl!(POST, ReportErrorService, ReportErrorIn, ()); diff --git a/tuta-sdk/rust/sdk/src/services/service_executor.rs b/tuta-sdk/rust/sdk/src/services/service_executor.rs new file mode 100644 index 000000000000..3493d958caeb --- /dev/null +++ b/tuta-sdk/rust/sdk/src/services/service_executor.rs @@ -0,0 +1,650 @@ +#[cfg_attr(test, mockall_double::double)] +use crate::crypto::crypto_facade::CryptoFacade; +use crate::entities::entity_facade::EntityFacade; +use crate::entities::Entity; +use crate::instance_mapper::InstanceMapper; +use crate::json_element::RawEntity; +use crate::json_serializer::JsonSerializer; +use crate::metamodel::TypeModel; +use crate::rest_client::{HttpMethod, RestClient, RestClientOptions}; +use crate::rest_error::HttpError; +use crate::services::hidden::Executor; +use crate::services::{ + DeleteService, ExtraServiceParams, GetService, PostService, PutService, Service, +}; +use crate::type_model_provider::TypeModelProvider; +use crate::{ApiCallError, HeadersProvider}; +use serde::Deserialize; +use serde::Serialize; +use std::sync::Arc; + +pub struct ServiceExecutor { + auth_headers_provider: Arc, + crypto_facade: Arc, + entity_facade: Arc, + instance_mapper: Arc, + json_serializer: Arc, + rest_client: Arc, + type_model_provider: Arc, + base_url: String, +} +impl ServiceExecutor { + pub fn new( + auth_headers_provider: Arc, + crypto_facade: Arc, + entity_facade: Arc, + instance_mapper: Arc, + json_serializer: Arc, + rest_client: Arc, + type_model_provider: Arc, + base_url: String, + ) -> Self { + Self { + auth_headers_provider, + crypto_facade, + entity_facade, + instance_mapper, + json_serializer, + rest_client, + type_model_provider, + base_url, + } + } + + pub async fn get( + &self, + data: S::Input, + params: ExtraServiceParams, + ) -> Result + where + S: GetService, + { + S::GET(self, data, params).await + } + + pub async fn post( + &self, + data: S::Input, + params: ExtraServiceParams, + ) -> Result + where + S: PostService, + { + S::POST(self, data, params).await + } + + pub async fn put( + &self, + data: S::Input, + params: ExtraServiceParams, + ) -> Result + where + S: PutService, + { + S::PUT(self, data, params).await + } + + pub async fn delete( + &self, + data: S::Input, + params: ExtraServiceParams, + ) -> Result + where + S: DeleteService, + { + S::DELETE(self, data, params).await + } +} + +#[async_trait::async_trait] +impl Executor for ServiceExecutor { + async fn do_request( + &self, + data: Option, + method: HttpMethod, + extra_service_params: ExtraServiceParams, + ) -> Result>, ApiCallError> + where + S: Service, + I: Entity + Serialize + Send, + { + let url = format!( + "{}/rest/{}", + if let Some(url) = extra_service_params.base_url { + url.clone() + } else { + self.base_url.clone() + }, + S::PATH, + ); + let model_version: u32 = S::VERSION; + + let body: Option> = if let Some(input_entity) = data { + let parsed_entity = self + .instance_mapper + .serialize_entity(input_entity) + .map_err(|e| { + ApiCallError::internal_with_err(e, "failed to convert to ParsedEntity") + })?; + let input_type_ref = I::type_ref(); + let type_model = self + .type_model_provider + .get_type_model(input_type_ref.app, input_type_ref.type_) + .ok_or(ApiCallError::internal(format!( + "type {:?} does not exist", + input_type_ref + )))?; + let encrypted_parsed_entity = self.entity_facade.encrypt_and_map_to_literal( + type_model, + &parsed_entity, + extra_service_params.session_key, + )?; + + let raw_entity = self + .json_serializer + .serialize(&I::type_ref(), encrypted_parsed_entity)?; + let bytes = serde_json::to_vec::(&raw_entity).map_err(|e| { + ApiCallError::internal_with_err(e, "failed to serialize input to string") + })?; + Some(bytes) + } else { + None + }; + + let mut headers = self.auth_headers_provider.provide_headers(model_version); + if let Some(extra_headers) = extra_service_params.extra_headers { + headers.extend(extra_headers); + } + + let response = self + .rest_client + .request_binary(url, method, RestClientOptions { body, headers }) + .await?; + let precondition = response.headers.get("precondition"); + match response.status { + 200 | 201 => Ok(response.body), + _ => Err(ApiCallError::ServerResponseError { + source: HttpError::from_http_response(response.status, precondition)?, + }), + } + } + + async fn handle_response( + &self, + body: Option>, + ) -> Result + where + OutputType: Entity + Deserialize<'static>, + { + let response_bytes = body.expect("no body"); + let response_entity = serde_json::from_slice::(response_bytes.as_slice()) + .map_err(|e| ApiCallError::internal_with_err(e, "Failed to serialize instance"))?; + let output_type_ref = &OutputType::type_ref(); + let mut parsed_entity = self + .json_serializer + .parse(output_type_ref, response_entity)?; + let type_model: &TypeModel = self + .type_model_provider + .get_type_model(output_type_ref.app, output_type_ref.type_) + .expect("invalid type ref!"); + + if type_model.marked_encrypted() { + let possible_session_key = self + .crypto_facade + .resolve_session_key(&mut parsed_entity, type_model) + .await + .map_err(|error| { + ApiCallError::internal(format!( + "Failed to resolve session key for service response '{}'; {}", + type_model.name, error + )) + })?; + match possible_session_key { + Some(session_key) => { + let decrypted_entity = self.entity_facade.decrypt_and_map( + type_model, + parsed_entity, + session_key, + )?; + let typed_entity = self + .instance_mapper + .parse_entity::(decrypted_entity) + .map_err(|e| { + ApiCallError::internal_with_err( + e, + "Failed to parse encrypted entity into proper types", + ) + })?; + Ok(typed_entity) + }, + // `resolve_session_key()` only returns none if the entity is unencrypted, so + // no need to handle it + None => { + unreachable!() + }, + } + } else { + let typed_entity = self + .instance_mapper + .parse_entity::(parsed_entity) + .map_err(|error| { + ApiCallError::internal_with_err( + error, + "Failed to parse unencrypted entity into proper types", + ) + })?; + Ok(typed_entity) + } + } +} + +#[cfg(test)] +mod tests { + #[mockall_double::double] + use crate::crypto::crypto_facade::CryptoFacade; + use crate::crypto::crypto_facade::ResolvedSessionKey; + use crate::crypto::key::GenericAesKey; + use crate::crypto::AES_256_KEY_SIZE; + use crate::date::DateTime; + use crate::element_value::ElementValue; + use crate::entities::entity_facade::MockEntityFacade; + use crate::instance_mapper::InstanceMapper; + use crate::json_element::RawEntity; + use crate::json_serializer::JsonSerializer; + use crate::rest_client::{HttpMethod, MockRestClient, RestResponse}; + use crate::services::service_executor::ServiceExecutor; + use crate::services::test_services::{ + HelloEncInput, HelloEncOutput, HelloEncryptedService, HelloUnEncInput, HelloUnEncOutput, + HelloUnEncryptedService, APP_VERSION_STR, + }; + use crate::services::{test_services, ExtraServiceParams, GetService}; + use crate::type_model_provider::TypeModelProvider; + use crate::HeadersProvider; + use base64::prelude::BASE64_STANDARD; + use base64::Engine; + use std::collections::HashMap; + use std::sync::Arc; + + #[tokio::test] + pub async fn post_should_map_unencrypted_data_and_response() { + let hello_input_data = HelloUnEncInput { + message: "Something".to_string(), + }; + let executor = maps_unencrypted_data_and_response(HttpMethod::POST).await; + let result = executor + .post::(hello_input_data, ExtraServiceParams::default()) + .await; + + assert_eq!( + Ok(HelloUnEncOutput { + timestamp: DateTime::from_millis(3000), + answer: "Response to some request".to_string(), + }), + result + ); + } + + #[tokio::test] + pub async fn put_should_map_unencrypted_data_and_response() { + let hello_input_data = HelloUnEncInput { + message: "Something".to_string(), + }; + let executor = maps_unencrypted_data_and_response(HttpMethod::PUT).await; + let result = executor + .put::(hello_input_data, ExtraServiceParams::default()) + .await; + + assert_eq!( + Ok(HelloUnEncOutput { + timestamp: DateTime::from_millis(3000), + answer: "Response to some request".to_string(), + }), + result + ); + } + + #[tokio::test] + pub async fn get_should_map_unencrypted_data_and_response() { + let hello_input_data = HelloUnEncInput { + message: "Something".to_string(), + }; + let executor = maps_unencrypted_data_and_response(HttpMethod::GET).await; + let result = executor + .get::(hello_input_data, ExtraServiceParams::default()) + .await; + + assert_eq!( + Ok(HelloUnEncOutput { + timestamp: DateTime::from_millis(3000), + answer: "Response to some request".to_string(), + }), + result + ); + } + + #[tokio::test] + pub async fn delete_should_map_unencrypted_data_and_response() { + let hello_input_data = HelloUnEncInput { + message: "Something".to_string(), + }; + let executor = maps_unencrypted_data_and_response(HttpMethod::DELETE).await; + let result = executor + .delete::(hello_input_data, ExtraServiceParams::default()) + .await; + + assert_eq!( + Ok(HelloUnEncOutput { + timestamp: DateTime::from_millis(3000), + answer: "Response to some request".to_string(), + }), + result + ); + } + + #[tokio::test] + pub async fn post_should_decrypt_map_encrypted_data_and_response() { + let session_key = + GenericAesKey::from_bytes(&rand::random::<[u8; AES_256_KEY_SIZE]>()).unwrap(); + let executor = + maps_encrypted_data_and_response_data(HttpMethod::POST, session_key.clone()).await; + + let mut params = ExtraServiceParams::default(); + params.session_key = Some(session_key.clone()); + let input_entity = HelloEncInput { + message: "my encrypted request".to_string(), + }; + + let result = executor + .post::(input_entity, params) + .await; + assert_eq!( + Ok(HelloEncOutput { + answer: "my secret response".to_string(), + timestamp: DateTime::from_millis(3000), + _finalIvs: HashMap::new() + }), + result + ); + } + + #[tokio::test] + pub async fn put_should_decrypt_map_encrypted_data_and_response() { + let session_key = + GenericAesKey::from_bytes(&rand::random::<[u8; AES_256_KEY_SIZE]>()).unwrap(); + let executor = + maps_encrypted_data_and_response_data(HttpMethod::PUT, session_key.clone()).await; + + let mut params = ExtraServiceParams::default(); + params.session_key = Some(session_key.clone()); + let input_entity = HelloEncInput { + message: "my encrypted request".to_string(), + }; + + let result = executor + .put::(input_entity, params) + .await; + assert_eq!( + Ok(HelloEncOutput { + answer: "my secret response".to_string(), + timestamp: DateTime::from_millis(3000), + _finalIvs: HashMap::new() + }), + result + ); + } + + #[tokio::test] + pub async fn get_should_decrypt_map_encrypted_data_and_response() { + let session_key = + GenericAesKey::from_bytes(&rand::random::<[u8; AES_256_KEY_SIZE]>()).unwrap(); + let executor = + maps_encrypted_data_and_response_data(HttpMethod::GET, session_key.clone()).await; + + let mut params = ExtraServiceParams::default(); + params.session_key = Some(session_key.clone()); + let input_entity = HelloEncInput { + message: "my encrypted request".to_string(), + }; + + let result = executor + .get::(input_entity, params) + .await; + assert_eq!( + Ok(HelloEncOutput { + answer: "my secret response".to_string(), + timestamp: DateTime::from_millis(3000), + _finalIvs: HashMap::new() + }), + result + ); + } + + #[tokio::test] + pub async fn delete_should_decrypt_map_encrypted_data_and_response() { + let session_key = + GenericAesKey::from_bytes(&rand::random::<[u8; AES_256_KEY_SIZE]>()).unwrap(); + let executor = + maps_encrypted_data_and_response_data(HttpMethod::DELETE, session_key.clone()).await; + + let mut params = ExtraServiceParams::default(); + params.session_key = Some(session_key.clone()); + let input_entity = HelloEncInput { + message: "my encrypted request".to_string(), + }; + + let result = executor + .delete::(input_entity, params) + .await; + assert_eq!( + Ok(HelloEncOutput { + answer: "my secret response".to_string(), + timestamp: DateTime::from_millis(3000), + _finalIvs: HashMap::new() + }), + result + ); + } + + fn setup() -> ServiceExecutor { + let mut model_provider_map = HashMap::new(); + test_services::extend_model_resolver(&mut model_provider_map); + let type_model_provider: Arc = + Arc::new(TypeModelProvider::new(model_provider_map)); + + let crypto_facade = Arc::new(CryptoFacade::default()); + let entity_facade = Arc::new(MockEntityFacade::default()); + let auth_headers_provider = Arc::new(HeadersProvider::new( + "1.2.3".to_string(), + Some("access_token".to_string()), + )); + let instance_mapper = Arc::new(InstanceMapper::new()); + let json_serializer = Arc::new(JsonSerializer::new(type_model_provider.clone())); + let rest_client = Arc::new(MockRestClient::new()); + + ServiceExecutor::new( + auth_headers_provider, + crypto_facade, + entity_facade, + instance_mapper, + json_serializer, + rest_client, + type_model_provider.clone(), + "http://api.tuta.com".to_string(), + ) + } + + async fn maps_unencrypted_data_and_response(http_method: HttpMethod) -> ServiceExecutor { + let executor = setup(); + let rest_client; + let entity_facade; + unsafe { + rest_client = Arc::as_ptr(&executor.rest_client) + .cast::() + .cast_mut() + .as_mut() + .unwrap(); + entity_facade = Arc::as_ptr(&executor.entity_facade) + .cast::() + .cast_mut() + .as_mut() + .unwrap(); + } + + rest_client + .expect_request_binary() + .return_once(move |url, method, opts| { + assert_eq!( + "http://api.tuta.com/rest/test/unencrypted-hello", + url.as_str() + ); + assert_eq!(http_method, method); + + let expected_headers = [ + ("v", APP_VERSION_STR), + ("accessToken", "access_token"), + ("cv", "1.2.3"), + ] + .into_iter() + .map(|(a, b)| (a.to_string(), b.to_string())) + .collect::>(); + assert_eq!(expected_headers, opts.headers); + let expected_body = + serde_json::from_str::(r#"{"message":"Something"}"#).unwrap(); + let body = + serde_json::from_slice::(opts.body.unwrap().as_slice()).unwrap(); + assert_eq!(expected_body, body); + + Ok(RestResponse { + status: 200, + headers: HashMap::new(), + body: Some( + br#"{"answer":"Response to some request","timestamp":"3000"}"#.to_vec(), + ), + }) + }); + + entity_facade + .expect_encrypt_and_map_to_literal() + .return_once(|_, entity, sk| { + assert_eq!(None, sk); + Ok(entity.clone()) + }); + + executor + } + + pub async fn maps_encrypted_data_and_response_data( + http_method: HttpMethod, + session_key: GenericAesKey, + ) -> ServiceExecutor { + let executor = setup(); + let crypto_facade; + let rest_client; + let entity_facade; + unsafe { + crypto_facade = Arc::as_ptr(&executor.crypto_facade) + .cast::() + .cast_mut() + .as_mut() + .unwrap(); + rest_client = Arc::as_ptr(&executor.rest_client) + .cast::() + .cast_mut() + .as_mut() + .unwrap(); + + entity_facade = Arc::as_ptr(&executor.entity_facade) + .cast::() + .cast_mut() + .as_mut() + .unwrap(); + } + let owner_enc_session_key = [rand::random(); 32].to_vec(); + + rest_client + .expect_request_binary() + .return_once(move |url, method, opts| { + assert_eq!( + "http://api.tuta.com/rest/test/encrypted-hello", + url.as_str() + ); + assert_eq!(http_method, method); + let expected_body = + serde_json::from_str::(r#"{"message": "my encrypted request"}"#) + .unwrap(); + let body = + serde_json::from_slice::(opts.body.unwrap().as_slice()).unwrap(); + assert_eq!(expected_body, body); + let expected_headers = [ + ("accessToken", "access_token"), + ("cv", "1.2.3"), + ("v", APP_VERSION_STR), + ] + .into_iter() + .map(|(a, b)| (a.to_string(), b.to_string())) + .collect::>(); + assert_eq!(expected_headers, opts.headers); + Ok(RestResponse { + status: 200, + headers: HashMap::new(), + body: Some( + br#"{ "answer":"bXkgc2VjcmV0IHJlc3BvbnNl","timestamp":"MzAwMA==" }"# + .to_vec(), + ), + }) + }); + + let session_key_clone = session_key.clone(); + crypto_facade + .expect_resolve_session_key() + .returning(move |_entity, model| { + assert_eq!(("test", "HelloEncOutput"), (model.app, model.name)); + assert_eq!(true, model.marked_encrypted()); + + Ok(Some(ResolvedSessionKey { + session_key: session_key_clone.clone(), + owner_enc_session_key: owner_enc_session_key.clone(), + })) + }); + + let session_key_clone = session_key.clone(); + entity_facade + .expect_encrypt_and_map_to_literal() + .return_once(move |_, instance, sk| { + assert_eq!(Some(session_key_clone), sk); + Ok(instance.clone()) + }); + + let session_key_clone = session_key.clone(); + entity_facade.expect_decrypt_and_map().return_once( + move |_, mut entity, resolved_session_key| { + assert_eq!(session_key_clone, resolved_session_key.session_key); + assert_eq!( + &ElementValue::Bytes(BASE64_STANDARD.decode(r#"MzAwMA=="#).unwrap()), + entity.get("timestamp").unwrap() + ); + assert_eq!( + &ElementValue::Bytes( + BASE64_STANDARD + .decode(r#"bXkgc2VjcmV0IHJlc3BvbnNl"#) + .unwrap() + ), + entity.get("answer").unwrap() + ); + + entity.insert( + "answer".to_string(), + ElementValue::String(String::from("my secret response")), + ); + entity.insert( + "timestamp".to_string(), + ElementValue::Date(DateTime::from_millis(3000)), + ); + entity.insert("_finalIvs".to_string(), ElementValue::Dict(HashMap::new())); + Ok(entity.clone()) + }, + ); + + executor + } +} diff --git a/tuta-sdk/rust/sdk/src/services/storage.rs b/tuta-sdk/rust/sdk/src/services/storage.rs new file mode 100644 index 000000000000..03a8713cfce8 --- /dev/null +++ b/tuta-sdk/rust/sdk/src/services/storage.rs @@ -0,0 +1,30 @@ +#![allow(unused_imports, dead_code, unused_variables)] +use crate::ApiCallError; +use crate::entities::Entity; +use crate::services::{PostService, GetService, PutService, DeleteService, Service, Executor, ExtraServiceParams}; +use crate::rest_client::HttpMethod; +use crate::services::hidden::Nothing; +use crate::entities::storage::BlobAccessTokenPostIn; +use crate::entities::storage::BlobAccessTokenPostOut; +use crate::entities::storage::BlobReferencePutIn; +use crate::entities::storage::BlobReferenceDeleteIn; +use crate::entities::storage::BlobPostOut; +use crate::entities::storage::BlobGetIn; +pub struct BlobAccessTokenService; + +crate::service_impl!(base, BlobAccessTokenService, "storage/blobaccesstokenservice", 9); +crate::service_impl!(POST, BlobAccessTokenService, BlobAccessTokenPostIn, BlobAccessTokenPostOut); + + +pub struct BlobReferenceService; + +crate::service_impl!(base, BlobReferenceService, "storage/blobreferenceservice", 9); +crate::service_impl!(PUT, BlobReferenceService, BlobReferencePutIn, ()); +crate::service_impl!(DELETE, BlobReferenceService, BlobReferenceDeleteIn, ()); + + +pub struct BlobService; + +crate::service_impl!(base, BlobService, "storage/blobservice", 9); +crate::service_impl!(POST, BlobService, (), BlobPostOut); +crate::service_impl!(GET, BlobService, BlobGetIn, ()); diff --git a/tuta-sdk/rust/sdk/src/services/sys.rs b/tuta-sdk/rust/sdk/src/services/sys.rs new file mode 100644 index 000000000000..2479973fc3cd --- /dev/null +++ b/tuta-sdk/rust/sdk/src/services/sys.rs @@ -0,0 +1,408 @@ +#![allow(unused_imports, dead_code, unused_variables)] +use crate::ApiCallError; +use crate::entities::Entity; +use crate::services::{PostService, GetService, PutService, DeleteService, Service, Executor, ExtraServiceParams}; +use crate::rest_client::HttpMethod; +use crate::services::hidden::Nothing; +use crate::entities::sys::AdminGroupKeyRotationPostIn; +use crate::entities::sys::AffiliatePartnerKpiServiceGetOut; +use crate::entities::sys::AlarmServicePost; +use crate::entities::sys::AutoLoginDataReturn; +use crate::entities::sys::AutoLoginPostReturn; +use crate::entities::sys::AutoLoginDataGet; +use crate::entities::sys::AutoLoginDataDelete; +use crate::entities::sys::BrandingDomainData; +use crate::entities::sys::BrandingDomainGetReturn; +use crate::entities::sys::BrandingDomainDeleteData; +use crate::entities::sys::ChangeKdfPostIn; +use crate::entities::sys::ChangePasswordPostIn; +use crate::entities::sys::CloseSessionServicePost; +use crate::entities::sys::CreateCustomerServerPropertiesData; +use crate::entities::sys::CreateCustomerServerPropertiesReturn; +use crate::entities::sys::CustomDomainCheckGetIn; +use crate::entities::sys::CustomDomainCheckGetOut; +use crate::entities::sys::CustomDomainData; +use crate::entities::sys::CustomDomainReturn; +use crate::entities::sys::CustomerAccountTerminationPostIn; +use crate::entities::sys::CustomerAccountTerminationPostOut; +use crate::entities::sys::PublicKeyGetOut; +use crate::entities::sys::DeleteCustomerData; +use crate::entities::sys::DebitServicePutData; +use crate::entities::sys::DomainMailAddressAvailabilityData; +use crate::entities::sys::DomainMailAddressAvailabilityReturn; +use crate::entities::sys::ExternalPropertiesReturn; +use crate::entities::sys::GiftCardRedeemData; +use crate::entities::sys::GiftCardRedeemGetReturn; +use crate::entities::sys::GiftCardCreateData; +use crate::entities::sys::GiftCardCreateReturn; +use crate::entities::sys::GiftCardGetReturn; +use crate::entities::sys::GiftCardDeleteData; +use crate::entities::sys::GroupKeyRotationInfoGetOut; +use crate::entities::sys::GroupKeyRotationPostIn; +use crate::entities::sys::InvoiceDataGetIn; +use crate::entities::sys::InvoiceDataGetOut; +use crate::entities::sys::LocationServiceGetReturn; +use crate::entities::sys::MailAddressAliasServiceData; +use crate::entities::sys::MailAddressAliasGetIn; +use crate::entities::sys::MailAddressAliasServiceReturn; +use crate::entities::sys::MailAddressAliasServiceDataDelete; +use crate::entities::sys::MembershipAddData; +use crate::entities::sys::MembershipPutIn; +use crate::entities::sys::MembershipRemoveData; +use crate::entities::sys::MultipleMailAddressAvailabilityData; +use crate::entities::sys::MultipleMailAddressAvailabilityReturn; +use crate::entities::sys::PaymentDataServicePostData; +use crate::entities::sys::PaymentDataServiceGetData; +use crate::entities::sys::PaymentDataServiceGetReturn; +use crate::entities::sys::PaymentDataServicePutData; +use crate::entities::sys::PaymentDataServicePutReturn; +use crate::entities::sys::PlanServiceGetOut; +use crate::entities::sys::PriceServiceData; +use crate::entities::sys::PriceServiceReturn; +use crate::entities::sys::PublicKeyGetIn; +use crate::entities::sys::PublicKeyPutIn; +use crate::entities::sys::ReferralCodePostIn; +use crate::entities::sys::ReferralCodePostOut; +use crate::entities::sys::ReferralCodeGetIn; +use crate::entities::sys::RegistrationCaptchaServiceData; +use crate::entities::sys::RegistrationCaptchaServiceGetData; +use crate::entities::sys::RegistrationCaptchaServiceReturn; +use crate::entities::sys::RegistrationServiceData; +use crate::entities::sys::RegistrationReturn; +use crate::entities::sys::ResetFactorsDeleteData; +use crate::entities::sys::ResetPasswordPostIn; +use crate::entities::sys::SaltData; +use crate::entities::sys::SaltReturn; +use crate::entities::sys::SecondFactorAuthAllowedReturn; +use crate::entities::sys::SecondFactorAuthData; +use crate::entities::sys::SecondFactorAuthGetData; +use crate::entities::sys::SecondFactorAuthGetReturn; +use crate::entities::sys::SecondFactorAuthDeleteData; +use crate::entities::sys::CreateSessionData; +use crate::entities::sys::CreateSessionReturn; +use crate::entities::sys::SignOrderProcessingAgreementData; +use crate::entities::sys::SwitchAccountTypePostIn; +use crate::entities::sys::SystemKeysReturn; +use crate::entities::sys::TakeOverDeletedAddressData; +use crate::entities::sys::UpdatePermissionKeyData; +use crate::entities::sys::UpdateSessionKeysPostIn; +use crate::entities::sys::UpgradePriceServiceData; +use crate::entities::sys::UpgradePriceServiceReturn; +use crate::entities::sys::UserGroupKeyRotationPostIn; +use crate::entities::sys::UserDataDelete; +use crate::entities::sys::VersionData; +use crate::entities::sys::VersionReturn; +pub struct AdminGroupKeyRotationService; + +crate::service_impl!(base, AdminGroupKeyRotationService, "sys/admingroupkeyrotationservice", 111); +crate::service_impl!(POST, AdminGroupKeyRotationService, AdminGroupKeyRotationPostIn, ()); + + +pub struct AffiliatePartnerKpiService; + +crate::service_impl!(base, AffiliatePartnerKpiService, "sys/affiliatepartnerkpiservice", 111); +crate::service_impl!(GET, AffiliatePartnerKpiService, (), AffiliatePartnerKpiServiceGetOut); + + +pub struct AlarmService; + +crate::service_impl!(base, AlarmService, "sys/alarmservice", 111); +crate::service_impl!(POST, AlarmService, AlarmServicePost, ()); + + +pub struct AutoLoginService; + +crate::service_impl!(base, AutoLoginService, "sys/autologinservice", 111); +crate::service_impl!(POST, AutoLoginService, AutoLoginDataReturn, AutoLoginPostReturn); +crate::service_impl!(GET, AutoLoginService, AutoLoginDataGet, AutoLoginDataReturn); +crate::service_impl!(DELETE, AutoLoginService, AutoLoginDataDelete, ()); + + +pub struct BrandingDomainService; + +crate::service_impl!(base, BrandingDomainService, "sys/brandingdomainservice", 111); +crate::service_impl!(POST, BrandingDomainService, BrandingDomainData, ()); +crate::service_impl!(GET, BrandingDomainService, (), BrandingDomainGetReturn); +crate::service_impl!(PUT, BrandingDomainService, BrandingDomainData, ()); +crate::service_impl!(DELETE, BrandingDomainService, BrandingDomainDeleteData, ()); + + +pub struct ChangeKdfService; + +crate::service_impl!(base, ChangeKdfService, "sys/changekdfservice", 111); +crate::service_impl!(POST, ChangeKdfService, ChangeKdfPostIn, ()); + + +pub struct ChangePasswordService; + +crate::service_impl!(base, ChangePasswordService, "sys/changepasswordservice", 111); +crate::service_impl!(POST, ChangePasswordService, ChangePasswordPostIn, ()); + + +pub struct CloseSessionService; + +crate::service_impl!(base, CloseSessionService, "sys/closesessionservice", 111); +crate::service_impl!(POST, CloseSessionService, CloseSessionServicePost, ()); + + +pub struct CreateCustomerServerProperties; + +crate::service_impl!(base, CreateCustomerServerProperties, "sys/createcustomerserverproperties", 111); +crate::service_impl!(POST, CreateCustomerServerProperties, CreateCustomerServerPropertiesData, CreateCustomerServerPropertiesReturn); + + +pub struct CustomDomainCheckService; + +crate::service_impl!(base, CustomDomainCheckService, "sys/customdomaincheckservice", 111); +crate::service_impl!(GET, CustomDomainCheckService, CustomDomainCheckGetIn, CustomDomainCheckGetOut); + + +pub struct CustomDomainService; + +crate::service_impl!(base, CustomDomainService, "sys/customdomainservice", 111); +crate::service_impl!(POST, CustomDomainService, CustomDomainData, CustomDomainReturn); +crate::service_impl!(PUT, CustomDomainService, CustomDomainData, ()); +crate::service_impl!(DELETE, CustomDomainService, CustomDomainData, ()); + + +pub struct CustomerAccountTerminationService; + +crate::service_impl!(base, CustomerAccountTerminationService, "sys/customeraccountterminationservice", 111); +crate::service_impl!(POST, CustomerAccountTerminationService, CustomerAccountTerminationPostIn, CustomerAccountTerminationPostOut); + + +pub struct CustomerPublicKeyService; + +crate::service_impl!(base, CustomerPublicKeyService, "sys/customerpublickeyservice", 111); +crate::service_impl!(GET, CustomerPublicKeyService, (), PublicKeyGetOut); + + +pub struct CustomerService; + +crate::service_impl!(base, CustomerService, "sys/customerservice", 111); +crate::service_impl!(DELETE, CustomerService, DeleteCustomerData, ()); + + +pub struct DebitService; + +crate::service_impl!(base, DebitService, "sys/debitservice", 111); +crate::service_impl!(PUT, DebitService, DebitServicePutData, ()); + + +pub struct DomainMailAddressAvailabilityService; + +crate::service_impl!(base, DomainMailAddressAvailabilityService, "sys/domainmailaddressavailabilityservice", 111); +crate::service_impl!(GET, DomainMailAddressAvailabilityService, DomainMailAddressAvailabilityData, DomainMailAddressAvailabilityReturn); + + +pub struct ExternalPropertiesService; + +crate::service_impl!(base, ExternalPropertiesService, "sys/externalpropertiesservice", 111); +crate::service_impl!(GET, ExternalPropertiesService, (), ExternalPropertiesReturn); + + +pub struct GiftCardRedeemService; + +crate::service_impl!(base, GiftCardRedeemService, "sys/giftcardredeemservice", 111); +crate::service_impl!(POST, GiftCardRedeemService, GiftCardRedeemData, ()); +crate::service_impl!(GET, GiftCardRedeemService, GiftCardRedeemData, GiftCardRedeemGetReturn); + + +pub struct GiftCardService; + +crate::service_impl!(base, GiftCardService, "sys/giftcardservice", 111); +crate::service_impl!(POST, GiftCardService, GiftCardCreateData, GiftCardCreateReturn); +crate::service_impl!(GET, GiftCardService, (), GiftCardGetReturn); +crate::service_impl!(DELETE, GiftCardService, GiftCardDeleteData, ()); + + +pub struct GroupKeyRotationInfoService; + +crate::service_impl!(base, GroupKeyRotationInfoService, "sys/groupkeyrotationinfoservice", 111); +crate::service_impl!(GET, GroupKeyRotationInfoService, (), GroupKeyRotationInfoGetOut); + + +pub struct GroupKeyRotationService; + +crate::service_impl!(base, GroupKeyRotationService, "sys/groupkeyrotationservice", 111); +crate::service_impl!(POST, GroupKeyRotationService, GroupKeyRotationPostIn, ()); + + +pub struct InvoiceDataService; + +crate::service_impl!(base, InvoiceDataService, "sys/invoicedataservice", 111); +crate::service_impl!(GET, InvoiceDataService, InvoiceDataGetIn, InvoiceDataGetOut); + + +pub struct LocationService; + +crate::service_impl!(base, LocationService, "sys/locationservice", 111); +crate::service_impl!(GET, LocationService, (), LocationServiceGetReturn); + + +pub struct MailAddressAliasService; + +crate::service_impl!(base, MailAddressAliasService, "sys/mailaddressaliasservice", 111); +crate::service_impl!(POST, MailAddressAliasService, MailAddressAliasServiceData, ()); +crate::service_impl!(GET, MailAddressAliasService, MailAddressAliasGetIn, MailAddressAliasServiceReturn); +crate::service_impl!(DELETE, MailAddressAliasService, MailAddressAliasServiceDataDelete, ()); + + +pub struct MembershipService; + +crate::service_impl!(base, MembershipService, "sys/membershipservice", 111); +crate::service_impl!(POST, MembershipService, MembershipAddData, ()); +crate::service_impl!(PUT, MembershipService, MembershipPutIn, ()); +crate::service_impl!(DELETE, MembershipService, MembershipRemoveData, ()); + + +pub struct MultipleMailAddressAvailabilityService; + +crate::service_impl!(base, MultipleMailAddressAvailabilityService, "sys/multiplemailaddressavailabilityservice", 111); +crate::service_impl!(GET, MultipleMailAddressAvailabilityService, MultipleMailAddressAvailabilityData, MultipleMailAddressAvailabilityReturn); + + +pub struct PaymentDataService; + +crate::service_impl!(base, PaymentDataService, "sys/paymentdataservice", 111); +crate::service_impl!(POST, PaymentDataService, PaymentDataServicePostData, ()); +crate::service_impl!(GET, PaymentDataService, PaymentDataServiceGetData, PaymentDataServiceGetReturn); +crate::service_impl!(PUT, PaymentDataService, PaymentDataServicePutData, PaymentDataServicePutReturn); + + +pub struct PlanService; + +crate::service_impl!(base, PlanService, "sys/planservice", 111); +crate::service_impl!(GET, PlanService, (), PlanServiceGetOut); + + +pub struct PriceService; + +crate::service_impl!(base, PriceService, "sys/priceservice", 111); +crate::service_impl!(GET, PriceService, PriceServiceData, PriceServiceReturn); + + +pub struct PublicKeyService; + +crate::service_impl!(base, PublicKeyService, "sys/publickeyservice", 111); +crate::service_impl!(GET, PublicKeyService, PublicKeyGetIn, PublicKeyGetOut); +crate::service_impl!(PUT, PublicKeyService, PublicKeyPutIn, ()); + + +pub struct ReferralCodeService; + +crate::service_impl!(base, ReferralCodeService, "sys/referralcodeservice", 111); +crate::service_impl!(POST, ReferralCodeService, ReferralCodePostIn, ReferralCodePostOut); +crate::service_impl!(GET, ReferralCodeService, ReferralCodeGetIn, ()); + + +pub struct RegistrationCaptchaService; + +crate::service_impl!(base, RegistrationCaptchaService, "sys/registrationcaptchaservice", 111); +crate::service_impl!(POST, RegistrationCaptchaService, RegistrationCaptchaServiceData, ()); +crate::service_impl!(GET, RegistrationCaptchaService, RegistrationCaptchaServiceGetData, RegistrationCaptchaServiceReturn); + + +pub struct RegistrationService; + +crate::service_impl!(base, RegistrationService, "sys/registrationservice", 111); +crate::service_impl!(POST, RegistrationService, RegistrationServiceData, RegistrationReturn); +crate::service_impl!(GET, RegistrationService, (), RegistrationServiceData); + + +pub struct ResetFactorsService; + +crate::service_impl!(base, ResetFactorsService, "sys/resetfactorsservice", 111); +crate::service_impl!(DELETE, ResetFactorsService, ResetFactorsDeleteData, ()); + + +pub struct ResetPasswordService; + +crate::service_impl!(base, ResetPasswordService, "sys/resetpasswordservice", 111); +crate::service_impl!(POST, ResetPasswordService, ResetPasswordPostIn, ()); + + +pub struct SaltService; + +crate::service_impl!(base, SaltService, "sys/saltservice", 111); +crate::service_impl!(GET, SaltService, SaltData, SaltReturn); + + +pub struct SecondFactorAuthAllowedService; + +crate::service_impl!(base, SecondFactorAuthAllowedService, "sys/secondfactorauthallowedservice", 111); +crate::service_impl!(GET, SecondFactorAuthAllowedService, (), SecondFactorAuthAllowedReturn); + + +pub struct SecondFactorAuthService; + +crate::service_impl!(base, SecondFactorAuthService, "sys/secondfactorauthservice", 111); +crate::service_impl!(POST, SecondFactorAuthService, SecondFactorAuthData, ()); +crate::service_impl!(GET, SecondFactorAuthService, SecondFactorAuthGetData, SecondFactorAuthGetReturn); +crate::service_impl!(DELETE, SecondFactorAuthService, SecondFactorAuthDeleteData, ()); + + +pub struct SessionService; + +crate::service_impl!(base, SessionService, "sys/sessionservice", 111); +crate::service_impl!(POST, SessionService, CreateSessionData, CreateSessionReturn); + + +pub struct SignOrderProcessingAgreementService; + +crate::service_impl!(base, SignOrderProcessingAgreementService, "sys/signorderprocessingagreementservice", 111); +crate::service_impl!(POST, SignOrderProcessingAgreementService, SignOrderProcessingAgreementData, ()); + + +pub struct SwitchAccountTypeService; + +crate::service_impl!(base, SwitchAccountTypeService, "sys/switchaccounttypeservice", 111); +crate::service_impl!(POST, SwitchAccountTypeService, SwitchAccountTypePostIn, ()); + + +pub struct SystemKeysService; + +crate::service_impl!(base, SystemKeysService, "sys/systemkeysservice", 111); +crate::service_impl!(GET, SystemKeysService, (), SystemKeysReturn); + + +pub struct TakeOverDeletedAddressService; + +crate::service_impl!(base, TakeOverDeletedAddressService, "sys/takeoverdeletedaddressservice", 111); +crate::service_impl!(POST, TakeOverDeletedAddressService, TakeOverDeletedAddressData, ()); + + +pub struct UpdatePermissionKeyService; + +crate::service_impl!(base, UpdatePermissionKeyService, "sys/updatepermissionkeyservice", 111); +crate::service_impl!(POST, UpdatePermissionKeyService, UpdatePermissionKeyData, ()); + + +pub struct UpdateSessionKeysService; + +crate::service_impl!(base, UpdateSessionKeysService, "sys/updatesessionkeysservice", 111); +crate::service_impl!(POST, UpdateSessionKeysService, UpdateSessionKeysPostIn, ()); + + +pub struct UpgradePriceService; + +crate::service_impl!(base, UpgradePriceService, "sys/upgradepriceservice", 111); +crate::service_impl!(GET, UpgradePriceService, UpgradePriceServiceData, UpgradePriceServiceReturn); + + +pub struct UserGroupKeyRotationService; + +crate::service_impl!(base, UserGroupKeyRotationService, "sys/usergroupkeyrotationservice", 111); +crate::service_impl!(POST, UserGroupKeyRotationService, UserGroupKeyRotationPostIn, ()); + + +pub struct UserService; + +crate::service_impl!(base, UserService, "sys/userservice", 111); +crate::service_impl!(DELETE, UserService, UserDataDelete, ()); + + +pub struct VersionService; + +crate::service_impl!(base, VersionService, "sys/versionservice", 111); +crate::service_impl!(GET, VersionService, VersionData, VersionReturn); diff --git a/tuta-sdk/rust/sdk/src/services/test_services.rs b/tuta-sdk/rust/sdk/src/services/test_services.rs new file mode 100644 index 000000000000..0e0d46937b07 --- /dev/null +++ b/tuta-sdk/rust/sdk/src/services/test_services.rs @@ -0,0 +1,216 @@ +use crate::date::DateTime; +use crate::entities::{Entity, FinalIv}; +use crate::metamodel::TypeModel; +use crate::services::GetService; +use crate::type_model_provider::{AppName, TypeName}; +use crate::{service_impl, TypeRef}; +use serde::{Deserialize, Serialize}; +use std::collections::HashMap; + +pub const APP_NAME: &str = "test"; +pub const APP_VERSION_NUMBER: u32 = 75; +pub const APP_VERSION_STR: &str = "75"; + +pub const HELLO_OUTPUT_ENCRYPTED: &str = r#"{ + "name": "HelloEncOutput", + "since": 7, + "type": "DATA_TRANSFER_TYPE", + "id": 458, + "rootId": "CHR1dGFub3RhAAHK", + "versioned": false, + "encrypted": true, + "values": { + "answer": { + "final": false, + "name": "answer", + "id": 459, + "since": 7, + "type": "String", + "cardinality": "One", + "encrypted": true + }, + "timestamp": { + "final": false, + "name": "timestamp", + "id": 460, + "since": 7, + "type": "Date", + "cardinality": "One", + "encrypted": true + } + }, + "associations": {}, + "app": "test", + "version": "75" + }"#; +pub const HELLO_INPUT_ENCRYPTED: &str = r#"{ + "name": "HelloEncInput", + "since": 7, + "type": "DATA_TRANSFER_TYPE", + "id": 358, + "rootId": "RDR1dGFub3RhAAHK", + "versioned": false, + "encrypted": true, + "values": { + "message": { + "final": false, + "name": "message", + "id": 359, + "since": 7, + "type": "String", + "cardinality": "One", + "encrypted": true + } + }, + "associations": {}, + "app": "test", + "version": "75" + }"#; + +pub const HELLO_OUTPUT_UNENCRYPTED: &str = r#"{ + "name": "HelloUnEncOutput", + "since": 7, + "type": "DATA_TRANSFER_TYPE", + "id": 458, + "rootId": "CHR1dGFub3RhAAHK", + "versioned": false, + "encrypted": false, + "values": { + "answer": { + "final": false, + "name": "answer", + "id": 159, + "since": 7, + "type": "String", + "cardinality": "One", + "encrypted": false + }, + "timestamp": { + "final": false, + "name": "timestamp", + "id": 160, + "since": 7, + "type": "Date", + "cardinality": "One", + "encrypted": false + } + }, + "associations": {}, + "app": "test", + "version": "75" + }"#; +pub const HELLO_INPUT_UNENCRYPTED: &str = r#"{ + "name": "HelloUnEncInput", + "since": 7, + "type": "DATA_TRANSFER_TYPE", + "id": 148, + "rootId": "RDR1dGFub3RhAAHK", + "versioned": false, + "encrypted": false, + "values": { + "message": { + "final": false, + "name": "message", + "id": 149, + "since": 7, + "type": "String", + "cardinality": "One", + "encrypted": false + } + }, + "associations": {}, + "app": "test", + "version": "75" + }"#; + +pub fn extend_model_resolver(model_resolver: &mut HashMap>) { + assert!(model_resolver.get("test").is_none()); + + let enc_input_type_model = serde_json::from_str::(HELLO_INPUT_ENCRYPTED).unwrap(); + let enc_output_type_model = serde_json::from_str::(HELLO_OUTPUT_ENCRYPTED).unwrap(); + let unenc_input_type_model = serde_json::from_str::(HELLO_INPUT_UNENCRYPTED).unwrap(); + let unenc_output_type_model = serde_json::from_str::(HELLO_OUTPUT_UNENCRYPTED).unwrap(); + + let test_types = [ + ("HelloEncInput", enc_input_type_model), + ("HelloEncOutput", enc_output_type_model), + ("HelloUnEncInput", unenc_input_type_model), + ("HelloUnEncOutput", unenc_output_type_model) + ].into_iter().collect(); + model_resolver.insert("test", test_types); +} + + +pub struct HelloEncryptedService; +pub struct HelloUnEncryptedService; + +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)] +pub struct HelloEncInput { + pub message: String, +} +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)] +pub struct HelloEncOutput { + pub answer: String, + pub timestamp: DateTime, + pub _finalIvs: HashMap, +} + +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)] +pub struct HelloUnEncInput { + pub message: String, +} +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)] +pub struct HelloUnEncOutput { + pub answer: String, + pub timestamp: DateTime, +} + +impl Entity for HelloEncInput { + fn type_ref() -> TypeRef { + TypeRef { + app: "test", + type_: "HelloEncInput", + } + } +} + + +impl Entity for HelloEncOutput { + fn type_ref() -> TypeRef { + TypeRef { + app: "test", + type_: "HelloEncOutput", + } + } +} + +impl Entity for HelloUnEncInput { + fn type_ref() -> TypeRef { + TypeRef { + app: "test", + type_: "HelloUnEncInput", + } + } +} + + +impl Entity for HelloUnEncOutput { + fn type_ref() -> TypeRef { + TypeRef { + app: "test", + type_: "HelloUnEncOutput", + } + } +} + +service_impl!(base, HelloEncryptedService, "test/encrypted-hello", APP_VERSION_NUMBER); +service_impl!(POST, HelloEncryptedService, HelloEncInput, HelloEncOutput); +service_impl!(PUT, HelloEncryptedService, HelloEncInput, HelloEncOutput); +service_impl!(GET, HelloEncryptedService, HelloEncInput, HelloEncOutput); +service_impl!(DELETE, HelloEncryptedService, HelloEncInput, HelloEncOutput); + +service_impl!(base, HelloUnEncryptedService, "test/unencrypted-hello", APP_VERSION_NUMBER); +service_impl!(POST, HelloUnEncryptedService, HelloUnEncInput, HelloUnEncOutput); +service_impl!(PUT, HelloUnEncryptedService, HelloUnEncInput, HelloUnEncOutput); +service_impl!(GET, HelloUnEncryptedService, HelloUnEncInput, HelloUnEncOutput); +service_impl!(DELETE, HelloUnEncryptedService, HelloUnEncInput, HelloUnEncOutput); \ No newline at end of file diff --git a/tuta-sdk/rust/sdk/src/services/tutanota.rs b/tuta-sdk/rust/sdk/src/services/tutanota.rs new file mode 100644 index 000000000000..6a369eb9636e --- /dev/null +++ b/tuta-sdk/rust/sdk/src/services/tutanota.rs @@ -0,0 +1,168 @@ +#![allow(unused_imports, dead_code, unused_variables)] +use crate::ApiCallError; +use crate::entities::Entity; +use crate::services::{PostService, GetService, PutService, DeleteService, Service, Executor, ExtraServiceParams}; +use crate::rest_client::HttpMethod; +use crate::services::hidden::Nothing; +use crate::entities::tutanota::UserAreaGroupPostData; +use crate::entities::tutanota::CreateGroupPostReturn; +use crate::entities::tutanota::CalendarDeleteData; +use crate::entities::tutanota::UserAreaGroupDeleteData; +use crate::entities::tutanota::CustomerAccountCreateData; +use crate::entities::tutanota::DraftCreateData; +use crate::entities::tutanota::DraftCreateReturn; +use crate::entities::tutanota::DraftUpdateData; +use crate::entities::tutanota::DraftUpdateReturn; +use crate::entities::tutanota::EncryptTutanotaPropertiesData; +use crate::entities::tutanota::EntropyData; +use crate::entities::tutanota::ExternalUserData; +use crate::entities::tutanota::GroupInvitationPostData; +use crate::entities::tutanota::GroupInvitationPostReturn; +use crate::entities::tutanota::GroupInvitationPutData; +use crate::entities::tutanota::GroupInvitationDeleteData; +use crate::entities::tutanota::ListUnsubscribeData; +use crate::entities::tutanota::CreateMailFolderData; +use crate::entities::tutanota::CreateMailFolderReturn; +use crate::entities::tutanota::UpdateMailFolderData; +use crate::entities::tutanota::DeleteMailFolderData; +use crate::entities::tutanota::CreateMailGroupData; +use crate::entities::tutanota::DeleteGroupData; +use crate::entities::tutanota::DeleteMailData; +use crate::entities::tutanota::MoveMailData; +use crate::entities::tutanota::NewsIn; +use crate::entities::tutanota::NewsOut; +use crate::entities::tutanota::ReceiveInfoServiceData; +use crate::entities::tutanota::ReportMailPostData; +use crate::entities::tutanota::SendDraftData; +use crate::entities::tutanota::SendDraftReturn; +use crate::entities::tutanota::TranslationGetIn; +use crate::entities::tutanota::TranslationGetOut; +use crate::entities::tutanota::UserAccountCreateData; +pub struct CalendarService; + +crate::service_impl!(base, CalendarService, "tutanota/calendarservice", 75); +crate::service_impl!(POST, CalendarService, UserAreaGroupPostData, CreateGroupPostReturn); +crate::service_impl!(DELETE, CalendarService, CalendarDeleteData, ()); + + +pub struct ContactListGroupService; + +crate::service_impl!(base, ContactListGroupService, "tutanota/contactlistgroupservice", 75); +crate::service_impl!(POST, ContactListGroupService, UserAreaGroupPostData, CreateGroupPostReturn); +crate::service_impl!(DELETE, ContactListGroupService, UserAreaGroupDeleteData, ()); + + +pub struct CustomerAccountService; + +crate::service_impl!(base, CustomerAccountService, "tutanota/customeraccountservice", 75); +crate::service_impl!(POST, CustomerAccountService, CustomerAccountCreateData, ()); + + +pub struct DraftService; + +crate::service_impl!(base, DraftService, "tutanota/draftservice", 75); +crate::service_impl!(POST, DraftService, DraftCreateData, DraftCreateReturn); +crate::service_impl!(PUT, DraftService, DraftUpdateData, DraftUpdateReturn); + + +pub struct EncryptTutanotaPropertiesService; + +crate::service_impl!(base, EncryptTutanotaPropertiesService, "tutanota/encrypttutanotapropertiesservice", 75); +crate::service_impl!(POST, EncryptTutanotaPropertiesService, EncryptTutanotaPropertiesData, ()); + + +pub struct EntropyService; + +crate::service_impl!(base, EntropyService, "tutanota/entropyservice", 75); +crate::service_impl!(PUT, EntropyService, EntropyData, ()); + + +pub struct ExternalUserService; + +crate::service_impl!(base, ExternalUserService, "tutanota/externaluserservice", 75); +crate::service_impl!(POST, ExternalUserService, ExternalUserData, ()); + + +pub struct GroupInvitationService; + +crate::service_impl!(base, GroupInvitationService, "tutanota/groupinvitationservice", 75); +crate::service_impl!(POST, GroupInvitationService, GroupInvitationPostData, GroupInvitationPostReturn); +crate::service_impl!(PUT, GroupInvitationService, GroupInvitationPutData, ()); +crate::service_impl!(DELETE, GroupInvitationService, GroupInvitationDeleteData, ()); + + +pub struct ListUnsubscribeService; + +crate::service_impl!(base, ListUnsubscribeService, "tutanota/listunsubscribeservice", 75); +crate::service_impl!(POST, ListUnsubscribeService, ListUnsubscribeData, ()); + + +pub struct MailFolderService; + +crate::service_impl!(base, MailFolderService, "tutanota/mailfolderservice", 75); +crate::service_impl!(POST, MailFolderService, CreateMailFolderData, CreateMailFolderReturn); +crate::service_impl!(PUT, MailFolderService, UpdateMailFolderData, ()); +crate::service_impl!(DELETE, MailFolderService, DeleteMailFolderData, ()); + + +pub struct MailGroupService; + +crate::service_impl!(base, MailGroupService, "tutanota/mailgroupservice", 75); +crate::service_impl!(POST, MailGroupService, CreateMailGroupData, ()); +crate::service_impl!(DELETE, MailGroupService, DeleteGroupData, ()); + + +pub struct MailService; + +crate::service_impl!(base, MailService, "tutanota/mailservice", 75); +crate::service_impl!(DELETE, MailService, DeleteMailData, ()); + + +pub struct MoveMailService; + +crate::service_impl!(base, MoveMailService, "tutanota/movemailservice", 75); +crate::service_impl!(POST, MoveMailService, MoveMailData, ()); + + +pub struct NewsService; + +crate::service_impl!(base, NewsService, "tutanota/newsservice", 75); +crate::service_impl!(POST, NewsService, NewsIn, ()); +crate::service_impl!(GET, NewsService, (), NewsOut); + + +pub struct ReceiveInfoService; + +crate::service_impl!(base, ReceiveInfoService, "tutanota/receiveinfoservice", 75); +crate::service_impl!(POST, ReceiveInfoService, ReceiveInfoServiceData, ()); + + +pub struct ReportMailService; + +crate::service_impl!(base, ReportMailService, "tutanota/reportmailservice", 75); +crate::service_impl!(POST, ReportMailService, ReportMailPostData, ()); + + +pub struct SendDraftService; + +crate::service_impl!(base, SendDraftService, "tutanota/senddraftservice", 75); +crate::service_impl!(POST, SendDraftService, SendDraftData, SendDraftReturn); + + +pub struct TemplateGroupService; + +crate::service_impl!(base, TemplateGroupService, "tutanota/templategroupservice", 75); +crate::service_impl!(POST, TemplateGroupService, UserAreaGroupPostData, CreateGroupPostReturn); +crate::service_impl!(DELETE, TemplateGroupService, UserAreaGroupDeleteData, ()); + + +pub struct TranslationService; + +crate::service_impl!(base, TranslationService, "tutanota/translationservice", 75); +crate::service_impl!(GET, TranslationService, TranslationGetIn, TranslationGetOut); + + +pub struct UserAccountService; + +crate::service_impl!(base, UserAccountService, "tutanota/useraccountservice", 75); +crate::service_impl!(POST, UserAccountService, UserAccountCreateData, ()); diff --git a/tuta-sdk/rust/sdk/src/services/usage.rs b/tuta-sdk/rust/sdk/src/services/usage.rs new file mode 100644 index 000000000000..0218931627c2 --- /dev/null +++ b/tuta-sdk/rust/sdk/src/services/usage.rs @@ -0,0 +1,20 @@ +#![allow(unused_imports, dead_code, unused_variables)] +use crate::ApiCallError; +use crate::entities::Entity; +use crate::services::{PostService, GetService, PutService, DeleteService, Service, Executor, ExtraServiceParams}; +use crate::rest_client::HttpMethod; +use crate::services::hidden::Nothing; +use crate::entities::usage::UsageTestAssignmentIn; +use crate::entities::usage::UsageTestAssignmentOut; +use crate::entities::usage::UsageTestParticipationIn; +pub struct UsageTestAssignmentService; + +crate::service_impl!(base, UsageTestAssignmentService, "usage/usagetestassignmentservice", 2); +crate::service_impl!(POST, UsageTestAssignmentService, UsageTestAssignmentIn, UsageTestAssignmentOut); +crate::service_impl!(PUT, UsageTestAssignmentService, UsageTestAssignmentIn, UsageTestAssignmentOut); + + +pub struct UsageTestParticipationService; + +crate::service_impl!(base, UsageTestParticipationService, "usage/usagetestparticipationservice", 2); +crate::service_impl!(POST, UsageTestParticipationService, UsageTestParticipationIn, ()); diff --git a/tuta-sdk/rust/sdk/src/type_model_provider.rs b/tuta-sdk/rust/sdk/src/type_model_provider.rs index 73e8b695d04f..cab77d38f4c5 100644 --- a/tuta-sdk/rust/sdk/src/type_model_provider.rs +++ b/tuta-sdk/rust/sdk/src/type_model_provider.rs @@ -10,19 +10,19 @@ pub type TypeName = &'static str; /// Contains a map between backend apps and entity/instance types within them pub struct TypeModelProvider { - app_models: HashMap>, + app_models: HashMap>, } impl TypeModelProvider { - pub fn new(app_models: HashMap>) -> TypeModelProvider { - TypeModelProvider { app_models } - } - - /// Gets an entity/instance type with a specified name in a backend app - pub fn get_type_model(&self, app_name: &str, entity_name: &str) -> Option<&TypeModel> { - let app_map = self.app_models.get(app_name)?; - app_map.get(entity_name) - } + pub fn new(app_models: HashMap>) -> TypeModelProvider { + TypeModelProvider { app_models } + } + + /// Gets an entity/instance type with a specified name in a backend app + pub fn get_type_model(&self, app_name: &str, entity_name: &str) -> Option<&TypeModel> { + let app_map = self.app_models.get(app_name)?; + app_map.get(entity_name) + } } // Reads all provided type models into a map. @@ -46,7 +46,7 @@ macro_rules! read_type_models { /// Creates a new `TypeModelProvider` populated with the type models from the JSON type model files pub fn init_type_model_provider() -> TypeModelProvider { - let type_model_map = read_type_models![ + let type_model_map = read_type_models![ "accounting", "base", "gossip", @@ -56,6 +56,6 @@ pub fn init_type_model_provider() -> TypeModelProvider { "tutanota", "usage" ]; - let type_model_provider = TypeModelProvider::new(type_model_map); - type_model_provider + let type_model_provider = TypeModelProvider::new(type_model_map); + type_model_provider } diff --git a/tuta-sdk/rust/sdk/src/typed_entity_client.rs b/tuta-sdk/rust/sdk/src/typed_entity_client.rs index c38c9720a9f6..50c90304441b 100644 --- a/tuta-sdk/rust/sdk/src/typed_entity_client.rs +++ b/tuta-sdk/rust/sdk/src/typed_entity_client.rs @@ -1,5 +1,5 @@ use crate::entities::Entity; -#[mockall_double::double] +#[cfg_attr(test, mockall_double::double)] use crate::entity_client::EntityClient; use crate::entity_client::IdType; use crate::generated_id::GeneratedId; diff --git a/tuta-sdk/rust/sdk/src/user_facade.rs b/tuta-sdk/rust/sdk/src/user_facade.rs index 69cb73ea29c2..d6737caa38cf 100644 --- a/tuta-sdk/rust/sdk/src/user_facade.rs +++ b/tuta-sdk/rust/sdk/src/user_facade.rs @@ -4,7 +4,7 @@ use crate::crypto::sha256; use crate::crypto::{Aes256Key, AES_256_KEY_SIZE}; use crate::entities::sys::{GroupMembership, User}; use crate::generated_id::GeneratedId; -#[mockall_double::double] +#[cfg_attr(test, mockall_double::double)] use crate::key_cache::KeyCache; use crate::key_loader_facade::VersionedAesKey; use crate::util::Versioned; diff --git a/tuta-sdk/rust/sdk/src/util/entity_test_utils.rs b/tuta-sdk/rust/sdk/src/util/entity_test_utils.rs index 533fedae2eca..096b9a759023 100644 --- a/tuta-sdk/rust/sdk/src/util/entity_test_utils.rs +++ b/tuta-sdk/rust/sdk/src/util/entity_test_utils.rs @@ -1,12 +1,13 @@ +use crate::crypto::aes::Iv; use crate::crypto::key::GenericAesKey; -use crate::crypto::Iv; use crate::date::DateTime; use crate::element_value::{ElementValue, ParsedEntity}; use crate::entities::tutanota::{Mail, MailAddress}; use crate::entities::Entity; +use crate::generated_id::GeneratedId; use crate::type_model_provider::{init_type_model_provider, TypeModelProvider}; use crate::util::test_utils::{create_test_entity, typed_entity_to_parsed_entity}; -use crate::TypeRef; +use crate::{IdTuple, TypeRef}; /// Generates and returns an encrypted Mail ParsedEntity. It also returns the decrypted Mail for comparison pub fn generate_email_entity( @@ -18,6 +19,10 @@ pub fn generate_email_entity( recipient_name: String, ) -> (ParsedEntity, ParsedEntity) { let original_mail = Mail { + _id: IdTuple { + list_id: GeneratedId("O1RT1m6-0R-0".to_string()), + element_id: GeneratedId("O1RT2Dj----0".to_string()), + }, receivedDate: DateTime::from_millis(1470039025474), confidential, subject, diff --git a/tuta-sdk/rust/sdk/src/util/mod.rs b/tuta-sdk/rust/sdk/src/util/mod.rs index 11e8fbb9b53f..9365cfee5849 100644 --- a/tuta-sdk/rust/sdk/src/util/mod.rs +++ b/tuta-sdk/rust/sdk/src/util/mod.rs @@ -1,7 +1,5 @@ -use crate::date::DateTime; -use crate::element_value::ElementValue; -use crate::metamodel::ValueType; -use base64::alphabet::Alphabet; +use base64::alphabet::{Alphabet, URL_SAFE}; +use base64::engine::general_purpose::NO_PAD; use base64::engine::GeneralPurpose; #[cfg(test)] @@ -198,18 +196,6 @@ pub fn array_cast_size( } } -pub(crate) fn resolve_default_value(value_type: &ValueType) -> ElementValue { - match value_type { - ValueType::String => ElementValue::String(String::new()), - ValueType::Number => ElementValue::Number(0), - ValueType::Bytes => ElementValue::Bytes(Vec::new()), - ValueType::Date => ElementValue::Date(DateTime::default()), - ValueType::Boolean => ElementValue::Bool(false), - ValueType::CompressedString => ElementValue::String(String::new()), - v => unreachable!("Invalid type {v:?}"), - } -} - #[cfg(test)] mod test { use super::*; diff --git a/tuta-sdk/rust/sdk/src/util/test_utils.rs b/tuta-sdk/rust/sdk/src/util/test_utils.rs index 374b60e9fc7f..50f64a2af80f 100644 --- a/tuta-sdk/rust/sdk/src/util/test_utils.rs +++ b/tuta-sdk/rust/sdk/src/util/test_utils.rs @@ -172,28 +172,28 @@ fn create_test_entity_dict_with_provider( Cardinality::Any => ElementValue::Array(Vec::new()), Cardinality::One => { match value.value_type { - ValueType::String => ElementValue::String(Default::default()), - ValueType::Number => ElementValue::Number(Default::default()), - ValueType::Bytes => ElementValue::Bytes(Default::default()), - ValueType::Date => ElementValue::Date(Default::default()), - ValueType::Boolean => ElementValue::Bool(Default::default()), - ValueType::GeneratedId => { - if name == "_id" && (model.element_type == ElementType::ListElement || model.element_type == ElementType::BlobElement) { - ElementValue::IdTupleId(IdTuple::new(GeneratedId::test_random(), GeneratedId::test_random())) - } else { - ElementValue::IdGeneratedId(GeneratedId::test_random()) - } - } - ValueType::CustomId => { - if name == "_id" && (model.element_type == ElementType::ListElement || model.element_type == ElementType::BlobElement) { - // TODO: adapt this when Custom Id tuples are supported - ElementValue::IdTupleId(IdTuple::new(GeneratedId::test_random(), GeneratedId::test_random())) - } else { - ElementValue::IdCustomId(CustomId::test_random()) - } - } - ValueType::CompressedString => todo!("Failed to create test entity {app}/{type_}: Compressed strings ({name}) are not yet supported!"), - } + ValueType::String => ElementValue::String(Default::default()), + ValueType::Number => ElementValue::Number(Default::default()), + ValueType::Bytes => ElementValue::Bytes(Default::default()), + ValueType::Date => ElementValue::Date(Default::default()), + ValueType::Boolean => ElementValue::Bool(Default::default()), + ValueType::GeneratedId => { + if name == "_id" && (model.element_type == ElementType::ListElement || model.element_type == ElementType::BlobElement) { + ElementValue::IdTupleId(IdTuple::new(GeneratedId::test_random(), GeneratedId::test_random())) + } else { + ElementValue::IdGeneratedId(GeneratedId::test_random()) + } + }, + ValueType::CustomId => { + if name == "_id" && (model.element_type == ElementType::ListElement || model.element_type == ElementType::BlobElement) { + // TODO: adapt this when Custom Id tuples are supported + ElementValue::IdTupleId(IdTuple::new(GeneratedId::test_random(), GeneratedId::test_random())) + } else { + ElementValue::IdCustomId(CustomId::test_random()) + } + }, + ValueType::CompressedString => todo!("Failed to create test entity {app}/{type_}: Compressed strings ({name}) are not yet supported!"), + } }, }; diff --git a/tuta-sdk/rust/sdk/tests/download_mail_test.rs b/tuta-sdk/rust/sdk/tests/download_mail_test.rs index 59182c097fe0..41f875171a99 100644 --- a/tuta-sdk/rust/sdk/tests/download_mail_test.rs +++ b/tuta-sdk/rust/sdk/tests/download_mail_test.rs @@ -1,84 +1,78 @@ -use std::sync::Arc; - -use base64::prelude::BASE64_STANDARD; -use base64::Engine; - -use tutasdk::generated_id::GeneratedId; -use tutasdk::login::{CredentialType, Credentials}; -use tutasdk::rest_client::{HttpMethod, RestClient}; -use tutasdk::{IdTuple, Sdk}; - -use crate::test_rest_client::TestRestClient; - mod test_rest_client; -#[tokio::test] -async fn test_download_mail() { - let rest_client = make_rest_client(); +mod tests { + use crate::test_rest_client::TestRestClient; + use base64::prelude::BASE64_STANDARD; + use base64::Engine; + use std::sync::Arc; + use tutasdk::generated_id::GeneratedId; + use tutasdk::login::{CredentialType, Credentials}; + use tutasdk::rest_client::{HttpMethod, RestClient}; + use tutasdk::{IdTuple, Sdk}; - // password is qawsedrftgyh - let encrypted_passphrase_key = BASE64_STANDARD.decode("AZWEA/KTrHu0bW52CsctsBTTV4U3jrU51TadSxf6Nqs3xbEs3WfoOpPtxUDCNjHNppt6LHCfgTioejjGUJ2cCsXosZAysUiau5Nvyi8mtjLz").unwrap(); + #[tokio::test] + async fn download_mail_with_logged_in_client() { + let rest_client = make_rest_client(); - let credentials = Credentials { - login: "bed-free@tutanota.de".to_string(), - user_id: GeneratedId("O1qC700----0".to_owned()), - access_token: "ZC2NIBDACUABAdJhibIwclzaPU3fEu-NzQ".to_string(), - encrypted_passphrase_key, - credential_type: CredentialType::Internal, - }; - let sdk = Sdk::new( - "http://localhost:9000".to_string(), - rest_client, - "".to_owned(), - ); - let logged_in_sdk = sdk.login(credentials).await.unwrap(); - let mail_facade = logged_in_sdk.mail_facade(); - let mail = mail_facade - .load_email_by_id_encrypted(&IdTuple { - list_id: GeneratedId("O1qC705-17-0".to_string()), - element_id: GeneratedId("O1qC7an--3-0".to_string()), - }) - .await - .unwrap(); + // password is qawsedrftgyh + let encrypted_passphrase_key = BASE64_STANDARD.decode("AZWEA/KTrHu0bW52CsctsBTTV4U3jrU51TadSxf6Nqs3xbEs3WfoOpPtxUDCNjHNppt6LHCfgTioejjGUJ2cCsXosZAysUiau5Nvyi8mtjLz").unwrap(); - assert_eq!("Html email features", mail.subject); - assert_eq!(1, mail.recipientCount); - assert_eq!("bed-free@tutanota.de", mail.firstRecipient.unwrap().address); - assert_eq!("map-free@tutanota.de", mail.sender.address); - assert_eq!("Matthias", mail.sender.name); - assert_eq!(1721043814832, mail.receivedDate.as_millis()); -} + let credentials = Credentials { + login: "bed-free@tutanota.de".to_string(), + user_id: GeneratedId("O1qC700----0".to_owned()), + access_token: "ZC2NIBDACUABAdJhibIwclzaPU3fEu-NzQ".to_string(), + encrypted_passphrase_key, + credential_type: CredentialType::Internal, + }; + let sdk = Sdk::new( + "http://localhost:9000".to_string(), + rest_client, + "".to_owned(), + ); + let logged_in_sdk = sdk.login(credentials).await.unwrap(); + let mail_facade = logged_in_sdk.mail_facade(); + let mail = mail_facade + .load_email_by_id_encrypted(&IdTuple { + list_id: GeneratedId("O1qC705-17-0".to_string()), + element_id: GeneratedId("O1qC7an--3-0".to_string()), + }) + .await + .unwrap(); + + assert_eq!("Html email features", mail.subject); + assert_eq!(1, mail.recipientCount); + assert_eq!("bed-free@tutanota.de", mail.firstRecipient.unwrap().address); + assert_eq!("map-free@tutanota.de", mail.sender.address); + assert_eq!("Matthias", mail.sender.name); + assert_eq!(1721043814832, mail.receivedDate.as_millis()); + } -fn make_rest_client() -> Arc { - let mut client = TestRestClient::default(); + fn make_rest_client() -> Arc { + let mut client = TestRestClient::default(); - client.insert_response( - "http://localhost:9000/rest/sys/Session/O1qC702-1J-0/3u3i8Lr9_7TnDDdAVw7w3TypTD2k1L00vIUTMF0SIPY", - HttpMethod::GET, - 200, - Some(include_bytes!("download_mail_test/session.json")) - ); + client.insert_response("http://localhost:9000/rest/sys/Session/O1qC702-1J-0/3u3i8Lr9_7TnDDdAVw7w3TypTD2k1L00vIUTMF0SIPY", HttpMethod::GET, 200, Some(include_bytes!("download_mail_test/session.json"))); - client.insert_response( - "http://localhost:9000/rest/sys/User/O1qC700----0", - HttpMethod::GET, - 200, - Some(include_bytes!("download_mail_test/session.json")), - ); + client.insert_response( + "http://localhost:9000/rest/sys/User/O1qC700----0", + HttpMethod::GET, + 200, + Some(include_bytes!("download_mail_test/session.json")), + ); - client.insert_response( - "http://localhost:9000/rest/sys/User/O1qC700----0", - HttpMethod::GET, - 200, - Some(include_bytes!("download_mail_test/user.json")), - ); + client.insert_response( + "http://localhost:9000/rest/sys/User/O1qC700----0", + HttpMethod::GET, + 200, + Some(include_bytes!("download_mail_test/user.json")), + ); - client.insert_response( - "http://localhost:9000/rest/tutanota/Mail/O1qC705-17-0/O1qC7an--3-0", - HttpMethod::GET, - 200, - Some(include_bytes!("download_mail_test/mail.json")), - ); + client.insert_response( + "http://localhost:9000/rest/tutanota/Mail/O1qC705-17-0/O1qC7an--3-0", + HttpMethod::GET, + 200, + Some(include_bytes!("download_mail_test/mail.json")), + ); - Arc::new(client) + Arc::new(client) + } } diff --git a/tuta-sdk/rust/sdk/tests/test_rest_client.rs b/tuta-sdk/rust/sdk/tests/test_rest_client.rs index 81ecafd2555a..6e48459a31cc 100644 --- a/tuta-sdk/rust/sdk/tests/test_rest_client.rs +++ b/tuta-sdk/rust/sdk/tests/test_rest_client.rs @@ -36,6 +36,7 @@ pub struct TestRestRequest { pub method: HttpMethod, } + #[async_trait::async_trait] impl RestClient for TestRestClient { async fn request_binary(