diff options
author | Bryan Newbold <bnewbold@robocracy.org> | 2018-09-06 15:02:57 -0700 |
---|---|---|
committer | Bryan Newbold <bnewbold@robocracy.org> | 2018-09-06 15:02:59 -0700 |
commit | 0f229e57965901a1230dd346fb676e8caf67ec2e (patch) | |
tree | 4d8af9a9aa99dcd67ce8ce15fdfc7484d8b77856 /rust | |
parent | 36a1fbe4ce13be3631e07a5ecfc84ffc87c74931 (diff) | |
download | fatcat-0f229e57965901a1230dd346fb676e8caf67ec2e.tar.gz fatcat-0f229e57965901a1230dd346fb676e8caf67ec2e.zip |
skeleton create/delete endpoints for works
Other entities just stubs
Diffstat (limited to 'rust')
-rw-r--r-- | rust/src/api_server.rs | 122 | ||||
-rw-r--r-- | rust/src/api_wrappers.rs | 108 | ||||
-rw-r--r-- | rust/tests/test_api_server.rs | 65 |
3 files changed, 293 insertions, 2 deletions
diff --git a/rust/src/api_server.rs b/rust/src/api_server.rs index 7bf3122b..66c31f61 100644 --- a/rust/src/api_server.rs +++ b/rust/src/api_server.rs @@ -535,6 +535,19 @@ impl Server { edit.into_model() } + // XXX: + pub fn update_container_handler( + &self, + id: &Uuid, + entity: models::ContainerEntity, + conn: &DbConn, + ) -> Result<EntityEdit> { + unimplemented!() + } + pub fn delete_container_handler(&self, id: &Uuid, editgroup_id: Option<Uuid>, conn: &DbConn) -> Result<EntityEdit> { + unimplemented!() + } + pub fn create_creator_handler( &self, entity: models::CreatorEntity, @@ -574,6 +587,19 @@ impl Server { edit.into_model() } + // XXX: + pub fn update_creator_handler( + &self, + id: &Uuid, + entity: models::CreatorEntity, + conn: &DbConn, + ) -> Result<EntityEdit> { + unimplemented!() + } + pub fn delete_creator_handler(&self, id: &Uuid, editgroup_id: Option<Uuid>, conn: &DbConn) -> Result<EntityEdit> { + unimplemented!() + } + pub fn create_file_handler( &self, entity: models::FileEntity, @@ -654,6 +680,19 @@ impl Server { edit.into_model() } + // XXX: + pub fn update_file_handler( + &self, + id: &Uuid, + entity: models::FileEntity, + conn: &DbConn, + ) -> Result<EntityEdit> { + unimplemented!() + } + pub fn delete_file_handler(&self, id: &Uuid, editgroup_id: Option<Uuid>, conn: &DbConn) -> Result<EntityEdit> { + unimplemented!() + } + pub fn create_release_handler( &self, entity: models::ReleaseEntity, @@ -829,6 +868,19 @@ impl Server { edit.into_model() } + // XXX: + pub fn update_release_handler( + &self, + id: &Uuid, + entity: models::ReleaseEntity, + conn: &DbConn, + ) -> Result<EntityEdit> { + unimplemented!() + } + pub fn delete_release_handler(&self, id: &Uuid, editgroup_id: Option<Uuid>, conn: &DbConn) -> Result<EntityEdit> { + unimplemented!() + } + pub fn create_work_handler( &self, entity: models::WorkEntity, @@ -858,6 +910,76 @@ impl Server { edit.into_model() } + pub fn update_work_handler( + &self, + id: &Uuid, + entity: models::WorkEntity, + conn: &DbConn, + ) -> Result<EntityEdit> { + let editor_id = Uuid::parse_str("00000000-0000-0000-AAAA-000000000001")?; // TODO: auth + let editgroup_id = match entity.editgroup_id { + None => get_or_create_editgroup(editor_id, conn).expect("current editgroup"), + Some(param) => fcid2uuid(¶m)?, + }; + + // TODO: refactor this into a check on WorkIdentRow + let current: WorkIdentRow = work_ident::table.find(id).first(conn)?; + if current.is_live != true { + // TODO: what if isn't live? 4xx not 5xx + bail!("can't delete an entity that doesn't exist yet"); + } + if current.rev_id.is_none() { + // TODO: what if it's already deleted? 4xx not 5xx + bail!("entity was already deleted"); + } + + let edit: WorkEditRow = + diesel::sql_query( + "WITH rev AS ( INSERT INTO work_rev (extra_json) + VALUES ($1) + RETURNING id ), + INSERT INTO work_edit (editgroup_id, ident_id, rev_id, prev_rev) VALUES + ($2, $3, (SELECT rev.id FROM rev), $4) + RETURNING *", + ).bind::<diesel::sql_types::Nullable<diesel::sql_types::Json>, _>(entity.extra) + .bind::<diesel::sql_types::Uuid, _>(editgroup_id) + .bind::<diesel::sql_types::Uuid, _>(id) + .bind::<diesel::sql_types::Uuid, _>(current.rev_id.unwrap()) + .get_result(conn)?; + + edit.into_model() + } + + pub fn delete_work_handler(&self, id: &Uuid, editgroup_id: Option<Uuid>, conn: &DbConn) -> Result<EntityEdit> { + let editor_id = Uuid::parse_str("00000000-0000-0000-AAAA-000000000001")?; // TODO: auth + let editgroup_id = match editgroup_id { + Some(egid) => egid, + None => get_or_create_editgroup(editor_id, conn)? + }; + + let current: WorkIdentRow = work_ident::table.find(id).first(conn)?; + if current.is_live != true { + // TODO: what if isn't live? 4xx not 5xx + bail!("can't delete an entity that doesn't exist yet"); + } + if current.rev_id.is_none() { + // TODO: what if it's already deleted? 4xx not 5xx + bail!("entity was already deleted"); + } + let edit: WorkEditRow = insert_into(work_edit::table) + .values(( + work_edit::editgroup_id.eq(editgroup_id), + work_edit::ident_id.eq(id), + work_edit::rev_id.eq(None::<Uuid>), + work_edit::redirect_id.eq(None::<Uuid>), + work_edit::prev_rev.eq(current.rev_id), + //work_edit::extra_json.eq(extra), + )) + .get_result(conn)?; + + edit.into_model() + } + pub fn accept_editgroup_handler(&self, id: &str, conn: &DbConn) -> Result<()> { accept_editgroup(fcid2uuid(id)?, conn)?; Ok(()) diff --git a/rust/src/api_wrappers.rs b/rust/src/api_wrappers.rs index 403c7caf..de1fc9da 100644 --- a/rust/src/api_wrappers.rs +++ b/rust/src/api_wrappers.rs @@ -19,8 +19,9 @@ macro_rules! wrap_entity_handlers { // The only stable approach I know of would be: https://github.com/dtolnay/mashup ($get_fn:ident, $get_handler:ident, $get_resp:ident, $post_fn:ident, $post_handler:ident, $post_resp:ident, $post_batch_fn:ident, $post_batch_handler:ident, - $post_batch_resp:ident, $get_history_fn:ident, $get_history_handler:ident, - $get_history_resp:ident, $model:ident) => { + $post_batch_resp:ident, $update_fn:ident, $update_handler:ident, $update_resp:ident, + $delete_fn:ident, $delete_handler:ident, $delete_resp:ident, $get_history_fn:ident, + $get_history_handler:ident, $get_history_resp:ident, $model:ident) => { fn $get_fn( &self, @@ -106,6 +107,79 @@ macro_rules! wrap_entity_handlers { Box::new(futures::done(Ok(ret))) } + fn $update_fn( + &self, + id: String, + entity: models::$model, + _context: &Context, + ) -> Box<Future<Item = $update_resp, Error = ApiError> + Send> { + let id = if let Ok(parsed) = fcid2uuid(&id) { parsed } else { + return Box::new(futures::done(Ok($update_resp::BadRequest(ErrorResponse { + message: ErrorKind::InvalidFatcatId(id).to_string() })))); + }; + let conn = self.db_pool.get().expect("db_pool error"); + let ret = match conn.transaction(|| self.$update_handler(&id, entity, &conn)) { + Ok(edit) => + $update_resp::UpdatedEntity(edit), + Err(Error(ErrorKind::Diesel(::diesel::result::Error::NotFound), _)) => + $update_resp::NotFound(ErrorResponse { message: format!("No such entity {}: {}", stringify!($model), id) }), + Err(Error(ErrorKind::Diesel(e), _)) => + $update_resp::BadRequest(ErrorResponse { message: e.to_string() }), + Err(Error(ErrorKind::Uuid(e), _)) => + $update_resp::BadRequest(ErrorResponse { message: e.to_string() }), + Err(Error(ErrorKind::InvalidFatcatId(e), _)) => + $update_resp::BadRequest(ErrorResponse { + message: ErrorKind::InvalidFatcatId(e).to_string() }), + Err(Error(ErrorKind::MalformedExternalId(e), _)) => + $update_resp::BadRequest(ErrorResponse { message: e.to_string() }), + Err(e) => { + error!("{}", e); + $update_resp::GenericError(ErrorResponse { message: e.to_string() }) + }, + }; + Box::new(futures::done(Ok(ret))) + } + + fn $delete_fn( + &self, + id: String, + editgroup_id: Option<String>, + _context: &Context, + ) -> Box<Future<Item = $delete_resp, Error = ApiError> + Send> { + let id = if let Ok(parsed) = fcid2uuid(&id) { parsed } else { + return Box::new(futures::done(Ok($delete_resp::BadRequest(ErrorResponse { + message: ErrorKind::InvalidFatcatId(id).to_string() })))); + }; + let editgroup_id = match editgroup_id { + Some(raw) => if let Ok(parsed) = fcid2uuid(&raw) { Some(parsed) } else { + return Box::new(futures::done(Ok($delete_resp::BadRequest(ErrorResponse { + message: ErrorKind::InvalidFatcatId(raw).to_string() })))) + } + None => None + }; + let conn = self.db_pool.get().expect("db_pool error"); + let ret = match conn.transaction(|| self.$delete_handler(&id, editgroup_id, &conn)) { + Ok(edit) => + $delete_resp::DeletedEntity(edit), + Err(Error(ErrorKind::Diesel(::diesel::result::Error::NotFound), _)) => + $delete_resp::NotFound(ErrorResponse { message: format!("No such entity {}: {}", stringify!($model), id) }), + Err(Error(ErrorKind::Diesel(e), _)) => + $delete_resp::BadRequest(ErrorResponse { message: e.to_string() }), + Err(Error(ErrorKind::Uuid(e), _)) => + $delete_resp::BadRequest(ErrorResponse { message: e.to_string() }), + Err(Error(ErrorKind::InvalidFatcatId(e), _)) => + $delete_resp::BadRequest(ErrorResponse { + message: ErrorKind::InvalidFatcatId(e).to_string() }), + Err(Error(ErrorKind::MalformedExternalId(e), _)) => + $delete_resp::BadRequest(ErrorResponse { message: e.to_string() }), + Err(e) => { + error!("{}", e); + $delete_resp::GenericError(ErrorResponse { message: e.to_string() }) + }, + }; + Box::new(futures::done(Ok(ret))) + } + fn $get_history_fn( &self, id: String, @@ -175,6 +249,12 @@ impl Api for Server { create_container_batch, create_container_batch_handler, CreateContainerBatchResponse, + update_container, + update_container_handler, + UpdateContainerResponse, + delete_container, + delete_container_handler, + DeleteContainerResponse, get_container_history, get_container_history_handler, GetContainerHistoryResponse, @@ -191,6 +271,12 @@ impl Api for Server { create_creator_batch, create_creator_batch_handler, CreateCreatorBatchResponse, + update_creator, + update_creator_handler, + UpdateCreatorResponse, + delete_creator, + delete_creator_handler, + DeleteCreatorResponse, get_creator_history, get_creator_history_handler, GetCreatorHistoryResponse, @@ -206,6 +292,12 @@ impl Api for Server { create_file_batch, create_file_batch_handler, CreateFileBatchResponse, + update_file, + update_file_handler, + UpdateFileResponse, + delete_file, + delete_file_handler, + DeleteFileResponse, get_file_history, get_file_history_handler, GetFileHistoryResponse, @@ -221,6 +313,12 @@ impl Api for Server { create_release_batch, create_release_batch_handler, CreateReleaseBatchResponse, + update_release, + update_release_handler, + UpdateReleaseResponse, + delete_release, + delete_release_handler, + DeleteReleaseResponse, get_release_history, get_release_history_handler, GetReleaseHistoryResponse, @@ -236,6 +334,12 @@ impl Api for Server { create_work_batch, create_work_batch_handler, CreateWorkBatchResponse, + update_work, + update_work_handler, + UpdateWorkResponse, + delete_work, + delete_work_handler, + DeleteWorkResponse, get_work_history, get_work_history_handler, GetWorkHistoryResponse, diff --git a/rust/tests/test_api_server.rs b/rust/tests/test_api_server.rs index 02c77413..4b181188 100644 --- a/rust/tests/test_api_server.rs +++ b/rust/tests/test_api_server.rs @@ -469,6 +469,71 @@ fn test_post_work() { } #[test] +fn test_update_work() { + let (headers, router, conn) = setup(); + + check_response( + request::post( + "http://localhost:9411/v0/work", + headers.clone(), + r#"{ + "extra": { "source": "other speculation" } + }"#, + &router, + ), + status::Created, + None, + ); + + let editor_id = Uuid::parse_str("00000000-0000-0000-AAAA-000000000001").unwrap(); + let editgroup_id = get_or_create_editgroup(editor_id, &conn).unwrap(); + check_response( + request::post( + &format!( + "http://localhost:9411/v0/editgroup/{}/accept", + uuid2fcid(&editgroup_id) + ), + headers.clone(), + "", + &router, + ), + status::Ok, + None, + ); +} + +#[test] +fn test_delete_work() { + let (headers, router, conn) = setup(); + + check_response( + request::delete( + "http://localhost:9411/v0/work/aaaaaaaaaaaaavkvaaaaaaaaai", + headers.clone(), + &router, + ), + status::Ok, + None, + ); + + let editor_id = Uuid::parse_str("00000000-0000-0000-AAAA-000000000001").unwrap(); + let editgroup_id = get_or_create_editgroup(editor_id, &conn).unwrap(); + check_response( + request::post( + &format!( + "http://localhost:9411/v0/editgroup/{}/accept", + uuid2fcid(&editgroup_id) + ), + headers.clone(), + "", + &router, + ), + status::Ok, + None, + ); +} + +#[test] fn test_accept_editgroup() { let (headers, router, conn) = setup(); |