Skip to main content

novel_api/common/utils/
keyring.rs

1use keyring_core::Entry;
2use zeroize::Zeroize;
3
4use crate::Error;
5
6/// Access the Keyring of the platform
7#[must_use]
8pub struct Keyring {
9    entry: Entry,
10}
11
12impl Keyring {
13    /// Create a Keyring
14    pub fn new<T, E>(app_name: T, username: E) -> Result<Self, Error>
15    where
16        T: AsRef<str>,
17        E: AsRef<str>,
18    {
19        #[cfg(target_os = "macos")]
20        {
21            use apple_native_keyring_store::keychain::Store;
22            keyring_core::set_default_store(Store::new()?);
23        }
24        #[cfg(target_os = "windows")]
25        {
26            use windows_native_keyring_store::Store;
27            keyring_core::set_default_store(Store::new()?);
28        }
29        #[cfg(target_os = "linux")]
30        {
31            use linux_keyutils_keyring_store::Store;
32            keyring_core::set_default_store(Store::new()?);
33        }
34
35        let service = format!("novel-rs-{}", app_name.as_ref());
36        let entry = Entry::new(&service, username.as_ref())?;
37
38        Ok(Self { entry })
39    }
40
41    /// Get password
42    pub fn get_password(&self) -> Result<String, Error> {
43        Ok(self.entry.get_password()?)
44    }
45
46    /// Set password
47    pub fn set_password(&self, mut password: String) -> Result<(), Error> {
48        self.entry.set_password(&password)?;
49        password.zeroize();
50        Ok(())
51    }
52
53    /// Delete password
54    pub fn delete_password(&self) -> Result<(), Error> {
55        Ok(self.entry.delete_credential()?)
56    }
57}
58
59#[cfg(test)]
60mod tests {
61    use pretty_assertions::assert_eq;
62    use testresult::TestResult;
63
64    use super::*;
65
66    #[tokio::test]
67    async fn keyring() -> TestResult {
68        let keyring = Keyring::new("test-app", "user-name")?;
69        let password = "test-password".to_string();
70
71        keyring.set_password(password.clone())?;
72        assert_eq!(keyring.get_password()?, password);
73
74        keyring.delete_password()?;
75
76        Ok(())
77    }
78}