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
63    use super::*;
64
65    #[tokio::test]
66    async fn keyring() -> Result<(), Error> {
67        let keyring = Keyring::new("test-app", "user-name")?;
68        let password = "test-password".to_string();
69
70        keyring.set_password(password.clone())?;
71        assert_eq!(keyring.get_password()?, password);
72
73        keyring.delete_password()?;
74
75        Ok(())
76    }
77}