diff options
author | Bryan Newbold <bnewbold@robocracy.org> | 2018-09-22 17:25:57 -0700 |
---|---|---|
committer | Bryan Newbold <bnewbold@robocracy.org> | 2018-09-22 17:25:57 -0700 |
commit | e9d7d73339df14ef2fe35815e693f0dbd7d1d244 (patch) | |
tree | 78140de79fbc0c3ace5d65808cba251219d438f3 /rust/fatcat-api-spec/src/server.rs | |
parent | 3b30465c2faa0b73ac2973f868105caad1a8e745 (diff) | |
download | fatcat-e9d7d73339df14ef2fe35815e693f0dbd7d1d244.tar.gz fatcat-e9d7d73339df14ef2fe35815e693f0dbd7d1d244.zip |
codegen fatcat-api-spec
Diffstat (limited to 'rust/fatcat-api-spec/src/server.rs')
-rw-r--r-- | rust/fatcat-api-spec/src/server.rs | 2391 |
1 files changed, 1188 insertions, 1203 deletions
diff --git a/rust/fatcat-api-spec/src/server.rs b/rust/fatcat-api-spec/src/server.rs index 8c699065..db8dcd7c 100644 --- a/rust/fatcat-api-spec/src/server.rs +++ b/rust/fatcat-api-spec/src/server.rs @@ -92,105 +92,6 @@ where { let api_clone = api.clone(); router.post( - "/v0/editgroup/:id/accept", - move |req: &mut Request| { - let mut context = Context::default(); - - // Helper function to provide a code block to use `?` in (to be replaced by the `catch` block when it exists). - fn handle_request<T>(req: &mut Request, api: &T, context: &mut Context) -> Result<Response, Response> - where - T: Api, - { - context.x_span_id = Some(req.headers.get::<XSpanId>().map(XSpanId::to_string).unwrap_or_else(|| self::uuid::Uuid::new_v4().to_string())); - context.auth_data = req.extensions.remove::<AuthData>(); - context.authorization = req.extensions.remove::<Authorization>(); - - // Path parameters - let param_id = { - let param = req - .extensions - .get::<Router>() - .ok_or_else(|| Response::with((status::InternalServerError, "An internal error occurred".to_string())))? - .find("id") - .ok_or_else(|| Response::with((status::BadRequest, "Missing path parameter id".to_string())))?; - percent_decode(param.as_bytes()) - .decode_utf8() - .map_err(|_| Response::with((status::BadRequest, format!("Couldn't percent-decode path parameter as UTF-8: {}", param))))? - .parse() - .map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse path parameter id: {}", e))))? - }; - - match api.accept_editgroup(param_id, context).wait() { - Ok(rsp) => match rsp { - AcceptEditgroupResponse::MergedSuccessfully(body) => { - let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); - - let mut response = Response::with((status::Status::from_u16(200), body_string)); - response.headers.set(ContentType(mimetypes::responses::ACCEPT_EDITGROUP_MERGED_SUCCESSFULLY.clone())); - - context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); - - Ok(response) - } - AcceptEditgroupResponse::BadRequest(body) => { - let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); - - let mut response = Response::with((status::Status::from_u16(400), body_string)); - response.headers.set(ContentType(mimetypes::responses::ACCEPT_EDITGROUP_BAD_REQUEST.clone())); - - context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); - - Ok(response) - } - AcceptEditgroupResponse::NotFound(body) => { - let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); - - let mut response = Response::with((status::Status::from_u16(404), body_string)); - response.headers.set(ContentType(mimetypes::responses::ACCEPT_EDITGROUP_NOT_FOUND.clone())); - - context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); - - Ok(response) - } - AcceptEditgroupResponse::EditConflict(body) => { - let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); - - let mut response = Response::with((status::Status::from_u16(409), body_string)); - response.headers.set(ContentType(mimetypes::responses::ACCEPT_EDITGROUP_EDIT_CONFLICT.clone())); - - context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); - - Ok(response) - } - AcceptEditgroupResponse::GenericError(body) => { - let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); - - let mut response = Response::with((status::Status::from_u16(500), body_string)); - response.headers.set(ContentType(mimetypes::responses::ACCEPT_EDITGROUP_GENERIC_ERROR.clone())); - - context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); - - Ok(response) - } - }, - Err(_) => { - // Application code returned an error. This should not happen, as the implementation should - // return a valid response. - Err(Response::with((status::InternalServerError, "An internal error occurred".to_string()))) - } - } - } - - handle_request(req, &api_clone, &mut context).or_else(|mut response| { - context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); - Ok(response) - }) - }, - "AcceptEditgroup", - ); - - let api_clone = api.clone(); - router.post( "/v0/container", move |req: &mut Request| { let mut context = Context::default(); @@ -221,11 +122,10 @@ where let param_entity = if let Some(param_entity_raw) = param_entity { let deserializer = &mut serde_json::Deserializer::from_str(¶m_entity_raw); - let param_entity: Option<models::ContainerEntity> = - serde_ignored::deserialize(deserializer, |path| { - warn!("Ignoring unknown field in body: {}", path); - unused_elements.push(path.to_string()); - }).map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse body parameter entity - doesn't match schema: {}", e))))?; + let param_entity: Option<models::ContainerEntity> = serde_ignored::deserialize(deserializer, |path| { + warn!("Ignoring unknown field in body: {}", path); + unused_elements.push(path.to_string()); + }).map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse body parameter entity - doesn't match schema: {}", e))))?; param_entity } else { @@ -333,11 +233,10 @@ where let param_entity_list = if let Some(param_entity_list_raw) = param_entity_list { let deserializer = &mut serde_json::Deserializer::from_str(¶m_entity_list_raw); - let param_entity_list: Option<Vec<models::ContainerEntity>> = - serde_ignored::deserialize(deserializer, |path| { - warn!("Ignoring unknown field in body: {}", path); - unused_elements.push(path.to_string()); - }).map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse body parameter entity_list - doesn't match schema: {}", e))))?; + let param_entity_list: Option<Vec<models::ContainerEntity>> = serde_ignored::deserialize(deserializer, |path| { + warn!("Ignoring unknown field in body: {}", path); + unused_elements.push(path.to_string()); + }).map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse body parameter entity_list - doesn't match schema: {}", e))))?; param_entity_list } else { @@ -413,8 +312,8 @@ where ); let api_clone = api.clone(); - router.post( - "/v0/creator", + router.delete( + "/v0/container/:id", move |req: &mut Request| { let mut context = Context::default(); @@ -427,83 +326,65 @@ where context.auth_data = req.extensions.remove::<AuthData>(); context.authorization = req.extensions.remove::<Authorization>(); + // Path parameters + let param_id = { + let param = req + .extensions + .get::<Router>() + .ok_or_else(|| Response::with((status::InternalServerError, "An internal error occurred".to_string())))? + .find("id") + .ok_or_else(|| Response::with((status::BadRequest, "Missing path parameter id".to_string())))?; + percent_decode(param.as_bytes()) + .decode_utf8() + .map_err(|_| Response::with((status::BadRequest, format!("Couldn't percent-decode path parameter as UTF-8: {}", param))))? + .parse() + .map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse path parameter id: {}", e))))? + }; + // Query parameters (note that non-required or collection query parameters will ignore garbage values, rather than causing a 400 response) let query_params = req.get::<UrlEncodedQuery>().unwrap_or_default(); let param_editgroup = query_params.get("editgroup").and_then(|list| list.first()).and_then(|x| x.parse::<String>().ok()); - // Body parameters (note that non-required body parameters will ignore garbage - // values, rather than causing a 400 response). Produce warning header and logs for - // any unused fields. - - let param_entity = req - .get::<bodyparser::Raw>() - .map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse body parameter entity - not valid UTF-8: {}", e))))?; - - let mut unused_elements = Vec::new(); - - let param_entity = if let Some(param_entity_raw) = param_entity { - let deserializer = &mut serde_json::Deserializer::from_str(¶m_entity_raw); - - let param_entity: Option<models::CreatorEntity> = - serde_ignored::deserialize(deserializer, |path| { - warn!("Ignoring unknown field in body: {}", path); - unused_elements.push(path.to_string()); - }).map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse body parameter entity - doesn't match schema: {}", e))))?; - - param_entity - } else { - None - }; - let param_entity = param_entity.ok_or_else(|| Response::with((status::BadRequest, "Missing required body parameter entity".to_string())))?; - - match api.create_creator(param_entity, param_editgroup, context).wait() { + match api.delete_container(param_id, param_editgroup, context).wait() { Ok(rsp) => match rsp { - CreateCreatorResponse::CreatedEntity(body) => { + DeleteContainerResponse::DeletedEntity(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); - let mut response = Response::with((status::Status::from_u16(201), body_string)); - response.headers.set(ContentType(mimetypes::responses::CREATE_CREATOR_CREATED_ENTITY.clone())); + let mut response = Response::with((status::Status::from_u16(200), body_string)); + response.headers.set(ContentType(mimetypes::responses::DELETE_CONTAINER_DELETED_ENTITY.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); - if !unused_elements.is_empty() { - response.headers.set(Warning(format!("Ignoring unknown fields in body: {:?}", unused_elements))); - } + Ok(response) } - CreateCreatorResponse::BadRequest(body) => { + DeleteContainerResponse::BadRequest(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(400), body_string)); - response.headers.set(ContentType(mimetypes::responses::CREATE_CREATOR_BAD_REQUEST.clone())); + response.headers.set(ContentType(mimetypes::responses::DELETE_CONTAINER_BAD_REQUEST.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); - if !unused_elements.is_empty() { - response.headers.set(Warning(format!("Ignoring unknown fields in body: {:?}", unused_elements))); - } + Ok(response) } - CreateCreatorResponse::NotFound(body) => { + DeleteContainerResponse::NotFound(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(404), body_string)); - response.headers.set(ContentType(mimetypes::responses::CREATE_CREATOR_NOT_FOUND.clone())); + response.headers.set(ContentType(mimetypes::responses::DELETE_CONTAINER_NOT_FOUND.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); - if !unused_elements.is_empty() { - response.headers.set(Warning(format!("Ignoring unknown fields in body: {:?}", unused_elements))); - } + Ok(response) } - CreateCreatorResponse::GenericError(body) => { + DeleteContainerResponse::GenericError(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(500), body_string)); - response.headers.set(ContentType(mimetypes::responses::CREATE_CREATOR_GENERIC_ERROR.clone())); + response.headers.set(ContentType(mimetypes::responses::DELETE_CONTAINER_GENERIC_ERROR.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); - if !unused_elements.is_empty() { - response.headers.set(Warning(format!("Ignoring unknown fields in body: {:?}", unused_elements))); - } + Ok(response) } }, @@ -520,12 +401,12 @@ where Ok(response) }) }, - "CreateCreator", + "DeleteContainer", ); let api_clone = api.clone(); - router.post( - "/v0/creator/batch", + router.get( + "/v0/container/:id", move |req: &mut Request| { let mut context = Context::default(); @@ -538,84 +419,65 @@ where context.auth_data = req.extensions.remove::<AuthData>(); context.authorization = req.extensions.remove::<Authorization>(); + // Path parameters + let param_id = { + let param = req + .extensions + .get::<Router>() + .ok_or_else(|| Response::with((status::InternalServerError, "An internal error occurred".to_string())))? + .find("id") + .ok_or_else(|| Response::with((status::BadRequest, "Missing path parameter id".to_string())))?; + percent_decode(param.as_bytes()) + .decode_utf8() + .map_err(|_| Response::with((status::BadRequest, format!("Couldn't percent-decode path parameter as UTF-8: {}", param))))? + .parse() + .map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse path parameter id: {}", e))))? + }; + // Query parameters (note that non-required or collection query parameters will ignore garbage values, rather than causing a 400 response) let query_params = req.get::<UrlEncodedQuery>().unwrap_or_default(); - let param_autoaccept = query_params.get("autoaccept").and_then(|list| list.first()).and_then(|x| x.parse::<bool>().ok()); - let param_editgroup = query_params.get("editgroup").and_then(|list| list.first()).and_then(|x| x.parse::<String>().ok()); - - // Body parameters (note that non-required body parameters will ignore garbage - // values, rather than causing a 400 response). Produce warning header and logs for - // any unused fields. - - let param_entity_list = req - .get::<bodyparser::Raw>() - .map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse body parameter entity_list - not valid UTF-8: {}", e))))?; - - let mut unused_elements = Vec::new(); - - let param_entity_list = if let Some(param_entity_list_raw) = param_entity_list { - let deserializer = &mut serde_json::Deserializer::from_str(¶m_entity_list_raw); - - let param_entity_list: Option<Vec<models::CreatorEntity>> = - serde_ignored::deserialize(deserializer, |path| { - warn!("Ignoring unknown field in body: {}", path); - unused_elements.push(path.to_string()); - }).map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse body parameter entity_list - doesn't match schema: {}", e))))?; - - param_entity_list - } else { - None - }; - let param_entity_list = param_entity_list.ok_or_else(|| Response::with((status::BadRequest, "Missing required body parameter entity_list".to_string())))?; + let param_expand = query_params.get("expand").and_then(|list| list.first()).and_then(|x| x.parse::<String>().ok()); - match api.create_creator_batch(param_entity_list.as_ref(), param_autoaccept, param_editgroup, context).wait() { + match api.get_container(param_id, param_expand, context).wait() { Ok(rsp) => match rsp { - CreateCreatorBatchResponse::CreatedEntities(body) => { + GetContainerResponse::FoundEntity(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); - let mut response = Response::with((status::Status::from_u16(201), body_string)); - response.headers.set(ContentType(mimetypes::responses::CREATE_CREATOR_BATCH_CREATED_ENTITIES.clone())); + let mut response = Response::with((status::Status::from_u16(200), body_string)); + response.headers.set(ContentType(mimetypes::responses::GET_CONTAINER_FOUND_ENTITY.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); - if !unused_elements.is_empty() { - response.headers.set(Warning(format!("Ignoring unknown fields in body: {:?}", unused_elements))); - } + Ok(response) } - CreateCreatorBatchResponse::BadRequest(body) => { + GetContainerResponse::BadRequest(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(400), body_string)); - response.headers.set(ContentType(mimetypes::responses::CREATE_CREATOR_BATCH_BAD_REQUEST.clone())); + response.headers.set(ContentType(mimetypes::responses::GET_CONTAINER_BAD_REQUEST.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); - if !unused_elements.is_empty() { - response.headers.set(Warning(format!("Ignoring unknown fields in body: {:?}", unused_elements))); - } + Ok(response) } - CreateCreatorBatchResponse::NotFound(body) => { + GetContainerResponse::NotFound(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(404), body_string)); - response.headers.set(ContentType(mimetypes::responses::CREATE_CREATOR_BATCH_NOT_FOUND.clone())); + response.headers.set(ContentType(mimetypes::responses::GET_CONTAINER_NOT_FOUND.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); - if !unused_elements.is_empty() { - response.headers.set(Warning(format!("Ignoring unknown fields in body: {:?}", unused_elements))); - } + Ok(response) } - CreateCreatorBatchResponse::GenericError(body) => { + GetContainerResponse::GenericError(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(500), body_string)); - response.headers.set(ContentType(mimetypes::responses::CREATE_CREATOR_BATCH_GENERIC_ERROR.clone())); + response.headers.set(ContentType(mimetypes::responses::GET_CONTAINER_GENERIC_ERROR.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); - if !unused_elements.is_empty() { - response.headers.set(Warning(format!("Ignoring unknown fields in body: {:?}", unused_elements))); - } + Ok(response) } }, @@ -632,12 +494,12 @@ where Ok(response) }) }, - "CreateCreatorBatch", + "GetContainer", ); let api_clone = api.clone(); - router.post( - "/v0/editgroup", + router.get( + "/v0/container/:id/history", move |req: &mut Request| { let mut context = Context::default(); @@ -650,66 +512,65 @@ where context.auth_data = req.extensions.remove::<AuthData>(); context.authorization = req.extensions.remove::<Authorization>(); - // Body parameters (note that non-required body parameters will ignore garbage - // values, rather than causing a 400 response). Produce warning header and logs for - // any unused fields. - - let param_entity = req - .get::<bodyparser::Raw>() - .map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse body parameter entity - not valid UTF-8: {}", e))))?; + // Path parameters + let param_id = { + let param = req + .extensions + .get::<Router>() + .ok_or_else(|| Response::with((status::InternalServerError, "An internal error occurred".to_string())))? + .find("id") + .ok_or_else(|| Response::with((status::BadRequest, "Missing path parameter id".to_string())))?; + percent_decode(param.as_bytes()) + .decode_utf8() + .map_err(|_| Response::with((status::BadRequest, format!("Couldn't percent-decode path parameter as UTF-8: {}", param))))? + .parse() + .map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse path parameter id: {}", e))))? + }; - let mut unused_elements = Vec::new(); + // Query parameters (note that non-required or collection query parameters will ignore garbage values, rather than causing a 400 response) + let query_params = req.get::<UrlEncodedQuery>().unwrap_or_default(); + let param_limit = query_params.get("limit").and_then(|list| list.first()).and_then(|x| x.parse::<i64>().ok()); - let param_entity = if let Some(param_entity_raw) = param_entity { - let deserializer = &mut serde_json::Deserializer::from_str(¶m_entity_raw); + match api.get_container_history(param_id, param_limit, context).wait() { + Ok(rsp) => match rsp { + GetContainerHistoryResponse::FoundEntityHistory(body) => { + let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); - let param_entity: Option<models::Editgroup> = serde_ignored::deserialize(deserializer, |path| { - warn!("Ignoring unknown field in body: {}", path); - unused_elements.push(path.to_string()); - }).map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse body parameter entity - doesn't match schema: {}", e))))?; + let mut response = Response::with((status::Status::from_u16(200), body_string)); + response.headers.set(ContentType(mimetypes::responses::GET_CONTAINER_HISTORY_FOUND_ENTITY_HISTORY.clone())); - param_entity - } else { - None - }; - let param_entity = param_entity.ok_or_else(|| Response::with((status::BadRequest, "Missing required body parameter entity".to_string())))?; + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); - match api.create_editgroup(param_entity, context).wait() { - Ok(rsp) => match rsp { - CreateEditgroupResponse::SuccessfullyCreated(body) => { + Ok(response) + } + GetContainerHistoryResponse::BadRequest(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); - let mut response = Response::with((status::Status::from_u16(201), body_string)); - response.headers.set(ContentType(mimetypes::responses::CREATE_EDITGROUP_SUCCESSFULLY_CREATED.clone())); + let mut response = Response::with((status::Status::from_u16(400), body_string)); + response.headers.set(ContentType(mimetypes::responses::GET_CONTAINER_HISTORY_BAD_REQUEST.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); - if !unused_elements.is_empty() { - response.headers.set(Warning(format!("Ignoring unknown fields in body: {:?}", unused_elements))); - } + Ok(response) } - CreateEditgroupResponse::BadRequest(body) => { + GetContainerHistoryResponse::NotFound(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); - let mut response = Response::with((status::Status::from_u16(400), body_string)); - response.headers.set(ContentType(mimetypes::responses::CREATE_EDITGROUP_BAD_REQUEST.clone())); + let mut response = Response::with((status::Status::from_u16(404), body_string)); + response.headers.set(ContentType(mimetypes::responses::GET_CONTAINER_HISTORY_NOT_FOUND.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); - if !unused_elements.is_empty() { - response.headers.set(Warning(format!("Ignoring unknown fields in body: {:?}", unused_elements))); - } + Ok(response) } - CreateEditgroupResponse::GenericError(body) => { + GetContainerHistoryResponse::GenericError(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(500), body_string)); - response.headers.set(ContentType(mimetypes::responses::CREATE_EDITGROUP_GENERIC_ERROR.clone())); + response.headers.set(ContentType(mimetypes::responses::GET_CONTAINER_HISTORY_GENERIC_ERROR.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); - if !unused_elements.is_empty() { - response.headers.set(Warning(format!("Ignoring unknown fields in body: {:?}", unused_elements))); - } + Ok(response) } }, @@ -726,12 +587,12 @@ where Ok(response) }) }, - "CreateEditgroup", + "GetContainerHistory", ); let api_clone = api.clone(); - router.post( - "/v0/file", + router.get( + "/v0/container/lookup", move |req: &mut Request| { let mut context = Context::default(); @@ -746,81 +607,54 @@ where // Query parameters (note that non-required or collection query parameters will ignore garbage values, rather than causing a 400 response) let query_params = req.get::<UrlEncodedQuery>().unwrap_or_default(); - let param_editgroup = query_params.get("editgroup").and_then(|list| list.first()).and_then(|x| x.parse::<String>().ok()); - - // Body parameters (note that non-required body parameters will ignore garbage - // values, rather than causing a 400 response). Produce warning header and logs for - // any unused fields. - - let param_entity = req - .get::<bodyparser::Raw>() - .map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse body parameter entity - not valid UTF-8: {}", e))))?; - - let mut unused_elements = Vec::new(); - - let param_entity = if let Some(param_entity_raw) = param_entity { - let deserializer = &mut serde_json::Deserializer::from_str(¶m_entity_raw); - - let param_entity: Option<models::FileEntity> = - serde_ignored::deserialize(deserializer, |path| { - warn!("Ignoring unknown field in body: {}", path); - unused_elements.push(path.to_string()); - }).map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse body parameter entity - doesn't match schema: {}", e))))?; - - param_entity - } else { - None - }; - let param_entity = param_entity.ok_or_else(|| Response::with((status::BadRequest, "Missing required body parameter entity".to_string())))?; + let param_issnl = query_params + .get("issnl") + .ok_or_else(|| Response::with((status::BadRequest, "Missing required query parameter issnl".to_string())))? + .first() + .ok_or_else(|| Response::with((status::BadRequest, "Required query parameter issnl was empty".to_string())))? + .parse::<String>() + .map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse query parameter issnl - doesn't match schema: {}", e))))?; - match api.create_file(param_entity, param_editgroup, context).wait() { + match api.lookup_container(param_issnl, context).wait() { Ok(rsp) => match rsp { - CreateFileResponse::CreatedEntity(body) => { + LookupContainerResponse::FoundEntity(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); - let mut response = Response::with((status::Status::from_u16(201), body_string)); - response.headers.set(ContentType(mimetypes::responses::CREATE_FILE_CREATED_ENTITY.clone())); + let mut response = Response::with((status::Status::from_u16(200), body_string)); + response.headers.set(ContentType(mimetypes::responses::LOOKUP_CONTAINER_FOUND_ENTITY.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); - if !unused_elements.is_empty() { - response.headers.set(Warning(format!("Ignoring unknown fields in body: {:?}", unused_elements))); - } + Ok(response) } - CreateFileResponse::BadRequest(body) => { + LookupContainerResponse::BadRequest(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(400), body_string)); - response.headers.set(ContentType(mimetypes::responses::CREATE_FILE_BAD_REQUEST.clone())); + response.headers.set(ContentType(mimetypes::responses::LOOKUP_CONTAINER_BAD_REQUEST.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); - if !unused_elements.is_empty() { - response.headers.set(Warning(format!("Ignoring unknown fields in body: {:?}", unused_elements))); - } + Ok(response) } - CreateFileResponse::NotFound(body) => { + LookupContainerResponse::NotFound(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(404), body_string)); - response.headers.set(ContentType(mimetypes::responses::CREATE_FILE_NOT_FOUND.clone())); + response.headers.set(ContentType(mimetypes::responses::LOOKUP_CONTAINER_NOT_FOUND.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); - if !unused_elements.is_empty() { - response.headers.set(Warning(format!("Ignoring unknown fields in body: {:?}", unused_elements))); - } + Ok(response) } - CreateFileResponse::GenericError(body) => { + LookupContainerResponse::GenericError(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(500), body_string)); - response.headers.set(ContentType(mimetypes::responses::CREATE_FILE_GENERIC_ERROR.clone())); + response.headers.set(ContentType(mimetypes::responses::LOOKUP_CONTAINER_GENERIC_ERROR.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); - if !unused_elements.is_empty() { - response.headers.set(Warning(format!("Ignoring unknown fields in body: {:?}", unused_elements))); - } + Ok(response) } }, @@ -837,12 +671,12 @@ where Ok(response) }) }, - "CreateFile", + "LookupContainer", ); let api_clone = api.clone(); - router.post( - "/v0/file/batch", + router.put( + "/v0/container/:id", move |req: &mut Request| { let mut context = Context::default(); @@ -855,43 +689,56 @@ where context.auth_data = req.extensions.remove::<AuthData>(); context.authorization = req.extensions.remove::<Authorization>(); + // Path parameters + let param_id = { + let param = req + .extensions + .get::<Router>() + .ok_or_else(|| Response::with((status::InternalServerError, "An internal error occurred".to_string())))? + .find("id") + .ok_or_else(|| Response::with((status::BadRequest, "Missing path parameter id".to_string())))?; + percent_decode(param.as_bytes()) + .decode_utf8() + .map_err(|_| Response::with((status::BadRequest, format!("Couldn't percent-decode path parameter as UTF-8: {}", param))))? + .parse() + .map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse path parameter id: {}", e))))? + }; + // Query parameters (note that non-required or collection query parameters will ignore garbage values, rather than causing a 400 response) let query_params = req.get::<UrlEncodedQuery>().unwrap_or_default(); - let param_autoaccept = query_params.get("autoaccept").and_then(|list| list.first()).and_then(|x| x.parse::<bool>().ok()); let param_editgroup = query_params.get("editgroup").and_then(|list| list.first()).and_then(|x| x.parse::<String>().ok()); // Body parameters (note that non-required body parameters will ignore garbage // values, rather than causing a 400 response). Produce warning header and logs for // any unused fields. - let param_entity_list = req + let param_entity = req .get::<bodyparser::Raw>() - .map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse body parameter entity_list - not valid UTF-8: {}", e))))?; + .map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse body parameter entity - not valid UTF-8: {}", e))))?; let mut unused_elements = Vec::new(); - let param_entity_list = if let Some(param_entity_list_raw) = param_entity_list { - let deserializer = &mut serde_json::Deserializer::from_str(¶m_entity_list_raw); + let param_entity = if let Some(param_entity_raw) = param_entity { + let deserializer = &mut serde_json::Deserializer::from_str(¶m_entity_raw); - let param_entity_list: Option<Vec<models::FileEntity>> = - serde_ignored::deserialize(deserializer, |path| { - warn!("Ignoring unknown field in body: {}", path); - unused_elements.push(path.to_string()); - }).map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse body parameter entity_list - doesn't match schema: {}", e))))?; + let param_entity: Option<models::ContainerEntity> = serde_ignored::deserialize(deserializer, |path| { + warn!("Ignoring unknown field in body: {}", path); + unused_elements.push(path.to_string()); + }).map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse body parameter entity - doesn't match schema: {}", e))))?; - param_entity_list + param_entity } else { None }; - let param_entity_list = param_entity_list.ok_or_else(|| Response::with((status::BadRequest, "Missing required body parameter entity_list".to_string())))?; + let param_entity = param_entity.ok_or_else(|| Response::with((status::BadRequest, "Missing required body parameter entity".to_string())))?; - match api.create_file_batch(param_entity_list.as_ref(), param_autoaccept, param_editgroup, context).wait() { + match api.update_container(param_id, param_entity, param_editgroup, context).wait() { Ok(rsp) => match rsp { - CreateFileBatchResponse::CreatedEntities(body) => { + UpdateContainerResponse::UpdatedEntity(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); - let mut response = Response::with((status::Status::from_u16(201), body_string)); - response.headers.set(ContentType(mimetypes::responses::CREATE_FILE_BATCH_CREATED_ENTITIES.clone())); + let mut response = Response::with((status::Status::from_u16(200), body_string)); + response.headers.set(ContentType(mimetypes::responses::UPDATE_CONTAINER_UPDATED_ENTITY.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); if !unused_elements.is_empty() { @@ -899,11 +746,11 @@ where } Ok(response) } - CreateFileBatchResponse::BadRequest(body) => { + UpdateContainerResponse::BadRequest(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(400), body_string)); - response.headers.set(ContentType(mimetypes::responses::CREATE_FILE_BATCH_BAD_REQUEST.clone())); + response.headers.set(ContentType(mimetypes::responses::UPDATE_CONTAINER_BAD_REQUEST.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); if !unused_elements.is_empty() { @@ -911,11 +758,11 @@ where } Ok(response) } - CreateFileBatchResponse::NotFound(body) => { + UpdateContainerResponse::NotFound(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(404), body_string)); - response.headers.set(ContentType(mimetypes::responses::CREATE_FILE_BATCH_NOT_FOUND.clone())); + response.headers.set(ContentType(mimetypes::responses::UPDATE_CONTAINER_NOT_FOUND.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); if !unused_elements.is_empty() { @@ -923,11 +770,11 @@ where } Ok(response) } - CreateFileBatchResponse::GenericError(body) => { + UpdateContainerResponse::GenericError(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(500), body_string)); - response.headers.set(ContentType(mimetypes::responses::CREATE_FILE_BATCH_GENERIC_ERROR.clone())); + response.headers.set(ContentType(mimetypes::responses::UPDATE_CONTAINER_GENERIC_ERROR.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); if !unused_elements.is_empty() { @@ -949,12 +796,12 @@ where Ok(response) }) }, - "CreateFileBatch", + "UpdateContainer", ); let api_clone = api.clone(); router.post( - "/v0/release", + "/v0/creator", move |req: &mut Request| { let mut context = Context::default(); @@ -984,11 +831,10 @@ where let param_entity = if let Some(param_entity_raw) = param_entity { let deserializer = &mut serde_json::Deserializer::from_str(¶m_entity_raw); - let param_entity: Option<models::ReleaseEntity> = - serde_ignored::deserialize(deserializer, |path| { - warn!("Ignoring unknown field in body: {}", path); - unused_elements.push(path.to_string()); - }).map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse body parameter entity - doesn't match schema: {}", e))))?; + let param_entity: Option<models::CreatorEntity> = serde_ignored::deserialize(deserializer, |path| { + warn!("Ignoring unknown field in body: {}", path); + unused_elements.push(path.to_string()); + }).map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse body parameter entity - doesn't match schema: {}", e))))?; param_entity } else { @@ -996,13 +842,13 @@ where }; let param_entity = param_entity.ok_or_else(|| Response::with((status::BadRequest, "Missing required body parameter entity".to_string())))?; - match api.create_release(param_entity, param_editgroup, context).wait() { + match api.create_creator(param_entity, param_editgroup, context).wait() { Ok(rsp) => match rsp { - CreateReleaseResponse::CreatedEntity(body) => { + CreateCreatorResponse::CreatedEntity(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(201), body_string)); - response.headers.set(ContentType(mimetypes::responses::CREATE_RELEASE_CREATED_ENTITY.clone())); + response.headers.set(ContentType(mimetypes::responses::CREATE_CREATOR_CREATED_ENTITY.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); if !unused_elements.is_empty() { @@ -1010,11 +856,11 @@ where } Ok(response) } - CreateReleaseResponse::BadRequest(body) => { + CreateCreatorResponse::BadRequest(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(400), body_string)); - response.headers.set(ContentType(mimetypes::responses::CREATE_RELEASE_BAD_REQUEST.clone())); + response.headers.set(ContentType(mimetypes::responses::CREATE_CREATOR_BAD_REQUEST.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); if !unused_elements.is_empty() { @@ -1022,11 +868,11 @@ where } Ok(response) } - CreateReleaseResponse::NotFound(body) => { + CreateCreatorResponse::NotFound(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(404), body_string)); - response.headers.set(ContentType(mimetypes::responses::CREATE_RELEASE_NOT_FOUND.clone())); + response.headers.set(ContentType(mimetypes::responses::CREATE_CREATOR_NOT_FOUND.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); if !unused_elements.is_empty() { @@ -1034,11 +880,11 @@ where } Ok(response) } - CreateReleaseResponse::GenericError(body) => { + CreateCreatorResponse::GenericError(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(500), body_string)); - response.headers.set(ContentType(mimetypes::responses::CREATE_RELEASE_GENERIC_ERROR.clone())); + response.headers.set(ContentType(mimetypes::responses::CREATE_CREATOR_GENERIC_ERROR.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); if !unused_elements.is_empty() { @@ -1060,12 +906,12 @@ where Ok(response) }) }, - "CreateRelease", + "CreateCreator", ); let api_clone = api.clone(); router.post( - "/v0/release/batch", + "/v0/creator/batch", move |req: &mut Request| { let mut context = Context::default(); @@ -1096,11 +942,10 @@ where let param_entity_list = if let Some(param_entity_list_raw) = param_entity_list { let deserializer = &mut serde_json::Deserializer::from_str(¶m_entity_list_raw); - let param_entity_list: Option<Vec<models::ReleaseEntity>> = - serde_ignored::deserialize(deserializer, |path| { - warn!("Ignoring unknown field in body: {}", path); - unused_elements.push(path.to_string()); - }).map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse body parameter entity_list - doesn't match schema: {}", e))))?; + let param_entity_list: Option<Vec<models::CreatorEntity>> = serde_ignored::deserialize(deserializer, |path| { + warn!("Ignoring unknown field in body: {}", path); + unused_elements.push(path.to_string()); + }).map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse body parameter entity_list - doesn't match schema: {}", e))))?; param_entity_list } else { @@ -1108,13 +953,13 @@ where }; let param_entity_list = param_entity_list.ok_or_else(|| Response::with((status::BadRequest, "Missing required body parameter entity_list".to_string())))?; - match api.create_release_batch(param_entity_list.as_ref(), param_autoaccept, param_editgroup, context).wait() { + match api.create_creator_batch(param_entity_list.as_ref(), param_autoaccept, param_editgroup, context).wait() { Ok(rsp) => match rsp { - CreateReleaseBatchResponse::CreatedEntities(body) => { + CreateCreatorBatchResponse::CreatedEntities(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(201), body_string)); - response.headers.set(ContentType(mimetypes::responses::CREATE_RELEASE_BATCH_CREATED_ENTITIES.clone())); + response.headers.set(ContentType(mimetypes::responses::CREATE_CREATOR_BATCH_CREATED_ENTITIES.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); if !unused_elements.is_empty() { @@ -1122,11 +967,11 @@ where } Ok(response) } - CreateReleaseBatchResponse::BadRequest(body) => { + CreateCreatorBatchResponse::BadRequest(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(400), body_string)); - response.headers.set(ContentType(mimetypes::responses::CREATE_RELEASE_BATCH_BAD_REQUEST.clone())); + response.headers.set(ContentType(mimetypes::responses::CREATE_CREATOR_BATCH_BAD_REQUEST.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); if !unused_elements.is_empty() { @@ -1134,11 +979,11 @@ where } Ok(response) } - CreateReleaseBatchResponse::NotFound(body) => { + CreateCreatorBatchResponse::NotFound(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(404), body_string)); - response.headers.set(ContentType(mimetypes::responses::CREATE_RELEASE_BATCH_NOT_FOUND.clone())); + response.headers.set(ContentType(mimetypes::responses::CREATE_CREATOR_BATCH_NOT_FOUND.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); if !unused_elements.is_empty() { @@ -1146,11 +991,11 @@ where } Ok(response) } - CreateReleaseBatchResponse::GenericError(body) => { + CreateCreatorBatchResponse::GenericError(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(500), body_string)); - response.headers.set(ContentType(mimetypes::responses::CREATE_RELEASE_BATCH_GENERIC_ERROR.clone())); + response.headers.set(ContentType(mimetypes::responses::CREATE_CREATOR_BATCH_GENERIC_ERROR.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); if !unused_elements.is_empty() { @@ -1172,12 +1017,12 @@ where Ok(response) }) }, - "CreateReleaseBatch", + "CreateCreatorBatch", ); let api_clone = api.clone(); - router.post( - "/v0/work", + router.delete( + "/v0/creator/:id", move |req: &mut Request| { let mut context = Context::default(); @@ -1190,83 +1035,65 @@ where context.auth_data = req.extensions.remove::<AuthData>(); context.authorization = req.extensions.remove::<Authorization>(); + // Path parameters + let param_id = { + let param = req + .extensions + .get::<Router>() + .ok_or_else(|| Response::with((status::InternalServerError, "An internal error occurred".to_string())))? + .find("id") + .ok_or_else(|| Response::with((status::BadRequest, "Missing path parameter id".to_string())))?; + percent_decode(param.as_bytes()) + .decode_utf8() + .map_err(|_| Response::with((status::BadRequest, format!("Couldn't percent-decode path parameter as UTF-8: {}", param))))? + .parse() + .map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse path parameter id: {}", e))))? + }; + // Query parameters (note that non-required or collection query parameters will ignore garbage values, rather than causing a 400 response) let query_params = req.get::<UrlEncodedQuery>().unwrap_or_default(); let param_editgroup = query_params.get("editgroup").and_then(|list| list.first()).and_then(|x| x.parse::<String>().ok()); - // Body parameters (note that non-required body parameters will ignore garbage - // values, rather than causing a 400 response). Produce warning header and logs for - // any unused fields. - - let param_entity = req - .get::<bodyparser::Raw>() - .map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse body parameter entity - not valid UTF-8: {}", e))))?; - - let mut unused_elements = Vec::new(); - - let param_entity = if let Some(param_entity_raw) = param_entity { - let deserializer = &mut serde_json::Deserializer::from_str(¶m_entity_raw); - - let param_entity: Option<models::WorkEntity> = - serde_ignored::deserialize(deserializer, |path| { - warn!("Ignoring unknown field in body: {}", path); - unused_elements.push(path.to_string()); - }).map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse body parameter entity - doesn't match schema: {}", e))))?; - - param_entity - } else { - None - }; - let param_entity = param_entity.ok_or_else(|| Response::with((status::BadRequest, "Missing required body parameter entity".to_string())))?; - - match api.create_work(param_entity, param_editgroup, context).wait() { + match api.delete_creator(param_id, param_editgroup, context).wait() { Ok(rsp) => match rsp { - CreateWorkResponse::CreatedEntity(body) => { + DeleteCreatorResponse::DeletedEntity(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); - let mut response = Response::with((status::Status::from_u16(201), body_string)); - response.headers.set(ContentType(mimetypes::responses::CREATE_WORK_CREATED_ENTITY.clone())); + let mut response = Response::with((status::Status::from_u16(200), body_string)); + response.headers.set(ContentType(mimetypes::responses::DELETE_CREATOR_DELETED_ENTITY.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); - if !unused_elements.is_empty() { - response.headers.set(Warning(format!("Ignoring unknown fields in body: {:?}", unused_elements))); - } + Ok(response) } - CreateWorkResponse::BadRequest(body) => { + DeleteCreatorResponse::BadRequest(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(400), body_string)); - response.headers.set(ContentType(mimetypes::responses::CREATE_WORK_BAD_REQUEST.clone())); + response.headers.set(ContentType(mimetypes::responses::DELETE_CREATOR_BAD_REQUEST.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); - if !unused_elements.is_empty() { - response.headers.set(Warning(format!("Ignoring unknown fields in body: {:?}", unused_elements))); - } + Ok(response) } - CreateWorkResponse::NotFound(body) => { + DeleteCreatorResponse::NotFound(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(404), body_string)); - response.headers.set(ContentType(mimetypes::responses::CREATE_WORK_NOT_FOUND.clone())); + response.headers.set(ContentType(mimetypes::responses::DELETE_CREATOR_NOT_FOUND.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); - if !unused_elements.is_empty() { - response.headers.set(Warning(format!("Ignoring unknown fields in body: {:?}", unused_elements))); - } + Ok(response) } - CreateWorkResponse::GenericError(body) => { + DeleteCreatorResponse::GenericError(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(500), body_string)); - response.headers.set(ContentType(mimetypes::responses::CREATE_WORK_GENERIC_ERROR.clone())); + response.headers.set(ContentType(mimetypes::responses::DELETE_CREATOR_GENERIC_ERROR.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); - if !unused_elements.is_empty() { - response.headers.set(Warning(format!("Ignoring unknown fields in body: {:?}", unused_elements))); - } + Ok(response) } }, @@ -1283,12 +1110,12 @@ where Ok(response) }) }, - "CreateWork", + "DeleteCreator", ); let api_clone = api.clone(); - router.post( - "/v0/work/batch", + router.get( + "/v0/creator/:id", move |req: &mut Request| { let mut context = Context::default(); @@ -1301,84 +1128,65 @@ where context.auth_data = req.extensions.remove::<AuthData>(); context.authorization = req.extensions.remove::<Authorization>(); + // Path parameters + let param_id = { + let param = req + .extensions + .get::<Router>() + .ok_or_else(|| Response::with((status::InternalServerError, "An internal error occurred".to_string())))? + .find("id") + .ok_or_else(|| Response::with((status::BadRequest, "Missing path parameter id".to_string())))?; + percent_decode(param.as_bytes()) + .decode_utf8() + .map_err(|_| Response::with((status::BadRequest, format!("Couldn't percent-decode path parameter as UTF-8: {}", param))))? + .parse() + .map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse path parameter id: {}", e))))? + }; + // Query parameters (note that non-required or collection query parameters will ignore garbage values, rather than causing a 400 response) let query_params = req.get::<UrlEncodedQuery>().unwrap_or_default(); - let param_autoaccept = query_params.get("autoaccept").and_then(|list| list.first()).and_then(|x| x.parse::<bool>().ok()); - let param_editgroup = query_params.get("editgroup").and_then(|list| list.first()).and_then(|x| x.parse::<String>().ok()); - - // Body parameters (note that non-required body parameters will ignore garbage - // values, rather than causing a 400 response). Produce warning header and logs for - // any unused fields. - - let param_entity_list = req - .get::<bodyparser::Raw>() - .map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse body parameter entity_list - not valid UTF-8: {}", e))))?; - - let mut unused_elements = Vec::new(); - - let param_entity_list = if let Some(param_entity_list_raw) = param_entity_list { - let deserializer = &mut serde_json::Deserializer::from_str(¶m_entity_list_raw); - - let param_entity_list: Option<Vec<models::WorkEntity>> = - serde_ignored::deserialize(deserializer, |path| { - warn!("Ignoring unknown field in body: {}", path); - unused_elements.push(path.to_string()); - }).map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse body parameter entity_list - doesn't match schema: {}", e))))?; - - param_entity_list - } else { - None - }; - let param_entity_list = param_entity_list.ok_or_else(|| Response::with((status::BadRequest, "Missing required body parameter entity_list".to_string())))?; + let param_expand = query_params.get("expand").and_then(|list| list.first()).and_then(|x| x.parse::<String>().ok()); - match api.create_work_batch(param_entity_list.as_ref(), param_autoaccept, param_editgroup, context).wait() { + match api.get_creator(param_id, param_expand, context).wait() { Ok(rsp) => match rsp { - CreateWorkBatchResponse::CreatedEntities(body) => { + GetCreatorResponse::FoundEntity(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); - let mut response = Response::with((status::Status::from_u16(201), body_string)); - response.headers.set(ContentType(mimetypes::responses::CREATE_WORK_BATCH_CREATED_ENTITIES.clone())); + let mut response = Response::with((status::Status::from_u16(200), body_string)); + response.headers.set(ContentType(mimetypes::responses::GET_CREATOR_FOUND_ENTITY.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); - if !unused_elements.is_empty() { - response.headers.set(Warning(format!("Ignoring unknown fields in body: {:?}", unused_elements))); - } + Ok(response) } - CreateWorkBatchResponse::BadRequest(body) => { + GetCreatorResponse::BadRequest(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(400), body_string)); - response.headers.set(ContentType(mimetypes::responses::CREATE_WORK_BATCH_BAD_REQUEST.clone())); + response.headers.set(ContentType(mimetypes::responses::GET_CREATOR_BAD_REQUEST.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); - if !unused_elements.is_empty() { - response.headers.set(Warning(format!("Ignoring unknown fields in body: {:?}", unused_elements))); - } + Ok(response) } - CreateWorkBatchResponse::NotFound(body) => { + GetCreatorResponse::NotFound(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(404), body_string)); - response.headers.set(ContentType(mimetypes::responses::CREATE_WORK_BATCH_NOT_FOUND.clone())); + response.headers.set(ContentType(mimetypes::responses::GET_CREATOR_NOT_FOUND.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); - if !unused_elements.is_empty() { - response.headers.set(Warning(format!("Ignoring unknown fields in body: {:?}", unused_elements))); - } + Ok(response) } - CreateWorkBatchResponse::GenericError(body) => { + GetCreatorResponse::GenericError(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(500), body_string)); - response.headers.set(ContentType(mimetypes::responses::CREATE_WORK_BATCH_GENERIC_ERROR.clone())); + response.headers.set(ContentType(mimetypes::responses::GET_CREATOR_GENERIC_ERROR.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); - if !unused_elements.is_empty() { - response.headers.set(Warning(format!("Ignoring unknown fields in body: {:?}", unused_elements))); - } + Ok(response) } }, @@ -1395,12 +1203,12 @@ where Ok(response) }) }, - "CreateWorkBatch", + "GetCreator", ); let api_clone = api.clone(); - router.delete( - "/v0/container/:id", + router.get( + "/v0/creator/:id/history", move |req: &mut Request| { let mut context = Context::default(); @@ -1430,45 +1238,45 @@ where // Query parameters (note that non-required or collection query parameters will ignore garbage values, rather than causing a 400 response) let query_params = req.get::<UrlEncodedQuery>().unwrap_or_default(); - let param_editgroup = query_params.get("editgroup").and_then(|list| list.first()).and_then(|x| x.parse::<String>().ok()); + let param_limit = query_params.get("limit").and_then(|list| list.first()).and_then(|x| x.parse::<i64>().ok()); - match api.delete_container(param_id, param_editgroup, context).wait() { + match api.get_creator_history(param_id, param_limit, context).wait() { Ok(rsp) => match rsp { - DeleteContainerResponse::DeletedEntity(body) => { + GetCreatorHistoryResponse::FoundEntityHistory(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(200), body_string)); - response.headers.set(ContentType(mimetypes::responses::DELETE_CONTAINER_DELETED_ENTITY.clone())); + response.headers.set(ContentType(mimetypes::responses::GET_CREATOR_HISTORY_FOUND_ENTITY_HISTORY.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); Ok(response) } - DeleteContainerResponse::BadRequest(body) => { + GetCreatorHistoryResponse::BadRequest(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(400), body_string)); - response.headers.set(ContentType(mimetypes::responses::DELETE_CONTAINER_BAD_REQUEST.clone())); + response.headers.set(ContentType(mimetypes::responses::GET_CREATOR_HISTORY_BAD_REQUEST.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); Ok(response) } - DeleteContainerResponse::NotFound(body) => { + GetCreatorHistoryResponse::NotFound(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(404), body_string)); - response.headers.set(ContentType(mimetypes::responses::DELETE_CONTAINER_NOT_FOUND.clone())); + response.headers.set(ContentType(mimetypes::responses::GET_CREATOR_HISTORY_NOT_FOUND.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); Ok(response) } - DeleteContainerResponse::GenericError(body) => { + GetCreatorHistoryResponse::GenericError(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(500), body_string)); - response.headers.set(ContentType(mimetypes::responses::DELETE_CONTAINER_GENERIC_ERROR.clone())); + response.headers.set(ContentType(mimetypes::responses::GET_CREATOR_HISTORY_GENERIC_ERROR.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); @@ -1488,12 +1296,12 @@ where Ok(response) }) }, - "DeleteContainer", + "GetCreatorHistory", ); let api_clone = api.clone(); - router.delete( - "/v0/creator/:id", + router.get( + "/v0/creator/:id/releases", move |req: &mut Request| { let mut context = Context::default(); @@ -1521,47 +1329,43 @@ where .map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse path parameter id: {}", e))))? }; - // Query parameters (note that non-required or collection query parameters will ignore garbage values, rather than causing a 400 response) - let query_params = req.get::<UrlEncodedQuery>().unwrap_or_default(); - let param_editgroup = query_params.get("editgroup").and_then(|list| list.first()).and_then(|x| x.parse::<String>().ok()); - - match api.delete_creator(param_id, param_editgroup, context).wait() { + match api.get_creator_releases(param_id, context).wait() { Ok(rsp) => match rsp { - DeleteCreatorResponse::DeletedEntity(body) => { + GetCreatorReleasesResponse::Found(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(200), body_string)); - response.headers.set(ContentType(mimetypes::responses::DELETE_CREATOR_DELETED_ENTITY.clone())); + response.headers.set(ContentType(mimetypes::responses::GET_CREATOR_RELEASES_FOUND.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); Ok(response) } - DeleteCreatorResponse::BadRequest(body) => { + GetCreatorReleasesResponse::BadRequest(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(400), body_string)); - response.headers.set(ContentType(mimetypes::responses::DELETE_CREATOR_BAD_REQUEST.clone())); + response.headers.set(ContentType(mimetypes::responses::GET_CREATOR_RELEASES_BAD_REQUEST.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); Ok(response) } - DeleteCreatorResponse::NotFound(body) => { + GetCreatorReleasesResponse::NotFound(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(404), body_string)); - response.headers.set(ContentType(mimetypes::responses::DELETE_CREATOR_NOT_FOUND.clone())); + response.headers.set(ContentType(mimetypes::responses::GET_CREATOR_RELEASES_NOT_FOUND.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); Ok(response) } - DeleteCreatorResponse::GenericError(body) => { + GetCreatorReleasesResponse::GenericError(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(500), body_string)); - response.headers.set(ContentType(mimetypes::responses::DELETE_CREATOR_GENERIC_ERROR.clone())); + response.headers.set(ContentType(mimetypes::responses::GET_CREATOR_RELEASES_GENERIC_ERROR.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); @@ -1581,12 +1385,12 @@ where Ok(response) }) }, - "DeleteCreator", + "GetCreatorReleases", ); let api_clone = api.clone(); - router.delete( - "/v0/file/:id", + router.get( + "/v0/creator/lookup", move |req: &mut Request| { let mut context = Context::default(); @@ -1599,62 +1403,53 @@ where context.auth_data = req.extensions.remove::<AuthData>(); context.authorization = req.extensions.remove::<Authorization>(); - // Path parameters - let param_id = { - let param = req - .extensions - .get::<Router>() - .ok_or_else(|| Response::with((status::InternalServerError, "An internal error occurred".to_string())))? - .find("id") - .ok_or_else(|| Response::with((status::BadRequest, "Missing path parameter id".to_string())))?; - percent_decode(param.as_bytes()) - .decode_utf8() - .map_err(|_| Response::with((status::BadRequest, format!("Couldn't percent-decode path parameter as UTF-8: {}", param))))? - .parse() - .map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse path parameter id: {}", e))))? - }; - // Query parameters (note that non-required or collection query parameters will ignore garbage values, rather than causing a 400 response) let query_params = req.get::<UrlEncodedQuery>().unwrap_or_default(); - let param_editgroup = query_params.get("editgroup").and_then(|list| list.first()).and_then(|x| x.parse::<String>().ok()); + let param_orcid = query_params + .get("orcid") + .ok_or_else(|| Response::with((status::BadRequest, "Missing required query parameter orcid".to_string())))? + .first() + .ok_or_else(|| Response::with((status::BadRequest, "Required query parameter orcid was empty".to_string())))? + .parse::<String>() + .map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse query parameter orcid - doesn't match schema: {}", e))))?; - match api.delete_file(param_id, param_editgroup, context).wait() { + match api.lookup_creator(param_orcid, context).wait() { Ok(rsp) => match rsp { - DeleteFileResponse::DeletedEntity(body) => { + LookupCreatorResponse::FoundEntity(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(200), body_string)); - response.headers.set(ContentType(mimetypes::responses::DELETE_FILE_DELETED_ENTITY.clone())); + response.headers.set(ContentType(mimetypes::responses::LOOKUP_CREATOR_FOUND_ENTITY.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); Ok(response) } - DeleteFileResponse::BadRequest(body) => { + LookupCreatorResponse::BadRequest(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(400), body_string)); - response.headers.set(ContentType(mimetypes::responses::DELETE_FILE_BAD_REQUEST.clone())); + response.headers.set(ContentType(mimetypes::responses::LOOKUP_CREATOR_BAD_REQUEST.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); Ok(response) } - DeleteFileResponse::NotFound(body) => { + LookupCreatorResponse::NotFound(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(404), body_string)); - response.headers.set(ContentType(mimetypes::responses::DELETE_FILE_NOT_FOUND.clone())); + response.headers.set(ContentType(mimetypes::responses::LOOKUP_CREATOR_NOT_FOUND.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); Ok(response) } - DeleteFileResponse::GenericError(body) => { + LookupCreatorResponse::GenericError(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(500), body_string)); - response.headers.set(ContentType(mimetypes::responses::DELETE_FILE_GENERIC_ERROR.clone())); + response.headers.set(ContentType(mimetypes::responses::LOOKUP_CREATOR_GENERIC_ERROR.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); @@ -1674,12 +1469,12 @@ where Ok(response) }) }, - "DeleteFile", + "LookupCreator", ); let api_clone = api.clone(); - router.delete( - "/v0/release/:id", + router.put( + "/v0/creator/:id", move |req: &mut Request| { let mut context = Context::default(); @@ -1711,46 +1506,78 @@ where let query_params = req.get::<UrlEncodedQuery>().unwrap_or_default(); let param_editgroup = query_params.get("editgroup").and_then(|list| list.first()).and_then(|x| x.parse::<String>().ok()); - match api.delete_release(param_id, param_editgroup, context).wait() { + // Body parameters (note that non-required body parameters will ignore garbage + // values, rather than causing a 400 response). Produce warning header and logs for + // any unused fields. + + let param_entity = req + .get::<bodyparser::Raw>() + .map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse body parameter entity - not valid UTF-8: {}", e))))?; + + let mut unused_elements = Vec::new(); + + let param_entity = if let Some(param_entity_raw) = param_entity { + let deserializer = &mut serde_json::Deserializer::from_str(¶m_entity_raw); + + let param_entity: Option<models::CreatorEntity> = serde_ignored::deserialize(deserializer, |path| { + warn!("Ignoring unknown field in body: {}", path); + unused_elements.push(path.to_string()); + }).map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse body parameter entity - doesn't match schema: {}", e))))?; + + param_entity + } else { + None + }; + let param_entity = param_entity.ok_or_else(|| Response::with((status::BadRequest, "Missing required body parameter entity".to_string())))?; + + match api.update_creator(param_id, param_entity, param_editgroup, context).wait() { Ok(rsp) => match rsp { - DeleteReleaseResponse::DeletedEntity(body) => { + UpdateCreatorResponse::UpdatedEntity(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(200), body_string)); - response.headers.set(ContentType(mimetypes::responses::DELETE_RELEASE_DELETED_ENTITY.clone())); + response.headers.set(ContentType(mimetypes::responses::UPDATE_CREATOR_UPDATED_ENTITY.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); - + if !unused_elements.is_empty() { + response.headers.set(Warning(format!("Ignoring unknown fields in body: {:?}", unused_elements))); + } Ok(response) } - DeleteReleaseResponse::BadRequest(body) => { + UpdateCreatorResponse::BadRequest(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(400), body_string)); - response.headers.set(ContentType(mimetypes::responses::DELETE_RELEASE_BAD_REQUEST.clone())); + response.headers.set(ContentType(mimetypes::responses::UPDATE_CREATOR_BAD_REQUEST.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); - + if !unused_elements.is_empty() { + response.headers.set(Warning(format!("Ignoring unknown fields in body: {:?}", unused_elements))); + } Ok(response) } - DeleteReleaseResponse::NotFound(body) => { + UpdateCreatorResponse::NotFound(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(404), body_string)); - response.headers.set(ContentType(mimetypes::responses::DELETE_RELEASE_NOT_FOUND.clone())); + response.headers.set(ContentType(mimetypes::responses::UPDATE_CREATOR_NOT_FOUND.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); - + if !unused_elements.is_empty() { + response.headers.set(Warning(format!("Ignoring unknown fields in body: {:?}", unused_elements))); + } Ok(response) } - DeleteReleaseResponse::GenericError(body) => { + UpdateCreatorResponse::GenericError(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(500), body_string)); - response.headers.set(ContentType(mimetypes::responses::DELETE_RELEASE_GENERIC_ERROR.clone())); + response.headers.set(ContentType(mimetypes::responses::UPDATE_CREATOR_GENERIC_ERROR.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); - + if !unused_elements.is_empty() { + response.headers.set(Warning(format!("Ignoring unknown fields in body: {:?}", unused_elements))); + } Ok(response) } }, @@ -1767,12 +1594,12 @@ where Ok(response) }) }, - "DeleteRelease", + "UpdateCreator", ); let api_clone = api.clone(); - router.delete( - "/v0/work/:id", + router.get( + "/v0/editor/:id", move |req: &mut Request| { let mut context = Context::default(); @@ -1800,47 +1627,43 @@ where .map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse path parameter id: {}", e))))? }; - // Query parameters (note that non-required or collection query parameters will ignore garbage values, rather than causing a 400 response) - let query_params = req.get::<UrlEncodedQuery>().unwrap_or_default(); - let param_editgroup = query_params.get("editgroup").and_then(|list| list.first()).and_then(|x| x.parse::<String>().ok()); - - match api.delete_work(param_id, param_editgroup, context).wait() { + match api.get_editor(param_id, context).wait() { Ok(rsp) => match rsp { - DeleteWorkResponse::DeletedEntity(body) => { + GetEditorResponse::Found(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(200), body_string)); - response.headers.set(ContentType(mimetypes::responses::DELETE_WORK_DELETED_ENTITY.clone())); + response.headers.set(ContentType(mimetypes::responses::GET_EDITOR_FOUND.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); Ok(response) } - DeleteWorkResponse::BadRequest(body) => { + GetEditorResponse::BadRequest(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(400), body_string)); - response.headers.set(ContentType(mimetypes::responses::DELETE_WORK_BAD_REQUEST.clone())); + response.headers.set(ContentType(mimetypes::responses::GET_EDITOR_BAD_REQUEST.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); Ok(response) } - DeleteWorkResponse::NotFound(body) => { + GetEditorResponse::NotFound(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(404), body_string)); - response.headers.set(ContentType(mimetypes::responses::DELETE_WORK_NOT_FOUND.clone())); + response.headers.set(ContentType(mimetypes::responses::GET_EDITOR_NOT_FOUND.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); Ok(response) } - DeleteWorkResponse::GenericError(body) => { + GetEditorResponse::GenericError(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(500), body_string)); - response.headers.set(ContentType(mimetypes::responses::DELETE_WORK_GENERIC_ERROR.clone())); + response.headers.set(ContentType(mimetypes::responses::GET_EDITOR_GENERIC_ERROR.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); @@ -1860,12 +1683,12 @@ where Ok(response) }) }, - "DeleteWork", + "GetEditor", ); let api_clone = api.clone(); router.get( - "/v0/changelog", + "/v0/editor/:id/changelog", move |req: &mut Request| { let mut context = Context::default(); @@ -1878,27 +1701,58 @@ where context.auth_data = req.extensions.remove::<AuthData>(); context.authorization = req.extensions.remove::<Authorization>(); - // Query parameters (note that non-required or collection query parameters will ignore garbage values, rather than causing a 400 response) - let query_params = req.get::<UrlEncodedQuery>().unwrap_or_default(); - let param_limit = query_params.get("limit").and_then(|list| list.first()).and_then(|x| x.parse::<i64>().ok()); + // Path parameters + let param_id = { + let param = req + .extensions + .get::<Router>() + .ok_or_else(|| Response::with((status::InternalServerError, "An internal error occurred".to_string())))? + .find("id") + .ok_or_else(|| Response::with((status::BadRequest, "Missing path parameter id".to_string())))?; + percent_decode(param.as_bytes()) + .decode_utf8() + .map_err(|_| Response::with((status::BadRequest, format!("Couldn't percent-decode path parameter as UTF-8: {}", param))))? + .parse() + .map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse path parameter id: {}", e))))? + }; - match api.get_changelog(param_limit, context).wait() { + match api.get_editor_changelog(param_id, context).wait() { Ok(rsp) => match rsp { - GetChangelogResponse::Success(body) => { + GetEditorChangelogResponse::Found(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(200), body_string)); - response.headers.set(ContentType(mimetypes::responses::GET_CHANGELOG_SUCCESS.clone())); + response.headers.set(ContentType(mimetypes::responses::GET_EDITOR_CHANGELOG_FOUND.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); Ok(response) } - GetChangelogResponse::GenericError(body) => { + GetEditorChangelogResponse::BadRequest(body) => { + let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); + + let mut response = Response::with((status::Status::from_u16(400), body_string)); + response.headers.set(ContentType(mimetypes::responses::GET_EDITOR_CHANGELOG_BAD_REQUEST.clone())); + + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + + Ok(response) + } + GetEditorChangelogResponse::NotFound(body) => { + let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); + + let mut response = Response::with((status::Status::from_u16(404), body_string)); + response.headers.set(ContentType(mimetypes::responses::GET_EDITOR_CHANGELOG_NOT_FOUND.clone())); + + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + + Ok(response) + } + GetEditorChangelogResponse::GenericError(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(500), body_string)); - response.headers.set(ContentType(mimetypes::responses::GET_CHANGELOG_GENERIC_ERROR.clone())); + response.headers.set(ContentType(mimetypes::responses::GET_EDITOR_CHANGELOG_GENERIC_ERROR.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); @@ -1918,12 +1772,12 @@ where Ok(response) }) }, - "GetChangelog", + "GetEditorChangelog", ); let api_clone = api.clone(); router.get( - "/v0/changelog/:id", + "/v0/stats", move |req: &mut Request| { let mut context = Context::default(); @@ -1936,48 +1790,27 @@ where context.auth_data = req.extensions.remove::<AuthData>(); context.authorization = req.extensions.remove::<Authorization>(); - // Path parameters - let param_id = { - let param = req - .extensions - .get::<Router>() - .ok_or_else(|| Response::with((status::InternalServerError, "An internal error occurred".to_string())))? - .find("id") - .ok_or_else(|| Response::with((status::BadRequest, "Missing path parameter id".to_string())))?; - percent_decode(param.as_bytes()) - .decode_utf8() - .map_err(|_| Response::with((status::BadRequest, format!("Couldn't percent-decode path parameter as UTF-8: {}", param))))? - .parse() - .map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse path parameter id: {}", e))))? - }; + // Query parameters (note that non-required or collection query parameters will ignore garbage values, rather than causing a 400 response) + let query_params = req.get::<UrlEncodedQuery>().unwrap_or_default(); + let param_more = query_params.get("more").and_then(|list| list.first()).and_then(|x| x.parse::<String>().ok()); - match api.get_changelog_entry(param_id, context).wait() { + match api.get_stats(param_more, context).wait() { Ok(rsp) => match rsp { - GetChangelogEntryResponse::FoundChangelogEntry(body) => { + GetStatsResponse::Success(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(200), body_string)); - response.headers.set(ContentType(mimetypes::responses::GET_CHANGELOG_ENTRY_FOUND_CHANGELOG_ENTRY.clone())); - - context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); - - Ok(response) - } - GetChangelogEntryResponse::NotFound(body) => { - let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); - - let mut response = Response::with((status::Status::from_u16(404), body_string)); - response.headers.set(ContentType(mimetypes::responses::GET_CHANGELOG_ENTRY_NOT_FOUND.clone())); + response.headers.set(ContentType(mimetypes::responses::GET_STATS_SUCCESS.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); Ok(response) } - GetChangelogEntryResponse::GenericError(body) => { + GetStatsResponse::GenericError(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(500), body_string)); - response.headers.set(ContentType(mimetypes::responses::GET_CHANGELOG_ENTRY_GENERIC_ERROR.clone())); + response.headers.set(ContentType(mimetypes::responses::GET_STATS_GENERIC_ERROR.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); @@ -1997,12 +1830,12 @@ where Ok(response) }) }, - "GetChangelogEntry", + "GetStats", ); let api_clone = api.clone(); - router.get( - "/v0/container/:id", + router.post( + "/v0/editgroup/:id/accept", move |req: &mut Request| { let mut context = Context::default(); @@ -2030,47 +1863,53 @@ where .map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse path parameter id: {}", e))))? }; - // Query parameters (note that non-required or collection query parameters will ignore garbage values, rather than causing a 400 response) - let query_params = req.get::<UrlEncodedQuery>().unwrap_or_default(); - let param_expand = query_params.get("expand").and_then(|list| list.first()).and_then(|x| x.parse::<String>().ok()); - - match api.get_container(param_id, param_expand, context).wait() { + match api.accept_editgroup(param_id, context).wait() { Ok(rsp) => match rsp { - GetContainerResponse::FoundEntity(body) => { + AcceptEditgroupResponse::MergedSuccessfully(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(200), body_string)); - response.headers.set(ContentType(mimetypes::responses::GET_CONTAINER_FOUND_ENTITY.clone())); + response.headers.set(ContentType(mimetypes::responses::ACCEPT_EDITGROUP_MERGED_SUCCESSFULLY.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); Ok(response) } - GetContainerResponse::BadRequest(body) => { + AcceptEditgroupResponse::BadRequest(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(400), body_string)); - response.headers.set(ContentType(mimetypes::responses::GET_CONTAINER_BAD_REQUEST.clone())); + response.headers.set(ContentType(mimetypes::responses::ACCEPT_EDITGROUP_BAD_REQUEST.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); Ok(response) } - GetContainerResponse::NotFound(body) => { + AcceptEditgroupResponse::NotFound(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(404), body_string)); - response.headers.set(ContentType(mimetypes::responses::GET_CONTAINER_NOT_FOUND.clone())); + response.headers.set(ContentType(mimetypes::responses::ACCEPT_EDITGROUP_NOT_FOUND.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); Ok(response) } - GetContainerResponse::GenericError(body) => { + AcceptEditgroupResponse::EditConflict(body) => { + let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); + + let mut response = Response::with((status::Status::from_u16(409), body_string)); + response.headers.set(ContentType(mimetypes::responses::ACCEPT_EDITGROUP_EDIT_CONFLICT.clone())); + + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + + Ok(response) + } + AcceptEditgroupResponse::GenericError(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(500), body_string)); - response.headers.set(ContentType(mimetypes::responses::GET_CONTAINER_GENERIC_ERROR.clone())); + response.headers.set(ContentType(mimetypes::responses::ACCEPT_EDITGROUP_GENERIC_ERROR.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); @@ -2090,12 +1929,12 @@ where Ok(response) }) }, - "GetContainer", + "AcceptEditgroup", ); let api_clone = api.clone(); - router.get( - "/v0/container/:id/history", + router.post( + "/v0/editgroup", move |req: &mut Request| { let mut context = Context::default(); @@ -2108,65 +1947,66 @@ where context.auth_data = req.extensions.remove::<AuthData>(); context.authorization = req.extensions.remove::<Authorization>(); - // Path parameters - let param_id = { - let param = req - .extensions - .get::<Router>() - .ok_or_else(|| Response::with((status::InternalServerError, "An internal error occurred".to_string())))? - .find("id") - .ok_or_else(|| Response::with((status::BadRequest, "Missing path parameter id".to_string())))?; - percent_decode(param.as_bytes()) - .decode_utf8() - .map_err(|_| Response::with((status::BadRequest, format!("Couldn't percent-decode path parameter as UTF-8: {}", param))))? - .parse() - .map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse path parameter id: {}", e))))? - }; + // Body parameters (note that non-required body parameters will ignore garbage + // values, rather than causing a 400 response). Produce warning header and logs for + // any unused fields. - // Query parameters (note that non-required or collection query parameters will ignore garbage values, rather than causing a 400 response) - let query_params = req.get::<UrlEncodedQuery>().unwrap_or_default(); - let param_limit = query_params.get("limit").and_then(|list| list.first()).and_then(|x| x.parse::<i64>().ok()); + let param_editgroup = req + .get::<bodyparser::Raw>() + .map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse body parameter editgroup - not valid UTF-8: {}", e))))?; - match api.get_container_history(param_id, param_limit, context).wait() { - Ok(rsp) => match rsp { - GetContainerHistoryResponse::FoundEntityHistory(body) => { - let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); + let mut unused_elements = Vec::new(); - let mut response = Response::with((status::Status::from_u16(200), body_string)); - response.headers.set(ContentType(mimetypes::responses::GET_CONTAINER_HISTORY_FOUND_ENTITY_HISTORY.clone())); + let param_editgroup = if let Some(param_editgroup_raw) = param_editgroup { + let deserializer = &mut serde_json::Deserializer::from_str(¶m_editgroup_raw); - context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + let param_editgroup: Option<models::Editgroup> = serde_ignored::deserialize(deserializer, |path| { + warn!("Ignoring unknown field in body: {}", path); + unused_elements.push(path.to_string()); + }).map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse body parameter editgroup - doesn't match schema: {}", e))))?; - Ok(response) - } - GetContainerHistoryResponse::BadRequest(body) => { + param_editgroup + } else { + None + }; + let param_editgroup = param_editgroup.ok_or_else(|| Response::with((status::BadRequest, "Missing required body parameter editgroup".to_string())))?; + + match api.create_editgroup(param_editgroup, context).wait() { + Ok(rsp) => match rsp { + CreateEditgroupResponse::SuccessfullyCreated(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); - let mut response = Response::with((status::Status::from_u16(400), body_string)); - response.headers.set(ContentType(mimetypes::responses::GET_CONTAINER_HISTORY_BAD_REQUEST.clone())); + let mut response = Response::with((status::Status::from_u16(201), body_string)); + response.headers.set(ContentType(mimetypes::responses::CREATE_EDITGROUP_SUCCESSFULLY_CREATED.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); - + if !unused_elements.is_empty() { + response.headers.set(Warning(format!("Ignoring unknown fields in body: {:?}", unused_elements))); + } Ok(response) } - GetContainerHistoryResponse::NotFound(body) => { + CreateEditgroupResponse::BadRequest(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); - let mut response = Response::with((status::Status::from_u16(404), body_string)); - response.headers.set(ContentType(mimetypes::responses::GET_CONTAINER_HISTORY_NOT_FOUND.clone())); + let mut response = Response::with((status::Status::from_u16(400), body_string)); + response.headers.set(ContentType(mimetypes::responses::CREATE_EDITGROUP_BAD_REQUEST.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); - + if !unused_elements.is_empty() { + response.headers.set(Warning(format!("Ignoring unknown fields in body: {:?}", unused_elements))); + } Ok(response) } - GetContainerHistoryResponse::GenericError(body) => { + CreateEditgroupResponse::GenericError(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(500), body_string)); - response.headers.set(ContentType(mimetypes::responses::GET_CONTAINER_HISTORY_GENERIC_ERROR.clone())); + response.headers.set(ContentType(mimetypes::responses::CREATE_EDITGROUP_GENERIC_ERROR.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); - + if !unused_elements.is_empty() { + response.headers.set(Warning(format!("Ignoring unknown fields in body: {:?}", unused_elements))); + } Ok(response) } }, @@ -2183,12 +2023,12 @@ where Ok(response) }) }, - "GetContainerHistory", + "CreateEditgroup", ); let api_clone = api.clone(); router.get( - "/v0/creator/:id", + "/v0/changelog", move |req: &mut Request| { let mut context = Context::default(); @@ -2201,62 +2041,27 @@ where context.auth_data = req.extensions.remove::<AuthData>(); context.authorization = req.extensions.remove::<Authorization>(); - // Path parameters - let param_id = { - let param = req - .extensions - .get::<Router>() - .ok_or_else(|| Response::with((status::InternalServerError, "An internal error occurred".to_string())))? - .find("id") - .ok_or_else(|| Response::with((status::BadRequest, "Missing path parameter id".to_string())))?; - percent_decode(param.as_bytes()) - .decode_utf8() - .map_err(|_| Response::with((status::BadRequest, format!("Couldn't percent-decode path parameter as UTF-8: {}", param))))? - .parse() - .map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse path parameter id: {}", e))))? - }; - // Query parameters (note that non-required or collection query parameters will ignore garbage values, rather than causing a 400 response) let query_params = req.get::<UrlEncodedQuery>().unwrap_or_default(); - let param_expand = query_params.get("expand").and_then(|list| list.first()).and_then(|x| x.parse::<String>().ok()); + let param_limit = query_params.get("limit").and_then(|list| list.first()).and_then(|x| x.parse::<i64>().ok()); - match api.get_creator(param_id, param_expand, context).wait() { + match api.get_changelog(param_limit, context).wait() { Ok(rsp) => match rsp { - GetCreatorResponse::FoundEntity(body) => { + GetChangelogResponse::Success(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(200), body_string)); - response.headers.set(ContentType(mimetypes::responses::GET_CREATOR_FOUND_ENTITY.clone())); - - context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); - - Ok(response) - } - GetCreatorResponse::BadRequest(body) => { - let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); - - let mut response = Response::with((status::Status::from_u16(400), body_string)); - response.headers.set(ContentType(mimetypes::responses::GET_CREATOR_BAD_REQUEST.clone())); - - context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); - - Ok(response) - } - GetCreatorResponse::NotFound(body) => { - let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); - - let mut response = Response::with((status::Status::from_u16(404), body_string)); - response.headers.set(ContentType(mimetypes::responses::GET_CREATOR_NOT_FOUND.clone())); + response.headers.set(ContentType(mimetypes::responses::GET_CHANGELOG_SUCCESS.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); Ok(response) } - GetCreatorResponse::GenericError(body) => { + GetChangelogResponse::GenericError(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(500), body_string)); - response.headers.set(ContentType(mimetypes::responses::GET_CREATOR_GENERIC_ERROR.clone())); + response.headers.set(ContentType(mimetypes::responses::GET_CHANGELOG_GENERIC_ERROR.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); @@ -2276,12 +2081,12 @@ where Ok(response) }) }, - "GetCreator", + "GetChangelog", ); let api_clone = api.clone(); router.get( - "/v0/creator/:id/history", + "/v0/changelog/:id", move |req: &mut Request| { let mut context = Context::default(); @@ -2309,47 +2114,33 @@ where .map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse path parameter id: {}", e))))? }; - // Query parameters (note that non-required or collection query parameters will ignore garbage values, rather than causing a 400 response) - let query_params = req.get::<UrlEncodedQuery>().unwrap_or_default(); - let param_limit = query_params.get("limit").and_then(|list| list.first()).and_then(|x| x.parse::<i64>().ok()); - - match api.get_creator_history(param_id, param_limit, context).wait() { + match api.get_changelog_entry(param_id, context).wait() { Ok(rsp) => match rsp { - GetCreatorHistoryResponse::FoundEntityHistory(body) => { + GetChangelogEntryResponse::FoundChangelogEntry(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(200), body_string)); - response.headers.set(ContentType(mimetypes::responses::GET_CREATOR_HISTORY_FOUND_ENTITY_HISTORY.clone())); - - context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); - - Ok(response) - } - GetCreatorHistoryResponse::BadRequest(body) => { - let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); - - let mut response = Response::with((status::Status::from_u16(400), body_string)); - response.headers.set(ContentType(mimetypes::responses::GET_CREATOR_HISTORY_BAD_REQUEST.clone())); + response.headers.set(ContentType(mimetypes::responses::GET_CHANGELOG_ENTRY_FOUND_CHANGELOG_ENTRY.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); Ok(response) } - GetCreatorHistoryResponse::NotFound(body) => { + GetChangelogEntryResponse::NotFound(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(404), body_string)); - response.headers.set(ContentType(mimetypes::responses::GET_CREATOR_HISTORY_NOT_FOUND.clone())); + response.headers.set(ContentType(mimetypes::responses::GET_CHANGELOG_ENTRY_NOT_FOUND.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); Ok(response) } - GetCreatorHistoryResponse::GenericError(body) => { + GetChangelogEntryResponse::GenericError(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(500), body_string)); - response.headers.set(ContentType(mimetypes::responses::GET_CREATOR_HISTORY_GENERIC_ERROR.clone())); + response.headers.set(ContentType(mimetypes::responses::GET_CHANGELOG_ENTRY_GENERIC_ERROR.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); @@ -2369,12 +2160,12 @@ where Ok(response) }) }, - "GetCreatorHistory", + "GetChangelogEntry", ); let api_clone = api.clone(); router.get( - "/v0/creator/:id/releases", + "/v0/editgroup/:id", move |req: &mut Request| { let mut context = Context::default(); @@ -2402,43 +2193,43 @@ where .map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse path parameter id: {}", e))))? }; - match api.get_creator_releases(param_id, context).wait() { + match api.get_editgroup(param_id, context).wait() { Ok(rsp) => match rsp { - GetCreatorReleasesResponse::Found(body) => { + GetEditgroupResponse::Found(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(200), body_string)); - response.headers.set(ContentType(mimetypes::responses::GET_CREATOR_RELEASES_FOUND.clone())); + response.headers.set(ContentType(mimetypes::responses::GET_EDITGROUP_FOUND.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); Ok(response) } - GetCreatorReleasesResponse::BadRequest(body) => { + GetEditgroupResponse::BadRequest(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(400), body_string)); - response.headers.set(ContentType(mimetypes::responses::GET_CREATOR_RELEASES_BAD_REQUEST.clone())); + response.headers.set(ContentType(mimetypes::responses::GET_EDITGROUP_BAD_REQUEST.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); Ok(response) } - GetCreatorReleasesResponse::NotFound(body) => { + GetEditgroupResponse::NotFound(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(404), body_string)); - response.headers.set(ContentType(mimetypes::responses::GET_CREATOR_RELEASES_NOT_FOUND.clone())); + response.headers.set(ContentType(mimetypes::responses::GET_EDITGROUP_NOT_FOUND.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); Ok(response) } - GetCreatorReleasesResponse::GenericError(body) => { + GetEditgroupResponse::GenericError(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(500), body_string)); - response.headers.set(ContentType(mimetypes::responses::GET_CREATOR_RELEASES_GENERIC_ERROR.clone())); + response.headers.set(ContentType(mimetypes::responses::GET_EDITGROUP_GENERIC_ERROR.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); @@ -2458,12 +2249,12 @@ where Ok(response) }) }, - "GetCreatorReleases", + "GetEditgroup", ); let api_clone = api.clone(); - router.get( - "/v0/editgroup/:id", + router.post( + "/v0/file", move |req: &mut Request| { let mut context = Context::default(); @@ -2476,61 +2267,82 @@ where context.auth_data = req.extensions.remove::<AuthData>(); context.authorization = req.extensions.remove::<Authorization>(); - // Path parameters - let param_id = { - let param = req - .extensions - .get::<Router>() - .ok_or_else(|| Response::with((status::InternalServerError, "An internal error occurred".to_string())))? - .find("id") - .ok_or_else(|| Response::with((status::BadRequest, "Missing path parameter id".to_string())))?; - percent_decode(param.as_bytes()) - .decode_utf8() - .map_err(|_| Response::with((status::BadRequest, format!("Couldn't percent-decode path parameter as UTF-8: {}", param))))? - .parse() - .map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse path parameter id: {}", e))))? + // Query parameters (note that non-required or collection query parameters will ignore garbage values, rather than causing a 400 response) + let query_params = req.get::<UrlEncodedQuery>().unwrap_or_default(); + let param_editgroup = query_params.get("editgroup").and_then(|list| list.first()).and_then(|x| x.parse::<String>().ok()); + + // Body parameters (note that non-required body parameters will ignore garbage + // values, rather than causing a 400 response). Produce warning header and logs for + // any unused fields. + + let param_entity = req + .get::<bodyparser::Raw>() + .map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse body parameter entity - not valid UTF-8: {}", e))))?; + + let mut unused_elements = Vec::new(); + + let param_entity = if let Some(param_entity_raw) = param_entity { + let deserializer = &mut serde_json::Deserializer::from_str(¶m_entity_raw); + + let param_entity: Option<models::FileEntity> = serde_ignored::deserialize(deserializer, |path| { + warn!("Ignoring unknown field in body: {}", path); + unused_elements.push(path.to_string()); + }).map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse body parameter entity - doesn't match schema: {}", e))))?; + + param_entity + } else { + None }; + let param_entity = param_entity.ok_or_else(|| Response::with((status::BadRequest, "Missing required body parameter entity".to_string())))?; - match api.get_editgroup(param_id, context).wait() { + match api.create_file(param_entity, param_editgroup, context).wait() { Ok(rsp) => match rsp { - GetEditgroupResponse::Found(body) => { + CreateFileResponse::CreatedEntity(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); - let mut response = Response::with((status::Status::from_u16(200), body_string)); - response.headers.set(ContentType(mimetypes::responses::GET_EDITGROUP_FOUND.clone())); + let mut response = Response::with((status::Status::from_u16(201), body_string)); + response.headers.set(ContentType(mimetypes::responses::CREATE_FILE_CREATED_ENTITY.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); - + if !unused_elements.is_empty() { + response.headers.set(Warning(format!("Ignoring unknown fields in body: {:?}", unused_elements))); + } Ok(response) } - GetEditgroupResponse::BadRequest(body) => { + CreateFileResponse::BadRequest(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(400), body_string)); - response.headers.set(ContentType(mimetypes::responses::GET_EDITGROUP_BAD_REQUEST.clone())); + response.headers.set(ContentType(mimetypes::responses::CREATE_FILE_BAD_REQUEST.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); - + if !unused_elements.is_empty() { + response.headers.set(Warning(format!("Ignoring unknown fields in body: {:?}", unused_elements))); + } Ok(response) } - GetEditgroupResponse::NotFound(body) => { + CreateFileResponse::NotFound(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(404), body_string)); - response.headers.set(ContentType(mimetypes::responses::GET_EDITGROUP_NOT_FOUND.clone())); + response.headers.set(ContentType(mimetypes::responses::CREATE_FILE_NOT_FOUND.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); - + if !unused_elements.is_empty() { + response.headers.set(Warning(format!("Ignoring unknown fields in body: {:?}", unused_elements))); + } Ok(response) } - GetEditgroupResponse::GenericError(body) => { + CreateFileResponse::GenericError(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(500), body_string)); - response.headers.set(ContentType(mimetypes::responses::GET_EDITGROUP_GENERIC_ERROR.clone())); + response.headers.set(ContentType(mimetypes::responses::CREATE_FILE_GENERIC_ERROR.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); - + if !unused_elements.is_empty() { + response.headers.set(Warning(format!("Ignoring unknown fields in body: {:?}", unused_elements))); + } Ok(response) } }, @@ -2547,12 +2359,12 @@ where Ok(response) }) }, - "GetEditgroup", + "CreateFile", ); let api_clone = api.clone(); - router.get( - "/v0/editor/:id", + router.post( + "/v0/file/batch", move |req: &mut Request| { let mut context = Context::default(); @@ -2565,61 +2377,83 @@ where context.auth_data = req.extensions.remove::<AuthData>(); context.authorization = req.extensions.remove::<Authorization>(); - // Path parameters - let param_id = { - let param = req - .extensions - .get::<Router>() - .ok_or_else(|| Response::with((status::InternalServerError, "An internal error occurred".to_string())))? - .find("id") - .ok_or_else(|| Response::with((status::BadRequest, "Missing path parameter id".to_string())))?; - percent_decode(param.as_bytes()) - .decode_utf8() - .map_err(|_| Response::with((status::BadRequest, format!("Couldn't percent-decode path parameter as UTF-8: {}", param))))? - .parse() - .map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse path parameter id: {}", e))))? + // Query parameters (note that non-required or collection query parameters will ignore garbage values, rather than causing a 400 response) + let query_params = req.get::<UrlEncodedQuery>().unwrap_or_default(); + let param_autoaccept = query_params.get("autoaccept").and_then(|list| list.first()).and_then(|x| x.parse::<bool>().ok()); + let param_editgroup = query_params.get("editgroup").and_then(|list| list.first()).and_then(|x| x.parse::<String>().ok()); + + // Body parameters (note that non-required body parameters will ignore garbage + // values, rather than causing a 400 response). Produce warning header and logs for + // any unused fields. + + let param_entity_list = req + .get::<bodyparser::Raw>() + .map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse body parameter entity_list - not valid UTF-8: {}", e))))?; + + let mut unused_elements = Vec::new(); + + let param_entity_list = if let Some(param_entity_list_raw) = param_entity_list { + let deserializer = &mut serde_json::Deserializer::from_str(¶m_entity_list_raw); + + let param_entity_list: Option<Vec<models::FileEntity>> = serde_ignored::deserialize(deserializer, |path| { + warn!("Ignoring unknown field in body: {}", path); + unused_elements.push(path.to_string()); + }).map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse body parameter entity_list - doesn't match schema: {}", e))))?; + + param_entity_list + } else { + None }; + let param_entity_list = param_entity_list.ok_or_else(|| Response::with((status::BadRequest, "Missing required body parameter entity_list".to_string())))?; - match api.get_editor(param_id, context).wait() { + match api.create_file_batch(param_entity_list.as_ref(), param_autoaccept, param_editgroup, context).wait() { Ok(rsp) => match rsp { - GetEditorResponse::Found(body) => { + CreateFileBatchResponse::CreatedEntities(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); - let mut response = Response::with((status::Status::from_u16(200), body_string)); - response.headers.set(ContentType(mimetypes::responses::GET_EDITOR_FOUND.clone())); + let mut response = Response::with((status::Status::from_u16(201), body_string)); + response.headers.set(ContentType(mimetypes::responses::CREATE_FILE_BATCH_CREATED_ENTITIES.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); - + if !unused_elements.is_empty() { + response.headers.set(Warning(format!("Ignoring unknown fields in body: {:?}", unused_elements))); + } Ok(response) } - GetEditorResponse::BadRequest(body) => { + CreateFileBatchResponse::BadRequest(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(400), body_string)); - response.headers.set(ContentType(mimetypes::responses::GET_EDITOR_BAD_REQUEST.clone())); + response.headers.set(ContentType(mimetypes::responses::CREATE_FILE_BATCH_BAD_REQUEST.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); - + if !unused_elements.is_empty() { + response.headers.set(Warning(format!("Ignoring unknown fields in body: {:?}", unused_elements))); + } Ok(response) } - GetEditorResponse::NotFound(body) => { + CreateFileBatchResponse::NotFound(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(404), body_string)); - response.headers.set(ContentType(mimetypes::responses::GET_EDITOR_NOT_FOUND.clone())); + response.headers.set(ContentType(mimetypes::responses::CREATE_FILE_BATCH_NOT_FOUND.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); - + if !unused_elements.is_empty() { + response.headers.set(Warning(format!("Ignoring unknown fields in body: {:?}", unused_elements))); + } Ok(response) } - GetEditorResponse::GenericError(body) => { + CreateFileBatchResponse::GenericError(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(500), body_string)); - response.headers.set(ContentType(mimetypes::responses::GET_EDITOR_GENERIC_ERROR.clone())); + response.headers.set(ContentType(mimetypes::responses::CREATE_FILE_BATCH_GENERIC_ERROR.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); - + if !unused_elements.is_empty() { + response.headers.set(Warning(format!("Ignoring unknown fields in body: {:?}", unused_elements))); + } Ok(response) } }, @@ -2636,12 +2470,12 @@ where Ok(response) }) }, - "GetEditor", + "CreateFileBatch", ); let api_clone = api.clone(); - router.get( - "/v0/editor/:id/changelog", + router.delete( + "/v0/file/:id", move |req: &mut Request| { let mut context = Context::default(); @@ -2669,43 +2503,47 @@ where .map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse path parameter id: {}", e))))? }; - match api.get_editor_changelog(param_id, context).wait() { + // Query parameters (note that non-required or collection query parameters will ignore garbage values, rather than causing a 400 response) + let query_params = req.get::<UrlEncodedQuery>().unwrap_or_default(); + let param_editgroup = query_params.get("editgroup").and_then(|list| list.first()).and_then(|x| x.parse::<String>().ok()); + + match api.delete_file(param_id, param_editgroup, context).wait() { Ok(rsp) => match rsp { - GetEditorChangelogResponse::Found(body) => { + DeleteFileResponse::DeletedEntity(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(200), body_string)); - response.headers.set(ContentType(mimetypes::responses::GET_EDITOR_CHANGELOG_FOUND.clone())); + response.headers.set(ContentType(mimetypes::responses::DELETE_FILE_DELETED_ENTITY.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); Ok(response) } - GetEditorChangelogResponse::BadRequest(body) => { + DeleteFileResponse::BadRequest(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(400), body_string)); - response.headers.set(ContentType(mimetypes::responses::GET_EDITOR_CHANGELOG_BAD_REQUEST.clone())); + response.headers.set(ContentType(mimetypes::responses::DELETE_FILE_BAD_REQUEST.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); Ok(response) } - GetEditorChangelogResponse::NotFound(body) => { + DeleteFileResponse::NotFound(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(404), body_string)); - response.headers.set(ContentType(mimetypes::responses::GET_EDITOR_CHANGELOG_NOT_FOUND.clone())); + response.headers.set(ContentType(mimetypes::responses::DELETE_FILE_NOT_FOUND.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); Ok(response) } - GetEditorChangelogResponse::GenericError(body) => { + DeleteFileResponse::GenericError(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(500), body_string)); - response.headers.set(ContentType(mimetypes::responses::GET_EDITOR_CHANGELOG_GENERIC_ERROR.clone())); + response.headers.set(ContentType(mimetypes::responses::DELETE_FILE_GENERIC_ERROR.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); @@ -2725,7 +2563,7 @@ where Ok(response) }) }, - "GetEditorChangelog", + "DeleteFile", ); let api_clone = api.clone(); @@ -2916,7 +2754,7 @@ where let api_clone = api.clone(); router.get( - "/v0/release/:id", + "/v0/file/lookup", move |req: &mut Request| { let mut context = Context::default(); @@ -2929,62 +2767,53 @@ where context.auth_data = req.extensions.remove::<AuthData>(); context.authorization = req.extensions.remove::<Authorization>(); - // Path parameters - let param_id = { - let param = req - .extensions - .get::<Router>() - .ok_or_else(|| Response::with((status::InternalServerError, "An internal error occurred".to_string())))? - .find("id") - .ok_or_else(|| Response::with((status::BadRequest, "Missing path parameter id".to_string())))?; - percent_decode(param.as_bytes()) - .decode_utf8() - .map_err(|_| Response::with((status::BadRequest, format!("Couldn't percent-decode path parameter as UTF-8: {}", param))))? - .parse() - .map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse path parameter id: {}", e))))? - }; - // Query parameters (note that non-required or collection query parameters will ignore garbage values, rather than causing a 400 response) let query_params = req.get::<UrlEncodedQuery>().unwrap_or_default(); - let param_expand = query_params.get("expand").and_then(|list| list.first()).and_then(|x| x.parse::<String>().ok()); + let param_sha1 = query_params + .get("sha1") + .ok_or_else(|| Response::with((status::BadRequest, "Missing required query parameter sha1".to_string())))? + .first() + .ok_or_else(|| Response::with((status::BadRequest, "Required query parameter sha1 was empty".to_string())))? + .parse::<String>() + .map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse query parameter sha1 - doesn't match schema: {}", e))))?; - match api.get_release(param_id, param_expand, context).wait() { + match api.lookup_file(param_sha1, context).wait() { Ok(rsp) => match rsp { - GetReleaseResponse::FoundEntity(body) => { + LookupFileResponse::FoundEntity(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(200), body_string)); - response.headers.set(ContentType(mimetypes::responses::GET_RELEASE_FOUND_ENTITY.clone())); + response.headers.set(ContentType(mimetypes::responses::LOOKUP_FILE_FOUND_ENTITY.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); Ok(response) } - GetReleaseResponse::BadRequest(body) => { + LookupFileResponse::BadRequest(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(400), body_string)); - response.headers.set(ContentType(mimetypes::responses::GET_RELEASE_BAD_REQUEST.clone())); + response.headers.set(ContentType(mimetypes::responses::LOOKUP_FILE_BAD_REQUEST.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); Ok(response) } - GetReleaseResponse::NotFound(body) => { + LookupFileResponse::NotFound(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(404), body_string)); - response.headers.set(ContentType(mimetypes::responses::GET_RELEASE_NOT_FOUND.clone())); + response.headers.set(ContentType(mimetypes::responses::LOOKUP_FILE_NOT_FOUND.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); Ok(response) } - GetReleaseResponse::GenericError(body) => { + LookupFileResponse::GenericError(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(500), body_string)); - response.headers.set(ContentType(mimetypes::responses::GET_RELEASE_GENERIC_ERROR.clone())); + response.headers.set(ContentType(mimetypes::responses::LOOKUP_FILE_GENERIC_ERROR.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); @@ -3004,12 +2833,12 @@ where Ok(response) }) }, - "GetRelease", + "LookupFile", ); let api_clone = api.clone(); - router.get( - "/v0/release/:id/files", + router.put( + "/v0/file/:id", move |req: &mut Request| { let mut context = Context::default(); @@ -3037,46 +2866,82 @@ where .map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse path parameter id: {}", e))))? }; - match api.get_release_files(param_id, context).wait() { + // Query parameters (note that non-required or collection query parameters will ignore garbage values, rather than causing a 400 response) + let query_params = req.get::<UrlEncodedQuery>().unwrap_or_default(); + let param_editgroup = query_params.get("editgroup").and_then(|list| list.first()).and_then(|x| x.parse::<String>().ok()); + + // Body parameters (note that non-required body parameters will ignore garbage + // values, rather than causing a 400 response). Produce warning header and logs for + // any unused fields. + + let param_entity = req + .get::<bodyparser::Raw>() + .map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse body parameter entity - not valid UTF-8: {}", e))))?; + + let mut unused_elements = Vec::new(); + + let param_entity = if let Some(param_entity_raw) = param_entity { + let deserializer = &mut serde_json::Deserializer::from_str(¶m_entity_raw); + + let param_entity: Option<models::FileEntity> = serde_ignored::deserialize(deserializer, |path| { + warn!("Ignoring unknown field in body: {}", path); + unused_elements.push(path.to_string()); + }).map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse body parameter entity - doesn't match schema: {}", e))))?; + + param_entity + } else { + None + }; + let param_entity = param_entity.ok_or_else(|| Response::with((status::BadRequest, "Missing required body parameter entity".to_string())))?; + + match api.update_file(param_id, param_entity, param_editgroup, context).wait() { Ok(rsp) => match rsp { - GetReleaseFilesResponse::Found(body) => { + UpdateFileResponse::UpdatedEntity(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(200), body_string)); - response.headers.set(ContentType(mimetypes::responses::GET_RELEASE_FILES_FOUND.clone())); + response.headers.set(ContentType(mimetypes::responses::UPDATE_FILE_UPDATED_ENTITY.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); - + if !unused_elements.is_empty() { + response.headers.set(Warning(format!("Ignoring unknown fields in body: {:?}", unused_elements))); + } Ok(response) } - GetReleaseFilesResponse::BadRequest(body) => { + UpdateFileResponse::BadRequest(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(400), body_string)); - response.headers.set(ContentType(mimetypes::responses::GET_RELEASE_FILES_BAD_REQUEST.clone())); + response.headers.set(ContentType(mimetypes::responses::UPDATE_FILE_BAD_REQUEST.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); - + if !unused_elements.is_empty() { + response.headers.set(Warning(format!("Ignoring unknown fields in body: {:?}", unused_elements))); + } Ok(response) } - GetReleaseFilesResponse::NotFound(body) => { + UpdateFileResponse::NotFound(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(404), body_string)); - response.headers.set(ContentType(mimetypes::responses::GET_RELEASE_FILES_NOT_FOUND.clone())); + response.headers.set(ContentType(mimetypes::responses::UPDATE_FILE_NOT_FOUND.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); - + if !unused_elements.is_empty() { + response.headers.set(Warning(format!("Ignoring unknown fields in body: {:?}", unused_elements))); + } Ok(response) } - GetReleaseFilesResponse::GenericError(body) => { + UpdateFileResponse::GenericError(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(500), body_string)); - response.headers.set(ContentType(mimetypes::responses::GET_RELEASE_FILES_GENERIC_ERROR.clone())); + response.headers.set(ContentType(mimetypes::responses::UPDATE_FILE_GENERIC_ERROR.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); - + if !unused_elements.is_empty() { + response.headers.set(Warning(format!("Ignoring unknown fields in body: {:?}", unused_elements))); + } Ok(response) } }, @@ -3093,12 +2958,12 @@ where Ok(response) }) }, - "GetReleaseFiles", + "UpdateFile", ); let api_clone = api.clone(); - router.get( - "/v0/release/:id/history", + router.post( + "/v0/release", move |req: &mut Request| { let mut context = Context::default(); @@ -3111,65 +2976,82 @@ where context.auth_data = req.extensions.remove::<AuthData>(); context.authorization = req.extensions.remove::<Authorization>(); - // Path parameters - let param_id = { - let param = req - .extensions - .get::<Router>() - .ok_or_else(|| Response::with((status::InternalServerError, "An internal error occurred".to_string())))? - .find("id") - .ok_or_else(|| Response::with((status::BadRequest, "Missing path parameter id".to_string())))?; - percent_decode(param.as_bytes()) - .decode_utf8() - .map_err(|_| Response::with((status::BadRequest, format!("Couldn't percent-decode path parameter as UTF-8: {}", param))))? - .parse() - .map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse path parameter id: {}", e))))? - }; - // Query parameters (note that non-required or collection query parameters will ignore garbage values, rather than causing a 400 response) let query_params = req.get::<UrlEncodedQuery>().unwrap_or_default(); - let param_limit = query_params.get("limit").and_then(|list| list.first()).and_then(|x| x.parse::<i64>().ok()); + let param_editgroup = query_params.get("editgroup").and_then(|list| list.first()).and_then(|x| x.parse::<String>().ok()); - match api.get_release_history(param_id, param_limit, context).wait() { + // Body parameters (note that non-required body parameters will ignore garbage + // values, rather than causing a 400 response). Produce warning header and logs for + // any unused fields. + + let param_entity = req + .get::<bodyparser::Raw>() + .map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse body parameter entity - not valid UTF-8: {}", e))))?; + + let mut unused_elements = Vec::new(); + + let param_entity = if let Some(param_entity_raw) = param_entity { + let deserializer = &mut serde_json::Deserializer::from_str(¶m_entity_raw); + + let param_entity: Option<models::ReleaseEntity> = serde_ignored::deserialize(deserializer, |path| { + warn!("Ignoring unknown field in body: {}", path); + unused_elements.push(path.to_string()); + }).map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse body parameter entity - doesn't match schema: {}", e))))?; + + param_entity + } else { + None + }; + let param_entity = param_entity.ok_or_else(|| Response::with((status::BadRequest, "Missing required body parameter entity".to_string())))?; + + match api.create_release(param_entity, param_editgroup, context).wait() { Ok(rsp) => match rsp { - GetReleaseHistoryResponse::FoundEntityHistory(body) => { + CreateReleaseResponse::CreatedEntity(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); - let mut response = Response::with((status::Status::from_u16(200), body_string)); - response.headers.set(ContentType(mimetypes::responses::GET_RELEASE_HISTORY_FOUND_ENTITY_HISTORY.clone())); + let mut response = Response::with((status::Status::from_u16(201), body_string)); + response.headers.set(ContentType(mimetypes::responses::CREATE_RELEASE_CREATED_ENTITY.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); - + if !unused_elements.is_empty() { + response.headers.set(Warning(format!("Ignoring unknown fields in body: {:?}", unused_elements))); + } Ok(response) } - GetReleaseHistoryResponse::BadRequest(body) => { + CreateReleaseResponse::BadRequest(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(400), body_string)); - response.headers.set(ContentType(mimetypes::responses::GET_RELEASE_HISTORY_BAD_REQUEST.clone())); + response.headers.set(ContentType(mimetypes::responses::CREATE_RELEASE_BAD_REQUEST.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); - + if !unused_elements.is_empty() { + response.headers.set(Warning(format!("Ignoring unknown fields in body: {:?}", unused_elements))); + } Ok(response) } - GetReleaseHistoryResponse::NotFound(body) => { + CreateReleaseResponse::NotFound(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(404), body_string)); - response.headers.set(ContentType(mimetypes::responses::GET_RELEASE_HISTORY_NOT_FOUND.clone())); + response.headers.set(ContentType(mimetypes::responses::CREATE_RELEASE_NOT_FOUND.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); - + if !unused_elements.is_empty() { + response.headers.set(Warning(format!("Ignoring unknown fields in body: {:?}", unused_elements))); + } Ok(response) } - GetReleaseHistoryResponse::GenericError(body) => { + CreateReleaseResponse::GenericError(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(500), body_string)); - response.headers.set(ContentType(mimetypes::responses::GET_RELEASE_HISTORY_GENERIC_ERROR.clone())); + response.headers.set(ContentType(mimetypes::responses::CREATE_RELEASE_GENERIC_ERROR.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); - + if !unused_elements.is_empty() { + response.headers.set(Warning(format!("Ignoring unknown fields in body: {:?}", unused_elements))); + } Ok(response) } }, @@ -3186,12 +3068,12 @@ where Ok(response) }) }, - "GetReleaseHistory", + "CreateRelease", ); let api_clone = api.clone(); - router.get( - "/v0/stats", + router.post( + "/v0/release/batch", move |req: &mut Request| { let mut context = Context::default(); @@ -3206,121 +3088,81 @@ where // Query parameters (note that non-required or collection query parameters will ignore garbage values, rather than causing a 400 response) let query_params = req.get::<UrlEncodedQuery>().unwrap_or_default(); - let param_more = query_params.get("more").and_then(|list| list.first()).and_then(|x| x.parse::<String>().ok()); - - match api.get_stats(param_more, context).wait() { - Ok(rsp) => match rsp { - GetStatsResponse::Success(body) => { - let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); - - let mut response = Response::with((status::Status::from_u16(200), body_string)); - response.headers.set(ContentType(mimetypes::responses::GET_STATS_SUCCESS.clone())); - - context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); - - Ok(response) - } - GetStatsResponse::GenericError(body) => { - let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); - - let mut response = Response::with((status::Status::from_u16(500), body_string)); - response.headers.set(ContentType(mimetypes::responses::GET_STATS_GENERIC_ERROR.clone())); + let param_autoaccept = query_params.get("autoaccept").and_then(|list| list.first()).and_then(|x| x.parse::<bool>().ok()); + let param_editgroup = query_params.get("editgroup").and_then(|list| list.first()).and_then(|x| x.parse::<String>().ok()); - context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + // Body parameters (note that non-required body parameters will ignore garbage + // values, rather than causing a 400 response). Produce warning header and logs for + // any unused fields. - Ok(response) - } - }, - Err(_) => { - // Application code returned an error. This should not happen, as the implementation should - // return a valid response. - Err(Response::with((status::InternalServerError, "An internal error occurred".to_string()))) - } - } - } + let param_entity_list = req + .get::<bodyparser::Raw>() + .map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse body parameter entity_list - not valid UTF-8: {}", e))))?; - handle_request(req, &api_clone, &mut context).or_else(|mut response| { - context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); - Ok(response) - }) - }, - "GetStats", - ); + let mut unused_elements = Vec::new(); - let api_clone = api.clone(); - router.get( - "/v0/work/:id", - move |req: &mut Request| { - let mut context = Context::default(); + let param_entity_list = if let Some(param_entity_list_raw) = param_entity_list { + let deserializer = &mut serde_json::Deserializer::from_str(¶m_entity_list_raw); - // Helper function to provide a code block to use `?` in (to be replaced by the `catch` block when it exists). - fn handle_request<T>(req: &mut Request, api: &T, context: &mut Context) -> Result<Response, Response> - where - T: Api, - { - context.x_span_id = Some(req.headers.get::<XSpanId>().map(XSpanId::to_string).unwrap_or_else(|| self::uuid::Uuid::new_v4().to_string())); - context.auth_data = req.extensions.remove::<AuthData>(); - context.authorization = req.extensions.remove::<Authorization>(); + let param_entity_list: Option<Vec<models::ReleaseEntity>> = serde_ignored::deserialize(deserializer, |path| { + warn!("Ignoring unknown field in body: {}", path); + unused_elements.push(path.to_string()); + }).map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse body parameter entity_list - doesn't match schema: {}", e))))?; - // Path parameters - let param_id = { - let param = req - .extensions - .get::<Router>() - .ok_or_else(|| Response::with((status::InternalServerError, "An internal error occurred".to_string())))? - .find("id") - .ok_or_else(|| Response::with((status::BadRequest, "Missing path parameter id".to_string())))?; - percent_decode(param.as_bytes()) - .decode_utf8() - .map_err(|_| Response::with((status::BadRequest, format!("Couldn't percent-decode path parameter as UTF-8: {}", param))))? - .parse() - .map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse path parameter id: {}", e))))? + param_entity_list + } else { + None }; + let param_entity_list = param_entity_list.ok_or_else(|| Response::with((status::BadRequest, "Missing required body parameter entity_list".to_string())))?; - // Query parameters (note that non-required or collection query parameters will ignore garbage values, rather than causing a 400 response) - let query_params = req.get::<UrlEncodedQuery>().unwrap_or_default(); - let param_expand = query_params.get("expand").and_then(|list| list.first()).and_then(|x| x.parse::<String>().ok()); - - match api.get_work(param_id, param_expand, context).wait() { + match api.create_release_batch(param_entity_list.as_ref(), param_autoaccept, param_editgroup, context).wait() { Ok(rsp) => match rsp { - GetWorkResponse::FoundEntity(body) => { + CreateReleaseBatchResponse::CreatedEntities(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); - let mut response = Response::with((status::Status::from_u16(200), body_string)); - response.headers.set(ContentType(mimetypes::responses::GET_WORK_FOUND_ENTITY.clone())); + let mut response = Response::with((status::Status::from_u16(201), body_string)); + response.headers.set(ContentType(mimetypes::responses::CREATE_RELEASE_BATCH_CREATED_ENTITIES.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); - + if !unused_elements.is_empty() { + response.headers.set(Warning(format!("Ignoring unknown fields in body: {:?}", unused_elements))); + } Ok(response) } - GetWorkResponse::BadRequest(body) => { + CreateReleaseBatchResponse::BadRequest(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(400), body_string)); - response.headers.set(ContentType(mimetypes::responses::GET_WORK_BAD_REQUEST.clone())); + response.headers.set(ContentType(mimetypes::responses::CREATE_RELEASE_BATCH_BAD_REQUEST.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); - + if !unused_elements.is_empty() { + response.headers.set(Warning(format!("Ignoring unknown fields in body: {:?}", unused_elements))); + } Ok(response) } - GetWorkResponse::NotFound(body) => { + CreateReleaseBatchResponse::NotFound(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(404), body_string)); - response.headers.set(ContentType(mimetypes::responses::GET_WORK_NOT_FOUND.clone())); + response.headers.set(ContentType(mimetypes::responses::CREATE_RELEASE_BATCH_NOT_FOUND.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); - + if !unused_elements.is_empty() { + response.headers.set(Warning(format!("Ignoring unknown fields in body: {:?}", unused_elements))); + } Ok(response) } - GetWorkResponse::GenericError(body) => { + CreateReleaseBatchResponse::GenericError(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(500), body_string)); - response.headers.set(ContentType(mimetypes::responses::GET_WORK_GENERIC_ERROR.clone())); + response.headers.set(ContentType(mimetypes::responses::CREATE_RELEASE_BATCH_GENERIC_ERROR.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); - + if !unused_elements.is_empty() { + response.headers.set(Warning(format!("Ignoring unknown fields in body: {:?}", unused_elements))); + } Ok(response) } }, @@ -3337,12 +3179,12 @@ where Ok(response) }) }, - "GetWork", + "CreateReleaseBatch", ); let api_clone = api.clone(); - router.get( - "/v0/work/:id/history", + router.post( + "/v0/work", move |req: &mut Request| { let mut context = Context::default(); @@ -3355,65 +3197,82 @@ where context.auth_data = req.extensions.remove::<AuthData>(); context.authorization = req.extensions.remove::<Authorization>(); - // Path parameters - let param_id = { - let param = req - .extensions - .get::<Router>() - .ok_or_else(|| Response::with((status::InternalServerError, "An internal error occurred".to_string())))? - .find("id") - .ok_or_else(|| Response::with((status::BadRequest, "Missing path parameter id".to_string())))?; - percent_decode(param.as_bytes()) - .decode_utf8() - .map_err(|_| Response::with((status::BadRequest, format!("Couldn't percent-decode path parameter as UTF-8: {}", param))))? - .parse() - .map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse path parameter id: {}", e))))? - }; - // Query parameters (note that non-required or collection query parameters will ignore garbage values, rather than causing a 400 response) let query_params = req.get::<UrlEncodedQuery>().unwrap_or_default(); - let param_limit = query_params.get("limit").and_then(|list| list.first()).and_then(|x| x.parse::<i64>().ok()); + let param_editgroup = query_params.get("editgroup").and_then(|list| list.first()).and_then(|x| x.parse::<String>().ok()); - match api.get_work_history(param_id, param_limit, context).wait() { + // Body parameters (note that non-required body parameters will ignore garbage + // values, rather than causing a 400 response). Produce warning header and logs for + // any unused fields. + + let param_entity = req + .get::<bodyparser::Raw>() + .map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse body parameter entity - not valid UTF-8: {}", e))))?; + + let mut unused_elements = Vec::new(); + + let param_entity = if let Some(param_entity_raw) = param_entity { + let deserializer = &mut serde_json::Deserializer::from_str(¶m_entity_raw); + + let param_entity: Option<models::WorkEntity> = serde_ignored::deserialize(deserializer, |path| { + warn!("Ignoring unknown field in body: {}", path); + unused_elements.push(path.to_string()); + }).map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse body parameter entity - doesn't match schema: {}", e))))?; + + param_entity + } else { + None + }; + let param_entity = param_entity.ok_or_else(|| Response::with((status::BadRequest, "Missing required body parameter entity".to_string())))?; + + match api.create_work(param_entity, param_editgroup, context).wait() { Ok(rsp) => match rsp { - GetWorkHistoryResponse::FoundEntityHistory(body) => { + CreateWorkResponse::CreatedEntity(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); - let mut response = Response::with((status::Status::from_u16(200), body_string)); - response.headers.set(ContentType(mimetypes::responses::GET_WORK_HISTORY_FOUND_ENTITY_HISTORY.clone())); + let mut response = Response::with((status::Status::from_u16(201), body_string)); + response.headers.set(ContentType(mimetypes::responses::CREATE_WORK_CREATED_ENTITY.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); - + if !unused_elements.is_empty() { + response.headers.set(Warning(format!("Ignoring unknown fields in body: {:?}", unused_elements))); + } Ok(response) } - GetWorkHistoryResponse::BadRequest(body) => { + CreateWorkResponse::BadRequest(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(400), body_string)); - response.headers.set(ContentType(mimetypes::responses::GET_WORK_HISTORY_BAD_REQUEST.clone())); + response.headers.set(ContentType(mimetypes::responses::CREATE_WORK_BAD_REQUEST.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); - + if !unused_elements.is_empty() { + response.headers.set(Warning(format!("Ignoring unknown fields in body: {:?}", unused_elements))); + } Ok(response) } - GetWorkHistoryResponse::NotFound(body) => { + CreateWorkResponse::NotFound(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(404), body_string)); - response.headers.set(ContentType(mimetypes::responses::GET_WORK_HISTORY_NOT_FOUND.clone())); + response.headers.set(ContentType(mimetypes::responses::CREATE_WORK_NOT_FOUND.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); - + if !unused_elements.is_empty() { + response.headers.set(Warning(format!("Ignoring unknown fields in body: {:?}", unused_elements))); + } Ok(response) } - GetWorkHistoryResponse::GenericError(body) => { + CreateWorkResponse::GenericError(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(500), body_string)); - response.headers.set(ContentType(mimetypes::responses::GET_WORK_HISTORY_GENERIC_ERROR.clone())); + response.headers.set(ContentType(mimetypes::responses::CREATE_WORK_GENERIC_ERROR.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); - + if !unused_elements.is_empty() { + response.headers.set(Warning(format!("Ignoring unknown fields in body: {:?}", unused_elements))); + } Ok(response) } }, @@ -3430,12 +3289,12 @@ where Ok(response) }) }, - "GetWorkHistory", + "CreateWork", ); let api_clone = api.clone(); - router.get( - "/v0/work/:id/releases", + router.delete( + "/v0/release/:id", move |req: &mut Request| { let mut context = Context::default(); @@ -3463,43 +3322,47 @@ where .map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse path parameter id: {}", e))))? }; - match api.get_work_releases(param_id, context).wait() { + // Query parameters (note that non-required or collection query parameters will ignore garbage values, rather than causing a 400 response) + let query_params = req.get::<UrlEncodedQuery>().unwrap_or_default(); + let param_editgroup = query_params.get("editgroup").and_then(|list| list.first()).and_then(|x| x.parse::<String>().ok()); + + match api.delete_release(param_id, param_editgroup, context).wait() { Ok(rsp) => match rsp { - GetWorkReleasesResponse::Found(body) => { + DeleteReleaseResponse::DeletedEntity(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(200), body_string)); - response.headers.set(ContentType(mimetypes::responses::GET_WORK_RELEASES_FOUND.clone())); + response.headers.set(ContentType(mimetypes::responses::DELETE_RELEASE_DELETED_ENTITY.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); Ok(response) } - GetWorkReleasesResponse::BadRequest(body) => { + DeleteReleaseResponse::BadRequest(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(400), body_string)); - response.headers.set(ContentType(mimetypes::responses::GET_WORK_RELEASES_BAD_REQUEST.clone())); + response.headers.set(ContentType(mimetypes::responses::DELETE_RELEASE_BAD_REQUEST.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); Ok(response) } - GetWorkReleasesResponse::NotFound(body) => { + DeleteReleaseResponse::NotFound(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(404), body_string)); - response.headers.set(ContentType(mimetypes::responses::GET_WORK_RELEASES_NOT_FOUND.clone())); + response.headers.set(ContentType(mimetypes::responses::DELETE_RELEASE_NOT_FOUND.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); Ok(response) } - GetWorkReleasesResponse::GenericError(body) => { + DeleteReleaseResponse::GenericError(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(500), body_string)); - response.headers.set(ContentType(mimetypes::responses::GET_WORK_RELEASES_GENERIC_ERROR.clone())); + response.headers.set(ContentType(mimetypes::responses::DELETE_RELEASE_GENERIC_ERROR.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); @@ -3519,12 +3382,12 @@ where Ok(response) }) }, - "GetWorkReleases", + "DeleteRelease", ); let api_clone = api.clone(); router.get( - "/v0/container/lookup", + "/v0/release/:id", move |req: &mut Request| { let mut context = Context::default(); @@ -3537,53 +3400,62 @@ where context.auth_data = req.extensions.remove::<AuthData>(); context.authorization = req.extensions.remove::<Authorization>(); + // Path parameters + let param_id = { + let param = req + .extensions + .get::<Router>() + .ok_or_else(|| Response::with((status::InternalServerError, "An internal error occurred".to_string())))? + .find("id") + .ok_or_else(|| Response::with((status::BadRequest, "Missing path parameter id".to_string())))?; + percent_decode(param.as_bytes()) + .decode_utf8() + .map_err(|_| Response::with((status::BadRequest, format!("Couldn't percent-decode path parameter as UTF-8: {}", param))))? + .parse() + .map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse path parameter id: {}", e))))? + }; + // Query parameters (note that non-required or collection query parameters will ignore garbage values, rather than causing a 400 response) let query_params = req.get::<UrlEncodedQuery>().unwrap_or_default(); - let param_issnl = query_params - .get("issnl") - .ok_or_else(|| Response::with((status::BadRequest, "Missing required query parameter issnl".to_string())))? - .first() - .ok_or_else(|| Response::with((status::BadRequest, "Required query parameter issnl was empty".to_string())))? - .parse::<String>() - .map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse query parameter issnl - doesn't match schema: {}", e))))?; + let param_expand = query_params.get("expand").and_then(|list| list.first()).and_then(|x| x.parse::<String>().ok()); - match api.lookup_container(param_issnl, context).wait() { + match api.get_release(param_id, param_expand, context).wait() { Ok(rsp) => match rsp { - LookupContainerResponse::FoundEntity(body) => { + GetReleaseResponse::FoundEntity(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(200), body_string)); - response.headers.set(ContentType(mimetypes::responses::LOOKUP_CONTAINER_FOUND_ENTITY.clone())); + response.headers.set(ContentType(mimetypes::responses::GET_RELEASE_FOUND_ENTITY.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); Ok(response) } - LookupContainerResponse::BadRequest(body) => { + GetReleaseResponse::BadRequest(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(400), body_string)); - response.headers.set(ContentType(mimetypes::responses::LOOKUP_CONTAINER_BAD_REQUEST.clone())); + response.headers.set(ContentType(mimetypes::responses::GET_RELEASE_BAD_REQUEST.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); Ok(response) } - LookupContainerResponse::NotFound(body) => { + GetReleaseResponse::NotFound(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(404), body_string)); - response.headers.set(ContentType(mimetypes::responses::LOOKUP_CONTAINER_NOT_FOUND.clone())); + response.headers.set(ContentType(mimetypes::responses::GET_RELEASE_NOT_FOUND.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); Ok(response) } - LookupContainerResponse::GenericError(body) => { + GetReleaseResponse::GenericError(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(500), body_string)); - response.headers.set(ContentType(mimetypes::responses::LOOKUP_CONTAINER_GENERIC_ERROR.clone())); + response.headers.set(ContentType(mimetypes::responses::GET_RELEASE_GENERIC_ERROR.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); @@ -3603,12 +3475,12 @@ where Ok(response) }) }, - "LookupContainer", + "GetRelease", ); let api_clone = api.clone(); router.get( - "/v0/creator/lookup", + "/v0/release/:id/files", move |req: &mut Request| { let mut context = Context::default(); @@ -3621,53 +3493,58 @@ where context.auth_data = req.extensions.remove::<AuthData>(); context.authorization = req.extensions.remove::<Authorization>(); - // Query parameters (note that non-required or collection query parameters will ignore garbage values, rather than causing a 400 response) - let query_params = req.get::<UrlEncodedQuery>().unwrap_or_default(); - let param_orcid = query_params - .get("orcid") - .ok_or_else(|| Response::with((status::BadRequest, "Missing required query parameter orcid".to_string())))? - .first() - .ok_or_else(|| Response::with((status::BadRequest, "Required query parameter orcid was empty".to_string())))? - .parse::<String>() - .map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse query parameter orcid - doesn't match schema: {}", e))))?; + // Path parameters + let param_id = { + let param = req + .extensions + .get::<Router>() + .ok_or_else(|| Response::with((status::InternalServerError, "An internal error occurred".to_string())))? + .find("id") + .ok_or_else(|| Response::with((status::BadRequest, "Missing path parameter id".to_string())))?; + percent_decode(param.as_bytes()) + .decode_utf8() + .map_err(|_| Response::with((status::BadRequest, format!("Couldn't percent-decode path parameter as UTF-8: {}", param))))? + .parse() + .map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse path parameter id: {}", e))))? + }; - match api.lookup_creator(param_orcid, context).wait() { + match api.get_release_files(param_id, context).wait() { Ok(rsp) => match rsp { - LookupCreatorResponse::FoundEntity(body) => { + GetReleaseFilesResponse::Found(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(200), body_string)); - response.headers.set(ContentType(mimetypes::responses::LOOKUP_CREATOR_FOUND_ENTITY.clone())); + response.headers.set(ContentType(mimetypes::responses::GET_RELEASE_FILES_FOUND.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); Ok(response) } - LookupCreatorResponse::BadRequest(body) => { + GetReleaseFilesResponse::BadRequest(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(400), body_string)); - response.headers.set(ContentType(mimetypes::responses::LOOKUP_CREATOR_BAD_REQUEST.clone())); + response.headers.set(ContentType(mimetypes::responses::GET_RELEASE_FILES_BAD_REQUEST.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); Ok(response) } - LookupCreatorResponse::NotFound(body) => { + GetReleaseFilesResponse::NotFound(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(404), body_string)); - response.headers.set(ContentType(mimetypes::responses::LOOKUP_CREATOR_NOT_FOUND.clone())); + response.headers.set(ContentType(mimetypes::responses::GET_RELEASE_FILES_NOT_FOUND.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); Ok(response) } - LookupCreatorResponse::GenericError(body) => { + GetReleaseFilesResponse::GenericError(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(500), body_string)); - response.headers.set(ContentType(mimetypes::responses::LOOKUP_CREATOR_GENERIC_ERROR.clone())); + response.headers.set(ContentType(mimetypes::responses::GET_RELEASE_FILES_GENERIC_ERROR.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); @@ -3687,12 +3564,12 @@ where Ok(response) }) }, - "LookupCreator", + "GetReleaseFiles", ); let api_clone = api.clone(); router.get( - "/v0/file/lookup", + "/v0/release/:id/history", move |req: &mut Request| { let mut context = Context::default(); @@ -3705,53 +3582,62 @@ where context.auth_data = req.extensions.remove::<AuthData>(); context.authorization = req.extensions.remove::<Authorization>(); + // Path parameters + let param_id = { + let param = req + .extensions + .get::<Router>() + .ok_or_else(|| Response::with((status::InternalServerError, "An internal error occurred".to_string())))? + .find("id") + .ok_or_else(|| Response::with((status::BadRequest, "Missing path parameter id".to_string())))?; + percent_decode(param.as_bytes()) + .decode_utf8() + .map_err(|_| Response::with((status::BadRequest, format!("Couldn't percent-decode path parameter as UTF-8: {}", param))))? + .parse() + .map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse path parameter id: {}", e))))? + }; + // Query parameters (note that non-required or collection query parameters will ignore garbage values, rather than causing a 400 response) let query_params = req.get::<UrlEncodedQuery>().unwrap_or_default(); - let param_sha1 = query_params - .get("sha1") - .ok_or_else(|| Response::with((status::BadRequest, "Missing required query parameter sha1".to_string())))? - .first() - .ok_or_else(|| Response::with((status::BadRequest, "Required query parameter sha1 was empty".to_string())))? - .parse::<String>() - .map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse query parameter sha1 - doesn't match schema: {}", e))))?; + let param_limit = query_params.get("limit").and_then(|list| list.first()).and_then(|x| x.parse::<i64>().ok()); - match api.lookup_file(param_sha1, context).wait() { + match api.get_release_history(param_id, param_limit, context).wait() { Ok(rsp) => match rsp { - LookupFileResponse::FoundEntity(body) => { + GetReleaseHistoryResponse::FoundEntityHistory(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(200), body_string)); - response.headers.set(ContentType(mimetypes::responses::LOOKUP_FILE_FOUND_ENTITY.clone())); + response.headers.set(ContentType(mimetypes::responses::GET_RELEASE_HISTORY_FOUND_ENTITY_HISTORY.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); Ok(response) } - LookupFileResponse::BadRequest(body) => { + GetReleaseHistoryResponse::BadRequest(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(400), body_string)); - response.headers.set(ContentType(mimetypes::responses::LOOKUP_FILE_BAD_REQUEST.clone())); + response.headers.set(ContentType(mimetypes::responses::GET_RELEASE_HISTORY_BAD_REQUEST.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); Ok(response) } - LookupFileResponse::NotFound(body) => { + GetReleaseHistoryResponse::NotFound(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(404), body_string)); - response.headers.set(ContentType(mimetypes::responses::LOOKUP_FILE_NOT_FOUND.clone())); + response.headers.set(ContentType(mimetypes::responses::GET_RELEASE_HISTORY_NOT_FOUND.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); Ok(response) } - LookupFileResponse::GenericError(body) => { + GetReleaseHistoryResponse::GenericError(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(500), body_string)); - response.headers.set(ContentType(mimetypes::responses::LOOKUP_FILE_GENERIC_ERROR.clone())); + response.headers.set(ContentType(mimetypes::responses::GET_RELEASE_HISTORY_GENERIC_ERROR.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); @@ -3771,7 +3657,7 @@ where Ok(response) }) }, - "LookupFile", + "GetReleaseHistory", ); let api_clone = api.clone(); @@ -3860,7 +3746,7 @@ where let api_clone = api.clone(); router.put( - "/v0/container/:id", + "/v0/release/:id", move |req: &mut Request| { let mut context = Context::default(); @@ -3905,11 +3791,10 @@ where let param_entity = if let Some(param_entity_raw) = param_entity { let deserializer = &mut serde_json::Deserializer::from_str(¶m_entity_raw); - let param_entity: Option<models::ContainerEntity> = - serde_ignored::deserialize(deserializer, |path| { - warn!("Ignoring unknown field in body: {}", path); - unused_elements.push(path.to_string()); - }).map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse body parameter entity - doesn't match schema: {}", e))))?; + let param_entity: Option<models::ReleaseEntity> = serde_ignored::deserialize(deserializer, |path| { + warn!("Ignoring unknown field in body: {}", path); + unused_elements.push(path.to_string()); + }).map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse body parameter entity - doesn't match schema: {}", e))))?; param_entity } else { @@ -3917,13 +3802,13 @@ where }; let param_entity = param_entity.ok_or_else(|| Response::with((status::BadRequest, "Missing required body parameter entity".to_string())))?; - match api.update_container(param_id, param_entity, param_editgroup, context).wait() { + match api.update_release(param_id, param_entity, param_editgroup, context).wait() { Ok(rsp) => match rsp { - UpdateContainerResponse::UpdatedEntity(body) => { + UpdateReleaseResponse::UpdatedEntity(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(200), body_string)); - response.headers.set(ContentType(mimetypes::responses::UPDATE_CONTAINER_UPDATED_ENTITY.clone())); + response.headers.set(ContentType(mimetypes::responses::UPDATE_RELEASE_UPDATED_ENTITY.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); if !unused_elements.is_empty() { @@ -3931,11 +3816,11 @@ where } Ok(response) } - UpdateContainerResponse::BadRequest(body) => { + UpdateReleaseResponse::BadRequest(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(400), body_string)); - response.headers.set(ContentType(mimetypes::responses::UPDATE_CONTAINER_BAD_REQUEST.clone())); + response.headers.set(ContentType(mimetypes::responses::UPDATE_RELEASE_BAD_REQUEST.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); if !unused_elements.is_empty() { @@ -3943,11 +3828,11 @@ where } Ok(response) } - UpdateContainerResponse::NotFound(body) => { + UpdateReleaseResponse::NotFound(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(404), body_string)); - response.headers.set(ContentType(mimetypes::responses::UPDATE_CONTAINER_NOT_FOUND.clone())); + response.headers.set(ContentType(mimetypes::responses::UPDATE_RELEASE_NOT_FOUND.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); if !unused_elements.is_empty() { @@ -3955,11 +3840,11 @@ where } Ok(response) } - UpdateContainerResponse::GenericError(body) => { + UpdateReleaseResponse::GenericError(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(500), body_string)); - response.headers.set(ContentType(mimetypes::responses::UPDATE_CONTAINER_GENERIC_ERROR.clone())); + response.headers.set(ContentType(mimetypes::responses::UPDATE_RELEASE_GENERIC_ERROR.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); if !unused_elements.is_empty() { @@ -3981,12 +3866,12 @@ where Ok(response) }) }, - "UpdateContainer", + "UpdateRelease", ); let api_clone = api.clone(); - router.put( - "/v0/creator/:id", + router.post( + "/v0/work/batch", move |req: &mut Request| { let mut context = Context::default(); @@ -3999,57 +3884,42 @@ where context.auth_data = req.extensions.remove::<AuthData>(); context.authorization = req.extensions.remove::<Authorization>(); - // Path parameters - let param_id = { - let param = req - .extensions - .get::<Router>() - .ok_or_else(|| Response::with((status::InternalServerError, "An internal error occurred".to_string())))? - .find("id") - .ok_or_else(|| Response::with((status::BadRequest, "Missing path parameter id".to_string())))?; - percent_decode(param.as_bytes()) - .decode_utf8() - .map_err(|_| Response::with((status::BadRequest, format!("Couldn't percent-decode path parameter as UTF-8: {}", param))))? - .parse() - .map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse path parameter id: {}", e))))? - }; - // Query parameters (note that non-required or collection query parameters will ignore garbage values, rather than causing a 400 response) let query_params = req.get::<UrlEncodedQuery>().unwrap_or_default(); + let param_autoaccept = query_params.get("autoaccept").and_then(|list| list.first()).and_then(|x| x.parse::<bool>().ok()); let param_editgroup = query_params.get("editgroup").and_then(|list| list.first()).and_then(|x| x.parse::<String>().ok()); // Body parameters (note that non-required body parameters will ignore garbage // values, rather than causing a 400 response). Produce warning header and logs for // any unused fields. - let param_entity = req + let param_entity_list = req .get::<bodyparser::Raw>() - .map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse body parameter entity - not valid UTF-8: {}", e))))?; + .map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse body parameter entity_list - not valid UTF-8: {}", e))))?; let mut unused_elements = Vec::new(); - let param_entity = if let Some(param_entity_raw) = param_entity { - let deserializer = &mut serde_json::Deserializer::from_str(¶m_entity_raw); + let param_entity_list = if let Some(param_entity_list_raw) = param_entity_list { + let deserializer = &mut serde_json::Deserializer::from_str(¶m_entity_list_raw); - let param_entity: Option<models::CreatorEntity> = - serde_ignored::deserialize(deserializer, |path| { - warn!("Ignoring unknown field in body: {}", path); - unused_elements.push(path.to_string()); - }).map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse body parameter entity - doesn't match schema: {}", e))))?; + let param_entity_list: Option<Vec<models::WorkEntity>> = serde_ignored::deserialize(deserializer, |path| { + warn!("Ignoring unknown field in body: {}", path); + unused_elements.push(path.to_string()); + }).map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse body parameter entity_list - doesn't match schema: {}", e))))?; - param_entity + param_entity_list } else { None }; - let param_entity = param_entity.ok_or_else(|| Response::with((status::BadRequest, "Missing required body parameter entity".to_string())))?; + let param_entity_list = param_entity_list.ok_or_else(|| Response::with((status::BadRequest, "Missing required body parameter entity_list".to_string())))?; - match api.update_creator(param_id, param_entity, param_editgroup, context).wait() { + match api.create_work_batch(param_entity_list.as_ref(), param_autoaccept, param_editgroup, context).wait() { Ok(rsp) => match rsp { - UpdateCreatorResponse::UpdatedEntity(body) => { + CreateWorkBatchResponse::CreatedEntities(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); - let mut response = Response::with((status::Status::from_u16(200), body_string)); - response.headers.set(ContentType(mimetypes::responses::UPDATE_CREATOR_UPDATED_ENTITY.clone())); + let mut response = Response::with((status::Status::from_u16(201), body_string)); + response.headers.set(ContentType(mimetypes::responses::CREATE_WORK_BATCH_CREATED_ENTITIES.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); if !unused_elements.is_empty() { @@ -4057,11 +3927,11 @@ where } Ok(response) } - UpdateCreatorResponse::BadRequest(body) => { + CreateWorkBatchResponse::BadRequest(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(400), body_string)); - response.headers.set(ContentType(mimetypes::responses::UPDATE_CREATOR_BAD_REQUEST.clone())); + response.headers.set(ContentType(mimetypes::responses::CREATE_WORK_BATCH_BAD_REQUEST.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); if !unused_elements.is_empty() { @@ -4069,11 +3939,11 @@ where } Ok(response) } - UpdateCreatorResponse::NotFound(body) => { + CreateWorkBatchResponse::NotFound(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(404), body_string)); - response.headers.set(ContentType(mimetypes::responses::UPDATE_CREATOR_NOT_FOUND.clone())); + response.headers.set(ContentType(mimetypes::responses::CREATE_WORK_BATCH_NOT_FOUND.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); if !unused_elements.is_empty() { @@ -4081,11 +3951,11 @@ where } Ok(response) } - UpdateCreatorResponse::GenericError(body) => { + CreateWorkBatchResponse::GenericError(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(500), body_string)); - response.headers.set(ContentType(mimetypes::responses::UPDATE_CREATOR_GENERIC_ERROR.clone())); + response.headers.set(ContentType(mimetypes::responses::CREATE_WORK_BATCH_GENERIC_ERROR.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); if !unused_elements.is_empty() { @@ -4107,12 +3977,12 @@ where Ok(response) }) }, - "UpdateCreator", + "CreateWorkBatch", ); let api_clone = api.clone(); - router.put( - "/v0/file/:id", + router.delete( + "/v0/work/:id", move |req: &mut Request| { let mut context = Context::default(); @@ -4144,79 +4014,139 @@ where let query_params = req.get::<UrlEncodedQuery>().unwrap_or_default(); let param_editgroup = query_params.get("editgroup").and_then(|list| list.first()).and_then(|x| x.parse::<String>().ok()); - // Body parameters (note that non-required body parameters will ignore garbage - // values, rather than causing a 400 response). Produce warning header and logs for - // any unused fields. + match api.delete_work(param_id, param_editgroup, context).wait() { + Ok(rsp) => match rsp { + DeleteWorkResponse::DeletedEntity(body) => { + let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); - let param_entity = req - .get::<bodyparser::Raw>() - .map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse body parameter entity - not valid UTF-8: {}", e))))?; + let mut response = Response::with((status::Status::from_u16(200), body_string)); + response.headers.set(ContentType(mimetypes::responses::DELETE_WORK_DELETED_ENTITY.clone())); - let mut unused_elements = Vec::new(); + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); - let param_entity = if let Some(param_entity_raw) = param_entity { - let deserializer = &mut serde_json::Deserializer::from_str(¶m_entity_raw); + Ok(response) + } + DeleteWorkResponse::BadRequest(body) => { + let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); - let param_entity: Option<models::FileEntity> = - serde_ignored::deserialize(deserializer, |path| { - warn!("Ignoring unknown field in body: {}", path); - unused_elements.push(path.to_string()); - }).map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse body parameter entity - doesn't match schema: {}", e))))?; + let mut response = Response::with((status::Status::from_u16(400), body_string)); + response.headers.set(ContentType(mimetypes::responses::DELETE_WORK_BAD_REQUEST.clone())); - param_entity - } else { - None + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + + Ok(response) + } + DeleteWorkResponse::NotFound(body) => { + let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); + + let mut response = Response::with((status::Status::from_u16(404), body_string)); + response.headers.set(ContentType(mimetypes::responses::DELETE_WORK_NOT_FOUND.clone())); + + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + + Ok(response) + } + DeleteWorkResponse::GenericError(body) => { + let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); + + let mut response = Response::with((status::Status::from_u16(500), body_string)); + response.headers.set(ContentType(mimetypes::responses::DELETE_WORK_GENERIC_ERROR.clone())); + + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + + Ok(response) + } + }, + Err(_) => { + // Application code returned an error. This should not happen, as the implementation should + // return a valid response. + Err(Response::with((status::InternalServerError, "An internal error occurred".to_string()))) + } + } + } + + handle_request(req, &api_clone, &mut context).or_else(|mut response| { + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + Ok(response) + }) + }, + "DeleteWork", + ); + + let api_clone = api.clone(); + router.get( + "/v0/work/:id", + move |req: &mut Request| { + let mut context = Context::default(); + + // Helper function to provide a code block to use `?` in (to be replaced by the `catch` block when it exists). + fn handle_request<T>(req: &mut Request, api: &T, context: &mut Context) -> Result<Response, Response> + where + T: Api, + { + context.x_span_id = Some(req.headers.get::<XSpanId>().map(XSpanId::to_string).unwrap_or_else(|| self::uuid::Uuid::new_v4().to_string())); + context.auth_data = req.extensions.remove::<AuthData>(); + context.authorization = req.extensions.remove::<Authorization>(); + + // Path parameters + let param_id = { + let param = req + .extensions + .get::<Router>() + .ok_or_else(|| Response::with((status::InternalServerError, "An internal error occurred".to_string())))? + .find("id") + .ok_or_else(|| Response::with((status::BadRequest, "Missing path parameter id".to_string())))?; + percent_decode(param.as_bytes()) + .decode_utf8() + .map_err(|_| Response::with((status::BadRequest, format!("Couldn't percent-decode path parameter as UTF-8: {}", param))))? + .parse() + .map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse path parameter id: {}", e))))? }; - let param_entity = param_entity.ok_or_else(|| Response::with((status::BadRequest, "Missing required body parameter entity".to_string())))?; - match api.update_file(param_id, param_entity, param_editgroup, context).wait() { + // Query parameters (note that non-required or collection query parameters will ignore garbage values, rather than causing a 400 response) + let query_params = req.get::<UrlEncodedQuery>().unwrap_or_default(); + let param_expand = query_params.get("expand").and_then(|list| list.first()).and_then(|x| x.parse::<String>().ok()); + + match api.get_work(param_id, param_expand, context).wait() { Ok(rsp) => match rsp { - UpdateFileResponse::UpdatedEntity(body) => { + GetWorkResponse::FoundEntity(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(200), body_string)); - response.headers.set(ContentType(mimetypes::responses::UPDATE_FILE_UPDATED_ENTITY.clone())); + response.headers.set(ContentType(mimetypes::responses::GET_WORK_FOUND_ENTITY.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); - if !unused_elements.is_empty() { - response.headers.set(Warning(format!("Ignoring unknown fields in body: {:?}", unused_elements))); - } + Ok(response) } - UpdateFileResponse::BadRequest(body) => { + GetWorkResponse::BadRequest(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(400), body_string)); - response.headers.set(ContentType(mimetypes::responses::UPDATE_FILE_BAD_REQUEST.clone())); + response.headers.set(ContentType(mimetypes::responses::GET_WORK_BAD_REQUEST.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); - if !unused_elements.is_empty() { - response.headers.set(Warning(format!("Ignoring unknown fields in body: {:?}", unused_elements))); - } + Ok(response) } - UpdateFileResponse::NotFound(body) => { + GetWorkResponse::NotFound(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(404), body_string)); - response.headers.set(ContentType(mimetypes::responses::UPDATE_FILE_NOT_FOUND.clone())); + response.headers.set(ContentType(mimetypes::responses::GET_WORK_NOT_FOUND.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); - if !unused_elements.is_empty() { - response.headers.set(Warning(format!("Ignoring unknown fields in body: {:?}", unused_elements))); - } + Ok(response) } - UpdateFileResponse::GenericError(body) => { + GetWorkResponse::GenericError(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(500), body_string)); - response.headers.set(ContentType(mimetypes::responses::UPDATE_FILE_GENERIC_ERROR.clone())); + response.headers.set(ContentType(mimetypes::responses::GET_WORK_GENERIC_ERROR.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); - if !unused_elements.is_empty() { - response.headers.set(Warning(format!("Ignoring unknown fields in body: {:?}", unused_elements))); - } + Ok(response) } }, @@ -4233,12 +4163,12 @@ where Ok(response) }) }, - "UpdateFile", + "GetWork", ); let api_clone = api.clone(); - router.put( - "/v0/release/:id", + router.get( + "/v0/work/:id/history", move |req: &mut Request| { let mut context = Context::default(); @@ -4268,81 +4198,137 @@ where // Query parameters (note that non-required or collection query parameters will ignore garbage values, rather than causing a 400 response) let query_params = req.get::<UrlEncodedQuery>().unwrap_or_default(); - let param_editgroup = query_params.get("editgroup").and_then(|list| list.first()).and_then(|x| x.parse::<String>().ok()); + let param_limit = query_params.get("limit").and_then(|list| list.first()).and_then(|x| x.parse::<i64>().ok()); - // Body parameters (note that non-required body parameters will ignore garbage - // values, rather than causing a 400 response). Produce warning header and logs for - // any unused fields. + match api.get_work_history(param_id, param_limit, context).wait() { + Ok(rsp) => match rsp { + GetWorkHistoryResponse::FoundEntityHistory(body) => { + let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); - let param_entity = req - .get::<bodyparser::Raw>() - .map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse body parameter entity - not valid UTF-8: {}", e))))?; + let mut response = Response::with((status::Status::from_u16(200), body_string)); + response.headers.set(ContentType(mimetypes::responses::GET_WORK_HISTORY_FOUND_ENTITY_HISTORY.clone())); - let mut unused_elements = Vec::new(); + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); - let param_entity = if let Some(param_entity_raw) = param_entity { - let deserializer = &mut serde_json::Deserializer::from_str(¶m_entity_raw); + Ok(response) + } + GetWorkHistoryResponse::BadRequest(body) => { + let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); - let param_entity: Option<models::ReleaseEntity> = - serde_ignored::deserialize(deserializer, |path| { - warn!("Ignoring unknown field in body: {}", path); - unused_elements.push(path.to_string()); - }).map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse body parameter entity - doesn't match schema: {}", e))))?; + let mut response = Response::with((status::Status::from_u16(400), body_string)); + response.headers.set(ContentType(mimetypes::responses::GET_WORK_HISTORY_BAD_REQUEST.clone())); - param_entity - } else { - None + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + + Ok(response) + } + GetWorkHistoryResponse::NotFound(body) => { + let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); + + let mut response = Response::with((status::Status::from_u16(404), body_string)); + response.headers.set(ContentType(mimetypes::responses::GET_WORK_HISTORY_NOT_FOUND.clone())); + + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + + Ok(response) + } + GetWorkHistoryResponse::GenericError(body) => { + let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); + + let mut response = Response::with((status::Status::from_u16(500), body_string)); + response.headers.set(ContentType(mimetypes::responses::GET_WORK_HISTORY_GENERIC_ERROR.clone())); + + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + + Ok(response) + } + }, + Err(_) => { + // Application code returned an error. This should not happen, as the implementation should + // return a valid response. + Err(Response::with((status::InternalServerError, "An internal error occurred".to_string()))) + } + } + } + + handle_request(req, &api_clone, &mut context).or_else(|mut response| { + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + Ok(response) + }) + }, + "GetWorkHistory", + ); + + let api_clone = api.clone(); + router.get( + "/v0/work/:id/releases", + move |req: &mut Request| { + let mut context = Context::default(); + + // Helper function to provide a code block to use `?` in (to be replaced by the `catch` block when it exists). + fn handle_request<T>(req: &mut Request, api: &T, context: &mut Context) -> Result<Response, Response> + where + T: Api, + { + context.x_span_id = Some(req.headers.get::<XSpanId>().map(XSpanId::to_string).unwrap_or_else(|| self::uuid::Uuid::new_v4().to_string())); + context.auth_data = req.extensions.remove::<AuthData>(); + context.authorization = req.extensions.remove::<Authorization>(); + + // Path parameters + let param_id = { + let param = req + .extensions + .get::<Router>() + .ok_or_else(|| Response::with((status::InternalServerError, "An internal error occurred".to_string())))? + .find("id") + .ok_or_else(|| Response::with((status::BadRequest, "Missing path parameter id".to_string())))?; + percent_decode(param.as_bytes()) + .decode_utf8() + .map_err(|_| Response::with((status::BadRequest, format!("Couldn't percent-decode path parameter as UTF-8: {}", param))))? + .parse() + .map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse path parameter id: {}", e))))? }; - let param_entity = param_entity.ok_or_else(|| Response::with((status::BadRequest, "Missing required body parameter entity".to_string())))?; - match api.update_release(param_id, param_entity, param_editgroup, context).wait() { + match api.get_work_releases(param_id, context).wait() { Ok(rsp) => match rsp { - UpdateReleaseResponse::UpdatedEntity(body) => { + GetWorkReleasesResponse::Found(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(200), body_string)); - response.headers.set(ContentType(mimetypes::responses::UPDATE_RELEASE_UPDATED_ENTITY.clone())); + response.headers.set(ContentType(mimetypes::responses::GET_WORK_RELEASES_FOUND.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); - if !unused_elements.is_empty() { - response.headers.set(Warning(format!("Ignoring unknown fields in body: {:?}", unused_elements))); - } + Ok(response) } - UpdateReleaseResponse::BadRequest(body) => { + GetWorkReleasesResponse::BadRequest(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(400), body_string)); - response.headers.set(ContentType(mimetypes::responses::UPDATE_RELEASE_BAD_REQUEST.clone())); + response.headers.set(ContentType(mimetypes::responses::GET_WORK_RELEASES_BAD_REQUEST.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); - if !unused_elements.is_empty() { - response.headers.set(Warning(format!("Ignoring unknown fields in body: {:?}", unused_elements))); - } + Ok(response) } - UpdateReleaseResponse::NotFound(body) => { + GetWorkReleasesResponse::NotFound(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(404), body_string)); - response.headers.set(ContentType(mimetypes::responses::UPDATE_RELEASE_NOT_FOUND.clone())); + response.headers.set(ContentType(mimetypes::responses::GET_WORK_RELEASES_NOT_FOUND.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); - if !unused_elements.is_empty() { - response.headers.set(Warning(format!("Ignoring unknown fields in body: {:?}", unused_elements))); - } + Ok(response) } - UpdateReleaseResponse::GenericError(body) => { + GetWorkReleasesResponse::GenericError(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(500), body_string)); - response.headers.set(ContentType(mimetypes::responses::UPDATE_RELEASE_GENERIC_ERROR.clone())); + response.headers.set(ContentType(mimetypes::responses::GET_WORK_RELEASES_GENERIC_ERROR.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); - if !unused_elements.is_empty() { - response.headers.set(Warning(format!("Ignoring unknown fields in body: {:?}", unused_elements))); - } + Ok(response) } }, @@ -4359,7 +4345,7 @@ where Ok(response) }) }, - "UpdateRelease", + "GetWorkReleases", ); let api_clone = api.clone(); @@ -4409,11 +4395,10 @@ where let param_entity = if let Some(param_entity_raw) = param_entity { let deserializer = &mut serde_json::Deserializer::from_str(¶m_entity_raw); - let param_entity: Option<models::WorkEntity> = - serde_ignored::deserialize(deserializer, |path| { - warn!("Ignoring unknown field in body: {}", path); - unused_elements.push(path.to_string()); - }).map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse body parameter entity - doesn't match schema: {}", e))))?; + let param_entity: Option<models::WorkEntity> = serde_ignored::deserialize(deserializer, |path| { + warn!("Ignoring unknown field in body: {}", path); + unused_elements.push(path.to_string()); + }).map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse body parameter entity - doesn't match schema: {}", e))))?; param_entity } else { |