From 2ff1adeeb85c23df1dd6de3c2dd9ebede2a04954 Mon Sep 17 00:00:00 2001 From: Bryan Newbold Date: Thu, 3 Jan 2019 16:52:42 -0800 Subject: crude /auth/oidc endpoint (and codegen) --- rust/fatcat-api-spec/src/client.rs | 118 ++++++++++++++++++++--- rust/fatcat-api-spec/src/lib.rs | 26 +++++ rust/fatcat-api-spec/src/mimetypes.rs | 32 +++++++ rust/fatcat-api-spec/src/models.rs | 57 ++++++++++- rust/fatcat-api-spec/src/server.rs | 172 +++++++++++++++++++++++++++++++--- 5 files changed, 380 insertions(+), 25 deletions(-) (limited to 'rust/fatcat-api-spec/src') diff --git a/rust/fatcat-api-spec/src/client.rs b/rust/fatcat-api-spec/src/client.rs index b67e193a..44bcd54d 100644 --- a/rust/fatcat-api-spec/src/client.rs +++ b/rust/fatcat-api-spec/src/client.rs @@ -35,18 +35,18 @@ use swagger::{ApiError, Context, XSpanId}; use models; use { - AcceptEditgroupResponse, Api, CreateContainerBatchResponse, CreateContainerResponse, CreateCreatorBatchResponse, CreateCreatorResponse, CreateEditgroupResponse, CreateFileBatchResponse, - CreateFileResponse, CreateFilesetBatchResponse, CreateFilesetResponse, CreateReleaseBatchResponse, CreateReleaseResponse, CreateWebcaptureBatchResponse, CreateWebcaptureResponse, - CreateWorkBatchResponse, CreateWorkResponse, DeleteContainerEditResponse, DeleteContainerResponse, DeleteCreatorEditResponse, DeleteCreatorResponse, DeleteFileEditResponse, DeleteFileResponse, - DeleteFilesetEditResponse, DeleteFilesetResponse, DeleteReleaseEditResponse, DeleteReleaseResponse, DeleteWebcaptureEditResponse, DeleteWebcaptureResponse, DeleteWorkEditResponse, - DeleteWorkResponse, GetChangelogEntryResponse, GetChangelogResponse, GetContainerEditResponse, GetContainerHistoryResponse, GetContainerRedirectsResponse, GetContainerResponse, - GetContainerRevisionResponse, GetCreatorEditResponse, GetCreatorHistoryResponse, GetCreatorRedirectsResponse, GetCreatorReleasesResponse, GetCreatorResponse, GetCreatorRevisionResponse, - GetEditgroupResponse, GetEditorChangelogResponse, GetEditorResponse, GetFileEditResponse, GetFileHistoryResponse, GetFileRedirectsResponse, GetFileResponse, GetFileRevisionResponse, - GetFilesetEditResponse, GetFilesetHistoryResponse, GetFilesetRedirectsResponse, GetFilesetResponse, GetFilesetRevisionResponse, GetReleaseEditResponse, GetReleaseFilesResponse, - GetReleaseFilesetsResponse, GetReleaseHistoryResponse, GetReleaseRedirectsResponse, GetReleaseResponse, GetReleaseRevisionResponse, GetReleaseWebcapturesResponse, GetWebcaptureEditResponse, - GetWebcaptureHistoryResponse, GetWebcaptureRedirectsResponse, GetWebcaptureResponse, GetWebcaptureRevisionResponse, GetWorkEditResponse, GetWorkHistoryResponse, GetWorkRedirectsResponse, - GetWorkReleasesResponse, GetWorkResponse, GetWorkRevisionResponse, LookupContainerResponse, LookupCreatorResponse, LookupFileResponse, LookupReleaseResponse, UpdateContainerResponse, - UpdateCreatorResponse, UpdateFileResponse, UpdateFilesetResponse, UpdateReleaseResponse, UpdateWebcaptureResponse, UpdateWorkResponse, + AcceptEditgroupResponse, Api, AuthOidcResponse, CreateContainerBatchResponse, CreateContainerResponse, CreateCreatorBatchResponse, CreateCreatorResponse, CreateEditgroupResponse, + CreateFileBatchResponse, CreateFileResponse, CreateFilesetBatchResponse, CreateFilesetResponse, CreateReleaseBatchResponse, CreateReleaseResponse, CreateWebcaptureBatchResponse, + CreateWebcaptureResponse, CreateWorkBatchResponse, CreateWorkResponse, DeleteContainerEditResponse, DeleteContainerResponse, DeleteCreatorEditResponse, DeleteCreatorResponse, + DeleteFileEditResponse, DeleteFileResponse, DeleteFilesetEditResponse, DeleteFilesetResponse, DeleteReleaseEditResponse, DeleteReleaseResponse, DeleteWebcaptureEditResponse, + DeleteWebcaptureResponse, DeleteWorkEditResponse, DeleteWorkResponse, GetChangelogEntryResponse, GetChangelogResponse, GetContainerEditResponse, GetContainerHistoryResponse, + GetContainerRedirectsResponse, GetContainerResponse, GetContainerRevisionResponse, GetCreatorEditResponse, GetCreatorHistoryResponse, GetCreatorRedirectsResponse, GetCreatorReleasesResponse, + GetCreatorResponse, GetCreatorRevisionResponse, GetEditgroupResponse, GetEditorChangelogResponse, GetEditorResponse, GetFileEditResponse, GetFileHistoryResponse, GetFileRedirectsResponse, + GetFileResponse, GetFileRevisionResponse, GetFilesetEditResponse, GetFilesetHistoryResponse, GetFilesetRedirectsResponse, GetFilesetResponse, GetFilesetRevisionResponse, GetReleaseEditResponse, + GetReleaseFilesResponse, GetReleaseFilesetsResponse, GetReleaseHistoryResponse, GetReleaseRedirectsResponse, GetReleaseResponse, GetReleaseRevisionResponse, GetReleaseWebcapturesResponse, + GetWebcaptureEditResponse, GetWebcaptureHistoryResponse, GetWebcaptureRedirectsResponse, GetWebcaptureResponse, GetWebcaptureRevisionResponse, GetWorkEditResponse, GetWorkHistoryResponse, + GetWorkRedirectsResponse, GetWorkReleasesResponse, GetWorkResponse, GetWorkRevisionResponse, LookupContainerResponse, LookupCreatorResponse, LookupFileResponse, LookupReleaseResponse, + UpdateContainerResponse, UpdateCreatorResponse, UpdateFileResponse, UpdateFilesetResponse, UpdateReleaseResponse, UpdateWebcaptureResponse, UpdateWorkResponse, }; /// Convert input into a base path, e.g. "http://example:123". Also checks the scheme as it goes. @@ -2030,6 +2030,100 @@ impl Api for Client { Box::new(futures::done(result)) } + fn auth_oidc(&self, param_oidc_params: models::AuthOidc, context: &Context) -> Box + Send> { + let url = format!("{}/v0/auth/oidc", self.base_path); + + let body = serde_json::to_string(¶m_oidc_params).expect("impossible to fail to serialize"); + + let hyper_client = (self.hyper_client)(); + let request = hyper_client.request(hyper::method::Method::Post, &url); + let mut custom_headers = hyper::header::Headers::new(); + + let request = request.body(&body); + + custom_headers.set(ContentType(mimetypes::requests::AUTH_OIDC.clone())); + context.x_span_id.as_ref().map(|header| custom_headers.set(XSpanId(header.clone()))); + + let request = request.headers(custom_headers); + + // Helper function to provide a code block to use `?` in (to be replaced by the `catch` block when it exists). + fn parse_response(mut response: hyper::client::response::Response) -> Result { + match response.status.to_u16() { + 200 => { + let mut buf = String::new(); + response.read_to_string(&mut buf).map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?; + let body = serde_json::from_str::(&buf)?; + + Ok(AuthOidcResponse::Found(body)) + } + 201 => { + let mut buf = String::new(); + response.read_to_string(&mut buf).map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?; + let body = serde_json::from_str::(&buf)?; + + Ok(AuthOidcResponse::Created(body)) + } + 400 => { + let mut buf = String::new(); + response.read_to_string(&mut buf).map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?; + let body = serde_json::from_str::(&buf)?; + + Ok(AuthOidcResponse::BadRequest(body)) + } + 401 => { + let mut buf = String::new(); + response.read_to_string(&mut buf).map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?; + let body = serde_json::from_str::(&buf)?; + header! { (ResponseWwwAuthenticate, "WWW_Authenticate") => [String] } + let response_www_authenticate = response + .headers + .get::() + .ok_or_else(|| "Required response header WWW_Authenticate for response 401 was not found.")?; + + Ok(AuthOidcResponse::NotAuthorized { + body: body, + www_authenticate: response_www_authenticate.0.clone(), + }) + } + 403 => { + let mut buf = String::new(); + response.read_to_string(&mut buf).map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?; + let body = serde_json::from_str::(&buf)?; + + Ok(AuthOidcResponse::Forbidden(body)) + } + 409 => { + let mut buf = String::new(); + response.read_to_string(&mut buf).map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?; + let body = serde_json::from_str::(&buf)?; + + Ok(AuthOidcResponse::Conflict(body)) + } + 500 => { + let mut buf = String::new(); + response.read_to_string(&mut buf).map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?; + let body = serde_json::from_str::(&buf)?; + + Ok(AuthOidcResponse::GenericError(body)) + } + code => { + let mut buf = [0; 100]; + let debug_body = match response.read(&mut buf) { + Ok(len) => match str::from_utf8(&buf[..len]) { + Ok(body) => Cow::from(body), + Err(_) => Cow::from(format!("", &buf[..len].to_vec())), + }, + Err(e) => Cow::from(format!("", e)), + }; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, response.headers, debug_body))) + } + } + } + + let result = request.send().map_err(|e| ApiError(format!("No response received: {}", e))).and_then(parse_response); + Box::new(futures::done(result)) + } + fn get_editor(&self, param_editor_id: String, context: &Context) -> Box + Send> { let url = format!( "{}/v0/editor/{editor_id}", diff --git a/rust/fatcat-api-spec/src/lib.rs b/rust/fatcat-api-spec/src/lib.rs index c6126c9c..c89dc90c 100644 --- a/rust/fatcat-api-spec/src/lib.rs +++ b/rust/fatcat-api-spec/src/lib.rs @@ -348,6 +348,24 @@ pub enum UpdateCreatorResponse { GenericError(models::ErrorResponse), } +#[derive(Debug, PartialEq)] +pub enum AuthOidcResponse { + /// Found + Found(models::AuthOidcResult), + /// Created + Created(models::AuthOidcResult), + /// Bad Request + BadRequest(models::ErrorResponse), + /// Not Authorized + NotAuthorized { body: models::ErrorResponse, www_authenticate: String }, + /// Forbidden + Forbidden(models::ErrorResponse), + /// Conflict + Conflict(models::ErrorResponse), + /// Generic Error + GenericError(models::ErrorResponse), +} + #[derive(Debug, PartialEq)] pub enum GetEditorResponse { /// Found @@ -1281,6 +1299,8 @@ pub trait Api { fn update_creator(&self, ident: String, entity: models::CreatorEntity, editgroup_id: Option, context: &Context) -> Box + Send>; + fn auth_oidc(&self, oidc_params: models::AuthOidc, context: &Context) -> Box + Send>; + fn get_editor(&self, editor_id: String, context: &Context) -> Box + Send>; fn get_editor_changelog(&self, editor_id: String, context: &Context) -> Box + Send>; @@ -1527,6 +1547,8 @@ pub trait ApiNoContext { fn update_creator(&self, ident: String, entity: models::CreatorEntity, editgroup_id: Option) -> Box + Send>; + fn auth_oidc(&self, oidc_params: models::AuthOidc) -> Box + Send>; + fn get_editor(&self, editor_id: String) -> Box + Send>; fn get_editor_changelog(&self, editor_id: String) -> Box + Send>; @@ -1810,6 +1832,10 @@ impl<'a, T: Api> ApiNoContext for ContextWrapper<'a, T> { self.api().update_creator(ident, entity, editgroup_id, &self.context()) } + fn auth_oidc(&self, oidc_params: models::AuthOidc) -> Box + Send> { + self.api().auth_oidc(oidc_params, &self.context()) + } + fn get_editor(&self, editor_id: String) -> Box + Send> { self.api().get_editor(editor_id, &self.context()) } diff --git a/rust/fatcat-api-spec/src/mimetypes.rs b/rust/fatcat-api-spec/src/mimetypes.rs index 77a66c46..322ab045 100644 --- a/rust/fatcat-api-spec/src/mimetypes.rs +++ b/rust/fatcat-api-spec/src/mimetypes.rs @@ -452,6 +452,34 @@ pub mod responses { lazy_static! { pub static ref UPDATE_CREATOR_GENERIC_ERROR: Mime = mime!(Application / Json); } + /// Create Mime objects for the response content types for AuthOidc + lazy_static! { + pub static ref AUTH_OIDC_FOUND: Mime = mime!(Application / Json); + } + /// Create Mime objects for the response content types for AuthOidc + lazy_static! { + pub static ref AUTH_OIDC_CREATED: Mime = mime!(Application / Json); + } + /// Create Mime objects for the response content types for AuthOidc + lazy_static! { + pub static ref AUTH_OIDC_BAD_REQUEST: Mime = mime!(Application / Json); + } + /// Create Mime objects for the response content types for AuthOidc + lazy_static! { + pub static ref AUTH_OIDC_NOT_AUTHORIZED: Mime = mime!(Application / Json); + } + /// Create Mime objects for the response content types for AuthOidc + lazy_static! { + pub static ref AUTH_OIDC_FORBIDDEN: Mime = mime!(Application / Json); + } + /// Create Mime objects for the response content types for AuthOidc + lazy_static! { + pub static ref AUTH_OIDC_CONFLICT: Mime = mime!(Application / Json); + } + /// Create Mime objects for the response content types for AuthOidc + lazy_static! { + pub static ref AUTH_OIDC_GENERIC_ERROR: Mime = mime!(Application / Json); + } /// Create Mime objects for the response content types for GetEditor lazy_static! { pub static ref GET_EDITOR_FOUND: Mime = mime!(Application / Json); @@ -1693,6 +1721,10 @@ pub mod requests { lazy_static! { pub static ref UPDATE_CREATOR: Mime = mime!(Application / Json); } + /// Create Mime objects for the request content types for AuthOidc + lazy_static! { + pub static ref AUTH_OIDC: Mime = mime!(Application / Json); + } /// Create Mime objects for the request content types for CreateEditgroup lazy_static! { pub static ref CREATE_EDITGROUP: Mime = mime!(Application / Json); diff --git a/rust/fatcat-api-spec/src/models.rs b/rust/fatcat-api-spec/src/models.rs index 4d7575b6..8c17cf66 100644 --- a/rust/fatcat-api-spec/src/models.rs +++ b/rust/fatcat-api-spec/src/models.rs @@ -9,6 +9,43 @@ use models; use std::collections::HashMap; use swagger; +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +pub struct AuthOidc { + #[serde(rename = "provider")] + pub provider: String, + + #[serde(rename = "sub")] + pub sub: String, + + #[serde(rename = "iss")] + pub iss: String, +} + +impl AuthOidc { + pub fn new(provider: String, sub: String, iss: String) -> AuthOidc { + AuthOidc { + provider: provider, + sub: sub, + iss: iss, + } + } +} + +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +pub struct AuthOidcResult { + #[serde(rename = "editor")] + pub editor: models::Editor, + + #[serde(rename = "token")] + pub token: String, +} + +impl AuthOidcResult { + pub fn new(editor: models::Editor, token: String) -> AuthOidcResult { + AuthOidcResult { editor: editor, token: token } + } +} + #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct ChangelogEntry { #[serde(rename = "index")] @@ -272,11 +309,29 @@ pub struct Editor { #[serde(rename = "username")] pub username: String, + + #[serde(rename = "is_admin")] + #[serde(skip_serializing_if = "Option::is_none")] + pub is_admin: Option, + + #[serde(rename = "is_bot")] + #[serde(skip_serializing_if = "Option::is_none")] + pub is_bot: Option, + + #[serde(rename = "is_active")] + #[serde(skip_serializing_if = "Option::is_none")] + pub is_active: Option, } impl Editor { pub fn new(username: String) -> Editor { - Editor { editor_id: None, username: username } + Editor { + editor_id: None, + username: username, + is_admin: None, + is_bot: None, + is_active: None, + } } } diff --git a/rust/fatcat-api-spec/src/server.rs b/rust/fatcat-api-spec/src/server.rs index 19e33194..8a515e43 100644 --- a/rust/fatcat-api-spec/src/server.rs +++ b/rust/fatcat-api-spec/src/server.rs @@ -37,18 +37,18 @@ use swagger::{ApiError, Context, XSpanId}; #[allow(unused_imports)] use models; use { - AcceptEditgroupResponse, Api, CreateContainerBatchResponse, CreateContainerResponse, CreateCreatorBatchResponse, CreateCreatorResponse, CreateEditgroupResponse, CreateFileBatchResponse, - CreateFileResponse, CreateFilesetBatchResponse, CreateFilesetResponse, CreateReleaseBatchResponse, CreateReleaseResponse, CreateWebcaptureBatchResponse, CreateWebcaptureResponse, - CreateWorkBatchResponse, CreateWorkResponse, DeleteContainerEditResponse, DeleteContainerResponse, DeleteCreatorEditResponse, DeleteCreatorResponse, DeleteFileEditResponse, DeleteFileResponse, - DeleteFilesetEditResponse, DeleteFilesetResponse, DeleteReleaseEditResponse, DeleteReleaseResponse, DeleteWebcaptureEditResponse, DeleteWebcaptureResponse, DeleteWorkEditResponse, - DeleteWorkResponse, GetChangelogEntryResponse, GetChangelogResponse, GetContainerEditResponse, GetContainerHistoryResponse, GetContainerRedirectsResponse, GetContainerResponse, - GetContainerRevisionResponse, GetCreatorEditResponse, GetCreatorHistoryResponse, GetCreatorRedirectsResponse, GetCreatorReleasesResponse, GetCreatorResponse, GetCreatorRevisionResponse, - GetEditgroupResponse, GetEditorChangelogResponse, GetEditorResponse, GetFileEditResponse, GetFileHistoryResponse, GetFileRedirectsResponse, GetFileResponse, GetFileRevisionResponse, - GetFilesetEditResponse, GetFilesetHistoryResponse, GetFilesetRedirectsResponse, GetFilesetResponse, GetFilesetRevisionResponse, GetReleaseEditResponse, GetReleaseFilesResponse, - GetReleaseFilesetsResponse, GetReleaseHistoryResponse, GetReleaseRedirectsResponse, GetReleaseResponse, GetReleaseRevisionResponse, GetReleaseWebcapturesResponse, GetWebcaptureEditResponse, - GetWebcaptureHistoryResponse, GetWebcaptureRedirectsResponse, GetWebcaptureResponse, GetWebcaptureRevisionResponse, GetWorkEditResponse, GetWorkHistoryResponse, GetWorkRedirectsResponse, - GetWorkReleasesResponse, GetWorkResponse, GetWorkRevisionResponse, LookupContainerResponse, LookupCreatorResponse, LookupFileResponse, LookupReleaseResponse, UpdateContainerResponse, - UpdateCreatorResponse, UpdateFileResponse, UpdateFilesetResponse, UpdateReleaseResponse, UpdateWebcaptureResponse, UpdateWorkResponse, + AcceptEditgroupResponse, Api, AuthOidcResponse, CreateContainerBatchResponse, CreateContainerResponse, CreateCreatorBatchResponse, CreateCreatorResponse, CreateEditgroupResponse, + CreateFileBatchResponse, CreateFileResponse, CreateFilesetBatchResponse, CreateFilesetResponse, CreateReleaseBatchResponse, CreateReleaseResponse, CreateWebcaptureBatchResponse, + CreateWebcaptureResponse, CreateWorkBatchResponse, CreateWorkResponse, DeleteContainerEditResponse, DeleteContainerResponse, DeleteCreatorEditResponse, DeleteCreatorResponse, + DeleteFileEditResponse, DeleteFileResponse, DeleteFilesetEditResponse, DeleteFilesetResponse, DeleteReleaseEditResponse, DeleteReleaseResponse, DeleteWebcaptureEditResponse, + DeleteWebcaptureResponse, DeleteWorkEditResponse, DeleteWorkResponse, GetChangelogEntryResponse, GetChangelogResponse, GetContainerEditResponse, GetContainerHistoryResponse, + GetContainerRedirectsResponse, GetContainerResponse, GetContainerRevisionResponse, GetCreatorEditResponse, GetCreatorHistoryResponse, GetCreatorRedirectsResponse, GetCreatorReleasesResponse, + GetCreatorResponse, GetCreatorRevisionResponse, GetEditgroupResponse, GetEditorChangelogResponse, GetEditorResponse, GetFileEditResponse, GetFileHistoryResponse, GetFileRedirectsResponse, + GetFileResponse, GetFileRevisionResponse, GetFilesetEditResponse, GetFilesetHistoryResponse, GetFilesetRedirectsResponse, GetFilesetResponse, GetFilesetRevisionResponse, GetReleaseEditResponse, + GetReleaseFilesResponse, GetReleaseFilesetsResponse, GetReleaseHistoryResponse, GetReleaseRedirectsResponse, GetReleaseResponse, GetReleaseRevisionResponse, GetReleaseWebcapturesResponse, + GetWebcaptureEditResponse, GetWebcaptureHistoryResponse, GetWebcaptureRedirectsResponse, GetWebcaptureResponse, GetWebcaptureRevisionResponse, GetWorkEditResponse, GetWorkHistoryResponse, + GetWorkRedirectsResponse, GetWorkReleasesResponse, GetWorkResponse, GetWorkRevisionResponse, LookupContainerResponse, LookupCreatorResponse, LookupFileResponse, LookupReleaseResponse, + UpdateContainerResponse, UpdateCreatorResponse, UpdateFileResponse, UpdateFilesetResponse, UpdateReleaseResponse, UpdateWebcaptureResponse, UpdateWorkResponse, }; header! { (Warning, "Warning") => [String] } @@ -2605,6 +2605,154 @@ where "UpdateCreator", ); + 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(req: &mut Request, api: &T, context: &mut Context) -> Result + where + T: Api, + { + context.x_span_id = Some(req.headers.get::().map(XSpanId::to_string).unwrap_or_else(|| self::uuid::Uuid::new_v4().to_string())); + context.auth_data = req.extensions.remove::(); + context.authorization = req.extensions.remove::(); + + 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::() + .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 = 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/editor/:editor_id", -- cgit v1.2.3