syncable_cli/auth/
credentials.rs1use crate::config::{load_config, save_global_config, types::SyncableAuth};
6use anyhow::Result;
7use std::time::{SystemTime, UNIX_EPOCH};
8
9pub fn save_credentials(
11 access_token: &str,
12 refresh_token: Option<&str>,
13 user_email: Option<&str>,
14 expires_in_secs: Option<u64>,
15) -> Result<()> {
16 let mut config = load_config(None).unwrap_or_default();
17
18 let expires_at = expires_in_secs.map(|secs| {
19 SystemTime::now()
20 .duration_since(UNIX_EPOCH)
21 .unwrap()
22 .as_secs()
23 + secs
24 });
25
26 config.syncable_auth = SyncableAuth {
27 access_token: Some(access_token.to_string()),
28 refresh_token: refresh_token.map(|s| s.to_string()),
29 expires_at,
30 user_email: user_email.map(|s| s.to_string()),
31 };
32
33 save_global_config(&config)?;
34 Ok(())
35}
36
37pub fn get_access_token() -> Option<String> {
39 let config = load_config(None).ok()?;
40
41 if let Some(expires_at) = config.syncable_auth.expires_at {
43 let now = SystemTime::now()
44 .duration_since(UNIX_EPOCH)
45 .ok()?
46 .as_secs();
47 if now > expires_at {
48 return None; }
50 }
51
52 config.syncable_auth.access_token
53}
54
55pub fn get_user_email() -> Option<String> {
57 let config = load_config(None).ok()?;
58 config.syncable_auth.user_email
59}
60
61pub fn is_authenticated() -> bool {
63 get_access_token().is_some()
64}
65
66pub fn get_auth_status() -> AuthStatus {
68 let config = match load_config(None) {
69 Ok(c) => c,
70 Err(_) => return AuthStatus::NotAuthenticated,
71 };
72
73 match &config.syncable_auth.access_token {
74 None => AuthStatus::NotAuthenticated,
75 Some(_) => {
76 if let Some(expires_at) = config.syncable_auth.expires_at {
77 let now = SystemTime::now()
78 .duration_since(UNIX_EPOCH)
79 .map(|d| d.as_secs())
80 .unwrap_or(0);
81
82 if now > expires_at {
83 return AuthStatus::Expired;
84 }
85
86 AuthStatus::Authenticated {
87 email: config.syncable_auth.user_email.clone(),
88 expires_at: Some(expires_at),
89 }
90 } else {
91 AuthStatus::Authenticated {
92 email: config.syncable_auth.user_email.clone(),
93 expires_at: None,
94 }
95 }
96 }
97 }
98}
99
100pub fn clear_credentials() -> Result<()> {
102 let mut config = load_config(None).unwrap_or_default();
103 config.syncable_auth = SyncableAuth::default();
104 save_global_config(&config)?;
105 Ok(())
106}
107
108#[derive(Debug)]
110pub enum AuthStatus {
111 NotAuthenticated,
112 Expired,
113 Authenticated {
114 email: Option<String>,
115 expires_at: Option<u64>,
116 },
117}