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,
alias: &Alias,
) -> 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?;
if let Some(details) = details {
@ -573,7 +576,13 @@ async fn process_details<R: FullRepo, S: Store>(
) -> Result<HttpResponse, Error> {
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
.variant_identifier::<S::Identifier>(hash, thumbnail_path.to_string_lossy().to_string())
.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 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
.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 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
.variant_identifier::<S::Identifier>(hash.clone(), path_string)
.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 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
.variant_identifier::<S::Identifier>(hash.clone(), path_string)
.await?;
@ -764,7 +785,11 @@ async fn serve<R: FullRepo, S: Store + 'static>(
) -> Result<HttpResponse, Error> {
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?;
@ -780,7 +805,10 @@ async fn serve_head<R: FullRepo, S: Store + 'static>(
) -> Result<HttpResponse, Error> {
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?;
@ -932,7 +960,11 @@ async fn purge<R: FullRepo>(
let alias = query.into_inner().alias;
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?;
Ok(HttpResponse::Ok().json(&serde_json::json!({
@ -961,7 +993,12 @@ async fn identifier<R: FullRepo, S: Store>(
repo: web::Data<R>,
) -> Result<HttpResponse, Error> {
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!({
"msg": "ok",

View file

@ -127,9 +127,13 @@ where
return Err(UploadError::InvalidToken.into());
}
let hash = repo.hash(&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?;
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_args: Vec<String>,
) -> 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 identifier_opt = repo

View file

@ -86,14 +86,20 @@ pub(crate) trait FullRepo:
async fn identifier_from_alias<I: Identifier + 'static>(
&self,
alias: &Alias,
) -> Result<I, StoreError> {
let hash = self.hash(alias).await?;
self.identifier(hash).await
) -> Result<Option<I>, StoreError> {
let Some(hash) = self.hash(alias).await? else {
return Ok(None);
};
self.identifier(hash).await.map(Some)
}
#[tracing::instrument(skip(self))]
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
}
@ -102,7 +108,10 @@ pub(crate) trait FullRepo:
&self,
alias: &Alias,
) -> 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?;
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 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>;
}
@ -441,7 +450,7 @@ where
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
}

View file

@ -729,13 +729,12 @@ impl AliasRepo for SledRepo {
}
#[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 opt = b!(self.alias_hashes, alias_hashes.get(key));
opt.ok_or(SledError::Missing("alias -> hash"))
.map_err(RepoError::from)
Ok(opt)
}
#[tracing::instrument(skip(self))]