From 5bab2120e71ed6621e885f6c117280efc02df995 Mon Sep 17 00:00:00 2001 From: Denis Savchuk Date: Thu, 26 Dec 2019 16:37:43 +0400 Subject: [PATCH 1/5] user: Add `has_token` field --- src/controllers/user/me.rs | 14 ++++++++++---- src/models/user.rs | 2 ++ src/tests/user.rs | 18 +++++++++++++++++- src/views.rs | 1 + 4 files changed, 30 insertions(+), 5 deletions(-) diff --git a/src/controllers/user/me.rs b/src/controllers/user/me.rs index 5dd184a9220..ea57af6086e 100644 --- a/src/controllers/user/me.rs +++ b/src/controllers/user/me.rs @@ -7,14 +7,15 @@ use crate::email; use crate::controllers::helpers::pagination::Paginated; use crate::models::{ - CrateOwner, Email, Follow, NewEmail, OwnerKind, User, Version, VersionOwnerAction, + ApiToken, CrateOwner, Email, Follow, NewEmail, OwnerKind, User, Version, VersionOwnerAction, }; -use crate::schema::{crate_owners, crates, emails, follows, users, versions}; +use crate::schema::{api_tokens, crate_owners, crates, emails, follows, users, versions}; use crate::views::{EncodableMe, EncodableVersion, OwnedCrate}; /// Handles the `GET /me` route. pub fn me(req: &mut dyn RequestExt) -> EndpointResult { - let user_id = req.authenticate()?.user_id(); + let user = req.authenticate()?; + let user_id = user.user_id(); let conn = req.db_conn()?; let (user, verified, email, verification_sent): (User, Option, Option, bool) = @@ -29,6 +30,11 @@ pub fn me(req: &mut dyn RequestExt) -> EndpointResult { )) .first(&*conn)?; + let tokens: Vec = ApiToken::belonging_to(&user) + .filter(api_tokens::revoked.eq(false)) + .load(&*conn)?; + let has_tokens = !tokens.is_empty(); + let owned_crates = CrateOwner::by_owner_kind(OwnerKind::User) .inner_join(crates::table) .filter(crate_owners::owner_id.eq(user_id)) @@ -46,7 +52,7 @@ pub fn me(req: &mut dyn RequestExt) -> EndpointResult { let verified = verified.unwrap_or(false); let verification_sent = verified || verification_sent; Ok(req.json(&EncodableMe { - user: user.encodable_private(email, verified, verification_sent), + user: user.encodable_private(email, verified, verification_sent, has_tokens), owned_crates, })) } diff --git a/src/models/user.rs b/src/models/user.rs index c577af7bd31..7007f24fbb6 100644 --- a/src/models/user.rs +++ b/src/models/user.rs @@ -174,6 +174,7 @@ impl User { email: Option, email_verified: bool, email_verification_sent: bool, + has_tokens: bool, ) -> EncodablePrivateUser { let User { id, @@ -189,6 +190,7 @@ impl User { email, email_verified, email_verification_sent, + has_tokens, avatar: gh_avatar, login: gh_login, name, diff --git a/src/tests/user.rs b/src/tests/user.rs index db280868dc4..826f65be8f4 100644 --- a/src/tests/user.rs +++ b/src/tests/user.rs @@ -5,7 +5,7 @@ use crate::{ OkBool, TestApp, }; use cargo_registry::{ - models::{Email, NewUser, User}, + models::{ApiToken, Email, NewUser, User}, schema::crate_owners, views::{EncodablePrivateUser, EncodablePublicUser, EncodableVersion, OwnedCrate}, }; @@ -748,3 +748,19 @@ fn test_update_email_notifications_not_owned() { // There should be no change to the `email_notifications` value for a crate not belonging to me assert!(email_notifications); } + +#[test] +fn shows_that_user_has_tokens() { + let (app, _, user) = TestApp::init().with_user(); + + let user_id = user.as_model().id; + app.db(|conn| { + vec![ + assert_ok!(ApiToken::insert(conn, user_id, "bar")), + assert_ok!(ApiToken::insert(conn, user_id, "baz")), + ] + }); + + let json = user.show_me(); + assert!(json.user.has_tokens); +} diff --git a/src/views.rs b/src/views.rs index 228335e6e9e..f483e1f9b96 100644 --- a/src/views.rs +++ b/src/views.rs @@ -176,6 +176,7 @@ pub struct EncodablePrivateUser { pub email: Option, pub avatar: Option, pub url: Option, + pub has_tokens: bool, } /// The serialization format for the `User` model. From 099e402ad386bbbc1e80936d99b8047656573509 Mon Sep 17 00:00:00 2001 From: Tobias Bieniek Date: Fri, 4 Dec 2020 19:28:50 +0100 Subject: [PATCH 2/5] user: Add additional `has_tokens` assertion --- src/tests/user.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/tests/user.rs b/src/tests/user.rs index 826f65be8f4..24adebb55cf 100644 --- a/src/tests/user.rs +++ b/src/tests/user.rs @@ -753,6 +753,9 @@ fn test_update_email_notifications_not_owned() { fn shows_that_user_has_tokens() { let (app, _, user) = TestApp::init().with_user(); + let json = user.show_me(); + assert!(!json.user.has_tokens); + let user_id = user.as_model().id; app.db(|conn| { vec![ From 974caff38b2684513d4f816d5140d8b0be4de4cb Mon Sep 17 00:00:00 2001 From: Tobias Bieniek Date: Fri, 4 Dec 2020 19:36:00 +0100 Subject: [PATCH 3/5] user: Move `has_tokens` property from `user` to a `meta` object --- src/controllers/user/me.rs | 5 +++-- src/models/user.rs | 2 -- src/tests/user.rs | 9 ++++++--- src/views.rs | 7 ++++++- 4 files changed, 15 insertions(+), 8 deletions(-) diff --git a/src/controllers/user/me.rs b/src/controllers/user/me.rs index ea57af6086e..eb070ca5577 100644 --- a/src/controllers/user/me.rs +++ b/src/controllers/user/me.rs @@ -10,7 +10,7 @@ use crate::models::{ ApiToken, CrateOwner, Email, Follow, NewEmail, OwnerKind, User, Version, VersionOwnerAction, }; use crate::schema::{api_tokens, crate_owners, crates, emails, follows, users, versions}; -use crate::views::{EncodableMe, EncodableVersion, OwnedCrate}; +use crate::views::{EncodableMe, EncodableMeMeta, EncodableVersion, OwnedCrate}; /// Handles the `GET /me` route. pub fn me(req: &mut dyn RequestExt) -> EndpointResult { @@ -52,8 +52,9 @@ pub fn me(req: &mut dyn RequestExt) -> EndpointResult { let verified = verified.unwrap_or(false); let verification_sent = verified || verification_sent; Ok(req.json(&EncodableMe { - user: user.encodable_private(email, verified, verification_sent, has_tokens), + user: user.encodable_private(email, verified, verification_sent), owned_crates, + meta: EncodableMeMeta { has_tokens }, })) } diff --git a/src/models/user.rs b/src/models/user.rs index 7007f24fbb6..c577af7bd31 100644 --- a/src/models/user.rs +++ b/src/models/user.rs @@ -174,7 +174,6 @@ impl User { email: Option, email_verified: bool, email_verification_sent: bool, - has_tokens: bool, ) -> EncodablePrivateUser { let User { id, @@ -190,7 +189,6 @@ impl User { email, email_verified, email_verification_sent, - has_tokens, avatar: gh_avatar, login: gh_login, name, diff --git a/src/tests/user.rs b/src/tests/user.rs index 24adebb55cf..ee4f6f39bff 100644 --- a/src/tests/user.rs +++ b/src/tests/user.rs @@ -7,7 +7,9 @@ use crate::{ use cargo_registry::{ models::{ApiToken, Email, NewUser, User}, schema::crate_owners, - views::{EncodablePrivateUser, EncodablePublicUser, EncodableVersion, OwnedCrate}, + views::{ + EncodableMeMeta, EncodablePrivateUser, EncodablePublicUser, EncodableVersion, OwnedCrate, + }, }; use diesel::prelude::*; @@ -27,6 +29,7 @@ pub struct UserShowPublicResponse { pub struct UserShowPrivateResponse { pub user: EncodablePrivateUser, pub owned_crates: Vec, + pub meta: EncodableMeMeta, } #[derive(Deserialize)] @@ -754,7 +757,7 @@ fn shows_that_user_has_tokens() { let (app, _, user) = TestApp::init().with_user(); let json = user.show_me(); - assert!(!json.user.has_tokens); + assert!(!json.meta.has_tokens); let user_id = user.as_model().id; app.db(|conn| { @@ -765,5 +768,5 @@ fn shows_that_user_has_tokens() { }); let json = user.show_me(); - assert!(json.user.has_tokens); + assert!(json.meta.has_tokens); } diff --git a/src/views.rs b/src/views.rs index f483e1f9b96..250988d3ea0 100644 --- a/src/views.rs +++ b/src/views.rs @@ -161,6 +161,12 @@ pub struct OwnedCrate { pub struct EncodableMe { pub user: EncodablePrivateUser, pub owned_crates: Vec, + pub meta: EncodableMeMeta, +} + +#[derive(Serialize, Deserialize, Debug, Clone, Copy)] +pub struct EncodableMeMeta { + pub has_tokens: bool, } /// The serialization format for the `User` model. @@ -176,7 +182,6 @@ pub struct EncodablePrivateUser { pub email: Option, pub avatar: Option, pub url: Option, - pub has_tokens: bool, } /// The serialization format for the `User` model. From ded1aa44eaf8cb05252f88021c040dd6c04d662d Mon Sep 17 00:00:00 2001 From: Tobias Bieniek Date: Fri, 4 Dec 2020 19:41:21 +0100 Subject: [PATCH 4/5] user: Convert `has_tokens` to `token_count` --- src/controllers/user/me.rs | 5 +++-- src/tests/user.rs | 4 ++-- src/views.rs | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/controllers/user/me.rs b/src/controllers/user/me.rs index eb070ca5577..9ebd1e05ebd 100644 --- a/src/controllers/user/me.rs +++ b/src/controllers/user/me.rs @@ -33,7 +33,8 @@ pub fn me(req: &mut dyn RequestExt) -> EndpointResult { let tokens: Vec = ApiToken::belonging_to(&user) .filter(api_tokens::revoked.eq(false)) .load(&*conn)?; - let has_tokens = !tokens.is_empty(); + + let token_count = tokens.len() as i64; let owned_crates = CrateOwner::by_owner_kind(OwnerKind::User) .inner_join(crates::table) @@ -54,7 +55,7 @@ pub fn me(req: &mut dyn RequestExt) -> EndpointResult { Ok(req.json(&EncodableMe { user: user.encodable_private(email, verified, verification_sent), owned_crates, - meta: EncodableMeMeta { has_tokens }, + meta: EncodableMeMeta { token_count }, })) } diff --git a/src/tests/user.rs b/src/tests/user.rs index ee4f6f39bff..1cbf195227c 100644 --- a/src/tests/user.rs +++ b/src/tests/user.rs @@ -757,7 +757,7 @@ fn shows_that_user_has_tokens() { let (app, _, user) = TestApp::init().with_user(); let json = user.show_me(); - assert!(!json.meta.has_tokens); + assert_eq!(json.meta.token_count, 0); let user_id = user.as_model().id; app.db(|conn| { @@ -768,5 +768,5 @@ fn shows_that_user_has_tokens() { }); let json = user.show_me(); - assert!(json.meta.has_tokens); + assert_eq!(json.meta.token_count, 2); } diff --git a/src/views.rs b/src/views.rs index 250988d3ea0..646d246d691 100644 --- a/src/views.rs +++ b/src/views.rs @@ -166,7 +166,7 @@ pub struct EncodableMe { #[derive(Serialize, Deserialize, Debug, Clone, Copy)] pub struct EncodableMeMeta { - pub has_tokens: bool, + pub token_count: i64, } /// The serialization format for the `User` model. From aaee1c2cdadbb9d93367ea41f1b8efd483fc5333 Mon Sep 17 00:00:00 2001 From: Tobias Bieniek Date: Fri, 4 Dec 2020 19:47:49 +0100 Subject: [PATCH 5/5] user: Use `count()` to count tokens --- src/controllers/user/me.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/controllers/user/me.rs b/src/controllers/user/me.rs index 9ebd1e05ebd..5a80fdb30e0 100644 --- a/src/controllers/user/me.rs +++ b/src/controllers/user/me.rs @@ -30,11 +30,10 @@ pub fn me(req: &mut dyn RequestExt) -> EndpointResult { )) .first(&*conn)?; - let tokens: Vec = ApiToken::belonging_to(&user) + let token_count = ApiToken::belonging_to(&user) .filter(api_tokens::revoked.eq(false)) - .load(&*conn)?; - - let token_count = tokens.len() as i64; + .count() + .get_result(&*conn)?; let owned_crates = CrateOwner::by_owner_kind(OwnerKind::User) .inner_join(crates::table)