diff options
author | Bryan Newbold <bnewbold@robocracy.org> | 2019-09-13 11:27:09 -0700 |
---|---|---|
committer | Bryan Newbold <bnewbold@robocracy.org> | 2019-09-13 11:32:05 -0700 |
commit | eb6993c6cc40e532cb1462e44408ed30db5244c0 (patch) | |
tree | 3dce637443f1fdf602f8967b65b140456445f004 /rust/fatcat-openapi/src/server.rs | |
parent | 601f3f6ac91546dd5e047c3e932a61c402305826 (diff) | |
download | fatcat-eb6993c6cc40e532cb1462e44408ed30db5244c0.tar.gz fatcat-eb6993c6cc40e532cb1462e44408ed30db5244c0.zip |
rust codegen
This re-ordered a lot of code, because several endpoints had their tags
changed, but should be no actual change in behavior/spec.
Diffstat (limited to 'rust/fatcat-openapi/src/server.rs')
-rw-r--r-- | rust/fatcat-openapi/src/server.rs | 1856 |
1 files changed, 928 insertions, 928 deletions
diff --git a/rust/fatcat-openapi/src/server.rs b/rust/fatcat-openapi/src/server.rs index 102b6e41..406b6789 100644 --- a/rust/fatcat-openapi/src/server.rs +++ b/rust/fatcat-openapi/src/server.rs @@ -98,6 +98,409 @@ where T: Api + Send + Sync + Clone + 'static, { let api_clone = api.clone(); + router.get( + "/v0/auth/check", + 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>(); + + let authorization = context.authorization.as_ref().ok_or_else(|| Response::with((status::Forbidden, "Unauthenticated".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_role = query_params.get("role").and_then(|list| list.first()).and_then(|x| x.parse::<String>().ok()); + + match api.auth_check(param_role, context).wait() { + Ok(rsp) => match rsp { + AuthCheckResponse::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::AUTH_CHECK_SUCCESS.clone())); + + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + + Ok(response) + } + AuthCheckResponse::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::AUTH_CHECK_BAD_REQUEST.clone())); + + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + + Ok(response) + } + AuthCheckResponse::NotAuthorized { body, www_authenticate } => { + let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); + + let mut response = Response::with((status::Status::from_u16(401), body_string)); + header! { (ResponseWwwAuthenticate, "WWW_Authenticate") => [String] } + response.headers.set(ResponseWwwAuthenticate(www_authenticate)); + + response.headers.set(ContentType(mimetypes::responses::AUTH_CHECK_NOT_AUTHORIZED.clone())); + + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + + Ok(response) + } + AuthCheckResponse::Forbidden(body) => { + let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); + + let mut response = Response::with((status::Status::from_u16(403), body_string)); + response.headers.set(ContentType(mimetypes::responses::AUTH_CHECK_FORBIDDEN.clone())); + + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + + Ok(response) + } + AuthCheckResponse::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::AUTH_CHECK_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) + }) + }, + "AuthCheck", + ); + + let api_clone = api.clone(); + router.post( + "/v0/auth/oidc", + 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>(); + + let authorization = context.authorization.as_ref().ok_or_else(|| Response::with((status::Forbidden, "Unauthenticated".to_string())))?; + + // 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_oidc_params = req + .get::<bodyparser::Raw>() + .map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse body parameter oidc_params - not valid UTF-8: {}", e))))?; + + let mut unused_elements = Vec::new(); + + let param_oidc_params = if let Some(param_oidc_params_raw) = param_oidc_params { + let deserializer = &mut serde_json::Deserializer::from_str(¶m_oidc_params_raw); + + let param_oidc_params: Option<models::AuthOidc> = 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 oidc_params - doesn't match schema: {}", e))))?; + + param_oidc_params + } else { + None + }; + let param_oidc_params = param_oidc_params.ok_or_else(|| Response::with((status::BadRequest, "Missing required body parameter oidc_params".to_string())))?; + + match api.auth_oidc(param_oidc_params, context).wait() { + Ok(rsp) => match rsp { + AuthOidcResponse::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::AUTH_OIDC_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) + } + AuthOidcResponse::Created(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::AUTH_OIDC_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) + } + AuthOidcResponse::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::AUTH_OIDC_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) + } + AuthOidcResponse::NotAuthorized { body, www_authenticate } => { + let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); + + let mut response = Response::with((status::Status::from_u16(401), body_string)); + header! { (ResponseWwwAuthenticate, "WWW_Authenticate") => [String] } + response.headers.set(ResponseWwwAuthenticate(www_authenticate)); + + response.headers.set(ContentType(mimetypes::responses::AUTH_OIDC_NOT_AUTHORIZED.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) + } + AuthOidcResponse::Forbidden(body) => { + let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); + + let mut response = Response::with((status::Status::from_u16(403), body_string)); + response.headers.set(ContentType(mimetypes::responses::AUTH_OIDC_FORBIDDEN.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) + } + AuthOidcResponse::Conflict(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::AUTH_OIDC_CONFLICT.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) + } + AuthOidcResponse::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::AUTH_OIDC_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) + } + }, + 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) + }) + }, + "AuthOidc", + ); + + let api_clone = api.clone(); + router.get( + "/v0/changelog", + 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>(); + + // 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| Some(x.parse::<i64>())) + .map_or_else(|| Ok(None), |x| x.map(|v| Some(v))) + .map_err(|x| Response::with((status::BadRequest, "unparsable query parameter (expected integer)".to_string())))?; + + match api.get_changelog(param_limit, context).wait() { + Ok(rsp) => match rsp { + 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_CHANGELOG_SUCCESS.clone())); + + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + + Ok(response) + } + GetChangelogResponse::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_CHANGELOG_BAD_REQUEST.clone())); + + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + + Ok(response) + } + 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_CHANGELOG_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) + }) + }, + "GetChangelog", + ); + + let api_clone = api.clone(); + router.get( + "/v0/changelog/:index", + 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_index = { + let param = req + .extensions + .get::<Router>() + .ok_or_else(|| Response::with((status::InternalServerError, "An internal error occurred".to_string())))? + .find("index") + .ok_or_else(|| Response::with((status::BadRequest, "Missing path parameter index".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 index: {}", e))))? + }; + + match api.get_changelog_entry(param_index, context).wait() { + Ok(rsp) => match rsp { + 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_CHANGELOG_ENTRY_FOUND_CHANGELOG_ENTRY.clone())); + + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + + Ok(response) + } + GetChangelogEntryResponse::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_CHANGELOG_ENTRY_BAD_REQUEST.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())); + + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + + Ok(response) + } + 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_CHANGELOG_ENTRY_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) + }) + }, + "GetChangelogEntry", + ); + + let api_clone = api.clone(); router.post( "/v0/editgroup/:editgroup_id/container", move |req: &mut Request| { @@ -2691,8 +3094,8 @@ where ); let api_clone = api.clone(); - router.get( - "/v0/auth/check", + router.post( + "/v0/editgroup/:editgroup_id/accept", move |req: &mut Request| { let mut context = Context::default(); @@ -2707,60 +3110,91 @@ where let authorization = context.authorization.as_ref().ok_or_else(|| Response::with((status::Forbidden, "Unauthenticated".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_role = query_params.get("role").and_then(|list| list.first()).and_then(|x| x.parse::<String>().ok()); + // Path parameters + let param_editgroup_id = { + let param = req + .extensions + .get::<Router>() + .ok_or_else(|| Response::with((status::InternalServerError, "An internal error occurred".to_string())))? + .find("editgroup_id") + .ok_or_else(|| Response::with((status::BadRequest, "Missing path parameter editgroup_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 editgroup_id: {}", e))))? + }; - match api.auth_check(param_role, context).wait() { + match api.accept_editgroup(param_editgroup_id, context).wait() { Ok(rsp) => match rsp { - AuthCheckResponse::Success(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::AUTH_CHECK_SUCCESS.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) } - AuthCheckResponse::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::AUTH_CHECK_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) } - AuthCheckResponse::NotAuthorized { body, www_authenticate } => { + AcceptEditgroupResponse::NotAuthorized { body, www_authenticate } => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(401), body_string)); header! { (ResponseWwwAuthenticate, "WWW_Authenticate") => [String] } response.headers.set(ResponseWwwAuthenticate(www_authenticate)); - response.headers.set(ContentType(mimetypes::responses::AUTH_CHECK_NOT_AUTHORIZED.clone())); + response.headers.set(ContentType(mimetypes::responses::ACCEPT_EDITGROUP_NOT_AUTHORIZED.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); Ok(response) } - AuthCheckResponse::Forbidden(body) => { + AcceptEditgroupResponse::Forbidden(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(403), body_string)); - response.headers.set(ContentType(mimetypes::responses::AUTH_CHECK_FORBIDDEN.clone())); + response.headers.set(ContentType(mimetypes::responses::ACCEPT_EDITGROUP_FORBIDDEN.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); Ok(response) } - AuthCheckResponse::GenericError(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::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::AUTH_CHECK_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()))); @@ -2780,12 +3214,12 @@ where Ok(response) }) }, - "AuthCheck", + "AcceptEditgroup", ); let api_clone = api.clone(); router.post( - "/v0/auth/oidc", + "/v0/editgroup", move |req: &mut Request| { let mut context = Context::default(); @@ -2804,46 +3238,34 @@ where // values, rather than causing a 400 response). Produce warning header and logs for // any unused fields. - let param_oidc_params = req + let param_editgroup = req .get::<bodyparser::Raw>() - .map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse body parameter oidc_params - not valid UTF-8: {}", e))))?; + .map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse body parameter editgroup - not valid UTF-8: {}", e))))?; let mut unused_elements = Vec::new(); - let param_oidc_params = if let Some(param_oidc_params_raw) = param_oidc_params { - let deserializer = &mut serde_json::Deserializer::from_str(¶m_oidc_params_raw); + let param_editgroup = if let Some(param_editgroup_raw) = param_editgroup { + let deserializer = &mut serde_json::Deserializer::from_str(¶m_editgroup_raw); - let param_oidc_params: Option<models::AuthOidc> = serde_ignored::deserialize(deserializer, |path| { + 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 oidc_params - doesn't match schema: {}", e))))?; + .map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse body parameter editgroup - doesn't match schema: {}", e))))?; - param_oidc_params + param_editgroup } else { None }; - let param_oidc_params = param_oidc_params.ok_or_else(|| Response::with((status::BadRequest, "Missing required body parameter oidc_params".to_string())))?; + let param_editgroup = param_editgroup.ok_or_else(|| Response::with((status::BadRequest, "Missing required body parameter editgroup".to_string())))?; - match api.auth_oidc(param_oidc_params, context).wait() { + match api.create_editgroup(param_editgroup, context).wait() { Ok(rsp) => match rsp { - AuthOidcResponse::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::AUTH_OIDC_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) - } - AuthOidcResponse::Created(body) => { + 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(201), body_string)); - response.headers.set(ContentType(mimetypes::responses::AUTH_OIDC_CREATED.clone())); + 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() { @@ -2851,11 +3273,11 @@ where } Ok(response) } - AuthOidcResponse::BadRequest(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(400), body_string)); - response.headers.set(ContentType(mimetypes::responses::AUTH_OIDC_BAD_REQUEST.clone())); + 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() { @@ -2863,14 +3285,14 @@ where } Ok(response) } - AuthOidcResponse::NotAuthorized { body, www_authenticate } => { + CreateEditgroupResponse::NotAuthorized { body, www_authenticate } => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(401), body_string)); header! { (ResponseWwwAuthenticate, "WWW_Authenticate") => [String] } response.headers.set(ResponseWwwAuthenticate(www_authenticate)); - response.headers.set(ContentType(mimetypes::responses::AUTH_OIDC_NOT_AUTHORIZED.clone())); + response.headers.set(ContentType(mimetypes::responses::CREATE_EDITGROUP_NOT_AUTHORIZED.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); if !unused_elements.is_empty() { @@ -2878,11 +3300,11 @@ where } Ok(response) } - AuthOidcResponse::Forbidden(body) => { + CreateEditgroupResponse::Forbidden(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(403), body_string)); - response.headers.set(ContentType(mimetypes::responses::AUTH_OIDC_FORBIDDEN.clone())); + response.headers.set(ContentType(mimetypes::responses::CREATE_EDITGROUP_FORBIDDEN.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); if !unused_elements.is_empty() { @@ -2890,11 +3312,11 @@ where } Ok(response) } - AuthOidcResponse::Conflict(body) => { + CreateEditgroupResponse::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(409), body_string)); - response.headers.set(ContentType(mimetypes::responses::AUTH_OIDC_CONFLICT.clone())); + let mut response = Response::with((status::Status::from_u16(404), body_string)); + response.headers.set(ContentType(mimetypes::responses::CREATE_EDITGROUP_NOT_FOUND.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); if !unused_elements.is_empty() { @@ -2902,11 +3324,11 @@ where } Ok(response) } - AuthOidcResponse::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::AUTH_OIDC_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() { @@ -2928,307 +3350,12 @@ where Ok(response) }) }, - "AuthOidc", - ); - - let api_clone = api.clone(); - router.get( - "/v0/editgroup/reviewable", - 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>(); - - // 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| Some(x.parse::<i64>())) - .map_or_else(|| Ok(None), |x| x.map(|v| Some(v))) - .map_err(|x| Response::with((status::BadRequest, "unparsable query parameter (expected integer)".to_string())))?; - let param_before = query_params - .get("before") - .and_then(|list| list.first()) - .and_then(|x| Some(x.parse::<chrono::DateTime<chrono::Utc>>())) - .map_or_else(|| Ok(None), |x| x.map(|v| Some(v))) - .map_err(|x| Response::with((status::BadRequest, "unparsable query parameter (expected UTC datetime in ISO/RFC format)".to_string())))?; - let param_since = query_params - .get("since") - .and_then(|list| list.first()) - .and_then(|x| Some(x.parse::<chrono::DateTime<chrono::Utc>>())) - .map_or_else(|| Ok(None), |x| x.map(|v| Some(v))) - .map_err(|x| Response::with((status::BadRequest, "unparsable query parameter (expected UTC datetime in ISO/RFC format)".to_string())))?; - - match api.get_editgroups_reviewable(param_expand, param_limit, param_before, param_since, context).wait() { - Ok(rsp) => match rsp { - GetEditgroupsReviewableResponse::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_EDITGROUPS_REVIEWABLE_FOUND.clone())); - - context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); - - Ok(response) - } - GetEditgroupsReviewableResponse::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_EDITGROUPS_REVIEWABLE_BAD_REQUEST.clone())); - - context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); - - Ok(response) - } - GetEditgroupsReviewableResponse::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_EDITGROUPS_REVIEWABLE_NOT_FOUND.clone())); - - context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); - - Ok(response) - } - GetEditgroupsReviewableResponse::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_EDITGROUPS_REVIEWABLE_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) - }) - }, - "GetEditgroupsReviewable", - ); - - let api_clone = api.clone(); - router.get( - "/v0/editor/:editor_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_editor_id = { - let param = req - .extensions - .get::<Router>() - .ok_or_else(|| Response::with((status::InternalServerError, "An internal error occurred".to_string())))? - .find("editor_id") - .ok_or_else(|| Response::with((status::BadRequest, "Missing path parameter editor_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 editor_id: {}", e))))? - }; - - match api.get_editor(param_editor_id, context).wait() { - Ok(rsp) => match rsp { - 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::GET_EDITOR_FOUND.clone())); - - context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); - - Ok(response) - } - 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::GET_EDITOR_BAD_REQUEST.clone())); - - context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); - - Ok(response) - } - 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::GET_EDITOR_NOT_FOUND.clone())); - - context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); - - Ok(response) - } - 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::GET_EDITOR_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) - }) - }, - "GetEditor", - ); - - let api_clone = api.clone(); - router.get( - "/v0/editor/:editor_id/editgroups", - 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_editor_id = { - let param = req - .extensions - .get::<Router>() - .ok_or_else(|| Response::with((status::InternalServerError, "An internal error occurred".to_string())))? - .find("editor_id") - .ok_or_else(|| Response::with((status::BadRequest, "Missing path parameter editor_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 editor_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| Some(x.parse::<i64>())) - .map_or_else(|| Ok(None), |x| x.map(|v| Some(v))) - .map_err(|x| Response::with((status::BadRequest, "unparsable query parameter (expected integer)".to_string())))?; - let param_before = query_params - .get("before") - .and_then(|list| list.first()) - .and_then(|x| Some(x.parse::<chrono::DateTime<chrono::Utc>>())) - .map_or_else(|| Ok(None), |x| x.map(|v| Some(v))) - .map_err(|x| Response::with((status::BadRequest, "unparsable query parameter (expected UTC datetime in ISO/RFC format)".to_string())))?; - let param_since = query_params - .get("since") - .and_then(|list| list.first()) - .and_then(|x| Some(x.parse::<chrono::DateTime<chrono::Utc>>())) - .map_or_else(|| Ok(None), |x| x.map(|v| Some(v))) - .map_err(|x| Response::with((status::BadRequest, "unparsable query parameter (expected UTC datetime in ISO/RFC format)".to_string())))?; - - match api.get_editor_editgroups(param_editor_id, param_limit, param_before, param_since, context).wait() { - Ok(rsp) => match rsp { - GetEditorEditgroupsResponse::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_EDITOR_EDITGROUPS_FOUND.clone())); - - context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); - - Ok(response) - } - GetEditorEditgroupsResponse::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_EDITGROUPS_BAD_REQUEST.clone())); - - context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); - - Ok(response) - } - GetEditorEditgroupsResponse::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_EDITGROUPS_NOT_FOUND.clone())); - - context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); - - Ok(response) - } - GetEditorEditgroupsResponse::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_EDITGROUPS_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) - }) - }, - "GetEditorEditgroups", + "CreateEditgroup", ); let api_clone = api.clone(); - router.put( - "/v0/editgroup/:editgroup_id", + router.post( + "/v0/editgroup/:editgroup_id/annotation", move |req: &mut Request| { let mut context = Context::default(); @@ -3258,47 +3385,38 @@ where .map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse path parameter editgroup_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_submit = query_params - .get("submit") - .and_then(|list| list.first()) - .and_then(|x| Some(x.to_lowercase().parse::<bool>())) - .map_or_else(|| Ok(None), |x| x.map(|v| Some(v))) - .map_err(|x| Response::with((status::BadRequest, "unparsable query parameter (expected boolean)".to_string())))?; - // 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_editgroup = req + let param_annotation = req .get::<bodyparser::Raw>() - .map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse body parameter editgroup - not valid UTF-8: {}", e))))?; + .map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse body parameter annotation - not valid UTF-8: {}", e))))?; let mut unused_elements = Vec::new(); - let param_editgroup = if let Some(param_editgroup_raw) = param_editgroup { - let deserializer = &mut serde_json::Deserializer::from_str(¶m_editgroup_raw); + let param_annotation = if let Some(param_annotation_raw) = param_annotation { + let deserializer = &mut serde_json::Deserializer::from_str(¶m_annotation_raw); - let param_editgroup: Option<models::Editgroup> = serde_ignored::deserialize(deserializer, |path| { + let param_annotation: Option<models::EditgroupAnnotation> = 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))))?; + .map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse body parameter annotation - doesn't match schema: {}", e))))?; - param_editgroup + param_annotation } else { None }; - let param_editgroup = param_editgroup.ok_or_else(|| Response::with((status::BadRequest, "Missing required body parameter editgroup".to_string())))?; + let param_annotation = param_annotation.ok_or_else(|| Response::with((status::BadRequest, "Missing required body parameter annotation".to_string())))?; - match api.update_editgroup(param_editgroup_id, param_editgroup, param_submit, context).wait() { + match api.create_editgroup_annotation(param_editgroup_id, param_annotation, context).wait() { Ok(rsp) => match rsp { - UpdateEditgroupResponse::UpdatedEditgroup(body) => { + CreateEditgroupAnnotationResponse::Created(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_EDITGROUP_UPDATED_EDITGROUP.clone())); + let mut response = Response::with((status::Status::from_u16(201), body_string)); + response.headers.set(ContentType(mimetypes::responses::CREATE_EDITGROUP_ANNOTATION_CREATED.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); if !unused_elements.is_empty() { @@ -3306,11 +3424,11 @@ where } Ok(response) } - UpdateEditgroupResponse::BadRequest(body) => { + CreateEditgroupAnnotationResponse::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_EDITGROUP_BAD_REQUEST.clone())); + response.headers.set(ContentType(mimetypes::responses::CREATE_EDITGROUP_ANNOTATION_BAD_REQUEST.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); if !unused_elements.is_empty() { @@ -3318,14 +3436,14 @@ where } Ok(response) } - UpdateEditgroupResponse::NotAuthorized { body, www_authenticate } => { + CreateEditgroupAnnotationResponse::NotAuthorized { body, www_authenticate } => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(401), body_string)); header! { (ResponseWwwAuthenticate, "WWW_Authenticate") => [String] } response.headers.set(ResponseWwwAuthenticate(www_authenticate)); - response.headers.set(ContentType(mimetypes::responses::UPDATE_EDITGROUP_NOT_AUTHORIZED.clone())); + response.headers.set(ContentType(mimetypes::responses::CREATE_EDITGROUP_ANNOTATION_NOT_AUTHORIZED.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); if !unused_elements.is_empty() { @@ -3333,11 +3451,11 @@ where } Ok(response) } - UpdateEditgroupResponse::Forbidden(body) => { + CreateEditgroupAnnotationResponse::Forbidden(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(403), body_string)); - response.headers.set(ContentType(mimetypes::responses::UPDATE_EDITGROUP_FORBIDDEN.clone())); + response.headers.set(ContentType(mimetypes::responses::CREATE_EDITGROUP_ANNOTATION_FORBIDDEN.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); if !unused_elements.is_empty() { @@ -3345,11 +3463,11 @@ where } Ok(response) } - UpdateEditgroupResponse::NotFound(body) => { + CreateEditgroupAnnotationResponse::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_EDITGROUP_NOT_FOUND.clone())); + response.headers.set(ContentType(mimetypes::responses::CREATE_EDITGROUP_ANNOTATION_NOT_FOUND.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); if !unused_elements.is_empty() { @@ -3357,11 +3475,11 @@ where } Ok(response) } - UpdateEditgroupResponse::GenericError(body) => { + CreateEditgroupAnnotationResponse::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_EDITGROUP_GENERIC_ERROR.clone())); + response.headers.set(ContentType(mimetypes::responses::CREATE_EDITGROUP_ANNOTATION_GENERIC_ERROR.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); if !unused_elements.is_empty() { @@ -3383,12 +3501,12 @@ where Ok(response) }) }, - "UpdateEditgroup", + "CreateEditgroupAnnotation", ); let api_clone = api.clone(); - router.put( - "/v0/editor/:editor_id", + router.get( + "/v0/editgroup/:editgroup_id", move |req: &mut Request| { let mut context = Context::default(); @@ -3401,123 +3519,61 @@ where context.auth_data = req.extensions.remove::<AuthData>(); context.authorization = req.extensions.remove::<Authorization>(); - let authorization = context.authorization.as_ref().ok_or_else(|| Response::with((status::Forbidden, "Unauthenticated".to_string())))?; - // Path parameters - let param_editor_id = { + let param_editgroup_id = { let param = req .extensions .get::<Router>() .ok_or_else(|| Response::with((status::InternalServerError, "An internal error occurred".to_string())))? - .find("editor_id") - .ok_or_else(|| Response::with((status::BadRequest, "Missing path parameter editor_id".to_string())))?; + .find("editgroup_id") + .ok_or_else(|| Response::with((status::BadRequest, "Missing path parameter editgroup_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 editor_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. - - let param_editor = req - .get::<bodyparser::Raw>() - .map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse body parameter editor - not valid UTF-8: {}", e))))?; - - let mut unused_elements = Vec::new(); - - let param_editor = if let Some(param_editor_raw) = param_editor { - let deserializer = &mut serde_json::Deserializer::from_str(¶m_editor_raw); - - let param_editor: Option<models::Editor> = 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 editor - doesn't match schema: {}", e))))?; - - param_editor - } else { - None + .map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse path parameter editgroup_id: {}", e))))? }; - let param_editor = param_editor.ok_or_else(|| Response::with((status::BadRequest, "Missing required body parameter editor".to_string())))?; - match api.update_editor(param_editor_id, param_editor, context).wait() { + match api.get_editgroup(param_editgroup_id, context).wait() { Ok(rsp) => match rsp { - UpdateEditorResponse::UpdatedEditor(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::UPDATE_EDITOR_UPDATED_EDITOR.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()))); - if !unused_elements.is_empty() { - response.headers.set(Warning(format!("Ignoring unknown fields in body: {:?}", unused_elements))); - } - Ok(response) - } - UpdateEditorResponse::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_EDITOR_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) } - UpdateEditorResponse::NotAuthorized { body, www_authenticate } => { + 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(401), body_string)); - header! { (ResponseWwwAuthenticate, "WWW_Authenticate") => [String] } - response.headers.set(ResponseWwwAuthenticate(www_authenticate)); - - response.headers.set(ContentType(mimetypes::responses::UPDATE_EDITOR_NOT_AUTHORIZED.clone())); + let mut response = Response::with((status::Status::from_u16(400), body_string)); + 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()))); - if !unused_elements.is_empty() { - response.headers.set(Warning(format!("Ignoring unknown fields in body: {:?}", unused_elements))); - } - Ok(response) - } - UpdateEditorResponse::Forbidden(body) => { - let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); - let mut response = Response::with((status::Status::from_u16(403), body_string)); - response.headers.set(ContentType(mimetypes::responses::UPDATE_EDITOR_FORBIDDEN.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) } - UpdateEditorResponse::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::UPDATE_EDITOR_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()))); - if !unused_elements.is_empty() { - response.headers.set(Warning(format!("Ignoring unknown fields in body: {:?}", unused_elements))); - } + Ok(response) } - UpdateEditorResponse::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::UPDATE_EDITOR_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()))); - if !unused_elements.is_empty() { - response.headers.set(Warning(format!("Ignoring unknown fields in body: {:?}", unused_elements))); - } + Ok(response) } }, @@ -3534,12 +3590,12 @@ where Ok(response) }) }, - "UpdateEditor", + "GetEditgroup", ); let api_clone = api.clone(); - router.post( - "/v0/editgroup/:editgroup_id/accept", + router.get( + "/v0/editgroup/:editgroup_id/annotations", move |req: &mut Request| { let mut context = Context::default(); @@ -3552,8 +3608,6 @@ where context.auth_data = req.extensions.remove::<AuthData>(); context.authorization = req.extensions.remove::<Authorization>(); - let authorization = context.authorization.as_ref().ok_or_else(|| Response::with((status::Forbidden, "Unauthenticated".to_string())))?; - // Path parameters let param_editgroup_id = { let param = req @@ -3569,76 +3623,70 @@ where .map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse path parameter editgroup_id: {}", e))))? }; - match api.accept_editgroup(param_editgroup_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_expand = query_params.get("expand").and_then(|list| list.first()).and_then(|x| x.parse::<String>().ok()); + + match api.get_editgroup_annotations(param_editgroup_id, param_expand, context).wait() { Ok(rsp) => match rsp { - AcceptEditgroupResponse::MergedSuccessfully(body) => { + GetEditgroupAnnotationsResponse::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::ACCEPT_EDITGROUP_MERGED_SUCCESSFULLY.clone())); + response.headers.set(ContentType(mimetypes::responses::GET_EDITGROUP_ANNOTATIONS_SUCCESS.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); Ok(response) } - AcceptEditgroupResponse::BadRequest(body) => { + GetEditgroupAnnotationsResponse::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())); + response.headers.set(ContentType(mimetypes::responses::GET_EDITGROUP_ANNOTATIONS_BAD_REQUEST.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); Ok(response) } - AcceptEditgroupResponse::NotAuthorized { body, www_authenticate } => { + GetEditgroupAnnotationsResponse::NotAuthorized { body, www_authenticate } => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(401), body_string)); header! { (ResponseWwwAuthenticate, "WWW_Authenticate") => [String] } response.headers.set(ResponseWwwAuthenticate(www_authenticate)); - response.headers.set(ContentType(mimetypes::responses::ACCEPT_EDITGROUP_NOT_AUTHORIZED.clone())); + response.headers.set(ContentType(mimetypes::responses::GET_EDITGROUP_ANNOTATIONS_NOT_AUTHORIZED.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); Ok(response) } - AcceptEditgroupResponse::Forbidden(body) => { + GetEditgroupAnnotationsResponse::Forbidden(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(403), body_string)); - response.headers.set(ContentType(mimetypes::responses::ACCEPT_EDITGROUP_FORBIDDEN.clone())); + response.headers.set(ContentType(mimetypes::responses::GET_EDITGROUP_ANNOTATIONS_FORBIDDEN.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); Ok(response) } - AcceptEditgroupResponse::NotFound(body) => { + GetEditgroupAnnotationsResponse::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())); + response.headers.set(ContentType(mimetypes::responses::GET_EDITGROUP_ANNOTATIONS_NOT_FOUND.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); Ok(response) } - AcceptEditgroupResponse::GenericError(body) => { + GetEditgroupAnnotationsResponse::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())); + response.headers.set(ContentType(mimetypes::responses::GET_EDITGROUP_ANNOTATIONS_GENERIC_ERROR.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); @@ -3658,12 +3706,12 @@ where Ok(response) }) }, - "AcceptEditgroup", + "GetEditgroupAnnotations", ); let api_clone = api.clone(); - router.post( - "/v0/editgroup", + router.get( + "/v0/editgroup/reviewable", move |req: &mut Request| { let mut context = Context::default(); @@ -3676,108 +3724,68 @@ where context.auth_data = req.extensions.remove::<AuthData>(); context.authorization = req.extensions.remove::<Authorization>(); - let authorization = context.authorization.as_ref().ok_or_else(|| Response::with((status::Forbidden, "Unauthenticated".to_string())))?; - - // 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_editgroup = req - .get::<bodyparser::Raw>() - .map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse body parameter editgroup - not valid UTF-8: {}", e))))?; - - let mut unused_elements = Vec::new(); - - let param_editgroup = if let Some(param_editgroup_raw) = param_editgroup { - let deserializer = &mut serde_json::Deserializer::from_str(¶m_editgroup_raw); - - 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))))?; - - param_editgroup - } else { - None - }; - let param_editgroup = param_editgroup.ok_or_else(|| Response::with((status::BadRequest, "Missing required body parameter editgroup".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()); + let param_limit = query_params + .get("limit") + .and_then(|list| list.first()) + .and_then(|x| Some(x.parse::<i64>())) + .map_or_else(|| Ok(None), |x| x.map(|v| Some(v))) + .map_err(|x| Response::with((status::BadRequest, "unparsable query parameter (expected integer)".to_string())))?; + let param_before = query_params + .get("before") + .and_then(|list| list.first()) + .and_then(|x| Some(x.parse::<chrono::DateTime<chrono::Utc>>())) + .map_or_else(|| Ok(None), |x| x.map(|v| Some(v))) + .map_err(|x| Response::with((status::BadRequest, "unparsable query parameter (expected UTC datetime in ISO/RFC format)".to_string())))?; + let param_since = query_params + .get("since") + .and_then(|list| list.first()) + .and_then(|x| Some(x.parse::<chrono::DateTime<chrono::Utc>>())) + .map_or_else(|| Ok(None), |x| x.map(|v| Some(v))) + .map_err(|x| Response::with((status::BadRequest, "unparsable query parameter (expected UTC datetime in ISO/RFC format)".to_string())))?; - match api.create_editgroup(param_editgroup, context).wait() { + match api.get_editgroups_reviewable(param_expand, param_limit, param_before, param_since, context).wait() { Ok(rsp) => match rsp { - CreateEditgroupResponse::SuccessfullyCreated(body) => { + GetEditgroupsReviewableResponse::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(201), body_string)); - response.headers.set(ContentType(mimetypes::responses::CREATE_EDITGROUP_SUCCESSFULLY_CREATED.clone())); + let mut response = Response::with((status::Status::from_u16(200), body_string)); + response.headers.set(ContentType(mimetypes::responses::GET_EDITGROUPS_REVIEWABLE_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::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_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) } - CreateEditgroupResponse::NotAuthorized { body, www_authenticate } => { + GetEditgroupsReviewableResponse::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(401), body_string)); - header! { (ResponseWwwAuthenticate, "WWW_Authenticate") => [String] } - response.headers.set(ResponseWwwAuthenticate(www_authenticate)); - - response.headers.set(ContentType(mimetypes::responses::CREATE_EDITGROUP_NOT_AUTHORIZED.clone())); + let mut response = Response::with((status::Status::from_u16(400), body_string)); + response.headers.set(ContentType(mimetypes::responses::GET_EDITGROUPS_REVIEWABLE_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::Forbidden(body) => { - let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); - let mut response = Response::with((status::Status::from_u16(403), body_string)); - response.headers.set(ContentType(mimetypes::responses::CREATE_EDITGROUP_FORBIDDEN.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::NotFound(body) => { + GetEditgroupsReviewableResponse::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_EDITGROUP_NOT_FOUND.clone())); + response.headers.set(ContentType(mimetypes::responses::GET_EDITGROUPS_REVIEWABLE_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) => { + GetEditgroupsReviewableResponse::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_EDITGROUPS_REVIEWABLE_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) } }, @@ -3794,12 +3802,12 @@ where Ok(response) }) }, - "CreateEditgroup", + "GetEditgroupsReviewable", ); let api_clone = api.clone(); - router.post( - "/v0/editgroup/:editgroup_id/annotation", + router.put( + "/v0/editgroup/:editgroup_id", move |req: &mut Request| { let mut context = Context::default(); @@ -3829,38 +3837,47 @@ where .map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse path parameter editgroup_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_submit = query_params + .get("submit") + .and_then(|list| list.first()) + .and_then(|x| Some(x.to_lowercase().parse::<bool>())) + .map_or_else(|| Ok(None), |x| x.map(|v| Some(v))) + .map_err(|x| Response::with((status::BadRequest, "unparsable query parameter (expected boolean)".to_string())))?; + // 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_annotation = req + let param_editgroup = req .get::<bodyparser::Raw>() - .map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse body parameter annotation - not valid UTF-8: {}", e))))?; + .map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse body parameter editgroup - not valid UTF-8: {}", e))))?; let mut unused_elements = Vec::new(); - let param_annotation = if let Some(param_annotation_raw) = param_annotation { - let deserializer = &mut serde_json::Deserializer::from_str(¶m_annotation_raw); + let param_editgroup = if let Some(param_editgroup_raw) = param_editgroup { + let deserializer = &mut serde_json::Deserializer::from_str(¶m_editgroup_raw); - let param_annotation: Option<models::EditgroupAnnotation> = serde_ignored::deserialize(deserializer, |path| { + 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 annotation - doesn't match schema: {}", e))))?; + .map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse body parameter editgroup - doesn't match schema: {}", e))))?; - param_annotation + param_editgroup } else { None }; - let param_annotation = param_annotation.ok_or_else(|| Response::with((status::BadRequest, "Missing required body parameter annotation".to_string())))?; + let param_editgroup = param_editgroup.ok_or_else(|| Response::with((status::BadRequest, "Missing required body parameter editgroup".to_string())))?; - match api.create_editgroup_annotation(param_editgroup_id, param_annotation, context).wait() { + match api.update_editgroup(param_editgroup_id, param_editgroup, param_submit, context).wait() { Ok(rsp) => match rsp { - CreateEditgroupAnnotationResponse::Created(body) => { + UpdateEditgroupResponse::UpdatedEditgroup(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_ANNOTATION_CREATED.clone())); + let mut response = Response::with((status::Status::from_u16(200), body_string)); + response.headers.set(ContentType(mimetypes::responses::UPDATE_EDITGROUP_UPDATED_EDITGROUP.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); if !unused_elements.is_empty() { @@ -3868,11 +3885,11 @@ where } Ok(response) } - CreateEditgroupAnnotationResponse::BadRequest(body) => { + UpdateEditgroupResponse::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_EDITGROUP_ANNOTATION_BAD_REQUEST.clone())); + response.headers.set(ContentType(mimetypes::responses::UPDATE_EDITGROUP_BAD_REQUEST.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); if !unused_elements.is_empty() { @@ -3880,14 +3897,14 @@ where } Ok(response) } - CreateEditgroupAnnotationResponse::NotAuthorized { body, www_authenticate } => { + UpdateEditgroupResponse::NotAuthorized { body, www_authenticate } => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(401), body_string)); header! { (ResponseWwwAuthenticate, "WWW_Authenticate") => [String] } response.headers.set(ResponseWwwAuthenticate(www_authenticate)); - response.headers.set(ContentType(mimetypes::responses::CREATE_EDITGROUP_ANNOTATION_NOT_AUTHORIZED.clone())); + response.headers.set(ContentType(mimetypes::responses::UPDATE_EDITGROUP_NOT_AUTHORIZED.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); if !unused_elements.is_empty() { @@ -3895,11 +3912,11 @@ where } Ok(response) } - CreateEditgroupAnnotationResponse::Forbidden(body) => { + UpdateEditgroupResponse::Forbidden(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(403), body_string)); - response.headers.set(ContentType(mimetypes::responses::CREATE_EDITGROUP_ANNOTATION_FORBIDDEN.clone())); + response.headers.set(ContentType(mimetypes::responses::UPDATE_EDITGROUP_FORBIDDEN.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); if !unused_elements.is_empty() { @@ -3907,11 +3924,11 @@ where } Ok(response) } - CreateEditgroupAnnotationResponse::NotFound(body) => { + UpdateEditgroupResponse::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_EDITGROUP_ANNOTATION_NOT_FOUND.clone())); + response.headers.set(ContentType(mimetypes::responses::UPDATE_EDITGROUP_NOT_FOUND.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); if !unused_elements.is_empty() { @@ -3919,11 +3936,11 @@ where } Ok(response) } - CreateEditgroupAnnotationResponse::GenericError(body) => { + UpdateEditgroupResponse::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_ANNOTATION_GENERIC_ERROR.clone())); + response.headers.set(ContentType(mimetypes::responses::UPDATE_EDITGROUP_GENERIC_ERROR.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); if !unused_elements.is_empty() { @@ -3945,85 +3962,12 @@ where Ok(response) }) }, - "CreateEditgroupAnnotation", - ); - - let api_clone = api.clone(); - router.get( - "/v0/changelog", - 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>(); - - // 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| Some(x.parse::<i64>())) - .map_or_else(|| Ok(None), |x| x.map(|v| Some(v))) - .map_err(|x| Response::with((status::BadRequest, "unparsable query parameter (expected integer)".to_string())))?; - - match api.get_changelog(param_limit, context).wait() { - Ok(rsp) => match rsp { - 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_CHANGELOG_SUCCESS.clone())); - - context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); - - Ok(response) - } - GetChangelogResponse::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_CHANGELOG_BAD_REQUEST.clone())); - - context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); - - Ok(response) - } - 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_CHANGELOG_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) - }) - }, - "GetChangelog", + "UpdateEditgroup", ); let api_clone = api.clone(); router.get( - "/v0/changelog/:index", + "/v0/editor/:editor_id", move |req: &mut Request| { let mut context = Context::default(); @@ -4037,57 +3981,57 @@ where context.authorization = req.extensions.remove::<Authorization>(); // Path parameters - let param_index = { + let param_editor_id = { let param = req .extensions .get::<Router>() .ok_or_else(|| Response::with((status::InternalServerError, "An internal error occurred".to_string())))? - .find("index") - .ok_or_else(|| Response::with((status::BadRequest, "Missing path parameter index".to_string())))?; + .find("editor_id") + .ok_or_else(|| Response::with((status::BadRequest, "Missing path parameter editor_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 index: {}", e))))? + .map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse path parameter editor_id: {}", e))))? }; - match api.get_changelog_entry(param_index, context).wait() { + match api.get_editor(param_editor_id, context).wait() { Ok(rsp) => match rsp { - GetChangelogEntryResponse::FoundChangelogEntry(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::GET_CHANGELOG_ENTRY_FOUND_CHANGELOG_ENTRY.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) } - GetChangelogEntryResponse::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::GET_CHANGELOG_ENTRY_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) } - GetChangelogEntryResponse::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::GET_CHANGELOG_ENTRY_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) } - GetChangelogEntryResponse::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::GET_CHANGELOG_ENTRY_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()))); @@ -4107,12 +4051,12 @@ where Ok(response) }) }, - "GetChangelogEntry", + "GetEditor", ); let api_clone = api.clone(); router.get( - "/v0/editgroup/:editgroup_id", + "/v0/editor/:editor_id/annotations", move |req: &mut Request| { let mut context = Context::default(); @@ -4126,57 +4070,101 @@ where context.authorization = req.extensions.remove::<Authorization>(); // Path parameters - let param_editgroup_id = { + let param_editor_id = { let param = req .extensions .get::<Router>() .ok_or_else(|| Response::with((status::InternalServerError, "An internal error occurred".to_string())))? - .find("editgroup_id") - .ok_or_else(|| Response::with((status::BadRequest, "Missing path parameter editgroup_id".to_string())))?; + .find("editor_id") + .ok_or_else(|| Response::with((status::BadRequest, "Missing path parameter editor_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 editgroup_id: {}", e))))? + .map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse path parameter editor_id: {}", e))))? }; - match api.get_editgroup(param_editgroup_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_limit = query_params + .get("limit") + .and_then(|list| list.first()) + .and_then(|x| Some(x.parse::<i64>())) + .map_or_else(|| Ok(None), |x| x.map(|v| Some(v))) + .map_err(|x| Response::with((status::BadRequest, "unparsable query parameter (expected integer)".to_string())))?; + let param_before = query_params + .get("before") + .and_then(|list| list.first()) + .and_then(|x| Some(x.parse::<chrono::DateTime<chrono::Utc>>())) + .map_or_else(|| Ok(None), |x| x.map(|v| Some(v))) + .map_err(|x| Response::with((status::BadRequest, "unparsable query parameter (expected UTC datetime in ISO/RFC format)".to_string())))?; + let param_since = query_params + .get("since") + .and_then(|list| list.first()) + .and_then(|x| Some(x.parse::<chrono::DateTime<chrono::Utc>>())) + .map_or_else(|| Ok(None), |x| x.map(|v| Some(v))) + .map_err(|x| Response::with((status::BadRequest, "unparsable query parameter (expected UTC datetime in ISO/RFC format)".to_string())))?; + + match api.get_editor_annotations(param_editor_id, param_limit, param_before, param_since, context).wait() { Ok(rsp) => match rsp { - GetEditgroupResponse::Found(body) => { + GetEditorAnnotationsResponse::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_EDITGROUP_FOUND.clone())); + response.headers.set(ContentType(mimetypes::responses::GET_EDITOR_ANNOTATIONS_SUCCESS.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); Ok(response) } - GetEditgroupResponse::BadRequest(body) => { + GetEditorAnnotationsResponse::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::GET_EDITOR_ANNOTATIONS_BAD_REQUEST.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); Ok(response) } - GetEditgroupResponse::NotFound(body) => { + GetEditorAnnotationsResponse::NotAuthorized { body, www_authenticate } => { + let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); + + let mut response = Response::with((status::Status::from_u16(401), body_string)); + header! { (ResponseWwwAuthenticate, "WWW_Authenticate") => [String] } + response.headers.set(ResponseWwwAuthenticate(www_authenticate)); + + response.headers.set(ContentType(mimetypes::responses::GET_EDITOR_ANNOTATIONS_NOT_AUTHORIZED.clone())); + + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + + Ok(response) + } + GetEditorAnnotationsResponse::Forbidden(body) => { + let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); + + let mut response = Response::with((status::Status::from_u16(403), body_string)); + response.headers.set(ContentType(mimetypes::responses::GET_EDITOR_ANNOTATIONS_FORBIDDEN.clone())); + + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + + Ok(response) + } + GetEditorAnnotationsResponse::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::GET_EDITOR_ANNOTATIONS_NOT_FOUND.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); Ok(response) } - GetEditgroupResponse::GenericError(body) => { + GetEditorAnnotationsResponse::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::GET_EDITOR_ANNOTATIONS_GENERIC_ERROR.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); @@ -4196,12 +4184,12 @@ where Ok(response) }) }, - "GetEditgroup", + "GetEditorAnnotations", ); let api_clone = api.clone(); router.get( - "/v0/editgroup/:editgroup_id/annotations", + "/v0/editor/:editor_id/editgroups", move |req: &mut Request| { let mut context = Context::default(); @@ -4215,84 +4203,78 @@ where context.authorization = req.extensions.remove::<Authorization>(); // Path parameters - let param_editgroup_id = { + let param_editor_id = { let param = req .extensions .get::<Router>() .ok_or_else(|| Response::with((status::InternalServerError, "An internal error occurred".to_string())))? - .find("editgroup_id") - .ok_or_else(|| Response::with((status::BadRequest, "Missing path parameter editgroup_id".to_string())))?; + .find("editor_id") + .ok_or_else(|| Response::with((status::BadRequest, "Missing path parameter editor_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 editgroup_id: {}", e))))? + .map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse path parameter editor_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| Some(x.parse::<i64>())) + .map_or_else(|| Ok(None), |x| x.map(|v| Some(v))) + .map_err(|x| Response::with((status::BadRequest, "unparsable query parameter (expected integer)".to_string())))?; + let param_before = query_params + .get("before") + .and_then(|list| list.first()) + .and_then(|x| Some(x.parse::<chrono::DateTime<chrono::Utc>>())) + .map_or_else(|| Ok(None), |x| x.map(|v| Some(v))) + .map_err(|x| Response::with((status::BadRequest, "unparsable query parameter (expected UTC datetime in ISO/RFC format)".to_string())))?; + let param_since = query_params + .get("since") + .and_then(|list| list.first()) + .and_then(|x| Some(x.parse::<chrono::DateTime<chrono::Utc>>())) + .map_or_else(|| Ok(None), |x| x.map(|v| Some(v))) + .map_err(|x| Response::with((status::BadRequest, "unparsable query parameter (expected UTC datetime in ISO/RFC format)".to_string())))?; - match api.get_editgroup_annotations(param_editgroup_id, param_expand, context).wait() { + match api.get_editor_editgroups(param_editor_id, param_limit, param_before, param_since, context).wait() { Ok(rsp) => match rsp { - GetEditgroupAnnotationsResponse::Success(body) => { + GetEditorEditgroupsResponse::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_EDITGROUP_ANNOTATIONS_SUCCESS.clone())); + response.headers.set(ContentType(mimetypes::responses::GET_EDITOR_EDITGROUPS_FOUND.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); Ok(response) } - GetEditgroupAnnotationsResponse::BadRequest(body) => { + GetEditorEditgroupsResponse::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_ANNOTATIONS_BAD_REQUEST.clone())); - - context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); - - Ok(response) - } - GetEditgroupAnnotationsResponse::NotAuthorized { body, www_authenticate } => { - let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); - - let mut response = Response::with((status::Status::from_u16(401), body_string)); - header! { (ResponseWwwAuthenticate, "WWW_Authenticate") => [String] } - response.headers.set(ResponseWwwAuthenticate(www_authenticate)); - - response.headers.set(ContentType(mimetypes::responses::GET_EDITGROUP_ANNOTATIONS_NOT_AUTHORIZED.clone())); - - context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); - - Ok(response) - } - GetEditgroupAnnotationsResponse::Forbidden(body) => { - let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); - - let mut response = Response::with((status::Status::from_u16(403), body_string)); - response.headers.set(ContentType(mimetypes::responses::GET_EDITGROUP_ANNOTATIONS_FORBIDDEN.clone())); + response.headers.set(ContentType(mimetypes::responses::GET_EDITOR_EDITGROUPS_BAD_REQUEST.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); Ok(response) } - GetEditgroupAnnotationsResponse::NotFound(body) => { + GetEditorEditgroupsResponse::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_ANNOTATIONS_NOT_FOUND.clone())); + response.headers.set(ContentType(mimetypes::responses::GET_EDITOR_EDITGROUPS_NOT_FOUND.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); Ok(response) } - GetEditgroupAnnotationsResponse::GenericError(body) => { + GetEditorEditgroupsResponse::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_ANNOTATIONS_GENERIC_ERROR.clone())); + response.headers.set(ContentType(mimetypes::responses::GET_EDITOR_EDITGROUPS_GENERIC_ERROR.clone())); context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); @@ -4312,12 +4294,12 @@ where Ok(response) }) }, - "GetEditgroupAnnotations", + "GetEditorEditgroups", ); let api_clone = api.clone(); - router.get( - "/v0/editor/:editor_id/annotations", + router.put( + "/v0/editor/:editor_id", move |req: &mut Request| { let mut context = Context::default(); @@ -4330,6 +4312,8 @@ where context.auth_data = req.extensions.remove::<AuthData>(); context.authorization = req.extensions.remove::<Authorization>(); + let authorization = context.authorization.as_ref().ok_or_else(|| Response::with((status::Forbidden, "Unauthenticated".to_string())))?; + // Path parameters let param_editor_id = { let param = req @@ -4345,90 +4329,106 @@ where .map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse path parameter editor_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| Some(x.parse::<i64>())) - .map_or_else(|| Ok(None), |x| x.map(|v| Some(v))) - .map_err(|x| Response::with((status::BadRequest, "unparsable query parameter (expected integer)".to_string())))?; - let param_before = query_params - .get("before") - .and_then(|list| list.first()) - .and_then(|x| Some(x.parse::<chrono::DateTime<chrono::Utc>>())) - .map_or_else(|| Ok(None), |x| x.map(|v| Some(v))) - .map_err(|x| Response::with((status::BadRequest, "unparsable query parameter (expected UTC datetime in ISO/RFC format)".to_string())))?; - let param_since = query_params - .get("since") - .and_then(|list| list.first()) - .and_then(|x| Some(x.parse::<chrono::DateTime<chrono::Utc>>())) - .map_or_else(|| Ok(None), |x| x.map(|v| Some(v))) - .map_err(|x| Response::with((status::BadRequest, "unparsable query parameter (expected UTC datetime in ISO/RFC format)".to_string())))?; + // 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_editor_annotations(param_editor_id, param_limit, param_before, param_since, context).wait() { + let param_editor = req + .get::<bodyparser::Raw>() + .map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse body parameter editor - not valid UTF-8: {}", e))))?; + + let mut unused_elements = Vec::new(); + + let param_editor = if let Some(param_editor_raw) = param_editor { + let deserializer = &mut serde_json::Deserializer::from_str(¶m_editor_raw); + + let param_editor: Option<models::Editor> = 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 editor - doesn't match schema: {}", e))))?; + + param_editor + } else { + None + }; + let param_editor = param_editor.ok_or_else(|| Response::with((status::BadRequest, "Missing required body parameter editor".to_string())))?; + + match api.update_editor(param_editor_id, param_editor, context).wait() { Ok(rsp) => match rsp { - GetEditorAnnotationsResponse::Success(body) => { + UpdateEditorResponse::UpdatedEditor(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_ANNOTATIONS_SUCCESS.clone())); + response.headers.set(ContentType(mimetypes::responses::UPDATE_EDITOR_UPDATED_EDITOR.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) } - GetEditorAnnotationsResponse::BadRequest(body) => { + UpdateEditorResponse::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_ANNOTATIONS_BAD_REQUEST.clone())); + response.headers.set(ContentType(mimetypes::responses::UPDATE_EDITOR_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) } - GetEditorAnnotationsResponse::NotAuthorized { body, www_authenticate } => { + UpdateEditorResponse::NotAuthorized { body, www_authenticate } => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(401), body_string)); header! { (ResponseWwwAuthenticate, "WWW_Authenticate") => [String] } response.headers.set(ResponseWwwAuthenticate(www_authenticate)); - response.headers.set(ContentType(mimetypes::responses::GET_EDITOR_ANNOTATIONS_NOT_AUTHORIZED.clone())); + response.headers.set(ContentType(mimetypes::responses::UPDATE_EDITOR_NOT_AUTHORIZED.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) } - GetEditorAnnotationsResponse::Forbidden(body) => { + UpdateEditorResponse::Forbidden(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); let mut response = Response::with((status::Status::from_u16(403), body_string)); - response.headers.set(ContentType(mimetypes::responses::GET_EDITOR_ANNOTATIONS_FORBIDDEN.clone())); + response.headers.set(ContentType(mimetypes::responses::UPDATE_EDITOR_FORBIDDEN.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) } - GetEditorAnnotationsResponse::NotFound(body) => { + UpdateEditorResponse::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_ANNOTATIONS_NOT_FOUND.clone())); + response.headers.set(ContentType(mimetypes::responses::UPDATE_EDITOR_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) } - GetEditorAnnotationsResponse::GenericError(body) => { + UpdateEditorResponse::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_ANNOTATIONS_GENERIC_ERROR.clone())); + response.headers.set(ContentType(mimetypes::responses::UPDATE_EDITOR_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) } }, @@ -4445,7 +4445,7 @@ where Ok(response) }) }, - "GetEditorAnnotations", + "UpdateEditor", ); let api_clone = api.clone(); @@ -7156,157 +7156,6 @@ where ); let api_clone = api.clone(); - router.post( - "/v0/editgroup/:editgroup_id/work", - 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>(); - - let authorization = context.authorization.as_ref().ok_or_else(|| Response::with((status::Forbidden, "Unauthenticated".to_string())))?; - - // Path parameters - let param_editgroup_id = { - let param = req - .extensions - .get::<Router>() - .ok_or_else(|| Response::with((status::InternalServerError, "An internal error occurred".to_string())))? - .find("editgroup_id") - .ok_or_else(|| Response::with((status::BadRequest, "Missing path parameter editgroup_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 editgroup_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. - - 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_editgroup_id, param_entity, context).wait() { - Ok(rsp) => match rsp { - 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(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) - } - 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::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) - } - CreateWorkResponse::NotAuthorized { body, www_authenticate } => { - let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); - - let mut response = Response::with((status::Status::from_u16(401), body_string)); - header! { (ResponseWwwAuthenticate, "WWW_Authenticate") => [String] } - response.headers.set(ResponseWwwAuthenticate(www_authenticate)); - - response.headers.set(ContentType(mimetypes::responses::CREATE_WORK_NOT_AUTHORIZED.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::Forbidden(body) => { - let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); - - let mut response = Response::with((status::Status::from_u16(403), body_string)); - response.headers.set(ContentType(mimetypes::responses::CREATE_WORK_FORBIDDEN.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) => { - 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())); - - 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) => { - 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())); - - 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) - } - }, - 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) - }) - }, - "CreateWork", - ); - - let api_clone = api.clone(); router.delete( "/v0/editgroup/:editgroup_id/release/:ident", move |req: &mut Request| { @@ -9744,6 +9593,157 @@ where let api_clone = api.clone(); router.post( + "/v0/editgroup/:editgroup_id/work", + 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>(); + + let authorization = context.authorization.as_ref().ok_or_else(|| Response::with((status::Forbidden, "Unauthenticated".to_string())))?; + + // Path parameters + let param_editgroup_id = { + let param = req + .extensions + .get::<Router>() + .ok_or_else(|| Response::with((status::InternalServerError, "An internal error occurred".to_string())))? + .find("editgroup_id") + .ok_or_else(|| Response::with((status::BadRequest, "Missing path parameter editgroup_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 editgroup_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. + + 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_editgroup_id, param_entity, context).wait() { + Ok(rsp) => match rsp { + 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(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) + } + 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::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) + } + CreateWorkResponse::NotAuthorized { body, www_authenticate } => { + let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); + + let mut response = Response::with((status::Status::from_u16(401), body_string)); + header! { (ResponseWwwAuthenticate, "WWW_Authenticate") => [String] } + response.headers.set(ResponseWwwAuthenticate(www_authenticate)); + + response.headers.set(ContentType(mimetypes::responses::CREATE_WORK_NOT_AUTHORIZED.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::Forbidden(body) => { + let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); + + let mut response = Response::with((status::Status::from_u16(403), body_string)); + response.headers.set(ContentType(mimetypes::responses::CREATE_WORK_FORBIDDEN.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) => { + 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())); + + 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) => { + 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())); + + 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) + } + }, + 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) + }) + }, + "CreateWork", + ); + + let api_clone = api.clone(); + router.post( "/v0/editgroup/auto/work/batch", move |req: &mut Request| { let mut context = Context::default(); |