diff options
-rw-r--r-- | rust/migrations/2018-05-12-001226_init/up.sql | 8 | ||||
-rw-r--r-- | rust/src/api_server.rs | 77 | ||||
-rw-r--r-- | rust/src/api_wrappers.rs | 38 | ||||
-rw-r--r-- | rust/tests/test_api_server_http.rs | 152 |
4 files changed, 240 insertions, 35 deletions
diff --git a/rust/migrations/2018-05-12-001226_init/up.sql b/rust/migrations/2018-05-12-001226_init/up.sql index b5214078..88614e7b 100644 --- a/rust/migrations/2018-05-12-001226_init/up.sql +++ b/rust/migrations/2018-05-12-001226_init/up.sql @@ -425,10 +425,10 @@ INSERT INTO work_edit (ident_id, rev_id, redirect_id, editgroup_id, prev_rev) VA ('00000000-0000-0000-5555-000000000002', '00000000-0000-0000-5555-FFF000000002', null, '00000000-0000-0000-BBBB-000000000004', null), ('00000000-0000-0000-5555-000000000002', '00000000-0000-0000-5555-FFF000000003', null, '00000000-0000-0000-BBBB-000000000005', '00000000-0000-0000-5555-FFF000000002'); -INSERT INTO release_rev (id, work_ident_id, container_ident_id, title, release_type, release_status, release_date, doi, isbn13, core_id, volume, issue, pages, publisher, language) VALUES - ('00000000-0000-0000-4444-FFF000000001', '00000000-0000-0000-5555-000000000001', null, 'example title', null, null, null, null, null, null, null, null, null, null, null), - ('00000000-0000-0000-4444-FFF000000002', '00000000-0000-0000-5555-000000000002', '00000000-0000-0000-1111-000000000001', 'bigger example', 'article-journal', null,'2018-01-01', '10.123/abc', '978-3-16-148410-0', '42022773', '12', 'IV', '5-9', 'bogus publishing group', 'cn'), - ('00000000-0000-0000-4444-FFF000000003', '00000000-0000-0000-5555-000000000003', '00000000-0000-0000-1111-000000000003', 'Why Most Published Research Findings Are False', 'article-journal', 'published', '2005-08-30', '10.1371/journal.pmed.0020124', null, null, '2', '8', 'e124', 'Public Library of Science', 'en'); +INSERT INTO release_rev (id, work_ident_id, container_ident_id, title, release_type, release_status, release_date, doi, wikidata_qid, pmid, pmcid, isbn13, core_id, volume, issue, pages, publisher, language) VALUES + ('00000000-0000-0000-4444-FFF000000001', '00000000-0000-0000-5555-000000000001', null, 'example title', null, null, null, null, null, null, null, null, null, null, null, null, null, null), + ('00000000-0000-0000-4444-FFF000000002', '00000000-0000-0000-5555-000000000002', '00000000-0000-0000-1111-000000000001', 'bigger example', 'article-journal', null, '2018-01-01', '10.123/abc', 'Q55555', '54321', 'PMC555','978-3-16-148410-0', '42022773', '12', 'IV', '5-9', 'bogus publishing group', 'cn'), + ('00000000-0000-0000-4444-FFF000000003', '00000000-0000-0000-5555-000000000003', '00000000-0000-0000-1111-000000000003', 'Why Most Published Research Findings Are False', 'article-journal', 'published', '2005-08-30', '10.1371/journal.pmed.0020124', null, null, null, null, null, '2', '8', 'e124', 'Public Library of Science', 'en'); INSERT INTO release_ident (id, is_live, rev_id, redirect_id) VALUES ('00000000-0000-0000-4444-000000000001', true, '00000000-0000-0000-4444-FFF000000001', null), -- aaaaaaaaaaaaarceaaaaaaaaae diff --git a/rust/src/api_server.rs b/rust/src/api_server.rs index 0a415e91..2278f64f 100644 --- a/rust/src/api_server.rs +++ b/rust/src/api_server.rs @@ -53,7 +53,7 @@ pub struct Server { pub db_pool: ConnectionPool, } -pub fn get_release_files(id: FatCatId, hide: HideFlags, conn: &DbConn) -> Result<Vec<FileEntity>> { +pub fn get_release_files(id: FatCatId, hide_flags: HideFlags, conn: &DbConn) -> Result<Vec<FileEntity>> { let rows: Vec<(FileRevRow, FileIdentRow, FileReleaseRow)> = file_rev::table .inner_join(file_ident::table) .inner_join(file_release::table) @@ -63,7 +63,7 @@ pub fn get_release_files(id: FatCatId, hide: HideFlags, conn: &DbConn) -> Result .load(conn)?; rows.into_iter() - .map(|(rev, ident, _)| FileEntity::db_from_row(conn, rev, Some(ident), hide)) + .map(|(rev, ident, _)| FileEntity::db_from_row(conn, rev, Some(ident), hide_flags)) .collect() } @@ -72,7 +72,8 @@ impl Server { &self, issnl: &Option<String>, wikidata_qid: &Option<String>, - hide: HideFlags, + expand_flags: ExpandFlags, + hide_flags: HideFlags, conn: &DbConn, ) -> Result<ContainerEntity> { let (ident, rev): (ContainerIdentRow, ContainerRevRow) = match (issnl, wikidata_qid) { @@ -86,7 +87,7 @@ impl Server { .first(conn)? } (None, Some(wikidata_qid)) => { - check_issn(wikidata_qid)?; + check_wikidata_qid(wikidata_qid)?; container_ident::table .inner_join(container_rev::table) .filter(container_rev::wikidata_qid.eq(&wikidata_qid)) @@ -99,14 +100,17 @@ impl Server { } }; - ContainerEntity::db_from_row(conn, rev, Some(ident), hide) + let mut entity = ContainerEntity::db_from_row(conn, rev, Some(ident), hide_flags)?; + entity.db_expand(&conn, expand_flags)?; + Ok(entity) } pub fn lookup_creator_handler( &self, orcid: &Option<String>, wikidata_qid: &Option<String>, - hide: HideFlags, + expand_flags: ExpandFlags, + hide_flags: HideFlags, conn: &DbConn, ) -> Result<CreatorEntity> { let (ident, rev): (CreatorIdentRow, CreatorRevRow) = match (orcid, wikidata_qid) { @@ -133,13 +137,15 @@ impl Server { } }; - CreatorEntity::db_from_row(conn, rev, Some(ident), hide) + let mut entity = CreatorEntity::db_from_row(conn, rev, Some(ident), hide_flags)?; + entity.db_expand(&conn, expand_flags)?; + Ok(entity) } pub fn get_creator_releases_handler( &self, id: FatCatId, - hide: HideFlags, + hide_flags: HideFlags, conn: &DbConn, ) -> Result<Vec<ReleaseEntity>> { // TODO: some kind of unique or group-by? @@ -153,7 +159,7 @@ impl Server { // TODO: from_rows, not from_row? rows.into_iter() - .map(|(rev, ident, _)| ReleaseEntity::db_from_row(conn, rev, Some(ident), hide)) + .map(|(rev, ident, _)| ReleaseEntity::db_from_row(conn, rev, Some(ident), hide_flags)) .collect() } @@ -162,7 +168,8 @@ impl Server { md5: &Option<String>, sha1: &Option<String>, sha256: &Option<String>, - hide: HideFlags, + expand_flags: ExpandFlags, + hide_flags: HideFlags, conn: &DbConn, ) -> Result<FileEntity> { let (ident, rev): (FileIdentRow, FileRevRow) = match (md5, sha1, sha256) { @@ -189,7 +196,9 @@ impl Server { } }; - FileEntity::db_from_row(conn, rev, Some(ident), hide) + let mut entity = FileEntity::db_from_row(conn, rev, Some(ident), hide_flags)?; + entity.db_expand(&conn, expand_flags)?; + Ok(entity) } pub fn lookup_release_handler( @@ -199,12 +208,14 @@ impl Server { isbn13: &Option<String>, pmid: &Option<String>, pmcid: &Option<String>, - hide: HideFlags, + core_id: &Option<String>, + expand_flags: ExpandFlags, + hide_flags: HideFlags, conn: &DbConn, ) -> Result<ReleaseEntity> { let (ident, rev): (ReleaseIdentRow, ReleaseRevRow) = - match (doi, wikidata_qid, isbn13, pmid, pmcid) { - (Some(doi), None, None, None, None) => { + match (doi, wikidata_qid, isbn13, pmid, pmcid, core_id) { + (Some(doi), None, None, None, None, None) => { check_doi(doi)?; release_ident::table .inner_join(release_rev::table) @@ -213,7 +224,7 @@ impl Server { .filter(release_ident::redirect_id.is_null()) .first(conn)? } - (None, Some(wikidata_qid), None, None, None) => { + (None, Some(wikidata_qid), None, None, None, None) => { check_wikidata_qid(wikidata_qid)?; release_ident::table .inner_join(release_rev::table) @@ -222,7 +233,7 @@ impl Server { .filter(release_ident::redirect_id.is_null()) .first(conn)? } - (None, None, Some(isbn13), None, None) => { + (None, None, Some(isbn13), None, None, None) => { // TODO: check_isbn13(isbn13)?; release_ident::table .inner_join(release_rev::table) @@ -231,7 +242,7 @@ impl Server { .filter(release_ident::redirect_id.is_null()) .first(conn)? } - (None, None, None, Some(pmid), None) => { + (None, None, None, Some(pmid), None, None) => { check_pmid(pmid)?; release_ident::table .inner_join(release_rev::table) @@ -240,7 +251,7 @@ impl Server { .filter(release_ident::redirect_id.is_null()) .first(conn)? } - (None, None, None, None, Some(pmcid)) => { + (None, None, None, None, Some(pmcid), None) => { check_pmcid(pmcid)?; release_ident::table .inner_join(release_rev::table) @@ -249,6 +260,15 @@ impl Server { .filter(release_ident::redirect_id.is_null()) .first(conn)? } + (None, None, None, None, None, Some(core_id)) => { + // TODO: check_core_id(core_id)?; + release_ident::table + .inner_join(release_rev::table) + .filter(release_rev::core_id.eq(core_id)) + .filter(release_ident::is_live.eq(true)) + .filter(release_ident::redirect_id.is_null()) + .first(conn)? + } _ => { return Err( ErrorKind::MissingOrMultipleExternalId("in lookup".to_string()).into(), @@ -256,22 +276,24 @@ impl Server { } }; - ReleaseEntity::db_from_row(conn, rev, Some(ident), hide) + let mut entity = ReleaseEntity::db_from_row(conn, rev, Some(ident), hide_flags)?; + entity.db_expand(&conn, expand_flags)?; + Ok(entity) } pub fn get_release_files_handler( &self, id: FatCatId, - hide: HideFlags, + hide_flags: HideFlags, conn: &DbConn, ) -> Result<Vec<FileEntity>> { - get_release_files(id, hide, conn) + get_release_files(id, hide_flags, conn) } pub fn get_work_releases_handler( &self, id: FatCatId, - hide: HideFlags, + hide_flags: HideFlags, conn: &DbConn, ) -> Result<Vec<ReleaseEntity>> { let rows: Vec<(ReleaseRevRow, ReleaseIdentRow)> = release_rev::table @@ -282,7 +304,7 @@ impl Server { .load(conn)?; rows.into_iter() - .map(|(rev, ident)| ReleaseEntity::db_from_row(conn, rev, Some(ident), hide)) + .map(|(rev, ident)| ReleaseEntity::db_from_row(conn, rev, Some(ident), hide_flags)) .collect() } @@ -301,7 +323,8 @@ impl Server { editgroup::editor_id.eq(FatCatId::from_str(&entity.editor_id)?.to_uuid()), editgroup::description.eq(entity.description), editgroup::extra_json.eq(entity.extra), - )).get_result(conn)?; + )) + .get_result(conn)?; Ok(Editgroup { id: Some(uuid2fcid(&row.id)), @@ -397,7 +420,8 @@ impl Server { editgroup: Some(eg_row.into_model_partial()), editgroup_id: uuid2fcid(&cl_row.editgroup_id), timestamp: chrono::DateTime::from_utc(cl_row.timestamp, chrono::Utc), - }).collect(); + }) + .collect(); Ok(entries) } @@ -421,7 +445,8 @@ impl Server { editgroup: Some(eg_row.into_model_partial()), editgroup_id: uuid2fcid(&cl_row.editgroup_id), timestamp: chrono::DateTime::from_utc(cl_row.timestamp, chrono::Utc), - }).collect(); + }) + .collect(); Ok(entries) } diff --git a/rust/src/api_wrappers.rs b/rust/src/api_wrappers.rs index 8c274fb5..cb93ec54 100644 --- a/rust/src/api_wrappers.rs +++ b/rust/src/api_wrappers.rs @@ -371,22 +371,29 @@ macro_rules! wrap_lookup_handler { &self, $idname: Option<String>, wikidata_qid: Option<String>, + expand: Option<String>, hide: Option<String>, _context: &Context, ) -> Box<Future<Item = $get_resp, Error = ApiError> + Send> { let conn = self.db_pool.get().expect("db_pool error"); + let expand_flags = match expand { + None => ExpandFlags::none(), + Some(param) => ExpandFlags::from_str(¶m).unwrap(), + }; let hide_flags = match hide { None => HideFlags::none(), Some(param) => HideFlags::from_str(¶m).unwrap(), }; // No transaction for GET - let ret = match self.$get_handler(&$idname, &wikidata_qid, hide_flags, &conn) { + let ret = match self.$get_handler(&$idname, &wikidata_qid, expand_flags, hide_flags, &conn) { Ok(entity) => $get_resp::FoundEntity(entity), Err(Error(ErrorKind::Diesel(::diesel::result::Error::NotFound), _)) => $get_resp::NotFound(ErrorResponse { message: format!("Not found: {:?} / {:?}", $idname, wikidata_qid) }), Err(Error(ErrorKind::MalformedExternalId(e), _)) => $get_resp::BadRequest(ErrorResponse { message: e.to_string() }), + Err(Error(ErrorKind::MissingOrMultipleExternalId(e), _)) => { + $get_resp::BadRequest(ErrorResponse { message: e.to_string(), }) }, Err(e) => { error!("{}", e); $get_resp::BadRequest(ErrorResponse { message: e.to_string() }) @@ -627,16 +634,21 @@ impl Api for Server { md5: Option<String>, sha1: Option<String>, sha256: Option<String>, + expand: Option<String>, hide: Option<String>, _context: &Context, ) -> Box<Future<Item = LookupFileResponse, Error = ApiError> + Send> { let conn = self.db_pool.get().expect("db_pool error"); + let expand_flags = match expand { + None => ExpandFlags::none(), + Some(param) => ExpandFlags::from_str(¶m).unwrap(), + }; let hide_flags = match hide { None => HideFlags::none(), Some(param) => HideFlags::from_str(¶m).unwrap(), }; // No transaction for GET - let ret = match self.lookup_file_handler(&md5, &sha1, &sha256, hide_flags, &conn) { + let ret = match self.lookup_file_handler(&md5, &sha1, &sha256, expand_flags, hide_flags, &conn) { Ok(entity) => LookupFileResponse::FoundEntity(entity), Err(Error(ErrorKind::Diesel(::diesel::result::Error::NotFound), _)) => { LookupFileResponse::NotFound(ErrorResponse { @@ -648,6 +660,11 @@ impl Api for Server { message: e.to_string(), }) } + Err(Error(ErrorKind::MissingOrMultipleExternalId(e), _)) => { + LookupFileResponse::BadRequest(ErrorResponse { + message: e.to_string(), + }) + } Err(e) => { error!("{}", e); LookupFileResponse::BadRequest(ErrorResponse { @@ -665,10 +682,16 @@ impl Api for Server { isbn13: Option<String>, pmid: Option<String>, pmcid: Option<String>, + core_id: Option<String>, + expand: Option<String>, hide: Option<String>, _context: &Context, ) -> Box<Future<Item = LookupReleaseResponse, Error = ApiError> + Send> { let conn = self.db_pool.get().expect("db_pool error"); + let expand_flags = match expand { + None => ExpandFlags::none(), + Some(param) => ExpandFlags::from_str(¶m).unwrap(), + }; let hide_flags = match hide { None => HideFlags::none(), Some(param) => HideFlags::from_str(¶m).unwrap(), @@ -680,6 +703,8 @@ impl Api for Server { &isbn13, &pmid, &pmcid, + &core_id, + expand_flags, hide_flags, &conn, ) { @@ -687,8 +712,8 @@ impl Api for Server { Err(Error(ErrorKind::Diesel(::diesel::result::Error::NotFound), _)) => { LookupReleaseResponse::NotFound(ErrorResponse { message: format!( - "Not found: {:?} / {:?} / {:?} / {:?} / {:?}", - doi, wikidata_qid, isbn13, pmid, pmcid + "Not found: {:?} / {:?} / {:?} / {:?} / {:?} / {:?}", + doi, wikidata_qid, isbn13, pmid, pmcid, core_id ), }) } @@ -697,6 +722,11 @@ impl Api for Server { message: e.to_string(), }) } + Err(Error(ErrorKind::MissingOrMultipleExternalId(e), _)) => { + LookupReleaseResponse::BadRequest(ErrorResponse { + message: e.to_string(), + }) + } Err(e) => { error!("{}", e); LookupReleaseResponse::BadRequest(ErrorResponse { diff --git a/rust/tests/test_api_server_http.rs b/rust/tests/test_api_server_http.rs index 614e6b65..031a0abf 100644 --- a/rust/tests/test_api_server_http.rs +++ b/rust/tests/test_api_server_http.rs @@ -197,6 +197,46 @@ fn test_lookups() { check_http_response( request::get( + "http://localhost:9411/v0/container/lookup?issnl=1234", + headers.clone(), + &router, + ), + status::BadRequest, + None, + ); + + check_http_response( + request::get( + "http://localhost:9411/v0/container/lookup?wikidata_qid=Q84913959359", + headers.clone(), + &router, + ), + status::NotFound, + None, + ); + + check_http_response( + request::get( + "http://localhost:9411/v0/container/lookup?wikidata_qid=84913959359", + headers.clone(), + &router, + ), + status::BadRequest, + None, + ); + + check_http_response( + request::get( + "http://localhost:9411/v0/container/lookup?wikidata_qid=Q84913959359&issnl=1234-0000", + headers.clone(), + &router, + ), + status::BadRequest, + None, + ); + + check_http_response( + request::get( "http://localhost:9411/v0/creator/lookup?orcid=0000-0003-2088-7465", headers.clone(), &router, @@ -207,6 +247,16 @@ fn test_lookups() { check_http_response( request::get( + "http://localhost:9411/v0/creator/lookup?wikidata_qid=Q5678", + headers.clone(), + &router, + ), + status::Ok, + Some("John P. A. Ioannidis"), + ); + + check_http_response( + request::get( "http://localhost:9411/v0/creator/lookup?orcid=0000-0003-2088-0000", headers.clone(), &router, @@ -217,6 +267,24 @@ fn test_lookups() { check_http_response( request::get( + "http://localhost:9411/v0/file/lookup?md5=7d97e98f8af710c7e7fe703abc8f639e0ee507c4", + headers.clone(), + &router, + ), + status::NotFound, + None, + ); + check_http_response( + request::get( + "http://localhost:9411/v0/file/lookup?md5=f4de91152c7ab9fdc2a128f962faebff", + headers.clone(), + &router, + ), + status::Ok, + Some("0020124&type=printable"), + ); + check_http_response( + request::get( "http://localhost:9411/v0/file/lookup?sha1=7d97e98f8af710c7e7fe703abc8f639e0ee507c4", headers.clone(), &router, @@ -224,6 +292,15 @@ fn test_lookups() { status::Ok, Some("robots.txt"), ); + check_http_response( + request::get( + "http://localhost:9411/v0/file/lookup?sha256=ffc1005680cb620eec4c913437dfabbf311b535cfe16cbaeb2faec1f92afc362", + headers.clone(), + &router, + ), + status::Ok, + Some("0020124&type=printable"), + ); check_http_response( request::get( @@ -234,6 +311,78 @@ fn test_lookups() { status::NotFound, None, ); + + // not URL encoded + check_http_response( + request::get( + "http://localhost:9411/v0/release/lookup?doi=10.123/abc", + headers.clone(), + &router, + ), + status::Ok, + Some("bigger example"), + ); + + // URL encoded + check_http_response( + request::get( + "http://localhost:9411/v0/release/lookup?doi=10.123%2Fabc", + headers.clone(), + &router, + ), + status::Ok, + Some("bigger example"), + ); + + check_http_response( + request::get( + "http://localhost:9411/v0/release/lookup?wikidata_qid=Q55555", + headers.clone(), + &router, + ), + status::Ok, + Some("bigger example"), + ); + + check_http_response( + request::get( + "http://localhost:9411/v0/release/lookup?pmid=54321", + headers.clone(), + &router, + ), + status::Ok, + Some("bigger example"), + ); + + check_http_response( + request::get( + "http://localhost:9411/v0/release/lookup?pmcid=PMC555", + headers.clone(), + &router, + ), + status::Ok, + Some("bigger example"), + ); + + check_http_response( + request::get( + "http://localhost:9411/v0/release/lookup?isbn13=978-3-16-148410-0", + headers.clone(), + &router, + ), + status::Ok, + Some("bigger example"), + ); + + check_http_response( + request::get( + "http://localhost:9411/v0/release/lookup?core_id=42022773", + headers.clone(), + &router, + ), + status::Ok, + Some("bigger example"), + ); } #[test] @@ -474,7 +623,8 @@ fn test_post_release() { status::BadRequest, None, ); - */} + */ +} #[test] fn test_post_work() { |