Explicitly handle cases of invalid aliases

This commit is contained in:
asonix 2023-07-05 16:46:44 -05:00
parent d9c5ed20b9
commit e7e4876908
5 changed files with 74 additions and 22 deletions

View file

@ -105,7 +105,10 @@ async fn ensure_details<R: FullRepo, S: Store + 'static>(
store: &S, store: &S,
alias: &Alias, alias: &Alias,
) -> Result<Details, Error> { ) -> Result<Details, Error> {
let identifier = repo.identifier_from_alias::<S::Identifier>(alias).await?; let Some(identifier) = repo.identifier_from_alias::<S::Identifier>(alias).await? else {
return Err(UploadError::MissingAlias.into());
};
let details = repo.details(&identifier).await?; let details = repo.details(&identifier).await?;
if let Some(details) = details { if let Some(details) = details {
@ -573,7 +576,13 @@ async fn process_details<R: FullRepo, S: Store>(
) -> Result<HttpResponse, Error> { ) -> Result<HttpResponse, Error> {
let (_, alias, thumbnail_path, _) = prepare_process(query, ext.as_str())?; let (_, alias, thumbnail_path, _) = prepare_process(query, ext.as_str())?;
let hash = repo.hash(&alias).await?; let Some(hash) = repo.hash(&alias).await? else {
// Invalid alias
return Ok(HttpResponse::NotFound().json(&serde_json::json!({
"msg": "No images associated with provided alias",
})));
};
let identifier = repo let identifier = repo
.variant_identifier::<S::Identifier>(hash, thumbnail_path.to_string_lossy().to_string()) .variant_identifier::<S::Identifier>(hash, thumbnail_path.to_string_lossy().to_string())
.await? .await?
@ -598,7 +607,11 @@ async fn process<R: FullRepo, S: Store + 'static>(
let (format, alias, thumbnail_path, thumbnail_args) = prepare_process(query, ext.as_str())?; let (format, alias, thumbnail_path, thumbnail_args) = prepare_process(query, ext.as_str())?;
let path_string = thumbnail_path.to_string_lossy().to_string(); let path_string = thumbnail_path.to_string_lossy().to_string();
let hash = repo.hash(&alias).await?; let Some(hash) = repo.hash(&alias).await? else {
// Invalid alias
// TODO: placeholder 404 image
return Ok(HttpResponse::NotFound().finish());
};
let identifier_opt = repo let identifier_opt = repo
.variant_identifier::<S::Identifier>(hash.clone(), path_string) .variant_identifier::<S::Identifier>(hash.clone(), path_string)
@ -685,7 +698,11 @@ async fn process_head<R: FullRepo, S: Store + 'static>(
let (format, alias, thumbnail_path, _) = prepare_process(query, ext.as_str())?; let (format, alias, thumbnail_path, _) = prepare_process(query, ext.as_str())?;
let path_string = thumbnail_path.to_string_lossy().to_string(); let path_string = thumbnail_path.to_string_lossy().to_string();
let hash = repo.hash(&alias).await?; let Some(hash) = repo.hash(&alias).await? else {
// Invalid alias
return Ok(HttpResponse::NotFound().finish());
};
let identifier_opt = repo let identifier_opt = repo
.variant_identifier::<S::Identifier>(hash.clone(), path_string) .variant_identifier::<S::Identifier>(hash.clone(), path_string)
.await?; .await?;
@ -726,7 +743,11 @@ async fn process_backgrounded<R: FullRepo, S: Store>(
let (target_format, source, process_path, process_args) = prepare_process(query, ext.as_str())?; let (target_format, source, process_path, process_args) = prepare_process(query, ext.as_str())?;
let path_string = process_path.to_string_lossy().to_string(); let path_string = process_path.to_string_lossy().to_string();
let hash = repo.hash(&source).await?; let Some(hash) = repo.hash(&source).await? else {
// Invalid alias
return Ok(HttpResponse::BadRequest().finish());
};
let identifier_opt = repo let identifier_opt = repo
.variant_identifier::<S::Identifier>(hash.clone(), path_string) .variant_identifier::<S::Identifier>(hash.clone(), path_string)
.await?; .await?;
@ -764,7 +785,11 @@ async fn serve<R: FullRepo, S: Store + 'static>(
) -> Result<HttpResponse, Error> { ) -> Result<HttpResponse, Error> {
let alias = alias.into_inner(); let alias = alias.into_inner();
let identifier = repo.identifier_from_alias::<S::Identifier>(&alias).await?; let Some(identifier) = repo.identifier_from_alias::<S::Identifier>(&alias).await? else {
// Invalid alias
// TODO: placeholder 404 image
return Ok(HttpResponse::NotFound().finish());
};
let details = ensure_details(&repo, &store, &alias).await?; let details = ensure_details(&repo, &store, &alias).await?;
@ -780,7 +805,10 @@ async fn serve_head<R: FullRepo, S: Store + 'static>(
) -> Result<HttpResponse, Error> { ) -> Result<HttpResponse, Error> {
let alias = alias.into_inner(); let alias = alias.into_inner();
let identifier = repo.identifier_from_alias::<S::Identifier>(&alias).await?; let Some(identifier) = repo.identifier_from_alias::<S::Identifier>(&alias).await? else {
// Invalid alias
return Ok(HttpResponse::NotFound().finish());
};
let details = ensure_details(&repo, &store, &alias).await?; let details = ensure_details(&repo, &store, &alias).await?;
@ -932,7 +960,11 @@ async fn purge<R: FullRepo>(
let alias = query.into_inner().alias; let alias = query.into_inner().alias;
let aliases = repo.aliases_from_alias(&alias).await?; let aliases = repo.aliases_from_alias(&alias).await?;
let hash = repo.hash(&alias).await?; let Some(hash) = repo.hash(&alias).await? else {
return Ok(HttpResponse::BadRequest().json(&serde_json::json!({
"msg": "No images associated with provided alias",
})));
};
queue::cleanup_hash(&repo, hash).await?; queue::cleanup_hash(&repo, hash).await?;
Ok(HttpResponse::Ok().json(&serde_json::json!({ Ok(HttpResponse::Ok().json(&serde_json::json!({
@ -961,7 +993,12 @@ async fn identifier<R: FullRepo, S: Store>(
repo: web::Data<R>, repo: web::Data<R>,
) -> Result<HttpResponse, Error> { ) -> Result<HttpResponse, Error> {
let alias = query.into_inner().alias; let alias = query.into_inner().alias;
let identifier = repo.identifier_from_alias::<S::Identifier>(&alias).await?; let Some(identifier) = repo.identifier_from_alias::<S::Identifier>(&alias).await? else {
// Invalid alias
return Ok(HttpResponse::NotFound().json(serde_json::json!({
"msg": "No identifiers associated with provided alias"
})));
};
Ok(HttpResponse::Ok().json(&serde_json::json!({ Ok(HttpResponse::Ok().json(&serde_json::json!({
"msg": "ok", "msg": "ok",

View file

@ -127,9 +127,13 @@ where
return Err(UploadError::InvalidToken.into()); return Err(UploadError::InvalidToken.into());
} }
let hash = repo.hash(&alias).await?;
AliasRepo::cleanup(repo, &alias).await?; AliasRepo::cleanup(repo, &alias).await?;
let Some(hash) = repo.hash(&alias).await? else {
// hash doesn't exist, nothing to do
return Ok(());
};
repo.remove_alias(hash.clone(), &alias).await?; repo.remove_alias(hash.clone(), &alias).await?;
if repo.aliases(hash.clone()).await?.is_empty() { if repo.aliases(hash.clone()).await?.is_empty() {

View file

@ -125,7 +125,10 @@ async fn generate<R: FullRepo, S: Store + 'static>(
process_path: PathBuf, process_path: PathBuf,
process_args: Vec<String>, process_args: Vec<String>,
) -> Result<(), Error> { ) -> Result<(), Error> {
let hash = repo.hash(&source).await?; let Some(hash) = repo.hash(&source).await? else {
// Nothing to do
return Ok(());
};
let path_string = process_path.to_string_lossy().to_string(); let path_string = process_path.to_string_lossy().to_string();
let identifier_opt = repo let identifier_opt = repo

View file

@ -86,14 +86,20 @@ pub(crate) trait FullRepo:
async fn identifier_from_alias<I: Identifier + 'static>( async fn identifier_from_alias<I: Identifier + 'static>(
&self, &self,
alias: &Alias, alias: &Alias,
) -> Result<I, StoreError> { ) -> Result<Option<I>, StoreError> {
let hash = self.hash(alias).await?; let Some(hash) = self.hash(alias).await? else {
self.identifier(hash).await return Ok(None);
};
self.identifier(hash).await.map(Some)
} }
#[tracing::instrument(skip(self))] #[tracing::instrument(skip(self))]
async fn aliases_from_alias(&self, alias: &Alias) -> Result<Vec<Alias>, RepoError> { async fn aliases_from_alias(&self, alias: &Alias) -> Result<Vec<Alias>, RepoError> {
let hash = self.hash(alias).await?; let Some(hash) = self.hash(alias).await? else {
return Ok(vec![]);
};
self.aliases(hash).await self.aliases(hash).await
} }
@ -102,7 +108,10 @@ pub(crate) trait FullRepo:
&self, &self,
alias: &Alias, alias: &Alias,
) -> Result<Option<I>, StoreError> { ) -> Result<Option<I>, StoreError> {
let hash = self.hash(alias).await?; let Some(hash) = self.hash(alias).await? else {
return Ok(None);
};
let identifier = self.identifier::<I>(hash.clone()).await?; let identifier = self.identifier::<I>(hash.clone()).await?;
match self.details(&identifier).await? { match self.details(&identifier).await? {
@ -411,7 +420,7 @@ pub(crate) trait AliasRepo: BaseRepo {
async fn delete_token(&self, alias: &Alias) -> Result<DeleteToken, RepoError>; async fn delete_token(&self, alias: &Alias) -> Result<DeleteToken, RepoError>;
async fn relate_hash(&self, alias: &Alias, hash: Self::Bytes) -> Result<(), RepoError>; async fn relate_hash(&self, alias: &Alias, hash: Self::Bytes) -> Result<(), RepoError>;
async fn hash(&self, alias: &Alias) -> Result<Self::Bytes, RepoError>; async fn hash(&self, alias: &Alias) -> Result<Option<Self::Bytes>, RepoError>;
async fn cleanup(&self, alias: &Alias) -> Result<(), RepoError>; async fn cleanup(&self, alias: &Alias) -> Result<(), RepoError>;
} }
@ -441,7 +450,7 @@ where
T::relate_hash(self, alias, hash).await T::relate_hash(self, alias, hash).await
} }
async fn hash(&self, alias: &Alias) -> Result<Self::Bytes, RepoError> { async fn hash(&self, alias: &Alias) -> Result<Option<Self::Bytes>, RepoError> {
T::hash(self, alias).await T::hash(self, alias).await
} }

View file

@ -729,13 +729,12 @@ impl AliasRepo for SledRepo {
} }
#[tracing::instrument(level = "trace", skip(self))] #[tracing::instrument(level = "trace", skip(self))]
async fn hash(&self, alias: &Alias) -> Result<Self::Bytes, RepoError> { async fn hash(&self, alias: &Alias) -> Result<Option<Self::Bytes>, RepoError> {
let key = alias.to_bytes(); let key = alias.to_bytes();
let opt = b!(self.alias_hashes, alias_hashes.get(key)); let opt = b!(self.alias_hashes, alias_hashes.get(key));
opt.ok_or(SledError::Missing("alias -> hash")) Ok(opt)
.map_err(RepoError::from)
} }
#[tracing::instrument(skip(self))] #[tracing::instrument(skip(self))]