crud_auth_bearer/
lib.rs

1//! ## Crud bearer authentification.
2//!
3//! Authentification trait implementation for [crud-api](../crud-api):
4//!
5//! ### Configuration
6//!
7//! | configuration | cli        | description         |
8//! |---------------|------------|---------------------|
9//! | auth_token    | auth-token | Authorization token |
10//!
11//!
12
13use clap::{Arg, ArgAction, ArgMatches, Command};
14use config::Config;
15use crud_auth::CrudAuth;
16use owo_colors::OwoColorize;
17
18#[derive(Default, Debug)]
19pub struct Auth {
20  header: (String, String),
21}
22
23const AUTH_TOKEN_ARG: &str = "auth_token";
24const AUTH_TOKEN_SETTING: &str = "auth_token";
25
26impl CrudAuth for Auth {
27  fn clap_auth(&self, app: Command) -> Command {
28    app.arg(
29      Arg::new(AUTH_TOKEN_ARG)
30        .short('t')
31        .long("auth-token")
32        .action(ArgAction::Set)
33        .help("Authorization token")
34        .help_heading("Configuration"),
35    )
36  }
37
38  fn clap_matches(&mut self, matches: &ArgMatches, _app: &mut Command, settings: &Config) {
39    if let Some(token) = matches.get_one::<String>(AUTH_TOKEN_ARG).cloned() {
40      self.header = ("Authorization".to_string(), "Bearer ".to_string() + &token);
41    } else if let Some(profile) = matches.get_one::<String>("profile") {
42      if let Ok(token) = settings.get_string(&format!("profile.{profile}.{}", AUTH_TOKEN_SETTING)) {
43        self.header = ("Authorization".to_string(), "Bearer ".to_string() + &token);
44      } else if let Ok(token) = settings.get_string(AUTH_TOKEN_SETTING) {
45        self.header = ("Authorization".to_string(), "Bearer ".to_string() + &token);
46      }
47    } else if let Ok(token) = settings.get_string(AUTH_TOKEN_SETTING) {
48      self.header = ("Authorization".to_string(), "Bearer ".to_string() + &token);
49    }
50  }
51
52  fn auth_header(&self) -> (String, String) {
53    self.header.clone()
54  }
55
56  fn error_help_message(&self) -> String {
57    format!("Use or check the `{}` argument.", "--auth-token".yellow())
58  }
59}
60
61#[cfg(feature = "save_token")]
62impl Auth {
63  /// Save the token in the configuration file.
64  pub fn save_token(token: &str, settings: &Config) -> miette::Result<()> {
65    use miette::IntoDiagnostic;
66    use std::{fs, path::Path};
67    use toml_edit::{value, Document};
68
69    let config_path = settings
70      .get_string("configuration_path")
71      .into_diagnostic()?;
72    let config_str = fs::read_to_string(&config_path).unwrap_or_default();
73
74    let mut doc = config_str.parse::<Document>().into_diagnostic()?;
75    doc[AUTH_TOKEN_SETTING] = value(token);
76
77    let path = Path::new(&config_path).parent().unwrap();
78    fs::create_dir_all(path).into_diagnostic()?;
79    fs::write(config_path, doc.to_string()).into_diagnostic()?;
80
81    Ok(())
82  }
83}