diff options
Diffstat (limited to 'src/domain/specifications.rs')
| -rw-r--r-- | src/domain/specifications.rs | 40 |
1 files changed, 24 insertions, 16 deletions
diff --git a/src/domain/specifications.rs b/src/domain/specifications.rs index 3237d1b..76aafcc 100644 --- a/src/domain/specifications.rs +++ b/src/domain/specifications.rs @@ -22,7 +22,7 @@ impl<T> Specification<T> for AndSpecification<T> { fn is_satisfied_by(&self, candidate: &T) -> bool { self.left.is_satisfied_by(candidate) && self.right.is_satisfied_by(candidate) } - + fn reason_for_failure(&self, candidate: &T) -> Option<String> { if !self.left.is_satisfied_by(candidate) { self.left.reason_for_failure(candidate) @@ -40,7 +40,7 @@ impl Specification<OAuthClient> for ActiveClientSpecification { fn is_satisfied_by(&self, client: &OAuthClient) -> bool { client.is_active } - + fn reason_for_failure(&self, _client: &OAuthClient) -> Option<String> { Some("Client is not active".to_string()) } @@ -60,7 +60,7 @@ impl Specification<OAuthClient> for ValidRedirectUriSpecification { fn is_satisfied_by(&self, client: &OAuthClient) -> bool { client.redirect_uris.contains(&self.redirect_uri) } - + fn reason_for_failure(&self, _client: &OAuthClient) -> Option<String> { Some(format!("Invalid redirect_uri: {}", self.redirect_uri)) } @@ -78,15 +78,19 @@ impl SupportedScopesSpecification { impl Specification<OAuthClient> for SupportedScopesSpecification { fn is_satisfied_by(&self, client: &OAuthClient) -> bool { - self.requested_scopes.iter().all(|scope| client.scopes.contains(scope)) + self.requested_scopes + .iter() + .all(|scope| client.scopes.contains(scope)) } - + fn reason_for_failure(&self, client: &OAuthClient) -> Option<String> { - let unsupported: Vec<_> = self.requested_scopes.iter() + let unsupported: Vec<_> = self + .requested_scopes + .iter() .filter(|scope| !client.scopes.contains(scope)) .cloned() .collect(); - + if !unsupported.is_empty() { Some(format!("Unsupported scopes: {}", unsupported.join(", "))) } else { @@ -101,7 +105,7 @@ impl Specification<AuthorizationCode> for UnusedAuthCodeSpecification { fn is_satisfied_by(&self, code: &AuthorizationCode) -> bool { !code.is_used } - + fn reason_for_failure(&self, _code: &AuthorizationCode) -> Option<String> { Some("Authorization code has already been used".to_string()) } @@ -112,7 +116,7 @@ impl Specification<AuthorizationCode> for ValidAuthCodeSpecification { fn is_satisfied_by(&self, code: &AuthorizationCode) -> bool { chrono::Utc::now() < code.expires_at } - + fn reason_for_failure(&self, _code: &AuthorizationCode) -> Option<String> { Some("Authorization code has expired".to_string()) } @@ -132,7 +136,7 @@ impl Specification<AuthorizationCode> for MatchingClientSpecification { fn is_satisfied_by(&self, code: &AuthorizationCode) -> bool { code.client_id == self.client_id } - + fn reason_for_failure(&self, _code: &AuthorizationCode) -> Option<String> { Some("Client ID mismatch".to_string()) } @@ -153,14 +157,18 @@ impl Specification<AuthorizationCode> for ValidPkceSpecification { fn is_satisfied_by(&self, code: &AuthorizationCode) -> bool { if let Some(challenge) = &code.code_challenge { let method = code.code_challenge_method.as_deref().unwrap_or("plain"); - crate::oauth::pkce::verify_code_challenge(&self.code_verifier, challenge, - &crate::oauth::pkce::CodeChallengeMethod::from_str(method).unwrap_or(crate::oauth::pkce::CodeChallengeMethod::Plain) - ).is_ok() + crate::oauth::pkce::verify_code_challenge( + &self.code_verifier, + challenge, + &crate::oauth::pkce::CodeChallengeMethod::from_str(method) + .unwrap_or(crate::oauth::pkce::CodeChallengeMethod::Plain), + ) + .is_ok() } else { true // No PKCE required } } - + fn reason_for_failure(&self, _code: &AuthorizationCode) -> Option<String> { Some("PKCE verification failed".to_string()) } @@ -172,7 +180,7 @@ impl Specification<AccessToken> for ValidTokenSpecification { fn is_satisfied_by(&self, token: &AccessToken) -> bool { !token.is_revoked && chrono::Utc::now() < token.expires_at } - + fn reason_for_failure(&self, token: &AccessToken) -> Option<String> { if token.is_revoked { Some("Token has been revoked".to_string()) @@ -191,4 +199,4 @@ pub trait SpecificationExt<T>: Specification<T> + Sized + 'static { } } -impl<T, S: Specification<T> + 'static> SpecificationExt<T> for S {}
\ No newline at end of file +impl<T, S: Specification<T> + 'static> SpecificationExt<T> for S {} |
