aboutsummaryrefslogtreecommitdiffstats
path: root/rust/src
diff options
context:
space:
mode:
Diffstat (limited to 'rust/src')
-rw-r--r--rust/src/api_server.rs56
-rw-r--r--rust/src/database_models.rs26
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),
+ }
+ }
+}