Skip to main content

rskit_auth/
outcome.rs

1//! Typed authentication outcomes for request middleware.
2
3/// Policy for requests that do not include credentials.
4#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
5#[non_exhaustive]
6pub enum MissingCredentialPolicy {
7    /// Reject requests with missing credentials.
8    #[default]
9    RejectMissing,
10    /// Allow requests with missing credentials and expose [`AuthOutcome::Missing`].
11    AcceptMissing,
12}
13
14/// Result of request authentication.
15#[derive(Debug, Clone, PartialEq, Eq)]
16#[non_exhaustive]
17pub enum AuthOutcome<C> {
18    /// Credentials were present and valid.
19    Authenticated(C),
20    /// Credentials were absent and the middleware was configured with
21    /// [`MissingCredentialPolicy::AcceptMissing`].
22    Missing,
23}
24
25impl<C> AuthOutcome<C> {
26    /// Return the authenticated claims when present.
27    #[must_use]
28    pub const fn claims(&self) -> Option<&C> {
29        match self {
30            Self::Authenticated(claims) => Some(claims),
31            Self::Missing => None,
32        }
33    }
34
35    /// Return `true` when credentials were absent and accepted by policy.
36    #[must_use]
37    pub const fn is_missing(&self) -> bool {
38        matches!(self, Self::Missing)
39    }
40}
41
42#[cfg(test)]
43mod tests {
44    use super::{AuthOutcome, MissingCredentialPolicy};
45
46    #[test]
47    fn missing_policy_rejects_missing_by_default() {
48        assert_eq!(
49            MissingCredentialPolicy::default(),
50            MissingCredentialPolicy::RejectMissing
51        );
52    }
53
54    #[test]
55    fn auth_outcome_exposes_claims_only_when_authenticated() {
56        let authenticated = AuthOutcome::Authenticated("claims");
57        assert_eq!(authenticated.claims(), Some(&"claims"));
58        assert!(!authenticated.is_missing());
59
60        let missing = AuthOutcome::<&str>::Missing;
61        assert_eq!(missing.claims(), None);
62        assert!(missing.is_missing());
63    }
64}