Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/bin/crates-admin/delete_crate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@
.await
.context("Failed to look up crate name from the database")?;

let deleted_by = User::async_find_by_login(&mut conn, &opts.deleted_by)
let deleted_by = User::find_by_login(&mut conn, &opts.deleted_by)

Check warning on line 64 in src/bin/crates-admin/delete_crate.rs

View check run for this annotation

Codecov / codecov/patch

src/bin/crates-admin/delete_crate.rs#L64

Added line #L64 was not covered by tests
.await
.context("Failed to look up `--deleted-by` user from the database")?;

Expand Down
2 changes: 1 addition & 1 deletion src/controllers/crate_owner_invitation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ async fn prepare_list(
ListFilter::CrateName(crate_name) => {
// Only allow crate owners to query pending invitations for their crate.
let krate: Crate = Crate::by_name(&crate_name).first(conn).await?;
let owners = krate.async_owners(conn).await?;
let owners = krate.owners(conn).await?;
if user.rights(state, &owners).await? != Rights::Full {
let detail = "only crate owners can query pending invitations for their crate";
return Err(forbidden(detail));
Expand Down
4 changes: 2 additions & 2 deletions src/controllers/github/secret_scanning.rs
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ async fn send_notification_email(
.await
.context("Failed to find user")?;

let Some(recipient) = user.async_email(conn).await? else {
let Some(recipient) = user.email(conn).await? else {
return Err(anyhow!("No address found"));
};

Expand All @@ -199,7 +199,7 @@ async fn send_notification_email(
url: &alert.url,
};

state.emails.async_send(&recipient, email).await?;
state.emails.send(&recipient, email).await?;

Ok(())
}
Expand Down
8 changes: 4 additions & 4 deletions src/controllers/krate/owners.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ pub async fn owners(state: AppState, Path(crate_name): Path<String>) -> AppResul
.ok_or_else(|| crate_not_found(&crate_name))?;

let owners = krate
.async_owners(&mut conn)
.owners(&mut conn)
.await?
.into_iter()
.map(Owner::into)
Expand Down Expand Up @@ -144,7 +144,7 @@ async fn modify_owners(
.optional()?
.ok_or_else(|| crate_not_found(&crate_name))?;

let owners = krate.async_owners(conn).await?;
let owners = krate.owners(conn).await?;

match user.rights(&app, &owners).await? {
Rights::Full => {}
Expand Down Expand Up @@ -188,7 +188,7 @@ async fn modify_owners(
));

if let Some(recipient) =
invitee.async_verified_email(conn).await.ok().flatten()
invitee.verified_email(conn).await.ok().flatten()
{
emails.push(OwnerInviteEmail {
recipient_email_address: recipient,
Expand Down Expand Up @@ -243,7 +243,7 @@ async fn modify_owners(
for email in emails {
let addr = email.recipient_email_address().to_string();

if let Err(e) = app.emails.async_send(&addr, email).await {
if let Err(e) = app.emails.send(&addr, email).await {
warn!("Failed to send co-owner invite email: {e}");
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/controllers/krate/publish.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ pub async fn publish(app: AppState, req: BytesRequest) -> AppResult<Json<GoodCra
.check(&req, &mut conn)
.await?;

let verified_email_address = auth.user().async_verified_email(&mut conn).await?;
let verified_email_address = auth.user().verified_email(&mut conn).await?;
let verified_email_address = verified_email_address.ok_or_else(|| {
bad_request(format!(
"A verified email address is required to publish crates to crates.io. \
Expand Down Expand Up @@ -349,7 +349,7 @@ pub async fn publish(app: AppState, req: BytesRequest) -> AppResult<Json<GoodCra
None => persist.update(conn).await?,
};

let owners = krate.async_owners(conn).await?;
let owners = krate.owners(conn).await?;
if user.rights(&app, &owners).await? < Rights::Publish {
return Err(custom(StatusCode::FORBIDDEN, MISSING_RIGHTS_ERROR_MESSAGE));
}
Expand Down
4 changes: 2 additions & 2 deletions src/controllers/token.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ pub async fn new(
.transpose()
.map_err(|_err| bad_request("invalid endpoint scope"))?;

let recipient = user.async_email(&mut conn).await?;
let recipient = user.email(&mut conn).await?;

let api_token = ApiToken::insert_with_scopes(
&mut conn,
Expand All @@ -154,7 +154,7 @@ pub async fn new(
// At this point the token has been created so failing to send the
// email should not cause an error response to be returned to the
// caller.
let email_ret = app.emails.async_send(&recipient, email).await;
let email_ret = app.emails.send(&recipient, email).await;
if let Err(e) = email_ret {
error!("Failed to send token creation email: {e}")
}
Expand Down
2 changes: 1 addition & 1 deletion src/controllers/user/resend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ pub async fn regenerate_token_and_send(

state
.emails
.async_send(&email.email, email1)
.send(&email.email, email1)
.await
.map_err(BoxedAppError::from)
}
Expand Down
6 changes: 3 additions & 3 deletions src/controllers/user/update.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,15 +50,15 @@ pub async fn update_user(
.await?;

if !publish_notifications {
let email_address = user.async_verified_email(&mut conn).await?;
let email_address = user.verified_email(&mut conn).await?;

if let Some(email_address) = email_address {
let email = PublishNotificationsUnsubscribeEmail {
user_name: &user.gh_login,
domain: &state.emails.domain,
};

if let Err(error) = state.emails.async_send(&email_address, email).await {
if let Err(error) = state.emails.send(&email_address, email).await {
warn!("Failed to send publish notifications unsubscribe email to {email_address}: {error}");
}
}
Expand Down Expand Up @@ -103,7 +103,7 @@ pub async fn update_user(
token,
};

let _ = state.emails.async_send(user_email, email).await;
let _ = state.emails.send(user_email, email).await;
}

ok_true()
Expand Down
2 changes: 1 addition & 1 deletion src/controllers/version/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ pub async fn perform_version_yank_update(

let api_token_id = auth.api_token_id();
let user = auth.user();
let owners = krate.async_owners(conn).await?;
let owners = krate.owners(conn).await?;

let yanked = yanked.unwrap_or(version.yanked);

Expand Down
15 changes: 3 additions & 12 deletions src/email.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ use lettre::transport::stub::AsyncStubTransport;
use lettre::{Address, AsyncTransport, Message, Tokio1Executor};
use rand::distributions::{Alphanumeric, DistString};
use std::sync::Arc;
use tokio::runtime::Handle;

pub trait Email {
fn subject(&self) -> String;
Expand Down Expand Up @@ -115,15 +114,7 @@ impl Emails {
Ok(message)
}

pub fn send<E: Email>(&self, recipient: &str, email: E) -> Result<(), EmailError> {
let email = self.build_message(recipient, email)?;

Handle::current()
.block_on(self.backend.send(email))
.map_err(EmailError::TransportError)
}

pub async fn async_send<E: Email>(&self, recipient: &str, email: E) -> Result<(), EmailError> {
pub async fn send<E: Email>(&self, recipient: &str, email: E) -> Result<(), EmailError> {
let email = self.build_message(recipient, email)?;

self.backend
Expand Down Expand Up @@ -195,14 +186,14 @@ mod tests {
let emails = Emails::new_in_memory();

let address = "String.Format(\"{0}.{1}@live.com\", FirstName, LastName)";
assert_err!(emails.async_send(address, TestEmail).await);
assert_err!(emails.send(address, TestEmail).await);
}

#[tokio::test]
async fn sending_to_valid_email_succeeds() {
let emails = Emails::new_in_memory();

let address = "[email protected]";
assert_ok!(emails.async_send(address, TestEmail).await);
assert_ok!(emails.send(address, TestEmail).await);
}
}
43 changes: 3 additions & 40 deletions src/models/krate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@ use chrono::NaiveDateTime;
use diesel::associations::Identifiable;
use diesel::dsl;
use diesel::pg::Pg;
use diesel::prelude::*;
use diesel::sql_types::{Bool, Integer, Text};
use diesel_async::scoped_futures::ScopedFutureExt;
use diesel_async::{AsyncConnection, AsyncPgConnection};
use diesel_async::{AsyncConnection, AsyncPgConnection, RunQueryDsl};
use secrecy::SecretString;
use thiserror::Error;

Expand All @@ -17,8 +18,6 @@ use crate::models::{
};
use crate::schema::*;
use crate::sql::canon_crate_name;
use crate::util::diesel::prelude::*;
use crate::util::diesel::Conn;
use crate::util::errors::{bad_request, version_not_found, AppResult};
use crate::{app::App, util::errors::BoxedAppError};

Expand Down Expand Up @@ -110,7 +109,6 @@ pub struct NewCrate<'a> {
impl<'a> NewCrate<'a> {
pub async fn update(&self, conn: &mut AsyncPgConnection) -> QueryResult<Crate> {
use diesel::update;
use diesel_async::RunQueryDsl;

update(crates::table)
.filter(canon_crate_name(crates::name).eq(canon_crate_name(self.name)))
Expand All @@ -127,8 +125,6 @@ impl<'a> NewCrate<'a> {
}

pub async fn create(&self, conn: &mut AsyncPgConnection, user_id: i32) -> QueryResult<Crate> {
use diesel_async::RunQueryDsl;

conn.transaction(|conn| {
async move {
let krate: Crate = diesel::insert_into(crates::table)
Expand Down Expand Up @@ -209,8 +205,6 @@ impl Crate {
conn: &mut AsyncPgConnection,
version: &str,
) -> AppResult<Version> {
use diesel_async::RunQueryDsl;

Version::belonging_to(self)
.filter(versions::num.eq(version))
.first(conn)
Expand Down Expand Up @@ -353,8 +347,6 @@ impl Crate {
/// highest version (in semver order) for the current crate,
/// where all top versions are not yanked.
pub async fn top_versions(&self, conn: &mut AsyncPgConnection) -> QueryResult<TopVersions> {
use diesel_async::RunQueryDsl;

Ok(TopVersions::from_date_version_pairs(
Version::belonging_to(self)
.filter(versions::yanked.eq(false))
Expand All @@ -364,9 +356,7 @@ impl Crate {
))
}

pub async fn async_owners(&self, conn: &mut AsyncPgConnection) -> QueryResult<Vec<Owner>> {
use diesel_async::RunQueryDsl;

pub async fn owners(&self, conn: &mut AsyncPgConnection) -> QueryResult<Vec<Owner>> {
let users = CrateOwner::by_owner_kind(OwnerKind::User)
.filter(crate_owners::crate_id.eq(self.id))
.order((crate_owners::owner_id, crate_owners::owner_kind))
Expand All @@ -390,29 +380,6 @@ impl Crate {
Ok(users.chain(teams).collect())
}

pub fn owners(&self, conn: &mut impl Conn) -> QueryResult<Vec<Owner>> {
use diesel::RunQueryDsl;

let users = CrateOwner::by_owner_kind(OwnerKind::User)
.filter(crate_owners::crate_id.eq(self.id))
.order((crate_owners::owner_id, crate_owners::owner_kind))
.inner_join(users::table)
.select(User::as_select())
.load(conn)?
.into_iter()
.map(Owner::User);
let teams = CrateOwner::by_owner_kind(OwnerKind::Team)
.filter(crate_owners::crate_id.eq(self.id))
.order((crate_owners::owner_id, crate_owners::owner_kind))
.inner_join(teams::table)
.select(Team::as_select())
.load(conn)?
.into_iter()
.map(Owner::Team);

Ok(users.chain(teams).collect())
}

/// Invite `login` as an owner of this crate, returning the created
/// [`NewOwnerInvite`].
pub async fn owner_add(
Expand All @@ -423,7 +390,6 @@ impl Crate {
login: &str,
) -> Result<NewOwnerInvite, OwnerAddError> {
use diesel::insert_into;
use diesel_async::RunQueryDsl;

let owner = Owner::find_or_create_by_login(app, conn, req_user, login).await?;
match owner {
Expand Down Expand Up @@ -466,8 +432,6 @@ impl Crate {
}

pub async fn owner_remove(&self, conn: &mut AsyncPgConnection, login: &str) -> AppResult<()> {
use diesel_async::RunQueryDsl;

let query = diesel::sql_query(
r#"WITH crate_owners_with_login AS (
SELECT
Expand Down Expand Up @@ -519,7 +483,6 @@ impl Crate {
) -> QueryResult<(Vec<ReverseDependency>, i64)> {
use diesel::sql_query;
use diesel::sql_types::{BigInt, Integer};
use diesel_async::RunQueryDsl;

let offset = options.offset().unwrap_or_default();
let rows: Vec<WithCount<ReverseDependency>> =
Expand Down
2 changes: 1 addition & 1 deletion src/models/owner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ impl Owner {
Team::create_or_update(app, conn, name, req_user).await?,
))
} else {
User::async_find_by_login(conn, name)
User::find_by_login(conn, name)
.await
.optional()?
.map(Owner::User)
Expand Down
Loading