vw_small

Hardened fork of Vaultwarden (https://github.com/dani-garcia/vaultwarden) with fewer features.
git clone https://git.philomathiclife.com/repos/vw_small
Log | Files | Refs | README

commit f906f6230a8308a3b60d0bac49f99244b7c89df9
parent 951ba5512330d34b633a5e6692935c594b40575a
Author: BlackDex <black.dex@gmail.com>
Date:   Sun, 30 Apr 2023 17:18:12 +0200

Change `String` to `&str` for all Rocket functions

During setting the latest commit hash for Rocket and updating all the
other crates, there were some messages regarding the usage of `String`
for the Rocket endpoint function calls. I acted upon this message and
changed all `String` types to `&str` and modified the code where needed.

This ended up in less alloc calls, and probably also a bit less memory usage.

- Updated all the crates and commit hashes
- Modified all `String` to `&str` where applicable

Diffstat:
MCargo.lock | 96++++++++++++++++++++++++++++++++++++++++----------------------------------------
MCargo.toml | 18+++++++++---------
Msrc/api/admin.rs | 42+++++++++++++++++++++---------------------
Msrc/api/core/accounts.rs | 14+++++++-------
Msrc/api/core/ciphers.rs | 141++++++++++++++++++++++++++++++++++++++++---------------------------------------
Msrc/api/core/emergency_access.rs | 88++++++++++++++++++++++++++++++++++++-------------------------------------------
Msrc/api/core/events.rs | 26+++++++++++++-------------
Msrc/api/core/folders.rs | 16++++++++--------
Msrc/api/core/mod.rs | 6+++---
Msrc/api/core/organizations.rs | 477+++++++++++++++++++++++++++++++++++++++----------------------------------------
Msrc/api/core/sends.rs | 42+++++++++++++++++++++---------------------
Msrc/api/icons.rs | 10+++++-----
Msrc/api/web.rs | 4++--
Msrc/auth.rs | 46++++++++++++++++++++++++----------------------
Msrc/mail.rs | 4++--
Msrc/util.rs | 4++--
16 files changed, 512 insertions(+), 522 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock @@ -909,9 +909,9 @@ dependencies = [ [[package]] name = "flate2" -version = "1.0.25" +version = "1.0.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8a2db397cb1c8772f31494cb8917e48cd1e64f0fa7efac59fbd741a0a8ce841" +checksum = "3b9429470923de8e8cbd4d2dc513535400b4b3fef0319fb5c4e1f520a7bef743" dependencies = [ "crc32fast", "miniz_oxide", @@ -1516,9 +1516,9 @@ checksum = "6a987beff54b60ffa6d51982e1aa1146bc42f19bd26be28b0586f252fccf5317" [[package]] name = "libmimalloc-sys" -version = "0.1.32" +version = "0.1.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43a558e3d911bc3c7bfc8c78bc580b404d6e51c1cefbf656e176a94b49b0df40" +checksum = "f4ac0e912c8ef1b735e92369695618dc5b1819f5a7bf3f167301a3ba1cea515e" dependencies = [ "cc", "libc", @@ -1552,9 +1552,9 @@ checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" [[package]] name = "linux-raw-sys" -version = "0.3.4" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36eb31c1778188ae1e64398743890d0877fef36d11521ac60406b42016e8c2cf" +checksum = "b64f40e5e03e0d54f03845c8197d0291253cdbedfb1cb46b13c2c117554a9f4c" [[package]] name = "lock_api" @@ -1659,9 +1659,9 @@ dependencies = [ [[package]] name = "mimalloc" -version = "0.1.36" +version = "0.1.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d88dad3f985ec267a3fcb7a1726f5cb1a7e8cad8b646e70a84f967210df23da" +checksum = "4e2894987a3459f3ffb755608bd82188f8ed00d0ae077f1edea29c068d639d98" dependencies = [ "libmimalloc-sys", ] @@ -1680,9 +1680,9 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.6.2" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa" +checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" dependencies = [ "adler", ] @@ -1847,9 +1847,9 @@ checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" [[package]] name = "openssl" -version = "0.10.51" +version = "0.10.52" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97ea2d98598bf9ada7ea6ee8a30fb74f9156b63bbe495d64ec2b87c269d2dda3" +checksum = "01b8574602df80f7b85fdfc5392fa884a4e3b3f4f35402c070ab34c3d3f78d56" dependencies = [ "bitflags 1.3.2", "cfg-if", @@ -1888,9 +1888,9 @@ dependencies = [ [[package]] name = "openssl-sys" -version = "0.9.86" +version = "0.9.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "992bac49bdbab4423199c654a5515bd2a6c6a23bf03f2dd3bdb7e5ae6259bc69" +checksum = "8e17f59264b2809d77ae94f0e1ebabc434773f370d6ca667bd223ea10e06cc7e" dependencies = [ "cc", "libc", @@ -2000,9 +2000,9 @@ checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" [[package]] name = "pest" -version = "2.5.7" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b1403e8401ad5dedea73c626b99758535b342502f8d1e361f4a2dd952749122" +checksum = "e68e84bfb01f0507134eac1e9b410a12ba379d064eab48c50ba4ce329a527b70" dependencies = [ "thiserror", "ucd-trie", @@ -2010,9 +2010,9 @@ dependencies = [ [[package]] name = "pest_derive" -version = "2.5.7" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be99c4c1d2fc2769b1d00239431d711d08f6efedcecb8b6e30707160aee99c15" +checksum = "6b79d4c71c865a25a4322296122e3924d30bc8ee0834c8bfc8b95f7f054afbfb" dependencies = [ "pest", "pest_generator", @@ -2020,9 +2020,9 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.5.7" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e56094789873daa36164de2e822b3888c6ae4b4f9da555a1103587658c805b1e" +checksum = "6c435bf1076437b851ebc8edc3a18442796b30f1728ffea6262d59bbe28b077e" dependencies = [ "pest", "pest_meta", @@ -2033,9 +2033,9 @@ dependencies = [ [[package]] name = "pest_meta" -version = "2.5.7" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6733073c7cff3d8459fda0e42f13a047870242aed8b509fe98000928975f359e" +checksum = "745a452f8eb71e39ffd8ee32b3c5f51d03845f99786fa9b68db6ff509c505411" dependencies = [ "once_cell", "pest", @@ -2230,9 +2230,9 @@ dependencies = [ [[package]] name = "quoted_printable" -version = "0.4.7" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a24039f627d8285853cc90dcddf8c1ebfaa91f834566948872b225b9a28ed1b6" +checksum = "5a3866219251662ec3b26fc217e3e05bf9c4f84325234dfb96bf0bf840889e49" [[package]] name = "r2d2" @@ -2356,9 +2356,9 @@ checksum = "a5996294f19bd3aae0453a862ad728f60e6600695733dd5df01da90c54363a3c" [[package]] name = "reqwest" -version = "0.11.16" +version = "0.11.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27b71749df584b7f4cac2c426c127a7c785a5106cc98f7a8feb044115f0fa254" +checksum = "13293b639a097af28fc8a90f22add145a9c954e49d77da06263d58cf44d5fb91" dependencies = [ "async-compression", "base64 0.21.0", @@ -2447,7 +2447,7 @@ dependencies = [ [[package]] name = "rocket" version = "0.5.0-rc.3" -source = "git+https://github.com/SergioBenitez/Rocket?rev=a82508b403420bd941c32ddec3ee3e4875f2b8a5#a82508b403420bd941c32ddec3ee3e4875f2b8a5" +source = "git+https://github.com/SergioBenitez/Rocket?rev=9b0564ed27f90686b333337d9f6ed76484a84b27#9b0564ed27f90686b333337d9f6ed76484a84b27" dependencies = [ "async-stream", "async-trait", @@ -2485,7 +2485,7 @@ dependencies = [ [[package]] name = "rocket_codegen" version = "0.5.0-rc.3" -source = "git+https://github.com/SergioBenitez/Rocket?rev=a82508b403420bd941c32ddec3ee3e4875f2b8a5#a82508b403420bd941c32ddec3ee3e4875f2b8a5" +source = "git+https://github.com/SergioBenitez/Rocket?rev=9b0564ed27f90686b333337d9f6ed76484a84b27#9b0564ed27f90686b333337d9f6ed76484a84b27" dependencies = [ "devise", "glob", @@ -2500,7 +2500,7 @@ dependencies = [ [[package]] name = "rocket_http" version = "0.5.0-rc.3" -source = "git+https://github.com/SergioBenitez/Rocket?rev=a82508b403420bd941c32ddec3ee3e4875f2b8a5#a82508b403420bd941c32ddec3ee3e4875f2b8a5" +source = "git+https://github.com/SergioBenitez/Rocket?rev=9b0564ed27f90686b333337d9f6ed76484a84b27#9b0564ed27f90686b333337d9f6ed76484a84b27" dependencies = [ "cookie 0.17.0", "either", @@ -2529,7 +2529,7 @@ dependencies = [ [[package]] name = "rocket_ws" version = "0.1.0-rc.3" -source = "git+https://github.com/SergioBenitez/Rocket?rev=a82508b403420bd941c32ddec3ee3e4875f2b8a5#a82508b403420bd941c32ddec3ee3e4875f2b8a5" +source = "git+https://github.com/SergioBenitez/Rocket?rev=9b0564ed27f90686b333337d9f6ed76484a84b27#9b0564ed27f90686b333337d9f6ed76484a84b27" dependencies = [ "rocket", "tokio-tungstenite", @@ -2558,9 +2558,9 @@ dependencies = [ [[package]] name = "rustix" -version = "0.37.14" +version = "0.37.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b864d3c18a5785a05953adeed93e2dca37ed30f18e69bba9f30079d51f363f" +checksum = "8bbfc1d1c7c40c01715f47d71444744a81669ca84e8b63e25a55e169b1f86433" dependencies = [ "bitflags 1.3.2", "errno", @@ -2920,9 +2920,9 @@ dependencies = [ [[package]] name = "syslog" -version = "6.0.1" +version = "6.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "978044cc68150ad5e40083c9f6a725e6fd02d7ba1bcf691ec2ff0d66c0b41acc" +checksum = "7434e95bcccce1215d30f4bf84fe8c00e8de1b9be4fb736d747ca53d36e7f96f" dependencies = [ "error-chain", "hostname", @@ -3038,9 +3038,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.27.0" +version = "1.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0de47a4eecbe11f498978a9b29d792f0d2692d1dd003650c24c76510e3bc001" +checksum = "c3c786bf8134e5a3a166db9b29ab8f48134739014a3eca7bc6bfa95d673b136f" dependencies = [ "autocfg", "bytes", @@ -3052,14 +3052,14 @@ dependencies = [ "signal-hook-registry", "socket2", "tokio-macros", - "windows-sys 0.45.0", + "windows-sys 0.48.0", ] [[package]] name = "tokio-macros" -version = "2.0.0" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61a573bdc87985e9d6ddeed1b3d864e8a302c847e40d647746df2f1de209d1ce" +checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" dependencies = [ "proc-macro2", "quote", @@ -3100,9 +3100,9 @@ dependencies = [ [[package]] name = "tokio-stream" -version = "0.1.12" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fb52b74f05dbf495a8fba459fdc331812b96aa086d9eb78101fa0d4569c3313" +checksum = "397c988d37662c7dda6d2208364a706264bf3d6138b11d436cbac0ad38832842" dependencies = [ "futures-core", "pin-project-lite", @@ -3123,9 +3123,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.7" +version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5427d89453009325de0d8f342c9490009f76e999cb7672d77e46267448f7e6b2" +checksum = "806fe8c2c87eccc8b3267cbae29ed3ab2d0bd37fca70ab622e46aaa9375ddb7d" dependencies = [ "bytes", "futures-core", @@ -3177,13 +3177,13 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.23" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4017f8f45139870ca7e672686113917c71c7a6e02d4924eda67186083c03081a" +checksum = "0f57e3ca2a01450b1a921183a9c9cbfda207fd822cef4ccb00a65402cbba7a74" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.15", ] [[package]] @@ -3385,9 +3385,9 @@ checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" [[package]] name = "uuid" -version = "1.3.1" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b55a3fef2a1e3b3a00ce878640918820d3c51081576ac657d23af9fc7928fdb" +checksum = "4dad5567ad0cf5b760e5665964bec1b47dfd077ba8a2544b513f3556d3d239a2" dependencies = [ "getrandom", ] diff --git a/Cargo.toml b/Cargo.toml @@ -36,7 +36,7 @@ unstable = [] [target."cfg(not(windows))".dependencies] # Logging -syslog = "6.0.1" +syslog = "6.1.0" [dependencies] # Logging @@ -57,7 +57,7 @@ num-derive = "0.3.3" # Web framework rocket = { version = "0.5.0-rc.3", features = ["tls", "json"], default-features = false } # rocket_ws = { version ="0.1.0-rc.3" } -rocket_ws = { git = 'https://github.com/SergioBenitez/Rocket', rev = "a82508b403420bd941c32ddec3ee3e4875f2b8a5" } +rocket_ws = { git = 'https://github.com/SergioBenitez/Rocket', rev = "9b0564ed27f90686b333337d9f6ed76484a84b27" } # WebSockets libraries tokio-tungstenite = "0.18.0" @@ -68,7 +68,7 @@ dashmap = "5.4.0" # Async futures futures = "0.3.28" -tokio = { version = "1.27.0", features = ["rt-multi-thread", "fs", "io-util", "parking_lot", "time", "signal"] } +tokio = { version = "1.28.0", features = ["rt-multi-thread", "fs", "io-util", "parking_lot", "time", "signal"] } # A generic serialization/deserialization framework serde = { version = "1.0.160", features = ["derive"] } @@ -87,7 +87,7 @@ rand = { version = "0.8.5", features = ["small_rng"] } ring = "0.16.20" # UUID generation -uuid = { version = "1.3.1", features = ["v4"] } +uuid = { version = "1.3.2", features = ["v4"] } # Date and time libraries chrono = { version = "0.4.24", features = ["clock", "serde"], default-features = false } @@ -124,7 +124,7 @@ email_address = "0.2.4" handlebars = { version = "4.3.6", features = ["dir_source"] } # HTTP client (Used for favicons, version check, DUO and HIBP API) -reqwest = { version = "0.11.16", features = ["stream", "json", "gzip", "brotli", "socks", "cookies", "trust-dns"] } +reqwest = { version = "0.11.17", features = ["stream", "json", "gzip", "brotli", "socks", "cookies", "trust-dns"] } # Favicon extraction libraries html5gum = "0.5.2" @@ -140,7 +140,7 @@ cookie = "0.16.2" cookie_store = "0.19.0" # Used by U2F, JWT and PostgreSQL -openssl = "0.10.51" +openssl = "0.10.52" # CLI argument parsing pico-args = "0.5.0" @@ -154,7 +154,7 @@ semver = "1.0.17" # Allow overriding the default memory allocator # Mainly used for the musl builds, since the default musl malloc is very slow -mimalloc = { version = "0.1.36", features = ["secure"], default-features = false, optional = true } +mimalloc = { version = "0.1.37", features = ["secure"], default-features = false, optional = true } which = "4.4.0" # Argon2 library with support for the PHC format @@ -164,8 +164,8 @@ argon2 = "0.5.0" rpassword = "7.2.0" [patch.crates-io] -rocket = { git = 'https://github.com/SergioBenitez/Rocket', rev = 'a82508b403420bd941c32ddec3ee3e4875f2b8a5' } -# rocket_ws = { git = 'https://github.com/SergioBenitez/Rocket', rev = 'a82508b403420bd941c32ddec3ee3e4875f2b8a5' } +rocket = { git = 'https://github.com/SergioBenitez/Rocket', rev = '9b0564ed27f90686b333337d9f6ed76484a84b27' } +# rocket_ws = { git = 'https://github.com/SergioBenitez/Rocket', rev = '9b0564ed27f90686b333337d9f6ed76484a84b27' } # Strip debuginfo from the release builds # Also enable thin LTO for some optimizations diff --git a/src/api/admin.rs b/src/api/admin.rs @@ -349,8 +349,8 @@ async fn users_overview(_token: AdminToken, mut conn: DbConn) -> ApiResult<Html< } #[get("/users/by-mail/<mail>")] -async fn get_user_by_mail_json(mail: String, _token: AdminToken, mut conn: DbConn) -> JsonResult { - if let Some(u) = User::find_by_mail(&mail, &mut conn).await { +async fn get_user_by_mail_json(mail: &str, _token: AdminToken, mut conn: DbConn) -> JsonResult { + if let Some(u) = User::find_by_mail(mail, &mut conn).await { let mut usr = u.to_json(&mut conn).await; usr["UserEnabled"] = json!(u.enabled); usr["CreatedAt"] = json!(format_naive_datetime_local(&u.created_at, DT_FMT)); @@ -361,8 +361,8 @@ async fn get_user_by_mail_json(mail: String, _token: AdminToken, mut conn: DbCon } #[get("/users/<uuid>")] -async fn get_user_json(uuid: String, _token: AdminToken, mut conn: DbConn) -> JsonResult { - let u = get_user_or_404(&uuid, &mut conn).await?; +async fn get_user_json(uuid: &str, _token: AdminToken, mut conn: DbConn) -> JsonResult { + let u = get_user_or_404(uuid, &mut conn).await?; let mut usr = u.to_json(&mut conn).await; usr["UserEnabled"] = json!(u.enabled); usr["CreatedAt"] = json!(format_naive_datetime_local(&u.created_at, DT_FMT)); @@ -370,18 +370,18 @@ async fn get_user_json(uuid: String, _token: AdminToken, mut conn: DbConn) -> Js } #[post("/users/<uuid>/delete")] -async fn delete_user(uuid: String, token: AdminToken, mut conn: DbConn) -> EmptyResult { - let user = get_user_or_404(&uuid, &mut conn).await?; +async fn delete_user(uuid: &str, token: AdminToken, mut conn: DbConn) -> EmptyResult { + let user = get_user_or_404(uuid, &mut conn).await?; // Get the user_org records before deleting the actual user - let user_orgs = UserOrganization::find_any_state_by_user(&uuid, &mut conn).await; + let user_orgs = UserOrganization::find_any_state_by_user(uuid, &mut conn).await; let res = user.delete(&mut conn).await; for user_org in user_orgs { log_event( EventType::OrganizationUserRemoved as i32, &user_org.uuid, - user_org.org_uuid, + &user_org.org_uuid, String::from(ACTING_ADMIN_USER), 14, // Use UnknownBrowser type &token.ip.ip, @@ -394,8 +394,8 @@ async fn delete_user(uuid: String, token: AdminToken, mut conn: DbConn) -> Empty } #[post("/users/<uuid>/deauth")] -async fn deauth_user(uuid: String, _token: AdminToken, mut conn: DbConn, nt: Notify<'_>) -> EmptyResult { - let mut user = get_user_or_404(&uuid, &mut conn).await?; +async fn deauth_user(uuid: &str, _token: AdminToken, mut conn: DbConn, nt: Notify<'_>) -> EmptyResult { + let mut user = get_user_or_404(uuid, &mut conn).await?; Device::delete_all_by_user(&user.uuid, &mut conn).await?; user.reset_security_stamp(); @@ -407,8 +407,8 @@ async fn deauth_user(uuid: String, _token: AdminToken, mut conn: DbConn, nt: Not } #[post("/users/<uuid>/disable")] -async fn disable_user(uuid: String, _token: AdminToken, mut conn: DbConn, nt: Notify<'_>) -> EmptyResult { - let mut user = get_user_or_404(&uuid, &mut conn).await?; +async fn disable_user(uuid: &str, _token: AdminToken, mut conn: DbConn, nt: Notify<'_>) -> EmptyResult { + let mut user = get_user_or_404(uuid, &mut conn).await?; Device::delete_all_by_user(&user.uuid, &mut conn).await?; user.reset_security_stamp(); user.enabled = false; @@ -421,24 +421,24 @@ async fn disable_user(uuid: String, _token: AdminToken, mut conn: DbConn, nt: No } #[post("/users/<uuid>/enable")] -async fn enable_user(uuid: String, _token: AdminToken, mut conn: DbConn) -> EmptyResult { - let mut user = get_user_or_404(&uuid, &mut conn).await?; +async fn enable_user(uuid: &str, _token: AdminToken, mut conn: DbConn) -> EmptyResult { + let mut user = get_user_or_404(uuid, &mut conn).await?; user.enabled = true; user.save(&mut conn).await } #[post("/users/<uuid>/remove-2fa")] -async fn remove_2fa(uuid: String, _token: AdminToken, mut conn: DbConn) -> EmptyResult { - let mut user = get_user_or_404(&uuid, &mut conn).await?; +async fn remove_2fa(uuid: &str, _token: AdminToken, mut conn: DbConn) -> EmptyResult { + let mut user = get_user_or_404(uuid, &mut conn).await?; TwoFactor::delete_all_by_user(&user.uuid, &mut conn).await?; user.totp_recover = None; user.save(&mut conn).await } #[post("/users/<uuid>/invite/resend")] -async fn resend_user_invite(uuid: String, _token: AdminToken, mut conn: DbConn) -> EmptyResult { - if let Some(user) = User::find_by_uuid(&uuid, &mut conn).await { +async fn resend_user_invite(uuid: &str, _token: AdminToken, mut conn: DbConn) -> EmptyResult { + if let Some(user) = User::find_by_uuid(uuid, &mut conn).await { //TODO: replace this with user.status check when it will be available (PR#3397) if !user.password_hash.is_empty() { err_code!("User already accepted invitation", Status::BadRequest.code); @@ -500,7 +500,7 @@ async fn update_user_org_type(data: Json<UserOrgTypeData>, token: AdminToken, mu log_event( EventType::OrganizationUserUpdated as i32, &user_to_edit.uuid, - data.org_uuid, + &data.org_uuid, String::from(ACTING_ADMIN_USER), 14, // Use UnknownBrowser type &token.ip.ip, @@ -538,8 +538,8 @@ async fn organizations_overview(_token: AdminToken, mut conn: DbConn) -> ApiResu } #[post("/organizations/<uuid>/delete")] -async fn delete_organization(uuid: String, _token: AdminToken, mut conn: DbConn) -> EmptyResult { - let org = Organization::find_by_uuid(&uuid, &mut conn).await.map_res("Organization doesn't exist")?; +async fn delete_organization(uuid: &str, _token: AdminToken, mut conn: DbConn) -> EmptyResult { + let org = Organization::find_by_uuid(uuid, &mut conn).await.map_res("Organization doesn't exist")?; org.delete(&mut conn).await } diff --git a/src/api/core/accounts.rs b/src/api/core/accounts.rs @@ -133,7 +133,7 @@ pub async fn _register(data: JsonUpcase<RegisterData>, mut conn: DbConn) -> Json err!("Registration email does not match invite email") } } else if Invitation::take(&email, &mut conn).await { - for mut user_org in UserOrganization::find_invited_by_user(&user.uuid, &mut conn).await.iter_mut() { + for user_org in UserOrganization::find_invited_by_user(&user.uuid, &mut conn).await.iter_mut() { user_org.status = UserOrgStatus::Accepted as i32; user_org.save(&mut conn).await?; } @@ -266,8 +266,8 @@ async fn put_avatar(data: JsonUpcase<AvatarData>, headers: Headers, mut conn: Db } #[get("/users/<uuid>/public-key")] -async fn get_public_keys(uuid: String, _headers: Headers, mut conn: DbConn) -> JsonResult { - let user = match User::find_by_uuid(&uuid, &mut conn).await { +async fn get_public_keys(uuid: &str, _headers: Headers, mut conn: DbConn) -> JsonResult { + let user = match User::find_by_uuid(uuid, &mut conn).await { Some(user) => user, None => err!("User doesn't exist"), }; @@ -874,18 +874,18 @@ async fn rotate_api_key(data: JsonUpcase<SecretVerificationRequest>, headers: He // This variant is deprecated: https://github.com/bitwarden/server/pull/2682 #[get("/devices/knowndevice/<email>/<uuid>")] -async fn get_known_device_from_path(email: String, uuid: String, mut conn: DbConn) -> JsonResult { +async fn get_known_device_from_path(email: &str, uuid: &str, mut conn: DbConn) -> JsonResult { // This endpoint doesn't have auth header let mut result = false; - if let Some(user) = User::find_by_mail(&email, &mut conn).await { - result = Device::find_by_uuid_and_user(&uuid, &user.uuid, &mut conn).await.is_some(); + if let Some(user) = User::find_by_mail(email, &mut conn).await { + result = Device::find_by_uuid_and_user(uuid, &user.uuid, &mut conn).await.is_some(); } Ok(Json(json!(result))) } #[get("/devices/knowndevice")] async fn get_known_device(device: KnownDevice, conn: DbConn) -> JsonResult { - get_known_device_from_path(device.email, device.uuid, conn).await + get_known_device_from_path(&device.email, &device.uuid, conn).await } struct KnownDevice { diff --git a/src/api/core/ciphers.rs b/src/api/core/ciphers.rs @@ -172,8 +172,8 @@ async fn get_ciphers(headers: Headers, mut conn: DbConn) -> Json<Value> { } #[get("/ciphers/<uuid>")] -async fn get_cipher(uuid: String, headers: Headers, mut conn: DbConn) -> JsonResult { - let cipher = match Cipher::find_by_uuid(&uuid, &mut conn).await { +async fn get_cipher(uuid: &str, headers: Headers, mut conn: DbConn) -> JsonResult { + let cipher = match Cipher::find_by_uuid(uuid, &mut conn).await { Some(cipher) => cipher, None => err!("Cipher doesn't exist"), }; @@ -186,13 +186,13 @@ async fn get_cipher(uuid: String, headers: Headers, mut conn: DbConn) -> JsonRes } #[get("/ciphers/<uuid>/admin")] -async fn get_cipher_admin(uuid: String, headers: Headers, conn: DbConn) -> JsonResult { +async fn get_cipher_admin(uuid: &str, headers: Headers, conn: DbConn) -> JsonResult { // TODO: Implement this correctly get_cipher(uuid, headers, conn).await } #[get("/ciphers/<uuid>/details")] -async fn get_cipher_details(uuid: String, headers: Headers, conn: DbConn) -> JsonResult { +async fn get_cipher_details(uuid: &str, headers: Headers, conn: DbConn) -> JsonResult { get_cipher(uuid, headers, conn).await } @@ -503,7 +503,7 @@ pub async fn update_cipher_from_data( log_event( event_type as i32, &cipher.uuid, - String::from(org_uuid), + org_uuid, headers.user.uuid.clone(), headers.device.atype, &headers.ip.ip, @@ -586,7 +586,7 @@ async fn post_ciphers_import( /// Called when an org admin modifies an existing org cipher. #[put("/ciphers/<uuid>/admin", data = "<data>")] async fn put_cipher_admin( - uuid: String, + uuid: &str, data: JsonUpcase<CipherData>, headers: Headers, conn: DbConn, @@ -597,7 +597,7 @@ async fn put_cipher_admin( #[post("/ciphers/<uuid>/admin", data = "<data>")] async fn post_cipher_admin( - uuid: String, + uuid: &str, data: JsonUpcase<CipherData>, headers: Headers, conn: DbConn, @@ -608,7 +608,7 @@ async fn post_cipher_admin( #[post("/ciphers/<uuid>", data = "<data>")] async fn post_cipher( - uuid: String, + uuid: &str, data: JsonUpcase<CipherData>, headers: Headers, conn: DbConn, @@ -619,7 +619,7 @@ async fn post_cipher( #[put("/ciphers/<uuid>", data = "<data>")] async fn put_cipher( - uuid: String, + uuid: &str, data: JsonUpcase<CipherData>, headers: Headers, mut conn: DbConn, @@ -627,7 +627,7 @@ async fn put_cipher( ) -> JsonResult { let data: CipherData = data.into_inner().data; - let mut cipher = match Cipher::find_by_uuid(&uuid, &mut conn).await { + let mut cipher = match Cipher::find_by_uuid(uuid, &mut conn).await { Some(cipher) => cipher, None => err!("Cipher doesn't exist"), }; @@ -648,7 +648,7 @@ async fn put_cipher( #[post("/ciphers/<uuid>/partial", data = "<data>")] async fn post_cipher_partial( - uuid: String, + uuid: &str, data: JsonUpcase<PartialCipherData>, headers: Headers, conn: DbConn, @@ -659,14 +659,14 @@ async fn post_cipher_partial( // Only update the folder and favorite for the user, since this cipher is read-only #[put("/ciphers/<uuid>/partial", data = "<data>")] async fn put_cipher_partial( - uuid: String, + uuid: &str, data: JsonUpcase<PartialCipherData>, headers: Headers, mut conn: DbConn, ) -> JsonResult { let data: PartialCipherData = data.into_inner().data; - let cipher = match Cipher::find_by_uuid(&uuid, &mut conn).await { + let cipher = match Cipher::find_by_uuid(uuid, &mut conn).await { Some(cipher) => cipher, None => err!("Cipher doesn't exist"), }; @@ -698,7 +698,7 @@ struct CollectionsAdminData { #[put("/ciphers/<uuid>/collections", data = "<data>")] async fn put_collections_update( - uuid: String, + uuid: &str, data: JsonUpcase<CollectionsAdminData>, headers: Headers, conn: DbConn, @@ -708,7 +708,7 @@ async fn put_collections_update( #[post("/ciphers/<uuid>/collections", data = "<data>")] async fn post_collections_update( - uuid: String, + uuid: &str, data: JsonUpcase<CollectionsAdminData>, headers: Headers, conn: DbConn, @@ -718,7 +718,7 @@ async fn post_collections_update( #[put("/ciphers/<uuid>/collections-admin", data = "<data>")] async fn put_collections_admin( - uuid: String, + uuid: &str, data: JsonUpcase<CollectionsAdminData>, headers: Headers, conn: DbConn, @@ -728,14 +728,14 @@ async fn put_collections_admin( #[post("/ciphers/<uuid>/collections-admin", data = "<data>")] async fn post_collections_admin( - uuid: String, + uuid: &str, data: JsonUpcase<CollectionsAdminData>, headers: Headers, mut conn: DbConn, ) -> EmptyResult { let data: CollectionsAdminData = data.into_inner().data; - let cipher = match Cipher::find_by_uuid(&uuid, &mut conn).await { + let cipher = match Cipher::find_by_uuid(uuid, &mut conn).await { Some(cipher) => cipher, None => err!("Cipher doesn't exist"), }; @@ -770,7 +770,7 @@ async fn post_collections_admin( log_event( EventType::CipherUpdatedCollections as i32, &cipher.uuid, - cipher.organization_uuid.unwrap(), + &cipher.organization_uuid.unwrap(), headers.user.uuid.clone(), headers.device.atype, &headers.ip.ip, @@ -790,7 +790,7 @@ struct ShareCipherData { #[post("/ciphers/<uuid>/share", data = "<data>")] async fn post_cipher_share( - uuid: String, + uuid: &str, data: JsonUpcase<ShareCipherData>, headers: Headers, mut conn: DbConn, @@ -798,12 +798,12 @@ async fn post_cipher_share( ) -> JsonResult { let data: ShareCipherData = data.into_inner().data; - share_cipher_by_uuid(&uuid, data, &headers, &mut conn, &nt).await + share_cipher_by_uuid(uuid, data, &headers, &mut conn, &nt).await } #[put("/ciphers/<uuid>/share", data = "<data>")] async fn put_cipher_share( - uuid: String, + uuid: &str, data: JsonUpcase<ShareCipherData>, headers: Headers, mut conn: DbConn, @@ -811,7 +811,7 @@ async fn put_cipher_share( ) -> JsonResult { let data: ShareCipherData = data.into_inner().data; - share_cipher_by_uuid(&uuid, data, &headers, &mut conn, &nt).await + share_cipher_by_uuid(uuid, data, &headers, &mut conn, &nt).await } #[derive(Deserialize)] @@ -916,8 +916,8 @@ async fn share_cipher_by_uuid( /// their object storage service. For self-hosted instances, it basically just /// redirects to the same location as before the v2 API. #[get("/ciphers/<uuid>/attachment/<attachment_id>")] -async fn get_attachment(uuid: String, attachment_id: String, headers: Headers, mut conn: DbConn) -> JsonResult { - match Attachment::find_by_id(&attachment_id, &mut conn).await { +async fn get_attachment(uuid: &str, attachment_id: &str, headers: Headers, mut conn: DbConn) -> JsonResult { + match Attachment::find_by_id(attachment_id, &mut conn).await { Some(attachment) if uuid == attachment.cipher_uuid => Ok(Json(attachment.to_json(&headers.host))), Some(_) => err!("Attachment doesn't belong to cipher"), None => err!("Attachment doesn't exist"), @@ -944,12 +944,12 @@ enum FileUploadType { /// For self-hosted instances, it's another API on the local instance. #[post("/ciphers/<uuid>/attachment/v2", data = "<data>")] async fn post_attachment_v2( - uuid: String, + uuid: &str, data: JsonUpcase<AttachmentRequestData>, headers: Headers, mut conn: DbConn, ) -> JsonResult { - let cipher = match Cipher::find_by_uuid(&uuid, &mut conn).await { + let cipher = match Cipher::find_by_uuid(uuid, &mut conn).await { Some(cipher) => cipher, None => err!("Cipher doesn't exist"), }; @@ -995,13 +995,13 @@ struct UploadData<'f> { /// database record, which is passed in as `attachment`. async fn save_attachment( mut attachment: Option<Attachment>, - cipher_uuid: String, + cipher_uuid: &str, data: Form<UploadData<'_>>, headers: &Headers, mut conn: DbConn, nt: Notify<'_>, ) -> Result<(Cipher, DbConn), crate::error::Error> { - let cipher = match Cipher::find_by_uuid(&cipher_uuid, &mut conn).await { + let cipher = match Cipher::find_by_uuid(cipher_uuid, &mut conn).await { Some(cipher) => cipher, None => err!("Cipher doesn't exist"), }; @@ -1058,7 +1058,7 @@ async fn save_attachment( None => crypto::generate_attachment_id(), // Legacy API }; - let folder_path = tokio::fs::canonicalize(&CONFIG.attachments_folder()).await?.join(&cipher_uuid); + let folder_path = tokio::fs::canonicalize(&CONFIG.attachments_folder()).await?.join(cipher_uuid); let file_path = folder_path.join(&file_id); tokio::fs::create_dir_all(&folder_path).await?; @@ -1094,7 +1094,8 @@ async fn save_attachment( if data.key.is_none() { err!("No attachment key provided") } - let attachment = Attachment::new(file_id, cipher_uuid.clone(), encrypted_filename.unwrap(), size, data.key); + let attachment = + Attachment::new(file_id, String::from(cipher_uuid), encrypted_filename.unwrap(), size, data.key); attachment.save(&mut conn).await.expect("Error saving attachment"); } @@ -1114,7 +1115,7 @@ async fn save_attachment( log_event( EventType::CipherAttachmentCreated as i32, &cipher.uuid, - String::from(org_uuid), + org_uuid, headers.user.uuid.clone(), headers.device.atype, &headers.ip.ip, @@ -1132,14 +1133,14 @@ async fn save_attachment( /// with this one. #[post("/ciphers/<uuid>/attachment/<attachment_id>", format = "multipart/form-data", data = "<data>", rank = 1)] async fn post_attachment_v2_data( - uuid: String, - attachment_id: String, + uuid: &str, + attachment_id: &str, data: Form<UploadData<'_>>, headers: Headers, mut conn: DbConn, nt: Notify<'_>, ) -> EmptyResult { - let attachment = match Attachment::find_by_id(&attachment_id, &mut conn).await { + let attachment = match Attachment::find_by_id(attachment_id, &mut conn).await { Some(attachment) if uuid == attachment.cipher_uuid => Some(attachment), Some(_) => err!("Attachment doesn't belong to cipher"), None => err!("Attachment doesn't exist"), @@ -1153,7 +1154,7 @@ async fn post_attachment_v2_data( /// Legacy API for creating an attachment associated with a cipher. #[post("/ciphers/<uuid>/attachment", format = "multipart/form-data", data = "<data>")] async fn post_attachment( - uuid: String, + uuid: &str, data: Form<UploadData<'_>>, headers: Headers, conn: DbConn, @@ -1170,7 +1171,7 @@ async fn post_attachment( #[post("/ciphers/<uuid>/attachment-admin", format = "multipart/form-data", data = "<data>")] async fn post_attachment_admin( - uuid: String, + uuid: &str, data: Form<UploadData<'_>>, headers: Headers, conn: DbConn, @@ -1181,21 +1182,21 @@ async fn post_attachment_admin( #[post("/ciphers/<uuid>/attachment/<attachment_id>/share", format = "multipart/form-data", data = "<data>")] async fn post_attachment_share( - uuid: String, - attachment_id: String, + uuid: &str, + attachment_id: &str, data: Form<UploadData<'_>>, headers: Headers, mut conn: DbConn, nt: Notify<'_>, ) -> JsonResult { - _delete_cipher_attachment_by_id(&uuid, &attachment_id, &headers, &mut conn, &nt).await?; + _delete_cipher_attachment_by_id(uuid, attachment_id, &headers, &mut conn, &nt).await?; post_attachment(uuid, data, headers, conn, nt).await } #[post("/ciphers/<uuid>/attachment/<attachment_id>/delete-admin")] async fn delete_attachment_post_admin( - uuid: String, - attachment_id: String, + uuid: &str, + attachment_id: &str, headers: Headers, conn: DbConn, nt: Notify<'_>, @@ -1205,8 +1206,8 @@ async fn delete_attachment_post_admin( #[post("/ciphers/<uuid>/attachment/<attachment_id>/delete")] async fn delete_attachment_post( - uuid: String, - attachment_id: String, + uuid: &str, + attachment_id: &str, headers: Headers, conn: DbConn, nt: Notify<'_>, @@ -1216,58 +1217,58 @@ async fn delete_attachment_post( #[delete("/ciphers/<uuid>/attachment/<attachment_id>")] async fn delete_attachment( - uuid: String, - attachment_id: String, + uuid: &str, + attachment_id: &str, headers: Headers, mut conn: DbConn, nt: Notify<'_>, ) -> EmptyResult { - _delete_cipher_attachment_by_id(&uuid, &attachment_id, &headers, &mut conn, &nt).await + _delete_cipher_attachment_by_id(uuid, attachment_id, &headers, &mut conn, &nt).await } #[delete("/ciphers/<uuid>/attachment/<attachment_id>/admin")] async fn delete_attachment_admin( - uuid: String, - attachment_id: String, + uuid: &str, + attachment_id: &str, headers: Headers, mut conn: DbConn, nt: Notify<'_>, ) -> EmptyResult { - _delete_cipher_attachment_by_id(&uuid, &attachment_id, &headers, &mut conn, &nt).await + _delete_cipher_attachment_by_id(uuid, attachment_id, &headers, &mut conn, &nt).await } #[post("/ciphers/<uuid>/delete")] -async fn delete_cipher_post(uuid: String, headers: Headers, mut conn: DbConn, nt: Notify<'_>) -> EmptyResult { - _delete_cipher_by_uuid(&uuid, &headers, &mut conn, false, &nt).await +async fn delete_cipher_post(uuid: &str, headers: Headers, mut conn: DbConn, nt: Notify<'_>) -> EmptyResult { + _delete_cipher_by_uuid(uuid, &headers, &mut conn, false, &nt).await // permanent delete } #[post("/ciphers/<uuid>/delete-admin")] -async fn delete_cipher_post_admin(uuid: String, headers: Headers, mut conn: DbConn, nt: Notify<'_>) -> EmptyResult { - _delete_cipher_by_uuid(&uuid, &headers, &mut conn, false, &nt).await +async fn delete_cipher_post_admin(uuid: &str, headers: Headers, mut conn: DbConn, nt: Notify<'_>) -> EmptyResult { + _delete_cipher_by_uuid(uuid, &headers, &mut conn, false, &nt).await // permanent delete } #[put("/ciphers/<uuid>/delete")] -async fn delete_cipher_put(uuid: String, headers: Headers, mut conn: DbConn, nt: Notify<'_>) -> EmptyResult { - _delete_cipher_by_uuid(&uuid, &headers, &mut conn, true, &nt).await +async fn delete_cipher_put(uuid: &str, headers: Headers, mut conn: DbConn, nt: Notify<'_>) -> EmptyResult { + _delete_cipher_by_uuid(uuid, &headers, &mut conn, true, &nt).await // soft delete } #[put("/ciphers/<uuid>/delete-admin")] -async fn delete_cipher_put_admin(uuid: String, headers: Headers, mut conn: DbConn, nt: Notify<'_>) -> EmptyResult { - _delete_cipher_by_uuid(&uuid, &headers, &mut conn, true, &nt).await +async fn delete_cipher_put_admin(uuid: &str, headers: Headers, mut conn: DbConn, nt: Notify<'_>) -> EmptyResult { + _delete_cipher_by_uuid(uuid, &headers, &mut conn, true, &nt).await } #[delete("/ciphers/<uuid>")] -async fn delete_cipher(uuid: String, headers: Headers, mut conn: DbConn, nt: Notify<'_>) -> EmptyResult { - _delete_cipher_by_uuid(&uuid, &headers, &mut conn, false, &nt).await +async fn delete_cipher(uuid: &str, headers: Headers, mut conn: DbConn, nt: Notify<'_>) -> EmptyResult { + _delete_cipher_by_uuid(uuid, &headers, &mut conn, false, &nt).await // permanent delete } #[delete("/ciphers/<uuid>/admin")] -async fn delete_cipher_admin(uuid: String, headers: Headers, mut conn: DbConn, nt: Notify<'_>) -> EmptyResult { - _delete_cipher_by_uuid(&uuid, &headers, &mut conn, false, &nt).await +async fn delete_cipher_admin(uuid: &str, headers: Headers, mut conn: DbConn, nt: Notify<'_>) -> EmptyResult { + _delete_cipher_by_uuid(uuid, &headers, &mut conn, false, &nt).await // permanent delete } @@ -1332,13 +1333,13 @@ async fn delete_cipher_selected_put_admin( } #[put("/ciphers/<uuid>/restore")] -async fn restore_cipher_put(uuid: String, headers: Headers, mut conn: DbConn, nt: Notify<'_>) -> JsonResult { - _restore_cipher_by_uuid(&uuid, &headers, &mut conn, &nt).await +async fn restore_cipher_put(uuid: &str, headers: Headers, mut conn: DbConn, nt: Notify<'_>) -> JsonResult { + _restore_cipher_by_uuid(uuid, &headers, &mut conn, &nt).await } #[put("/ciphers/<uuid>/restore-admin")] -async fn restore_cipher_put_admin(uuid: String, headers: Headers, mut conn: DbConn, nt: Notify<'_>) -> JsonResult { - _restore_cipher_by_uuid(&uuid, &headers, &mut conn, &nt).await +async fn restore_cipher_put_admin(uuid: &str, headers: Headers, mut conn: DbConn, nt: Notify<'_>) -> JsonResult { + _restore_cipher_by_uuid(uuid, &headers, &mut conn, &nt).await } #[put("/ciphers/restore", data = "<data>")] @@ -1444,7 +1445,7 @@ async fn delete_all( log_event( EventType::OrganizationPurgedVault as i32, &org_data.org_id, - org_data.org_id.clone(), + &org_data.org_id, user.uuid, headers.device.atype, &headers.ip.ip, @@ -1524,7 +1525,7 @@ async fn _delete_cipher_by_uuid( log_event( event_type, &cipher.uuid, - org_uuid, + &org_uuid, headers.user.uuid.clone(), headers.device.atype, &headers.ip.ip, @@ -1586,7 +1587,7 @@ async fn _restore_cipher_by_uuid(uuid: &str, headers: &Headers, conn: &mut DbCon log_event( EventType::CipherRestored as i32, &cipher.uuid.clone(), - String::from(org_uuid), + org_uuid, headers.user.uuid.clone(), headers.device.atype, &headers.ip.ip, @@ -1667,7 +1668,7 @@ async fn _delete_cipher_attachment_by_id( log_event( EventType::CipherAttachmentDeleted as i32, &cipher.uuid, - org_uuid, + &org_uuid, headers.user.uuid.clone(), headers.device.atype, &headers.ip.ip, diff --git a/src/api/core/emergency_access.rs b/src/api/core/emergency_access.rs @@ -71,10 +71,10 @@ async fn get_grantees(headers: Headers, mut conn: DbConn) -> JsonResult { } #[get("/emergency-access/<emer_id>")] -async fn get_emergency_access(emer_id: String, mut conn: DbConn) -> JsonResult { +async fn get_emergency_access(emer_id: &str, mut conn: DbConn) -> JsonResult { check_emergency_access_allowed()?; - match EmergencyAccess::find_by_uuid(&emer_id, &mut conn).await { + match EmergencyAccess::find_by_uuid(emer_id, &mut conn).await { Some(emergency_access) => Ok(Json(emergency_access.to_json_grantee_details(&mut conn).await)), None => err!("Emergency access not valid."), } @@ -93,17 +93,13 @@ struct EmergencyAccessUpdateData { } #[put("/emergency-access/<emer_id>", data = "<data>")] -async fn put_emergency_access( - emer_id: String, - data: JsonUpcase<EmergencyAccessUpdateData>, - conn: DbConn, -) -> JsonResult { +async fn put_emergency_access(emer_id: &str, data: JsonUpcase<EmergencyAccessUpdateData>, conn: DbConn) -> JsonResult { post_emergency_access(emer_id, data, conn).await } #[post("/emergency-access/<emer_id>", data = "<data>")] async fn post_emergency_access( - emer_id: String, + emer_id: &str, data: JsonUpcase<EmergencyAccessUpdateData>, mut conn: DbConn, ) -> JsonResult { @@ -111,7 +107,7 @@ async fn post_emergency_access( let data: EmergencyAccessUpdateData = data.into_inner().data; - let mut emergency_access = match EmergencyAccess::find_by_uuid(&emer_id, &mut conn).await { + let mut emergency_access = match EmergencyAccess::find_by_uuid(emer_id, &mut conn).await { Some(emergency_access) => emergency_access, None => err!("Emergency access not valid."), }; @@ -136,12 +132,12 @@ async fn post_emergency_access( // region delete #[delete("/emergency-access/<emer_id>")] -async fn delete_emergency_access(emer_id: String, headers: Headers, mut conn: DbConn) -> EmptyResult { +async fn delete_emergency_access(emer_id: &str, headers: Headers, mut conn: DbConn) -> EmptyResult { check_emergency_access_allowed()?; let grantor_user = headers.user; - let emergency_access = match EmergencyAccess::find_by_uuid(&emer_id, &mut conn).await { + let emergency_access = match EmergencyAccess::find_by_uuid(emer_id, &mut conn).await { Some(emer) => { if emer.grantor_uuid != grantor_user.uuid && emer.grantee_uuid != Some(grantor_user.uuid) { err!("Emergency access not valid.") @@ -155,7 +151,7 @@ async fn delete_emergency_access(emer_id: String, headers: Headers, mut conn: Db } #[post("/emergency-access/<emer_id>/delete")] -async fn post_delete_emergency_access(emer_id: String, headers: Headers, conn: DbConn) -> EmptyResult { +async fn post_delete_emergency_access(emer_id: &str, headers: Headers, conn: DbConn) -> EmptyResult { delete_emergency_access(emer_id, headers, conn).await } @@ -243,7 +239,7 @@ async fn send_invite(data: JsonUpcase<EmergencyAccessInviteData>, headers: Heade } else { // Automatically mark user as accepted if no email invites match User::find_by_mail(&email, &mut conn).await { - Some(user) => match accept_invite_process(user.uuid, &mut new_emergency_access, &email, &mut conn).await { + Some(user) => match accept_invite_process(&user.uuid, &mut new_emergency_access, &email, &mut conn).await { Ok(v) => v, Err(e) => err!(e.to_string()), }, @@ -255,10 +251,10 @@ async fn send_invite(data: JsonUpcase<EmergencyAccessInviteData>, headers: Heade } #[post("/emergency-access/<emer_id>/reinvite")] -async fn resend_invite(emer_id: String, headers: Headers, mut conn: DbConn) -> EmptyResult { +async fn resend_invite(emer_id: &str, headers: Headers, mut conn: DbConn) -> EmptyResult { check_emergency_access_allowed()?; - let mut emergency_access = match EmergencyAccess::find_by_uuid(&emer_id, &mut conn).await { + let mut emergency_access = match EmergencyAccess::find_by_uuid(emer_id, &mut conn).await { Some(emer) => emer, None => err!("Emergency access not valid."), }; @@ -299,7 +295,7 @@ async fn resend_invite(emer_id: String, headers: Headers, mut conn: DbConn) -> E } // Automatically mark user as accepted if no email invites - match accept_invite_process(grantee_user.uuid, &mut emergency_access, &email, &mut conn).await { + match accept_invite_process(&grantee_user.uuid, &mut emergency_access, &email, &mut conn).await { Ok(v) => v, Err(e) => err!(e.to_string()), } @@ -315,12 +311,7 @@ struct AcceptData { } #[post("/emergency-access/<emer_id>/accept", data = "<data>")] -async fn accept_invite( - emer_id: String, - data: JsonUpcase<AcceptData>, - headers: Headers, - mut conn: DbConn, -) -> EmptyResult { +async fn accept_invite(emer_id: &str, data: JsonUpcase<AcceptData>, headers: Headers, mut conn: DbConn) -> EmptyResult { check_emergency_access_allowed()?; let data: AcceptData = data.into_inner().data; @@ -341,7 +332,7 @@ async fn accept_invite( None => err!("Invited user not found"), }; - let mut emergency_access = match EmergencyAccess::find_by_uuid(&emer_id, &mut conn).await { + let mut emergency_access = match EmergencyAccess::find_by_uuid(emer_id, &mut conn).await { Some(emer) => emer, None => err!("Emergency access not valid."), }; @@ -356,7 +347,7 @@ async fn accept_invite( && grantor_user.name == claims.grantor_name && grantor_user.email == claims.grantor_email { - match accept_invite_process(grantee_user.uuid, &mut emergency_access, &grantee_user.email, &mut conn).await { + match accept_invite_process(&grantee_user.uuid, &mut emergency_access, &grantee_user.email, &mut conn).await { Ok(v) => v, Err(e) => err!(e.to_string()), } @@ -372,7 +363,7 @@ async fn accept_invite( } async fn accept_invite_process( - grantee_uuid: String, + grantee_uuid: &str, emergency_access: &mut EmergencyAccess, grantee_email: &str, conn: &mut DbConn, @@ -386,7 +377,7 @@ async fn accept_invite_process( } emergency_access.status = EmergencyAccessStatus::Accepted as i32; - emergency_access.grantee_uuid = Some(grantee_uuid); + emergency_access.grantee_uuid = Some(String::from(grantee_uuid)); emergency_access.email = None; emergency_access.save(conn).await } @@ -399,7 +390,7 @@ struct ConfirmData { #[post("/emergency-access/<emer_id>/confirm", data = "<data>")] async fn confirm_emergency_access( - emer_id: String, + emer_id: &str, data: JsonUpcase<ConfirmData>, headers: Headers, mut conn: DbConn, @@ -410,7 +401,7 @@ async fn confirm_emergency_access( let data: ConfirmData = data.into_inner().data; let key = data.Key; - let mut emergency_access = match EmergencyAccess::find_by_uuid(&emer_id, &mut conn).await { + let mut emergency_access = match EmergencyAccess::find_by_uuid(emer_id, &mut conn).await { Some(emer) => emer, None => err!("Emergency access not valid."), }; @@ -452,11 +443,11 @@ async fn confirm_emergency_access( // region access emergency access #[post("/emergency-access/<emer_id>/initiate")] -async fn initiate_emergency_access(emer_id: String, headers: Headers, mut conn: DbConn) -> JsonResult { +async fn initiate_emergency_access(emer_id: &str, headers: Headers, mut conn: DbConn) -> JsonResult { check_emergency_access_allowed()?; let initiating_user = headers.user; - let mut emergency_access = match EmergencyAccess::find_by_uuid(&emer_id, &mut conn).await { + let mut emergency_access = match EmergencyAccess::find_by_uuid(emer_id, &mut conn).await { Some(emer) => emer, None => err!("Emergency access not valid."), }; @@ -492,10 +483,10 @@ async fn initiate_emergency_access(emer_id: String, headers: Headers, mut conn: } #[post("/emergency-access/<emer_id>/approve")] -async fn approve_emergency_access(emer_id: String, headers: Headers, mut conn: DbConn) -> JsonResult { +async fn approve_emergency_access(emer_id: &str, headers: Headers, mut conn: DbConn) -> JsonResult { check_emergency_access_allowed()?; - let mut emergency_access = match EmergencyAccess::find_by_uuid(&emer_id, &mut conn).await { + let mut emergency_access = match EmergencyAccess::find_by_uuid(emer_id, &mut conn).await { Some(emer) => emer, None => err!("Emergency access not valid."), }; @@ -530,10 +521,10 @@ async fn approve_emergency_access(emer_id: String, headers: Headers, mut conn: D } #[post("/emergency-access/<emer_id>/reject")] -async fn reject_emergency_access(emer_id: String, headers: Headers, mut conn: DbConn) -> JsonResult { +async fn reject_emergency_access(emer_id: &str, headers: Headers, mut conn: DbConn) -> JsonResult { check_emergency_access_allowed()?; - let mut emergency_access = match EmergencyAccess::find_by_uuid(&emer_id, &mut conn).await { + let mut emergency_access = match EmergencyAccess::find_by_uuid(emer_id, &mut conn).await { Some(emer) => emer, None => err!("Emergency access not valid."), }; @@ -573,15 +564,15 @@ async fn reject_emergency_access(emer_id: String, headers: Headers, mut conn: Db // region action #[post("/emergency-access/<emer_id>/view")] -async fn view_emergency_access(emer_id: String, headers: Headers, mut conn: DbConn) -> JsonResult { +async fn view_emergency_access(emer_id: &str, headers: Headers, mut conn: DbConn) -> JsonResult { check_emergency_access_allowed()?; - let emergency_access = match EmergencyAccess::find_by_uuid(&emer_id, &mut conn).await { + let emergency_access = match EmergencyAccess::find_by_uuid(emer_id, &mut conn).await { Some(emer) => emer, None => err!("Emergency access not valid."), }; - if !is_valid_request(&emergency_access, headers.user.uuid, EmergencyAccessType::View) { + if !is_valid_request(&emergency_access, &headers.user.uuid, EmergencyAccessType::View) { err!("Emergency access not valid.") } @@ -610,16 +601,16 @@ async fn view_emergency_access(emer_id: String, headers: Headers, mut conn: DbCo } #[post("/emergency-access/<emer_id>/takeover")] -async fn takeover_emergency_access(emer_id: String, headers: Headers, mut conn: DbConn) -> JsonResult { +async fn takeover_emergency_access(emer_id: &str, headers: Headers, mut conn: DbConn) -> JsonResult { check_emergency_access_allowed()?; let requesting_user = headers.user; - let emergency_access = match EmergencyAccess::find_by_uuid(&emer_id, &mut conn).await { + let emergency_access = match EmergencyAccess::find_by_uuid(emer_id, &mut conn).await { Some(emer) => emer, None => err!("Emergency access not valid."), }; - if !is_valid_request(&emergency_access, requesting_user.uuid, EmergencyAccessType::Takeover) { + if !is_valid_request(&emergency_access, &requesting_user.uuid, EmergencyAccessType::Takeover) { err!("Emergency access not valid.") } @@ -649,7 +640,7 @@ struct EmergencyAccessPasswordData { #[post("/emergency-access/<emer_id>/password", data = "<data>")] async fn password_emergency_access( - emer_id: String, + emer_id: &str, data: JsonUpcase<EmergencyAccessPasswordData>, headers: Headers, mut conn: DbConn, @@ -661,12 +652,12 @@ async fn password_emergency_access( //let key = &data.Key; let requesting_user = headers.user; - let emergency_access = match EmergencyAccess::find_by_uuid(&emer_id, &mut conn).await { + let emergency_access = match EmergencyAccess::find_by_uuid(emer_id, &mut conn).await { Some(emer) => emer, None => err!("Emergency access not valid."), }; - if !is_valid_request(&emergency_access, requesting_user.uuid, EmergencyAccessType::Takeover) { + if !is_valid_request(&emergency_access, &requesting_user.uuid, EmergencyAccessType::Takeover) { err!("Emergency access not valid.") } @@ -694,14 +685,14 @@ async fn password_emergency_access( // endregion #[get("/emergency-access/<emer_id>/policies")] -async fn policies_emergency_access(emer_id: String, headers: Headers, mut conn: DbConn) -> JsonResult { +async fn policies_emergency_access(emer_id: &str, headers: Headers, mut conn: DbConn) -> JsonResult { let requesting_user = headers.user; - let emergency_access = match EmergencyAccess::find_by_uuid(&emer_id, &mut conn).await { + let emergency_access = match EmergencyAccess::find_by_uuid(emer_id, &mut conn).await { Some(emer) => emer, None => err!("Emergency access not valid."), }; - if !is_valid_request(&emergency_access, requesting_user.uuid, EmergencyAccessType::Takeover) { + if !is_valid_request(&emergency_access, &requesting_user.uuid, EmergencyAccessType::Takeover) { err!("Emergency access not valid.") } @@ -722,10 +713,11 @@ async fn policies_emergency_access(emer_id: String, headers: Headers, mut conn: fn is_valid_request( emergency_access: &EmergencyAccess, - requesting_user_uuid: String, + requesting_user_uuid: &str, requested_access_type: EmergencyAccessType, ) -> bool { - emergency_access.grantee_uuid == Some(requesting_user_uuid) + emergency_access.grantee_uuid.is_some() + && emergency_access.grantee_uuid.as_ref().unwrap() == requesting_user_uuid && emergency_access.status == EmergencyAccessStatus::RecoveryApproved as i32 && emergency_access.atype == requested_access_type as i32 } diff --git a/src/api/core/events.rs b/src/api/core/events.rs @@ -32,7 +32,7 @@ struct EventRange { // Upstream: https://github.com/bitwarden/server/blob/9ecf69d9cabce732cf2c57976dd9afa5728578fb/src/Api/Controllers/EventsController.cs#LL84C35-L84C41 #[get("/organizations/<org_id>/events?<data..>")] -async fn get_org_events(org_id: String, data: EventRange, _headers: AdminHeaders, mut conn: DbConn) -> JsonResult { +async fn get_org_events(org_id: &str, data: EventRange, _headers: AdminHeaders, mut conn: DbConn) -> JsonResult { // Return an empty vec when we org events are disabled. // This prevents client errors let events_json: Vec<Value> = if !CONFIG.org_events_enabled() { @@ -45,7 +45,7 @@ async fn get_org_events(org_id: String, data: EventRange, _headers: AdminHeaders parse_date(&data.end) }; - Event::find_by_organization_uuid(&org_id, &start_date, &end_date, &mut conn) + Event::find_by_organization_uuid(org_id, &start_date, &end_date, &mut conn) .await .iter() .map(|e| e.to_json()) @@ -60,14 +60,14 @@ async fn get_org_events(org_id: String, data: EventRange, _headers: AdminHeaders } #[get("/ciphers/<cipher_id>/events?<data..>")] -async fn get_cipher_events(cipher_id: String, data: EventRange, headers: Headers, mut conn: DbConn) -> JsonResult { +async fn get_cipher_events(cipher_id: &str, data: EventRange, headers: Headers, mut conn: DbConn) -> JsonResult { // Return an empty vec when we org events are disabled. // This prevents client errors let events_json: Vec<Value> = if !CONFIG.org_events_enabled() { Vec::with_capacity(0) } else { let mut events_json = Vec::with_capacity(0); - if UserOrganization::user_has_ge_admin_access_to_cipher(&headers.user.uuid, &cipher_id, &mut conn).await { + if UserOrganization::user_has_ge_admin_access_to_cipher(&headers.user.uuid, cipher_id, &mut conn).await { let start_date = parse_date(&data.start); let end_date = if let Some(before_date) = &data.continuation_token { parse_date(before_date) @@ -75,7 +75,7 @@ async fn get_cipher_events(cipher_id: String, data: EventRange, headers: Headers parse_date(&data.end) }; - events_json = Event::find_by_cipher_uuid(&cipher_id, &start_date, &end_date, &mut conn) + events_json = Event::find_by_cipher_uuid(cipher_id, &start_date, &end_date, &mut conn) .await .iter() .map(|e| e.to_json()) @@ -93,8 +93,8 @@ async fn get_cipher_events(cipher_id: String, data: EventRange, headers: Headers #[get("/organizations/<org_id>/users/<user_org_id>/events?<data..>")] async fn get_user_events( - org_id: String, - user_org_id: String, + org_id: &str, + user_org_id: &str, data: EventRange, _headers: AdminHeaders, mut conn: DbConn, @@ -111,7 +111,7 @@ async fn get_user_events( parse_date(&data.end) }; - Event::find_by_org_and_user_org(&org_id, &user_org_id, &start_date, &end_date, &mut conn) + Event::find_by_org_and_user_org(org_id, user_org_id, &start_date, &end_date, &mut conn) .await .iter() .map(|e| e.to_json()) @@ -185,7 +185,7 @@ async fn post_events_collect(data: JsonUpcaseVec<EventCollection>, headers: Head _log_event( event.Type, org_uuid, - String::from(org_uuid), + org_uuid, &headers.user.uuid, headers.device.atype, Some(event_date), @@ -202,7 +202,7 @@ async fn post_events_collect(data: JsonUpcaseVec<EventCollection>, headers: Head _log_event( event.Type, cipher_uuid, - org_uuid, + &org_uuid, &headers.user.uuid, headers.device.atype, Some(event_date), @@ -262,7 +262,7 @@ async fn _log_user_event( pub async fn log_event( event_type: i32, source_uuid: &str, - org_uuid: String, + org_uuid: &str, act_user_uuid: String, device_type: i32, ip: &IpAddr, @@ -278,7 +278,7 @@ pub async fn log_event( async fn _log_event( event_type: i32, source_uuid: &str, - org_uuid: String, + org_uuid: &str, act_user_uuid: &str, device_type: i32, event_date: Option<NaiveDateTime>, @@ -314,7 +314,7 @@ async fn _log_event( _ => {} } - event.org_uuid = Some(org_uuid); + event.org_uuid = Some(String::from(org_uuid)); event.act_user_uuid = Some(String::from(act_user_uuid)); event.device_type = Some(device_type); event.ip_address = Some(ip.to_string()); diff --git a/src/api/core/folders.rs b/src/api/core/folders.rs @@ -24,8 +24,8 @@ async fn get_folders(headers: Headers, mut conn: DbConn) -> Json<Value> { } #[get("/folders/<uuid>")] -async fn get_folder(uuid: String, headers: Headers, mut conn: DbConn) -> JsonResult { - let folder = match Folder::find_by_uuid(&uuid, &mut conn).await { +async fn get_folder(uuid: &str, headers: Headers, mut conn: DbConn) -> JsonResult { + let folder = match Folder::find_by_uuid(uuid, &mut conn).await { Some(folder) => folder, _ => err!("Invalid folder"), }; @@ -57,7 +57,7 @@ async fn post_folders(data: JsonUpcase<FolderData>, headers: Headers, mut conn: #[post("/folders/<uuid>", data = "<data>")] async fn post_folder( - uuid: String, + uuid: &str, data: JsonUpcase<FolderData>, headers: Headers, conn: DbConn, @@ -68,7 +68,7 @@ async fn post_folder( #[put("/folders/<uuid>", data = "<data>")] async fn put_folder( - uuid: String, + uuid: &str, data: JsonUpcase<FolderData>, headers: Headers, mut conn: DbConn, @@ -76,7 +76,7 @@ async fn put_folder( ) -> JsonResult { let data: FolderData = data.into_inner().data; - let mut folder = match Folder::find_by_uuid(&uuid, &mut conn).await { + let mut folder = match Folder::find_by_uuid(uuid, &mut conn).await { Some(folder) => folder, _ => err!("Invalid folder"), }; @@ -94,13 +94,13 @@ async fn put_folder( } #[post("/folders/<uuid>/delete")] -async fn delete_folder_post(uuid: String, headers: Headers, conn: DbConn, nt: Notify<'_>) -> EmptyResult { +async fn delete_folder_post(uuid: &str, headers: Headers, conn: DbConn, nt: Notify<'_>) -> EmptyResult { delete_folder(uuid, headers, conn, nt).await } #[delete("/folders/<uuid>")] -async fn delete_folder(uuid: String, headers: Headers, mut conn: DbConn, nt: Notify<'_>) -> EmptyResult { - let folder = match Folder::find_by_uuid(&uuid, &mut conn).await { +async fn delete_folder(uuid: &str, headers: Headers, mut conn: DbConn, nt: Notify<'_>) -> EmptyResult { + let folder = match Folder::find_by_uuid(uuid, &mut conn).await { Some(folder) => folder, _ => err!("Invalid folder"), }; diff --git a/src/api/core/mod.rs b/src/api/core/mod.rs @@ -58,7 +58,7 @@ use crate::{ }; #[put("/devices/identifier/<uuid>/clear-token")] -fn clear_device_token(uuid: String) -> &'static str { +fn clear_device_token(uuid: &str) -> &'static str { // This endpoint doesn't have auth header let _ = uuid; @@ -71,7 +71,7 @@ fn clear_device_token(uuid: String) -> &'static str { } #[put("/devices/identifier/<uuid>/token", data = "<data>")] -fn put_device_token(uuid: String, data: JsonUpcase<Value>, headers: Headers) -> Json<Value> { +fn put_device_token(uuid: &str, data: JsonUpcase<Value>, headers: Headers) -> Json<Value> { let _data: Value = data.into_inner().data; // Data has a single string value "PushToken" let _ = uuid; @@ -170,7 +170,7 @@ async fn put_eq_domains( } #[get("/hibp/breach?<username>")] -async fn hibp_breach(username: String) -> JsonResult { +async fn hibp_breach(username: &str) -> JsonResult { let url = format!( "https://haveibeenpwned.com/api/v3/breachedaccount/{username}?truncateResponse=false&includeUnverified=false" ); diff --git a/src/api/core/organizations.rs b/src/api/core/organizations.rs @@ -182,7 +182,7 @@ async fn create_organization(headers: Headers, data: JsonUpcase<OrgData>, mut co #[delete("/organizations/<org_id>", data = "<data>")] async fn delete_organization( - org_id: String, + org_id: &str, data: JsonUpcase<PasswordData>, headers: OwnerHeaders, mut conn: DbConn, @@ -194,7 +194,7 @@ async fn delete_organization( err!("Invalid password") } - match Organization::find_by_uuid(&org_id, &mut conn).await { + match Organization::find_by_uuid(org_id, &mut conn).await { None => err!("Organization not found"), Some(org) => org.delete(&mut conn).await, } @@ -202,7 +202,7 @@ async fn delete_organization( #[post("/organizations/<org_id>/delete", data = "<data>")] async fn post_delete_organization( - org_id: String, + org_id: &str, data: JsonUpcase<PasswordData>, headers: OwnerHeaders, conn: DbConn, @@ -211,12 +211,12 @@ async fn post_delete_organization( } #[post("/organizations/<org_id>/leave")] -async fn leave_organization(org_id: String, headers: Headers, mut conn: DbConn) -> EmptyResult { - match UserOrganization::find_by_user_and_org(&headers.user.uuid, &org_id, &mut conn).await { +async fn leave_organization(org_id: &str, headers: Headers, mut conn: DbConn) -> EmptyResult { + match UserOrganization::find_by_user_and_org(&headers.user.uuid, org_id, &mut conn).await { None => err!("User not part of organization"), Some(user_org) => { if user_org.atype == UserOrgType::Owner - && UserOrganization::count_confirmed_by_org_and_type(&org_id, UserOrgType::Owner, &mut conn).await <= 1 + && UserOrganization::count_confirmed_by_org_and_type(org_id, UserOrgType::Owner, &mut conn).await <= 1 { err!("The last owner can't leave") } @@ -238,8 +238,8 @@ async fn leave_organization(org_id: String, headers: Headers, mut conn: DbConn) } #[get("/organizations/<org_id>")] -async fn get_organization(org_id: String, _headers: OwnerHeaders, mut conn: DbConn) -> JsonResult { - match Organization::find_by_uuid(&org_id, &mut conn).await { +async fn get_organization(org_id: &str, _headers: OwnerHeaders, mut conn: DbConn) -> JsonResult { + match Organization::find_by_uuid(org_id, &mut conn).await { Some(organization) => Ok(Json(organization.to_json())), None => err!("Can't find organization details"), } @@ -247,7 +247,7 @@ async fn get_organization(org_id: String, _headers: OwnerHeaders, mut conn: DbCo #[put("/organizations/<org_id>", data = "<data>")] async fn put_organization( - org_id: String, + org_id: &str, headers: OwnerHeaders, data: JsonUpcase<OrganizationUpdateData>, conn: DbConn, @@ -257,14 +257,14 @@ async fn put_organization( #[post("/organizations/<org_id>", data = "<data>")] async fn post_organization( - org_id: String, + org_id: &str, headers: OwnerHeaders, data: JsonUpcase<OrganizationUpdateData>, mut conn: DbConn, ) -> JsonResult { let data: OrganizationUpdateData = data.into_inner().data; - let mut org = match Organization::find_by_uuid(&org_id, &mut conn).await { + let mut org = match Organization::find_by_uuid(org_id, &mut conn).await { Some(organization) => organization, None => err!("Can't find organization details"), }; @@ -276,8 +276,8 @@ async fn post_organization( log_event( EventType::OrganizationUpdated as i32, - &org_id, - org_id.clone(), + org_id, + org_id, headers.user.uuid.clone(), headers.device.atype, &headers.ip.ip, @@ -303,26 +303,26 @@ async fn get_user_collections(headers: Headers, mut conn: DbConn) -> Json<Value> } #[get("/organizations/<org_id>/collections")] -async fn get_org_collections(org_id: String, _headers: ManagerHeadersLoose, mut conn: DbConn) -> Json<Value> { +async fn get_org_collections(org_id: &str, _headers: ManagerHeadersLoose, mut conn: DbConn) -> Json<Value> { Json(json!({ - "Data": _get_org_collections(&org_id, &mut conn).await, + "Data": _get_org_collections(org_id, &mut conn).await, "Object": "list", "ContinuationToken": null, })) } #[get("/organizations/<org_id>/collections/details")] -async fn get_org_collections_details(org_id: String, headers: ManagerHeadersLoose, mut conn: DbConn) -> JsonResult { +async fn get_org_collections_details(org_id: &str, headers: ManagerHeadersLoose, mut conn: DbConn) -> JsonResult { let mut data = Vec::new(); - let user_org = match UserOrganization::find_by_user_and_org(&headers.user.uuid, &org_id, &mut conn).await { + let user_org = match UserOrganization::find_by_user_and_org(&headers.user.uuid, org_id, &mut conn).await { Some(u) => u, None => err!("User is not part of organization"), }; - let coll_users = CollectionUser::find_by_organization(&org_id, &mut conn).await; + let coll_users = CollectionUser::find_by_organization(org_id, &mut conn).await; - for col in Collection::find_by_organization(&org_id, &mut conn).await { + for col in Collection::find_by_organization(org_id, &mut conn).await { let groups: Vec<Value> = if CONFIG.org_groups_enabled() { CollectionGroup::find_by_collection(&col.uuid, &mut conn) .await @@ -376,14 +376,14 @@ async fn _get_org_collections(org_id: &str, conn: &mut DbConn) -> Value { #[post("/organizations/<org_id>/collections", data = "<data>")] async fn post_organization_collections( - org_id: String, + org_id: &str, headers: ManagerHeadersLoose, data: JsonUpcase<NewCollectionData>, mut conn: DbConn, ) -> JsonResult { let data: NewCollectionData = data.into_inner().data; - let org = match Organization::find_by_uuid(&org_id, &mut conn).await { + let org = match Organization::find_by_uuid(org_id, &mut conn).await { Some(organization) => organization, None => err!("Can't find organization details"), }; @@ -427,8 +427,8 @@ async fn post_organization_collections( #[put("/organizations/<org_id>/collections/<col_id>", data = "<data>")] async fn put_organization_collection_update( - org_id: String, - col_id: String, + org_id: &str, + col_id: &str, headers: ManagerHeaders, data: JsonUpcase<NewCollectionData>, conn: DbConn, @@ -438,20 +438,20 @@ async fn put_organization_collection_update( #[post("/organizations/<org_id>/collections/<col_id>", data = "<data>")] async fn post_organization_collection_update( - org_id: String, - col_id: String, + org_id: &str, + col_id: &str, headers: ManagerHeaders, data: JsonUpcase<NewCollectionData>, mut conn: DbConn, ) -> JsonResult { let data: NewCollectionData = data.into_inner().data; - let org = match Organization::find_by_uuid(&org_id, &mut conn).await { + let org = match Organization::find_by_uuid(org_id, &mut conn).await { Some(organization) => organization, None => err!("Can't find organization details"), }; - let mut collection = match Collection::find_by_uuid(&col_id, &mut conn).await { + let mut collection = match Collection::find_by_uuid(col_id, &mut conn).await { Some(collection) => collection, None => err!("Collection not found"), }; @@ -474,13 +474,15 @@ async fn post_organization_collection_update( ) .await; - CollectionGroup::delete_all_by_collection(&col_id, &mut conn).await?; + CollectionGroup::delete_all_by_collection(col_id, &mut conn).await?; for group in data.Groups { - CollectionGroup::new(col_id.clone(), group.Id, group.ReadOnly, group.HidePasswords).save(&mut conn).await?; + CollectionGroup::new(String::from(col_id), group.Id, group.ReadOnly, group.HidePasswords) + .save(&mut conn) + .await?; } - CollectionUser::delete_all_by_collection(&col_id, &mut conn).await?; + CollectionUser::delete_all_by_collection(col_id, &mut conn).await?; for user in data.Users { let org_user = match UserOrganization::find_by_uuid(&user.Id, &mut conn).await { @@ -492,7 +494,7 @@ async fn post_organization_collection_update( continue; } - CollectionUser::save(&org_user.user_uuid, &col_id, user.ReadOnly, user.HidePasswords, &mut conn).await?; + CollectionUser::save(&org_user.user_uuid, col_id, user.ReadOnly, user.HidePasswords, &mut conn).await?; } Ok(Json(collection.to_json())) @@ -500,13 +502,13 @@ async fn post_organization_collection_update( #[delete("/organizations/<org_id>/collections/<col_id>/user/<org_user_id>")] async fn delete_organization_collection_user( - org_id: String, - col_id: String, - org_user_id: String, + org_id: &str, + col_id: &str, + org_user_id: &str, _headers: AdminHeaders, mut conn: DbConn, ) -> EmptyResult { - let collection = match Collection::find_by_uuid(&col_id, &mut conn).await { + let collection = match Collection::find_by_uuid(col_id, &mut conn).await { None => err!("Collection not found"), Some(collection) => { if collection.org_uuid == org_id { @@ -517,7 +519,7 @@ async fn delete_organization_collection_user( } }; - match UserOrganization::find_by_uuid_and_org(&org_user_id, &org_id, &mut conn).await { + match UserOrganization::find_by_uuid_and_org(org_user_id, org_id, &mut conn).await { None => err!("User not found in organization"), Some(user_org) => { match CollectionUser::find_by_collection_and_user(&collection.uuid, &user_org.user_uuid, &mut conn).await { @@ -530,9 +532,9 @@ async fn delete_organization_collection_user( #[post("/organizations/<org_id>/collections/<col_id>/delete-user/<org_user_id>")] async fn post_organization_collection_delete_user( - org_id: String, - col_id: String, - org_user_id: String, + org_id: &str, + col_id: &str, + org_user_id: &str, headers: AdminHeaders, conn: DbConn, ) -> EmptyResult { @@ -552,7 +554,7 @@ async fn _delete_organization_collection( log_event( EventType::CollectionDeleted as i32, &collection.uuid, - org_id.to_string(), + org_id, headers.user.uuid.clone(), headers.device.atype, &headers.ip.ip, @@ -569,12 +571,12 @@ async fn _delete_organization_collection( #[delete("/organizations/<org_id>/collections/<col_id>")] async fn delete_organization_collection( - org_id: String, - col_id: String, + org_id: &str, + col_id: &str, headers: ManagerHeaders, mut conn: DbConn, ) -> EmptyResult { - _delete_organization_collection(&org_id, &col_id, &headers, &mut conn).await + _delete_organization_collection(org_id, col_id, &headers, &mut conn).await } #[derive(Deserialize, Debug)] @@ -586,13 +588,13 @@ struct DeleteCollectionData { #[post("/organizations/<org_id>/collections/<col_id>/delete", data = "<_data>")] async fn post_organization_collection_delete( - org_id: String, - col_id: String, + org_id: &str, + col_id: &str, headers: ManagerHeaders, _data: JsonUpcase<DeleteCollectionData>, mut conn: DbConn, ) -> EmptyResult { - _delete_organization_collection(&org_id, &col_id, &headers, &mut conn).await + _delete_organization_collection(org_id, col_id, &headers, &mut conn).await } #[derive(Deserialize, Debug)] @@ -626,19 +628,19 @@ async fn bulk_delete_organization_collections( #[get("/organizations/<org_id>/collections/<coll_id>/details")] async fn get_org_collection_detail( - org_id: String, - coll_id: String, + org_id: &str, + coll_id: &str, headers: ManagerHeaders, mut conn: DbConn, ) -> JsonResult { - match Collection::find_by_uuid_and_user(&coll_id, headers.user.uuid.clone(), &mut conn).await { + match Collection::find_by_uuid_and_user(coll_id, headers.user.uuid.clone(), &mut conn).await { None => err!("Collection not found"), Some(collection) => { if collection.org_uuid != org_id { err!("Collection is not owned by organization") } - let user_org = match UserOrganization::find_by_user_and_org(&headers.user.uuid, &org_id, &mut conn).await { + let user_org = match UserOrganization::find_by_user_and_org(&headers.user.uuid, org_id, &mut conn).await { Some(u) => u, None => err!("User is not part of organization"), }; @@ -688,14 +690,9 @@ async fn get_org_collection_detail( } #[get("/organizations/<org_id>/collections/<coll_id>/users")] -async fn get_collection_users( - org_id: String, - coll_id: String, - _headers: ManagerHeaders, - mut conn: DbConn, -) -> JsonResult { +async fn get_collection_users(org_id: &str, coll_id: &str, _headers: ManagerHeaders, mut conn: DbConn) -> JsonResult { // Get org and collection, check that collection is from org - let collection = match Collection::find_by_uuid_and_org(&coll_id, &org_id, &mut conn).await { + let collection = match Collection::find_by_uuid_and_org(coll_id, org_id, &mut conn).await { None => err!("Collection not found in Organization"), Some(collection) => collection, }; @@ -703,7 +700,7 @@ async fn get_collection_users( let mut user_list = Vec::new(); for col_user in CollectionUser::find_by_collection(&collection.uuid, &mut conn).await { user_list.push( - UserOrganization::find_by_user_and_org(&col_user.user_uuid, &org_id, &mut conn) + UserOrganization::find_by_user_and_org(&col_user.user_uuid, org_id, &mut conn) .await .unwrap() .to_json_user_access_restrictions(&col_user), @@ -715,19 +712,19 @@ async fn get_collection_users( #[put("/organizations/<org_id>/collections/<coll_id>/users", data = "<data>")] async fn put_collection_users( - org_id: String, - coll_id: String, + org_id: &str, + coll_id: &str, data: JsonUpcaseVec<CollectionData>, _headers: ManagerHeaders, mut conn: DbConn, ) -> EmptyResult { // Get org and collection, check that collection is from org - if Collection::find_by_uuid_and_org(&coll_id, &org_id, &mut conn).await.is_none() { + if Collection::find_by_uuid_and_org(coll_id, org_id, &mut conn).await.is_none() { err!("Collection not found in Organization") } // Delete all the user-collections - CollectionUser::delete_all_by_collection(&coll_id, &mut conn).await?; + CollectionUser::delete_all_by_collection(coll_id, &mut conn).await?; // And then add all the received ones (except if the user has access_all) for d in data.iter().map(|d| &d.data) { @@ -740,7 +737,7 @@ async fn put_collection_users( continue; } - CollectionUser::save(&user.user_uuid, &coll_id, d.ReadOnly, d.HidePasswords, &mut conn).await?; + CollectionUser::save(&user.user_uuid, coll_id, d.ReadOnly, d.HidePasswords, &mut conn).await?; } Ok(()) @@ -784,12 +781,12 @@ struct GetOrgUserData { #[get("/organizations/<org_id>/users?<data..>")] async fn get_org_users( data: GetOrgUserData, - org_id: String, + org_id: &str, _headers: ManagerHeadersLoose, mut conn: DbConn, ) -> Json<Value> { let mut users_json = Vec::new(); - for u in UserOrganization::find_by_org(&org_id, &mut conn).await { + for u in UserOrganization::find_by_org(org_id, &mut conn).await { users_json.push( u.to_json_user_details( data.include_collections.unwrap_or(false), @@ -809,14 +806,14 @@ async fn get_org_users( #[post("/organizations/<org_id>/keys", data = "<data>")] async fn post_org_keys( - org_id: String, + org_id: &str, data: JsonUpcase<OrgKeyData>, _headers: AdminHeaders, mut conn: DbConn, ) -> JsonResult { let data: OrgKeyData = data.into_inner().data; - let mut org = match Organization::find_by_uuid(&org_id, &mut conn).await { + let mut org = match Organization::find_by_uuid(org_id, &mut conn).await { Some(organization) => { if organization.private_key.is_some() && organization.public_key.is_some() { err!("Organization Keys already exist") @@ -857,7 +854,7 @@ struct InviteData { #[post("/organizations/<org_id>/users/invite", data = "<data>")] async fn send_invite( - org_id: String, + org_id: &str, data: JsonUpcase<InviteData>, headers: AdminHeaders, mut conn: DbConn, @@ -896,7 +893,7 @@ async fn send_invite( user } Some(user) => { - if UserOrganization::find_by_user_and_org(&user.uuid, &org_id, &mut conn).await.is_some() { + if UserOrganization::find_by_user_and_org(&user.uuid, org_id, &mut conn).await.is_some() { err!(format!("User already in organization: {email}")) } else { // automatically accept existing users if mail is disabled @@ -908,7 +905,7 @@ async fn send_invite( } }; - let mut new_user = UserOrganization::new(user.uuid.clone(), org_id.clone()); + let mut new_user = UserOrganization::new(user.uuid.clone(), String::from(org_id)); let access_all = data.AccessAll.unwrap_or(false); new_user.access_all = access_all; new_user.atype = new_type; @@ -917,7 +914,7 @@ async fn send_invite( // If no accessAll, add the collections received if !access_all { for col in data.Collections.iter().flatten() { - match Collection::find_by_uuid_and_org(&col.Id, &org_id, &mut conn).await { + match Collection::find_by_uuid_and_org(&col.Id, org_id, &mut conn).await { None => err!("Collection not found in Organization"), Some(collection) => { CollectionUser::save(&user.uuid, &collection.uuid, col.ReadOnly, col.HidePasswords, &mut conn) @@ -932,7 +929,7 @@ async fn send_invite( log_event( EventType::OrganizationUserInvited as i32, &new_user.uuid, - org_id.clone(), + org_id, headers.user.uuid.clone(), headers.device.atype, &headers.ip.ip, @@ -941,7 +938,7 @@ async fn send_invite( .await; if CONFIG.mail_enabled() { - let org_name = match Organization::find_by_uuid(&org_id, &mut conn).await { + let org_name = match Organization::find_by_uuid(org_id, &mut conn).await { Some(org) => org.name, None => err!("Error looking up organization"), }; @@ -949,7 +946,7 @@ async fn send_invite( mail::send_invite( &email, &user.uuid, - Some(org_id.clone()), + Some(String::from(org_id)), Some(new_user.uuid), &org_name, Some(headers.user.email.clone()), @@ -963,7 +960,7 @@ async fn send_invite( #[post("/organizations/<org_id>/users/reinvite", data = "<data>")] async fn bulk_reinvite_user( - org_id: String, + org_id: &str, data: JsonUpcase<OrgBulkIds>, headers: AdminHeaders, mut conn: DbConn, @@ -972,7 +969,7 @@ async fn bulk_reinvite_user( let mut bulk_response = Vec::new(); for org_user_id in data.Ids { - let err_msg = match _reinvite_user(&org_id, &org_user_id, &headers.user.email, &mut conn).await { + let err_msg = match _reinvite_user(org_id, &org_user_id, &headers.user.email, &mut conn).await { Ok(_) => String::new(), Err(e) => format!("{e:?}"), }; @@ -994,8 +991,8 @@ async fn bulk_reinvite_user( } #[post("/organizations/<org_id>/users/<user_org>/reinvite")] -async fn reinvite_user(org_id: String, user_org: String, headers: AdminHeaders, mut conn: DbConn) -> EmptyResult { - _reinvite_user(&org_id, &user_org, &headers.user.email, &mut conn).await +async fn reinvite_user(org_id: &str, user_org: &str, headers: AdminHeaders, mut conn: DbConn) -> EmptyResult { + _reinvite_user(org_id, user_org, &headers.user.email, &mut conn).await } async fn _reinvite_user(org_id: &str, user_org: &str, invited_by_email: &str, conn: &mut DbConn) -> EmptyResult { @@ -1053,8 +1050,8 @@ struct AcceptData { #[post("/organizations/<org_id>/users/<_org_user_id>/accept", data = "<data>")] async fn accept_invite( - org_id: String, - _org_user_id: String, + org_id: &str, + _org_user_id: &str, data: JsonUpcase<AcceptData>, mut conn: DbConn, ) -> EmptyResult { @@ -1084,7 +1081,7 @@ async fn accept_invite( // This check is also done at accept_invite(), _confirm_invite, _activate_user(), edit_user(), admin::update_user_org_type // It returns different error messages per function. if user_org.atype < UserOrgType::Admin { - match OrgPolicy::is_user_allowed(&user_org.user_uuid, &org_id, false, &mut conn).await { + match OrgPolicy::is_user_allowed(&user_org.user_uuid, org_id, false, &mut conn).await { Ok(_) => {} Err(OrgPolicyErr::TwoFactorMissing) => { err!("You cannot join this organization until you enable two-step login on your user account"); @@ -1129,7 +1126,7 @@ async fn accept_invite( #[post("/organizations/<org_id>/users/confirm", data = "<data>")] async fn bulk_confirm_invite( - org_id: String, + org_id: &str, data: JsonUpcase<Value>, headers: AdminHeaders, mut conn: DbConn, @@ -1143,7 +1140,7 @@ async fn bulk_confirm_invite( for invite in keys { let org_user_id = invite["Id"].as_str().unwrap_or_default(); let user_key = invite["Key"].as_str().unwrap_or_default(); - let err_msg = match _confirm_invite(&org_id, org_user_id, user_key, &headers, &mut conn, &nt).await { + let err_msg = match _confirm_invite(org_id, org_user_id, user_key, &headers, &mut conn, &nt).await { Ok(_) => String::new(), Err(e) => format!("{e:?}"), }; @@ -1169,8 +1166,8 @@ async fn bulk_confirm_invite( #[post("/organizations/<org_id>/users/<org_user_id>/confirm", data = "<data>")] async fn confirm_invite( - org_id: String, - org_user_id: String, + org_id: &str, + org_user_id: &str, data: JsonUpcase<Value>, headers: AdminHeaders, mut conn: DbConn, @@ -1178,7 +1175,7 @@ async fn confirm_invite( ) -> EmptyResult { let data = data.into_inner().data; let user_key = data["Key"].as_str().unwrap_or_default(); - _confirm_invite(&org_id, &org_user_id, user_key, &headers, &mut conn, &nt).await + _confirm_invite(org_id, org_user_id, user_key, &headers, &mut conn, &nt).await } async fn _confirm_invite( @@ -1226,7 +1223,7 @@ async fn _confirm_invite( log_event( EventType::OrganizationUserConfirmed as i32, &user_to_confirm.uuid, - String::from(org_id), + org_id, headers.user.uuid.clone(), headers.device.atype, &headers.ip.ip, @@ -1257,13 +1254,13 @@ async fn _confirm_invite( #[get("/organizations/<org_id>/users/<org_user_id>?<data..>")] async fn get_user( - org_id: String, - org_user_id: String, + org_id: &str, + org_user_id: &str, data: GetOrgUserData, _headers: AdminHeaders, mut conn: DbConn, ) -> JsonResult { - let user = match UserOrganization::find_by_uuid_and_org(&org_user_id, &org_id, &mut conn).await { + let user = match UserOrganization::find_by_uuid_and_org(org_user_id, org_id, &mut conn).await { Some(user) => user, None => err!("The specified user isn't a member of the organization"), }; @@ -1287,8 +1284,8 @@ struct EditUserData { #[put("/organizations/<org_id>/users/<org_user_id>", data = "<data>", rank = 1)] async fn put_organization_user( - org_id: String, - org_user_id: String, + org_id: &str, + org_user_id: &str, data: JsonUpcase<EditUserData>, headers: AdminHeaders, conn: DbConn, @@ -1298,8 +1295,8 @@ async fn put_organization_user( #[post("/organizations/<org_id>/users/<org_user_id>", data = "<data>", rank = 1)] async fn edit_user( - org_id: String, - org_user_id: String, + org_id: &str, + org_user_id: &str, data: JsonUpcase<EditUserData>, headers: AdminHeaders, mut conn: DbConn, @@ -1311,7 +1308,7 @@ async fn edit_user( None => err!("Invalid type"), }; - let mut user_to_edit = match UserOrganization::find_by_uuid_and_org(&org_user_id, &org_id, &mut conn).await { + let mut user_to_edit = match UserOrganization::find_by_uuid_and_org(org_user_id, org_id, &mut conn).await { Some(user) => user, None => err!("The specified user isn't member of the organization"), }; @@ -1332,7 +1329,7 @@ async fn edit_user( && user_to_edit.status == UserOrgStatus::Confirmed as i32 { // Removing owner permission, check that there is at least one other confirmed owner - if UserOrganization::count_confirmed_by_org_and_type(&org_id, UserOrgType::Owner, &mut conn).await <= 1 { + if UserOrganization::count_confirmed_by_org_and_type(org_id, UserOrgType::Owner, &mut conn).await <= 1 { err!("Can't delete the last owner") } } @@ -1340,7 +1337,7 @@ async fn edit_user( // This check is also done at accept_invite(), _confirm_invite, _activate_user(), edit_user(), admin::update_user_org_type // It returns different error messages per function. if new_type < UserOrgType::Admin { - match OrgPolicy::is_user_allowed(&user_to_edit.user_uuid, &org_id, true, &mut conn).await { + match OrgPolicy::is_user_allowed(&user_to_edit.user_uuid, org_id, true, &mut conn).await { Ok(_) => {} Err(OrgPolicyErr::TwoFactorMissing) => { err!("You cannot modify this user to this type because it has no two-step login method activated"); @@ -1355,14 +1352,14 @@ async fn edit_user( user_to_edit.atype = new_type as i32; // Delete all the odd collections - for c in CollectionUser::find_by_organization_and_user_uuid(&org_id, &user_to_edit.user_uuid, &mut conn).await { + for c in CollectionUser::find_by_organization_and_user_uuid(org_id, &user_to_edit.user_uuid, &mut conn).await { c.delete(&mut conn).await?; } // If no accessAll, add the collections received if !data.AccessAll { for col in data.Collections.iter().flatten() { - match Collection::find_by_uuid_and_org(&col.Id, &org_id, &mut conn).await { + match Collection::find_by_uuid_and_org(&col.Id, org_id, &mut conn).await { None => err!("Collection not found in Organization"), Some(collection) => { CollectionUser::save( @@ -1388,7 +1385,7 @@ async fn edit_user( log_event( EventType::OrganizationUserUpdated as i32, &user_to_edit.uuid, - org_id.clone(), + org_id, headers.user.uuid.clone(), headers.device.atype, &headers.ip.ip, @@ -1401,7 +1398,7 @@ async fn edit_user( #[delete("/organizations/<org_id>/users", data = "<data>")] async fn bulk_delete_user( - org_id: String, + org_id: &str, data: JsonUpcase<OrgBulkIds>, headers: AdminHeaders, mut conn: DbConn, @@ -1411,7 +1408,7 @@ async fn bulk_delete_user( let mut bulk_response = Vec::new(); for org_user_id in data.Ids { - let err_msg = match _delete_user(&org_id, &org_user_id, &headers, &mut conn, &nt).await { + let err_msg = match _delete_user(org_id, &org_user_id, &headers, &mut conn, &nt).await { Ok(_) => String::new(), Err(e) => format!("{e:?}"), }; @@ -1434,24 +1431,24 @@ async fn bulk_delete_user( #[delete("/organizations/<org_id>/users/<org_user_id>")] async fn delete_user( - org_id: String, - org_user_id: String, + org_id: &str, + org_user_id: &str, headers: AdminHeaders, mut conn: DbConn, nt: Notify<'_>, ) -> EmptyResult { - _delete_user(&org_id, &org_user_id, &headers, &mut conn, &nt).await + _delete_user(org_id, org_user_id, &headers, &mut conn, &nt).await } #[post("/organizations/<org_id>/users/<org_user_id>/delete")] async fn post_delete_user( - org_id: String, - org_user_id: String, + org_id: &str, + org_user_id: &str, headers: AdminHeaders, mut conn: DbConn, nt: Notify<'_>, ) -> EmptyResult { - _delete_user(&org_id, &org_user_id, &headers, &mut conn, &nt).await + _delete_user(org_id, org_user_id, &headers, &mut conn, &nt).await } async fn _delete_user( @@ -1480,7 +1477,7 @@ async fn _delete_user( log_event( EventType::OrganizationUserRemoved as i32, &user_to_delete.uuid, - String::from(org_id), + org_id, headers.user.uuid.clone(), headers.device.atype, &headers.ip.ip, @@ -1497,7 +1494,7 @@ async fn _delete_user( #[post("/organizations/<org_id>/users/public-keys", data = "<data>")] async fn bulk_public_keys( - org_id: String, + org_id: &str, data: JsonUpcase<OrgBulkIds>, _headers: AdminHeaders, mut conn: DbConn, @@ -1509,7 +1506,7 @@ async fn bulk_public_keys( // If the user does not exists, just ignore it, and do not return any information regarding that UserOrg UUID. // The web-vault will then ignore that user for the folowing steps. for user_org_id in data.Ids { - match UserOrganization::find_by_uuid_and_org(&user_org_id, &org_id, &mut conn).await { + match UserOrganization::find_by_uuid_and_org(&user_org_id, org_id, &mut conn).await { Some(user_org) => match User::find_by_uuid(&user_org.user_uuid, &mut conn).await { Some(user) => bulk_response.push(json!( { @@ -1611,8 +1608,8 @@ async fn post_org_import( } #[get("/organizations/<org_id>/policies")] -async fn list_policies(org_id: String, _headers: AdminHeaders, mut conn: DbConn) -> Json<Value> { - let policies = OrgPolicy::find_by_org(&org_id, &mut conn).await; +async fn list_policies(org_id: &str, _headers: AdminHeaders, mut conn: DbConn) -> Json<Value> { + let policies = OrgPolicy::find_by_org(org_id, &mut conn).await; let policies_json: Vec<Value> = policies.iter().map(OrgPolicy::to_json).collect(); Json(json!({ @@ -1623,8 +1620,8 @@ async fn list_policies(org_id: String, _headers: AdminHeaders, mut conn: DbConn) } #[get("/organizations/<org_id>/policies/token?<token>")] -async fn list_policies_token(org_id: String, token: String, mut conn: DbConn) -> JsonResult { - let invite = crate::auth::decode_invite(&token)?; +async fn list_policies_token(org_id: &str, token: &str, mut conn: DbConn) -> JsonResult { + let invite = crate::auth::decode_invite(token)?; let invite_org_id = match invite.org_id { Some(invite_org_id) => invite_org_id, @@ -1636,7 +1633,7 @@ async fn list_policies_token(org_id: String, token: String, mut conn: DbConn) -> } // TODO: We receive the invite token as ?token=<>, validate it contains the org id - let policies = OrgPolicy::find_by_org(&org_id, &mut conn).await; + let policies = OrgPolicy::find_by_org(org_id, &mut conn).await; let policies_json: Vec<Value> = policies.iter().map(OrgPolicy::to_json).collect(); Ok(Json(json!({ @@ -1647,15 +1644,15 @@ async fn list_policies_token(org_id: String, token: String, mut conn: DbConn) -> } #[get("/organizations/<org_id>/policies/<pol_type>")] -async fn get_policy(org_id: String, pol_type: i32, _headers: AdminHeaders, mut conn: DbConn) -> JsonResult { +async fn get_policy(org_id: &str, pol_type: i32, _headers: AdminHeaders, mut conn: DbConn) -> JsonResult { let pol_type_enum = match OrgPolicyType::from_i32(pol_type) { Some(pt) => pt, None => err!("Invalid or unsupported policy type"), }; - let policy = match OrgPolicy::find_by_org_and_type(&org_id, pol_type_enum, &mut conn).await { + let policy = match OrgPolicy::find_by_org_and_type(org_id, pol_type_enum, &mut conn).await { Some(p) => p, - None => OrgPolicy::new(org_id, pol_type_enum, "{}".to_string()), + None => OrgPolicy::new(String::from(org_id), pol_type_enum, "{}".to_string()), }; Ok(Json(policy.to_json())) @@ -1671,7 +1668,7 @@ struct PolicyData { #[put("/organizations/<org_id>/policies/<pol_type>", data = "<data>")] async fn put_policy( - org_id: String, + org_id: &str, pol_type: i32, data: Json<PolicyData>, headers: AdminHeaders, @@ -1686,7 +1683,7 @@ async fn put_policy( // When enabling the TwoFactorAuthentication policy, remove this org's members that do have 2FA if pol_type_enum == OrgPolicyType::TwoFactorAuthentication && data.enabled { - for member in UserOrganization::find_by_org(&org_id, &mut conn).await.into_iter() { + for member in UserOrganization::find_by_org(org_id, &mut conn).await.into_iter() { let user_twofactor_disabled = TwoFactor::find_by_user(&member.user_uuid, &mut conn).await.is_empty(); // Policy only applies to non-Owner/non-Admin members who have accepted joining the org @@ -1705,7 +1702,7 @@ async fn put_policy( log_event( EventType::OrganizationUserRemoved as i32, &member.uuid, - org_id.clone(), + org_id, headers.user.uuid.clone(), headers.device.atype, &headers.ip.ip, @@ -1720,7 +1717,7 @@ async fn put_policy( // When enabling the SingleOrg policy, remove this org's members that are members of other orgs if pol_type_enum == OrgPolicyType::SingleOrg && data.enabled { - for member in UserOrganization::find_by_org(&org_id, &mut conn).await.into_iter() { + for member in UserOrganization::find_by_org(org_id, &mut conn).await.into_iter() { // Policy only applies to non-Owner/non-Admin members who have accepted joining the org // Exclude invited and revoked users when checking for this policy. // Those users will not be allowed to accept or be activated because of the policy checks done there. @@ -1739,7 +1736,7 @@ async fn put_policy( log_event( EventType::OrganizationUserRemoved as i32, &member.uuid, - org_id.clone(), + org_id, headers.user.uuid.clone(), headers.device.atype, &headers.ip.ip, @@ -1752,9 +1749,9 @@ async fn put_policy( } } - let mut policy = match OrgPolicy::find_by_org_and_type(&org_id, pol_type_enum, &mut conn).await { + let mut policy = match OrgPolicy::find_by_org_and_type(org_id, pol_type_enum, &mut conn).await { Some(p) => p, - None => OrgPolicy::new(org_id.clone(), pol_type_enum, "{}".to_string()), + None => OrgPolicy::new(String::from(org_id), pol_type_enum, "{}".to_string()), }; policy.enabled = data.enabled; @@ -1777,7 +1774,7 @@ async fn put_policy( #[allow(unused_variables)] #[get("/organizations/<org_id>/tax")] -fn get_organization_tax(org_id: String, _headers: Headers) -> Json<Value> { +fn get_organization_tax(org_id: &str, _headers: Headers) -> Json<Value> { // Prevent a 404 error, which also causes Javascript errors. // Upstream sends "Only allowed when not self hosted." As an error message. // If we do the same it will also output this to the log, which is overkill. @@ -1843,7 +1840,7 @@ struct OrgImportData { } #[post("/organizations/<org_id>/import", data = "<data>")] -async fn import(org_id: String, data: JsonUpcase<OrgImportData>, headers: Headers, mut conn: DbConn) -> EmptyResult { +async fn import(org_id: &str, data: JsonUpcase<OrgImportData>, headers: Headers, mut conn: DbConn) -> EmptyResult { let data = data.into_inner().data; // TODO: Currently we aren't storing the externalId's anywhere, so we also don't have a way @@ -1852,7 +1849,7 @@ async fn import(org_id: String, data: JsonUpcase<OrgImportData>, headers: Header // as opposed to upstream which only removes auto-imported users. // User needs to be admin or owner to use the Directry Connector - match UserOrganization::find_by_user_and_org(&headers.user.uuid, &org_id, &mut conn).await { + match UserOrganization::find_by_user_and_org(&headers.user.uuid, org_id, &mut conn).await { Some(user_org) if user_org.atype >= UserOrgType::Admin => { /* Okay, nothing to do */ } Some(_) => err!("User has insufficient permissions to use Directory Connector"), None => err!("User not part of organization"), @@ -1861,12 +1858,11 @@ async fn import(org_id: String, data: JsonUpcase<OrgImportData>, headers: Header for user_data in &data.Users { if user_data.Deleted { // If user is marked for deletion and it exists, delete it - if let Some(user_org) = UserOrganization::find_by_email_and_org(&user_data.Email, &org_id, &mut conn).await - { + if let Some(user_org) = UserOrganization::find_by_email_and_org(&user_data.Email, org_id, &mut conn).await { log_event( EventType::OrganizationUserRemoved as i32, &user_org.uuid, - org_id.clone(), + org_id, headers.user.uuid.clone(), headers.device.atype, &headers.ip.ip, @@ -1878,7 +1874,7 @@ async fn import(org_id: String, data: JsonUpcase<OrgImportData>, headers: Header } // If user is not part of the organization, but it exists - } else if UserOrganization::find_by_email_and_org(&user_data.Email, &org_id, &mut conn).await.is_none() { + } else if UserOrganization::find_by_email_and_org(&user_data.Email, org_id, &mut conn).await.is_none() { if let Some(user) = User::find_by_mail(&user_data.Email, &mut conn).await { let user_org_status = if CONFIG.mail_enabled() { UserOrgStatus::Invited as i32 @@ -1886,7 +1882,7 @@ async fn import(org_id: String, data: JsonUpcase<OrgImportData>, headers: Header UserOrgStatus::Accepted as i32 // Automatically mark user as accepted if no email invites }; - let mut new_org_user = UserOrganization::new(user.uuid.clone(), org_id.clone()); + let mut new_org_user = UserOrganization::new(user.uuid.clone(), String::from(org_id)); new_org_user.access_all = false; new_org_user.atype = UserOrgType::User as i32; new_org_user.status = user_org_status; @@ -1896,7 +1892,7 @@ async fn import(org_id: String, data: JsonUpcase<OrgImportData>, headers: Header log_event( EventType::OrganizationUserInvited as i32, &new_org_user.uuid, - org_id.clone(), + org_id, headers.user.uuid.clone(), headers.device.atype, &headers.ip.ip, @@ -1905,7 +1901,7 @@ async fn import(org_id: String, data: JsonUpcase<OrgImportData>, headers: Header .await; if CONFIG.mail_enabled() { - let org_name = match Organization::find_by_uuid(&org_id, &mut conn).await { + let org_name = match Organization::find_by_uuid(org_id, &mut conn).await { Some(org) => org.name, None => err!("Error looking up organization"), }; @@ -1913,7 +1909,7 @@ async fn import(org_id: String, data: JsonUpcase<OrgImportData>, headers: Header mail::send_invite( &user_data.Email, &user.uuid, - Some(org_id.clone()), + Some(String::from(org_id)), Some(new_org_user.uuid), &org_name, Some(headers.user.email.clone()), @@ -1926,13 +1922,13 @@ async fn import(org_id: String, data: JsonUpcase<OrgImportData>, headers: Header // If this flag is enabled, any user that isn't provided in the Users list will be removed (by default they will be kept unless they have Deleted == true) if data.OverwriteExisting { - for user_org in UserOrganization::find_by_org_and_type(&org_id, UserOrgType::User, &mut conn).await { + for user_org in UserOrganization::find_by_org_and_type(org_id, UserOrgType::User, &mut conn).await { if let Some(user_email) = User::find_by_uuid(&user_org.user_uuid, &mut conn).await.map(|u| u.email) { if !data.Users.iter().any(|u| u.Email == user_email) { log_event( EventType::OrganizationUserRemoved as i32, &user_org.uuid, - org_id.clone(), + org_id, headers.user.uuid.clone(), headers.device.atype, &headers.ip.ip, @@ -1952,18 +1948,18 @@ async fn import(org_id: String, data: JsonUpcase<OrgImportData>, headers: Header // Pre web-vault v2022.9.x endpoint #[put("/organizations/<org_id>/users/<org_user_id>/deactivate")] async fn deactivate_organization_user( - org_id: String, - org_user_id: String, + org_id: &str, + org_user_id: &str, headers: AdminHeaders, mut conn: DbConn, ) -> EmptyResult { - _revoke_organization_user(&org_id, &org_user_id, &headers, &mut conn).await + _revoke_organization_user(org_id, org_user_id, &headers, &mut conn).await } // Pre web-vault v2022.9.x endpoint #[put("/organizations/<org_id>/users/deactivate", data = "<data>")] async fn bulk_deactivate_organization_user( - org_id: String, + org_id: &str, data: JsonUpcase<Value>, headers: AdminHeaders, conn: DbConn, @@ -1973,17 +1969,17 @@ async fn bulk_deactivate_organization_user( #[put("/organizations/<org_id>/users/<org_user_id>/revoke")] async fn revoke_organization_user( - org_id: String, - org_user_id: String, + org_id: &str, + org_user_id: &str, headers: AdminHeaders, mut conn: DbConn, ) -> EmptyResult { - _revoke_organization_user(&org_id, &org_user_id, &headers, &mut conn).await + _revoke_organization_user(org_id, org_user_id, &headers, &mut conn).await } #[put("/organizations/<org_id>/users/revoke", data = "<data>")] async fn bulk_revoke_organization_user( - org_id: String, + org_id: &str, data: JsonUpcase<Value>, headers: AdminHeaders, mut conn: DbConn, @@ -1995,7 +1991,7 @@ async fn bulk_revoke_organization_user( Some(org_users) => { for org_user_id in org_users { let org_user_id = org_user_id.as_str().unwrap_or_default(); - let err_msg = match _revoke_organization_user(&org_id, org_user_id, &headers, &mut conn).await { + let err_msg = match _revoke_organization_user(org_id, org_user_id, &headers, &mut conn).await { Ok(_) => String::new(), Err(e) => format!("{e:?}"), }; @@ -2045,7 +2041,7 @@ async fn _revoke_organization_user( log_event( EventType::OrganizationUserRevoked as i32, &user_org.uuid, - org_id.to_string(), + org_id, headers.user.uuid.clone(), headers.device.atype, &headers.ip.ip, @@ -2062,18 +2058,18 @@ async fn _revoke_organization_user( // Pre web-vault v2022.9.x endpoint #[put("/organizations/<org_id>/users/<org_user_id>/activate")] async fn activate_organization_user( - org_id: String, - org_user_id: String, + org_id: &str, + org_user_id: &str, headers: AdminHeaders, mut conn: DbConn, ) -> EmptyResult { - _restore_organization_user(&org_id, &org_user_id, &headers, &mut conn).await + _restore_organization_user(org_id, org_user_id, &headers, &mut conn).await } // Pre web-vault v2022.9.x endpoint #[put("/organizations/<org_id>/users/activate", data = "<data>")] async fn bulk_activate_organization_user( - org_id: String, + org_id: &str, data: JsonUpcase<Value>, headers: AdminHeaders, conn: DbConn, @@ -2083,17 +2079,17 @@ async fn bulk_activate_organization_user( #[put("/organizations/<org_id>/users/<org_user_id>/restore")] async fn restore_organization_user( - org_id: String, - org_user_id: String, + org_id: &str, + org_user_id: &str, headers: AdminHeaders, mut conn: DbConn, ) -> EmptyResult { - _restore_organization_user(&org_id, &org_user_id, &headers, &mut conn).await + _restore_organization_user(org_id, org_user_id, &headers, &mut conn).await } #[put("/organizations/<org_id>/users/restore", data = "<data>")] async fn bulk_restore_organization_user( - org_id: String, + org_id: &str, data: JsonUpcase<Value>, headers: AdminHeaders, mut conn: DbConn, @@ -2105,7 +2101,7 @@ async fn bulk_restore_organization_user( Some(org_users) => { for org_user_id in org_users { let org_user_id = org_user_id.as_str().unwrap_or_default(); - let err_msg = match _restore_organization_user(&org_id, org_user_id, &headers, &mut conn).await { + let err_msg = match _restore_organization_user(org_id, org_user_id, &headers, &mut conn).await { Ok(_) => String::new(), Err(e) => format!("{e:?}"), }; @@ -2164,7 +2160,7 @@ async fn _restore_organization_user( log_event( EventType::OrganizationUserRestored as i32, &user_org.uuid, - org_id.to_string(), + org_id, headers.user.uuid.clone(), headers.device.atype, &headers.ip.ip, @@ -2179,10 +2175,10 @@ async fn _restore_organization_user( } #[get("/organizations/<org_id>/groups")] -async fn get_groups(org_id: String, _headers: ManagerHeadersLoose, mut conn: DbConn) -> JsonResult { +async fn get_groups(org_id: &str, _headers: ManagerHeadersLoose, mut conn: DbConn) -> JsonResult { let groups: Vec<Value> = if CONFIG.org_groups_enabled() { // Group::find_by_organization(&org_id, &mut conn).await.iter().map(Group::to_json).collect::<Value>() - let groups = Group::find_by_organization(&org_id, &mut conn).await; + let groups = Group::find_by_organization(org_id, &mut conn).await; let mut groups_json = Vec::with_capacity(groups.len()); for g in groups { groups_json.push(g.to_json_details(&mut conn).await) @@ -2274,8 +2270,8 @@ impl SelectionReadOnly { #[post("/organizations/<org_id>/groups/<group_id>", data = "<data>")] async fn post_group( - org_id: String, - group_id: String, + org_id: &str, + group_id: &str, data: JsonUpcase<GroupRequest>, headers: AdminHeaders, conn: DbConn, @@ -2285,7 +2281,7 @@ async fn post_group( #[post("/organizations/<org_id>/groups", data = "<data>")] async fn post_groups( - org_id: String, + org_id: &str, headers: AdminHeaders, data: JsonUpcase<GroupRequest>, mut conn: DbConn, @@ -2295,12 +2291,12 @@ async fn post_groups( } let group_request = data.into_inner().data; - let group = group_request.to_group(&org_id)?; + let group = group_request.to_group(org_id)?; log_event( EventType::GroupCreated as i32, &group.uuid, - org_id.clone(), + org_id, headers.user.uuid.clone(), headers.device.atype, &headers.ip.ip, @@ -2308,13 +2304,13 @@ async fn post_groups( ) .await; - add_update_group(group, group_request.Collections, group_request.Users, &org_id, &headers, &mut conn).await + add_update_group(group, group_request.Collections, group_request.Users, org_id, &headers, &mut conn).await } #[put("/organizations/<org_id>/groups/<group_id>", data = "<data>")] async fn put_group( - org_id: String, - group_id: String, + org_id: &str, + group_id: &str, data: JsonUpcase<GroupRequest>, headers: AdminHeaders, mut conn: DbConn, @@ -2323,7 +2319,7 @@ async fn put_group( err!("Group support is disabled"); } - let group = match Group::find_by_uuid(&group_id, &mut conn).await { + let group = match Group::find_by_uuid(group_id, &mut conn).await { Some(group) => group, None => err!("Group not found"), }; @@ -2331,13 +2327,13 @@ async fn put_group( let group_request = data.into_inner().data; let updated_group = group_request.update_group(group)?; - CollectionGroup::delete_all_by_group(&group_id, &mut conn).await?; - GroupUser::delete_all_by_group(&group_id, &mut conn).await?; + CollectionGroup::delete_all_by_group(group_id, &mut conn).await?; + GroupUser::delete_all_by_group(group_id, &mut conn).await?; log_event( EventType::GroupUpdated as i32, &updated_group.uuid, - org_id.clone(), + org_id, headers.user.uuid.clone(), headers.device.atype, &headers.ip.ip, @@ -2345,7 +2341,7 @@ async fn put_group( ) .await; - add_update_group(updated_group, group_request.Collections, group_request.Users, &org_id, &headers, &mut conn).await + add_update_group(updated_group, group_request.Collections, group_request.Users, org_id, &headers, &mut conn).await } async fn add_update_group( @@ -2370,7 +2366,7 @@ async fn add_update_group( log_event( EventType::OrganizationUserUpdatedGroups as i32, &assigned_user_id, - String::from(org_id), + org_id, headers.user.uuid.clone(), headers.device.atype, &headers.ip.ip, @@ -2389,12 +2385,12 @@ async fn add_update_group( } #[get("/organizations/<_org_id>/groups/<group_id>/details")] -async fn get_group_details(_org_id: String, group_id: String, _headers: AdminHeaders, mut conn: DbConn) -> JsonResult { +async fn get_group_details(_org_id: &str, group_id: &str, _headers: AdminHeaders, mut conn: DbConn) -> JsonResult { if !CONFIG.org_groups_enabled() { err!("Group support is disabled"); } - let group = match Group::find_by_uuid(&group_id, &mut conn).await { + let group = match Group::find_by_uuid(group_id, &mut conn).await { Some(group) => group, _ => err!("Group could not be found!"), }; @@ -2403,21 +2399,21 @@ async fn get_group_details(_org_id: String, group_id: String, _headers: AdminHea } #[post("/organizations/<org_id>/groups/<group_id>/delete")] -async fn post_delete_group(org_id: String, group_id: String, headers: AdminHeaders, mut conn: DbConn) -> EmptyResult { +async fn post_delete_group(org_id: &str, group_id: &str, headers: AdminHeaders, mut conn: DbConn) -> EmptyResult { _delete_group(org_id, group_id, &headers, &mut conn).await } #[delete("/organizations/<org_id>/groups/<group_id>")] -async fn delete_group(org_id: String, group_id: String, headers: AdminHeaders, mut conn: DbConn) -> EmptyResult { +async fn delete_group(org_id: &str, group_id: &str, headers: AdminHeaders, mut conn: DbConn) -> EmptyResult { _delete_group(org_id, group_id, &headers, &mut conn).await } -async fn _delete_group(org_id: String, group_id: String, headers: &AdminHeaders, conn: &mut DbConn) -> EmptyResult { +async fn _delete_group(org_id: &str, group_id: &str, headers: &AdminHeaders, conn: &mut DbConn) -> EmptyResult { if !CONFIG.org_groups_enabled() { err!("Group support is disabled"); } - let group = match Group::find_by_uuid(&group_id, conn).await { + let group = match Group::find_by_uuid(group_id, conn).await { Some(group) => group, _ => err!("Group not found"), }; @@ -2438,7 +2434,7 @@ async fn _delete_group(org_id: String, group_id: String, headers: &AdminHeaders, #[delete("/organizations/<org_id>/groups", data = "<data>")] async fn bulk_delete_groups( - org_id: String, + org_id: &str, data: JsonUpcase<OrgBulkIds>, headers: AdminHeaders, mut conn: DbConn, @@ -2450,18 +2446,18 @@ async fn bulk_delete_groups( let data: OrgBulkIds = data.into_inner().data; for group_id in data.Ids { - _delete_group(org_id.clone(), group_id, &headers, &mut conn).await? + _delete_group(org_id, &group_id, &headers, &mut conn).await? } Ok(()) } #[get("/organizations/<_org_id>/groups/<group_id>")] -async fn get_group(_org_id: String, group_id: String, _headers: AdminHeaders, mut conn: DbConn) -> JsonResult { +async fn get_group(_org_id: &str, group_id: &str, _headers: AdminHeaders, mut conn: DbConn) -> JsonResult { if !CONFIG.org_groups_enabled() { err!("Group support is disabled"); } - let group = match Group::find_by_uuid(&group_id, &mut conn).await { + let group = match Group::find_by_uuid(group_id, &mut conn).await { Some(group) => group, _ => err!("Group not found"), }; @@ -2470,17 +2466,17 @@ async fn get_group(_org_id: String, group_id: String, _headers: AdminHeaders, mu } #[get("/organizations/<_org_id>/groups/<group_id>/users")] -async fn get_group_users(_org_id: String, group_id: String, _headers: AdminHeaders, mut conn: DbConn) -> JsonResult { +async fn get_group_users(_org_id: &str, group_id: &str, _headers: AdminHeaders, mut conn: DbConn) -> JsonResult { if !CONFIG.org_groups_enabled() { err!("Group support is disabled"); } - match Group::find_by_uuid(&group_id, &mut conn).await { + match Group::find_by_uuid(group_id, &mut conn).await { Some(_) => { /* Do nothing */ } _ => err!("Group could not be found!"), }; - let group_users: Vec<String> = GroupUser::find_by_group(&group_id, &mut conn) + let group_users: Vec<String> = GroupUser::find_by_group(group_id, &mut conn) .await .iter() .map(|entry| entry.users_organizations_uuid.clone()) @@ -2491,8 +2487,8 @@ async fn get_group_users(_org_id: String, group_id: String, _headers: AdminHeade #[put("/organizations/<org_id>/groups/<group_id>/users", data = "<data>")] async fn put_group_users( - org_id: String, - group_id: String, + org_id: &str, + group_id: &str, headers: AdminHeaders, data: JsonVec<String>, mut conn: DbConn, @@ -2501,22 +2497,22 @@ async fn put_group_users( err!("Group support is disabled"); } - match Group::find_by_uuid(&group_id, &mut conn).await { + match Group::find_by_uuid(group_id, &mut conn).await { Some(_) => { /* Do nothing */ } _ => err!("Group could not be found!"), }; - GroupUser::delete_all_by_group(&group_id, &mut conn).await?; + GroupUser::delete_all_by_group(group_id, &mut conn).await?; let assigned_user_ids = data.into_inner(); for assigned_user_id in assigned_user_ids { - let mut user_entry = GroupUser::new(group_id.clone(), assigned_user_id.clone()); + let mut user_entry = GroupUser::new(String::from(group_id), assigned_user_id.clone()); user_entry.save(&mut conn).await?; log_event( EventType::OrganizationUserUpdatedGroups as i32, &assigned_user_id, - org_id.clone(), + org_id, headers.user.uuid.clone(), headers.device.atype, &headers.ip.ip, @@ -2529,18 +2525,18 @@ async fn put_group_users( } #[get("/organizations/<_org_id>/users/<user_id>/groups")] -async fn get_user_groups(_org_id: String, user_id: String, _headers: AdminHeaders, mut conn: DbConn) -> JsonResult { +async fn get_user_groups(_org_id: &str, user_id: &str, _headers: AdminHeaders, mut conn: DbConn) -> JsonResult { if !CONFIG.org_groups_enabled() { err!("Group support is disabled"); } - match UserOrganization::find_by_uuid(&user_id, &mut conn).await { + match UserOrganization::find_by_uuid(user_id, &mut conn).await { Some(_) => { /* Do nothing */ } _ => err!("User could not be found!"), }; let user_groups: Vec<String> = - GroupUser::find_by_user(&user_id, &mut conn).await.iter().map(|entry| entry.groups_uuid.clone()).collect(); + GroupUser::find_by_user(user_id, &mut conn).await.iter().map(|entry| entry.groups_uuid.clone()).collect(); Ok(Json(json!(user_groups))) } @@ -2553,8 +2549,8 @@ struct OrganizationUserUpdateGroupsRequest { #[post("/organizations/<org_id>/users/<org_user_id>/groups", data = "<data>")] async fn post_user_groups( - org_id: String, - org_user_id: String, + org_id: &str, + org_user_id: &str, data: JsonUpcase<OrganizationUserUpdateGroupsRequest>, headers: AdminHeaders, conn: DbConn, @@ -2564,8 +2560,8 @@ async fn post_user_groups( #[put("/organizations/<org_id>/users/<org_user_id>/groups", data = "<data>")] async fn put_user_groups( - org_id: String, - org_user_id: String, + org_id: &str, + org_user_id: &str, data: JsonUpcase<OrganizationUserUpdateGroupsRequest>, headers: AdminHeaders, mut conn: DbConn, @@ -2574,22 +2570,22 @@ async fn put_user_groups( err!("Group support is disabled"); } - match UserOrganization::find_by_uuid(&org_user_id, &mut conn).await { + match UserOrganization::find_by_uuid(org_user_id, &mut conn).await { Some(_) => { /* Do nothing */ } _ => err!("User could not be found!"), }; - GroupUser::delete_all_by_user(&org_user_id, &mut conn).await?; + GroupUser::delete_all_by_user(org_user_id, &mut conn).await?; let assigned_group_ids = data.into_inner().data; for assigned_group_id in assigned_group_ids.GroupIds { - let mut group_user = GroupUser::new(assigned_group_id.clone(), org_user_id.clone()); + let mut group_user = GroupUser::new(assigned_group_id.clone(), String::from(org_user_id)); group_user.save(&mut conn).await?; } log_event( EventType::OrganizationUserUpdatedGroups as i32, - &org_user_id, + org_user_id, org_id, headers.user.uuid.clone(), headers.device.atype, @@ -2603,9 +2599,9 @@ async fn put_user_groups( #[post("/organizations/<org_id>/groups/<group_id>/delete-user/<org_user_id>")] async fn post_delete_group_user( - org_id: String, - group_id: String, - org_user_id: String, + org_id: &str, + group_id: &str, + org_user_id: &str, headers: AdminHeaders, conn: DbConn, ) -> EmptyResult { @@ -2614,9 +2610,9 @@ async fn post_delete_group_user( #[delete("/organizations/<org_id>/groups/<group_id>/users/<org_user_id>")] async fn delete_group_user( - org_id: String, - group_id: String, - org_user_id: String, + org_id: &str, + group_id: &str, + org_user_id: &str, headers: AdminHeaders, mut conn: DbConn, ) -> EmptyResult { @@ -2624,19 +2620,19 @@ async fn delete_group_user( err!("Group support is disabled"); } - match UserOrganization::find_by_uuid(&org_user_id, &mut conn).await { + match UserOrganization::find_by_uuid(org_user_id, &mut conn).await { Some(_) => { /* Do nothing */ } _ => err!("User could not be found!"), }; - match Group::find_by_uuid(&group_id, &mut conn).await { + match Group::find_by_uuid(group_id, &mut conn).await { Some(_) => { /* Do nothing */ } _ => err!("Group could not be found!"), }; log_event( EventType::OrganizationUserUpdatedGroups as i32, - &org_user_id, + org_user_id, org_id, headers.user.uuid.clone(), headers.device.atype, @@ -2645,7 +2641,7 @@ async fn delete_group_user( ) .await; - GroupUser::delete_by_group_id_and_user_id(&group_id, &org_user_id, &mut conn).await + GroupUser::delete_by_group_id_and_user_id(group_id, org_user_id, &mut conn).await } #[derive(Deserialize)] @@ -2662,8 +2658,8 @@ struct OrganizationUserResetPasswordRequest { } #[get("/organizations/<org_id>/keys")] -async fn get_organization_keys(org_id: String, mut conn: DbConn) -> JsonResult { - let org = match Organization::find_by_uuid(&org_id, &mut conn).await { +async fn get_organization_keys(org_id: &str, mut conn: DbConn) -> JsonResult { + let org = match Organization::find_by_uuid(org_id, &mut conn).await { Some(organization) => organization, None => err!("Organization not found"), }; @@ -2677,19 +2673,19 @@ async fn get_organization_keys(org_id: String, mut conn: DbConn) -> JsonResult { #[put("/organizations/<org_id>/users/<org_user_id>/reset-password", data = "<data>")] async fn put_reset_password( - org_id: String, - org_user_id: String, + org_id: &str, + org_user_id: &str, headers: AdminHeaders, data: JsonUpcase<OrganizationUserResetPasswordRequest>, mut conn: DbConn, nt: Notify<'_>, ) -> EmptyResult { - let org = match Organization::find_by_uuid(&org_id, &mut conn).await { + let org = match Organization::find_by_uuid(org_id, &mut conn).await { Some(org) => org, None => err!("Required organization not found"), }; - let org_user = match UserOrganization::find_by_uuid_and_org(&org_user_id, &org.uuid, &mut conn).await { + let org_user = match UserOrganization::find_by_uuid_and_org(org_user_id, &org.uuid, &mut conn).await { Some(user) => user, None => err!("User to reset isn't member of required organization"), }; @@ -2699,7 +2695,7 @@ async fn put_reset_password( None => err!("User not found"), }; - check_reset_password_applicable_and_permissions(&org_id, &org_user_id, &headers, &mut conn).await?; + check_reset_password_applicable_and_permissions(org_id, org_user_id, &headers, &mut conn).await?; if org_user.reset_password_key.is_none() { err!("Password reset not or not correctly enrolled"); @@ -2724,8 +2720,8 @@ async fn put_reset_password( log_event( EventType::OrganizationUserAdminResetPassword as i32, - &org_user_id, - org.uuid.clone(), + org_user_id, + org_id, headers.user.uuid.clone(), headers.device.atype, &headers.ip.ip, @@ -2738,17 +2734,17 @@ async fn put_reset_password( #[get("/organizations/<org_id>/users/<org_user_id>/reset-password-details")] async fn get_reset_password_details( - org_id: String, - org_user_id: String, + org_id: &str, + org_user_id: &str, headers: AdminHeaders, mut conn: DbConn, ) -> JsonResult { - let org = match Organization::find_by_uuid(&org_id, &mut conn).await { + let org = match Organization::find_by_uuid(org_id, &mut conn).await { Some(org) => org, None => err!("Required organization not found"), }; - let org_user = match UserOrganization::find_by_uuid_and_org(&org_user_id, &org_id, &mut conn).await { + let org_user = match UserOrganization::find_by_uuid_and_org(org_user_id, org_id, &mut conn).await { Some(user) => user, None => err!("User to reset isn't member of required organization"), }; @@ -2758,7 +2754,7 @@ async fn get_reset_password_details( None => err!("User not found"), }; - check_reset_password_applicable_and_permissions(&org_id, &org_user_id, &headers, &mut conn).await?; + check_reset_password_applicable_and_permissions(org_id, org_user_id, &headers, &mut conn).await?; // https://github.com/bitwarden/server/blob/3b50ccb9f804efaacdc46bed5b60e5b28eddefcf/src/Api/Models/Response/Organizations/OrganizationUserResponseModel.cs#L111 Ok(Json(json!({ @@ -2813,23 +2809,22 @@ async fn check_reset_password_applicable(org_id: &str, conn: &mut DbConn) -> Emp #[put("/organizations/<org_id>/users/<org_user_id>/reset-password-enrollment", data = "<data>")] async fn put_reset_password_enrollment( - org_id: String, - org_user_id: String, + org_id: &str, + org_user_id: &str, headers: Headers, data: JsonUpcase<OrganizationUserResetPasswordEnrollmentRequest>, mut conn: DbConn, ) -> EmptyResult { - let mut org_user = match UserOrganization::find_by_user_and_org(&headers.user.uuid, &org_id, &mut conn).await { + let mut org_user = match UserOrganization::find_by_user_and_org(&headers.user.uuid, org_id, &mut conn).await { Some(u) => u, None => err!("User to enroll isn't member of required organization"), }; - check_reset_password_applicable(&org_id, &mut conn).await?; + check_reset_password_applicable(org_id, &mut conn).await?; let reset_request = data.into_inner().data; - if reset_request.ResetPasswordKey.is_none() - && OrgPolicy::org_is_reset_password_auto_enroll(&org_id, &mut conn).await + if reset_request.ResetPasswordKey.is_none() && OrgPolicy::org_is_reset_password_auto_enroll(org_id, &mut conn).await { err!("Reset password can't be withdrawed due to an enterprise policy"); } @@ -2843,7 +2838,7 @@ async fn put_reset_password_enrollment( EventType::OrganizationUserResetPasswordWithdraw as i32 }; - log_event(log_id, &org_user_id, org_id, headers.user.uuid.clone(), headers.device.atype, &headers.ip.ip, &mut conn) + log_event(log_id, org_user_id, org_id, headers.user.uuid.clone(), headers.device.atype, &headers.ip.ip, &mut conn) .await; Ok(()) @@ -2857,7 +2852,7 @@ async fn put_reset_password_enrollment( // We need to convert all keys so they have the first character to be a lowercase. // Else the export will be just an empty JSON file. #[get("/organizations/<org_id>/export")] -async fn get_org_export(org_id: String, headers: AdminHeaders, mut conn: DbConn) -> Json<Value> { +async fn get_org_export(org_id: &str, headers: AdminHeaders, mut conn: DbConn) -> Json<Value> { use semver::{Version, VersionReq}; // Since version v2023.1.0 the format of the export is different. @@ -2878,12 +2873,12 @@ async fn get_org_export(org_id: String, headers: AdminHeaders, mut conn: DbConn) // Backwards compatible pre v2023.1.0 response Json(json!({ "collections": { - "data": convert_json_key_lcase_first(_get_org_collections(&org_id, &mut conn).await), + "data": convert_json_key_lcase_first(_get_org_collections(org_id, &mut conn).await), "object": "list", "continuationToken": null, }, "ciphers": { - "data": convert_json_key_lcase_first(_get_org_details(&org_id, &headers.host, &headers.user.uuid, &mut conn).await), + "data": convert_json_key_lcase_first(_get_org_details(org_id, &headers.host, &headers.user.uuid, &mut conn).await), "object": "list", "continuationToken": null, } @@ -2891,8 +2886,8 @@ async fn get_org_export(org_id: String, headers: AdminHeaders, mut conn: DbConn) } else { // v2023.1.0 and newer response Json(json!({ - "collections": convert_json_key_lcase_first(_get_org_collections(&org_id, &mut conn).await), - "ciphers": convert_json_key_lcase_first(_get_org_details(&org_id, &headers.host, &headers.user.uuid, &mut conn).await), + "collections": convert_json_key_lcase_first(_get_org_collections(org_id, &mut conn).await), + "ciphers": convert_json_key_lcase_first(_get_org_details(org_id, &headers.host, &headers.user.uuid, &mut conn).await), })) } } diff --git a/src/api/core/sends.rs b/src/api/core/sends.rs @@ -154,8 +154,8 @@ async fn get_sends(headers: Headers, mut conn: DbConn) -> Json<Value> { } #[get("/sends/<uuid>")] -async fn get_send(uuid: String, headers: Headers, mut conn: DbConn) -> JsonResult { - let send = match Send::find_by_uuid(&uuid, &mut conn).await { +async fn get_send(uuid: &str, headers: Headers, mut conn: DbConn) -> JsonResult { + let send = match Send::find_by_uuid(uuid, &mut conn).await { Some(send) => send, None => err!("Send not found"), }; @@ -315,8 +315,8 @@ async fn post_send_file_v2(data: JsonUpcase<SendData>, headers: Headers, mut con // https://github.com/bitwarden/server/blob/d0c793c95181dfb1b447eb450f85ba0bfd7ef643/src/Api/Controllers/SendsController.cs#L243 #[post("/sends/<send_uuid>/file/<file_id>", format = "multipart/form-data", data = "<data>")] async fn post_send_file_v2_data( - send_uuid: String, - file_id: String, + send_uuid: &str, + file_id: &str, data: Form<UploadDataV2<'_>>, headers: Headers, mut conn: DbConn, @@ -326,9 +326,9 @@ async fn post_send_file_v2_data( let mut data = data.into_inner(); - if let Some(send) = Send::find_by_uuid(&send_uuid, &mut conn).await { - let folder_path = tokio::fs::canonicalize(&CONFIG.sends_folder()).await?.join(&send_uuid); - let file_path = folder_path.join(&file_id); + if let Some(send) = Send::find_by_uuid(send_uuid, &mut conn).await { + let folder_path = tokio::fs::canonicalize(&CONFIG.sends_folder()).await?.join(send_uuid); + let file_path = folder_path.join(file_id); tokio::fs::create_dir_all(&folder_path).await?; if let Err(_err) = data.data.persist_to(&file_path).await { @@ -351,13 +351,13 @@ pub struct SendAccessData { #[post("/sends/access/<access_id>", data = "<data>")] async fn post_access( - access_id: String, + access_id: &str, data: JsonUpcase<SendAccessData>, mut conn: DbConn, ip: ClientIp, nt: Notify<'_>, ) -> JsonResult { - let mut send = match Send::find_by_access_id(&access_id, &mut conn).await { + let mut send = match Send::find_by_access_id(access_id, &mut conn).await { Some(s) => s, None => err_code!(SEND_INACCESSIBLE_MSG, 404), }; @@ -404,14 +404,14 @@ async fn post_access( #[post("/sends/<send_id>/access/file/<file_id>", data = "<data>")] async fn post_access_file( - send_id: String, - file_id: String, + send_id: &str, + file_id: &str, data: JsonUpcase<SendAccessData>, host: Host, mut conn: DbConn, nt: Notify<'_>, ) -> JsonResult { - let mut send = match Send::find_by_uuid(&send_id, &mut conn).await { + let mut send = match Send::find_by_uuid(send_id, &mut conn).await { Some(s) => s, None => err_code!(SEND_INACCESSIBLE_MSG, 404), }; @@ -450,7 +450,7 @@ async fn post_access_file( nt.send_send_update(UpdateType::SyncSendUpdate, &send, &send.update_users_revision(&mut conn).await).await; - let token_claims = crate::auth::generate_send_claims(&send_id, &file_id); + let token_claims = crate::auth::generate_send_claims(send_id, file_id); let token = crate::auth::encode_jwt(&token_claims); Ok(Json(json!({ "Object": "send-fileDownload", @@ -460,8 +460,8 @@ async fn post_access_file( } #[get("/sends/<send_id>/<file_id>?<t>")] -async fn download_send(send_id: SafeString, file_id: SafeString, t: String) -> Option<NamedFile> { - if let Ok(claims) = crate::auth::decode_send(&t) { +async fn download_send(send_id: SafeString, file_id: SafeString, t: &str) -> Option<NamedFile> { + if let Ok(claims) = crate::auth::decode_send(t) { if claims.sub == format!("{send_id}/{file_id}") { return NamedFile::open(Path::new(&CONFIG.sends_folder()).join(send_id).join(file_id)).await.ok(); } @@ -471,7 +471,7 @@ async fn download_send(send_id: SafeString, file_id: SafeString, t: String) -> O #[put("/sends/<id>", data = "<data>")] async fn put_send( - id: String, + id: &str, data: JsonUpcase<SendData>, headers: Headers, mut conn: DbConn, @@ -482,7 +482,7 @@ async fn put_send( let data: SendData = data.into_inner().data; enforce_disable_hide_email_policy(&data, &headers, &mut conn).await?; - let mut send = match Send::find_by_uuid(&id, &mut conn).await { + let mut send = match Send::find_by_uuid(id, &mut conn).await { Some(s) => s, None => err!("Send not found"), }; @@ -536,8 +536,8 @@ async fn put_send( } #[delete("/sends/<id>")] -async fn delete_send(id: String, headers: Headers, mut conn: DbConn, nt: Notify<'_>) -> EmptyResult { - let send = match Send::find_by_uuid(&id, &mut conn).await { +async fn delete_send(id: &str, headers: Headers, mut conn: DbConn, nt: Notify<'_>) -> EmptyResult { + let send = match Send::find_by_uuid(id, &mut conn).await { Some(s) => s, None => err!("Send not found"), }; @@ -553,10 +553,10 @@ async fn delete_send(id: String, headers: Headers, mut conn: DbConn, nt: Notify< } #[put("/sends/<id>/remove-password")] -async fn put_remove_password(id: String, headers: Headers, mut conn: DbConn, nt: Notify<'_>) -> JsonResult { +async fn put_remove_password(id: &str, headers: Headers, mut conn: DbConn, nt: Notify<'_>) -> JsonResult { enforce_disable_send_policy(&headers, &mut conn).await?; - let mut send = match Send::find_by_uuid(&id, &mut conn).await { + let mut send = match Send::find_by_uuid(id, &mut conn).await { Some(s) => s, None => err!("Send not found"), }; diff --git a/src/api/icons.rs b/src/api/icons.rs @@ -97,15 +97,15 @@ async fn icon_redirect(domain: &str, template: &str) -> Option<Redirect> { } #[get("/<domain>/icon.png")] -async fn icon_external(domain: String) -> Option<Redirect> { - icon_redirect(&domain, &CONFIG._icon_service_url()).await +async fn icon_external(domain: &str) -> Option<Redirect> { + icon_redirect(domain, &CONFIG._icon_service_url()).await } #[get("/<domain>/icon.png")] -async fn icon_internal(domain: String) -> Cached<(ContentType, Vec<u8>)> { +async fn icon_internal(domain: &str) -> Cached<(ContentType, Vec<u8>)> { const FALLBACK_ICON: &[u8] = include_bytes!("../static/images/fallback-icon.png"); - if !is_valid_domain(&domain) { + if !is_valid_domain(domain) { warn!("Invalid domain: {}", domain); return Cached::ttl( (ContentType::new("image", "png"), FALLBACK_ICON.to_vec()), @@ -114,7 +114,7 @@ async fn icon_internal(domain: String) -> Cached<(ContentType, Vec<u8>)> { ); } - match get_icon(&domain).await { + match get_icon(domain).await { Some((icon, icon_type)) => { Cached::ttl((ContentType::new("image", icon_type), icon), CONFIG.icon_cache_ttl(), true) } diff --git a/src/api/web.rs b/src/api/web.rs @@ -111,8 +111,8 @@ fn alive_head(_conn: DbConn) -> EmptyResult { } #[get("/vw_static/<filename>")] -pub fn static_files(filename: String) -> Result<(ContentType, &'static [u8]), Error> { - match filename.as_ref() { +pub fn static_files(filename: &str) -> Result<(ContentType, &'static [u8]), Error> { + match filename { "404.png" => Ok((ContentType::PNG, include_bytes!("../static/images/404.png"))), "mail-github.png" => Ok((ContentType::PNG, include_bytes!("../static/images/mail-github.png"))), "logo-gray.png" => Ok((ContentType::PNG, include_bytes!("../static/images/logo-gray.png"))), diff --git a/src/auth.rs b/src/auth.rs @@ -443,32 +443,34 @@ pub struct OrgHeaders { pub ip: ClientIp, } -// org_id is usually the second path param ("/organizations/<org_id>"), -// but there are cases where it is a query value. -// First check the path, if this is not a valid uuid, try the query values. -fn get_org_id(request: &Request<'_>) -> Option<String> { - if let Some(Ok(org_id)) = request.param::<String>(1) { - if uuid::Uuid::parse_str(&org_id).is_ok() { - return Some(org_id); - } - } - - if let Some(Ok(org_id)) = request.query_value::<String>("organizationId") { - if uuid::Uuid::parse_str(&org_id).is_ok() { - return Some(org_id); - } - } - - None -} - #[rocket::async_trait] impl<'r> FromRequest<'r> for OrgHeaders { type Error = &'static str; async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Self::Error> { let headers = try_outcome!(Headers::from_request(request).await); - match get_org_id(request) { + + // org_id is usually the second path param ("/organizations/<org_id>"), + // but there are cases where it is a query value. + // First check the path, if this is not a valid uuid, try the query values. + let url_org_id: Option<&str> = { + let mut url_org_id = None; + if let Some(Ok(org_id)) = request.param::<&str>(1) { + if uuid::Uuid::parse_str(org_id).is_ok() { + url_org_id = Some(org_id); + } + } + + if let Some(Ok(org_id)) = request.query_value::<&str>("organizationId") { + if uuid::Uuid::parse_str(org_id).is_ok() { + url_org_id = Some(org_id); + } + } + + url_org_id + }; + + match url_org_id { Some(org_id) => { let mut conn = match DbConn::from_request(request).await { Outcome::Success(conn) => conn, @@ -476,7 +478,7 @@ impl<'r> FromRequest<'r> for OrgHeaders { }; let user = headers.user; - let org_user = match UserOrganization::find_by_user_and_org(&user.uuid, &org_id, &mut conn).await { + let org_user = match UserOrganization::find_by_user_and_org(&user.uuid, org_id, &mut conn).await { Some(user) => { if user.status == UserOrgStatus::Confirmed as i32 { user @@ -500,7 +502,7 @@ impl<'r> FromRequest<'r> for OrgHeaders { } }, org_user, - org_id, + org_id: String::from(org_id), ip: headers.ip, }) } diff --git a/src/mail.rs b/src/mail.rs @@ -573,8 +573,8 @@ async fn send_email(address: &str, subject: &str, body_html: String, body_text: let smtp_from = &CONFIG.smtp_from(); let body = if CONFIG.smtp_embed_images() { - let logo_gray_body = Body::new(crate::api::static_files("logo-gray.png".to_string()).unwrap().1.to_vec()); - let mail_github_body = Body::new(crate::api::static_files("mail-github.png".to_string()).unwrap().1.to_vec()); + let logo_gray_body = Body::new(crate::api::static_files("logo-gray.png").unwrap().1.to_vec()); + let mail_github_body = Body::new(crate::api::static_files("mail-github.png").unwrap().1.to_vec()); MultiPart::alternative().singlepart(SinglePart::plain(body_text)).multipart( MultiPart::related() .singlepart(SinglePart::html(body_html)) diff --git a/src/util.rs b/src/util.rs @@ -231,7 +231,7 @@ impl<'r> FromParam<'r> for SafeString { // Log all the routes from the main paths list, and the attachments endpoint // Effectively ignores, any static file route, and the alive endpoint -const LOGGED_ROUTES: [&str; 5] = ["/api", "/admin", "/identity", "/icons", "/attachments"]; +const LOGGED_ROUTES: [&str; 7] = ["/api", "/admin", "/identity", "/icons", "/attachments", "/events", "/notifications"]; // Boolean is extra debug, when true, we ignore the whitelist above and also print the mounts pub struct BetterLogging(pub bool); @@ -248,7 +248,7 @@ impl Fairing for BetterLogging { if self.0 { info!(target: "routes", "Routes loaded:"); let mut routes: Vec<_> = rocket.routes().collect(); - routes.sort_by_key(|r| r.uri.path()); + routes.sort_by_key(|r| r.uri.path().as_str()); for route in routes { if route.rank < 0 { info!(target: "routes", "{:<6} {}", route.method, route.uri);