summaryrefslogtreecommitdiffstats
path: root/rust/src
diff options
context:
space:
mode:
Diffstat (limited to 'rust/src')
-rw-r--r--rust/src/editing.rs30
-rw-r--r--rust/src/endpoint_handlers.rs44
-rw-r--r--rust/src/endpoints.rs250
-rw-r--r--rust/src/entity_crud.rs12
4 files changed, 163 insertions, 173 deletions
diff --git a/rust/src/editing.rs b/rust/src/editing.rs
index c17e5964..65cd5bb8 100644
--- a/rust/src/editing.rs
+++ b/rust/src/editing.rs
@@ -5,7 +5,6 @@
use crate::database_models::*;
use crate::database_schema::*;
-use crate::editing_crud::EditgroupCrud;
use crate::entity_crud::EntityCrud;
use crate::errors::{FatcatError, Result};
use crate::identifiers::FatcatId;
@@ -37,37 +36,12 @@ impl EditContext {
}
}
+// This function used to be more complex, and take a database response.
pub fn make_edit_context(
- conn: &DbConn,
editor_id: FatcatId,
- editgroup_id: Option<FatcatId>,
+ editgroup_id: FatcatId,
autoaccept: bool,
- description: Option<String>,
- extra: Option<serde_json::Value>,
) -> Result<EditContext> {
- // *either* autoaccept is false and editgroup_id is Some, *or* autoaccept is true and
- // editgroup_id is None
- let editgroup_id: FatcatId = match (editgroup_id, autoaccept) {
- (Some(eg), false) => eg,
- (None, true) => {
- let eg = Editgroup {
- editgroup_id: None,
- editor_id: Some(editor_id.to_string()),
- editor: None,
- changelog_index: None,
- submitted: None,
- description: description,
- extra: extra,
- annotations: None,
- edits: None,
- };
- let row = eg.db_create(conn, autoaccept)?;
- FatcatId::from_uuid(&row.id)
- }
- _ => Err(FatcatError::BadRequest(
- "unsupported batch editgroup/accept combination".to_string(),
- ))?,
- };
Ok(EditContext {
editor_id,
editgroup_id,
diff --git a/rust/src/endpoint_handlers.rs b/rust/src/endpoint_handlers.rs
index a19d33f9..dcc647ea 100644
--- a/rust/src/endpoint_handlers.rs
+++ b/rust/src/endpoint_handlers.rs
@@ -17,30 +17,28 @@ use diesel::prelude::*;
use fatcat_api_spec::models;
use fatcat_api_spec::models::*;
-macro_rules! entity_batch_handler {
- ($post_batch_handler:ident, $model:ident) => {
- pub fn $post_batch_handler(
+macro_rules! entity_auto_batch_handler {
+ ($post_auto_batch_handler:ident, $model:ident) => {
+ pub fn $post_auto_batch_handler(
&self,
conn: &DbConn,
+ editgroup: Editgroup,
entity_list: &[models::$model],
- autoaccept: bool,
editor_id: FatcatId,
- editgroup_id: Option<FatcatId>,
- description: Option<String>,
- extra: Option<serde_json::Value>,
- ) -> Result<Vec<EntityEdit>> {
+ ) -> Result<Editgroup> {
- let edit_context = make_edit_context(conn, editor_id, editgroup_id, autoaccept, description, extra)?;
+ let editgroup_row = editgroup.db_create(conn, true)?;
+ let editgroup_id = FatcatId::from_uuid(&editgroup_row.id);
+ let edit_context = make_edit_context(editor_id, editgroup_id, true)?;
edit_context.check(&conn)?;
let model_list: Vec<&models::$model> = entity_list.iter().map(|e| e).collect();
- let edits = $model::db_create_batch(conn, &edit_context, model_list.as_slice())?;
+ let _edits = $model::db_create_batch(conn, &edit_context, model_list.as_slice())?;
- if autoaccept {
- let _clr: ChangelogRow = diesel::insert_into(changelog::table)
- .values((changelog::editgroup_id.eq(edit_context.editgroup_id.to_uuid()),))
- .get_result(conn)?;
- }
- edits.into_iter().map(|e| e.into_model()).collect()
+ let _clr: ChangelogRow = diesel::insert_into(changelog::table)
+ .values((changelog::editgroup_id.eq(edit_context.editgroup_id.to_uuid()),))
+ .get_result(conn)?;
+ // XXX: edits.into_iter().map(|e| e.into_model()).collect()
+ self.get_editgroup_handler(conn, editgroup_id)
}
}
}
@@ -620,11 +618,11 @@ impl Server {
Ok((editor_row.into_model(), created))
}
- entity_batch_handler!(create_container_batch_handler, ContainerEntity);
- entity_batch_handler!(create_creator_batch_handler, CreatorEntity);
- entity_batch_handler!(create_file_batch_handler, FileEntity);
- entity_batch_handler!(create_fileset_batch_handler, FilesetEntity);
- entity_batch_handler!(create_webcapture_batch_handler, WebcaptureEntity);
- entity_batch_handler!(create_release_batch_handler, ReleaseEntity);
- entity_batch_handler!(create_work_batch_handler, WorkEntity);
+ entity_auto_batch_handler!(create_container_auto_batch_handler, ContainerEntity);
+ entity_auto_batch_handler!(create_creator_auto_batch_handler, CreatorEntity);
+ entity_auto_batch_handler!(create_file_auto_batch_handler, FileEntity);
+ entity_auto_batch_handler!(create_fileset_auto_batch_handler, FilesetEntity);
+ entity_auto_batch_handler!(create_webcapture_auto_batch_handler, WebcaptureEntity);
+ entity_auto_batch_handler!(create_release_auto_batch_handler, ReleaseEntity);
+ entity_auto_batch_handler!(create_work_auto_batch_handler, WorkEntity);
}
diff --git a/rust/src/endpoints.rs b/rust/src/endpoints.rs
index 4817184f..7d6db908 100644
--- a/rust/src/endpoints.rs
+++ b/rust/src/endpoints.rs
@@ -69,11 +69,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,
- $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,
+ ($get_fn:ident, $get_resp:ident, $post_fn:ident, $post_resp:ident, $auto_batch_type:ident,
+ $post_auto_batch_fn:ident, $post_auto_batch_handler:ident, $post_auto_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(
@@ -110,8 +111,8 @@ macro_rules! wrap_entity_handlers {
fn $post_fn(
&self,
- entity: models::$model,
editgroup_id: String,
+ entity: models::$model,
context: &Context,
) -> Box<Future<Item = $post_resp, Error = ApiError> + Send> {
let conn = self.db_pool.get().expect("db_pool error");
@@ -120,7 +121,7 @@ macro_rules! wrap_entity_handlers {
let auth_context = self.auth_confectionary.require_auth(&conn, &context.auth_data, Some(stringify!($post_fn)))?;
auth_context.require_role(FatcatRole::Editor)?;
auth_context.require_editgroup(&conn, editgroup_id)?;
- let edit_context = make_edit_context(&conn, auth_context.editor_id, Some(editgroup_id), false, None, None)?;
+ let edit_context = make_edit_context(auth_context.editor_id, editgroup_id, false)?;
edit_context.check(&conn)?;
entity.db_create(&conn, &edit_context)?.into_model()
}).map_err(|e| FatcatError::from(e)) {
@@ -133,54 +134,51 @@ macro_rules! wrap_entity_handlers {
Box::new(futures::done(Ok(ret)))
}
- fn $post_batch_fn(
+ fn $post_auto_batch_fn(
&self,
- entity_list: &Vec<models::$model>,
- autoaccept: Option<bool>,
- editgroup_id: Option<String>,
- description: Option<String>,
- extra: Option<String>,
+ auto_batch: $auto_batch_type,
context: &Context,
- ) -> Box<Future<Item = $post_batch_resp, Error = ApiError> + Send> {
+ ) -> Box<Future<Item = $post_auto_batch_resp, Error = ApiError> + Send> {
let conn = self.db_pool.get().expect("db_pool error");
let ret = match conn.transaction(|| {
- let auth_context = self.auth_confectionary.require_auth(&conn, &context.auth_data, Some(stringify!($post_batch_fn)))?;
- let autoaccept = autoaccept.unwrap_or(false);
- if autoaccept {
- auth_context.require_role(FatcatRole::Admin)?;
- } else {
- auth_context.require_role(FatcatRole::Editor)?;
- };
- let editgroup_id = if let Some(s) = editgroup_id {
- // make_edit_context() checks for "both editgroup_id and autosubmit" error case
- let eg_id = FatcatId::from_str(&s)?;
- auth_context.require_editgroup(&conn, eg_id)?;
- Some(eg_id)
- } else { None };
- let extra: Option<serde_json::Value> = match extra {
- Some(v) => serde_json::from_str(&v)?,
- None => None,
+ let auth_context = self.auth_confectionary.require_auth(&conn, &context.auth_data, Some(stringify!($post_auto_batch_fn)))?;
+ auth_context.require_role(FatcatRole::Admin)?;
+ let mut editgroup = auto_batch.editgroup.clone();
+ // TODO: this is duplicated code with create_editgroup()
+ match editgroup.editor_id.clone() {
+ Some(editor_id) => {
+ if editor_id != auth_context.editor_id.to_string()
+ && !auth_context.has_role(FatcatRole::Admin)
+ {
+ return Err(FatcatError::InsufficientPrivileges(
+ "not authorized to create editgroups in others' names".to_string()
+ ))
+ }
+ }
+ None => {
+ editgroup.editor_id = Some(auth_context.editor_id.to_string());
+ }
};
- self.$post_batch_handler(&conn, entity_list, autoaccept, auth_context.editor_id, editgroup_id, description, extra)
- }).map_err(|e| FatcatError::from(e)) {
- Ok(edits) => {
- self.metrics.count("entities.created", edits.len() as i64).ok();
- if let Some(true) = autoaccept {
- self.metrics.incr("editgroup.created").ok();
- self.metrics.incr("editgroup.accepted").ok();
- };
- $post_batch_resp::CreatedEntities(edits)
+ self.$post_auto_batch_handler(&conn, editgroup, &auto_batch.entity_list, auth_context.editor_id)
+ .map_err(|e| FatcatError::from(e))
+ }) {
+ Ok(editgroup) => {
+ // TODO: need a count helper on editgroup
+ //self.metrics.count("entities.created", count as i64).ok();
+ self.metrics.incr("editgroup.created").ok();
+ self.metrics.incr("editgroup.accepted").ok();
+ $post_auto_batch_resp::CreatedEditgroup(editgroup)
},
- Err(fe) => generic_auth_err_responses!(fe, $post_batch_resp),
+ Err(fe) => generic_auth_err_responses!(fe, $post_auto_batch_resp),
};
Box::new(futures::done(Ok(ret)))
}
fn $update_fn(
&self,
+ editgroup_id: String,
ident: String,
entity: models::$model,
- editgroup_id: String,
context: &Context,
) -> Box<Future<Item = $update_resp, Error = ApiError> + Send> {
let conn = self.db_pool.get().expect("db_pool error");
@@ -190,7 +188,7 @@ macro_rules! wrap_entity_handlers {
auth_context.require_role(FatcatRole::Editor)?;
let entity_id = FatcatId::from_str(&ident)?;
auth_context.require_editgroup(&conn, editgroup_id)?;
- let edit_context = make_edit_context(&conn, auth_context.editor_id, Some(editgroup_id), false, None, None)?;
+ let edit_context = make_edit_context(auth_context.editor_id, editgroup_id, false)?;
edit_context.check(&conn)?;
entity.db_update(&conn, &edit_context, entity_id)?.into_model()
}).map_err(|e| FatcatError::from(e)) {
@@ -205,8 +203,8 @@ macro_rules! wrap_entity_handlers {
fn $delete_fn(
&self,
- ident: String,
editgroup_id: String,
+ ident: String,
context: &Context,
) -> Box<Future<Item = $delete_resp, Error = ApiError> + Send> {
let conn = self.db_pool.get().expect("db_pool error");
@@ -216,7 +214,7 @@ macro_rules! wrap_entity_handlers {
auth_context.require_role(FatcatRole::Editor)?;
let entity_id = FatcatId::from_str(&ident)?;
auth_context.require_editgroup(&conn, editgroup_id)?;
- let edit_context = make_edit_context(&conn, auth_context.editor_id, Some(editgroup_id), false, None, None)?;
+ let edit_context = make_edit_context(auth_context.editor_id, editgroup_id, false)?;
edit_context.check(&conn)?;
$model::db_delete(&conn, &edit_context, entity_id)?.into_model()
}).map_err(|e| FatcatError::from(e)) {
@@ -300,18 +298,27 @@ macro_rules! wrap_entity_handlers {
fn $delete_edit_fn(
&self,
+ editgroup_id: String,
edit_id: String,
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(|| {
+ let editgroup_id = FatcatId::from_str(&editgroup_id)?;
let edit_id = Uuid::from_str(&edit_id)?;
let auth_context = self.auth_confectionary.require_auth(&conn, &context.auth_data, Some(stringify!($delete_edit_fn)))?;
auth_context.require_role(FatcatRole::Editor)?;
let edit = $model::db_get_edit(&conn, edit_id)?;
- auth_context.require_editgroup(&conn, FatcatId::from_uuid(&edit.editgroup_id))?;
+ if !(edit.editgroup_id == editgroup_id.to_uuid()) {
+ return Err(FatcatError::BadRequest(
+ "editgroup_id parameter didn't match that of the edit".to_string()
+ ))
+ }
+ auth_context.require_editgroup(&conn, editgroup_id)?;
+ // check for editgroup being deleted happens in db_delete_edit()
$model::db_delete_edit(&conn, edit_id)
- }).map_err(|e| FatcatError::from(e)) {
+ .map_err(|e| FatcatError::from(e))
+ }) {
Ok(()) =>
$delete_edit_resp::DeletedEdit(Success {
success: true,
@@ -429,9 +436,10 @@ impl Api for Server {
GetContainerResponse,
create_container,
CreateContainerResponse,
- create_container_batch,
- create_container_batch_handler,
- CreateContainerBatchResponse,
+ ContainerAutoBatch,
+ create_container_auto_batch,
+ create_container_auto_batch_handler,
+ CreateContainerAutoBatchResponse,
update_container,
UpdateContainerResponse,
delete_container,
@@ -454,9 +462,10 @@ impl Api for Server {
GetCreatorResponse,
create_creator,
CreateCreatorResponse,
- create_creator_batch,
- create_creator_batch_handler,
- CreateCreatorBatchResponse,
+ CreatorAutoBatch,
+ create_creator_auto_batch,
+ create_creator_auto_batch_handler,
+ CreateCreatorAutoBatchResponse,
update_creator,
UpdateCreatorResponse,
delete_creator,
@@ -478,9 +487,10 @@ impl Api for Server {
GetFileResponse,
create_file,
CreateFileResponse,
- create_file_batch,
- create_file_batch_handler,
- CreateFileBatchResponse,
+ FileAutoBatch,
+ create_file_auto_batch,
+ create_file_auto_batch_handler,
+ CreateFileAutoBatchResponse,
update_file,
UpdateFileResponse,
delete_file,
@@ -502,9 +512,10 @@ impl Api for Server {
GetFilesetResponse,
create_fileset,
CreateFilesetResponse,
- create_fileset_batch,
- create_fileset_batch_handler,
- CreateFilesetBatchResponse,
+ FilesetAutoBatch,
+ create_fileset_auto_batch,
+ create_fileset_auto_batch_handler,
+ CreateFilesetAutoBatchResponse,
update_fileset,
UpdateFilesetResponse,
delete_fileset,
@@ -526,9 +537,10 @@ impl Api for Server {
GetWebcaptureResponse,
create_webcapture,
CreateWebcaptureResponse,
- create_webcapture_batch,
- create_webcapture_batch_handler,
- CreateWebcaptureBatchResponse,
+ WebcaptureAutoBatch,
+ create_webcapture_auto_batch,
+ create_webcapture_auto_batch_handler,
+ CreateWebcaptureAutoBatchResponse,
update_webcapture,
UpdateWebcaptureResponse,
delete_webcapture,
@@ -550,9 +562,10 @@ impl Api for Server {
GetReleaseResponse,
create_release,
CreateReleaseResponse,
- create_release_batch,
- create_release_batch_handler,
- CreateReleaseBatchResponse,
+ ReleaseAutoBatch,
+ create_release_auto_batch,
+ create_release_auto_batch_handler,
+ CreateReleaseAutoBatchResponse,
update_release,
UpdateReleaseResponse,
delete_release,
@@ -574,9 +587,10 @@ impl Api for Server {
GetWorkResponse,
create_work,
CreateWorkResponse,
- create_work_batch,
- create_work_batch_handler,
- CreateWorkBatchResponse,
+ WorkAutoBatch,
+ create_work_auto_batch,
+ create_work_auto_batch_handler,
+ CreateWorkAutoBatchResponse,
update_work,
UpdateWorkResponse,
delete_work,
@@ -941,31 +955,31 @@ impl Api for Server {
context: &Context,
) -> Box<Future<Item = CreateEditgroupResponse, Error = ApiError> + Send> {
let conn = self.db_pool.get().expect("db_pool error");
- let ret = match conn
- .transaction(|| {
- let auth_context = self.auth_confectionary.require_auth(
- &conn,
- &context.auth_data,
- Some("create_editgroup"),
- )?;
- auth_context.require_role(FatcatRole::Editor)?;
- let mut entity = entity.clone();
- match entity.editor_id.clone() {
- Some(editor_id) => {
- if editor_id != auth_context.editor_id.to_string()
- && !auth_context.has_role(FatcatRole::Admin)
- {
- bail!("not authorized to create editgroups in others' names");
- }
- }
- None => {
- entity.editor_id = Some(auth_context.editor_id.to_string());
+ let ret = match conn.transaction(|| {
+ let auth_context = self.auth_confectionary.require_auth(
+ &conn,
+ &context.auth_data,
+ Some("create_editgroup"),
+ )?;
+ auth_context.require_role(FatcatRole::Editor)?;
+ let mut entity = entity.clone();
+ match entity.editor_id.clone() {
+ Some(editor_id) => {
+ if editor_id != auth_context.editor_id.to_string()
+ && !auth_context.has_role(FatcatRole::Admin)
+ {
+ return Err(FatcatError::InsufficientPrivileges(
+ "not authorized to create editgroups in others' names".to_string(),
+ ));
}
- };
- self.create_editgroup_handler(&conn, entity)
- })
- .map_err(|e| FatcatError::from(e))
- {
+ }
+ None => {
+ entity.editor_id = Some(auth_context.editor_id.to_string());
+ }
+ };
+ self.create_editgroup_handler(&conn, entity)
+ .map_err(|e| FatcatError::from(e))
+ }) {
Ok(eg) => {
self.metrics.incr("editgroup.created").ok();
CreateEditgroupResponse::SuccessfullyCreated(eg)
@@ -1035,33 +1049,35 @@ impl Api for Server {
context: &Context,
) -> Box<Future<Item = CreateEditgroupAnnotationResponse, Error = ApiError> + Send> {
let conn = self.db_pool.get().expect("db_pool error");
- let ret = match conn
- .transaction(|| {
- let auth_context = self.auth_confectionary.require_auth(
- &conn,
- &context.auth_data,
- Some("create_editgroup_annotation"),
- )?;
- auth_context.require_role(FatcatRole::Editor)?;
- let editgroup_id = FatcatId::from_str(&editgroup_id)?;
- let mut annotation = annotation.clone();
- annotation.editgroup_id = Some(editgroup_id.to_string());
- match annotation.editor_id.clone() {
- Some(editor_id) => {
- if editor_id != auth_context.editor_id.to_string()
- && !auth_context.has_role(FatcatRole::Superuser)
- {
- bail!("not authorized to annotate in others' names");
- }
- }
- None => {
- annotation.editor_id = Some(auth_context.editor_id.to_string());
+ let ret = match conn.transaction(|| {
+ let auth_context = self.auth_confectionary.require_auth(
+ &conn,
+ &context.auth_data,
+ Some("create_editgroup_annotation"),
+ )?;
+ auth_context.require_role(FatcatRole::Editor)?;
+ let editgroup_id = FatcatId::from_str(&editgroup_id)?;
+ let mut annotation = annotation.clone();
+ annotation.editgroup_id = Some(editgroup_id.to_string());
+ match annotation.editor_id.clone() {
+ Some(editor_id) => {
+ if editor_id != auth_context.editor_id.to_string()
+ && !auth_context.has_role(FatcatRole::Superuser)
+ {
+ return Err(FatcatError::BadRequest(
+ "not authorized to annotate in others' names".to_string(),
+ ));
}
- };
- annotation.db_create(&conn).map(|a| a.into_model())
- })
- .map_err(|e: Error| FatcatError::from(e))
- {
+ }
+ None => {
+ annotation.editor_id = Some(auth_context.editor_id.to_string());
+ }
+ };
+ annotation
+ .db_create(&conn)
+ .map(|a| a.into_model())
+ .map_err(|e: Error| FatcatError::from(e))
+ }) {
Ok(annotation) => CreateEditgroupAnnotationResponse::Created(annotation),
Err(fe) => generic_auth_err_responses!(fe, CreateEditgroupAnnotationResponse),
};
diff --git a/rust/src/entity_crud.rs b/rust/src/entity_crud.rs
index 8f4c33a8..bdb83560 100644
--- a/rust/src/entity_crud.rs
+++ b/rust/src/entity_crud.rs
@@ -385,13 +385,14 @@ macro_rules! generic_db_create_batch {
rev_ids
.into_iter()
.zip(ident_ids.into_iter())
- .map(|(rev_id, ident_id)| Self::EditNewRow {
+ .zip(models.into_iter().map(|m| m.edit_extra.clone()))
+ .map(|((rev_id, ident_id), edit_extra)| Self::EditNewRow {
editgroup_id: edit_context.editgroup_id.to_uuid(),
rev_id: Some(rev_id),
ident_id,
redirect_id: None,
prev_rev: None,
- extra_json: edit_context.extra_json.clone(),
+ extra_json: edit_extra,
})
.collect::<Vec<Self::EditNewRow>>(),
)
@@ -519,7 +520,7 @@ macro_rules! generic_db_delete {
$edit_table::rev_id.eq(None::<Uuid>),
$edit_table::redirect_id.eq(None::<Uuid>),
$edit_table::prev_rev.eq(current.rev_id),
- $edit_table::extra_json.eq(&edit_context.extra_json),
+ //$edit_table::extra_json.eq(None::<?>),
))
.get_result(conn)?;
@@ -1816,13 +1817,14 @@ impl EntityCrud for ReleaseEntity {
rev_ids
.into_iter()
.zip(ident_ids.into_iter())
- .map(|(rev_id, ident_id)| Self::EditNewRow {
+ .zip(models.into_iter().map(|m| m.edit_extra.clone()))
+ .map(|((rev_id, ident_id), edit_extra)| Self::EditNewRow {
editgroup_id: edit_context.editgroup_id.to_uuid(),
rev_id: Some(rev_id),
ident_id,
redirect_id: None,
prev_rev: None,
- extra_json: edit_context.extra_json.clone(),
+ extra_json: edit_extra,
})
.collect::<Vec<Self::EditNewRow>>(),
)