nextcloud_auth/basic/
app_password.rs1use std::fmt;
2
3use crate::SecretString;
4
5#[derive(Clone)]
10pub struct AppPassword {
11 user: String,
12 password: SecretString,
13}
14
15impl AppPassword {
16 pub fn new(user: impl Into<String>, password: SecretString) -> Self {
18 Self {
19 user: user.into(),
20 password,
21 }
22 }
23
24 pub fn user(&self) -> &str {
26 &self.user
27 }
28
29 pub fn password(&self) -> &SecretString {
34 &self.password
35 }
36}
37
38impl fmt::Debug for AppPassword {
39 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
40 f.debug_struct("AppPassword")
41 .field("user", &self.user)
42 .field("password", &self.password)
43 .finish()
44 }
45}
46
47#[cfg(test)]
48mod tests {
49 use super::AppPassword;
50 use crate::SecretString;
51
52 #[test]
53 fn debug_redacts_the_password() {
54 let credentials = AppPassword::new("alice", SecretString::new("s3cr3t-app-password"));
55 let rendered = format!("{credentials:?}");
56 assert!(!rendered.contains("s3cr3t-app-password"));
57 assert!(rendered.contains("<redacted>"));
58 assert!(rendered.contains("alice"));
59 }
60
61 #[test]
62 fn exposes_user_and_password() {
63 let credentials = AppPassword::new("alice", SecretString::new("pw"));
64 assert_eq!(credentials.user(), "alice");
65 assert_eq!(credentials.password().expose(), "pw");
66 }
67}