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
pull/3491/head
BlackDex 2 years ago
parent 951ba55123
commit f906f6230a
No known key found for this signature in database
GPG Key ID: 58C80A2AA6C765E1

96
Cargo.lock generated

@ -909,9 +909,9 @@ dependencies = [
[[package]] [[package]]
name = "flate2" name = "flate2"
version = "1.0.25" version = "1.0.26"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a8a2db397cb1c8772f31494cb8917e48cd1e64f0fa7efac59fbd741a0a8ce841" checksum = "3b9429470923de8e8cbd4d2dc513535400b4b3fef0319fb5c4e1f520a7bef743"
dependencies = [ dependencies = [
"crc32fast", "crc32fast",
"miniz_oxide", "miniz_oxide",
@ -1516,9 +1516,9 @@ checksum = "6a987beff54b60ffa6d51982e1aa1146bc42f19bd26be28b0586f252fccf5317"
[[package]] [[package]]
name = "libmimalloc-sys" name = "libmimalloc-sys"
version = "0.1.32" version = "0.1.33"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "43a558e3d911bc3c7bfc8c78bc580b404d6e51c1cefbf656e176a94b49b0df40" checksum = "f4ac0e912c8ef1b735e92369695618dc5b1819f5a7bf3f167301a3ba1cea515e"
dependencies = [ dependencies = [
"cc", "cc",
"libc", "libc",
@ -1552,9 +1552,9 @@ checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f"
[[package]] [[package]]
name = "linux-raw-sys" name = "linux-raw-sys"
version = "0.3.4" version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "36eb31c1778188ae1e64398743890d0877fef36d11521ac60406b42016e8c2cf" checksum = "b64f40e5e03e0d54f03845c8197d0291253cdbedfb1cb46b13c2c117554a9f4c"
[[package]] [[package]]
name = "lock_api" name = "lock_api"
@ -1659,9 +1659,9 @@ dependencies = [
[[package]] [[package]]
name = "mimalloc" name = "mimalloc"
version = "0.1.36" version = "0.1.37"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d88dad3f985ec267a3fcb7a1726f5cb1a7e8cad8b646e70a84f967210df23da" checksum = "4e2894987a3459f3ffb755608bd82188f8ed00d0ae077f1edea29c068d639d98"
dependencies = [ dependencies = [
"libmimalloc-sys", "libmimalloc-sys",
] ]
@ -1680,9 +1680,9 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
[[package]] [[package]]
name = "miniz_oxide" name = "miniz_oxide"
version = "0.6.2" version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa" checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7"
dependencies = [ dependencies = [
"adler", "adler",
] ]
@ -1847,9 +1847,9 @@ checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3"
[[package]] [[package]]
name = "openssl" name = "openssl"
version = "0.10.51" version = "0.10.52"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "97ea2d98598bf9ada7ea6ee8a30fb74f9156b63bbe495d64ec2b87c269d2dda3" checksum = "01b8574602df80f7b85fdfc5392fa884a4e3b3f4f35402c070ab34c3d3f78d56"
dependencies = [ dependencies = [
"bitflags 1.3.2", "bitflags 1.3.2",
"cfg-if", "cfg-if",
@ -1888,9 +1888,9 @@ dependencies = [
[[package]] [[package]]
name = "openssl-sys" name = "openssl-sys"
version = "0.9.86" version = "0.9.87"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "992bac49bdbab4423199c654a5515bd2a6c6a23bf03f2dd3bdb7e5ae6259bc69" checksum = "8e17f59264b2809d77ae94f0e1ebabc434773f370d6ca667bd223ea10e06cc7e"
dependencies = [ dependencies = [
"cc", "cc",
"libc", "libc",
@ -2000,9 +2000,9 @@ checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e"
[[package]] [[package]]
name = "pest" name = "pest"
version = "2.5.7" version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b1403e8401ad5dedea73c626b99758535b342502f8d1e361f4a2dd952749122" checksum = "e68e84bfb01f0507134eac1e9b410a12ba379d064eab48c50ba4ce329a527b70"
dependencies = [ dependencies = [
"thiserror", "thiserror",
"ucd-trie", "ucd-trie",
@ -2010,9 +2010,9 @@ dependencies = [
[[package]] [[package]]
name = "pest_derive" name = "pest_derive"
version = "2.5.7" version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "be99c4c1d2fc2769b1d00239431d711d08f6efedcecb8b6e30707160aee99c15" checksum = "6b79d4c71c865a25a4322296122e3924d30bc8ee0834c8bfc8b95f7f054afbfb"
dependencies = [ dependencies = [
"pest", "pest",
"pest_generator", "pest_generator",
@ -2020,9 +2020,9 @@ dependencies = [
[[package]] [[package]]
name = "pest_generator" name = "pest_generator"
version = "2.5.7" version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e56094789873daa36164de2e822b3888c6ae4b4f9da555a1103587658c805b1e" checksum = "6c435bf1076437b851ebc8edc3a18442796b30f1728ffea6262d59bbe28b077e"
dependencies = [ dependencies = [
"pest", "pest",
"pest_meta", "pest_meta",
@ -2033,9 +2033,9 @@ dependencies = [
[[package]] [[package]]
name = "pest_meta" name = "pest_meta"
version = "2.5.7" version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6733073c7cff3d8459fda0e42f13a047870242aed8b509fe98000928975f359e" checksum = "745a452f8eb71e39ffd8ee32b3c5f51d03845f99786fa9b68db6ff509c505411"
dependencies = [ dependencies = [
"once_cell", "once_cell",
"pest", "pest",
@ -2230,9 +2230,9 @@ dependencies = [
[[package]] [[package]]
name = "quoted_printable" name = "quoted_printable"
version = "0.4.7" version = "0.4.8"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a24039f627d8285853cc90dcddf8c1ebfaa91f834566948872b225b9a28ed1b6" checksum = "5a3866219251662ec3b26fc217e3e05bf9c4f84325234dfb96bf0bf840889e49"
[[package]] [[package]]
name = "r2d2" name = "r2d2"
@ -2356,9 +2356,9 @@ checksum = "a5996294f19bd3aae0453a862ad728f60e6600695733dd5df01da90c54363a3c"
[[package]] [[package]]
name = "reqwest" name = "reqwest"
version = "0.11.16" version = "0.11.17"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "27b71749df584b7f4cac2c426c127a7c785a5106cc98f7a8feb044115f0fa254" checksum = "13293b639a097af28fc8a90f22add145a9c954e49d77da06263d58cf44d5fb91"
dependencies = [ dependencies = [
"async-compression", "async-compression",
"base64 0.21.0", "base64 0.21.0",
@ -2447,7 +2447,7 @@ dependencies = [
[[package]] [[package]]
name = "rocket" name = "rocket"
version = "0.5.0-rc.3" 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 = [ dependencies = [
"async-stream", "async-stream",
"async-trait", "async-trait",
@ -2485,7 +2485,7 @@ dependencies = [
[[package]] [[package]]
name = "rocket_codegen" name = "rocket_codegen"
version = "0.5.0-rc.3" 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 = [ dependencies = [
"devise", "devise",
"glob", "glob",
@ -2500,7 +2500,7 @@ dependencies = [
[[package]] [[package]]
name = "rocket_http" name = "rocket_http"
version = "0.5.0-rc.3" 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 = [ dependencies = [
"cookie 0.17.0", "cookie 0.17.0",
"either", "either",
@ -2529,7 +2529,7 @@ dependencies = [
[[package]] [[package]]
name = "rocket_ws" name = "rocket_ws"
version = "0.1.0-rc.3" 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 = [ dependencies = [
"rocket", "rocket",
"tokio-tungstenite", "tokio-tungstenite",
@ -2558,9 +2558,9 @@ dependencies = [
[[package]] [[package]]
name = "rustix" name = "rustix"
version = "0.37.14" version = "0.37.18"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9b864d3c18a5785a05953adeed93e2dca37ed30f18e69bba9f30079d51f363f" checksum = "8bbfc1d1c7c40c01715f47d71444744a81669ca84e8b63e25a55e169b1f86433"
dependencies = [ dependencies = [
"bitflags 1.3.2", "bitflags 1.3.2",
"errno", "errno",
@ -2920,9 +2920,9 @@ dependencies = [
[[package]] [[package]]
name = "syslog" name = "syslog"
version = "6.0.1" version = "6.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "978044cc68150ad5e40083c9f6a725e6fd02d7ba1bcf691ec2ff0d66c0b41acc" checksum = "7434e95bcccce1215d30f4bf84fe8c00e8de1b9be4fb736d747ca53d36e7f96f"
dependencies = [ dependencies = [
"error-chain", "error-chain",
"hostname", "hostname",
@ -3038,9 +3038,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
[[package]] [[package]]
name = "tokio" name = "tokio"
version = "1.27.0" version = "1.28.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d0de47a4eecbe11f498978a9b29d792f0d2692d1dd003650c24c76510e3bc001" checksum = "c3c786bf8134e5a3a166db9b29ab8f48134739014a3eca7bc6bfa95d673b136f"
dependencies = [ dependencies = [
"autocfg", "autocfg",
"bytes", "bytes",
@ -3052,14 +3052,14 @@ dependencies = [
"signal-hook-registry", "signal-hook-registry",
"socket2", "socket2",
"tokio-macros", "tokio-macros",
"windows-sys 0.45.0", "windows-sys 0.48.0",
] ]
[[package]] [[package]]
name = "tokio-macros" name = "tokio-macros"
version = "2.0.0" version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "61a573bdc87985e9d6ddeed1b3d864e8a302c847e40d647746df2f1de209d1ce" checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -3100,9 +3100,9 @@ dependencies = [
[[package]] [[package]]
name = "tokio-stream" name = "tokio-stream"
version = "0.1.12" version = "0.1.14"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8fb52b74f05dbf495a8fba459fdc331812b96aa086d9eb78101fa0d4569c3313" checksum = "397c988d37662c7dda6d2208364a706264bf3d6138b11d436cbac0ad38832842"
dependencies = [ dependencies = [
"futures-core", "futures-core",
"pin-project-lite", "pin-project-lite",
@ -3123,9 +3123,9 @@ dependencies = [
[[package]] [[package]]
name = "tokio-util" name = "tokio-util"
version = "0.7.7" version = "0.7.8"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5427d89453009325de0d8f342c9490009f76e999cb7672d77e46267448f7e6b2" checksum = "806fe8c2c87eccc8b3267cbae29ed3ab2d0bd37fca70ab622e46aaa9375ddb7d"
dependencies = [ dependencies = [
"bytes", "bytes",
"futures-core", "futures-core",
@ -3177,13 +3177,13 @@ dependencies = [
[[package]] [[package]]
name = "tracing-attributes" name = "tracing-attributes"
version = "0.1.23" version = "0.1.24"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4017f8f45139870ca7e672686113917c71c7a6e02d4924eda67186083c03081a" checksum = "0f57e3ca2a01450b1a921183a9c9cbfda207fd822cef4ccb00a65402cbba7a74"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 1.0.109", "syn 2.0.15",
] ]
[[package]] [[package]]
@ -3385,9 +3385,9 @@ checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9"
[[package]] [[package]]
name = "uuid" name = "uuid"
version = "1.3.1" version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b55a3fef2a1e3b3a00ce878640918820d3c51081576ac657d23af9fc7928fdb" checksum = "4dad5567ad0cf5b760e5665964bec1b47dfd077ba8a2544b513f3556d3d239a2"
dependencies = [ dependencies = [
"getrandom", "getrandom",
] ]

@ -36,7 +36,7 @@ unstable = []
[target."cfg(not(windows))".dependencies] [target."cfg(not(windows))".dependencies]
# Logging # Logging
syslog = "6.0.1" syslog = "6.1.0"
[dependencies] [dependencies]
# Logging # Logging
@ -57,7 +57,7 @@ num-derive = "0.3.3"
# Web framework # Web framework
rocket = { version = "0.5.0-rc.3", features = ["tls", "json"], default-features = false } rocket = { version = "0.5.0-rc.3", features = ["tls", "json"], default-features = false }
# rocket_ws = { version ="0.1.0-rc.3" } # 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 # WebSockets libraries
tokio-tungstenite = "0.18.0" tokio-tungstenite = "0.18.0"
@ -68,7 +68,7 @@ dashmap = "5.4.0"
# Async futures # Async futures
futures = "0.3.28" 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 # A generic serialization/deserialization framework
serde = { version = "1.0.160", features = ["derive"] } serde = { version = "1.0.160", features = ["derive"] }
@ -87,7 +87,7 @@ rand = { version = "0.8.5", features = ["small_rng"] }
ring = "0.16.20" ring = "0.16.20"
# UUID generation # UUID generation
uuid = { version = "1.3.1", features = ["v4"] } uuid = { version = "1.3.2", features = ["v4"] }
# Date and time libraries # Date and time libraries
chrono = { version = "0.4.24", features = ["clock", "serde"], default-features = false } 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"] } handlebars = { version = "4.3.6", features = ["dir_source"] }
# HTTP client (Used for favicons, version check, DUO and HIBP API) # 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 # Favicon extraction libraries
html5gum = "0.5.2" html5gum = "0.5.2"
@ -140,7 +140,7 @@ cookie = "0.16.2"
cookie_store = "0.19.0" cookie_store = "0.19.0"
# Used by U2F, JWT and PostgreSQL # Used by U2F, JWT and PostgreSQL
openssl = "0.10.51" openssl = "0.10.52"
# CLI argument parsing # CLI argument parsing
pico-args = "0.5.0" pico-args = "0.5.0"
@ -154,7 +154,7 @@ semver = "1.0.17"
# Allow overriding the default memory allocator # Allow overriding the default memory allocator
# Mainly used for the musl builds, since the default musl malloc is very slow # 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" which = "4.4.0"
# Argon2 library with support for the PHC format # Argon2 library with support for the PHC format
@ -164,8 +164,8 @@ argon2 = "0.5.0"
rpassword = "7.2.0" rpassword = "7.2.0"
[patch.crates-io] [patch.crates-io]
rocket = { 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 = 'a82508b403420bd941c32ddec3ee3e4875f2b8a5' } # rocket_ws = { git = 'https://github.com/SergioBenitez/Rocket', rev = '9b0564ed27f90686b333337d9f6ed76484a84b27' }
# Strip debuginfo from the release builds # Strip debuginfo from the release builds
# Also enable thin LTO for some optimizations # Also enable thin LTO for some optimizations

@ -349,8 +349,8 @@ async fn users_overview(_token: AdminToken, mut conn: DbConn) -> ApiResult<Html<
} }
#[get("/users/by-mail/<mail>")] #[get("/users/by-mail/<mail>")]
async fn get_user_by_mail_json(mail: String, _token: AdminToken, mut conn: DbConn) -> JsonResult { 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 { if let Some(u) = User::find_by_mail(mail, &mut conn).await {
let mut usr = u.to_json(&mut conn).await; let mut usr = u.to_json(&mut conn).await;
usr["UserEnabled"] = json!(u.enabled); usr["UserEnabled"] = json!(u.enabled);
usr["CreatedAt"] = json!(format_naive_datetime_local(&u.created_at, DT_FMT)); 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>")] #[get("/users/<uuid>")]
async fn get_user_json(uuid: String, _token: AdminToken, mut conn: DbConn) -> JsonResult { async fn get_user_json(uuid: &str, _token: AdminToken, mut conn: DbConn) -> JsonResult {
let u = get_user_or_404(&uuid, &mut conn).await?; let u = get_user_or_404(uuid, &mut conn).await?;
let mut usr = u.to_json(&mut conn).await; let mut usr = u.to_json(&mut conn).await;
usr["UserEnabled"] = json!(u.enabled); usr["UserEnabled"] = json!(u.enabled);
usr["CreatedAt"] = json!(format_naive_datetime_local(&u.created_at, DT_FMT)); 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")] #[post("/users/<uuid>/delete")]
async fn delete_user(uuid: String, token: AdminToken, mut conn: DbConn) -> EmptyResult { async fn delete_user(uuid: &str, token: AdminToken, mut conn: DbConn) -> EmptyResult {
let user = get_user_or_404(&uuid, &mut conn).await?; let user = get_user_or_404(uuid, &mut conn).await?;
// Get the user_org records before deleting the actual user // 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; let res = user.delete(&mut conn).await;
for user_org in user_orgs { for user_org in user_orgs {
log_event( log_event(
EventType::OrganizationUserRemoved as i32, EventType::OrganizationUserRemoved as i32,
&user_org.uuid, &user_org.uuid,
user_org.org_uuid, &user_org.org_uuid,
String::from(ACTING_ADMIN_USER), String::from(ACTING_ADMIN_USER),
14, // Use UnknownBrowser type 14, // Use UnknownBrowser type
&token.ip.ip, &token.ip.ip,
@ -394,8 +394,8 @@ async fn delete_user(uuid: String, token: AdminToken, mut conn: DbConn) -> Empty
} }
#[post("/users/<uuid>/deauth")] #[post("/users/<uuid>/deauth")]
async fn deauth_user(uuid: String, _token: AdminToken, mut conn: DbConn, nt: Notify<'_>) -> EmptyResult { 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?; let mut user = get_user_or_404(uuid, &mut conn).await?;
Device::delete_all_by_user(&user.uuid, &mut conn).await?; Device::delete_all_by_user(&user.uuid, &mut conn).await?;
user.reset_security_stamp(); 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")] #[post("/users/<uuid>/disable")]
async fn disable_user(uuid: String, _token: AdminToken, mut conn: DbConn, nt: Notify<'_>) -> EmptyResult { 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?; let mut user = get_user_or_404(uuid, &mut conn).await?;
Device::delete_all_by_user(&user.uuid, &mut conn).await?; Device::delete_all_by_user(&user.uuid, &mut conn).await?;
user.reset_security_stamp(); user.reset_security_stamp();
user.enabled = false; user.enabled = false;
@ -421,24 +421,24 @@ async fn disable_user(uuid: String, _token: AdminToken, mut conn: DbConn, nt: No
} }
#[post("/users/<uuid>/enable")] #[post("/users/<uuid>/enable")]
async fn enable_user(uuid: String, _token: AdminToken, mut conn: DbConn) -> EmptyResult { async fn enable_user(uuid: &str, _token: AdminToken, mut conn: DbConn) -> EmptyResult {
let mut user = get_user_or_404(&uuid, &mut conn).await?; let mut user = get_user_or_404(uuid, &mut conn).await?;
user.enabled = true; user.enabled = true;
user.save(&mut conn).await user.save(&mut conn).await
} }
#[post("/users/<uuid>/remove-2fa")] #[post("/users/<uuid>/remove-2fa")]
async fn remove_2fa(uuid: String, _token: AdminToken, mut conn: DbConn) -> EmptyResult { async fn remove_2fa(uuid: &str, _token: AdminToken, mut conn: DbConn) -> EmptyResult {
let mut user = get_user_or_404(&uuid, &mut conn).await?; let mut user = get_user_or_404(uuid, &mut conn).await?;
TwoFactor::delete_all_by_user(&user.uuid, &mut conn).await?; TwoFactor::delete_all_by_user(&user.uuid, &mut conn).await?;
user.totp_recover = None; user.totp_recover = None;
user.save(&mut conn).await user.save(&mut conn).await
} }
#[post("/users/<uuid>/invite/resend")] #[post("/users/<uuid>/invite/resend")]
async fn resend_user_invite(uuid: String, _token: AdminToken, mut conn: DbConn) -> EmptyResult { 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 { 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) //TODO: replace this with user.status check when it will be available (PR#3397)
if !user.password_hash.is_empty() { if !user.password_hash.is_empty() {
err_code!("User already accepted invitation", Status::BadRequest.code); 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( log_event(
EventType::OrganizationUserUpdated as i32, EventType::OrganizationUserUpdated as i32,
&user_to_edit.uuid, &user_to_edit.uuid,
data.org_uuid, &data.org_uuid,
String::from(ACTING_ADMIN_USER), String::from(ACTING_ADMIN_USER),
14, // Use UnknownBrowser type 14, // Use UnknownBrowser type
&token.ip.ip, &token.ip.ip,
@ -538,8 +538,8 @@ async fn organizations_overview(_token: AdminToken, mut conn: DbConn) -> ApiResu
} }
#[post("/organizations/<uuid>/delete")] #[post("/organizations/<uuid>/delete")]
async fn delete_organization(uuid: String, _token: AdminToken, mut conn: DbConn) -> EmptyResult { 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")?; let org = Organization::find_by_uuid(uuid, &mut conn).await.map_res("Organization doesn't exist")?;
org.delete(&mut conn).await org.delete(&mut conn).await
} }

@ -133,7 +133,7 @@ pub async fn _register(data: JsonUpcase<RegisterData>, mut conn: DbConn) -> Json
err!("Registration email does not match invite email") err!("Registration email does not match invite email")
} }
} else if Invitation::take(&email, &mut conn).await { } 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.status = UserOrgStatus::Accepted as i32;
user_org.save(&mut conn).await?; 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")] #[get("/users/<uuid>/public-key")]
async fn get_public_keys(uuid: String, _headers: Headers, mut conn: DbConn) -> JsonResult { async fn get_public_keys(uuid: &str, _headers: Headers, mut conn: DbConn) -> JsonResult {
let user = match User::find_by_uuid(&uuid, &mut conn).await { let user = match User::find_by_uuid(uuid, &mut conn).await {
Some(user) => user, Some(user) => user,
None => err!("User doesn't exist"), 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 // This variant is deprecated: https://github.com/bitwarden/server/pull/2682
#[get("/devices/knowndevice/<email>/<uuid>")] #[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 // This endpoint doesn't have auth header
let mut result = false; let mut result = false;
if let Some(user) = User::find_by_mail(&email, &mut conn).await { 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(); result = Device::find_by_uuid_and_user(uuid, &user.uuid, &mut conn).await.is_some();
} }
Ok(Json(json!(result))) Ok(Json(json!(result)))
} }
#[get("/devices/knowndevice")] #[get("/devices/knowndevice")]
async fn get_known_device(device: KnownDevice, conn: DbConn) -> JsonResult { 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 { struct KnownDevice {

@ -172,8 +172,8 @@ async fn get_ciphers(headers: Headers, mut conn: DbConn) -> Json<Value> {
} }
#[get("/ciphers/<uuid>")] #[get("/ciphers/<uuid>")]
async fn get_cipher(uuid: String, headers: Headers, mut conn: DbConn) -> JsonResult { async fn get_cipher(uuid: &str, 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, Some(cipher) => cipher,
None => err!("Cipher doesn't exist"), 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")] #[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 // TODO: Implement this correctly
get_cipher(uuid, headers, conn).await get_cipher(uuid, headers, conn).await
} }
#[get("/ciphers/<uuid>/details")] #[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 get_cipher(uuid, headers, conn).await
} }
@ -503,7 +503,7 @@ pub async fn update_cipher_from_data(
log_event( log_event(
event_type as i32, event_type as i32,
&cipher.uuid, &cipher.uuid,
String::from(org_uuid), org_uuid,
headers.user.uuid.clone(), headers.user.uuid.clone(),
headers.device.atype, headers.device.atype,
&headers.ip.ip, &headers.ip.ip,
@ -586,7 +586,7 @@ async fn post_ciphers_import(
/// Called when an org admin modifies an existing org cipher. /// Called when an org admin modifies an existing org cipher.
#[put("/ciphers/<uuid>/admin", data = "<data>")] #[put("/ciphers/<uuid>/admin", data = "<data>")]
async fn put_cipher_admin( async fn put_cipher_admin(
uuid: String, uuid: &str,
data: JsonUpcase<CipherData>, data: JsonUpcase<CipherData>,
headers: Headers, headers: Headers,
conn: DbConn, conn: DbConn,
@ -597,7 +597,7 @@ async fn put_cipher_admin(
#[post("/ciphers/<uuid>/admin", data = "<data>")] #[post("/ciphers/<uuid>/admin", data = "<data>")]
async fn post_cipher_admin( async fn post_cipher_admin(
uuid: String, uuid: &str,
data: JsonUpcase<CipherData>, data: JsonUpcase<CipherData>,
headers: Headers, headers: Headers,
conn: DbConn, conn: DbConn,
@ -608,7 +608,7 @@ async fn post_cipher_admin(
#[post("/ciphers/<uuid>", data = "<data>")] #[post("/ciphers/<uuid>", data = "<data>")]
async fn post_cipher( async fn post_cipher(
uuid: String, uuid: &str,
data: JsonUpcase<CipherData>, data: JsonUpcase<CipherData>,
headers: Headers, headers: Headers,
conn: DbConn, conn: DbConn,
@ -619,7 +619,7 @@ async fn post_cipher(
#[put("/ciphers/<uuid>", data = "<data>")] #[put("/ciphers/<uuid>", data = "<data>")]
async fn put_cipher( async fn put_cipher(
uuid: String, uuid: &str,
data: JsonUpcase<CipherData>, data: JsonUpcase<CipherData>,
headers: Headers, headers: Headers,
mut conn: DbConn, mut conn: DbConn,
@ -627,7 +627,7 @@ async fn put_cipher(
) -> JsonResult { ) -> JsonResult {
let data: CipherData = data.into_inner().data; 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, Some(cipher) => cipher,
None => err!("Cipher doesn't exist"), None => err!("Cipher doesn't exist"),
}; };
@ -648,7 +648,7 @@ async fn put_cipher(
#[post("/ciphers/<uuid>/partial", data = "<data>")] #[post("/ciphers/<uuid>/partial", data = "<data>")]
async fn post_cipher_partial( async fn post_cipher_partial(
uuid: String, uuid: &str,
data: JsonUpcase<PartialCipherData>, data: JsonUpcase<PartialCipherData>,
headers: Headers, headers: Headers,
conn: DbConn, 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 // Only update the folder and favorite for the user, since this cipher is read-only
#[put("/ciphers/<uuid>/partial", data = "<data>")] #[put("/ciphers/<uuid>/partial", data = "<data>")]
async fn put_cipher_partial( async fn put_cipher_partial(
uuid: String, uuid: &str,
data: JsonUpcase<PartialCipherData>, data: JsonUpcase<PartialCipherData>,
headers: Headers, headers: Headers,
mut conn: DbConn, mut conn: DbConn,
) -> JsonResult { ) -> JsonResult {
let data: PartialCipherData = data.into_inner().data; 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, Some(cipher) => cipher,
None => err!("Cipher doesn't exist"), None => err!("Cipher doesn't exist"),
}; };
@ -698,7 +698,7 @@ struct CollectionsAdminData {
#[put("/ciphers/<uuid>/collections", data = "<data>")] #[put("/ciphers/<uuid>/collections", data = "<data>")]
async fn put_collections_update( async fn put_collections_update(
uuid: String, uuid: &str,
data: JsonUpcase<CollectionsAdminData>, data: JsonUpcase<CollectionsAdminData>,
headers: Headers, headers: Headers,
conn: DbConn, conn: DbConn,
@ -708,7 +708,7 @@ async fn put_collections_update(
#[post("/ciphers/<uuid>/collections", data = "<data>")] #[post("/ciphers/<uuid>/collections", data = "<data>")]
async fn post_collections_update( async fn post_collections_update(
uuid: String, uuid: &str,
data: JsonUpcase<CollectionsAdminData>, data: JsonUpcase<CollectionsAdminData>,
headers: Headers, headers: Headers,
conn: DbConn, conn: DbConn,
@ -718,7 +718,7 @@ async fn post_collections_update(
#[put("/ciphers/<uuid>/collections-admin", data = "<data>")] #[put("/ciphers/<uuid>/collections-admin", data = "<data>")]
async fn put_collections_admin( async fn put_collections_admin(
uuid: String, uuid: &str,
data: JsonUpcase<CollectionsAdminData>, data: JsonUpcase<CollectionsAdminData>,
headers: Headers, headers: Headers,
conn: DbConn, conn: DbConn,
@ -728,14 +728,14 @@ async fn put_collections_admin(
#[post("/ciphers/<uuid>/collections-admin", data = "<data>")] #[post("/ciphers/<uuid>/collections-admin", data = "<data>")]
async fn post_collections_admin( async fn post_collections_admin(
uuid: String, uuid: &str,
data: JsonUpcase<CollectionsAdminData>, data: JsonUpcase<CollectionsAdminData>,
headers: Headers, headers: Headers,
mut conn: DbConn, mut conn: DbConn,
) -> EmptyResult { ) -> EmptyResult {
let data: CollectionsAdminData = data.into_inner().data; 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, Some(cipher) => cipher,
None => err!("Cipher doesn't exist"), None => err!("Cipher doesn't exist"),
}; };
@ -770,7 +770,7 @@ async fn post_collections_admin(
log_event( log_event(
EventType::CipherUpdatedCollections as i32, EventType::CipherUpdatedCollections as i32,
&cipher.uuid, &cipher.uuid,
cipher.organization_uuid.unwrap(), &cipher.organization_uuid.unwrap(),
headers.user.uuid.clone(), headers.user.uuid.clone(),
headers.device.atype, headers.device.atype,
&headers.ip.ip, &headers.ip.ip,
@ -790,7 +790,7 @@ struct ShareCipherData {
#[post("/ciphers/<uuid>/share", data = "<data>")] #[post("/ciphers/<uuid>/share", data = "<data>")]
async fn post_cipher_share( async fn post_cipher_share(
uuid: String, uuid: &str,
data: JsonUpcase<ShareCipherData>, data: JsonUpcase<ShareCipherData>,
headers: Headers, headers: Headers,
mut conn: DbConn, mut conn: DbConn,
@ -798,12 +798,12 @@ async fn post_cipher_share(
) -> JsonResult { ) -> JsonResult {
let data: ShareCipherData = data.into_inner().data; 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>")] #[put("/ciphers/<uuid>/share", data = "<data>")]
async fn put_cipher_share( async fn put_cipher_share(
uuid: String, uuid: &str,
data: JsonUpcase<ShareCipherData>, data: JsonUpcase<ShareCipherData>,
headers: Headers, headers: Headers,
mut conn: DbConn, mut conn: DbConn,
@ -811,7 +811,7 @@ async fn put_cipher_share(
) -> JsonResult { ) -> JsonResult {
let data: ShareCipherData = data.into_inner().data; 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)] #[derive(Deserialize)]
@ -916,8 +916,8 @@ async fn share_cipher_by_uuid(
/// their object storage service. For self-hosted instances, it basically just /// their object storage service. For self-hosted instances, it basically just
/// redirects to the same location as before the v2 API. /// redirects to the same location as before the v2 API.
#[get("/ciphers/<uuid>/attachment/<attachment_id>")] #[get("/ciphers/<uuid>/attachment/<attachment_id>")]
async fn get_attachment(uuid: String, attachment_id: String, headers: Headers, mut conn: DbConn) -> JsonResult { 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 { 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(attachment) if uuid == attachment.cipher_uuid => Ok(Json(attachment.to_json(&headers.host))),
Some(_) => err!("Attachment doesn't belong to cipher"), Some(_) => err!("Attachment doesn't belong to cipher"),
None => err!("Attachment doesn't exist"), None => err!("Attachment doesn't exist"),
@ -944,12 +944,12 @@ enum FileUploadType {
/// For self-hosted instances, it's another API on the local instance. /// For self-hosted instances, it's another API on the local instance.
#[post("/ciphers/<uuid>/attachment/v2", data = "<data>")] #[post("/ciphers/<uuid>/attachment/v2", data = "<data>")]
async fn post_attachment_v2( async fn post_attachment_v2(
uuid: String, uuid: &str,
data: JsonUpcase<AttachmentRequestData>, data: JsonUpcase<AttachmentRequestData>,
headers: Headers, headers: Headers,
mut conn: DbConn, mut conn: DbConn,
) -> JsonResult { ) -> 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, Some(cipher) => cipher,
None => err!("Cipher doesn't exist"), None => err!("Cipher doesn't exist"),
}; };
@ -995,13 +995,13 @@ struct UploadData<'f> {
/// database record, which is passed in as `attachment`. /// database record, which is passed in as `attachment`.
async fn save_attachment( async fn save_attachment(
mut attachment: Option<Attachment>, mut attachment: Option<Attachment>,
cipher_uuid: String, cipher_uuid: &str,
data: Form<UploadData<'_>>, data: Form<UploadData<'_>>,
headers: &Headers, headers: &Headers,
mut conn: DbConn, mut conn: DbConn,
nt: Notify<'_>, nt: Notify<'_>,
) -> Result<(Cipher, DbConn), crate::error::Error> { ) -> 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, Some(cipher) => cipher,
None => err!("Cipher doesn't exist"), None => err!("Cipher doesn't exist"),
}; };
@ -1058,7 +1058,7 @@ async fn save_attachment(
None => crypto::generate_attachment_id(), // Legacy API 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); let file_path = folder_path.join(&file_id);
tokio::fs::create_dir_all(&folder_path).await?; tokio::fs::create_dir_all(&folder_path).await?;
@ -1094,7 +1094,8 @@ async fn save_attachment(
if data.key.is_none() { if data.key.is_none() {
err!("No attachment key provided") 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"); attachment.save(&mut conn).await.expect("Error saving attachment");
} }
@ -1114,7 +1115,7 @@ async fn save_attachment(
log_event( log_event(
EventType::CipherAttachmentCreated as i32, EventType::CipherAttachmentCreated as i32,
&cipher.uuid, &cipher.uuid,
String::from(org_uuid), org_uuid,
headers.user.uuid.clone(), headers.user.uuid.clone(),
headers.device.atype, headers.device.atype,
&headers.ip.ip, &headers.ip.ip,
@ -1132,14 +1133,14 @@ async fn save_attachment(
/// with this one. /// with this one.
#[post("/ciphers/<uuid>/attachment/<attachment_id>", format = "multipart/form-data", data = "<data>", rank = 1)] #[post("/ciphers/<uuid>/attachment/<attachment_id>", format = "multipart/form-data", data = "<data>", rank = 1)]
async fn post_attachment_v2_data( async fn post_attachment_v2_data(
uuid: String, uuid: &str,
attachment_id: String, attachment_id: &str,
data: Form<UploadData<'_>>, data: Form<UploadData<'_>>,
headers: Headers, headers: Headers,
mut conn: DbConn, mut conn: DbConn,
nt: Notify<'_>, nt: Notify<'_>,
) -> EmptyResult { ) -> 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(attachment) if uuid == attachment.cipher_uuid => Some(attachment),
Some(_) => err!("Attachment doesn't belong to cipher"), Some(_) => err!("Attachment doesn't belong to cipher"),
None => err!("Attachment doesn't exist"), 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. /// Legacy API for creating an attachment associated with a cipher.
#[post("/ciphers/<uuid>/attachment", format = "multipart/form-data", data = "<data>")] #[post("/ciphers/<uuid>/attachment", format = "multipart/form-data", data = "<data>")]
async fn post_attachment( async fn post_attachment(
uuid: String, uuid: &str,
data: Form<UploadData<'_>>, data: Form<UploadData<'_>>,
headers: Headers, headers: Headers,
conn: DbConn, conn: DbConn,
@ -1170,7 +1171,7 @@ async fn post_attachment(
#[post("/ciphers/<uuid>/attachment-admin", format = "multipart/form-data", data = "<data>")] #[post("/ciphers/<uuid>/attachment-admin", format = "multipart/form-data", data = "<data>")]
async fn post_attachment_admin( async fn post_attachment_admin(
uuid: String, uuid: &str,
data: Form<UploadData<'_>>, data: Form<UploadData<'_>>,
headers: Headers, headers: Headers,
conn: DbConn, conn: DbConn,
@ -1181,21 +1182,21 @@ async fn post_attachment_admin(
#[post("/ciphers/<uuid>/attachment/<attachment_id>/share", format = "multipart/form-data", data = "<data>")] #[post("/ciphers/<uuid>/attachment/<attachment_id>/share", format = "multipart/form-data", data = "<data>")]
async fn post_attachment_share( async fn post_attachment_share(
uuid: String, uuid: &str,
attachment_id: String, attachment_id: &str,
data: Form<UploadData<'_>>, data: Form<UploadData<'_>>,
headers: Headers, headers: Headers,
mut conn: DbConn, mut conn: DbConn,
nt: Notify<'_>, nt: Notify<'_>,
) -> JsonResult { ) -> 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_attachment(uuid, data, headers, conn, nt).await
} }
#[post("/ciphers/<uuid>/attachment/<attachment_id>/delete-admin")] #[post("/ciphers/<uuid>/attachment/<attachment_id>/delete-admin")]
async fn delete_attachment_post_admin( async fn delete_attachment_post_admin(
uuid: String, uuid: &str,
attachment_id: String, attachment_id: &str,
headers: Headers, headers: Headers,
conn: DbConn, conn: DbConn,
nt: Notify<'_>, nt: Notify<'_>,
@ -1205,8 +1206,8 @@ async fn delete_attachment_post_admin(
#[post("/ciphers/<uuid>/attachment/<attachment_id>/delete")] #[post("/ciphers/<uuid>/attachment/<attachment_id>/delete")]
async fn delete_attachment_post( async fn delete_attachment_post(
uuid: String, uuid: &str,
attachment_id: String, attachment_id: &str,
headers: Headers, headers: Headers,
conn: DbConn, conn: DbConn,
nt: Notify<'_>, nt: Notify<'_>,
@ -1216,58 +1217,58 @@ async fn delete_attachment_post(
#[delete("/ciphers/<uuid>/attachment/<attachment_id>")] #[delete("/ciphers/<uuid>/attachment/<attachment_id>")]
async fn delete_attachment( async fn delete_attachment(
uuid: String, uuid: &str,
attachment_id: String, attachment_id: &str,
headers: Headers, headers: Headers,
mut conn: DbConn, mut conn: DbConn,
nt: Notify<'_>, nt: Notify<'_>,
) -> EmptyResult { ) -> 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")] #[delete("/ciphers/<uuid>/attachment/<attachment_id>/admin")]
async fn delete_attachment_admin( async fn delete_attachment_admin(
uuid: String, uuid: &str,
attachment_id: String, attachment_id: &str,
headers: Headers, headers: Headers,
mut conn: DbConn, mut conn: DbConn,
nt: Notify<'_>, nt: Notify<'_>,
) -> EmptyResult { ) -> 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")] #[post("/ciphers/<uuid>/delete")]
async fn delete_cipher_post(uuid: String, headers: Headers, mut conn: DbConn, nt: Notify<'_>) -> EmptyResult { 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 _delete_cipher_by_uuid(uuid, &headers, &mut conn, false, &nt).await
// permanent delete // permanent delete
} }
#[post("/ciphers/<uuid>/delete-admin")] #[post("/ciphers/<uuid>/delete-admin")]
async fn delete_cipher_post_admin(uuid: String, headers: Headers, mut conn: DbConn, nt: Notify<'_>) -> EmptyResult { 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 _delete_cipher_by_uuid(uuid, &headers, &mut conn, false, &nt).await
// permanent delete // permanent delete
} }
#[put("/ciphers/<uuid>/delete")] #[put("/ciphers/<uuid>/delete")]
async fn delete_cipher_put(uuid: String, headers: Headers, mut conn: DbConn, nt: Notify<'_>) -> EmptyResult { 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 _delete_cipher_by_uuid(uuid, &headers, &mut conn, true, &nt).await
// soft delete // soft delete
} }
#[put("/ciphers/<uuid>/delete-admin")] #[put("/ciphers/<uuid>/delete-admin")]
async fn delete_cipher_put_admin(uuid: String, headers: Headers, mut conn: DbConn, nt: Notify<'_>) -> EmptyResult { 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_cipher_by_uuid(uuid, &headers, &mut conn, true, &nt).await
} }
#[delete("/ciphers/<uuid>")] #[delete("/ciphers/<uuid>")]
async fn delete_cipher(uuid: String, headers: Headers, mut conn: DbConn, nt: Notify<'_>) -> EmptyResult { 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 _delete_cipher_by_uuid(uuid, &headers, &mut conn, false, &nt).await
// permanent delete // permanent delete
} }
#[delete("/ciphers/<uuid>/admin")] #[delete("/ciphers/<uuid>/admin")]
async fn delete_cipher_admin(uuid: String, headers: Headers, mut conn: DbConn, nt: Notify<'_>) -> EmptyResult { 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 _delete_cipher_by_uuid(uuid, &headers, &mut conn, false, &nt).await
// permanent delete // permanent delete
} }
@ -1332,13 +1333,13 @@ async fn delete_cipher_selected_put_admin(
} }
#[put("/ciphers/<uuid>/restore")] #[put("/ciphers/<uuid>/restore")]
async fn restore_cipher_put(uuid: String, headers: Headers, mut conn: DbConn, nt: Notify<'_>) -> JsonResult { 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 _restore_cipher_by_uuid(uuid, &headers, &mut conn, &nt).await
} }
#[put("/ciphers/<uuid>/restore-admin")] #[put("/ciphers/<uuid>/restore-admin")]
async fn restore_cipher_put_admin(uuid: String, headers: Headers, mut conn: DbConn, nt: Notify<'_>) -> JsonResult { 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 _restore_cipher_by_uuid(uuid, &headers, &mut conn, &nt).await
} }
#[put("/ciphers/restore", data = "<data>")] #[put("/ciphers/restore", data = "<data>")]
@ -1444,7 +1445,7 @@ async fn delete_all(
log_event( log_event(
EventType::OrganizationPurgedVault as i32, EventType::OrganizationPurgedVault as i32,
&org_data.org_id, &org_data.org_id,
org_data.org_id.clone(), &org_data.org_id,
user.uuid, user.uuid,
headers.device.atype, headers.device.atype,
&headers.ip.ip, &headers.ip.ip,
@ -1524,7 +1525,7 @@ async fn _delete_cipher_by_uuid(
log_event( log_event(
event_type, event_type,
&cipher.uuid, &cipher.uuid,
org_uuid, &org_uuid,
headers.user.uuid.clone(), headers.user.uuid.clone(),
headers.device.atype, headers.device.atype,
&headers.ip.ip, &headers.ip.ip,
@ -1586,7 +1587,7 @@ async fn _restore_cipher_by_uuid(uuid: &str, headers: &Headers, conn: &mut DbCon
log_event( log_event(
EventType::CipherRestored as i32, EventType::CipherRestored as i32,
&cipher.uuid.clone(), &cipher.uuid.clone(),
String::from(org_uuid), org_uuid,
headers.user.uuid.clone(), headers.user.uuid.clone(),
headers.device.atype, headers.device.atype,
&headers.ip.ip, &headers.ip.ip,
@ -1667,7 +1668,7 @@ async fn _delete_cipher_attachment_by_id(
log_event( log_event(
EventType::CipherAttachmentDeleted as i32, EventType::CipherAttachmentDeleted as i32,
&cipher.uuid, &cipher.uuid,
org_uuid, &org_uuid,
headers.user.uuid.clone(), headers.user.uuid.clone(),
headers.device.atype, headers.device.atype,
&headers.ip.ip, &headers.ip.ip,

@ -71,10 +71,10 @@ async fn get_grantees(headers: Headers, mut conn: DbConn) -> JsonResult {
} }
#[get("/emergency-access/<emer_id>")] #[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()?; 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)), Some(emergency_access) => Ok(Json(emergency_access.to_json_grantee_details(&mut conn).await)),
None => err!("Emergency access not valid."), None => err!("Emergency access not valid."),
} }
@ -93,17 +93,13 @@ struct EmergencyAccessUpdateData {
} }
#[put("/emergency-access/<emer_id>", data = "<data>")] #[put("/emergency-access/<emer_id>", data = "<data>")]
async fn put_emergency_access( async fn put_emergency_access(emer_id: &str, data: JsonUpcase<EmergencyAccessUpdateData>, conn: DbConn) -> JsonResult {
emer_id: String,
data: JsonUpcase<EmergencyAccessUpdateData>,
conn: DbConn,
) -> JsonResult {
post_emergency_access(emer_id, data, conn).await post_emergency_access(emer_id, data, conn).await
} }
#[post("/emergency-access/<emer_id>", data = "<data>")] #[post("/emergency-access/<emer_id>", data = "<data>")]
async fn post_emergency_access( async fn post_emergency_access(
emer_id: String, emer_id: &str,
data: JsonUpcase<EmergencyAccessUpdateData>, data: JsonUpcase<EmergencyAccessUpdateData>,
mut conn: DbConn, mut conn: DbConn,
) -> JsonResult { ) -> JsonResult {
@ -111,7 +107,7 @@ async fn post_emergency_access(
let data: EmergencyAccessUpdateData = data.into_inner().data; 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, Some(emergency_access) => emergency_access,
None => err!("Emergency access not valid."), None => err!("Emergency access not valid."),
}; };
@ -136,12 +132,12 @@ async fn post_emergency_access(
// region delete // region delete
#[delete("/emergency-access/<emer_id>")] #[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()?; check_emergency_access_allowed()?;
let grantor_user = headers.user; 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) => { Some(emer) => {
if emer.grantor_uuid != grantor_user.uuid && emer.grantee_uuid != Some(grantor_user.uuid) { if emer.grantor_uuid != grantor_user.uuid && emer.grantee_uuid != Some(grantor_user.uuid) {
err!("Emergency access not valid.") 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")] #[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 delete_emergency_access(emer_id, headers, conn).await
} }
@ -243,7 +239,7 @@ async fn send_invite(data: JsonUpcase<EmergencyAccessInviteData>, headers: Heade
} else { } else {
// Automatically mark user as accepted if no email invites // Automatically mark user as accepted if no email invites
match User::find_by_mail(&email, &mut conn).await { 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, Ok(v) => v,
Err(e) => err!(e.to_string()), 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")] #[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()?; 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, Some(emer) => emer,
None => err!("Emergency access not valid."), 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 // 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, Ok(v) => v,
Err(e) => err!(e.to_string()), Err(e) => err!(e.to_string()),
} }
@ -315,12 +311,7 @@ struct AcceptData {
} }
#[post("/emergency-access/<emer_id>/accept", data = "<data>")] #[post("/emergency-access/<emer_id>/accept", data = "<data>")]
async fn accept_invite( async fn accept_invite(emer_id: &str, data: JsonUpcase<AcceptData>, headers: Headers, mut conn: DbConn) -> EmptyResult {
emer_id: String,
data: JsonUpcase<AcceptData>,
headers: Headers,
mut conn: DbConn,
) -> EmptyResult {
check_emergency_access_allowed()?; check_emergency_access_allowed()?;
let data: AcceptData = data.into_inner().data; let data: AcceptData = data.into_inner().data;
@ -341,7 +332,7 @@ async fn accept_invite(
None => err!("Invited user not found"), 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, Some(emer) => emer,
None => err!("Emergency access not valid."), None => err!("Emergency access not valid."),
}; };
@ -356,7 +347,7 @@ async fn accept_invite(
&& grantor_user.name == claims.grantor_name && grantor_user.name == claims.grantor_name
&& grantor_user.email == claims.grantor_email && 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, Ok(v) => v,
Err(e) => err!(e.to_string()), Err(e) => err!(e.to_string()),
} }
@ -372,7 +363,7 @@ async fn accept_invite(
} }
async fn accept_invite_process( async fn accept_invite_process(
grantee_uuid: String, grantee_uuid: &str,
emergency_access: &mut EmergencyAccess, emergency_access: &mut EmergencyAccess,
grantee_email: &str, grantee_email: &str,
conn: &mut DbConn, conn: &mut DbConn,
@ -386,7 +377,7 @@ async fn accept_invite_process(
} }
emergency_access.status = EmergencyAccessStatus::Accepted as i32; 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.email = None;
emergency_access.save(conn).await emergency_access.save(conn).await
} }
@ -399,7 +390,7 @@ struct ConfirmData {
#[post("/emergency-access/<emer_id>/confirm", data = "<data>")] #[post("/emergency-access/<emer_id>/confirm", data = "<data>")]
async fn confirm_emergency_access( async fn confirm_emergency_access(
emer_id: String, emer_id: &str,
data: JsonUpcase<ConfirmData>, data: JsonUpcase<ConfirmData>,
headers: Headers, headers: Headers,
mut conn: DbConn, mut conn: DbConn,
@ -410,7 +401,7 @@ async fn confirm_emergency_access(
let data: ConfirmData = data.into_inner().data; let data: ConfirmData = data.into_inner().data;
let key = data.Key; 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, Some(emer) => emer,
None => err!("Emergency access not valid."), None => err!("Emergency access not valid."),
}; };
@ -452,11 +443,11 @@ async fn confirm_emergency_access(
// region access emergency access // region access emergency access
#[post("/emergency-access/<emer_id>/initiate")] #[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()?; check_emergency_access_allowed()?;
let initiating_user = headers.user; 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, Some(emer) => emer,
None => err!("Emergency access not valid."), 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")] #[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()?; 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, Some(emer) => emer,
None => err!("Emergency access not valid."), 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")] #[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()?; 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, Some(emer) => emer,
None => err!("Emergency access not valid."), 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 // region action
#[post("/emergency-access/<emer_id>/view")] #[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()?; 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, Some(emer) => emer,
None => err!("Emergency access not valid."), 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.") 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")] #[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()?; check_emergency_access_allowed()?;
let requesting_user = headers.user; 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, Some(emer) => emer,
None => err!("Emergency access not valid."), 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.") err!("Emergency access not valid.")
} }
@ -649,7 +640,7 @@ struct EmergencyAccessPasswordData {
#[post("/emergency-access/<emer_id>/password", data = "<data>")] #[post("/emergency-access/<emer_id>/password", data = "<data>")]
async fn password_emergency_access( async fn password_emergency_access(
emer_id: String, emer_id: &str,
data: JsonUpcase<EmergencyAccessPasswordData>, data: JsonUpcase<EmergencyAccessPasswordData>,
headers: Headers, headers: Headers,
mut conn: DbConn, mut conn: DbConn,
@ -661,12 +652,12 @@ async fn password_emergency_access(
//let key = &data.Key; //let key = &data.Key;
let requesting_user = headers.user; 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, Some(emer) => emer,
None => err!("Emergency access not valid."), 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.") err!("Emergency access not valid.")
} }
@ -694,14 +685,14 @@ async fn password_emergency_access(
// endregion // endregion
#[get("/emergency-access/<emer_id>/policies")] #[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 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, Some(emer) => emer,
None => err!("Emergency access not valid."), 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.") 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( fn is_valid_request(
emergency_access: &EmergencyAccess, emergency_access: &EmergencyAccess,
requesting_user_uuid: String, requesting_user_uuid: &str,
requested_access_type: EmergencyAccessType, requested_access_type: EmergencyAccessType,
) -> bool { ) -> 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.status == EmergencyAccessStatus::RecoveryApproved as i32
&& emergency_access.atype == requested_access_type as i32 && emergency_access.atype == requested_access_type as i32
} }

@ -32,7 +32,7 @@ struct EventRange {
// Upstream: https://github.com/bitwarden/server/blob/9ecf69d9cabce732cf2c57976dd9afa5728578fb/src/Api/Controllers/EventsController.cs#LL84C35-L84C41 // Upstream: https://github.com/bitwarden/server/blob/9ecf69d9cabce732cf2c57976dd9afa5728578fb/src/Api/Controllers/EventsController.cs#LL84C35-L84C41
#[get("/organizations/<org_id>/events?<data..>")] #[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. // Return an empty vec when we org events are disabled.
// This prevents client errors // This prevents client errors
let events_json: Vec<Value> = if !CONFIG.org_events_enabled() { 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) 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 .await
.iter() .iter()
.map(|e| e.to_json()) .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..>")] #[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. // Return an empty vec when we org events are disabled.
// This prevents client errors // This prevents client errors
let events_json: Vec<Value> = if !CONFIG.org_events_enabled() { let events_json: Vec<Value> = if !CONFIG.org_events_enabled() {
Vec::with_capacity(0) Vec::with_capacity(0)
} else { } else {
let mut events_json = Vec::with_capacity(0); 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 start_date = parse_date(&data.start);
let end_date = if let Some(before_date) = &data.continuation_token { let end_date = if let Some(before_date) = &data.continuation_token {
parse_date(before_date) parse_date(before_date)
@ -75,7 +75,7 @@ async fn get_cipher_events(cipher_id: String, data: EventRange, headers: Headers
parse_date(&data.end) 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 .await
.iter() .iter()
.map(|e| e.to_json()) .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..>")] #[get("/organizations/<org_id>/users/<user_org_id>/events?<data..>")]
async fn get_user_events( async fn get_user_events(
org_id: String, org_id: &str,
user_org_id: String, user_org_id: &str,
data: EventRange, data: EventRange,
_headers: AdminHeaders, _headers: AdminHeaders,
mut conn: DbConn, mut conn: DbConn,
@ -111,7 +111,7 @@ async fn get_user_events(
parse_date(&data.end) 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 .await
.iter() .iter()
.map(|e| e.to_json()) .map(|e| e.to_json())
@ -185,7 +185,7 @@ async fn post_events_collect(data: JsonUpcaseVec<EventCollection>, headers: Head
_log_event( _log_event(
event.Type, event.Type,
org_uuid, org_uuid,
String::from(org_uuid), org_uuid,
&headers.user.uuid, &headers.user.uuid,
headers.device.atype, headers.device.atype,
Some(event_date), Some(event_date),
@ -202,7 +202,7 @@ async fn post_events_collect(data: JsonUpcaseVec<EventCollection>, headers: Head
_log_event( _log_event(
event.Type, event.Type,
cipher_uuid, cipher_uuid,
org_uuid, &org_uuid,
&headers.user.uuid, &headers.user.uuid,
headers.device.atype, headers.device.atype,
Some(event_date), Some(event_date),
@ -262,7 +262,7 @@ async fn _log_user_event(
pub async fn log_event( pub async fn log_event(
event_type: i32, event_type: i32,
source_uuid: &str, source_uuid: &str,
org_uuid: String, org_uuid: &str,
act_user_uuid: String, act_user_uuid: String,
device_type: i32, device_type: i32,
ip: &IpAddr, ip: &IpAddr,
@ -278,7 +278,7 @@ pub async fn log_event(
async fn _log_event( async fn _log_event(
event_type: i32, event_type: i32,
source_uuid: &str, source_uuid: &str,
org_uuid: String, org_uuid: &str,
act_user_uuid: &str, act_user_uuid: &str,
device_type: i32, device_type: i32,
event_date: Option<NaiveDateTime>, 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.act_user_uuid = Some(String::from(act_user_uuid));
event.device_type = Some(device_type); event.device_type = Some(device_type);
event.ip_address = Some(ip.to_string()); event.ip_address = Some(ip.to_string());

@ -24,8 +24,8 @@ async fn get_folders(headers: Headers, mut conn: DbConn) -> Json<Value> {
} }
#[get("/folders/<uuid>")] #[get("/folders/<uuid>")]
async fn get_folder(uuid: String, headers: Headers, mut conn: DbConn) -> JsonResult { async fn get_folder(uuid: &str, headers: Headers, mut conn: DbConn) -> JsonResult {
let folder = match Folder::find_by_uuid(&uuid, &mut conn).await { let folder = match Folder::find_by_uuid(uuid, &mut conn).await {
Some(folder) => folder, Some(folder) => folder,
_ => err!("Invalid folder"), _ => err!("Invalid folder"),
}; };
@ -57,7 +57,7 @@ async fn post_folders(data: JsonUpcase<FolderData>, headers: Headers, mut conn:
#[post("/folders/<uuid>", data = "<data>")] #[post("/folders/<uuid>", data = "<data>")]
async fn post_folder( async fn post_folder(
uuid: String, uuid: &str,
data: JsonUpcase<FolderData>, data: JsonUpcase<FolderData>,
headers: Headers, headers: Headers,
conn: DbConn, conn: DbConn,
@ -68,7 +68,7 @@ async fn post_folder(
#[put("/folders/<uuid>", data = "<data>")] #[put("/folders/<uuid>", data = "<data>")]
async fn put_folder( async fn put_folder(
uuid: String, uuid: &str,
data: JsonUpcase<FolderData>, data: JsonUpcase<FolderData>,
headers: Headers, headers: Headers,
mut conn: DbConn, mut conn: DbConn,
@ -76,7 +76,7 @@ async fn put_folder(
) -> JsonResult { ) -> JsonResult {
let data: FolderData = data.into_inner().data; 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, Some(folder) => folder,
_ => err!("Invalid folder"), _ => err!("Invalid folder"),
}; };
@ -94,13 +94,13 @@ async fn put_folder(
} }
#[post("/folders/<uuid>/delete")] #[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_folder(uuid, headers, conn, nt).await
} }
#[delete("/folders/<uuid>")] #[delete("/folders/<uuid>")]
async fn delete_folder(uuid: String, headers: Headers, mut conn: DbConn, nt: Notify<'_>) -> EmptyResult { 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 { let folder = match Folder::find_by_uuid(uuid, &mut conn).await {
Some(folder) => folder, Some(folder) => folder,
_ => err!("Invalid folder"), _ => err!("Invalid folder"),
}; };

@ -58,7 +58,7 @@ use crate::{
}; };
#[put("/devices/identifier/<uuid>/clear-token")] #[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 // This endpoint doesn't have auth header
let _ = uuid; let _ = uuid;
@ -71,7 +71,7 @@ fn clear_device_token(uuid: String) -> &'static str {
} }
#[put("/devices/identifier/<uuid>/token", data = "<data>")] #[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; let _data: Value = data.into_inner().data;
// Data has a single string value "PushToken" // Data has a single string value "PushToken"
let _ = uuid; let _ = uuid;
@ -170,7 +170,7 @@ async fn put_eq_domains(
} }
#[get("/hibp/breach?<username>")] #[get("/hibp/breach?<username>")]
async fn hibp_breach(username: String) -> JsonResult { async fn hibp_breach(username: &str) -> JsonResult {
let url = format!( let url = format!(
"https://haveibeenpwned.com/api/v3/breachedaccount/{username}?truncateResponse=false&includeUnverified=false" "https://haveibeenpwned.com/api/v3/breachedaccount/{username}?truncateResponse=false&includeUnverified=false"
); );

File diff suppressed because it is too large Load Diff

@ -154,8 +154,8 @@ async fn get_sends(headers: Headers, mut conn: DbConn) -> Json<Value> {
} }
#[get("/sends/<uuid>")] #[get("/sends/<uuid>")]
async fn get_send(uuid: String, headers: Headers, mut conn: DbConn) -> JsonResult { async fn get_send(uuid: &str, headers: Headers, mut conn: DbConn) -> JsonResult {
let send = match Send::find_by_uuid(&uuid, &mut conn).await { let send = match Send::find_by_uuid(uuid, &mut conn).await {
Some(send) => send, Some(send) => send,
None => err!("Send not found"), 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 // 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>")] #[post("/sends/<send_uuid>/file/<file_id>", format = "multipart/form-data", data = "<data>")]
async fn post_send_file_v2_data( async fn post_send_file_v2_data(
send_uuid: String, send_uuid: &str,
file_id: String, file_id: &str,
data: Form<UploadDataV2<'_>>, data: Form<UploadDataV2<'_>>,
headers: Headers, headers: Headers,
mut conn: DbConn, mut conn: DbConn,
@ -326,9 +326,9 @@ async fn post_send_file_v2_data(
let mut data = data.into_inner(); let mut data = data.into_inner();
if let Some(send) = Send::find_by_uuid(&send_uuid, &mut conn).await { 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 folder_path = tokio::fs::canonicalize(&CONFIG.sends_folder()).await?.join(send_uuid);
let file_path = folder_path.join(&file_id); let file_path = folder_path.join(file_id);
tokio::fs::create_dir_all(&folder_path).await?; tokio::fs::create_dir_all(&folder_path).await?;
if let Err(_err) = data.data.persist_to(&file_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>")] #[post("/sends/access/<access_id>", data = "<data>")]
async fn post_access( async fn post_access(
access_id: String, access_id: &str,
data: JsonUpcase<SendAccessData>, data: JsonUpcase<SendAccessData>,
mut conn: DbConn, mut conn: DbConn,
ip: ClientIp, ip: ClientIp,
nt: Notify<'_>, nt: Notify<'_>,
) -> JsonResult { ) -> 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, Some(s) => s,
None => err_code!(SEND_INACCESSIBLE_MSG, 404), 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>")] #[post("/sends/<send_id>/access/file/<file_id>", data = "<data>")]
async fn post_access_file( async fn post_access_file(
send_id: String, send_id: &str,
file_id: String, file_id: &str,
data: JsonUpcase<SendAccessData>, data: JsonUpcase<SendAccessData>,
host: Host, host: Host,
mut conn: DbConn, mut conn: DbConn,
nt: Notify<'_>, nt: Notify<'_>,
) -> JsonResult { ) -> 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, Some(s) => s,
None => err_code!(SEND_INACCESSIBLE_MSG, 404), 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; 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); let token = crate::auth::encode_jwt(&token_claims);
Ok(Json(json!({ Ok(Json(json!({
"Object": "send-fileDownload", "Object": "send-fileDownload",
@ -460,8 +460,8 @@ async fn post_access_file(
} }
#[get("/sends/<send_id>/<file_id>?<t>")] #[get("/sends/<send_id>/<file_id>?<t>")]
async fn download_send(send_id: SafeString, file_id: SafeString, t: String) -> Option<NamedFile> { async fn download_send(send_id: SafeString, file_id: SafeString, t: &str) -> Option<NamedFile> {
if let Ok(claims) = crate::auth::decode_send(&t) { if let Ok(claims) = crate::auth::decode_send(t) {
if claims.sub == format!("{send_id}/{file_id}") { if claims.sub == format!("{send_id}/{file_id}") {
return NamedFile::open(Path::new(&CONFIG.sends_folder()).join(send_id).join(file_id)).await.ok(); 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>")] #[put("/sends/<id>", data = "<data>")]
async fn put_send( async fn put_send(
id: String, id: &str,
data: JsonUpcase<SendData>, data: JsonUpcase<SendData>,
headers: Headers, headers: Headers,
mut conn: DbConn, mut conn: DbConn,
@ -482,7 +482,7 @@ async fn put_send(
let data: SendData = data.into_inner().data; let data: SendData = data.into_inner().data;
enforce_disable_hide_email_policy(&data, &headers, &mut conn).await?; 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, Some(s) => s,
None => err!("Send not found"), None => err!("Send not found"),
}; };
@ -536,8 +536,8 @@ async fn put_send(
} }
#[delete("/sends/<id>")] #[delete("/sends/<id>")]
async fn delete_send(id: String, headers: Headers, mut conn: DbConn, nt: Notify<'_>) -> EmptyResult { 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 { let send = match Send::find_by_uuid(id, &mut conn).await {
Some(s) => s, Some(s) => s,
None => err!("Send not found"), 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")] #[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?; 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, Some(s) => s,
None => err!("Send not found"), None => err!("Send not found"),
}; };

@ -97,15 +97,15 @@ async fn icon_redirect(domain: &str, template: &str) -> Option<Redirect> {
} }
#[get("/<domain>/icon.png")] #[get("/<domain>/icon.png")]
async fn icon_external(domain: String) -> Option<Redirect> { async fn icon_external(domain: &str) -> Option<Redirect> {
icon_redirect(&domain, &CONFIG._icon_service_url()).await icon_redirect(domain, &CONFIG._icon_service_url()).await
} }
#[get("/<domain>/icon.png")] #[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"); 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); warn!("Invalid domain: {}", domain);
return Cached::ttl( return Cached::ttl(
(ContentType::new("image", "png"), FALLBACK_ICON.to_vec()), (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)) => { Some((icon, icon_type)) => {
Cached::ttl((ContentType::new("image", icon_type), icon), CONFIG.icon_cache_ttl(), true) Cached::ttl((ContentType::new("image", icon_type), icon), CONFIG.icon_cache_ttl(), true)
} }

@ -111,8 +111,8 @@ fn alive_head(_conn: DbConn) -> EmptyResult {
} }
#[get("/vw_static/<filename>")] #[get("/vw_static/<filename>")]
pub fn static_files(filename: String) -> Result<(ContentType, &'static [u8]), Error> { pub fn static_files(filename: &str) -> Result<(ContentType, &'static [u8]), Error> {
match filename.as_ref() { match filename {
"404.png" => Ok((ContentType::PNG, include_bytes!("../static/images/404.png"))), "404.png" => Ok((ContentType::PNG, include_bytes!("../static/images/404.png"))),
"mail-github.png" => Ok((ContentType::PNG, include_bytes!("../static/images/mail-github.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"))), "logo-gray.png" => Ok((ContentType::PNG, include_bytes!("../static/images/logo-gray.png"))),

@ -443,32 +443,34 @@ pub struct OrgHeaders {
pub ip: ClientIp, 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] #[rocket::async_trait]
impl<'r> FromRequest<'r> for OrgHeaders { impl<'r> FromRequest<'r> for OrgHeaders {
type Error = &'static str; type Error = &'static str;
async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Self::Error> { async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Self::Error> {
let headers = try_outcome!(Headers::from_request(request).await); 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) => { Some(org_id) => {
let mut conn = match DbConn::from_request(request).await { let mut conn = match DbConn::from_request(request).await {
Outcome::Success(conn) => conn, Outcome::Success(conn) => conn,
@ -476,7 +478,7 @@ impl<'r> FromRequest<'r> for OrgHeaders {
}; };
let user = headers.user; 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) => { Some(user) => {
if user.status == UserOrgStatus::Confirmed as i32 { if user.status == UserOrgStatus::Confirmed as i32 {
user user
@ -500,7 +502,7 @@ impl<'r> FromRequest<'r> for OrgHeaders {
} }
}, },
org_user, org_user,
org_id, org_id: String::from(org_id),
ip: headers.ip, ip: headers.ip,
}) })
} }

@ -573,8 +573,8 @@ async fn send_email(address: &str, subject: &str, body_html: String, body_text:
let smtp_from = &CONFIG.smtp_from(); let smtp_from = &CONFIG.smtp_from();
let body = if CONFIG.smtp_embed_images() { 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 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".to_string()).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::alternative().singlepart(SinglePart::plain(body_text)).multipart(
MultiPart::related() MultiPart::related()
.singlepart(SinglePart::html(body_html)) .singlepart(SinglePart::html(body_html))

@ -231,7 +231,7 @@ impl<'r> FromParam<'r> for SafeString {
// Log all the routes from the main paths list, and the attachments endpoint // Log all the routes from the main paths list, and the attachments endpoint
// Effectively ignores, any static file route, and the alive 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 // Boolean is extra debug, when true, we ignore the whitelist above and also print the mounts
pub struct BetterLogging(pub bool); pub struct BetterLogging(pub bool);
@ -248,7 +248,7 @@ impl Fairing for BetterLogging {
if self.0 { if self.0 {
info!(target: "routes", "Routes loaded:"); info!(target: "routes", "Routes loaded:");
let mut routes: Vec<_> = rocket.routes().collect(); 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 { for route in routes {
if route.rank < 0 { if route.rank < 0 {
info!(target: "routes", "{:<6} {}", route.method, route.uri); info!(target: "routes", "{:<6} {}", route.method, route.uri);

Loading…
Cancel
Save