use nu_plugin::{EngineInterface, EvaluatedCall, PluginCommand};
use nu_protocol::{Category, Example, LabeledError, PipelineData, Record, Signature, Type, Value};
pub struct SecretConfigShowCommand;
fn build_structured_config_display(
config_manager: &crate::config::ConfigManager,
span: nu_protocol::Span,
) -> Record {
let mut record = Record::new();
record.push(
"version",
Value::string(config_manager.config().version.clone(), span),
);
if let Some(config_path) = crate::config::get_config_file_path() {
record.push(
"config_file",
Value::string(config_path.to_string_lossy().to_string(), span),
);
}
let mut redaction_record = Record::new();
redaction_record.push(
"redaction_template",
Value::string(
config_manager.config().redaction.get_redaction_template(),
span,
),
);
record.push("redaction", Value::record(redaction_record, span));
let mut security_record = Record::new();
security_record.push(
"level",
Value::string(
format!("{:?}", config_manager.config().security.level).to_lowercase(),
span,
),
);
security_record.push(
"audit_config_changes",
Value::bool(config_manager.config().security.audit_config_changes, span),
);
security_record.push(
"max_custom_text_length",
Value::int(
config_manager.config().security.max_custom_text_length as i64,
span,
),
);
record.push("security", Value::record(security_record, span));
let env_overrides = std::env::vars()
.filter(|(key, _)| key.starts_with("NU_PLUGIN_SECRET_"))
.count();
if env_overrides > 0 {
record.push(
"environment_overrides",
Value::int(env_overrides as i64, span),
);
}
record
}
impl PluginCommand for SecretConfigShowCommand {
type Plugin = crate::SecretPlugin;
fn name(&self) -> &str {
"secret config show"
}
fn description(&self) -> &str {
"Display current secret plugin configuration settings"
}
fn signature(&self) -> Signature {
Signature::build(self.name())
.input_output_types(vec![(Type::Nothing, Type::Record(Box::new([])))])
.switch("raw", "Show raw TOML configuration", Some('r'))
.switch("file-path", "Show configuration file path only", Some('f'))
.category(Category::Custom("secret".into()))
}
fn examples(&self) -> Vec<Example<'_>> {
vec![
Example {
example: "secret config show",
description: "Display current configuration in structured format",
result: None,
},
Example {
example: "secret config show --raw",
description: "Display raw TOML configuration",
result: None,
},
Example {
example: "secret config show --file-path",
description: "Show only the configuration file path",
result: None,
},
]
}
fn run(
&self,
plugin: &Self::Plugin,
_engine: &EngineInterface,
call: &EvaluatedCall,
_input: PipelineData,
) -> Result<PipelineData, LabeledError> {
let span = call.head;
if call.has_flag("file-path")? {
let config_path = crate::config::get_config_file_path()
.map(|p| p.to_string_lossy().to_string())
.unwrap_or_else(|| "Configuration file path not available".to_string());
return Ok(PipelineData::Value(Value::string(config_path, span), None));
}
let config_manager = plugin.config_manager().read().map_err(|e| {
LabeledError::new("Configuration Error")
.with_label(format!("Failed to access configuration: {}", e), span)
})?;
if call.has_flag("raw")? {
let toml_content = toml::to_string_pretty(config_manager.config()).map_err(|e| {
LabeledError::new("Serialization Error")
.with_label(format!("Failed to serialize configuration: {}", e), span)
})?;
return Ok(PipelineData::Value(Value::string(toml_content, span), None));
}
let record = build_structured_config_display(&config_manager, span);
Ok(PipelineData::Value(Value::record(record, span), None))
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_command_name() {
let command = SecretConfigShowCommand;
assert_eq!(command.name(), "secret config show");
}
#[test]
fn test_signature() {
let command = SecretConfigShowCommand;
let signature = command.signature();
assert_eq!(signature.name, "secret config show");
}
}