From cf6fcd4ef2a5e7ec450ef73d04884b23630ccd1b Mon Sep 17 00:00:00 2001 From: goose Date: Sat, 27 Jun 2026 20:57:24 -0300 Subject: [PATCH] fix(backend): refresh-token jti + code cleanup (#15,#28,#29,#30) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Refresh-token rotation bug (found via Solaria smoke test): * RefreshClaims now carries a unique random jti (UUID v4). Without it, two refresh tokens issued in the same second (e.g. on rotation) were byte-identical — breaking rotation, colliding on the tokenHash unique index, and making a stolen old token indistinguishable from the new one. Every refresh token is now unique regardless of issue time. Added a unit test asserting consecutive tokens differ. Code cleanup (review items): * #15: removed unused deps tower_governor, slog, thiserror (zero refs in src/). * #30: deleted leftover src/main.rs.restore (a stale git-error-message backup). * #28: removed the 9 single-line-comment stub files under src/db/ (appointment, family, health_data, lab_result, medication, profile, permission, share, user) and their mod declarations; nothing referenced them, real logic lives in mongodb_impl.rs/init.rs. * #29: stripped 61 broad module-level #![allow(...)] suppressions across src/. Fixed the surfaced warnings instead: 4 unused 'claims' extractor bindings -> _claims; removed dead OpenFDAService.client/base_url fields + the never-called query_drug_events method + unused HashMap/reqwest imports; applied clippy's mechanical fixes (Ok(?) -> ?, Copy ObjectId clone, redundant closures, useless conversions); rewrote 'if let Ok(_) = x' -> 'if x.is_ok()'. Result: cargo build + clippy --all-targets are warning-free with no blanket allows. Verified: fmt clean, build clean, clippy 0 warnings, 19 unit tests pass (was 18; +1 jti-uniqueness test). --- backend/Cargo.lock | 158 -------------------- backend/Cargo.toml | 3 - backend/src/auth/jwt.rs | 33 +++- backend/src/auth/mod.rs | 1 - backend/src/config/mod.rs | 2 - backend/src/db/appointment.rs | 1 - backend/src/db/family.rs | 1 - backend/src/db/health_data.rs | 1 - backend/src/db/init.rs | 1 - backend/src/db/lab_result.rs | 1 - backend/src/db/medication.rs | 1 - backend/src/db/mod.rs | 12 -- backend/src/db/mongodb_impl.rs | 21 +-- backend/src/db/permission.rs | 2 - backend/src/db/profile.rs | 1 - backend/src/db/share.rs | 2 - backend/src/db/user.rs | 2 - backend/src/handlers/health.rs | 5 +- backend/src/handlers/health_stats.rs | 1 - backend/src/handlers/interactions.rs | 1 - backend/src/handlers/medications.rs | 11 +- backend/src/handlers/shares.rs | 7 +- backend/src/main.rs.restore | 2 - backend/src/middleware/auth.rs | 2 - backend/src/middleware/client_ip.rs | 1 - backend/src/middleware/rate_limit.rs | 2 - backend/src/models/appointment.rs | 1 - backend/src/models/audit_log.rs | 2 - backend/src/models/family.rs | 2 - backend/src/models/health_data.rs | 3 - backend/src/models/health_stats.rs | 1 - backend/src/models/interactions.rs | 1 - backend/src/models/lab_result.rs | 2 - backend/src/models/medication.rs | 2 - backend/src/models/permission.rs | 1 - backend/src/models/profile.rs | 2 - backend/src/models/refresh_token.rs | 1 - backend/src/models/session.rs | 2 - backend/src/models/share.rs | 6 - backend/src/models/user.rs | 2 - backend/src/security/audit_logger.rs | 2 - backend/src/security/session_manager.rs | 2 - backend/src/services/ingredient_mapper.rs | 2 - backend/src/services/interaction_service.rs | 1 - backend/src/services/openfda_service.rs | 41 +---- 45 files changed, 54 insertions(+), 297 deletions(-) delete mode 100644 backend/src/db/appointment.rs delete mode 100644 backend/src/db/family.rs delete mode 100644 backend/src/db/health_data.rs delete mode 100644 backend/src/db/lab_result.rs delete mode 100644 backend/src/db/medication.rs delete mode 100644 backend/src/db/permission.rs delete mode 100644 backend/src/db/profile.rs delete mode 100644 backend/src/db/share.rs delete mode 100644 backend/src/db/user.rs delete mode 100644 backend/src/main.rs.restore diff --git a/backend/Cargo.lock b/backend/Cargo.lock index 411f592..58bf0d5 100644 --- a/backend/Cargo.lock +++ b/backend/Cargo.lock @@ -280,12 +280,6 @@ dependencies = [ "libc", ] -[[package]] -name = "crossbeam-utils" -version = "0.8.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" - [[package]] name = "crypto-common" version = "0.1.7" @@ -331,19 +325,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "dashmap" -version = "5.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" -dependencies = [ - "cfg-if", - "hashbrown 0.14.5", - "lock_api", - "once_cell", - "parking_lot_core", -] - [[package]] name = "data-encoding" version = "2.10.0" @@ -438,15 +419,6 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" -[[package]] -name = "erased-serde" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c138974f9d5e7fe373eb04df7cae98833802ae4b11c24ac7039a21d5af4b26c" -dependencies = [ - "serde", -] - [[package]] name = "errno" version = "0.3.14" @@ -505,16 +477,6 @@ dependencies = [ "percent-encoding", ] -[[package]] -name = "forwarded-header-value" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8835f84f38484cc86f110a805655697908257fb9a7af005234060891557198e9" -dependencies = [ - "nonempty", - "thiserror 1.0.69", -] - [[package]] name = "funty" version = "2.0.0" @@ -592,12 +554,6 @@ version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" -[[package]] -name = "futures-timer" -version = "3.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f288b0a4f20f9a56b5d1da57e2227c661b7b16168e2f72365f57b63326e29b24" - [[package]] name = "futures-util" version = "0.3.32" @@ -665,26 +621,6 @@ dependencies = [ "wasip3", ] -[[package]] -name = "governor" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68a7f542ee6b35af73b06abc0dad1c1bae89964e4e253bc4b587b91c9637867b" -dependencies = [ - "cfg-if", - "dashmap", - "futures", - "futures-timer", - "no-std-compat", - "nonzero_ext", - "parking_lot", - "portable-atomic", - "quanta", - "rand 0.8.5", - "smallvec", - "spinning_top", -] - [[package]] name = "h2" version = "0.4.13" @@ -704,12 +640,6 @@ dependencies = [ "tracing", ] -[[package]] -name = "hashbrown" -version = "0.14.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" - [[package]] name = "hashbrown" version = "0.15.5" @@ -1291,24 +1221,6 @@ dependencies = [ "tempfile", ] -[[package]] -name = "no-std-compat" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b93853da6d84c2e3c7d730d6473e8817692dd89be387eb01b94d7f108ecb5b8c" - -[[package]] -name = "nonempty" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9e591e719385e6ebaeb5ce5d3887f7d5676fceca6411d1925ccc95745f3d6f7" - -[[package]] -name = "nonzero_ext" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38bf9645c8b145698bb0b18a4637dcacbc421ea49bef2317e4fd8065a387cf21" - [[package]] name = "normogen-backend" version = "0.1.0" @@ -1328,14 +1240,11 @@ dependencies = [ "serde", "serde_json", "sha2", - "slog", "strum", "strum_macros", - "thiserror 1.0.69", "tokio", "tower 0.4.13", "tower-http 0.5.2", - "tower_governor", "tracing", "tracing-subscriber", "uuid", @@ -1544,12 +1453,6 @@ version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" -[[package]] -name = "portable-atomic" -version = "1.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49" - [[package]] name = "potential_utf" version = "0.1.4" @@ -1617,21 +1520,6 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "quanta" -version = "0.12.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3ab5a9d756f0d97bdc89019bd2e4ea098cf9cde50ee7564dde6b81ccc8f06c7" -dependencies = [ - "crossbeam-utils", - "libc", - "once_cell", - "raw-cpuid", - "wasi", - "web-sys", - "winapi", -] - [[package]] name = "quote" version = "1.0.45" @@ -1718,15 +1606,6 @@ dependencies = [ "getrandom 0.3.4", ] -[[package]] -name = "raw-cpuid" -version = "11.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "498cd0dc59d73224351ee52a95fee0f1a617a2eae0e7d9d720cc622c73a54186" -dependencies = [ - "bitflags 2.11.0", -] - [[package]] name = "redox_syscall" version = "0.5.18" @@ -2175,18 +2054,6 @@ version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" -[[package]] -name = "slog" -version = "2.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b3b8565691b22d2bdfc066426ed48f837fc0c5f2c8cad8d9718f7f99d6995c1" -dependencies = [ - "anyhow", - "erased-serde", - "rustversion", - "serde_core", -] - [[package]] name = "smallvec" version = "1.15.1" @@ -2223,15 +2090,6 @@ dependencies = [ "windows-sys 0.61.2", ] -[[package]] -name = "spinning_top" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d96d2d1d716fb500937168cc09353ffdc7a012be8475ac7308e1bdf0e3923300" -dependencies = [ - "lock_api", -] - [[package]] name = "stable_deref_trait" version = "1.2.1" @@ -2626,22 +2484,6 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" -[[package]] -name = "tower_governor" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aea939ea6cfa7c4880f3e7422616624f97a567c16df67b53b11f0d03917a8e46" -dependencies = [ - "axum", - "forwarded-header-value", - "governor", - "http", - "pin-project", - "thiserror 1.0.69", - "tower 0.5.3", - "tracing", -] - [[package]] name = "tracing" version = "0.1.44" diff --git a/backend/Cargo.toml b/backend/Cargo.toml index f77cddc..62a529e 100644 --- a/backend/Cargo.toml +++ b/backend/Cargo.toml @@ -8,7 +8,6 @@ axum = "0.7.9" tokio = { version = "1.41.1", features = ["full"] } tower = { version = "0.4.13", features = ["util"] } tower-http = { version = "0.5.2", features = ["cors", "trace"] } -tower_governor = "0.4.3" serde = { version = "1.0.215", features = ["derive"] } serde_json = "1.0.133" mongodb = "2.8.2" @@ -23,11 +22,9 @@ password-hash = "0.5.0" rand = "0.8.5" base64 = "0.22.1" sha2 = "0.10" -thiserror = "1.0.69" anyhow = "1.0.94" tracing = "0.1.41" tracing-subscriber = { version = "0.3.19", features = ["env-filter"] } -slog = "2.7.0" strum = { version = "0.26", features = ["derive"] } strum_macros = "0.26" futures = "0.3" diff --git a/backend/src/auth/jwt.rs b/backend/src/auth/jwt.rs index 6ec6e37..7bd05cc 100644 --- a/backend/src/auth/jwt.rs +++ b/backend/src/auth/jwt.rs @@ -1,4 +1,3 @@ -#![allow(dead_code)] use anyhow::Result; use chrono::{Duration, Utc}; use jsonwebtoken::{decode, encode, DecodingKey, EncodingKey, Header, Validation}; @@ -41,12 +40,17 @@ pub struct RefreshClaims { pub sub: String, pub exp: usize, pub iat: usize, + /// Unique per-token id. Without this, two refresh tokens for the same user + /// issued in the same second (e.g. on rotation) would be byte-identical, + /// breaking rotation/reuse-detection. The jti makes every token unique. + pub jti: String, pub user_id: String, pub token_version: i32, } impl RefreshClaims { /// Build refresh-token claims. `expiry` is taken from `JwtConfig` by callers. + /// A fresh random `jti` is generated so each token is unique. pub fn new(user_id: String, token_version: i32, expiry: Duration) -> Self { let now = Utc::now(); let exp = now + expiry; @@ -55,6 +59,7 @@ impl RefreshClaims { sub: user_id.clone(), exp: exp.timestamp() as usize, iat: now.timestamp() as usize, + jti: uuid::Uuid::new_v4().to_string(), user_id, token_version, } @@ -175,4 +180,30 @@ mod tests { let refresh_claims = svc.validate_refresh_token(&refresh).unwrap(); assert_eq!(refresh_claims.token_version, 3); } + + /// Two refresh tokens issued back-to-back for the same user must be distinct, + /// even though everything else (sub, user_id, token_version, iat, exp) is + /// identical. The jti claim guarantees this — without it, rotation would + /// mint a byte-identical token and break reuse detection. + #[test] + fn refresh_tokens_are_unique_even_in_same_second() { + let svc = JwtService::new(test_config()); + let claims = Claims::new( + "user-3".to_string(), + "u3@example.com".to_string(), + 0, + Duration::minutes(15), + ); + let (_, refresh_a) = svc.generate_tokens(claims.clone()).unwrap(); + let (_, refresh_b) = svc.generate_tokens(claims).unwrap(); + assert_ne!( + refresh_a, refresh_b, + "consecutive refresh tokens must differ (jti)" + ); + + // And the jti values themselves differ. + let jti_a = svc.validate_refresh_token(&refresh_a).unwrap().jti; + let jti_b = svc.validate_refresh_token(&refresh_b).unwrap().jti; + assert_ne!(jti_a, jti_b); + } } diff --git a/backend/src/auth/mod.rs b/backend/src/auth/mod.rs index 8a1993f..956b164 100644 --- a/backend/src/auth/mod.rs +++ b/backend/src/auth/mod.rs @@ -1,4 +1,3 @@ -#![allow(dead_code)] pub mod jwt; pub mod password; pub mod token_version_cache; diff --git a/backend/src/config/mod.rs b/backend/src/config/mod.rs index 30fdc63..edb6869 100644 --- a/backend/src/config/mod.rs +++ b/backend/src/config/mod.rs @@ -1,5 +1,3 @@ -#![allow(dead_code)] -#![allow(unused_imports)] use anyhow::Result; use std::sync::Arc; diff --git a/backend/src/db/appointment.rs b/backend/src/db/appointment.rs deleted file mode 100644 index 77cf576..0000000 --- a/backend/src/db/appointment.rs +++ /dev/null @@ -1 +0,0 @@ -// Stub for future appointment operations diff --git a/backend/src/db/family.rs b/backend/src/db/family.rs deleted file mode 100644 index 9d0d242..0000000 --- a/backend/src/db/family.rs +++ /dev/null @@ -1 +0,0 @@ -// Stub for future family operations diff --git a/backend/src/db/health_data.rs b/backend/src/db/health_data.rs deleted file mode 100644 index 088ad7c..0000000 --- a/backend/src/db/health_data.rs +++ /dev/null @@ -1 +0,0 @@ -// Stub for future health_data operations diff --git a/backend/src/db/init.rs b/backend/src/db/init.rs index 0e0ffc1..8193095 100644 --- a/backend/src/db/init.rs +++ b/backend/src/db/init.rs @@ -1,4 +1,3 @@ -#![allow(dead_code)] use mongodb::{bson::doc, options::IndexOptions, Collection, IndexModel}; use anyhow::Result; diff --git a/backend/src/db/lab_result.rs b/backend/src/db/lab_result.rs deleted file mode 100644 index 4ffed49..0000000 --- a/backend/src/db/lab_result.rs +++ /dev/null @@ -1 +0,0 @@ -// Stub for future lab_result operations diff --git a/backend/src/db/medication.rs b/backend/src/db/medication.rs deleted file mode 100644 index 3bdbf68..0000000 --- a/backend/src/db/medication.rs +++ /dev/null @@ -1 +0,0 @@ -// Stub for future medication operations diff --git a/backend/src/db/mod.rs b/backend/src/db/mod.rs index bb4df1a..7b3c125 100644 --- a/backend/src/db/mod.rs +++ b/backend/src/db/mod.rs @@ -1,19 +1,7 @@ -#![allow(dead_code)] -#![allow(clippy::useless_conversion)] use anyhow::Result; use mongodb::{Client, Database}; use std::env; -pub mod appointment; -pub mod family; -pub mod health_data; -pub mod lab_result; -pub mod medication; -pub mod permission; -pub mod profile; -pub mod share; -pub mod user; - pub mod init; // Database initialization module mod mongodb_impl; diff --git a/backend/src/db/mongodb_impl.rs b/backend/src/db/mongodb_impl.rs index 4107fc5..861b34e 100644 --- a/backend/src/db/mongodb_impl.rs +++ b/backend/src/db/mongodb_impl.rs @@ -1,4 +1,3 @@ -#![allow(clippy::needless_question_mark)] use anyhow::Result; use mongodb::bson::oid::ObjectId; use mongodb::{bson::doc, options::ClientOptions, Client, Collection, Database}; @@ -286,10 +285,9 @@ impl MongoDb { pub async fn get_medication(&self, id: &str) -> Result> { let object_id = ObjectId::parse_str(id)?; let repo = MedicationRepository::new(self.medications.clone()); - Ok(repo - .find_by_id(&object_id) + repo.find_by_id(&object_id) .await - .map_err(|e| anyhow::anyhow!("Failed to get medication: {}", e))?) + .map_err(|e| anyhow::anyhow!("Failed to get medication: {}", e)) } pub async fn list_medications( @@ -318,19 +316,17 @@ impl MongoDb { ) -> Result> { let object_id = ObjectId::parse_str(id)?; let repo = MedicationRepository::new(self.medications.clone()); - Ok(repo - .update(&object_id, updates) + repo.update(&object_id, updates) .await - .map_err(|e| anyhow::anyhow!("Failed to update medication: {}", e))?) + .map_err(|e| anyhow::anyhow!("Failed to update medication: {}", e)) } pub async fn delete_medication(&self, id: &str) -> Result { let object_id = ObjectId::parse_str(id)?; let repo = MedicationRepository::new(self.medications.clone()); - Ok(repo - .delete(&object_id) + repo.delete(&object_id) .await - .map_err(|e| anyhow::anyhow!("Failed to delete medication: {}", e))?) + .map_err(|e| anyhow::anyhow!("Failed to delete medication: {}", e)) } pub async fn log_medication_dose(&self, dose: &MedicationDose) -> Result> { @@ -349,9 +345,8 @@ impl MongoDb { days: i64, ) -> Result { let repo = MedicationRepository::new(self.medications.clone()); - Ok(repo - .calculate_adherence(medication_id, days) + repo.calculate_adherence(medication_id, days) .await - .map_err(|e| anyhow::anyhow!("Failed to calculate adherence: {}", e))?) + .map_err(|e| anyhow::anyhow!("Failed to calculate adherence: {}", e)) } } diff --git a/backend/src/db/permission.rs b/backend/src/db/permission.rs deleted file mode 100644 index 6639bce..0000000 --- a/backend/src/db/permission.rs +++ /dev/null @@ -1,2 +0,0 @@ -// Permission-related database operations are in MongoDb struct -// This file exists for module organization diff --git a/backend/src/db/profile.rs b/backend/src/db/profile.rs deleted file mode 100644 index e8d20ea..0000000 --- a/backend/src/db/profile.rs +++ /dev/null @@ -1 +0,0 @@ -// Stub for future profile operations diff --git a/backend/src/db/share.rs b/backend/src/db/share.rs deleted file mode 100644 index ed94a98..0000000 --- a/backend/src/db/share.rs +++ /dev/null @@ -1,2 +0,0 @@ -// Share-related database operations are in MongoDb struct -// This file exists for module organization diff --git a/backend/src/db/user.rs b/backend/src/db/user.rs deleted file mode 100644 index a77a7fa..0000000 --- a/backend/src/db/user.rs +++ /dev/null @@ -1,2 +0,0 @@ -// User-related database operations are in MongoDb struct -// This file exists for module organization diff --git a/backend/src/handlers/health.rs b/backend/src/handlers/health.rs index d30a84d..41e6393 100644 --- a/backend/src/handlers/health.rs +++ b/backend/src/handlers/health.rs @@ -1,12 +1,9 @@ -#![allow(dead_code)] -#![allow(unused_imports)] -#![allow(clippy::redundant_pattern_matching)] use crate::config::AppState; use axum::{extract::State, response::Json}; use serde_json::{json, Value}; pub async fn health_check(State(state): State) -> Json { - let status = if let Ok(_) = state.db.health_check().await { + let status = if state.db.health_check().await.is_ok() { "connected" } else { "error" diff --git a/backend/src/handlers/health_stats.rs b/backend/src/handlers/health_stats.rs index ce0126b..3db6a67 100644 --- a/backend/src/handlers/health_stats.rs +++ b/backend/src/handlers/health_stats.rs @@ -1,4 +1,3 @@ -#![allow(dead_code)] use crate::auth::jwt::Claims; use crate::config::AppState; use crate::models::health_stats::HealthStatistic; diff --git a/backend/src/handlers/interactions.rs b/backend/src/handlers/interactions.rs index 396b239..ce7c2e3 100644 --- a/backend/src/handlers/interactions.rs +++ b/backend/src/handlers/interactions.rs @@ -1,4 +1,3 @@ -#![allow(dead_code)] //! Drug Interaction Handlers (Phase 2.8) use axum::{ diff --git a/backend/src/handlers/medications.rs b/backend/src/handlers/medications.rs index 939f465..2b6fd35 100644 --- a/backend/src/handlers/medications.rs +++ b/backend/src/handlers/medications.rs @@ -1,6 +1,3 @@ -#![allow(dead_code)] -#![allow(unused_imports)] -#![allow(unused_variables)] use axum::{ extract::{Extension, Json, Path, Query, State}, http::StatusCode, @@ -103,7 +100,7 @@ pub async fn list_medications( pub async fn get_medication( State(state): State, - Extension(claims): Extension, + Extension(_claims): Extension, Path(id): Path, ) -> Result, StatusCode> { let database = state.db.get_database(); @@ -121,7 +118,7 @@ pub async fn get_medication( pub async fn update_medication( State(state): State, - Extension(claims): Extension, + Extension(_claims): Extension, Path(id): Path, Json(req): Json, ) -> Result, StatusCode> { @@ -140,7 +137,7 @@ pub async fn update_medication( pub async fn delete_medication( State(state): State, - Extension(claims): Extension, + Extension(_claims): Extension, Path(id): Path, ) -> Result { let database = state.db.get_database(); @@ -188,7 +185,7 @@ pub async fn log_dose( pub async fn get_adherence( State(state): State, - Extension(claims): Extension, + Extension(_claims): Extension, Path(id): Path, ) -> Result, StatusCode> { let database = state.db.get_database(); diff --git a/backend/src/handlers/shares.rs b/backend/src/handlers/shares.rs index c13d209..4481f96 100644 --- a/backend/src/handlers/shares.rs +++ b/backend/src/handlers/shares.rs @@ -1,8 +1,3 @@ -#![allow(dead_code)] -#![allow(unused_imports)] -#![allow(clippy::redundant_closure)] -#![allow(clippy::useless_conversion)] -#![allow(clippy::clone_on_copy)] use axum::{ extract::{Path, State}, http::StatusCode, @@ -171,7 +166,7 @@ pub async fn create_share( }); let share = Share::new( - owner_id.clone(), + owner_id, target_user_id, req.resource_type, resource_id, diff --git a/backend/src/main.rs.restore b/backend/src/main.rs.restore deleted file mode 100644 index dc5d375..0000000 --- a/backend/src/main.rs.restore +++ /dev/null @@ -1,2 +0,0 @@ -fatal: path 'backend/src/main.rs' exists, but not 'src/main.rs' -hint: Did you mean 'a316699:backend/src/main.rs' aka 'a316699:./src/main.rs'? diff --git a/backend/src/middleware/auth.rs b/backend/src/middleware/auth.rs index 1d16aca..11cda49 100644 --- a/backend/src/middleware/auth.rs +++ b/backend/src/middleware/auth.rs @@ -1,5 +1,3 @@ -#![allow(dead_code)] -#![allow(unused_imports)] use crate::auth::jwt::Claims; use crate::config::AppState; use axum::{ diff --git a/backend/src/middleware/client_ip.rs b/backend/src/middleware/client_ip.rs index 90cf855..21ee503 100644 --- a/backend/src/middleware/client_ip.rs +++ b/backend/src/middleware/client_ip.rs @@ -8,7 +8,6 @@ //! 3. The peer address from Axum's `ConnectInfo` (direct connection). //! 4. `"0.0.0.0"` only if none of the above are present. -#![allow(dead_code)] use axum::{ extract::ConnectInfo, extract::Request, http::HeaderMap, middleware::Next, response::Response, }; diff --git a/backend/src/middleware/rate_limit.rs b/backend/src/middleware/rate_limit.rs index 84808aa..b10f95e 100644 --- a/backend/src/middleware/rate_limit.rs +++ b/backend/src/middleware/rate_limit.rs @@ -1,5 +1,3 @@ -#![allow(dead_code)] -#![allow(unused_imports)] use axum::{extract::Request, http::StatusCode, middleware::Next, response::Response}; /// Middleware for general rate limiting diff --git a/backend/src/models/appointment.rs b/backend/src/models/appointment.rs index 12219ec..0e0b144 100644 --- a/backend/src/models/appointment.rs +++ b/backend/src/models/appointment.rs @@ -1,4 +1,3 @@ -#![allow(dead_code)] use serde::{Deserialize, Serialize}; use mongodb::bson::{oid::ObjectId, DateTime}; use super::health_data::EncryptedField; diff --git a/backend/src/models/audit_log.rs b/backend/src/models/audit_log.rs index 327d215..0704717 100644 --- a/backend/src/models/audit_log.rs +++ b/backend/src/models/audit_log.rs @@ -1,5 +1,3 @@ -#![allow(dead_code)] -#![allow(unused_imports)] use anyhow::Result; use futures::stream::TryStreamExt; use mongodb::{ diff --git a/backend/src/models/family.rs b/backend/src/models/family.rs index b9eb4a5..9aa9a90 100644 --- a/backend/src/models/family.rs +++ b/backend/src/models/family.rs @@ -1,5 +1,3 @@ -#![allow(dead_code)] -#![allow(unused_imports)] use mongodb::{ bson::{doc, oid::ObjectId, DateTime}, Collection, diff --git a/backend/src/models/health_data.rs b/backend/src/models/health_data.rs index eaaf69d..f55efe4 100644 --- a/backend/src/models/health_data.rs +++ b/backend/src/models/health_data.rs @@ -1,6 +1,3 @@ -#![allow(dead_code)] -#![allow(clippy::useless_conversion)] -#![allow(unused_imports)] use mongodb::bson::{oid::ObjectId, DateTime}; use serde::{Deserialize, Serialize}; diff --git a/backend/src/models/health_stats.rs b/backend/src/models/health_stats.rs index 4f467c7..a03d78d 100644 --- a/backend/src/models/health_stats.rs +++ b/backend/src/models/health_stats.rs @@ -1,4 +1,3 @@ -#![allow(dead_code)] use futures::stream::TryStreamExt; use mongodb::Collection; use mongodb::{ diff --git a/backend/src/models/interactions.rs b/backend/src/models/interactions.rs index ea7bb28..f4b526e 100644 --- a/backend/src/models/interactions.rs +++ b/backend/src/models/interactions.rs @@ -1,4 +1,3 @@ -#![allow(dead_code)] //! Interaction Models //! //! Database models for drug interactions diff --git a/backend/src/models/lab_result.rs b/backend/src/models/lab_result.rs index 167346b..50f179f 100644 --- a/backend/src/models/lab_result.rs +++ b/backend/src/models/lab_result.rs @@ -1,5 +1,3 @@ -#![allow(dead_code)] -#![allow(unused_imports)] use futures::stream::TryStreamExt; use mongodb::{bson::oid::ObjectId, Collection}; use serde::{Deserialize, Serialize}; diff --git a/backend/src/models/medication.rs b/backend/src/models/medication.rs index 3efe3ab..ff70bd4 100644 --- a/backend/src/models/medication.rs +++ b/backend/src/models/medication.rs @@ -1,5 +1,3 @@ -#![allow(dead_code)] -#![allow(unused_imports)] use super::health_data::EncryptedField; use futures::stream::StreamExt; use mongodb::bson::{doc, oid::ObjectId, DateTime}; diff --git a/backend/src/models/permission.rs b/backend/src/models/permission.rs index 4cb9071..db0513c 100644 --- a/backend/src/models/permission.rs +++ b/backend/src/models/permission.rs @@ -1,4 +1,3 @@ -#![allow(dead_code)] use serde::{Deserialize, Serialize}; use std::fmt; diff --git a/backend/src/models/profile.rs b/backend/src/models/profile.rs index 361ad8f..9f828ce 100644 --- a/backend/src/models/profile.rs +++ b/backend/src/models/profile.rs @@ -1,5 +1,3 @@ -#![allow(dead_code)] -#![allow(unused_imports)] use mongodb::{ bson::{doc, oid::ObjectId, DateTime}, Collection, diff --git a/backend/src/models/refresh_token.rs b/backend/src/models/refresh_token.rs index d9d8e30..90a9ce4 100644 --- a/backend/src/models/refresh_token.rs +++ b/backend/src/models/refresh_token.rs @@ -1,4 +1,3 @@ -#![allow(dead_code)] use anyhow::Result; use base64::Engine; use mongodb::{ diff --git a/backend/src/models/session.rs b/backend/src/models/session.rs index 0471d1c..e26272a 100644 --- a/backend/src/models/session.rs +++ b/backend/src/models/session.rs @@ -1,5 +1,3 @@ -#![allow(dead_code)] -#![allow(unused_imports)] use anyhow::Result; use futures::stream::TryStreamExt; use mongodb::{ diff --git a/backend/src/models/share.rs b/backend/src/models/share.rs index 8a42b83..2a9df80 100644 --- a/backend/src/models/share.rs +++ b/backend/src/models/share.rs @@ -1,7 +1,3 @@ -#![allow(dead_code)] -#![allow(unused_imports)] -#![allow(clippy::redundant_closure)] -#![allow(clippy::useless_conversion)] use mongodb::bson::DateTime; use mongodb::bson::{doc, oid::ObjectId}; use mongodb::Collection; @@ -91,7 +87,6 @@ impl ShareRepository { .await? .try_collect() .await - .map_err(|e| mongodb::error::Error::from(e)) } pub async fn find_by_target( @@ -108,7 +103,6 @@ impl ShareRepository { .await? .try_collect() .await - .map_err(|e| mongodb::error::Error::from(e)) } pub async fn update(&self, share: &Share) -> mongodb::error::Result<()> { diff --git a/backend/src/models/user.rs b/backend/src/models/user.rs index 6552d97..53b9cf8 100644 --- a/backend/src/models/user.rs +++ b/backend/src/models/user.rs @@ -1,5 +1,3 @@ -#![allow(dead_code)] -#![allow(unused_imports)] use mongodb::bson::{doc, oid::ObjectId}; use mongodb::Collection; use serde::{Deserialize, Serialize}; diff --git a/backend/src/security/audit_logger.rs b/backend/src/security/audit_logger.rs index bdfef70..23bdde3 100644 --- a/backend/src/security/audit_logger.rs +++ b/backend/src/security/audit_logger.rs @@ -1,5 +1,3 @@ -#![allow(dead_code)] -#![allow(unused_imports)] use crate::models::audit_log::{AuditEventType, AuditLog, AuditLogRepository}; use anyhow::Result; use mongodb::bson::oid::ObjectId; diff --git a/backend/src/security/session_manager.rs b/backend/src/security/session_manager.rs index 1284f5c..6945d68 100644 --- a/backend/src/security/session_manager.rs +++ b/backend/src/security/session_manager.rs @@ -1,5 +1,3 @@ -#![allow(dead_code)] -#![allow(unused_imports)] use crate::models::session::{DeviceInfo, Session, SessionRepository}; use anyhow::Result; use mongodb::bson::oid::ObjectId; diff --git a/backend/src/services/ingredient_mapper.rs b/backend/src/services/ingredient_mapper.rs index 064b4e5..0e22c5f 100644 --- a/backend/src/services/ingredient_mapper.rs +++ b/backend/src/services/ingredient_mapper.rs @@ -1,5 +1,3 @@ -#![allow(dead_code)] -#![allow(unused_imports)] //! Ingredient Mapper Service //! //! Maps EU drug names to US drug names for interaction checking diff --git a/backend/src/services/interaction_service.rs b/backend/src/services/interaction_service.rs index 71feac9..f252319 100644 --- a/backend/src/services/interaction_service.rs +++ b/backend/src/services/interaction_service.rs @@ -1,4 +1,3 @@ -#![allow(dead_code)] //! Interaction Service //! //! Combines ingredient mapping and OpenFDA interaction checking diff --git a/backend/src/services/openfda_service.rs b/backend/src/services/openfda_service.rs index cbfa1b3..ba5859d 100644 --- a/backend/src/services/openfda_service.rs +++ b/backend/src/services/openfda_service.rs @@ -1,8 +1,10 @@ -#![allow(dead_code)] -#![allow(unused_imports)] -use reqwest::Client; use serde::{Deserialize, Serialize}; -use std::collections::HashMap; + +// NOTE: the real OpenFDA API query (reqwest -> api.fda.gov) was a dead-code +// stub (`query_drug_events`, never called) and has been removed for now. +// `check_interactions` currently uses a built-in table of known interactions. +// When the live OpenFDA integration is wired up, re-add reqwest + the query +// method here. #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] #[serde(rename_all = "lowercase")] @@ -21,17 +23,11 @@ pub struct DrugInteraction { pub description: String, } -pub struct OpenFDAService { - client: Client, - base_url: String, -} +pub struct OpenFDAService; impl OpenFDAService { pub fn new() -> Self { - Self { - client: Client::new(), - base_url: "https://api.fda.gov/drug/event.json".to_string(), - } + Self } /// Check for interactions between multiple drugs @@ -110,27 +106,6 @@ impl OpenFDAService { None } - - /// Query OpenFDA for drug event reports - async fn query_drug_events( - &self, - drug_name: &str, - ) -> Result> { - let query = format!( - "{}?search=patient.drug.medicinalproduct:{}&limit=10", - self.base_url, drug_name - ); - - let response = self - .client - .get(&query) - .send() - .await? - .json::() - .await?; - - Ok(response) - } } impl Default for OpenFDAService {