From e7e4876908314741ba25ed5b32aa0fdb18111a96 Mon Sep 17 00:00:00 2001 From: asonix Date: Wed, 5 Jul 2023 16:46:44 -0500 Subject: [PATCH] Explicitly handle cases of invalid aliases --- src/lib.rs | 55 ++++++++++++++++++++++++++++++++++++-------- src/queue/cleanup.rs | 8 +++++-- src/queue/process.rs | 5 +++- src/repo.rs | 23 ++++++++++++------ src/repo/sled.rs | 5 ++-- 5 files changed, 74 insertions(+), 22 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index d047198..b2fc17a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -105,7 +105,10 @@ async fn ensure_details( store: &S, alias: &Alias, ) -> Result { - let identifier = repo.identifier_from_alias::(alias).await?; + let Some(identifier) = repo.identifier_from_alias::(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( ) -> Result { 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::(hash, thumbnail_path.to_string_lossy().to_string()) .await? @@ -598,7 +607,11 @@ async fn process( 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::(hash.clone(), path_string) @@ -685,7 +698,11 @@ async fn process_head( 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::(hash.clone(), path_string) .await?; @@ -726,7 +743,11 @@ async fn process_backgrounded( 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::(hash.clone(), path_string) .await?; @@ -764,7 +785,11 @@ async fn serve( ) -> Result { let alias = alias.into_inner(); - let identifier = repo.identifier_from_alias::(&alias).await?; + let Some(identifier) = repo.identifier_from_alias::(&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( ) -> Result { let alias = alias.into_inner(); - let identifier = repo.identifier_from_alias::(&alias).await?; + let Some(identifier) = repo.identifier_from_alias::(&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( 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( repo: web::Data, ) -> Result { let alias = query.into_inner().alias; - let identifier = repo.identifier_from_alias::(&alias).await?; + let Some(identifier) = repo.identifier_from_alias::(&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", diff --git a/src/queue/cleanup.rs b/src/queue/cleanup.rs index 7beb5ff..dd3c667 100644 --- a/src/queue/cleanup.rs +++ b/src/queue/cleanup.rs @@ -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() { diff --git a/src/queue/process.rs b/src/queue/process.rs index 636129a..e06952e 100644 --- a/src/queue/process.rs +++ b/src/queue/process.rs @@ -125,7 +125,10 @@ async fn generate( process_path: PathBuf, process_args: Vec, ) -> 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 diff --git a/src/repo.rs b/src/repo.rs index 84e8fb8..a8ece2a 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -86,14 +86,20 @@ pub(crate) trait FullRepo: async fn identifier_from_alias( &self, alias: &Alias, - ) -> Result { - let hash = self.hash(alias).await?; - self.identifier(hash).await + ) -> Result, 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, 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, StoreError> { - let hash = self.hash(alias).await?; + let Some(hash) = self.hash(alias).await? else { + return Ok(None); + }; + let identifier = self.identifier::(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; async fn relate_hash(&self, alias: &Alias, hash: Self::Bytes) -> Result<(), RepoError>; - async fn hash(&self, alias: &Alias) -> Result; + async fn hash(&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 } - async fn hash(&self, alias: &Alias) -> Result { + async fn hash(&self, alias: &Alias) -> Result, RepoError> { T::hash(self, alias).await } diff --git a/src/repo/sled.rs b/src/repo/sled.rs index 04c0623..ab41230 100644 --- a/src/repo/sled.rs +++ b/src/repo/sled.rs @@ -729,13 +729,12 @@ impl AliasRepo for SledRepo { } #[tracing::instrument(level = "trace", skip(self))] - async fn hash(&self, alias: &Alias) -> Result { + async fn hash(&self, alias: &Alias) -> Result, 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))]