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
20 changes: 19 additions & 1 deletion src/controllers/crate_owner_invitation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@ use crate::app::AppState;
use crate::auth::AuthCheck;
use crate::auth::Authentication;
use crate::controllers::helpers::pagination::{Page, PaginationOptions, PaginationQueryParams};
use crate::models::crate_owner_invitation::AcceptError;
use crate::models::{Crate, CrateOwnerInvitation, Rights, User};
use crate::schema::{crate_owner_invitations, crates, users};
use crate::util::errors::{bad_request, forbidden, internal, AppResult, BoxedAppError};
use crate::util::errors::{bad_request, custom, forbidden, internal, AppResult, BoxedAppError};
use crate::util::RequestUtils;
use crate::views::{
EncodableCrateOwnerInvitation, EncodableCrateOwnerInvitationV1, EncodablePublicUser,
Expand All @@ -20,6 +21,7 @@ use diesel::prelude::*;
use diesel::sql_types::Bool;
use diesel_async::{AsyncPgConnection, RunQueryDsl};
use http::request::Parts;
use http::StatusCode;
use indexmap::IndexMap;
use std::collections::{HashMap, HashSet};

Expand Down Expand Up @@ -380,3 +382,19 @@ pub async fn accept_crate_owner_invitation_with_token(
},
}))
}

impl From<AcceptError> for BoxedAppError {
fn from(error: AcceptError) -> Self {
match error {
AcceptError::Diesel(error) => error.into(),
AcceptError::Expired { crate_name } => {
let detail = format!(
"The invitation to become an owner of the {crate_name} crate expired. \
Please reach out to an owner of the crate to request a new invitation.",
);

custom(StatusCode::GONE, detail)
}
}
}
}
2 changes: 1 addition & 1 deletion src/models.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ pub mod helpers;

mod action;
pub mod category;
mod crate_owner_invitation;
pub mod crate_owner_invitation;
pub mod default_versions;
mod deleted_crate;
pub mod dependency;
Expand Down
19 changes: 10 additions & 9 deletions src/models/crate_owner_invitation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,11 @@ use chrono::{NaiveDateTime, Utc};
use diesel::prelude::*;
use diesel_async::scoped_futures::ScopedFutureExt;
use diesel_async::{AsyncConnection, AsyncPgConnection, RunQueryDsl};
use http::StatusCode;
use secrecy::SecretString;

use crate::config;
use crate::models::{CrateOwner, OwnerKind};
use crate::schema::{crate_owner_invitations, crate_owners, crates};
use crate::util::errors::{custom, AppResult};

#[derive(Debug)]
pub enum NewCrateOwnerInvitationOutcome {
Expand Down Expand Up @@ -109,7 +107,7 @@ impl CrateOwnerInvitation {
self,
conn: &mut AsyncPgConnection,
config: &config::Server,
) -> AppResult<()> {
) -> Result<(), AcceptError> {
use diesel_async::scoped_futures::ScopedFutureExt;
use diesel_async::{AsyncConnection, RunQueryDsl};

Expand All @@ -120,12 +118,7 @@ impl CrateOwnerInvitation {
.first(conn)
.await?;

let detail = format!(
"The invitation to become an owner of the {crate_name} crate expired. \
Please reach out to an owner of the crate to request a new invitation.",
);

return Err(custom(StatusCode::GONE, detail));
return Err(AcceptError::Expired { crate_name });
}

conn.transaction(|conn| {
Expand Down Expand Up @@ -170,3 +163,11 @@ impl CrateOwnerInvitation {
self.created_at + config.ownership_invitations_expiration
}
}

#[derive(Debug, thiserror::Error)]
pub enum AcceptError {
#[error(transparent)]
Diesel(#[from] diesel::result::Error),
#[error("The invitation has expired")]
Expired { crate_name: String },
}