diff --git a/src/agent/config.rs b/src/agent/config.rs index 6c09c15..7d7f704 100644 --- a/src/agent/config.rs +++ b/src/agent/config.rs @@ -1,4 +1,4 @@ -use super::LoginOptions; +use super::{LoginOptions, LogoutOptions}; use crate::agent::Client; use std::time::Duration; @@ -9,7 +9,9 @@ pub struct AgentConfiguration { pub scopes: Vec, pub grace_period: Duration, pub audience: Option, - pub options: Option, + + pub default_login_options: Option, + pub default_logout_options: Option, } impl PartialEq for AgentConfiguration { @@ -17,6 +19,7 @@ impl PartialEq for AgentConfiguration { self.config == other.config && self.scopes == other.scopes && self.grace_period == other.grace_period + && self.audience == other.audience } } diff --git a/src/agent/mod.rs b/src/agent/mod.rs index 68f633e..386a1c1 100644 --- a/src/agent/mod.rs +++ b/src/agent/mod.rs @@ -140,8 +140,8 @@ where C: Client, { Configure(AgentConfiguration), - StartLogin(LoginOptions), - Logout(LogoutOptions), + StartLogin(Option), + Logout(Option), Refresh, } @@ -188,7 +188,8 @@ pub struct InnerConfig { scopes: Vec, grace_period: Duration, audience: Option, - options: Option, + default_login_options: Option, + default_logout_options: Option, } impl InnerAgent @@ -331,7 +332,8 @@ where scopes, grace_period, audience, - options, + default_login_options, + default_logout_options, } = config; let client = C::from_config(config).await?; @@ -340,7 +342,8 @@ where scopes, grace_period, audience, - options, + default_login_options, + default_logout_options, }; Ok((client, inner)) @@ -419,7 +422,7 @@ where fn post_login_redirect(&self) -> Result<(), OAuth2Error> { let config = self.config.as_ref().ok_or(OAuth2Error::NotInitialized)?; let Some(redirect_callback) = config - .options + .default_login_options .as_ref() .and_then(|opts| opts.post_login_redirect_callback.clone()) else { @@ -529,10 +532,13 @@ where self.configured(Self::make_client(config).await).await; } - fn start_login(&mut self, options: LoginOptions) -> Result<(), OAuth2Error> { + fn start_login(&mut self, options: Option) -> Result<(), OAuth2Error> { let client = self.client.as_ref().ok_or(OAuth2Error::NotInitialized)?; let config = self.config.as_ref().ok_or(OAuth2Error::NotInitialized)?; + let options = + options.unwrap_or_else(|| config.default_login_options.clone().unwrap_or_default()); + let current_url = Self::current_url().map_err(OAuth2Error::StartLogin)?; // take the parameter value first, then the agent configured value, then fall back to the default @@ -540,7 +546,7 @@ where .redirect_url .or_else(|| { config - .options + .default_login_options .as_ref() .and_then(|opts| opts.redirect_url.clone()) }) @@ -565,7 +571,7 @@ where let mut login_url = login_context.url; login_url.query_pairs_mut().extend_pairs(options.query); - if let Some(options) = &config.options { + if let Some(options) = &config.default_login_options { login_url .query_pairs_mut() .extend_pairs(options.query.clone()); @@ -586,12 +592,19 @@ where Ok(()) } - fn logout_opts(&mut self, options: LogoutOptions) { + fn logout_opts(&mut self, options: Option) { if let Some(client) = &self.client { if let Some(session_state) = self.session_state.clone() { // let the client know that log out, clients may navigate to a different // page log::debug!("Notify client of logout"); + let options = options + .or_else(|| { + self.config + .as_ref() + .and_then(|config| config.default_logout_options.clone()) + }) + .unwrap_or_default(); client.logout(session_state, options); } } @@ -618,15 +631,27 @@ where .map_err(|_| Error::NoAgent) } + fn start_login(&self) -> Result<(), Error> { + self.tx + .try_send(Msg::StartLogin(None)) + .map_err(|_| Error::NoAgent) + } + fn start_login_opts(&self, options: LoginOptions) -> Result<(), Error> { self.tx - .try_send(Msg::StartLogin(options)) + .try_send(Msg::StartLogin(Some(options))) + .map_err(|_| Error::NoAgent) + } + + fn logout(&self) -> Result<(), Error> { + self.tx + .try_send(Msg::Logout(None)) .map_err(|_| Error::NoAgent) } fn logout_opts(&self, options: LogoutOptions) -> Result<(), Error> { self.tx - .try_send(Msg::Logout(options)) + .try_send(Msg::Logout(Some(options))) .map_err(|_| Error::NoAgent) } } diff --git a/src/agent/ops.rs b/src/agent/ops.rs index 13a4771..f26a128 100644 --- a/src/agent/ops.rs +++ b/src/agent/ops.rs @@ -25,17 +25,13 @@ pub trait OAuth2Operations { fn configure(&self, config: AgentConfiguration) -> Result<(), Error>; /// Start a login flow with default options. - fn start_login(&self) -> Result<(), Error> { - self.start_login_opts(Default::default()) - } + fn start_login(&self) -> Result<(), Error>; /// Start a login flow. fn start_login_opts(&self, options: LoginOptions) -> Result<(), Error>; /// Trigger the logout with default options. - fn logout(&self) -> Result<(), Error> { - self.logout_opts(Default::default()) - } + fn logout(&self) -> Result<(), Error>; /// Trigger the logout. fn logout_opts(&self, options: LogoutOptions) -> Result<(), Error>; diff --git a/src/components/context/mod.rs b/src/components/context/mod.rs index 0576e3c..eed0850 100644 --- a/src/components/context/mod.rs +++ b/src/components/context/mod.rs @@ -5,7 +5,7 @@ mod agent; pub use agent::*; use crate::{ - agent::{AgentConfiguration, Client, LoginOptions, OAuth2Operations}, + agent::{AgentConfiguration, Client, LoginOptions, LogoutOptions, OAuth2Operations}, context::{LatestAccessToken, OAuth2Context}, }; use agent::Agent as AgentContext; @@ -36,9 +36,13 @@ pub struct OAuth2Properties { #[prop_or_default] pub children: Children, - /// Default [`LoginOptions`] that will be used for every request + /// Default [`LoginOptions`] that will be used unless more specific options have been requested. #[prop_or_default] - pub options: Option, + pub login_options: Option, + + /// Default [`LogoutOptions`] that will be used unless more specific options have been requested. + #[prop_or_default] + pub logout_options: Option, } impl PartialEq for OAuth2Properties { @@ -132,8 +136,9 @@ impl OAuth2 { config: props.config.clone(), scopes: props.scopes.clone(), grace_period: props.grace_period, - options: props.options.clone(), audience: props.audience.clone(), + default_login_options: props.login_options.clone(), + default_logout_options: props.logout_options.clone(), } } }