87 lines
2.1 KiB
Rust
87 lines
2.1 KiB
Rust
use std::sync::Arc;
|
|
|
|
use async_trait::async_trait;
|
|
use axum::{
|
|
extract::{FromRequest, Path as AxumPath, RequestParts},
|
|
Extension,
|
|
};
|
|
use semver::Version;
|
|
use serde::de::DeserializeOwned;
|
|
use sqlx::query_as;
|
|
|
|
use crate::{
|
|
auth, db::PgU32, db_error, index::update_crate_from_db, Auth, Errors, RespResult, State,
|
|
Success,
|
|
};
|
|
|
|
pub struct Path<T>(T);
|
|
|
|
#[async_trait]
|
|
impl<T, B> FromRequest<B> for Path<T>
|
|
where
|
|
T: DeserializeOwned + Send,
|
|
B: Send,
|
|
{
|
|
type Rejection = Errors;
|
|
|
|
async fn from_request(req: &mut RequestParts<B>) -> Result<Self, Self::Rejection> {
|
|
let res = AxumPath::<T>::from_request(req).await;
|
|
|
|
match res {
|
|
Ok(AxumPath(v)) => Ok(Path(v)),
|
|
Err(e) => Err(Errors::new(format_args!("Invalid path fragments: {e}"))),
|
|
}
|
|
}
|
|
}
|
|
|
|
pub async fn yank(
|
|
Path((crate_name, version)): Path<(String, Version)>,
|
|
Auth(auth_user): Auth,
|
|
Extension(state): Extension<Arc<State>>,
|
|
) -> RespResult {
|
|
auth(&crate_name, &auth_user, &state).await?;
|
|
|
|
do_yank(&crate_name, &version, &state, true).await
|
|
}
|
|
|
|
pub async fn unyank(
|
|
Path((crate_name, version)): Path<(String, Version)>,
|
|
Auth(auth_user): Auth,
|
|
Extension(state): Extension<Arc<State>>,
|
|
) -> RespResult {
|
|
auth(&crate_name, &auth_user, &state).await?;
|
|
|
|
do_yank(&crate_name, &version, &state, false).await
|
|
}
|
|
|
|
async fn do_yank(crate_name: &str, version: &Version, state: &State, yank: bool) -> RespResult {
|
|
let (crate_id,): (PgU32,) = query_as(
|
|
r"UPDATE versions SET yanked = $1
|
|
FROM crates
|
|
WHERE crates.id = versions.crate_id
|
|
and crates.name = $2
|
|
and versions.vers = $3
|
|
RETURNING crates.id",
|
|
)
|
|
.bind(yank)
|
|
.bind(crate_name)
|
|
.bind(&version.to_string())
|
|
.fetch_one(&state.db)
|
|
.await
|
|
.map_err(db_error)?;
|
|
|
|
update_crate_from_db(
|
|
crate_id,
|
|
state,
|
|
&format!(
|
|
"{} version {} of `{}`",
|
|
if yank { "Yank" } else { "Unyank" },
|
|
version,
|
|
crate_name
|
|
),
|
|
)
|
|
.await?;
|
|
|
|
Ok(Success)
|
|
}
|