diff options
Diffstat (limited to 'rust/src')
-rw-r--r-- | rust/src/api_server.rs | 56 | ||||
-rw-r--r-- | rust/src/database_models.rs | 26 |
2 files changed, 81 insertions, 1 deletions
diff --git a/rust/src/api_server.rs b/rust/src/api_server.rs index aaf3d9a7..efe40165 100644 --- a/rust/src/api_server.rs +++ b/rust/src/api_server.rs @@ -129,6 +129,31 @@ macro_rules! wrap_lookup_handler { } } +macro_rules! wrap_history_handler { + ($get_fn:ident, $get_handler:ident, $get_resp:ident) => { + fn $get_fn( + &self, + id: String, + limit: Option<i64>, + _context: &Context, + ) -> Box<Future<Item = $get_resp, Error = ApiError> + Send> { + let ret = match self.$get_handler(id.clone(), limit) { + Ok(history) => + $get_resp::FoundEntityHistory(history), + Err(Error(ErrorKind::Diesel(::diesel::result::Error::NotFound), _)) => + $get_resp::NotFound(ErrorResponse { message: format!("No such entity {}: {}", stringify!($model), id) }), + Err(Error(ErrorKind::Uuid(e), _)) => + $get_resp::BadRequest(ErrorResponse { message: e.to_string() }), + Err(e) => { + error!("{}", e); + $get_resp::GenericError(ErrorResponse { message: e.to_string() }) + }, + }; + Box::new(futures::done(Ok(ret))) + } + } +} + macro_rules! count_entity { ($table:ident, $conn:expr) => {{ let count: i64 = $table::table @@ -350,6 +375,32 @@ impl Server { container_row2entity(Some(ident), rev) } + fn get_container_history_handler( + &self, + id: String, + limit: Option<i64>, + ) -> Result<Vec<EntityHistoryEntry>> { + let conn = self.db_pool.get().expect("db_pool error"); + let id = uuid::Uuid::parse_str(&id)?; + let limit = limit.unwrap_or(50); + + let rows: Vec<(EditgroupRow, ChangelogRow, ContainerEditRow)> = editgroup::table + .inner_join(changelog::table) + .inner_join(container_edit::table) + .filter(container_edit::ident_id.eq(id)) + .limit(limit) + .get_results(&conn)?; + + let history: Vec<EntityHistoryEntry> = rows.into_iter() + .map(|(eg_row, cl_row, ce_row)| EntityHistoryEntry { + edit: ce_row.to_model().expect("edit row to model"), + editgroup: eg_row.to_model_partial(), + changelog_entry: cl_row.to_model(), + }) + .collect(); + Ok(history) + } + fn get_creator_handler(&self, id: String) -> Result<CreatorEntity> { let conn = self.db_pool.get().expect("db_pool error"); let id = uuid::Uuid::parse_str(&id)?; @@ -1084,6 +1135,11 @@ impl Api for Server { doi, String ); + wrap_history_handler!( + get_container_history, + get_container_history_handler, + GetContainerHistoryResponse + ); // Rename "wrap_lookup_handler"? wrap_lookup_handler!( diff --git a/rust/src/database_models.rs b/rust/src/database_models.rs index dd84748d..6fa9b7b7 100644 --- a/rust/src/database_models.rs +++ b/rust/src/database_models.rs @@ -1,7 +1,7 @@ use chrono; use database_schema::*; use errors::*; -use fatcat_api::models::EntityEdit; +use fatcat_api::models::{ChangelogEntry, Editgroup, EntityEdit}; use serde_json; use uuid::Uuid; @@ -243,6 +243,20 @@ pub struct EditgroupRow { pub description: Option<String>, } +impl EditgroupRow { + /// Returns an Edigroup API model *without* the entity edits actually populated. Useful for, + /// eg, entity history queries (where we already have the entity edit we want) + pub fn to_model_partial(self) -> Editgroup { + Editgroup { + id: Some(self.id), + editor_id: self.editor_id, + description: self.description, + extra: self.extra_json, + edits: None, + } + } +} + #[derive(Debug, Queryable, Identifiable, Associations, AsChangeset)] #[table_name = "editor"] pub struct EditorRow { @@ -259,3 +273,13 @@ pub struct ChangelogRow { pub editgroup_id: i64, pub timestamp: chrono::NaiveDateTime, } + +impl ChangelogRow { + pub fn to_model(self) -> ChangelogEntry { + ChangelogEntry { + index: self.id, + editgroup_id: self.editgroup_id, + timestamp: chrono::DateTime::from_utc(self.timestamp, chrono::Utc), + } + } +} |