From e095a6587c1915941d4ee4d4742418b31103ae46 Mon Sep 17 00:00:00 2001 From: Bryan Newbold Date: Wed, 14 Nov 2018 19:57:50 -0800 Subject: enforce some controlled vocabularies in API --- rust/src/api_entity_crud.rs | 10 +++++ rust/src/api_helpers.rs | 106 ++++++++++++++++++++++++++++++++++++++++++++ rust/src/api_wrappers.rs | 8 ++++ rust/src/lib.rs | 4 ++ 4 files changed, 128 insertions(+) diff --git a/rust/src/api_entity_crud.rs b/rust/src/api_entity_crud.rs index f8e3a0ed..80cae471 100644 --- a/rust/src/api_entity_crud.rs +++ b/rust/src/api_entity_crud.rs @@ -877,6 +877,16 @@ impl EntityCrud for ReleaseEntity { if let Some(ref extid) = entity.wikidata_qid { check_wikidata_qid(extid)?; } + if let Some(ref release_type) = entity.release_type { + check_release_type(release_type)?; + } + if let Some(ref contribs) = entity.contribs { + for contrib in contribs { + if let Some(ref role) = contrib.role { + check_contrib_role(role)?; + } + } + } } let rev_ids: Vec = insert_into(release_rev::table) diff --git a/rust/src/api_helpers.rs b/rust/src/api_helpers.rs index 47c03e58..4b3f573b 100644 --- a/rust/src/api_helpers.rs +++ b/rust/src/api_helpers.rs @@ -319,6 +319,112 @@ fn test_check_orcid() { assert!(check_orcid("0x23-4567-3456-6780").is_err()); } +pub fn check_release_type(raw: &str) -> Result<()> { + + let valid_types = vec![ + // Citation Style Language official types + "article", + "article-magazine", + "article-newspaper", + "article-journal", + "bill", + "book", + "broadcast", + "chapter", + "dataset", + "entry", + "entry-dictionary", + "entry-encyclopedia", + "figure", + "graphic", + "interview", + "legislation", + "legal_case", + "manuscript", + "map", + "motion_picture", + "musical_score", + "pamphlet", + "paper-conference", + "patent", + "post", + "post-weblog", + "personal_communication", + "report", + "review", + "review-book", + "song", + "speech", + "thesis", + "treaty", + "webpage", + // fatcat-specific extensions + "peer_review", + "software", + "standard", + ]; + for good in valid_types { + if raw == good { + return Ok(()) + } + } + Err(ErrorKind::NotInControlledVocabulary(format!( + "not a valid release_type: '{}' (expected a CSL type, eg, 'article-journal', 'book')", + raw + )).into()) +} + +#[test] +fn test_check_release_type() { + assert!(check_release_type("book").is_ok()); + assert!(check_release_type("article-journal").is_ok()); + assert!(check_release_type("standard").is_ok()); + assert!(check_release_type("journal-article").is_err()); + assert!(check_release_type("BOOK").is_err()); + assert!(check_release_type("book ").is_err()); +} + +pub fn check_contrib_role(raw: &str) -> Result<()> { + + let valid_types = vec![ + // Citation Style Language official role types + "author", + "collection-editor", + "composer", + "container-author", + "director", + "editor", + "editorial-director", + "editortranslator", + "illustrator", + "interviewer", + "original-author", + "recipient", + "reviewed-author", + "translator", + // common extension (for conference proceeding chair) + //"chair", + ]; + for good in valid_types { + if raw == good { + return Ok(()) + } + } + Err(ErrorKind::NotInControlledVocabulary(format!( + "not a valid contrib.role: '{}' (expected a CSL type, eg, 'author', 'editor')", + raw + )).into()) +} + +#[test] +fn test_check_contrib_role() { + assert!(check_contrib_role("author").is_ok()); + assert!(check_contrib_role("editor").is_ok()); + assert!(check_contrib_role("chair").is_err()); + assert!(check_contrib_role("EDITOR").is_err()); + assert!(check_contrib_role("editor ").is_err()); +} + // TODO: make the above checks "more correct" // TODO: check ISBN-13 // TODO: check hashes (SHA-1, etc) diff --git a/rust/src/api_wrappers.rs b/rust/src/api_wrappers.rs index 0daff73b..098ea0b9 100644 --- a/rust/src/api_wrappers.rs +++ b/rust/src/api_wrappers.rs @@ -90,6 +90,8 @@ macro_rules! wrap_entity_handlers { message: ErrorKind::InvalidFatcatId(e).to_string() }), Err(Error(ErrorKind::MalformedExternalId(e), _)) => $post_resp::BadRequest(ErrorResponse { message: e.to_string() }), + Err(Error(ErrorKind::NotInControlledVocabulary(e), _)) => + $post_resp::BadRequest(ErrorResponse { message: e.to_string() }), Err(e) => { error!("{}", e); $post_resp::GenericError(ErrorResponse { message: e.to_string() }) @@ -123,6 +125,8 @@ macro_rules! wrap_entity_handlers { message: ErrorKind::InvalidFatcatId(e).to_string() }), Err(Error(ErrorKind::MalformedExternalId(e), _)) => $post_batch_resp::BadRequest(ErrorResponse { message: e.to_string() }), + Err(Error(ErrorKind::NotInControlledVocabulary(e), _)) => + $post_batch_resp::BadRequest(ErrorResponse { message: e.to_string() }), Err(e) => { error!("{}", e); $post_batch_resp::GenericError(ErrorResponse { message: e.to_string() }) @@ -160,6 +164,8 @@ macro_rules! wrap_entity_handlers { message: ErrorKind::InvalidFatcatId(e).to_string() }), Err(Error(ErrorKind::MalformedExternalId(e), _)) => $update_resp::BadRequest(ErrorResponse { message: e.to_string() }), + Err(Error(ErrorKind::NotInControlledVocabulary(e), _)) => + $update_resp::BadRequest(ErrorResponse { message: e.to_string() }), Err(e) => { error!("{}", e); $update_resp::GenericError(ErrorResponse { message: e.to_string() }) @@ -281,6 +287,8 @@ macro_rules! wrap_fcid_handler { $get_resp::NotFound(ErrorResponse { message: format!("Not found: {}", id) }), Err(Error(ErrorKind::MalformedExternalId(e), _)) => $get_resp::BadRequest(ErrorResponse { message: e.to_string() }), + Err(Error(ErrorKind::NotInControlledVocabulary(e), _)) => + $get_resp::BadRequest(ErrorResponse { message: e.to_string() }), Err(e) => { error!("{}", e); $get_resp::BadRequest(ErrorResponse { message: e.to_string() }) diff --git a/rust/src/lib.rs b/rust/src/lib.rs index 4b227392..99035b85 100644 --- a/rust/src/lib.rs +++ b/rust/src/lib.rs @@ -50,6 +50,10 @@ pub mod errors { description("external identifier doesn't match required pattern") display("external identifier doesn't match required pattern") } + NotInControlledVocabulary(word: String) { + description("word or type not correct for controlled vocabulary") + display("word or type not correct for controlled vocabulary") + } EditgroupAlreadyAccepted(id: String) { description("editgroup was already accepted") display("attempted to accept an editgroup which was already accepted: {}", id) -- cgit v1.2.3