diff --git a/Cargo.lock b/Cargo.lock index 93926ac4e7f..24ac1c2e6ea 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -621,6 +621,7 @@ dependencies = [ "num-bigint", "num-integer", "num-traits", + "serde", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 9a3fa54208b..bb4f6ed32d6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -56,7 +56,7 @@ aws-sdk-sqs = "=1.15.0" axum = { version = "=0.7.4", features = ["macros", "matched-path"] } axum-extra = { version = "=0.9.2", features = ["cookie-signed", "typed-header"] } base64 = "=0.22.0" -bigdecimal = "=0.4.3" +bigdecimal = { version = "=0.4.3", features = ["serde"] } cargo-manifest = "=0.13.0" crates_io_cdn_logs = { path = "crates_io_cdn_logs" } crates_io_env_vars = { path = "crates_io_env_vars" } diff --git a/src/controllers/user/other.rs b/src/controllers/user/other.rs index 21ea742e522..4441d6c6ff3 100644 --- a/src/controllers/user/other.rs +++ b/src/controllers/user/other.rs @@ -1,7 +1,8 @@ use crate::controllers::frontend_prelude::*; +use bigdecimal::{BigDecimal, ToPrimitive}; use crate::models::{CrateOwner, OwnerKind, User}; -use crate::schema::{crate_owners, crates, users}; +use crate::schema::{crate_downloads, crate_owners, crates, users}; use crate::sql::lower; use crate::views::EncodablePublicUser; @@ -29,11 +30,13 @@ pub async fn stats(state: AppState, Path(user_id): Path) -> AppResult>(conn)? + .select(sum(crate_downloads::downloads)) + .first::>(conn)? + .map(|d| d.to_u64().unwrap_or(u64::MAX)) .unwrap_or(0); Ok(Json(json!({ "total_downloads": data }))) diff --git a/src/tests/routes/users/stats.rs b/src/tests/routes/users/stats.rs index fd98afcab00..204028516d8 100644 --- a/src/tests/routes/users/stats.rs +++ b/src/tests/routes/users/stats.rs @@ -9,7 +9,9 @@ struct UserStats { fn user_total_downloads() { use crate::builders::CrateBuilder; use crate::util::{RequestHelper, TestApp}; - use diesel::{update, RunQueryDsl}; + use crates_io::schema::crate_downloads; + use diesel::prelude::*; + use diesel::{update, QueryDsl, RunQueryDsl}; let (app, anon, user) = TestApp::init().with_user(); let user = user.as_model(); @@ -17,25 +19,27 @@ fn user_total_downloads() { let another_user = another_user.as_model(); app.db(|conn| { - let mut krate = CrateBuilder::new("foo_krate1", user.id).expect_build(conn); - krate.downloads = 10; - update(&krate).set(&krate).execute(conn).unwrap(); - - let mut krate2 = CrateBuilder::new("foo_krate2", user.id).expect_build(conn); - krate2.downloads = 20; - update(&krate2).set(&krate2).execute(conn).unwrap(); - - let mut another_krate = CrateBuilder::new("bar_krate1", another_user.id).expect_build(conn); - another_krate.downloads = 2; - update(&another_krate) - .set(&another_krate) + let krate = CrateBuilder::new("foo_krate1", user.id).expect_build(conn); + update(crate_downloads::table.filter(crate_downloads::crate_id.eq(krate.id))) + .set(crate_downloads::downloads.eq(10)) .execute(conn) .unwrap(); - let mut no_longer_my_krate = CrateBuilder::new("nacho", user.id).expect_build(conn); - no_longer_my_krate.downloads = 5; - update(&no_longer_my_krate) - .set(&no_longer_my_krate) + let krate2 = CrateBuilder::new("foo_krate2", user.id).expect_build(conn); + update(crate_downloads::table.filter(crate_downloads::crate_id.eq(krate2.id))) + .set(crate_downloads::downloads.eq(20)) + .execute(conn) + .unwrap(); + + let another_krate = CrateBuilder::new("bar_krate1", another_user.id).expect_build(conn); + update(crate_downloads::table.filter(crate_downloads::crate_id.eq(another_krate.id))) + .set(crate_downloads::downloads.eq(2)) + .execute(conn) + .unwrap(); + + let no_longer_my_krate = CrateBuilder::new("nacho", user.id).expect_build(conn); + update(crate_downloads::table.filter(crate_downloads::crate_id.eq(no_longer_my_krate.id))) + .set(crate_downloads::downloads.eq(5)) .execute(conn) .unwrap(); no_longer_my_krate