1use serde::Deserialize;
5use tower_http::auth::{AddAuthorizationLayer, require_authorization::Basic};
6use tower_http::validate_request::ValidateRequestHeaderLayer;
7
8use super::{AuthError, ClientAuthenticator, ServerAuthenticator};
9use crate::opaque::OpaqueString;
10
11#[derive(Debug, Deserialize, Clone, PartialEq)]
12pub struct Config {
13 username: String,
15
16 password: OpaqueString,
18}
19
20impl Default for Config {
21 fn default() -> Self {
22 Config {
23 username: "admin".to_string(),
24 password: OpaqueString::new("password"),
25 }
26 }
27}
28
29impl Config {
30 pub fn new(username: &str, password: &str) -> Self {
32 Config {
33 username: username.to_string(),
34 password: OpaqueString::new(password),
35 }
36 }
37
38 pub fn username(&self) -> &str {
40 &self.username
41 }
42
43 pub fn password(&self) -> &OpaqueString {
45 &self.password
46 }
47}
48
49impl ClientAuthenticator for Config {
50 type ClientLayer = AddAuthorizationLayer;
52
53 fn get_client_layer(&self) -> Result<Self::ClientLayer, AuthError> {
54 match (self.username(), self.password().as_ref()) {
55 ("", _) => Err(AuthError::ConfigError("username is empty".to_string())),
56 (_, "") => Err(AuthError::ConfigError("password is empty".to_string())),
57 _ => Ok(AddAuthorizationLayer::basic(
58 self.username(),
59 self.password(),
60 )),
61 }
62 }
63}
64
65impl<Response> ServerAuthenticator<Response> for Config
66where
67 Response: Default,
68{
69 type ServerLayer = ValidateRequestHeaderLayer<Basic<Response>>;
71
72 fn get_server_layer(&self) -> Result<Self::ServerLayer, AuthError> {
73 Ok(ValidateRequestHeaderLayer::basic(
74 self.username(),
75 self.password(),
76 ))
77 }
78}
79
80#[cfg(test)]
82mod tests {
83 use tower::ServiceBuilder;
84 use tower_reqwest::HttpClientLayer;
85
86 use super::*;
87
88 #[test]
89 fn test_config() {
90 let username = "admin".to_string();
91 let password = OpaqueString::new("password");
92 let config = Config::new(&username, &password);
93
94 assert_eq!(config.username(), username);
95 assert_eq!(config.password(), &password);
96 }
97
98 #[tokio::test]
99 async fn test_authenticator() {
100 let username = "admin".to_string();
101 let password = OpaqueString::new("password");
102 let config = Config::new(&username, &password);
103
104 let client_layer = config.get_client_layer().unwrap();
105 let server_layer: ValidateRequestHeaderLayer<Basic<String>> =
106 config.get_server_layer().unwrap();
107
108 let _ = ServiceBuilder::new().layer(server_layer);
110
111 let _ = ServiceBuilder::new()
112 .layer(HttpClientLayer)
113 .layer(client_layer);
114 }
115}