wiremux_auth/profile/
error.rs1use std::io;
4use std::path::PathBuf;
5
6#[derive(Debug, thiserror::Error)]
8pub enum ProfileError {
9 #[error("failed to read {}: {source}", path.display())]
11 Io {
12 path: PathBuf,
14 #[source]
16 source: io::Error,
17 },
18 #[error("failed to parse profile: {0}")]
20 Parse(String),
21 #[error(
23 "unknown schema_version {found} (crate max {max}); upgrade wiremux or pin schema_version"
24 )]
25 SchemaVersion {
26 found: u32,
28 max: u32,
30 },
31 #[error("{}", missing_required_field(.0))]
33 MissingField(&'static str),
34 #[error("refused: forbidden key name `{0}`")]
36 ForbiddenKey(String),
37 #[error("refused: command interpolation in {field} ({trigger})")]
39 Interpolation {
40 field: String,
42 trigger: &'static str,
44 },
45 #[error(
47 "refused: disallowed URL in {field}: {} (https, or http only on 127.0.0.1 / localhost / ::1)",
48 crate::helpers::redact_url_origin(url)
49 )]
50 DisallowedUrl {
51 field: String,
53 url: String,
55 },
56 #[error("refused: native module path in {field}")]
58 NativeModule {
59 field: String,
61 },
62 #[error("{}; a .toml or .json path also works", not_found_message(id, known))]
64 NotFound {
65 id: String,
67 known: Vec<String>,
69 },
70}
71
72fn missing_required_field(field: &&str) -> String {
73 if *field == "schema_version" {
74 format!(
75 "missing required field schema_version (set to 1; crate max {})",
76 super::types::SCHEMA_VERSION_MAX
77 )
78 } else {
79 format!("missing required field {field}")
80 }
81}
82
83pub fn not_found_message(id: &str, known: &[String]) -> String {
85 let listed = if known.is_empty() {
86 "(none)".to_string()
87 } else {
88 known.join(", ")
89 };
90 let mut msg = format!("profile `{id}` not found (known: {listed})");
91 let refs: Vec<&str> = known.iter().map(String::as_str).collect();
92 if let Some(suggest) = super::types::suggest_kebab(id, &refs) {
93 msg.push_str(&format!("; did you mean `{suggest}`"));
94 }
95 msg
96}