diff options
Diffstat (limited to 'rust/src/api_wrappers.rs')
-rw-r--r-- | rust/src/api_wrappers.rs | 282 |
1 files changed, 255 insertions, 27 deletions
diff --git a/rust/src/api_wrappers.rs b/rust/src/api_wrappers.rs index e5176ac6..8c274fb5 100644 --- a/rust/src/api_wrappers.rs +++ b/rust/src/api_wrappers.rs @@ -11,6 +11,7 @@ use fatcat_api_spec::models::*; use fatcat_api_spec::*; use futures::{self, Future}; use std::str::FromStr; +use uuid::Uuid; /// Helper for generating wrappers (which return "Box::new(futures::done(Ok(BLAH)))" like the /// codegen fatcat-api-spec code wants) that call through to actual helpers (which have simple @@ -20,11 +21,12 @@ macro_rules! wrap_entity_handlers { // stable doesn't have a mechanism to "concat" or generate new identifiers in macros, at least // in the context of defining new functions. // The only stable approach I know of would be: https://github.com/dtolnay/mashup - ($get_fn:ident, $get_resp:ident, $post_fn:ident, - $post_resp:ident, $post_batch_fn:ident, $post_batch_handler:ident, - $post_batch_resp:ident, $update_fn:ident, $update_resp:ident, - $delete_fn:ident, $delete_resp:ident, $get_history_fn:ident, - $get_history_resp:ident, $model:ident) => { + ($get_fn:ident, $get_resp:ident, $post_fn:ident, $post_resp:ident, $post_batch_fn:ident, + $post_batch_handler:ident, $post_batch_resp:ident, $update_fn:ident, $update_resp:ident, + $delete_fn:ident, $delete_resp:ident, $get_history_fn:ident, $get_history_resp:ident, + $get_edit_fn:ident, $get_edit_resp:ident, $delete_edit_fn:ident, $delete_edit_resp:ident, + $get_rev_fn:ident, $get_rev_resp:ident, $get_redirects_fn:ident, $get_redirects_resp:ident, + $model:ident) => { fn $get_fn( &self, @@ -244,14 +246,131 @@ macro_rules! wrap_entity_handlers { }; Box::new(futures::done(Ok(ret))) } + + fn $get_rev_fn( + &self, + id: String, + expand: Option<String>, + hide: Option<String>, + _context: &Context, + ) -> Box<Future<Item = $get_rev_resp, Error = ApiError> + Send> { + let conn = self.db_pool.get().expect("db_pool error"); + // No transaction for GET + let ret = match conn.transaction(|| { + let rev_id = Uuid::from_str(&id)?; + let hide_flags = match hide { + None => HideFlags::none(), + Some(param) => HideFlags::from_str(¶m)?, + }; + match expand { + None => $model::db_get_rev(&conn, rev_id, hide_flags), + Some(param) => { + let expand_flags = ExpandFlags::from_str(¶m)?; + let mut entity = $model::db_get_rev(&conn, rev_id, hide_flags)?; + entity.db_expand(&conn, expand_flags)?; + Ok(entity) + }, + } + }) { + Ok(entity) => + $get_rev_resp::FoundEntityRevision(entity), + Err(Error(ErrorKind::Diesel(::diesel::result::Error::NotFound), _)) => + $get_rev_resp::NotFound(ErrorResponse { message: format!("No such entity {}: {}", stringify!($model), id) }), + Err(Error(ErrorKind::Uuid(e), _)) => + $get_rev_resp::BadRequest(ErrorResponse { message: e.to_string() }), + Err(Error(ErrorKind::MalformedExternalId(e), _)) => + $get_rev_resp::BadRequest(ErrorResponse { message: e.to_string() }), + Err(e) => { + error!("{}", e); + $get_rev_resp::GenericError(ErrorResponse { message: e.to_string() }) + }, + }; + Box::new(futures::done(Ok(ret))) + } + + fn $get_edit_fn( + &self, + edit_id: i64, + _context: &Context, + ) -> Box<Future<Item = $get_edit_resp, Error = ApiError> + Send> { + let conn = self.db_pool.get().expect("db_pool error"); + // No transaction for GET + let ret = match conn.transaction(|| { + $model::db_get_edit(&conn, edit_id)?.into_model() + }) { + Ok(edit) => + $get_edit_resp::FoundEdit(edit), + Err(Error(ErrorKind::Diesel(::diesel::result::Error::NotFound), _)) => + $get_edit_resp::NotFound(ErrorResponse { message: format!("No such {} entity edit: {}", stringify!($model), edit_id) }), + Err(e) => { + error!("{}", e); + $get_edit_resp::GenericError(ErrorResponse { message: e.to_string() }) + }, + }; + Box::new(futures::done(Ok(ret))) + } + + fn $delete_edit_fn( + &self, + edit_id: i64, + _context: &Context, + ) -> Box<Future<Item = $delete_edit_resp, Error = ApiError> + Send> { + let conn = self.db_pool.get().expect("db_pool error"); + let ret = match conn.transaction(|| { + $model::db_delete_edit(&conn, edit_id) + }) { + Ok(()) => + $delete_edit_resp::DeletedEdit(Success { message: format!("Successfully deleted work-in-progress {} edit: {}", stringify!($model), edit_id) } ), + Err(Error(ErrorKind::Diesel(::diesel::result::Error::NotFound), _)) => + $delete_edit_resp::NotFound(ErrorResponse { message: format!("No such {} edit: {}", stringify!($model), edit_id) }), + Err(Error(ErrorKind::Diesel(e), _)) => + $delete_edit_resp::BadRequest(ErrorResponse { message: e.to_string() }), + Err(e) => { + error!("{}", e); + $delete_edit_resp::GenericError(ErrorResponse { message: e.to_string() }) + }, + }; + Box::new(futures::done(Ok(ret))) + } + + fn $get_redirects_fn( + &self, + id: String, + _context: &Context, + ) -> Box<Future<Item = $get_redirects_resp, Error = ApiError> + Send> { + let conn = self.db_pool.get().expect("db_pool error"); + // No transaction for GET + let ret = match conn.transaction(|| { + let entity_id = FatCatId::from_str(&id)?; + let redirects: Vec<FatCatId> = $model::db_get_redirects(&conn, entity_id)?; + Ok(redirects.into_iter().map(|fcid| fcid.to_string()).collect()) + }) { + Ok(redirects) => + $get_redirects_resp::FoundEntityRedirects(redirects), + Err(Error(ErrorKind::Diesel(::diesel::result::Error::NotFound), _)) => + $get_redirects_resp::NotFound(ErrorResponse { message: format!("No such entity {}: {}", stringify!($model), id) }), + Err(Error(ErrorKind::Uuid(e), _)) => + $get_redirects_resp::BadRequest(ErrorResponse { message: e.to_string() }), + Err(Error(ErrorKind::InvalidFatcatId(e), _)) => + $get_redirects_resp::BadRequest(ErrorResponse { + message: ErrorKind::InvalidFatcatId(e).to_string() }), + Err(e) => { + error!("{}", e); + $get_redirects_resp::GenericError(ErrorResponse { message: e.to_string() }) + }, + }; + Box::new(futures::done(Ok(ret))) + } + } } macro_rules! wrap_lookup_handler { - ($get_fn:ident, $get_handler:ident, $get_resp:ident, $idname:ident, $idtype:ident) => { + ($get_fn:ident, $get_handler:ident, $get_resp:ident, $idname:ident) => { fn $get_fn( &self, - $idname: $idtype, + $idname: Option<String>, + wikidata_qid: Option<String>, hide: Option<String>, _context: &Context, ) -> Box<Future<Item = $get_resp, Error = ApiError> + Send> { @@ -261,11 +380,11 @@ macro_rules! wrap_lookup_handler { Some(param) => HideFlags::from_str(¶m).unwrap(), }; // No transaction for GET - let ret = match self.$get_handler(&$idname, hide_flags, &conn) { + let ret = match self.$get_handler(&$idname, &wikidata_qid, 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) }), + $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(e) => { @@ -360,6 +479,14 @@ impl Api for Server { DeleteContainerResponse, get_container_history, GetContainerHistoryResponse, + get_container_edit, + GetContainerEditResponse, + delete_container_edit, + DeleteContainerEditResponse, + get_container_revision, + GetContainerRevisionResponse, + get_container_redirects, + GetContainerRedirectsResponse, ContainerEntity ); @@ -377,6 +504,14 @@ impl Api for Server { DeleteCreatorResponse, get_creator_history, GetCreatorHistoryResponse, + get_creator_edit, + GetCreatorEditResponse, + delete_creator_edit, + DeleteCreatorEditResponse, + get_creator_revision, + GetCreatorRevisionResponse, + get_creator_redirects, + GetCreatorRedirectsResponse, CreatorEntity ); wrap_entity_handlers!( @@ -393,6 +528,14 @@ impl Api for Server { DeleteFileResponse, get_file_history, GetFileHistoryResponse, + get_file_edit, + GetFileEditResponse, + delete_file_edit, + DeleteFileEditResponse, + get_file_revision, + GetFileRevisionResponse, + get_file_redirects, + GetFileRedirectsResponse, FileEntity ); wrap_entity_handlers!( @@ -409,6 +552,14 @@ impl Api for Server { DeleteReleaseResponse, get_release_history, GetReleaseHistoryResponse, + get_release_edit, + GetReleaseEditResponse, + delete_release_edit, + DeleteReleaseEditResponse, + get_release_revision, + GetReleaseRevisionResponse, + get_release_redirects, + GetReleaseRedirectsResponse, ReleaseEntity ); wrap_entity_handlers!( @@ -425,6 +576,14 @@ impl Api for Server { DeleteWorkResponse, get_work_history, GetWorkHistoryResponse, + get_work_edit, + GetWorkEditResponse, + delete_work_edit, + DeleteWorkEditResponse, + get_work_revision, + GetWorkRevisionResponse, + get_work_redirects, + GetWorkRedirectsResponse, WorkEntity ); @@ -432,29 +591,13 @@ impl Api for Server { lookup_container, lookup_container_handler, LookupContainerResponse, - issnl, - String + issnl ); wrap_lookup_handler!( lookup_creator, lookup_creator_handler, LookupCreatorResponse, - orcid, - String - ); - wrap_lookup_handler!( - lookup_file, - lookup_file_handler, - LookupFileResponse, - sha1, - String - ); - wrap_lookup_handler!( - lookup_release, - lookup_release_handler, - LookupReleaseResponse, - doi, - String + orcid ); wrap_fcid_hide_handler!( @@ -479,6 +622,91 @@ impl Api for Server { GetEditorChangelogResponse ); + fn lookup_file( + &self, + md5: Option<String>, + sha1: Option<String>, + sha256: 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 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) { + Ok(entity) => LookupFileResponse::FoundEntity(entity), + Err(Error(ErrorKind::Diesel(::diesel::result::Error::NotFound), _)) => { + LookupFileResponse::NotFound(ErrorResponse { + message: format!("Not found: {:?} / {:?} / {:?}", md5, sha1, sha256), + }) + } + Err(Error(ErrorKind::MalformedExternalId(e), _)) => { + LookupFileResponse::BadRequest(ErrorResponse { + message: e.to_string(), + }) + } + Err(e) => { + error!("{}", e); + LookupFileResponse::BadRequest(ErrorResponse { + message: e.to_string(), + }) + } + }; + Box::new(futures::done(Ok(ret))) + } + + fn lookup_release( + &self, + doi: Option<String>, + wikidata_qid: Option<String>, + isbn13: Option<String>, + pmid: Option<String>, + pmcid: 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 hide_flags = match hide { + None => HideFlags::none(), + Some(param) => HideFlags::from_str(¶m).unwrap(), + }; + // No transaction for GET + let ret = match self.lookup_release_handler( + &doi, + &wikidata_qid, + &isbn13, + &pmid, + &pmcid, + hide_flags, + &conn, + ) { + Ok(entity) => LookupReleaseResponse::FoundEntity(entity), + Err(Error(ErrorKind::Diesel(::diesel::result::Error::NotFound), _)) => { + LookupReleaseResponse::NotFound(ErrorResponse { + message: format!( + "Not found: {:?} / {:?} / {:?} / {:?} / {:?}", + doi, wikidata_qid, isbn13, pmid, pmcid + ), + }) + } + Err(Error(ErrorKind::MalformedExternalId(e), _)) => { + LookupReleaseResponse::BadRequest(ErrorResponse { + message: e.to_string(), + }) + } + Err(e) => { + error!("{}", e); + LookupReleaseResponse::BadRequest(ErrorResponse { + message: e.to_string(), + }) + } + }; + Box::new(futures::done(Ok(ret))) + } + fn accept_editgroup( &self, id: String, |