use crate::common::frontend::{FrontendResponse, FrontendResponseExt, PublicOAuthError};
use serde::{ser::SerializeStruct, Serialize, Serializer};
use url::Url;
#[derive(Debug, Serialize)]
pub struct AuthorizationResponse {
#[serde(flatten, serialize_with = "serialize_result")]
pub result: Result<String, PublicOAuthError>,
#[serde(skip_serializing_if = "Option::is_none")]
pub state: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub iss: Option<String>,
#[serde(skip)]
pub redirect_uri: Url,
}
impl FrontendResponseExt for AuthorizationResponse {
fn into_frontend_response(self) -> FrontendResponse {
let Ok(url_params) = serde_urlencoded::to_string(&self) else {
return FrontendResponse::Error { error: PublicOAuthError::ServerError.into() };
};
let mut location = self.redirect_uri;
let full_params = if let Some(existing) = location.query() {
format!("{}&{}", existing, url_params)
} else {
url_params
};
location.set_query(Some(&full_params));
FrontendResponse::Redirect { location }
}
}
fn serialize_result<S>(
result: &Result<String, PublicOAuthError>,
serializer: S,
) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut state = serializer.serialize_struct("AuthorizationResult", 2)?;
match result {
Ok(code) => state.serialize_field("code", code)?,
Err(error) => {
state.serialize_field("error", &error.to_string())?;
state.serialize_field("error_description", &error.to_description())?;
}
}
state.end()
}