credence_lib/configuration/
protect.rs

1use super::super::resolve::*;
2
3use {
4    ::axum::http::HeaderMap,
5    compris::resolve::*,
6    kutil::{cli::depict::*, http::*, std::immutable::*},
7};
8
9//
10// Protect
11//
12
13/// Protect.
14#[derive(Clone, Debug, Default, Depict, Resolve)]
15pub struct Protect {
16    /// Regex.
17    ///
18    /// See [implementation syntax](https://docs.rs/regex/latest/regex/#syntax).
19    #[resolve(required)]
20    #[depict(option, as(display), style(string))]
21    pub regex: Option<ResolveRegex>,
22
23    /// Optional realm.
24    ///
25    /// Note that modern browsers do not display the realm.
26    #[resolve]
27    #[depict(option, style(string))]
28    pub realm: Option<ByteString>,
29
30    /// Username.
31    #[resolve(required)]
32    #[depict(style(string))]
33    pub username: ByteString,
34
35    /// Password.
36    #[resolve(required)]
37    #[depict(style(string))]
38    pub password: ByteString,
39}
40
41impl Protect {
42    /// True if protected.
43    pub fn protect(&self, uri_path: &str) -> bool {
44        if let Some(regex) = &self.regex
45            && regex.inner.is_match(uri_path)
46        {
47            return true;
48        }
49
50        false
51    }
52
53    /// If the request is authorized returns [None].
54    ///
55    /// Otherwise returns a `WWW-Authenticate` header value.
56    pub fn authorized(&self, headers: &HeaderMap) -> Option<ByteString> {
57        if let Some((username, password)) = headers.authorization_basic()
58            && (self.username == username)
59            && (self.password == password)
60        {
61            match &self.realm {
62                Some(realm) => tracing::debug!("authorized: {}", realm),
63                None => tracing::debug!("authorized"),
64            }
65            return None;
66        }
67
68        let authenticate = match &self.realm {
69            Some(realm) => {
70                // Note that modern browsers do not display the realm
71                tracing::debug!("unauthorized: {}", realm);
72                &format!("Basic realm=\"{}\", charset=\"UTF-8\"", realm)
73            }
74
75            None => {
76                tracing::debug!("unauthorized");
77                "Basic charset=\"UTF-8\""
78            }
79        };
80
81        Some(authenticate.into())
82    }
83}