summaryrefslogtreecommitdiffstats
path: root/rust
diff options
context:
space:
mode:
authorBryan Newbold <bnewbold@robocracy.org>2018-09-06 15:02:57 -0700
committerBryan Newbold <bnewbold@robocracy.org>2018-09-06 15:02:59 -0700
commit0f229e57965901a1230dd346fb676e8caf67ec2e (patch)
tree4d8af9a9aa99dcd67ce8ce15fdfc7484d8b77856 /rust
parent36a1fbe4ce13be3631e07a5ecfc84ffc87c74931 (diff)
downloadfatcat-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.rs122
-rw-r--r--rust/src/api_wrappers.rs108
-rw-r--r--rust/tests/test_api_server.rs65
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(&param)?,
+ };
+
+ // 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();