From 623cfe7e76d3a3b7ae6108626b0e55aecbc4b660 Mon Sep 17 00:00:00 2001 From: "Carol (Nichols || Goulding)" Date: Fri, 8 Feb 2019 20:35:15 -0500 Subject: [PATCH] Record the verified email of the version publisher If there is one, because we're still in the optional stage, but we can start recording them now if possible. --- src/bin/update-downloads.rs | 1 + src/controllers/krate/publish.rs | 4 +++- src/models/user.rs | 17 +++++++---------- src/models/version.rs | 5 +++++ src/tests/builders.rs | 1 + src/tests/krate.rs | 29 ++++++++++++++++++++++++++++- 6 files changed, 45 insertions(+), 12 deletions(-) diff --git a/src/bin/update-downloads.rs b/src/bin/update-downloads.rs index 744aa46f963..2286a014954 100644 --- a/src/bin/update-downloads.rs +++ b/src/bin/update-downloads.rs @@ -147,6 +147,7 @@ mod test { None, 0, user_id, + Some("someone@example.com".into()), ) .unwrap(); let version = version.save(conn, &[]).unwrap(); diff --git a/src/controllers/krate/publish.rs b/src/controllers/krate/publish.rs index 237226e8221..3e3a2b5ce77 100644 --- a/src/controllers/krate/publish.rs +++ b/src/controllers/krate/publish.rs @@ -66,7 +66,8 @@ pub fn publish(req: &mut dyn Request) -> CargoResult { let conn = app.diesel_database.get()?; let mut other_warnings = vec![]; - if !user.has_verified_email(&conn)? { + let verified_email_address = user.verified_email(&conn)?; + if verified_email_address.is_none() { other_warnings.push(String::from( "You do not currently have a verified email address associated with your crates.io \ account. Starting 2019-02-28, a verified email will be required to publish crates. \ @@ -147,6 +148,7 @@ pub fn publish(req: &mut dyn Request) -> CargoResult { // to get here, and max upload sizes are way less than i32 max file_length as i32, user.id, + verified_email_address, )? .save(&conn, &new_crate.authors)?; diff --git a/src/models/user.rs b/src/models/user.rs index 83ee9b96d5d..f1c189c2df7 100644 --- a/src/models/user.rs +++ b/src/models/user.rs @@ -5,7 +5,7 @@ use std::borrow::Cow; use crate::app::App; use crate::util::CargoResult; -use crate::models::{Crate, CrateOwner, NewEmail, Owner, OwnerKind, Rights}; +use crate::models::{Crate, CrateOwner, Email, NewEmail, Owner, OwnerKind, Rights}; use crate::schema::{crate_owners, emails, users}; use crate::views::{EncodablePrivateUser, EncodablePublicUser}; @@ -162,15 +162,12 @@ impl User { Ok(best) } - pub fn has_verified_email(&self, conn: &PgConnection) -> CargoResult { - use diesel::dsl::exists; - let email_exists = diesel::select(exists( - emails::table - .filter(emails::user_id.eq(self.id)) - .filter(emails::verified.eq(true)), - )) - .get_result(&*conn)?; - Ok(email_exists) + pub fn verified_email(&self, conn: &PgConnection) -> CargoResult> { + Ok(Email::belonging_to(self) + .select(emails::email) + .filter(emails::verified.eq(true)) + .first::(&*conn) + .optional()?) } /// Converts this `User` model into an `EncodablePrivateUser` for JSON serialization. diff --git a/src/models/version.rs b/src/models/version.rs index f8ed071d78f..83aa5fdb12a 100644 --- a/src/models/version.rs +++ b/src/models/version.rs @@ -70,6 +70,7 @@ pub struct NewVersion { license: Option, crate_size: Option, published_by: i32, + published_by_email: Option, } impl Version { @@ -160,6 +161,7 @@ impl Version { impl NewVersion { #[allow(clippy::new_ret_no_self)] + #[allow(clippy::too_many_arguments)] pub fn new( crate_id: i32, num: &semver::Version, @@ -168,6 +170,7 @@ impl NewVersion { license_file: Option<&str>, crate_size: i32, published_by: i32, + verified_email_address: Option, // TODO: change to just `String` after 2019-02-28 ) -> CargoResult { let features = serde_json::to_value(features)?; @@ -178,6 +181,8 @@ impl NewVersion { license, crate_size: Some(crate_size), published_by, + // TODO: wrap `String` in `Some` after 2019-02-28 + published_by_email: verified_email_address, }; new_version.validate_license(license_file)?; diff --git a/src/tests/builders.rs b/src/tests/builders.rs index 7eda3ea2381..40b6971b34e 100644 --- a/src/tests/builders.rs +++ b/src/tests/builders.rs @@ -89,6 +89,7 @@ impl<'a> VersionBuilder<'a> { self.license_file, self.size, published_by, + Some("someone@example.com".into()), )? .save(connection, &[])?; diff --git a/src/tests/krate.rs b/src/tests/krate.rs index b6269c579a6..41a164d50d7 100644 --- a/src/tests/krate.rs +++ b/src/tests/krate.rs @@ -1077,7 +1077,7 @@ fn new_krate_with_readme() { // See https://github.com/rust-lang/crates-io-cargo-teams/issues/8 #[test] fn new_krate_without_any_email_warns() { - let (_, _, _, token) = TestApp::with_proxy().with_token(); + let (app, _, _, token) = TestApp::with_proxy().with_token(); let crate_to_publish = PublishBuilder::new("foo_no_email"); @@ -1086,6 +1086,15 @@ fn new_krate_without_any_email_warns() { assert_eq!(json.warnings.other[0], "You do not currently have a verified email address \ associated with your crates.io account. Starting 2019-02-28, a verified email will be required \ to publish crates. Visit https://crates.io/me to set and verify your email address."); + + // Don't record a verified email if there isn't one + app.db(|conn| { + let email = versions::table + .select(versions::published_by_email) + .first::>(conn) + .unwrap(); + assert!(email.is_none()); + }); } // This warning will soon become a hard error. @@ -1112,6 +1121,15 @@ fn new_krate_with_unverified_email_warns() { assert_eq!(json.warnings.other[0], "You do not currently have a verified email address \ associated with your crates.io account. Starting 2019-02-28, a verified email will be required \ to publish crates. Visit https://crates.io/me to set and verify your email address."); + + // Don't record a verified email if there isn't one + app.db(|conn| { + let email = versions::table + .select(versions::published_by_email) + .first::>(conn) + .unwrap(); + assert!(email.is_none()); + }); } #[test] @@ -1137,6 +1155,15 @@ fn new_krate_with_verified_email_doesnt_warn() { let json = token.publish(crate_to_publish).good(); assert_eq!(json.warnings.other.len(), 0); + + // Record a verified email because there is one + app.db(|conn| { + let email = versions::table + .select(versions::published_by_email) + .first::>(conn) + .unwrap(); + assert_eq!(email.unwrap(), "something@example.com"); + }); } #[test]