use bon::Builder;
use serde::Serialize;
use crate::{
core::{server_metadata::AuthorizationServerMetadata, token::RefreshToken},
grant::core::{OAuth2ExchangeGrant, mk_scopes},
};
#[huskarl_macros::grant]
#[derive(Debug, Clone, Builder)]
#[builder(state_mod(name = "builder"), on(String, into))]
pub struct RefreshGrant {}
impl<
Auth: crate::core::client_auth::ClientAuthentication + 'static,
D: crate::core::dpop::AuthorizationServerDPoP + 'static,
> RefreshGrant<Auth, D>
{
pub fn builder_from_metadata(
metadata: &AuthorizationServerMetadata,
) -> RefreshGrantBuilder<Auth, D, SetCommonMetadata> {
RefreshGrant::builder().with_common_metadata(metadata)
}
}
#[huskarl_macros::grant_impl]
impl<
Auth: crate::core::client_auth::ClientAuthentication + 'static,
D: crate::core::dpop::AuthorizationServerDPoP + 'static,
> OAuth2ExchangeGrant for RefreshGrant<Auth, D>
{
type Parameters = RefreshGrantParameters;
type ClientAuth = Auth;
type DPoP = D;
type Form<'a> = RefreshGrantForm;
fn to_refresh_grant(&self) -> RefreshGrant<Auth, D> {
self.clone()
}
fn build_form(&self, params: Self::Parameters) -> Self::Form<'_> {
RefreshGrantForm {
grant_type: "refresh_token",
refresh_token: params.refresh_token,
scope: params.scope,
resource: params.resource,
}
}
}
#[derive(Debug, Clone, Builder)]
pub struct RefreshGrantParameters {
refresh_token: RefreshToken,
#[builder(required, default, name = "scopes", with = |scopes: impl IntoIterator<Item = impl Into<String>>| mk_scopes(scopes))]
scope: Option<String>,
resource: Option<Vec<String>>,
}
impl RefreshGrantParameters {
#[must_use]
pub fn refresh_token(token: RefreshToken) -> Self {
Self::builder().refresh_token(token).build()
}
}
#[derive(Debug, Serialize)]
pub struct RefreshGrantForm {
grant_type: &'static str,
refresh_token: RefreshToken,
#[serde(skip_serializing_if = "Option::is_none")]
scope: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
resource: Option<Vec<String>>,
}