Skip to main content

fn0_deploy/
credentials.rs

1use anyhow::{Result, anyhow};
2use serde::{Deserialize, Serialize};
3use std::path::PathBuf;
4
5const DEFAULT_CONTROL_URL: &str = "https://fn0-control.fn0.dev";
6
7#[derive(Debug, Serialize, Deserialize)]
8pub struct Credentials {
9    pub token: String,
10    pub control_url: String,
11}
12
13pub fn path() -> Result<PathBuf> {
14    let dir = dirs::config_dir().ok_or_else(|| anyhow!("could not locate user config dir"))?;
15    Ok(dir.join("fn0").join("credentials"))
16}
17
18pub fn load() -> Result<Option<Credentials>> {
19    let p = path()?;
20    if !p.exists() {
21        return Ok(None);
22    }
23    let content = std::fs::read_to_string(&p)?;
24    let creds: Credentials = toml::from_str(&content)?;
25    Ok(Some(creds))
26}
27
28pub fn save(creds: &Credentials) -> Result<()> {
29    let p = path()?;
30    if let Some(parent) = p.parent() {
31        std::fs::create_dir_all(parent)?;
32    }
33    let content = toml::to_string(creds)?;
34    std::fs::write(&p, content)?;
35    set_mode_0600(&p)?;
36    Ok(())
37}
38
39pub fn require() -> Result<Credentials> {
40    load()?.ok_or_else(|| {
41        anyhow!(
42            "not signed in. Run `fn0 login` first (credentials would be at {}).",
43            path().map(|p| p.display().to_string()).unwrap_or_default()
44        )
45    })
46}
47
48pub fn default_control_url() -> String {
49    std::env::var("FN0_CONTROL_URL").unwrap_or_else(|_| DEFAULT_CONTROL_URL.to_string())
50}
51
52#[cfg(unix)]
53fn set_mode_0600(p: &std::path::Path) -> Result<()> {
54    use std::os::unix::fs::PermissionsExt;
55    let perms = std::fs::Permissions::from_mode(0o600);
56    std::fs::set_permissions(p, perms)?;
57    Ok(())
58}
59
60#[cfg(not(unix))]
61fn set_mode_0600(_p: &std::path::Path) -> Result<()> {
62    Ok(())
63}