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().duration_since(UNIX_EPOCH).ok()?.as_secs();
44 if now > expires_at {
45 return None; }
47 }
48
49 config.syncable_auth.access_token
50}
51
52pub fn get_user_email() -> Option<String> {
54 let config = load_config(None).ok()?;
55 config.syncable_auth.user_email
56}
57
58pub fn is_authenticated() -> bool {
60 get_access_token().is_some()
61}
62
63pub fn get_auth_status() -> AuthStatus {
65 let config = match load_config(None) {
66 Ok(c) => c,
67 Err(_) => return AuthStatus::NotAuthenticated,
68 };
69
70 match &config.syncable_auth.access_token {
71 None => AuthStatus::NotAuthenticated,
72 Some(_) => {
73 if let Some(expires_at) = config.syncable_auth.expires_at {
74 let now = SystemTime::now()
75 .duration_since(UNIX_EPOCH)
76 .map(|d| d.as_secs())
77 .unwrap_or(0);
78
79 if now > expires_at {
80 return AuthStatus::Expired;
81 }
82
83 AuthStatus::Authenticated {
84 email: config.syncable_auth.user_email.clone(),
85 expires_at: Some(expires_at),
86 }
87 } else {
88 AuthStatus::Authenticated {
89 email: config.syncable_auth.user_email.clone(),
90 expires_at: None,
91 }
92 }
93 }
94 }
95}
96
97pub fn clear_credentials() -> Result<()> {
99 let mut config = load_config(None).unwrap_or_default();
100 config.syncable_auth = SyncableAuth::default();
101 save_global_config(&config)?;
102 Ok(())
103}
104
105#[derive(Debug)]
107pub enum AuthStatus {
108 NotAuthenticated,
109 Expired,
110 Authenticated {
111 email: Option<String>,
112 expires_at: Option<u64>,
113 },
114}