From d59f68a51aa35e7e5491da79d667ad4dd497be5e Mon Sep 17 00:00:00 2001
From: Jason Volk <jason@zemos.net>
Date: Fri, 24 Jan 2025 22:49:10 +0000
Subject: [PATCH] add sensitive-field directives to config display

Signed-off-by: Jason Volk <jason@zemos.net>
---
 src/core/config/mod.rs |  9 +++++++++
 src/macros/config.rs   | 27 ++++++++++++++++++++++-----
 2 files changed, 31 insertions(+), 5 deletions(-)

diff --git a/src/core/config/mod.rs b/src/core/config/mod.rs
index e459f50b..c541c7e4 100644
--- a/src/core/config/mod.rs
+++ b/src/core/config/mod.rs
@@ -502,6 +502,8 @@ pub struct Config {
 	/// YOU NEED TO EDIT THIS OR USE registration_token_file.
 	///
 	/// example: "o&^uCtes4HPf0Vu@F20jQeeWE7"
+	///
+	/// display: sensitive
 	pub registration_token: Option<String>,
 
 	/// Path to a file on the system that gets read for the registration token.
@@ -793,6 +795,8 @@ pub struct Config {
 	/// Static TURN password to provide the client if not using a shared secret
 	/// ("turn_secret"). It is recommended to use a shared secret over static
 	/// credentials.
+	///
+	/// display: sensitive
 	#[serde(default)]
 	pub turn_password: String,
 
@@ -814,6 +818,8 @@ pub struct Config {
 	///
 	/// This is more secure, but if needed you can use traditional static
 	/// username/password credentials.
+	///
+	/// display: sensitive
 	#[serde(default)]
 	pub turn_secret: String,
 
@@ -1111,6 +1117,8 @@ pub struct Config {
 	/// security purposes.
 	///
 	/// example: "F670$2CP@Hw8mG7RY1$%!#Ic7YA"
+	///
+	/// display: sensitive
 	pub emergency_password: Option<String>,
 
 	/// default: "/_matrix/push/v1/notify"
@@ -1560,6 +1568,7 @@ pub struct Config {
 
 	/// Sentry reporting URL, if a custom one is desired.
 	///
+	/// display: sensitive
 	/// default: "https://fe2eb4536aa04949e28eff3128d64757@o4506996327251968.ingest.us.sentry.io/4506996334657536"
 	#[serde(default = "default_sentry_endpoint")]
 	pub sentry_endpoint: Option<Url>,
diff --git a/src/macros/config.rs b/src/macros/config.rs
index 90d6ef15..50feefa8 100644
--- a/src/macros/config.rs
+++ b/src/macros/config.rs
@@ -15,7 +15,7 @@ use crate::{
 
 const UNDOCUMENTED: &str = "# This item is undocumented. Please contribute documentation for it.";
 
-const HIDDEN: &[&str] = &["default"];
+const HIDDEN: &[&str] = &["default", "display"];
 
 #[allow(clippy::needless_pass_by_value)]
 pub(super) fn example_generator(input: ItemStruct, args: &[Meta]) -> Result<TokenStream> {
@@ -121,10 +121,27 @@ fn generate_example(input: &ItemStruct, args: &[Meta], write: bool) -> Result<To
 					.expect("written to config file");
 			}
 
-			let name = ident.to_string();
-			summary.push(quote! {
-				writeln!(out, "| {} | {:?} |", #name, self.#ident)?;
-			});
+			let display = get_doc_comment_line(field, "display");
+			let display_directive = |key| {
+				display
+					.as_ref()
+					.into_iter()
+					.flat_map(|display| display.split(' '))
+					.any(|directive| directive == key)
+			};
+
+			if !display_directive("hidden") {
+				let value = if display_directive("sensitive") {
+					quote! { "***********" }
+				} else {
+					quote! { format_args!("{:?}", self.#ident) }
+				};
+
+				let name = ident.to_string();
+				summary.push(quote! {
+					writeln!(out, "| {} | {} |", #name, #value)?;
+				});
+			}
 		}
 	}