Skip to content

Commit e19260e

Browse files
committed
Replace TrustedPublishingTokenExposedEmail struct with EmailMessage::from_template()
1 parent 309fdc8 commit e19260e

File tree

3 files changed

+39
-65
lines changed

3 files changed

+39
-65
lines changed

src/controllers/github/secret_scanning.rs

Lines changed: 19 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use crate::app::AppState;
2-
use crate::email::{Email, EmailMessage};
2+
use crate::email::EmailMessage;
33
use crate::models::{ApiToken, User};
44
use crate::schema::{api_tokens, crate_owners, crates, emails};
55
use crate::util::errors::{AppResult, BoxedAppError, bad_request};
@@ -290,12 +290,24 @@ async fn send_trustpub_notification_emails(
290290

291291
// Send notifications in sorted order by email for consistent testing
292292
for (email, crate_names) in notifications {
293-
let email_template = TrustedPublishingTokenExposedEmail {
294-
domain: &state.config.domain_name,
295-
reporter: "GitHub",
296-
source: &alert.source,
297-
crate_names: &crate_names.iter().cloned().collect::<Vec<_>>(),
298-
url: &alert.url,
293+
let message = EmailMessage::from_template(
294+
"trustpub_token_exposed",
295+
context! {
296+
domain => state.config.domain_name,
297+
reporter => "GitHub",
298+
source => alert.source,
299+
crate_names,
300+
url => alert.url
301+
},
302+
);
303+
304+
let Ok(email_template) = message.inspect_err(|error| {
305+
warn!(
306+
%email, ?crate_names, ?error,
307+
"Failed to create trusted publishing token exposure email template"
308+
);
309+
}) else {
310+
continue;
299311
};
300312

301313
if let Err(error) = state.emails.send(&email, email_template).await {
@@ -309,64 +321,6 @@ async fn send_trustpub_notification_emails(
309321
Ok(())
310322
}
311323

312-
struct TrustedPublishingTokenExposedEmail<'a> {
313-
domain: &'a str,
314-
reporter: &'a str,
315-
source: &'a str,
316-
crate_names: &'a [String],
317-
url: &'a str,
318-
}
319-
320-
impl Email for TrustedPublishingTokenExposedEmail<'_> {
321-
fn subject(&self) -> String {
322-
"crates.io: Your Trusted Publishing token has been revoked".to_string()
323-
}
324-
325-
fn body(&self) -> String {
326-
let authorization = if self.crate_names.len() == 1 {
327-
format!(
328-
"This token was only authorized to publish the \"{}\" crate.",
329-
self.crate_names[0]
330-
)
331-
} else {
332-
format!(
333-
"This token was authorized to publish the following crates: \"{}\".",
334-
self.crate_names.join("\", \"")
335-
)
336-
};
337-
338-
let mut body = format!(
339-
"{reporter} has notified us that one of your crates.io Trusted Publishing tokens \
340-
has been exposed publicly. We have revoked this token as a precaution.
341-
342-
{authorization}
343-
344-
Please review your account at https://{domain} and your GitHub repository \
345-
settings to confirm that no unexpected changes have been made to your crates \
346-
or trusted publishing configurations.
347-
348-
Source type: {source}",
349-
domain = self.domain,
350-
reporter = self.reporter,
351-
source = self.source,
352-
);
353-
354-
if self.url.is_empty() {
355-
body.push_str("\n\nWe were not informed of the URL where the token was found.");
356-
} else {
357-
body.push_str(&format!("\n\nURL where the token was found: {}", self.url));
358-
}
359-
360-
body.push_str(
361-
"\n\nTrusted Publishing tokens are temporary and used for automated \
362-
publishing from GitHub Actions. If this exposure was unexpected, please review \
363-
your repository's workflow files and secrets.",
364-
);
365-
366-
body
367-
}
368-
}
369-
370324
#[derive(Deserialize, Serialize)]
371325
pub struct GitHubSecretAlertFeedback {
372326
pub token_raw: String,
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{{ reporter }} has notified us that one of your crates.io Trusted Publishing tokens has been exposed publicly. We have revoked this token as a precaution.
2+
3+
{% if crate_names | length == 1 -%}
4+
This token was only authorized to publish the "{{ crate_names[0] }}" crate.
5+
{%- else -%}
6+
This token was authorized to publish the following crates: "{{ crate_names | join('", "') }}".
7+
{%- endif %}
8+
9+
Please review your account at https://{{ domain }} and your GitHub repository settings to confirm that no unexpected changes have been made to your crates or trusted publishing configurations.
10+
11+
Source type: {{ source }}
12+
13+
{% if url -%}
14+
URL where the token was found: {{ url }}
15+
{%- else -%}
16+
We were not informed of the URL where the token was found.
17+
{%- endif %}
18+
19+
Trusted Publishing tokens are temporary and used for automated publishing from GitHub Actions. If this exposure was unexpected, please review your repository's workflow files and secrets.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
crates.io: Your Trusted Publishing token has been revoked

0 commit comments

Comments
 (0)