1use crate::dirs::auth_file_path;
2use anyhow::{Context, Result, anyhow};
3use serde::{Deserialize, Serialize};
4use std::fs;
5
6#[derive(Debug, Clone, Serialize, Deserialize)]
7struct AuthPayload {
8 email: String,
9 password: String,
10}
11
12fn validate_auth(email: &str, password: &str) -> Result<(String, String)> {
13 let email = email.trim().to_string();
14 let password = password.to_string();
15
16 if email.is_empty() {
17 return Err(anyhow!("Missing auth email."));
18 }
19 if password.is_empty() {
20 return Err(anyhow!("Missing auth password."));
21 }
22
23 Ok((email, password))
24}
25
26pub fn load_auth() -> Result<(String, String)> {
27 let path = auth_file_path();
28 if !path.exists() {
29 return Err(anyhow!(
30 "Auth not configured. Run `things3 set-auth` to create {}.",
31 path.display()
32 ));
33 }
34
35 let raw = fs::read_to_string(&path)
36 .with_context(|| format!("Failed reading auth config at {}", path.display()))?;
37 let payload: AuthPayload = serde_json::from_str(&raw)
38 .with_context(|| format!("Failed reading auth config at {}", path.display()))?;
39
40 validate_auth(&payload.email, &payload.password)
41}
42
43pub fn write_auth(email: &str, password: &str) -> Result<std::path::PathBuf> {
44 let (email, password) = validate_auth(email, password)?;
45 let path = auth_file_path();
46 let parent = path
47 .parent()
48 .ok_or_else(|| anyhow!("Invalid auth file path"))?
49 .to_path_buf();
50 fs::create_dir_all(&parent).with_context(|| format!("Failed creating {}", parent.display()))?;
51
52 let payload = AuthPayload { email, password };
53 let serialized = serde_json::to_string(&payload)?;
54 let tmp_path = path.with_extension("tmp");
55 fs::write(&tmp_path, serialized)
56 .with_context(|| format!("Failed writing {}", tmp_path.display()))?;
57 fs::rename(&tmp_path, &path)
58 .with_context(|| format!("Failed finalizing {}", path.display()))?;
59
60 #[cfg(unix)]
61 {
62 use std::os::unix::fs::PermissionsExt;
63 let mut perms = fs::metadata(&path)?.permissions();
64 perms.set_mode(0o600);
65 fs::set_permissions(&path, perms)?;
66 }
67
68 Ok(path)
69}