diff --git a/src/api/admin.rs b/src/api/admin.rs
index 651e51b1113f8e1ca1cc356791313ed117a48a2a..0fd7c2cf08a846d94e6d0708f221cb2160478034 100644
--- a/src/api/admin.rs
+++ b/src/api/admin.rs
@@ -369,7 +369,7 @@ 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, ip: ClientIp) -> EmptyResult {
+async fn delete_user(uuid: String, 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
@@ -383,7 +383,7 @@ async fn delete_user(uuid: String, _token: AdminToken, mut conn: DbConn, ip: Cli
             user_org.org_uuid,
             String::from(ACTING_ADMIN_USER),
             14, // Use UnknownBrowser type
-            &ip.ip,
+            &token.ip.ip,
             &mut conn,
         )
         .await;
@@ -443,12 +443,7 @@ struct UserOrgTypeData {
 }
 
 #[post("/users/org_type", data = "<data>")]
-async fn update_user_org_type(
-    data: Json<UserOrgTypeData>,
-    _token: AdminToken,
-    mut conn: DbConn,
-    ip: ClientIp,
-) -> EmptyResult {
+async fn update_user_org_type(data: Json<UserOrgTypeData>, token: AdminToken, mut conn: DbConn) -> EmptyResult {
     let data: UserOrgTypeData = data.into_inner();
 
     let mut user_to_edit =
@@ -489,7 +484,7 @@ async fn update_user_org_type(
         data.org_uuid,
         String::from(ACTING_ADMIN_USER),
         14, // Use UnknownBrowser type
-        &ip.ip,
+        &token.ip.ip,
         &mut conn,
     )
     .await;
@@ -724,15 +719,24 @@ async fn backup_db(_token: AdminToken, mut conn: DbConn) -> EmptyResult {
     }
 }
 
-pub struct AdminToken {}
+pub struct AdminToken {
+    ip: ClientIp,
+}
 
 #[rocket::async_trait]
 impl<'r> FromRequest<'r> for AdminToken {
     type Error = &'static str;
 
     async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Self::Error> {
+        let ip = match ClientIp::from_request(request).await {
+            Outcome::Success(ip) => ip,
+            _ => err_handler!("Error getting Client IP"),
+        };
+
         if CONFIG.disable_admin_token() {
-            Outcome::Success(Self {})
+            Outcome::Success(Self {
+                ip,
+            })
         } else {
             let cookies = request.cookies();
 
@@ -741,19 +745,16 @@ impl<'r> FromRequest<'r> for AdminToken {
                 None => return Outcome::Failure((Status::Unauthorized, "Unauthorized")),
             };
 
-            let ip = match ClientIp::from_request(request).await {
-                Outcome::Success(ip) => ip.ip,
-                _ => err_handler!("Error getting Client IP"),
-            };
-
             if decode_admin(access_token).is_err() {
                 // Remove admin cookie
                 cookies.remove(Cookie::build(COOKIE_NAME, "").path(admin_path()).finish());
-                error!("Invalid or expired admin JWT. IP: {}.", ip);
+                error!("Invalid or expired admin JWT. IP: {}.", &ip.ip);
                 return Outcome::Failure((Status::Unauthorized, "Session expired"));
             }
 
-            Outcome::Success(Self {})
+            Outcome::Success(Self {
+                ip,
+            })
         }
     }
 }
diff --git a/src/api/core/accounts.rs b/src/api/core/accounts.rs
index 67633f0b8b266bad99a01d6ce75a05fb8f926b1d..dee8abd5354db5e7691c187aa8fa963c234c6ae5 100644
--- a/src/api/core/accounts.rs
+++ b/src/api/core/accounts.rs
@@ -6,7 +6,7 @@ use crate::{
     api::{
         core::log_user_event, EmptyResult, JsonResult, JsonUpcase, Notify, NumberOrString, PasswordData, UpdateType,
     },
-    auth::{decode_delete, decode_invite, decode_verify_email, ClientIp, Headers},
+    auth::{decode_delete, decode_invite, decode_verify_email, Headers},
     crypto,
     db::{models::*, DbConn},
     mail, CONFIG,
@@ -305,7 +305,6 @@ async fn post_password(
     data: JsonUpcase<ChangePassData>,
     headers: Headers,
     mut conn: DbConn,
-    ip: ClientIp,
     nt: Notify<'_>,
 ) -> EmptyResult {
     let data: ChangePassData = data.into_inner().data;
@@ -318,7 +317,8 @@ async fn post_password(
     user.password_hint = clean_password_hint(&data.MasterPasswordHint);
     enforce_password_hint_setting(&user.password_hint)?;
 
-    log_user_event(EventType::UserChangedPassword as i32, &user.uuid, headers.device.atype, &ip.ip, &mut conn).await;
+    log_user_event(EventType::UserChangedPassword as i32, &user.uuid, headers.device.atype, &headers.ip.ip, &mut conn)
+        .await;
 
     user.set_password(
         &data.NewMasterPasswordHash,
@@ -414,13 +414,7 @@ struct KeyData {
 }
 
 #[post("/accounts/key", data = "<data>")]
-async fn post_rotatekey(
-    data: JsonUpcase<KeyData>,
-    headers: Headers,
-    mut conn: DbConn,
-    ip: ClientIp,
-    nt: Notify<'_>,
-) -> EmptyResult {
+async fn post_rotatekey(data: JsonUpcase<KeyData>, headers: Headers, mut conn: DbConn, nt: Notify<'_>) -> EmptyResult {
     let data: KeyData = data.into_inner().data;
 
     if !headers.user.check_valid_password(&data.MasterPasswordHash) {
@@ -466,7 +460,7 @@ async fn post_rotatekey(
         // Prevent triggering cipher updates via WebSockets by settings UpdateType::None
         // The user sessions are invalidated because all the ciphers were re-encrypted and thus triggering an update could cause issues.
         // We force the users to logout after the user has been saved to try and prevent these issues.
-        update_cipher_from_data(&mut saved_cipher, cipher_data, &headers, false, &mut conn, &ip, &nt, UpdateType::None)
+        update_cipher_from_data(&mut saved_cipher, cipher_data, &headers, false, &mut conn, &nt, UpdateType::None)
             .await?
     }
 
diff --git a/src/api/core/ciphers.rs b/src/api/core/ciphers.rs
index 14d445978952a782ae79143c1aba11c638da8a03..67e2ae39f4f4dd05e0b0bc6c7955fbe7e5128176 100644
--- a/src/api/core/ciphers.rs
+++ b/src/api/core/ciphers.rs
@@ -11,7 +11,7 @@ use serde_json::Value;
 
 use crate::{
     api::{self, core::log_event, EmptyResult, JsonResult, JsonUpcase, Notify, PasswordData, UpdateType},
-    auth::{ClientIp, Headers},
+    auth::Headers,
     crypto,
     db::{models::*, DbConn, DbPool},
     CONFIG,
@@ -263,10 +263,9 @@ async fn post_ciphers_admin(
     data: JsonUpcase<ShareCipherData>,
     headers: Headers,
     conn: DbConn,
-    ip: ClientIp,
     nt: Notify<'_>,
 ) -> JsonResult {
-    post_ciphers_create(data, headers, conn, ip, nt).await
+    post_ciphers_create(data, headers, conn, nt).await
 }
 
 /// Called when creating a new org-owned cipher, or cloning a cipher (whether
@@ -277,7 +276,6 @@ async fn post_ciphers_create(
     data: JsonUpcase<ShareCipherData>,
     headers: Headers,
     mut conn: DbConn,
-    ip: ClientIp,
     nt: Notify<'_>,
 ) -> JsonResult {
     let mut data: ShareCipherData = data.into_inner().data;
@@ -305,18 +303,12 @@ async fn post_ciphers_create(
     // or otherwise), we can just ignore this field entirely.
     data.Cipher.LastKnownRevisionDate = None;
 
-    share_cipher_by_uuid(&cipher.uuid, data, &headers, &mut conn, &ip, &nt).await
+    share_cipher_by_uuid(&cipher.uuid, data, &headers, &mut conn, &nt).await
 }
 
 /// Called when creating a new user-owned cipher.
 #[post("/ciphers", data = "<data>")]
-async fn post_ciphers(
-    data: JsonUpcase<CipherData>,
-    headers: Headers,
-    mut conn: DbConn,
-    ip: ClientIp,
-    nt: Notify<'_>,
-) -> JsonResult {
+async fn post_ciphers(data: JsonUpcase<CipherData>, headers: Headers, mut conn: DbConn, nt: Notify<'_>) -> JsonResult {
     let mut data: CipherData = data.into_inner().data;
 
     // The web/browser clients set this field to null as expected, but the
@@ -326,8 +318,7 @@ async fn post_ciphers(
     data.LastKnownRevisionDate = None;
 
     let mut cipher = Cipher::new(data.Type, data.Name.clone());
-    update_cipher_from_data(&mut cipher, data, &headers, false, &mut conn, &ip, &nt, UpdateType::SyncCipherCreate)
-        .await?;
+    update_cipher_from_data(&mut cipher, data, &headers, false, &mut conn, &nt, UpdateType::SyncCipherCreate).await?;
 
     Ok(Json(cipher.to_json(&headers.host, &headers.user.uuid, None, CipherSyncType::User, &mut conn).await))
 }
@@ -354,14 +345,12 @@ async fn enforce_personal_ownership_policy(
     Ok(())
 }
 
-#[allow(clippy::too_many_arguments)]
 pub async fn update_cipher_from_data(
     cipher: &mut Cipher,
     data: CipherData,
     headers: &Headers,
     shared_to_collection: bool,
     conn: &mut DbConn,
-    ip: &ClientIp,
     nt: &Notify<'_>,
     ut: UpdateType,
 ) -> EmptyResult {
@@ -517,7 +506,7 @@ pub async fn update_cipher_from_data(
                 String::from(org_uuid),
                 headers.user.uuid.clone(),
                 headers.device.atype,
-                &ip.ip,
+                &headers.ip.ip,
                 conn,
             )
             .await;
@@ -551,7 +540,6 @@ async fn post_ciphers_import(
     data: JsonUpcase<ImportData>,
     headers: Headers,
     mut conn: DbConn,
-    ip: ClientIp,
     nt: Notify<'_>,
 ) -> EmptyResult {
     enforce_personal_ownership_policy(None, &headers, &mut conn).await?;
@@ -586,8 +574,7 @@ async fn post_ciphers_import(
         cipher_data.FolderId = folder_uuid;
 
         let mut cipher = Cipher::new(cipher_data.Type, cipher_data.Name.clone());
-        update_cipher_from_data(&mut cipher, cipher_data, &headers, false, &mut conn, &ip, &nt, UpdateType::None)
-            .await?;
+        update_cipher_from_data(&mut cipher, cipher_data, &headers, false, &mut conn, &nt, UpdateType::None).await?;
     }
 
     let mut user = headers.user;
@@ -603,10 +590,9 @@ async fn put_cipher_admin(
     data: JsonUpcase<CipherData>,
     headers: Headers,
     conn: DbConn,
-    ip: ClientIp,
     nt: Notify<'_>,
 ) -> JsonResult {
-    put_cipher(uuid, data, headers, conn, ip, nt).await
+    put_cipher(uuid, data, headers, conn, nt).await
 }
 
 #[post("/ciphers/<uuid>/admin", data = "<data>")]
@@ -615,10 +601,9 @@ async fn post_cipher_admin(
     data: JsonUpcase<CipherData>,
     headers: Headers,
     conn: DbConn,
-    ip: ClientIp,
     nt: Notify<'_>,
 ) -> JsonResult {
-    post_cipher(uuid, data, headers, conn, ip, nt).await
+    post_cipher(uuid, data, headers, conn, nt).await
 }
 
 #[post("/ciphers/<uuid>", data = "<data>")]
@@ -627,10 +612,9 @@ async fn post_cipher(
     data: JsonUpcase<CipherData>,
     headers: Headers,
     conn: DbConn,
-    ip: ClientIp,
     nt: Notify<'_>,
 ) -> JsonResult {
-    put_cipher(uuid, data, headers, conn, ip, nt).await
+    put_cipher(uuid, data, headers, conn, nt).await
 }
 
 #[put("/ciphers/<uuid>", data = "<data>")]
@@ -639,7 +623,6 @@ async fn put_cipher(
     data: JsonUpcase<CipherData>,
     headers: Headers,
     mut conn: DbConn,
-    ip: ClientIp,
     nt: Notify<'_>,
 ) -> JsonResult {
     let data: CipherData = data.into_inner().data;
@@ -658,8 +641,7 @@ async fn put_cipher(
         err!("Cipher is not write accessible")
     }
 
-    update_cipher_from_data(&mut cipher, data, &headers, false, &mut conn, &ip, &nt, UpdateType::SyncCipherUpdate)
-        .await?;
+    update_cipher_from_data(&mut cipher, data, &headers, false, &mut conn, &nt, UpdateType::SyncCipherUpdate).await?;
 
     Ok(Json(cipher.to_json(&headers.host, &headers.user.uuid, None, CipherSyncType::User, &mut conn).await))
 }
@@ -720,9 +702,8 @@ async fn put_collections_update(
     data: JsonUpcase<CollectionsAdminData>,
     headers: Headers,
     conn: DbConn,
-    ip: ClientIp,
 ) -> EmptyResult {
-    post_collections_admin(uuid, data, headers, conn, ip).await
+    post_collections_admin(uuid, data, headers, conn).await
 }
 
 #[post("/ciphers/<uuid>/collections", data = "<data>")]
@@ -731,9 +712,8 @@ async fn post_collections_update(
     data: JsonUpcase<CollectionsAdminData>,
     headers: Headers,
     conn: DbConn,
-    ip: ClientIp,
 ) -> EmptyResult {
-    post_collections_admin(uuid, data, headers, conn, ip).await
+    post_collections_admin(uuid, data, headers, conn).await
 }
 
 #[put("/ciphers/<uuid>/collections-admin", data = "<data>")]
@@ -742,9 +722,8 @@ async fn put_collections_admin(
     data: JsonUpcase<CollectionsAdminData>,
     headers: Headers,
     conn: DbConn,
-    ip: ClientIp,
 ) -> EmptyResult {
-    post_collections_admin(uuid, data, headers, conn, ip).await
+    post_collections_admin(uuid, data, headers, conn).await
 }
 
 #[post("/ciphers/<uuid>/collections-admin", data = "<data>")]
@@ -753,7 +732,6 @@ async fn post_collections_admin(
     data: JsonUpcase<CollectionsAdminData>,
     headers: Headers,
     mut conn: DbConn,
-    ip: ClientIp,
 ) -> EmptyResult {
     let data: CollectionsAdminData = data.into_inner().data;
 
@@ -795,7 +773,7 @@ async fn post_collections_admin(
         cipher.organization_uuid.unwrap(),
         headers.user.uuid.clone(),
         headers.device.atype,
-        &ip.ip,
+        &headers.ip.ip,
         &mut conn,
     )
     .await;
@@ -816,12 +794,11 @@ async fn post_cipher_share(
     data: JsonUpcase<ShareCipherData>,
     headers: Headers,
     mut conn: DbConn,
-    ip: ClientIp,
     nt: Notify<'_>,
 ) -> JsonResult {
     let data: ShareCipherData = data.into_inner().data;
 
-    share_cipher_by_uuid(&uuid, data, &headers, &mut conn, &ip, &nt).await
+    share_cipher_by_uuid(&uuid, data, &headers, &mut conn, &nt).await
 }
 
 #[put("/ciphers/<uuid>/share", data = "<data>")]
@@ -830,12 +807,11 @@ async fn put_cipher_share(
     data: JsonUpcase<ShareCipherData>,
     headers: Headers,
     mut conn: DbConn,
-    ip: ClientIp,
     nt: Notify<'_>,
 ) -> JsonResult {
     let data: ShareCipherData = data.into_inner().data;
 
-    share_cipher_by_uuid(&uuid, data, &headers, &mut conn, &ip, &nt).await
+    share_cipher_by_uuid(&uuid, data, &headers, &mut conn, &nt).await
 }
 
 #[derive(Deserialize)]
@@ -850,7 +826,6 @@ async fn put_cipher_share_selected(
     data: JsonUpcase<ShareSelectedCipherData>,
     headers: Headers,
     mut conn: DbConn,
-    ip: ClientIp,
     nt: Notify<'_>,
 ) -> EmptyResult {
     let mut data: ShareSelectedCipherData = data.into_inner().data;
@@ -878,7 +853,7 @@ async fn put_cipher_share_selected(
         };
 
         match shared_cipher_data.Cipher.Id.take() {
-            Some(id) => share_cipher_by_uuid(&id, shared_cipher_data, &headers, &mut conn, &ip, &nt).await?,
+            Some(id) => share_cipher_by_uuid(&id, shared_cipher_data, &headers, &mut conn, &nt).await?,
             None => err!("Request missing ids field"),
         };
     }
@@ -891,7 +866,6 @@ async fn share_cipher_by_uuid(
     data: ShareCipherData,
     headers: &Headers,
     conn: &mut DbConn,
-    ip: &ClientIp,
     nt: &Notify<'_>,
 ) -> JsonResult {
     let mut cipher = match Cipher::find_by_uuid(uuid, conn).await {
@@ -930,7 +904,7 @@ async fn share_cipher_by_uuid(
         UpdateType::SyncCipherCreate
     };
 
-    update_cipher_from_data(&mut cipher, data.Cipher, headers, shared_to_collection, conn, ip, nt, ut).await?;
+    update_cipher_from_data(&mut cipher, data.Cipher, headers, shared_to_collection, conn, nt, ut).await?;
 
     Ok(Json(cipher.to_json(&headers.host, &headers.user.uuid, None, CipherSyncType::User, conn).await))
 }
@@ -1025,7 +999,6 @@ async fn save_attachment(
     data: Form<UploadData<'_>>,
     headers: &Headers,
     mut conn: DbConn,
-    ip: ClientIp,
     nt: Notify<'_>,
 ) -> Result<(Cipher, DbConn), crate::error::Error> {
     let cipher = match Cipher::find_by_uuid(&cipher_uuid, &mut conn).await {
@@ -1144,7 +1117,7 @@ async fn save_attachment(
             String::from(org_uuid),
             headers.user.uuid.clone(),
             headers.device.atype,
-            &ip.ip,
+            &headers.ip.ip,
             &mut conn,
         )
         .await;
@@ -1164,7 +1137,6 @@ async fn post_attachment_v2_data(
     data: Form<UploadData<'_>>,
     headers: Headers,
     mut conn: DbConn,
-    ip: ClientIp,
     nt: Notify<'_>,
 ) -> EmptyResult {
     let attachment = match Attachment::find_by_id(&attachment_id, &mut conn).await {
@@ -1173,7 +1145,7 @@ async fn post_attachment_v2_data(
         None => err!("Attachment doesn't exist"),
     };
 
-    save_attachment(attachment, uuid, data, &headers, conn, ip, nt).await?;
+    save_attachment(attachment, uuid, data, &headers, conn, nt).await?;
 
     Ok(())
 }
@@ -1185,14 +1157,13 @@ async fn post_attachment(
     data: Form<UploadData<'_>>,
     headers: Headers,
     conn: DbConn,
-    ip: ClientIp,
     nt: Notify<'_>,
 ) -> JsonResult {
     // Setting this as None signifies to save_attachment() that it should create
     // the attachment database record as well as saving the data to disk.
     let attachment = None;
 
-    let (cipher, mut conn) = save_attachment(attachment, uuid, data, &headers, conn, ip, nt).await?;
+    let (cipher, mut conn) = save_attachment(attachment, uuid, data, &headers, conn, nt).await?;
 
     Ok(Json(cipher.to_json(&headers.host, &headers.user.uuid, None, CipherSyncType::User, &mut conn).await))
 }
@@ -1203,10 +1174,9 @@ async fn post_attachment_admin(
     data: Form<UploadData<'_>>,
     headers: Headers,
     conn: DbConn,
-    ip: ClientIp,
     nt: Notify<'_>,
 ) -> JsonResult {
-    post_attachment(uuid, data, headers, conn, ip, nt).await
+    post_attachment(uuid, data, headers, conn, nt).await
 }
 
 #[post("/ciphers/<uuid>/attachment/<attachment_id>/share", format = "multipart/form-data", data = "<data>")]
@@ -1216,11 +1186,10 @@ async fn post_attachment_share(
     data: Form<UploadData<'_>>,
     headers: Headers,
     mut conn: DbConn,
-    ip: ClientIp,
     nt: Notify<'_>,
 ) -> JsonResult {
-    _delete_cipher_attachment_by_id(&uuid, &attachment_id, &headers, &mut conn, &ip, &nt).await?;
-    post_attachment(uuid, data, headers, conn, ip, 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")]
@@ -1229,10 +1198,9 @@ async fn delete_attachment_post_admin(
     attachment_id: String,
     headers: Headers,
     conn: DbConn,
-    ip: ClientIp,
     nt: Notify<'_>,
 ) -> EmptyResult {
-    delete_attachment(uuid, attachment_id, headers, conn, ip, nt).await
+    delete_attachment(uuid, attachment_id, headers, conn, nt).await
 }
 
 #[post("/ciphers/<uuid>/attachment/<attachment_id>/delete")]
@@ -1241,10 +1209,9 @@ async fn delete_attachment_post(
     attachment_id: String,
     headers: Headers,
     conn: DbConn,
-    ip: ClientIp,
     nt: Notify<'_>,
 ) -> EmptyResult {
-    delete_attachment(uuid, attachment_id, headers, conn, ip, nt).await
+    delete_attachment(uuid, attachment_id, headers, conn, nt).await
 }
 
 #[delete("/ciphers/<uuid>/attachment/<attachment_id>")]
@@ -1253,10 +1220,9 @@ async fn delete_attachment(
     attachment_id: String,
     headers: Headers,
     mut conn: DbConn,
-    ip: ClientIp,
     nt: Notify<'_>,
 ) -> EmptyResult {
-    _delete_cipher_attachment_by_id(&uuid, &attachment_id, &headers, &mut conn, &ip, &nt).await
+    _delete_cipher_attachment_by_id(&uuid, &attachment_id, &headers, &mut conn, &nt).await
 }
 
 #[delete("/ciphers/<uuid>/attachment/<attachment_id>/admin")]
@@ -1265,70 +1231,44 @@ async fn delete_attachment_admin(
     attachment_id: String,
     headers: Headers,
     mut conn: DbConn,
-    ip: ClientIp,
     nt: Notify<'_>,
 ) -> EmptyResult {
-    _delete_cipher_attachment_by_id(&uuid, &attachment_id, &headers, &mut conn, &ip, &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,
-    ip: ClientIp,
-    nt: Notify<'_>,
-) -> EmptyResult {
-    _delete_cipher_by_uuid(&uuid, &headers, &mut conn, false, &ip, &nt).await // permanent 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
+    // permanent delete
 }
 
 #[post("/ciphers/<uuid>/delete-admin")]
-async fn delete_cipher_post_admin(
-    uuid: String,
-    headers: Headers,
-    mut conn: DbConn,
-    ip: ClientIp,
-    nt: Notify<'_>,
-) -> EmptyResult {
-    _delete_cipher_by_uuid(&uuid, &headers, &mut conn, false, &ip, &nt).await // permanent delete
+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
+    // permanent delete
 }
 
 #[put("/ciphers/<uuid>/delete")]
-async fn delete_cipher_put(
-    uuid: String,
-    headers: Headers,
-    mut conn: DbConn,
-    ip: ClientIp,
-    nt: Notify<'_>,
-) -> EmptyResult {
-    _delete_cipher_by_uuid(&uuid, &headers, &mut conn, true, &ip, &nt).await // soft 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
+    // soft delete
 }
 
 #[put("/ciphers/<uuid>/delete-admin")]
-async fn delete_cipher_put_admin(
-    uuid: String,
-    headers: Headers,
-    mut conn: DbConn,
-    ip: ClientIp,
-    nt: Notify<'_>,
-) -> EmptyResult {
-    _delete_cipher_by_uuid(&uuid, &headers, &mut conn, true, &ip, &nt).await
+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
 }
 
 #[delete("/ciphers/<uuid>")]
-async fn delete_cipher(uuid: String, headers: Headers, mut conn: DbConn, ip: ClientIp, nt: Notify<'_>) -> EmptyResult {
-    _delete_cipher_by_uuid(&uuid, &headers, &mut conn, false, &ip, &nt).await // permanent delete
+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
+    // permanent delete
 }
 
 #[delete("/ciphers/<uuid>/admin")]
-async fn delete_cipher_admin(
-    uuid: String,
-    headers: Headers,
-    mut conn: DbConn,
-    ip: ClientIp,
-    nt: Notify<'_>,
-) -> EmptyResult {
-    _delete_cipher_by_uuid(&uuid, &headers, &mut conn, false, &ip, &nt).await // permanent delete
+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
+    // permanent delete
 }
 
 #[delete("/ciphers", data = "<data>")]
@@ -1336,10 +1276,9 @@ async fn delete_cipher_selected(
     data: JsonUpcase<Value>,
     headers: Headers,
     conn: DbConn,
-    ip: ClientIp,
     nt: Notify<'_>,
 ) -> EmptyResult {
-    _delete_multiple_ciphers(data, headers, conn, false, ip, nt).await // permanent delete
+    _delete_multiple_ciphers(data, headers, conn, false, nt).await // permanent delete
 }
 
 #[post("/ciphers/delete", data = "<data>")]
@@ -1347,10 +1286,9 @@ async fn delete_cipher_selected_post(
     data: JsonUpcase<Value>,
     headers: Headers,
     conn: DbConn,
-    ip: ClientIp,
     nt: Notify<'_>,
 ) -> EmptyResult {
-    _delete_multiple_ciphers(data, headers, conn, false, ip, nt).await // permanent delete
+    _delete_multiple_ciphers(data, headers, conn, false, nt).await // permanent delete
 }
 
 #[put("/ciphers/delete", data = "<data>")]
@@ -1358,10 +1296,9 @@ async fn delete_cipher_selected_put(
     data: JsonUpcase<Value>,
     headers: Headers,
     conn: DbConn,
-    ip: ClientIp,
     nt: Notify<'_>,
 ) -> EmptyResult {
-    _delete_multiple_ciphers(data, headers, conn, true, ip, nt).await // soft delete
+    _delete_multiple_ciphers(data, headers, conn, true, nt).await // soft delete
 }
 
 #[delete("/ciphers/admin", data = "<data>")]
@@ -1369,10 +1306,9 @@ async fn delete_cipher_selected_admin(
     data: JsonUpcase<Value>,
     headers: Headers,
     conn: DbConn,
-    ip: ClientIp,
     nt: Notify<'_>,
 ) -> EmptyResult {
-    _delete_multiple_ciphers(data, headers, conn, false, ip, nt).await // permanent delete
+    _delete_multiple_ciphers(data, headers, conn, false, nt).await // permanent delete
 }
 
 #[post("/ciphers/delete-admin", data = "<data>")]
@@ -1380,10 +1316,9 @@ async fn delete_cipher_selected_post_admin(
     data: JsonUpcase<Value>,
     headers: Headers,
     conn: DbConn,
-    ip: ClientIp,
     nt: Notify<'_>,
 ) -> EmptyResult {
-    _delete_multiple_ciphers(data, headers, conn, false, ip, nt).await // permanent delete
+    _delete_multiple_ciphers(data, headers, conn, false, nt).await // permanent delete
 }
 
 #[put("/ciphers/delete-admin", data = "<data>")]
@@ -1391,32 +1326,19 @@ async fn delete_cipher_selected_put_admin(
     data: JsonUpcase<Value>,
     headers: Headers,
     conn: DbConn,
-    ip: ClientIp,
     nt: Notify<'_>,
 ) -> EmptyResult {
-    _delete_multiple_ciphers(data, headers, conn, true, ip, nt).await // soft delete
+    _delete_multiple_ciphers(data, headers, conn, true, nt).await // soft delete
 }
 
 #[put("/ciphers/<uuid>/restore")]
-async fn restore_cipher_put(
-    uuid: String,
-    headers: Headers,
-    mut conn: DbConn,
-    ip: ClientIp,
-    nt: Notify<'_>,
-) -> JsonResult {
-    _restore_cipher_by_uuid(&uuid, &headers, &mut conn, &ip, &nt).await
+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
 }
 
 #[put("/ciphers/<uuid>/restore-admin")]
-async fn restore_cipher_put_admin(
-    uuid: String,
-    headers: Headers,
-    mut conn: DbConn,
-    ip: ClientIp,
-    nt: Notify<'_>,
-) -> JsonResult {
-    _restore_cipher_by_uuid(&uuid, &headers, &mut conn, &ip, &nt).await
+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
 }
 
 #[put("/ciphers/restore", data = "<data>")]
@@ -1424,10 +1346,9 @@ async fn restore_cipher_selected(
     data: JsonUpcase<Value>,
     headers: Headers,
     mut conn: DbConn,
-    ip: ClientIp,
     nt: Notify<'_>,
 ) -> JsonResult {
-    _restore_multiple_ciphers(data, &headers, &mut conn, ip, &nt).await
+    _restore_multiple_ciphers(data, &headers, &mut conn, &nt).await
 }
 
 #[derive(Deserialize)]
@@ -1499,7 +1420,6 @@ async fn delete_all(
     data: JsonUpcase<PasswordData>,
     headers: Headers,
     mut conn: DbConn,
-    ip: ClientIp,
     nt: Notify<'_>,
 ) -> EmptyResult {
     let data: PasswordData = data.into_inner().data;
@@ -1527,7 +1447,7 @@ async fn delete_all(
                             org_data.org_id.clone(),
                             user.uuid,
                             headers.device.atype,
-                            &ip.ip,
+                            &headers.ip.ip,
                             &mut conn,
                         )
                         .await;
@@ -1563,7 +1483,6 @@ async fn _delete_cipher_by_uuid(
     headers: &Headers,
     conn: &mut DbConn,
     soft_delete: bool,
-    ip: &ClientIp,
     nt: &Notify<'_>,
 ) -> EmptyResult {
     let mut cipher = match Cipher::find_by_uuid(uuid, conn).await {
@@ -1602,8 +1521,16 @@ async fn _delete_cipher_by_uuid(
             false => EventType::CipherDeleted as i32,
         };
 
-        log_event(event_type, &cipher.uuid, org_uuid, headers.user.uuid.clone(), headers.device.atype, &ip.ip, conn)
-            .await;
+        log_event(
+            event_type,
+            &cipher.uuid,
+            org_uuid,
+            headers.user.uuid.clone(),
+            headers.device.atype,
+            &headers.ip.ip,
+            conn,
+        )
+        .await;
     }
 
     Ok(())
@@ -1614,7 +1541,6 @@ async fn _delete_multiple_ciphers(
     headers: Headers,
     mut conn: DbConn,
     soft_delete: bool,
-    ip: ClientIp,
     nt: Notify<'_>,
 ) -> EmptyResult {
     let data: Value = data.into_inner().data;
@@ -1628,7 +1554,7 @@ async fn _delete_multiple_ciphers(
     };
 
     for uuid in uuids {
-        if let error @ Err(_) = _delete_cipher_by_uuid(uuid, &headers, &mut conn, soft_delete, &ip, &nt).await {
+        if let error @ Err(_) = _delete_cipher_by_uuid(uuid, &headers, &mut conn, soft_delete, &nt).await {
             return error;
         };
     }
@@ -1636,13 +1562,7 @@ async fn _delete_multiple_ciphers(
     Ok(())
 }
 
-async fn _restore_cipher_by_uuid(
-    uuid: &str,
-    headers: &Headers,
-    conn: &mut DbConn,
-    ip: &ClientIp,
-    nt: &Notify<'_>,
-) -> JsonResult {
+async fn _restore_cipher_by_uuid(uuid: &str, headers: &Headers, conn: &mut DbConn, nt: &Notify<'_>) -> JsonResult {
     let mut cipher = match Cipher::find_by_uuid(uuid, conn).await {
         Some(cipher) => cipher,
         None => err!("Cipher doesn't exist"),
@@ -1669,7 +1589,7 @@ async fn _restore_cipher_by_uuid(
             String::from(org_uuid),
             headers.user.uuid.clone(),
             headers.device.atype,
-            &ip.ip,
+            &headers.ip.ip,
             conn,
         )
         .await;
@@ -1682,7 +1602,6 @@ async fn _restore_multiple_ciphers(
     data: JsonUpcase<Value>,
     headers: &Headers,
     conn: &mut DbConn,
-    ip: ClientIp,
     nt: &Notify<'_>,
 ) -> JsonResult {
     let data: Value = data.into_inner().data;
@@ -1697,7 +1616,7 @@ async fn _restore_multiple_ciphers(
 
     let mut ciphers: Vec<Value> = Vec::new();
     for uuid in uuids {
-        match _restore_cipher_by_uuid(uuid, headers, conn, &ip, nt).await {
+        match _restore_cipher_by_uuid(uuid, headers, conn, nt).await {
             Ok(json) => ciphers.push(json.into_inner()),
             err => return err,
         }
@@ -1715,7 +1634,6 @@ async fn _delete_cipher_attachment_by_id(
     attachment_id: &str,
     headers: &Headers,
     conn: &mut DbConn,
-    ip: &ClientIp,
     nt: &Notify<'_>,
 ) -> EmptyResult {
     let attachment = match Attachment::find_by_id(attachment_id, conn).await {
@@ -1752,7 +1670,7 @@ async fn _delete_cipher_attachment_by_id(
             org_uuid,
             headers.user.uuid.clone(),
             headers.device.atype,
-            &ip.ip,
+            &headers.ip.ip,
             conn,
         )
         .await;
diff --git a/src/api/core/events.rs b/src/api/core/events.rs
index 4310271210fe7391458319e569cf9b5b9428a4ed..fab13e40e1ed9b1834e8aea684ef72ee31e0b8c8 100644
--- a/src/api/core/events.rs
+++ b/src/api/core/events.rs
@@ -6,7 +6,7 @@ use serde_json::Value;
 
 use crate::{
     api::{EmptyResult, JsonResult, JsonUpcaseVec},
-    auth::{AdminHeaders, ClientIp, Headers},
+    auth::{AdminHeaders, Headers},
     db::{
         models::{Cipher, Event, UserOrganization},
         DbConn, DbPool,
@@ -161,12 +161,7 @@ struct EventCollection {
 // https://github.com/bitwarden/server/blob/8a22c0479e987e756ce7412c48a732f9002f0a2d/src/Events/Controllers/CollectController.cs
 // https://github.com/bitwarden/server/blob/8a22c0479e987e756ce7412c48a732f9002f0a2d/src/Core/Services/Implementations/EventService.cs
 #[post("/collect", format = "application/json", data = "<data>")]
-async fn post_events_collect(
-    data: JsonUpcaseVec<EventCollection>,
-    headers: Headers,
-    mut conn: DbConn,
-    ip: ClientIp,
-) -> EmptyResult {
+async fn post_events_collect(data: JsonUpcaseVec<EventCollection>, headers: Headers, mut conn: DbConn) -> EmptyResult {
     if !CONFIG.org_events_enabled() {
         return Ok(());
     }
@@ -180,7 +175,7 @@ async fn post_events_collect(
                     &headers.user.uuid,
                     headers.device.atype,
                     Some(event_date),
-                    &ip.ip,
+                    &headers.ip.ip,
                     &mut conn,
                 )
                 .await;
@@ -194,7 +189,7 @@ async fn post_events_collect(
                         &headers.user.uuid,
                         headers.device.atype,
                         Some(event_date),
-                        &ip.ip,
+                        &headers.ip.ip,
                         &mut conn,
                     )
                     .await;
@@ -211,7 +206,7 @@ async fn post_events_collect(
                                 &headers.user.uuid,
                                 headers.device.atype,
                                 Some(event_date),
-                                &ip.ip,
+                                &headers.ip.ip,
                                 &mut conn,
                             )
                             .await;
diff --git a/src/api/core/organizations.rs b/src/api/core/organizations.rs
index c79902a909023aff3de2433ba44d85d3a05787ca..9c46617ab67bbf4d723d796c8ae0a50203558f37 100644
--- a/src/api/core/organizations.rs
+++ b/src/api/core/organizations.rs
@@ -9,7 +9,7 @@ use crate::{
         ApiResult, EmptyResult, JsonResult, JsonUpcase, JsonUpcaseVec, JsonVec, Notify, NumberOrString, PasswordData,
         UpdateType,
     },
-    auth::{decode_invite, AdminHeaders, ClientIp, Headers, ManagerHeaders, ManagerHeadersLoose, OwnerHeaders},
+    auth::{decode_invite, AdminHeaders, Headers, ManagerHeaders, ManagerHeadersLoose, OwnerHeaders},
     db::{models::*, DbConn},
     error::Error,
     mail,
@@ -209,7 +209,7 @@ async fn post_delete_organization(
 }
 
 #[post("/organizations/<org_id>/leave")]
-async fn leave_organization(org_id: String, headers: Headers, mut conn: DbConn, ip: ClientIp) -> EmptyResult {
+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 {
         None => err!("User not part of organization"),
         Some(user_org) => {
@@ -225,7 +225,7 @@ async fn leave_organization(org_id: String, headers: Headers, mut conn: DbConn,
                 org_id,
                 headers.user.uuid.clone(),
                 headers.device.atype,
-                &ip.ip,
+                &headers.ip.ip,
                 &mut conn,
             )
             .await;
@@ -249,9 +249,8 @@ async fn put_organization(
     headers: OwnerHeaders,
     data: JsonUpcase<OrganizationUpdateData>,
     conn: DbConn,
-    ip: ClientIp,
 ) -> JsonResult {
-    post_organization(org_id, headers, data, conn, ip).await
+    post_organization(org_id, headers, data, conn).await
 }
 
 #[post("/organizations/<org_id>", data = "<data>")]
@@ -260,7 +259,6 @@ async fn post_organization(
     headers: OwnerHeaders,
     data: JsonUpcase<OrganizationUpdateData>,
     mut conn: DbConn,
-    ip: ClientIp,
 ) -> JsonResult {
     let data: OrganizationUpdateData = data.into_inner().data;
 
@@ -280,7 +278,7 @@ async fn post_organization(
         org_id.clone(),
         headers.user.uuid.clone(),
         headers.device.atype,
-        &ip.ip,
+        &headers.ip.ip,
         &mut conn,
     )
     .await;
@@ -380,7 +378,6 @@ async fn post_organization_collections(
     headers: ManagerHeadersLoose,
     data: JsonUpcase<NewCollectionData>,
     mut conn: DbConn,
-    ip: ClientIp,
 ) -> JsonResult {
     let data: NewCollectionData = data.into_inner().data;
 
@@ -398,7 +395,7 @@ async fn post_organization_collections(
         org_id,
         headers.user.uuid.clone(),
         headers.device.atype,
-        &ip.ip,
+        &headers.ip.ip,
         &mut conn,
     )
     .await;
@@ -433,9 +430,8 @@ async fn put_organization_collection_update(
     headers: ManagerHeaders,
     data: JsonUpcase<NewCollectionData>,
     conn: DbConn,
-    ip: ClientIp,
 ) -> JsonResult {
-    post_organization_collection_update(org_id, col_id, headers, data, conn, ip).await
+    post_organization_collection_update(org_id, col_id, headers, data, conn).await
 }
 
 #[post("/organizations/<org_id>/collections/<col_id>", data = "<data>")]
@@ -445,7 +441,6 @@ async fn post_organization_collection_update(
     headers: ManagerHeaders,
     data: JsonUpcase<NewCollectionData>,
     mut conn: DbConn,
-    ip: ClientIp,
 ) -> JsonResult {
     let data: NewCollectionData = data.into_inner().data;
 
@@ -472,7 +467,7 @@ async fn post_organization_collection_update(
         org_id,
         headers.user.uuid.clone(),
         headers.device.atype,
-        &ip.ip,
+        &headers.ip.ip,
         &mut conn,
     )
     .await;
@@ -548,7 +543,6 @@ async fn delete_organization_collection(
     col_id: String,
     headers: ManagerHeaders,
     mut conn: DbConn,
-    ip: ClientIp,
 ) -> EmptyResult {
     match Collection::find_by_uuid(&col_id, &mut conn).await {
         None => err!("Collection not found"),
@@ -560,7 +554,7 @@ async fn delete_organization_collection(
                     org_id,
                     headers.user.uuid.clone(),
                     headers.device.atype,
-                    &ip.ip,
+                    &headers.ip.ip,
                     &mut conn,
                 )
                 .await;
@@ -586,9 +580,8 @@ async fn post_organization_collection_delete(
     headers: ManagerHeaders,
     _data: JsonUpcase<DeleteCollectionData>,
     conn: DbConn,
-    ip: ClientIp,
 ) -> EmptyResult {
-    delete_organization_collection(org_id, col_id, headers, conn, ip).await
+    delete_organization_collection(org_id, col_id, headers, conn).await
 }
 
 #[get("/organizations/<org_id>/collections/<coll_id>/details")]
@@ -828,7 +821,6 @@ async fn send_invite(
     data: JsonUpcase<InviteData>,
     headers: AdminHeaders,
     mut conn: DbConn,
-    ip: ClientIp,
 ) -> EmptyResult {
     let data: InviteData = data.into_inner().data;
 
@@ -903,7 +895,7 @@ async fn send_invite(
             org_id.clone(),
             headers.user.uuid.clone(),
             headers.device.atype,
-            &ip.ip,
+            &headers.ip.ip,
             &mut conn,
         )
         .await;
@@ -1101,7 +1093,6 @@ async fn bulk_confirm_invite(
     data: JsonUpcase<Value>,
     headers: AdminHeaders,
     mut conn: DbConn,
-    ip: ClientIp,
     nt: Notify<'_>,
 ) -> Json<Value> {
     let data = data.into_inner().data;
@@ -1112,8 +1103,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, &ip, &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:?}"),
                 };
@@ -1144,12 +1134,11 @@ async fn confirm_invite(
     data: JsonUpcase<Value>,
     headers: AdminHeaders,
     mut conn: DbConn,
-    ip: ClientIp,
     nt: Notify<'_>,
 ) -> 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, &ip, &nt).await
+    _confirm_invite(&org_id, &org_user_id, user_key, &headers, &mut conn, &nt).await
 }
 
 async fn _confirm_invite(
@@ -1158,7 +1147,6 @@ async fn _confirm_invite(
     key: &str,
     headers: &AdminHeaders,
     conn: &mut DbConn,
-    ip: &ClientIp,
     nt: &Notify<'_>,
 ) -> EmptyResult {
     if key.is_empty() || org_user_id.is_empty() {
@@ -1201,7 +1189,7 @@ async fn _confirm_invite(
         String::from(org_id),
         headers.user.uuid.clone(),
         headers.device.atype,
-        &ip.ip,
+        &headers.ip.ip,
         conn,
     )
     .await;
@@ -1264,9 +1252,8 @@ async fn put_organization_user(
     data: JsonUpcase<EditUserData>,
     headers: AdminHeaders,
     conn: DbConn,
-    ip: ClientIp,
 ) -> EmptyResult {
-    edit_user(org_id, org_user_id, data, headers, conn, ip).await
+    edit_user(org_id, org_user_id, data, headers, conn).await
 }
 
 #[post("/organizations/<org_id>/users/<org_user_id>", data = "<data>", rank = 1)]
@@ -1276,7 +1263,6 @@ async fn edit_user(
     data: JsonUpcase<EditUserData>,
     headers: AdminHeaders,
     mut conn: DbConn,
-    ip: ClientIp,
 ) -> EmptyResult {
     let data: EditUserData = data.into_inner().data;
 
@@ -1365,7 +1351,7 @@ async fn edit_user(
         org_id.clone(),
         headers.user.uuid.clone(),
         headers.device.atype,
-        &ip.ip,
+        &headers.ip.ip,
         &mut conn,
     )
     .await;
@@ -1379,14 +1365,13 @@ async fn bulk_delete_user(
     data: JsonUpcase<OrgBulkIds>,
     headers: AdminHeaders,
     mut conn: DbConn,
-    ip: ClientIp,
     nt: Notify<'_>,
 ) -> Json<Value> {
     let data: OrgBulkIds = data.into_inner().data;
 
     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, &ip, &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:?}"),
         };
@@ -1413,10 +1398,9 @@ async fn delete_user(
     org_user_id: String,
     headers: AdminHeaders,
     mut conn: DbConn,
-    ip: ClientIp,
     nt: Notify<'_>,
 ) -> EmptyResult {
-    _delete_user(&org_id, &org_user_id, &headers, &mut conn, &ip, &nt).await
+    _delete_user(&org_id, &org_user_id, &headers, &mut conn, &nt).await
 }
 
 #[post("/organizations/<org_id>/users/<org_user_id>/delete")]
@@ -1425,10 +1409,9 @@ async fn post_delete_user(
     org_user_id: String,
     headers: AdminHeaders,
     mut conn: DbConn,
-    ip: ClientIp,
     nt: Notify<'_>,
 ) -> EmptyResult {
-    _delete_user(&org_id, &org_user_id, &headers, &mut conn, &ip, &nt).await
+    _delete_user(&org_id, &org_user_id, &headers, &mut conn, &nt).await
 }
 
 async fn _delete_user(
@@ -1436,7 +1419,6 @@ async fn _delete_user(
     org_user_id: &str,
     headers: &AdminHeaders,
     conn: &mut DbConn,
-    ip: &ClientIp,
     nt: &Notify<'_>,
 ) -> EmptyResult {
     let user_to_delete = match UserOrganization::find_by_uuid_and_org(org_user_id, org_id, conn).await {
@@ -1461,7 +1443,7 @@ async fn _delete_user(
         String::from(org_id),
         headers.user.uuid.clone(),
         headers.device.atype,
-        &ip.ip,
+        &headers.ip.ip,
         conn,
     )
     .await;
@@ -1536,7 +1518,6 @@ async fn post_org_import(
     data: JsonUpcase<ImportData>,
     headers: AdminHeaders,
     mut conn: DbConn,
-    ip: ClientIp,
     nt: Notify<'_>,
 ) -> EmptyResult {
     let data: ImportData = data.into_inner().data;
@@ -1569,9 +1550,7 @@ async fn post_org_import(
     let mut ciphers = Vec::new();
     for cipher_data in data.Ciphers {
         let mut cipher = Cipher::new(cipher_data.Type, cipher_data.Name.clone());
-        update_cipher_from_data(&mut cipher, cipher_data, &headers, false, &mut conn, &ip, &nt, UpdateType::None)
-            .await
-            .ok();
+        update_cipher_from_data(&mut cipher, cipher_data, &headers, false, &mut conn, &nt, UpdateType::None).await.ok();
         ciphers.push(cipher);
     }
 
@@ -1657,7 +1636,6 @@ async fn put_policy(
     data: Json<PolicyData>,
     headers: AdminHeaders,
     mut conn: DbConn,
-    ip: ClientIp,
 ) -> JsonResult {
     let data: PolicyData = data.into_inner();
 
@@ -1690,7 +1668,7 @@ async fn put_policy(
                     org_id.clone(),
                     headers.user.uuid.clone(),
                     headers.device.atype,
-                    &ip.ip,
+                    &headers.ip.ip,
                     &mut conn,
                 )
                 .await;
@@ -1724,7 +1702,7 @@ async fn put_policy(
                     org_id.clone(),
                     headers.user.uuid.clone(),
                     headers.device.atype,
-                    &ip.ip,
+                    &headers.ip.ip,
                     &mut conn,
                 )
                 .await;
@@ -1749,7 +1727,7 @@ async fn put_policy(
         org_id,
         headers.user.uuid.clone(),
         headers.device.atype,
-        &ip.ip,
+        &headers.ip.ip,
         &mut conn,
     )
     .await;
@@ -1825,13 +1803,7 @@ struct OrgImportData {
 }
 
 #[post("/organizations/<org_id>/import", data = "<data>")]
-async fn import(
-    org_id: String,
-    data: JsonUpcase<OrgImportData>,
-    headers: Headers,
-    mut conn: DbConn,
-    ip: ClientIp,
-) -> EmptyResult {
+async fn import(org_id: String, 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
@@ -1857,7 +1829,7 @@ async fn import(
                     org_id.clone(),
                     headers.user.uuid.clone(),
                     headers.device.atype,
-                    &ip.ip,
+                    &headers.ip.ip,
                     &mut conn,
                 )
                 .await;
@@ -1887,7 +1859,7 @@ async fn import(
                     org_id.clone(),
                     headers.user.uuid.clone(),
                     headers.device.atype,
-                    &ip.ip,
+                    &headers.ip.ip,
                     &mut conn,
                 )
                 .await;
@@ -1923,7 +1895,7 @@ async fn import(
                         org_id.clone(),
                         headers.user.uuid.clone(),
                         headers.device.atype,
-                        &ip.ip,
+                        &headers.ip.ip,
                         &mut conn,
                     )
                     .await;
@@ -1944,9 +1916,8 @@ async fn deactivate_organization_user(
     org_user_id: String,
     headers: AdminHeaders,
     mut conn: DbConn,
-    ip: ClientIp,
 ) -> EmptyResult {
-    _revoke_organization_user(&org_id, &org_user_id, &headers, &mut conn, &ip).await
+    _revoke_organization_user(&org_id, &org_user_id, &headers, &mut conn).await
 }
 
 // Pre web-vault v2022.9.x endpoint
@@ -1956,9 +1927,8 @@ async fn bulk_deactivate_organization_user(
     data: JsonUpcase<Value>,
     headers: AdminHeaders,
     conn: DbConn,
-    ip: ClientIp,
 ) -> Json<Value> {
-    bulk_revoke_organization_user(org_id, data, headers, conn, ip).await
+    bulk_revoke_organization_user(org_id, data, headers, conn).await
 }
 
 #[put("/organizations/<org_id>/users/<org_user_id>/revoke")]
@@ -1967,9 +1937,8 @@ async fn revoke_organization_user(
     org_user_id: String,
     headers: AdminHeaders,
     mut conn: DbConn,
-    ip: ClientIp,
 ) -> EmptyResult {
-    _revoke_organization_user(&org_id, &org_user_id, &headers, &mut conn, &ip).await
+    _revoke_organization_user(&org_id, &org_user_id, &headers, &mut conn).await
 }
 
 #[put("/organizations/<org_id>/users/revoke", data = "<data>")]
@@ -1978,7 +1947,6 @@ async fn bulk_revoke_organization_user(
     data: JsonUpcase<Value>,
     headers: AdminHeaders,
     mut conn: DbConn,
-    ip: ClientIp,
 ) -> Json<Value> {
     let data = data.into_inner().data;
 
@@ -1987,7 +1955,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, &ip).await {
+                let err_msg = match _revoke_organization_user(&org_id, org_user_id, &headers, &mut conn).await {
                     Ok(_) => String::new(),
                     Err(e) => format!("{e:?}"),
                 };
@@ -2016,7 +1984,6 @@ async fn _revoke_organization_user(
     org_user_id: &str,
     headers: &AdminHeaders,
     conn: &mut DbConn,
-    ip: &ClientIp,
 ) -> EmptyResult {
     match UserOrganization::find_by_uuid_and_org(org_user_id, org_id, conn).await {
         Some(mut user_org) if user_org.status > UserOrgStatus::Revoked as i32 => {
@@ -2041,7 +2008,7 @@ async fn _revoke_organization_user(
                 org_id.to_string(),
                 headers.user.uuid.clone(),
                 headers.device.atype,
-                &ip.ip,
+                &headers.ip.ip,
                 conn,
             )
             .await;
@@ -2059,9 +2026,8 @@ async fn activate_organization_user(
     org_user_id: String,
     headers: AdminHeaders,
     mut conn: DbConn,
-    ip: ClientIp,
 ) -> EmptyResult {
-    _restore_organization_user(&org_id, &org_user_id, &headers, &mut conn, &ip).await
+    _restore_organization_user(&org_id, &org_user_id, &headers, &mut conn).await
 }
 
 // Pre web-vault v2022.9.x endpoint
@@ -2071,9 +2037,8 @@ async fn bulk_activate_organization_user(
     data: JsonUpcase<Value>,
     headers: AdminHeaders,
     conn: DbConn,
-    ip: ClientIp,
 ) -> Json<Value> {
-    bulk_restore_organization_user(org_id, data, headers, conn, ip).await
+    bulk_restore_organization_user(org_id, data, headers, conn).await
 }
 
 #[put("/organizations/<org_id>/users/<org_user_id>/restore")]
@@ -2082,9 +2047,8 @@ async fn restore_organization_user(
     org_user_id: String,
     headers: AdminHeaders,
     mut conn: DbConn,
-    ip: ClientIp,
 ) -> EmptyResult {
-    _restore_organization_user(&org_id, &org_user_id, &headers, &mut conn, &ip).await
+    _restore_organization_user(&org_id, &org_user_id, &headers, &mut conn).await
 }
 
 #[put("/organizations/<org_id>/users/restore", data = "<data>")]
@@ -2093,7 +2057,6 @@ async fn bulk_restore_organization_user(
     data: JsonUpcase<Value>,
     headers: AdminHeaders,
     mut conn: DbConn,
-    ip: ClientIp,
 ) -> Json<Value> {
     let data = data.into_inner().data;
 
@@ -2102,7 +2065,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, &ip).await {
+                let err_msg = match _restore_organization_user(&org_id, org_user_id, &headers, &mut conn).await {
                     Ok(_) => String::new(),
                     Err(e) => format!("{e:?}"),
                 };
@@ -2131,7 +2094,6 @@ async fn _restore_organization_user(
     org_user_id: &str,
     headers: &AdminHeaders,
     conn: &mut DbConn,
-    ip: &ClientIp,
 ) -> EmptyResult {
     match UserOrganization::find_by_uuid_and_org(org_user_id, org_id, conn).await {
         Some(mut user_org) if user_org.status < UserOrgStatus::Accepted as i32 => {
@@ -2165,7 +2127,7 @@ async fn _restore_organization_user(
                 org_id.to_string(),
                 headers.user.uuid.clone(),
                 headers.device.atype,
-                &ip.ip,
+                &headers.ip.ip,
                 conn,
             )
             .await;
@@ -2277,9 +2239,8 @@ async fn post_group(
     data: JsonUpcase<GroupRequest>,
     headers: AdminHeaders,
     conn: DbConn,
-    ip: ClientIp,
 ) -> JsonResult {
-    put_group(org_id, group_id, data, headers, conn, ip).await
+    put_group(org_id, group_id, data, headers, conn).await
 }
 
 #[post("/organizations/<org_id>/groups", data = "<data>")]
@@ -2288,7 +2249,6 @@ async fn post_groups(
     headers: AdminHeaders,
     data: JsonUpcase<GroupRequest>,
     mut conn: DbConn,
-    ip: ClientIp,
 ) -> JsonResult {
     if !CONFIG.org_groups_enabled() {
         err!("Group support is disabled");
@@ -2303,12 +2263,12 @@ async fn post_groups(
         org_id.clone(),
         headers.user.uuid.clone(),
         headers.device.atype,
-        &ip.ip,
+        &headers.ip.ip,
         &mut conn,
     )
     .await;
 
-    add_update_group(group, group_request.Collections, group_request.Users, &org_id, &headers, &ip, &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>")]
@@ -2318,7 +2278,6 @@ async fn put_group(
     data: JsonUpcase<GroupRequest>,
     headers: AdminHeaders,
     mut conn: DbConn,
-    ip: ClientIp,
 ) -> JsonResult {
     if !CONFIG.org_groups_enabled() {
         err!("Group support is disabled");
@@ -2341,13 +2300,12 @@ async fn put_group(
         org_id.clone(),
         headers.user.uuid.clone(),
         headers.device.atype,
-        &ip.ip,
+        &headers.ip.ip,
         &mut conn,
     )
     .await;
 
-    add_update_group(updated_group, group_request.Collections, group_request.Users, &org_id, &headers, &ip, &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(
@@ -2356,7 +2314,6 @@ async fn add_update_group(
     users: Vec<String>,
     org_id: &str,
     headers: &AdminHeaders,
-    ip: &ClientIp,
     conn: &mut DbConn,
 ) -> JsonResult {
     group.save(conn).await?;
@@ -2376,7 +2333,7 @@ async fn add_update_group(
             String::from(org_id),
             headers.user.uuid.clone(),
             headers.device.atype,
-            &ip.ip,
+            &headers.ip.ip,
             conn,
         )
         .await;
@@ -2406,24 +2363,12 @@ 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,
-    conn: DbConn,
-    ip: ClientIp,
-) -> EmptyResult {
-    delete_group(org_id, group_id, headers, conn, ip).await
+async fn post_delete_group(org_id: String, group_id: String, headers: AdminHeaders, conn: DbConn) -> EmptyResult {
+    delete_group(org_id, group_id, headers, conn).await
 }
 
 #[delete("/organizations/<org_id>/groups/<group_id>")]
-async fn delete_group(
-    org_id: String,
-    group_id: String,
-    headers: AdminHeaders,
-    mut conn: DbConn,
-    ip: ClientIp,
-) -> EmptyResult {
+async fn delete_group(org_id: String, group_id: String, headers: AdminHeaders, mut conn: DbConn) -> EmptyResult {
     if !CONFIG.org_groups_enabled() {
         err!("Group support is disabled");
     }
@@ -2439,7 +2384,7 @@ async fn delete_group(
         org_id,
         headers.user.uuid.clone(),
         headers.device.atype,
-        &ip.ip,
+        &headers.ip.ip,
         &mut conn,
     )
     .await;
@@ -2488,7 +2433,6 @@ async fn put_group_users(
     headers: AdminHeaders,
     data: JsonVec<String>,
     mut conn: DbConn,
-    ip: ClientIp,
 ) -> EmptyResult {
     if !CONFIG.org_groups_enabled() {
         err!("Group support is disabled");
@@ -2512,7 +2456,7 @@ async fn put_group_users(
             org_id.clone(),
             headers.user.uuid.clone(),
             headers.device.atype,
-            &ip.ip,
+            &headers.ip.ip,
             &mut conn,
         )
         .await;
@@ -2551,9 +2495,8 @@ async fn post_user_groups(
     data: JsonUpcase<OrganizationUserUpdateGroupsRequest>,
     headers: AdminHeaders,
     conn: DbConn,
-    ip: ClientIp,
 ) -> EmptyResult {
-    put_user_groups(org_id, org_user_id, data, headers, conn, ip).await
+    put_user_groups(org_id, org_user_id, data, headers, conn).await
 }
 
 #[put("/organizations/<org_id>/users/<org_user_id>/groups", data = "<data>")]
@@ -2563,7 +2506,6 @@ async fn put_user_groups(
     data: JsonUpcase<OrganizationUserUpdateGroupsRequest>,
     headers: AdminHeaders,
     mut conn: DbConn,
-    ip: ClientIp,
 ) -> EmptyResult {
     if !CONFIG.org_groups_enabled() {
         err!("Group support is disabled");
@@ -2588,7 +2530,7 @@ async fn put_user_groups(
         org_id,
         headers.user.uuid.clone(),
         headers.device.atype,
-        &ip.ip,
+        &headers.ip.ip,
         &mut conn,
     )
     .await;
@@ -2603,9 +2545,8 @@ async fn post_delete_group_user(
     org_user_id: String,
     headers: AdminHeaders,
     conn: DbConn,
-    ip: ClientIp,
 ) -> EmptyResult {
-    delete_group_user(org_id, group_id, org_user_id, headers, conn, ip).await
+    delete_group_user(org_id, group_id, org_user_id, headers, conn).await
 }
 
 #[delete("/organizations/<org_id>/groups/<group_id>/users/<org_user_id>")]
@@ -2615,7 +2556,6 @@ async fn delete_group_user(
     org_user_id: String,
     headers: AdminHeaders,
     mut conn: DbConn,
-    ip: ClientIp,
 ) -> EmptyResult {
     if !CONFIG.org_groups_enabled() {
         err!("Group support is disabled");
@@ -2637,7 +2577,7 @@ async fn delete_group_user(
         org_id,
         headers.user.uuid.clone(),
         headers.device.atype,
-        &ip.ip,
+        &headers.ip.ip,
         &mut conn,
     )
     .await;
@@ -2679,7 +2619,6 @@ async fn put_reset_password(
     headers: AdminHeaders,
     data: JsonUpcase<OrganizationUserResetPasswordRequest>,
     mut conn: DbConn,
-    ip: ClientIp,
     nt: Notify<'_>,
 ) -> EmptyResult {
     let org = match Organization::find_by_uuid(&org_id, &mut conn).await {
@@ -2725,7 +2664,7 @@ async fn put_reset_password(
         org.uuid.clone(),
         headers.user.uuid.clone(),
         headers.device.atype,
-        &ip.ip,
+        &headers.ip.ip,
         &mut conn,
     )
     .await;
@@ -2812,7 +2751,6 @@ async fn put_reset_password_enrollment(
     headers: Headers,
     data: JsonUpcase<OrganizationUserResetPasswordEnrollmentRequest>,
     mut conn: DbConn,
-    ip: ClientIp,
 ) -> EmptyResult {
     let mut org_user = match UserOrganization::find_by_user_and_org(&headers.user.uuid, &org_id, &mut conn).await {
         Some(u) => u,
@@ -2838,7 +2776,8 @@ 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, &ip.ip, &mut conn).await;
+    log_event(log_id, &org_user_id, org_id, headers.user.uuid.clone(), headers.device.atype, &headers.ip.ip, &mut conn)
+        .await;
 
     Ok(())
 }
diff --git a/src/api/core/two_factor/authenticator.rs b/src/api/core/two_factor/authenticator.rs
index fa1792f250aba0782600b3b55d37daf23eae41b6..37221df104c9916196d5240971a78921a48027f9 100644
--- a/src/api/core/two_factor/authenticator.rs
+++ b/src/api/core/two_factor/authenticator.rs
@@ -57,7 +57,6 @@ struct EnableAuthenticatorData {
 async fn activate_authenticator(
     data: JsonUpcase<EnableAuthenticatorData>,
     headers: Headers,
-    ip: ClientIp,
     mut conn: DbConn,
 ) -> JsonResult {
     let data: EnableAuthenticatorData = data.into_inner().data;
@@ -82,11 +81,11 @@ async fn activate_authenticator(
     }
 
     // Validate the token provided with the key, and save new twofactor
-    validate_totp_code(&user.uuid, &token, &key.to_uppercase(), &ip, &mut conn).await?;
+    validate_totp_code(&user.uuid, &token, &key.to_uppercase(), &headers.ip, &mut conn).await?;
 
     _generate_recover_code(&mut user, &mut conn).await;
 
-    log_user_event(EventType::UserUpdated2fa as i32, &user.uuid, headers.device.atype, &ip.ip, &mut conn).await;
+    log_user_event(EventType::UserUpdated2fa as i32, &user.uuid, headers.device.atype, &headers.ip.ip, &mut conn).await;
 
     Ok(Json(json!({
         "Enabled": true,
@@ -99,10 +98,9 @@ async fn activate_authenticator(
 async fn activate_authenticator_put(
     data: JsonUpcase<EnableAuthenticatorData>,
     headers: Headers,
-    ip: ClientIp,
     conn: DbConn,
 ) -> JsonResult {
-    activate_authenticator(data, headers, ip, conn).await
+    activate_authenticator(data, headers, conn).await
 }
 
 pub async fn validate_totp_code_str(
diff --git a/src/api/core/two_factor/duo.rs b/src/api/core/two_factor/duo.rs
index 267d2db9d38538073adca35765375cd81b815ae1..c4ca0ba84343ab82c369375ae28c4c1d6ebaf7c7 100644
--- a/src/api/core/two_factor/duo.rs
+++ b/src/api/core/two_factor/duo.rs
@@ -8,7 +8,7 @@ use crate::{
         core::log_user_event, core::two_factor::_generate_recover_code, ApiResult, EmptyResult, JsonResult, JsonUpcase,
         PasswordData,
     },
-    auth::{ClientIp, Headers},
+    auth::Headers,
     crypto,
     db::{
         models::{EventType, TwoFactor, TwoFactorType, User},
@@ -155,7 +155,7 @@ fn check_duo_fields_custom(data: &EnableDuoData) -> bool {
 }
 
 #[post("/two-factor/duo", data = "<data>")]
-async fn activate_duo(data: JsonUpcase<EnableDuoData>, headers: Headers, mut conn: DbConn, ip: ClientIp) -> JsonResult {
+async fn activate_duo(data: JsonUpcase<EnableDuoData>, headers: Headers, mut conn: DbConn) -> JsonResult {
     let data: EnableDuoData = data.into_inner().data;
     let mut user = headers.user;
 
@@ -178,7 +178,7 @@ async fn activate_duo(data: JsonUpcase<EnableDuoData>, headers: Headers, mut con
 
     _generate_recover_code(&mut user, &mut conn).await;
 
-    log_user_event(EventType::UserUpdated2fa as i32, &user.uuid, headers.device.atype, &ip.ip, &mut conn).await;
+    log_user_event(EventType::UserUpdated2fa as i32, &user.uuid, headers.device.atype, &headers.ip.ip, &mut conn).await;
 
     Ok(Json(json!({
         "Enabled": true,
@@ -190,8 +190,8 @@ async fn activate_duo(data: JsonUpcase<EnableDuoData>, headers: Headers, mut con
 }
 
 #[put("/two-factor/duo", data = "<data>")]
-async fn activate_duo_put(data: JsonUpcase<EnableDuoData>, headers: Headers, conn: DbConn, ip: ClientIp) -> JsonResult {
-    activate_duo(data, headers, conn, ip).await
+async fn activate_duo_put(data: JsonUpcase<EnableDuoData>, headers: Headers, conn: DbConn) -> JsonResult {
+    activate_duo(data, headers, conn).await
 }
 
 async fn duo_api_request(method: &str, path: &str, params: &str, data: &DuoData) -> EmptyResult {
diff --git a/src/api/core/two_factor/email.rs b/src/api/core/two_factor/email.rs
index f9a0303bc9dca834eb2b521f1689ec69c9909219..1ca5152b6c9be788ee6c6f867530494e8b59ce8a 100644
--- a/src/api/core/two_factor/email.rs
+++ b/src/api/core/two_factor/email.rs
@@ -7,7 +7,7 @@ use crate::{
         core::{log_user_event, two_factor::_generate_recover_code},
         EmptyResult, JsonResult, JsonUpcase, PasswordData,
     },
-    auth::{ClientIp, Headers},
+    auth::Headers,
     crypto,
     db::{
         models::{EventType, TwoFactor, TwoFactorType},
@@ -90,7 +90,7 @@ async fn get_email(data: JsonUpcase<PasswordData>, headers: Headers, mut conn: D
                 let twofactor_data = EmailTokenData::from_json(&x.data)?;
                 (true, json!(twofactor_data.email))
             }
-            _ => (false, json!(null)),
+            _ => (false, serde_json::value::Value::Null),
         };
 
     Ok(Json(json!({
@@ -150,7 +150,7 @@ struct EmailData {
 
 /// Verify email belongs to user and can be used for 2FA email codes.
 #[put("/two-factor/email", data = "<data>")]
-async fn email(data: JsonUpcase<EmailData>, headers: Headers, mut conn: DbConn, ip: ClientIp) -> JsonResult {
+async fn email(data: JsonUpcase<EmailData>, headers: Headers, mut conn: DbConn) -> JsonResult {
     let data: EmailData = data.into_inner().data;
     let mut user = headers.user;
 
@@ -180,7 +180,7 @@ async fn email(data: JsonUpcase<EmailData>, headers: Headers, mut conn: DbConn,
 
     _generate_recover_code(&mut user, &mut conn).await;
 
-    log_user_event(EventType::UserUpdated2fa as i32, &user.uuid, headers.device.atype, &ip.ip, &mut conn).await;
+    log_user_event(EventType::UserUpdated2fa as i32, &user.uuid, headers.device.atype, &headers.ip.ip, &mut conn).await;
 
     Ok(Json(json!({
         "Email": email_data.email,
diff --git a/src/api/core/two_factor/mod.rs b/src/api/core/two_factor/mod.rs
index a2bbc806ee2d17164a125b349cf9f2a4204e8279..35c1867f2644993cabf62c5f870034bcec7cc658 100644
--- a/src/api/core/two_factor/mod.rs
+++ b/src/api/core/two_factor/mod.rs
@@ -6,7 +6,7 @@ use serde_json::Value;
 
 use crate::{
     api::{core::log_user_event, JsonResult, JsonUpcase, NumberOrString, PasswordData},
-    auth::{ClientHeaders, ClientIp, Headers},
+    auth::{ClientHeaders, Headers},
     crypto,
     db::{models::*, DbConn, DbPool},
     mail, CONFIG,
@@ -73,12 +73,7 @@ struct RecoverTwoFactor {
 }
 
 #[post("/two-factor/recover", data = "<data>")]
-async fn recover(
-    data: JsonUpcase<RecoverTwoFactor>,
-    client_headers: ClientHeaders,
-    mut conn: DbConn,
-    ip: ClientIp,
-) -> JsonResult {
+async fn recover(data: JsonUpcase<RecoverTwoFactor>, client_headers: ClientHeaders, mut conn: DbConn) -> JsonResult {
     let data: RecoverTwoFactor = data.into_inner().data;
 
     use crate::db::models::User;
@@ -102,12 +97,19 @@ async fn recover(
     // Remove all twofactors from the user
     TwoFactor::delete_all_by_user(&user.uuid, &mut conn).await?;
 
-    log_user_event(EventType::UserRecovered2fa as i32, &user.uuid, client_headers.device_type, &ip.ip, &mut conn).await;
+    log_user_event(
+        EventType::UserRecovered2fa as i32,
+        &user.uuid,
+        client_headers.device_type,
+        &client_headers.ip.ip,
+        &mut conn,
+    )
+    .await;
 
     // Remove the recovery code, not needed without twofactors
     user.totp_recover = None;
     user.save(&mut conn).await?;
-    Ok(Json(json!({})))
+    Ok(Json(Value::Object(serde_json::Map::new())))
 }
 
 async fn _generate_recover_code(user: &mut User, conn: &mut DbConn) {
@@ -126,12 +128,7 @@ struct DisableTwoFactorData {
 }
 
 #[post("/two-factor/disable", data = "<data>")]
-async fn disable_twofactor(
-    data: JsonUpcase<DisableTwoFactorData>,
-    headers: Headers,
-    mut conn: DbConn,
-    ip: ClientIp,
-) -> JsonResult {
+async fn disable_twofactor(data: JsonUpcase<DisableTwoFactorData>, headers: Headers, mut conn: DbConn) -> JsonResult {
     let data: DisableTwoFactorData = data.into_inner().data;
     let password_hash = data.MasterPasswordHash;
     let user = headers.user;
@@ -144,7 +141,8 @@ async fn disable_twofactor(
 
     if let Some(twofactor) = TwoFactor::find_by_user_and_type(&user.uuid, type_, &mut conn).await {
         twofactor.delete(&mut conn).await?;
-        log_user_event(EventType::UserDisabled2fa as i32, &user.uuid, headers.device.atype, &ip.ip, &mut conn).await;
+        log_user_event(EventType::UserDisabled2fa as i32, &user.uuid, headers.device.atype, &headers.ip.ip, &mut conn)
+            .await;
     }
 
     let twofactor_disabled = TwoFactor::find_by_user(&user.uuid, &mut conn).await.is_empty();
@@ -173,13 +171,8 @@ async fn disable_twofactor(
 }
 
 #[put("/two-factor/disable", data = "<data>")]
-async fn disable_twofactor_put(
-    data: JsonUpcase<DisableTwoFactorData>,
-    headers: Headers,
-    conn: DbConn,
-    ip: ClientIp,
-) -> JsonResult {
-    disable_twofactor(data, headers, conn, ip).await
+async fn disable_twofactor_put(data: JsonUpcase<DisableTwoFactorData>, headers: Headers, conn: DbConn) -> JsonResult {
+    disable_twofactor(data, headers, conn).await
 }
 
 pub async fn send_incomplete_2fa_notifications(pool: DbPool) {
diff --git a/src/api/core/two_factor/webauthn.rs b/src/api/core/two_factor/webauthn.rs
index 97711c7598f2f0f18f2d019e4db108e74bf2f1f1..3c62754af6d4035224d63ed372817727443b0c40 100644
--- a/src/api/core/two_factor/webauthn.rs
+++ b/src/api/core/two_factor/webauthn.rs
@@ -9,7 +9,7 @@ use crate::{
         core::{log_user_event, two_factor::_generate_recover_code},
         EmptyResult, JsonResult, JsonUpcase, NumberOrString, PasswordData,
     },
-    auth::{ClientIp, Headers},
+    auth::Headers,
     db::{
         models::{EventType, TwoFactor, TwoFactorType},
         DbConn,
@@ -242,12 +242,7 @@ impl From<PublicKeyCredentialCopy> for PublicKeyCredential {
 }
 
 #[post("/two-factor/webauthn", data = "<data>")]
-async fn activate_webauthn(
-    data: JsonUpcase<EnableWebauthnData>,
-    headers: Headers,
-    mut conn: DbConn,
-    ip: ClientIp,
-) -> JsonResult {
+async fn activate_webauthn(data: JsonUpcase<EnableWebauthnData>, headers: Headers, mut conn: DbConn) -> JsonResult {
     let data: EnableWebauthnData = data.into_inner().data;
     let mut user = headers.user;
 
@@ -286,7 +281,7 @@ async fn activate_webauthn(
         .await?;
     _generate_recover_code(&mut user, &mut conn).await;
 
-    log_user_event(EventType::UserUpdated2fa as i32, &user.uuid, headers.device.atype, &ip.ip, &mut conn).await;
+    log_user_event(EventType::UserUpdated2fa as i32, &user.uuid, headers.device.atype, &headers.ip.ip, &mut conn).await;
 
     let keys_json: Vec<Value> = registrations.iter().map(WebauthnRegistration::to_json).collect();
     Ok(Json(json!({
@@ -297,13 +292,8 @@ async fn activate_webauthn(
 }
 
 #[put("/two-factor/webauthn", data = "<data>")]
-async fn activate_webauthn_put(
-    data: JsonUpcase<EnableWebauthnData>,
-    headers: Headers,
-    conn: DbConn,
-    ip: ClientIp,
-) -> JsonResult {
-    activate_webauthn(data, headers, conn, ip).await
+async fn activate_webauthn_put(data: JsonUpcase<EnableWebauthnData>, headers: Headers, conn: DbConn) -> JsonResult {
+    activate_webauthn(data, headers, conn).await
 }
 
 #[derive(Deserialize, Debug)]
diff --git a/src/api/core/two_factor/yubikey.rs b/src/api/core/two_factor/yubikey.rs
index b076dd00d48f2042126e0e0bee56984cb1917863..7681ab01e6550655654af8d398caabcd3c907cc7 100644
--- a/src/api/core/two_factor/yubikey.rs
+++ b/src/api/core/two_factor/yubikey.rs
@@ -8,7 +8,7 @@ use crate::{
         core::{log_user_event, two_factor::_generate_recover_code},
         EmptyResult, JsonResult, JsonUpcase, PasswordData,
     },
-    auth::{ClientIp, Headers},
+    auth::Headers,
     db::{
         models::{EventType, TwoFactor, TwoFactorType},
         DbConn,
@@ -47,7 +47,7 @@ fn parse_yubikeys(data: &EnableYubikeyData) -> Vec<String> {
 }
 
 fn jsonify_yubikeys(yubikeys: Vec<String>) -> serde_json::Value {
-    let mut result = json!({});
+    let mut result = Value::Object(serde_json::Map::new());
 
     for (i, key) in yubikeys.into_iter().enumerate() {
         result[format!("Key{}", i + 1)] = Value::String(key);
@@ -118,12 +118,7 @@ async fn generate_yubikey(data: JsonUpcase<PasswordData>, headers: Headers, mut
 }
 
 #[post("/two-factor/yubikey", data = "<data>")]
-async fn activate_yubikey(
-    data: JsonUpcase<EnableYubikeyData>,
-    headers: Headers,
-    mut conn: DbConn,
-    ip: ClientIp,
-) -> JsonResult {
+async fn activate_yubikey(data: JsonUpcase<EnableYubikeyData>, headers: Headers, mut conn: DbConn) -> JsonResult {
     let data: EnableYubikeyData = data.into_inner().data;
     let mut user = headers.user;
 
@@ -169,7 +164,7 @@ async fn activate_yubikey(
 
     _generate_recover_code(&mut user, &mut conn).await;
 
-    log_user_event(EventType::UserUpdated2fa as i32, &user.uuid, headers.device.atype, &ip.ip, &mut conn).await;
+    log_user_event(EventType::UserUpdated2fa as i32, &user.uuid, headers.device.atype, &headers.ip.ip, &mut conn).await;
 
     let mut result = jsonify_yubikeys(yubikey_metadata.Keys);
 
@@ -181,13 +176,8 @@ async fn activate_yubikey(
 }
 
 #[put("/two-factor/yubikey", data = "<data>")]
-async fn activate_yubikey_put(
-    data: JsonUpcase<EnableYubikeyData>,
-    headers: Headers,
-    conn: DbConn,
-    ip: ClientIp,
-) -> JsonResult {
-    activate_yubikey(data, headers, conn, ip).await
+async fn activate_yubikey_put(data: JsonUpcase<EnableYubikeyData>, headers: Headers, conn: DbConn) -> JsonResult {
+    activate_yubikey(data, headers, conn).await
 }
 
 pub async fn validate_yubikey_login(response: &str, twofactor_data: &str) -> EmptyResult {
diff --git a/src/api/identity.rs b/src/api/identity.rs
index bb575cca21d8e6cd82ac67198afa57caeb717591..5115a534b37bf546f5262b7a33e7729f90883884 100644
--- a/src/api/identity.rs
+++ b/src/api/identity.rs
@@ -25,7 +25,7 @@ pub fn routes() -> Vec<Route> {
 }
 
 #[post("/connect/token", data = "<data>")]
-async fn login(data: Form<ConnectData>, client_header: ClientHeaders, mut conn: DbConn, ip: ClientIp) -> JsonResult {
+async fn login(data: Form<ConnectData>, client_header: ClientHeaders, mut conn: DbConn) -> JsonResult {
     let data: ConnectData = data.into_inner();
 
     let mut user_uuid: Option<String> = None;
@@ -45,7 +45,7 @@ async fn login(data: Form<ConnectData>, client_header: ClientHeaders, mut conn:
             _check_is_some(&data.device_name, "device_name cannot be blank")?;
             _check_is_some(&data.device_type, "device_type cannot be blank")?;
 
-            _password_login(data, &mut user_uuid, &mut conn, &ip).await
+            _password_login(data, &mut user_uuid, &mut conn, &client_header.ip).await
         }
         "client_credentials" => {
             _check_is_some(&data.client_id, "client_id cannot be blank")?;
@@ -56,7 +56,7 @@ async fn login(data: Form<ConnectData>, client_header: ClientHeaders, mut conn:
             _check_is_some(&data.device_name, "device_name cannot be blank")?;
             _check_is_some(&data.device_type, "device_type cannot be blank")?;
 
-            _api_key_login(data, &mut user_uuid, &mut conn, &ip).await
+            _api_key_login(data, &mut user_uuid, &mut conn, &client_header.ip).await
         }
         t => err!("Invalid type", t),
     };
@@ -68,14 +68,21 @@ async fn login(data: Form<ConnectData>, client_header: ClientHeaders, mut conn:
                     EventType::UserLoggedIn as i32,
                     &user_uuid,
                     client_header.device_type,
-                    &ip.ip,
+                    &client_header.ip.ip,
                     &mut conn,
                 )
                 .await;
             }
             Err(e) => {
                 if let Some(ev) = e.get_event() {
-                    log_user_event(ev.event as i32, &user_uuid, client_header.device_type, &ip.ip, &mut conn).await
+                    log_user_event(
+                        ev.event as i32,
+                        &user_uuid,
+                        client_header.device_type,
+                        &client_header.ip.ip,
+                        &mut conn,
+                    )
+                    .await
                 }
             }
         }
diff --git a/src/api/notifications.rs b/src/api/notifications.rs
index b4dc55e9615e0551705e3c922c95e136fedc3b52..2c96f0e4f29b25f16a729ecd56e323616d9bb90b 100644
--- a/src/api/notifications.rs
+++ b/src/api/notifications.rs
@@ -10,8 +10,7 @@ use std::{
 use chrono::NaiveDateTime;
 use futures::{SinkExt, StreamExt};
 use rmpv::Value;
-use rocket::{serde::json::Json, Route};
-use serde_json::Value as JsonValue;
+use rocket::Route;
 use tokio::{
     net::{TcpListener, TcpStream},
     sync::mpsc::Sender,
@@ -23,13 +22,12 @@ use tokio_tungstenite::{
 
 use crate::{
     api::EmptyResult,
-    auth::Headers,
     db::models::{Cipher, Folder, Send, User},
     Error, CONFIG,
 };
 
 pub fn routes() -> Vec<Route> {
-    routes![negotiate, websockets_err]
+    routes![websockets_err]
 }
 
 #[get("/hub")]
@@ -51,29 +49,6 @@ fn websockets_err() -> EmptyResult {
     }
 }
 
-#[post("/hub/negotiate")]
-fn negotiate(_headers: Headers) -> Json<JsonValue> {
-    use crate::crypto;
-    use data_encoding::BASE64URL;
-
-    let conn_id = crypto::encode_random_bytes::<16>(BASE64URL);
-    let mut available_transports: Vec<JsonValue> = Vec::new();
-
-    if CONFIG.websocket_enabled() {
-        available_transports.push(json!({"transport":"WebSockets", "transferFormats":["Text","Binary"]}));
-    }
-
-    // TODO: Implement transports
-    // Rocket WS support: https://github.com/SergioBenitez/Rocket/issues/90
-    // Rocket SSE support: https://github.com/SergioBenitez/Rocket/issues/33
-    // {"transport":"ServerSentEvents", "transferFormats":["Text"]},
-    // {"transport":"LongPolling", "transferFormats":["Text","Binary"]}
-    Json(json!({
-        "connectionId": conn_id,
-        "availableTransports": available_transports
-    }))
-}
-
 //
 // Websockets server
 //
diff --git a/src/auth.rs b/src/auth.rs
index 380c6a735a3632b74e808530d65df63cbcc52a7f..e5779dd6ce28e5fbd4b926c23db1a12cbe785e18 100644
--- a/src/auth.rs
+++ b/src/auth.rs
@@ -318,6 +318,7 @@ impl<'r> FromRequest<'r> for Host {
 pub struct ClientHeaders {
     pub host: String,
     pub device_type: i32,
+    pub ip: ClientIp,
 }
 
 #[rocket::async_trait]
@@ -326,6 +327,10 @@ impl<'r> FromRequest<'r> for ClientHeaders {
 
     async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Self::Error> {
         let host = try_outcome!(Host::from_request(request).await).host;
+        let ip = match ClientIp::from_request(request).await {
+            Outcome::Success(ip) => ip,
+            _ => err_handler!("Error getting Client IP"),
+        };
         // When unknown or unable to parse, return 14, which is 'Unknown Browser'
         let device_type: i32 =
             request.headers().get_one("device-type").map(|d| d.parse().unwrap_or(14)).unwrap_or_else(|| 14);
@@ -333,6 +338,7 @@ impl<'r> FromRequest<'r> for ClientHeaders {
         Outcome::Success(ClientHeaders {
             host,
             device_type,
+            ip,
         })
     }
 }
@@ -341,6 +347,7 @@ pub struct Headers {
     pub host: String,
     pub device: Device,
     pub user: User,
+    pub ip: ClientIp,
 }
 
 #[rocket::async_trait]
@@ -351,6 +358,10 @@ impl<'r> FromRequest<'r> for Headers {
         let headers = request.headers();
 
         let host = try_outcome!(Host::from_request(request).await).host;
+        let ip = match ClientIp::from_request(request).await {
+            Outcome::Success(ip) => ip,
+            _ => err_handler!("Error getting Client IP"),
+        };
 
         // Get access_token
         let access_token: &str = match headers.get_one("Authorization") {
@@ -420,6 +431,7 @@ impl<'r> FromRequest<'r> for Headers {
             host,
             device,
             user,
+            ip,
         })
     }
 }
@@ -431,6 +443,7 @@ pub struct OrgHeaders {
     pub org_user_type: UserOrgType,
     pub org_user: UserOrganization,
     pub org_id: String,
+    pub ip: ClientIp,
 }
 
 // org_id is usually the second path param ("/organizations/<org_id>"),
@@ -491,6 +504,7 @@ impl<'r> FromRequest<'r> for OrgHeaders {
                     },
                     org_user,
                     org_id,
+                    ip: headers.ip,
                 })
             }
             _ => err_handler!("Error getting the organization id"),
@@ -504,6 +518,7 @@ pub struct AdminHeaders {
     pub user: User,
     pub org_user_type: UserOrgType,
     pub client_version: Option<String>,
+    pub ip: ClientIp,
 }
 
 #[rocket::async_trait]
@@ -520,6 +535,7 @@ impl<'r> FromRequest<'r> for AdminHeaders {
                 user: headers.user,
                 org_user_type: headers.org_user_type,
                 client_version,
+                ip: headers.ip,
             })
         } else {
             err_handler!("You need to be Admin or Owner to call this endpoint")
@@ -533,6 +549,7 @@ impl From<AdminHeaders> for Headers {
             host: h.host,
             device: h.device,
             user: h.user,
+            ip: h.ip,
         }
     }
 }
@@ -564,6 +581,7 @@ pub struct ManagerHeaders {
     pub device: Device,
     pub user: User,
     pub org_user_type: UserOrgType,
+    pub ip: ClientIp,
 }
 
 #[rocket::async_trait]
@@ -599,6 +617,7 @@ impl<'r> FromRequest<'r> for ManagerHeaders {
                 device: headers.device,
                 user: headers.user,
                 org_user_type: headers.org_user_type,
+                ip: headers.ip,
             })
         } else {
             err_handler!("You need to be a Manager, Admin or Owner to call this endpoint")
@@ -612,6 +631,7 @@ impl From<ManagerHeaders> for Headers {
             host: h.host,
             device: h.device,
             user: h.user,
+            ip: h.ip,
         }
     }
 }
@@ -623,6 +643,7 @@ pub struct ManagerHeadersLoose {
     pub device: Device,
     pub user: User,
     pub org_user_type: UserOrgType,
+    pub ip: ClientIp,
 }
 
 #[rocket::async_trait]
@@ -637,6 +658,7 @@ impl<'r> FromRequest<'r> for ManagerHeadersLoose {
                 device: headers.device,
                 user: headers.user,
                 org_user_type: headers.org_user_type,
+                ip: headers.ip,
             })
         } else {
             err_handler!("You need to be a Manager, Admin or Owner to call this endpoint")
@@ -650,6 +672,7 @@ impl From<ManagerHeadersLoose> for Headers {
             host: h.host,
             device: h.device,
             user: h.user,
+            ip: h.ip,
         }
     }
 }
@@ -658,6 +681,7 @@ pub struct OwnerHeaders {
     pub host: String,
     pub device: Device,
     pub user: User,
+    pub ip: ClientIp,
 }
 
 #[rocket::async_trait]
@@ -671,6 +695,7 @@ impl<'r> FromRequest<'r> for OwnerHeaders {
                 host: headers.host,
                 device: headers.device,
                 user: headers.user,
+                ip: headers.ip,
             })
         } else {
             err_handler!("You need to be Owner to call this endpoint")
diff --git a/src/db/models/cipher.rs b/src/db/models/cipher.rs
index 79212f6abb5b3fba10178fb481f35d5a24b9dc26..9e324b7ba5b53127cc98c27f4b24667e7369fd32 100644
--- a/src/db/models/cipher.rs
+++ b/src/db/models/cipher.rs
@@ -151,7 +151,8 @@ impl Cipher {
 
         // Get the type_data or a default to an empty json object '{}'.
         // If not passing an empty object, mobile clients will crash.
-        let mut type_data_json: Value = serde_json::from_str(&self.data).unwrap_or_else(|_| json!({}));
+        let mut type_data_json: Value =
+            serde_json::from_str(&self.data).unwrap_or_else(|_| Value::Object(serde_json::Map::new()));
 
         // NOTE: This was marked as *Backwards Compatibility Code*, but as of January 2021 this is still being used by upstream
         // Set the first element of the Uris array as Uri, this is needed several (mobile) clients.
@@ -170,10 +171,10 @@ impl Cipher {
 
         // NOTE: This was marked as *Backwards Compatibility Code*, but as of January 2021 this is still being used by upstream
         // data_json should always contain the following keys with every atype
-        data_json["Fields"] = json!(fields_json);
+        data_json["Fields"] = fields_json.clone();
         data_json["Name"] = json!(self.name);
         data_json["Notes"] = json!(self.notes);
-        data_json["PasswordHistory"] = json!(password_history_json);
+        data_json["PasswordHistory"] = password_history_json.clone();
 
         let collection_ids = if let Some(cipher_sync_data) = cipher_sync_data {
             if let Some(cipher_collections) = cipher_sync_data.cipher_collections.get(&self.uuid) {
diff --git a/src/main.rs b/src/main.rs
index e61f7cf18f4d8442d992b96fd0b7bad41f07c331..b85b8900936b25ac0695deee8650bb8315db1e6c 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -250,6 +250,14 @@ fn init_logging(level: log::LevelFilter) -> Result<(), fern::InitError> {
             log::LevelFilter::Off
         };
 
+    // Only show rocket underscore `_` logs when the level is Debug or higher
+    // Else this will bloat the log output with useless messages.
+    let rocket_underscore_level = if level >= log::LevelFilter::Debug {
+        log::LevelFilter::Warn
+    } else {
+        log::LevelFilter::Off
+    };
+
     let mut logger = fern::Dispatch::new()
         .level(level)
         // Hide unknown certificate errors if using self-signed
@@ -257,7 +265,7 @@ fn init_logging(level: log::LevelFilter) -> Result<(), fern::InitError> {
         // Hide failed to close stream messages
         .level_for("hyper::server", log::LevelFilter::Warn)
         // Silence rocket logs
-        .level_for("_", log::LevelFilter::Warn)
+        .level_for("_", rocket_underscore_level)
         .level_for("rocket::launch", log::LevelFilter::Error)
         .level_for("rocket::launch_", log::LevelFilter::Error)
         .level_for("rocket::rocket", log::LevelFilter::Warn)
@@ -269,7 +277,8 @@ fn init_logging(level: log::LevelFilter) -> Result<(), fern::InitError> {
         // Prevent cookie_store logs
         .level_for("cookie_store", log::LevelFilter::Off)
         // Variable level for trust-dns used by reqwest
-        .level_for("trust_dns_proto", trust_dns_level)
+        .level_for("trust_dns_resolver::name_server::name_server", trust_dns_level)
+        .level_for("trust_dns_proto::xfer", trust_dns_level)
         .level_for("diesel_logger", diesel_logger_level)
         .chain(std::io::stdout());
 
@@ -277,9 +286,9 @@ fn init_logging(level: log::LevelFilter) -> Result<(), fern::InitError> {
     // This can contain sensitive information we do not want in the default debug/trace logging.
     if CONFIG.smtp_debug() {
         println!(
-            "[WARNING] SMTP Debugging is enabled (SMTP_DEBUG=true). Sensitive information could be disclosed via logs!"
+            "[WARNING] SMTP Debugging is enabled (SMTP_DEBUG=true). Sensitive information could be disclosed via logs!\n\
+             [WARNING] Only enable SMTP_DEBUG during troubleshooting!\n"
         );
-        println!("[WARNING] Only enable SMTP_DEBUG during troubleshooting!\n");
         logger = logger.level_for("lettre::transport::smtp", log::LevelFilter::Debug)
     } else {
         logger = logger.level_for("lettre::transport::smtp", log::LevelFilter::Off)
diff --git a/src/util.rs b/src/util.rs
index 18adea70aea650f56bf33cb71f13680c4fcbc615..a9e94405716cd8216de5e697a7fddec82618c50f 100644
--- a/src/util.rs
+++ b/src/util.rs
@@ -231,8 +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; 6] =
-    ["/api", "/admin", "/identity", "/icons", "/notifications/hub/negotiate", "/attachments"];
+const LOGGED_ROUTES: [&str; 5] = ["/api", "/admin", "/identity", "/icons", "/attachments"];
 
 // Boolean is extra debug, when true, we ignore the whitelist above and also print the mounts
 pub struct BetterLogging(pub bool);
@@ -588,7 +587,7 @@ impl<'de> Visitor<'de> for UpCaseVisitor {
 
 fn upcase_value(value: Value) -> Value {
     if let Value::Object(map) = value {
-        let mut new_value = json!({});
+        let mut new_value = Value::Object(serde_json::Map::new());
 
         for (key, val) in map.into_iter() {
             let processed_key = _process_key(&key);
@@ -597,7 +596,7 @@ fn upcase_value(value: Value) -> Value {
         new_value
     } else if let Value::Array(array) = value {
         // Initialize array with null values
-        let mut new_value = json!(vec![Value::Null; array.len()]);
+        let mut new_value = Value::Array(vec![Value::Null; array.len()]);
 
         for (index, val) in array.into_iter().enumerate() {
             new_value[index] = upcase_value(val);