client: allow storing the client token in a separate file

This commit is contained in:
Robin Appelman 2023-05-22 19:27:47 +02:00
parent 5f85e35a25
commit 4badbff966
4 changed files with 45 additions and 9 deletions

View file

@ -62,7 +62,7 @@ pub struct StructuredApiError {
impl ApiClient {
pub fn from_server_config(config: ServerConfig) -> Result<Self> {
let client = build_http_client(config.token.as_deref());
let client = build_http_client(config.token()?.as_deref());
Ok(Self {
endpoint: Url::parse(&config.endpoint)?,

View file

@ -3,7 +3,7 @@ use clap::Parser;
use crate::cache::ServerName;
use crate::cli::Opts;
use crate::config::{Config, ServerConfig};
use crate::config::{Config, ServerConfig, ServerTokenConfig};
/// Log into an Attic server.
#[derive(Debug, Parser)]
@ -32,8 +32,10 @@ pub async fn run(opts: Opts) -> Result<()> {
server.endpoint = sub.endpoint.to_owned();
if sub.token.is_some() {
server.token = sub.token.to_owned();
if let Some(token) = &sub.token {
server.token = Some(ServerTokenConfig::Raw {
token: token.clone(),
});
}
} else {
eprintln!("✍️ Configuring server \"{}\"", sub.name.as_str());
@ -42,7 +44,10 @@ pub async fn run(opts: Opts) -> Result<()> {
sub.name.to_owned(),
ServerConfig {
endpoint: sub.endpoint.to_owned(),
token: sub.token.to_owned(),
token: sub
.token
.to_owned()
.map(|token| ServerTokenConfig::Raw { token }),
},
);
}

View file

@ -49,7 +49,7 @@ pub async fn run(opts: Opts) -> Result<()> {
nix_config.add_trusted_public_key(&public_key);
// Modify netrc
if let Some(token) = &server.token {
if let Some(token) = server.token()? {
eprintln!("+ Access Token");
let mut nix_netrc = NixNetrc::load().await?;

View file

@ -5,13 +5,13 @@
//! experience (e.g., `attic login`).
use std::collections::HashMap;
use std::fs::{self, OpenOptions, Permissions};
use std::fs::{self, read_to_string, OpenOptions, Permissions};
use std::io::Write;
use std::ops::{Deref, DerefMut};
use std::os::unix::fs::{OpenOptionsExt, PermissionsExt};
use std::path::PathBuf;
use anyhow::{anyhow, Result};
use anyhow::{anyhow, Context, Result};
use serde::{Deserialize, Serialize};
use xdg::BaseDirectories;
@ -52,7 +52,38 @@ pub struct ConfigData {
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct ServerConfig {
pub endpoint: String,
pub token: Option<String>,
#[serde(flatten)]
pub token: Option<ServerTokenConfig>,
}
impl ServerConfig {
pub fn token(&self) -> Result<Option<String>> {
self.token.as_ref().map(|token| token.get()).transpose()
}
}
/// Configured server token
#[derive(Debug, Clone, Deserialize, Serialize)]
#[serde(untagged)]
pub enum ServerTokenConfig {
Raw {
token: String,
},
File {
#[serde(rename = "token-file")]
token_file: String,
},
}
impl ServerTokenConfig {
/// Get the token either directly from the config or through the token file
pub fn get(&self) -> Result<String> {
match self {
ServerTokenConfig::Raw { token } => Ok(token.clone()),
ServerTokenConfig::File { token_file } => Ok(read_to_string(token_file)
.with_context(|| format!("Failed to read token from {token_file}"))?),
}
}
}
/// Wrapper that automatically saves the config once dropped.