Skip to content

Commit b305d2e

Browse files
authored
Merge pull request #261 from syncable-dev/develop
feat: updated cli to include auth
2 parents aa4c1c4 + 1ad5282 commit b305d2e

11 files changed

Lines changed: 506 additions & 0 deletions

File tree

.DS_Store

2 KB
Binary file not shown.

Cargo.lock

Lines changed: 44 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,8 @@ strip-ansi-escapes = "0.2" # Strip ANSI codes for testing
100100

101101
# Dockerfile linting (hadolint-rs)
102102
nom = "7" # Parser combinators for Dockerfile parsing
103+
anyhow = "1.0.100"
104+
open = "5.3.3"
103105

104106
[dev-dependencies]
105107
assert_cmd = "2"

src/auth/credentials.rs

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
//! Credential storage and retrieval for Syncable authentication
2+
//!
3+
//! Stores authentication tokens in ~/.syncable.toml
4+
5+
use crate::config::{load_config, save_global_config, types::SyncableAuth};
6+
use anyhow::Result;
7+
use std::time::{SystemTime, UNIX_EPOCH};
8+
9+
/// Save credentials to global config file
10+
pub 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+
37+
/// Get the current access token if valid
38+
pub fn get_access_token() -> Option<String> {
39+
let config = load_config(None).ok()?;
40+
41+
// Check expiry
42+
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; // Token expired
49+
}
50+
}
51+
52+
config.syncable_auth.access_token
53+
}
54+
55+
/// Get the authenticated user's email
56+
pub fn get_user_email() -> Option<String> {
57+
let config = load_config(None).ok()?;
58+
config.syncable_auth.user_email
59+
}
60+
61+
/// Check if the user is currently authenticated with a valid token
62+
pub fn is_authenticated() -> bool {
63+
get_access_token().is_some()
64+
}
65+
66+
/// Get authentication status including expiry info
67+
pub 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+
100+
/// Clear stored credentials (logout)
101+
pub 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+
/// Authentication status enum
109+
#[derive(Debug)]
110+
pub enum AuthStatus {
111+
NotAuthenticated,
112+
Expired,
113+
Authenticated {
114+
email: Option<String>,
115+
expires_at: Option<u64>,
116+
},
117+
}

0 commit comments

Comments
 (0)