pub mod auth_cache;
pub use auth_cache::AuthCache;
pub mod token;
pub use token::{ResolvedToken, TokenOrigin, resolve_token};
use crate::diagnostic::Diagnostic;
const SHORTCUTS: &[(&str, &str)] = &[
("prod", "https://api.dasch.swiss"),
("stage", "https://api.stage.dasch.swiss"),
("dev", "https://api.dev.dasch.swiss"),
("demo", "https://api.demo.dasch.swiss"),
("rdu", "https://api.rdu.dasch.swiss"),
("ls-prod", "https://api.ls-prod-server.dasch.swiss"),
("ls-test", "https://api.ls-test-server.dasch.swiss"),
("local", "http://0.0.0.0:3333"),
];
#[derive(Debug, Clone)]
pub struct Config {
pub server: String,
}
impl Config {
pub fn resolve(server: Option<&str>) -> Result<Self, Diagnostic> {
match server {
None => Err(Diagnostic::Usage(
"no server specified. Provide one via --server <prod|dev|…|URL>, \
the DSP_SERVER environment variable, or a .env file in the current directory. \
See `dsp docs connecting` for details."
.to_string(),
)),
Some(s) => {
let lower = s.to_ascii_lowercase();
let url = SHORTCUTS
.iter()
.find(|(name, _)| *name == lower)
.map(|(_, url)| *url)
.unwrap_or(s);
tracing::debug!(server = url, "resolved server");
Ok(Config {
server: url.to_string(),
})
}
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::diagnostic::Diagnostic;
#[test]
fn resolve_with_literal_url() {
let cfg = Config::resolve(Some("https://api.example.org")).unwrap();
assert_eq!(cfg.server, "https://api.example.org");
}
#[test]
fn resolve_with_known_shortcut_prod() {
let cfg = Config::resolve(Some("prod")).unwrap();
assert_eq!(cfg.server, "https://api.dasch.swiss");
}
#[test]
fn resolve_with_known_shortcut_local() {
let cfg = Config::resolve(Some("local")).unwrap();
assert_eq!(cfg.server, "http://0.0.0.0:3333");
}
#[test]
fn resolve_with_unknown_word_passes_through() {
let cfg = Config::resolve(Some("staging-experiment")).unwrap();
assert_eq!(cfg.server, "staging-experiment");
}
#[test]
fn resolve_with_known_shortcut_dev() {
let cfg = Config::resolve(Some("dev")).unwrap();
assert_eq!(cfg.server, "https://api.dev.dasch.swiss");
}
#[test]
fn resolve_with_known_shortcut_demo() {
let cfg = Config::resolve(Some("demo")).unwrap();
assert_eq!(cfg.server, "https://api.demo.dasch.swiss");
}
#[test]
fn resolve_shortcut_is_case_insensitive() {
assert_eq!(
Config::resolve(Some("PROD")).unwrap().server,
"https://api.dasch.swiss"
);
assert_eq!(
Config::resolve(Some("Dev")).unwrap().server,
"https://api.dev.dasch.swiss"
);
}
#[test]
fn resolve_literal_url_preserves_case() {
let cfg = Config::resolve(Some("https://API.Example.ORG/Path")).unwrap();
assert_eq!(cfg.server, "https://API.Example.ORG/Path");
}
#[test]
fn resolve_with_none_returns_usage_diagnostic() {
let err = Config::resolve(None).unwrap_err();
assert!(matches!(err, Diagnostic::Usage(_)));
}
#[test]
fn missing_server_message_mentions_all_three_paths() {
let err = Config::resolve(None).unwrap_err();
let msg = err.to_string();
assert!(msg.contains("--server"), "missing --server in: {msg}");
assert!(msg.contains("DSP_SERVER"), "missing DSP_SERVER in: {msg}");
assert!(msg.contains(".env"), "missing .env in: {msg}");
}
#[test]
fn shortcut_and_canonical_url_resolve_identically() {
let via_shortcut = Config::resolve(Some("dev")).unwrap();
let via_url = Config::resolve(Some("https://api.dev.dasch.swiss")).unwrap();
assert_eq!(
via_shortcut.server, via_url.server,
"shortcut 'dev' and its URL must resolve to the same string for \
cache key lookups to work"
);
}
}