Skip to content

Commit c6757c8

Browse files
Redact API keys from terminal display
1 parent 47e07c2 commit c6757c8

1 file changed

Lines changed: 54 additions & 14 deletions

File tree

src/main.rs

Lines changed: 54 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -103,19 +103,28 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
103103
.send()
104104
.await?
105105
.error_for_status()?
106-
.json::<Vec<Keys>>()
106+
.json::<Vec<Key>>()
107107
.await?;
108108
let _ = term.clear_screen();
109109
term.flush()?;
110110
let mut clipboard = Clipboard::new()?;
111111
if api_keys.is_empty() {
112-
let new_key = client
113-
.post("https://api.cloud.developerdao.com/api/keys")
114-
.send()
115-
.await?
116-
.error_for_status()?
117-
.text()
118-
.await?;
112+
let new_key = Key {
113+
apikey: client
114+
.post("https://api.cloud.developerdao.com/api/keys")
115+
.send()
116+
.await?
117+
.error_for_status()?
118+
.text()
119+
.await?,
120+
};
121+
122+
let redacted_key = new_key.as_redacted();
123+
let redacted_ep = format!(
124+
"https://api.cloud.developerdao.com/rpc/{}/{}",
125+
CHAINS[chain].id(),
126+
redacted_key
127+
);
119128

120129
let endpoint = format!(
121130
"https://api.cloud.developerdao.com/rpc/{}/{}",
@@ -125,23 +134,35 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
125134

126135
clipboard.set_text(&endpoint)?;
127136
println!("\nYour RPC Endpoint for {}:\n", CHAINS[chain]);
128-
println!("\n{endpoint}\n");
137+
println!("\n{redacted_ep}\n");
129138
println!("\nYour API key is now copied to your clipboard");
130139
} else {
131-
let index = dialoguer::Select::new()
132-
.items(&api_keys)
140+
let redacted_keys = api_keys
141+
.iter()
142+
.map(|e| e.as_redacted())
143+
.collect::<Vec<RedactedKey>>();
144+
145+
let index = dialoguer::Select::with_theme(&ColorfulTheme::default())
146+
.items(&redacted_keys)
133147
.with_prompt("Select an API key to copy")
134148
.interact()?;
135149

150+
let redacted_ep = format!(
151+
"https://api.cloud.developerdao.com/rpc/{}/{}",
152+
CHAINS[chain].id(),
153+
redacted_keys[index].redacted,
154+
);
155+
136156
let endpoint = format!(
137157
"https://api.cloud.developerdao.com/rpc/{}/{}",
138158
CHAINS[chain].id(),
139159
api_keys[index].apikey
140160
);
161+
141162
clipboard.set_text(&endpoint)?;
142163

143164
println!("\nYour RPC Endpoint for {}:\n", CHAINS[chain]);
144-
println!("\n{endpoint}\n",);
165+
println!("\n{redacted_ep}\n",);
145166
println!("\nYour endpoint is now copied to your clipboard");
146167
}
147168

@@ -155,11 +176,30 @@ pub struct LoginRequest {
155176
}
156177

157178
#[derive(Serialize, Deserialize, Debug, Clone)]
158-
pub struct Keys {
179+
pub struct Key {
159180
apikey: String,
160181
}
161182

162-
impl Display for Keys {
183+
impl Key {
184+
pub fn as_redacted(&self) -> RedactedKey {
185+
let last_five = &self.apikey[self.apikey.len() - 5..];
186+
let first_five = &self.apikey[..5];
187+
let redacted = format!("{first_five}*****************{last_five}");
188+
RedactedKey { redacted }
189+
}
190+
}
191+
192+
pub struct RedactedKey {
193+
redacted: String,
194+
}
195+
196+
impl Display for RedactedKey {
197+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
198+
write!(f, "{}", self.redacted)
199+
}
200+
}
201+
202+
impl Display for Key {
163203
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
164204
write!(f, "{}", self.apikey)
165205
}

0 commit comments

Comments
 (0)