Skip to content

trustpub: Improve email templates #11575

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Jul 15, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion crates/crates_io_database/src/models/krate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use diesel::sql_types::{Bool, Integer, Text};
use diesel_async::scoped_futures::ScopedFutureExt;
use diesel_async::{AsyncConnection, AsyncPgConnection, RunQueryDsl};
use secrecy::SecretString;
use serde::Serialize;
use thiserror::Error;
use tracing::instrument;

Expand All @@ -35,7 +36,9 @@ pub struct CrateName {
pub name: String,
}

#[derive(Debug, Clone, Queryable, Identifiable, AsChangeset, QueryableByName, Selectable)]
#[derive(
Debug, Clone, Queryable, Identifiable, AsChangeset, QueryableByName, Selectable, Serialize,
)]
#[diesel(table_name = crates, check_for_backend(diesel::pg::Pg))]
pub struct Crate {
pub id: i32,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@ use crate::schema::trustpub_configs_github;
use chrono::{DateTime, Utc};
use diesel::prelude::*;
use diesel_async::{AsyncPgConnection, RunQueryDsl};
use serde::Serialize;

#[derive(Debug, Identifiable, Queryable, Selectable)]
#[derive(Debug, Identifiable, Queryable, Selectable, Serialize)]
#[diesel(table_name = trustpub_configs_github, check_for_backend(diesel::pg::Pg))]
pub struct GitHubConfig {
pub id: i32,
Expand Down
4 changes: 3 additions & 1 deletion crates/crates_io_database/src/models/user.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,18 @@ use diesel::sql_types::Integer;
use diesel::upsert::excluded;
use diesel_async::{AsyncPgConnection, RunQueryDsl};
use secrecy::SecretString;
use serde::Serialize;

use crate::models::{Crate, CrateOwner, Email, Owner, OwnerKind};
use crate::schema::{crate_owners, emails, users};
use crates_io_diesel_helpers::lower;

/// The model representing a row in the `users` database table.
#[derive(Clone, Debug, Queryable, Identifiable, Selectable)]
#[derive(Clone, Debug, Queryable, Identifiable, Selectable, Serialize)]
pub struct User {
pub id: i32,
#[diesel(deserialize_as = String)]
#[serde(skip)]
pub gh_access_token: SecretString,
pub gh_login: String,
pub name: Option<String>,
Expand Down
10 changes: 1 addition & 9 deletions src/controllers/trustpub/github_configs/create/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,15 +108,7 @@ pub async fn create_trustpub_github_config(
.collect::<Vec<_>>();

for (recipient, email_address) in &recipients {
let context = context! {
recipient => recipient,
user => auth_user.gh_login,
krate => krate.name,
repository_owner => saved_config.repository_owner,
repository_name => saved_config.repository_name,
workflow_filename => saved_config.workflow_filename,
environment => saved_config.environment
};
let context = context! { recipient, auth_user, krate, saved_config };

if let Err(err) = send_notification_email(&state, email_address, context).await {
warn!("Failed to send trusted publishing notification to {email_address}: {err}");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ Content-Transfer-Encoding: quoted-printable

Hello foo!

crates.io user foo added a new "Trusted Publishing" configuration for GitHub Actions to a crate that you manage ("foo"). Trusted publishers act as trusted users and can publish new versions of the crate automatically.
You added a new "Trusted Publishing" configuration for GitHub Actions to your crate "foo". Trusted publishers act as trusted users and can publish new versions of the crate automatically.

Trusted Publishing configuration:

Expand Down
20 changes: 6 additions & 14 deletions src/controllers/trustpub/github_configs/delete/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ use crate::email::EmailMessage;
use crate::util::errors::{AppResult, bad_request, not_found};
use anyhow::Context;
use axum::extract::Path;
use crates_io_database::models::OwnerKind;
use crates_io_database::models::trustpub::GitHubConfig;
use crates_io_database::models::{Crate, OwnerKind};
use crates_io_database::schema::{crate_owners, crates, emails, trustpub_configs_github, users};
use diesel::prelude::*;
use diesel_async::RunQueryDsl;
Expand Down Expand Up @@ -39,12 +39,12 @@ pub async fn delete_trustpub_github_config(
let auth_user = auth.user();

// Check that a trusted publishing config with the given ID exists,
// and fetch the corresponding crate ID and name.
let (config, crate_name) = trustpub_configs_github::table
// and fetch the corresponding crate.
let (config, krate) = trustpub_configs_github::table
.inner_join(crates::table)
.filter(trustpub_configs_github::id.eq(id))
.select((GitHubConfig::as_select(), crates::name))
.first::<(GitHubConfig, String)>(&mut conn)
.select((GitHubConfig::as_select(), Crate::as_select()))
.first::<(GitHubConfig, Crate)>(&mut conn)
.await
.optional()?
.ok_or_else(not_found)?;
Expand Down Expand Up @@ -79,15 +79,7 @@ pub async fn delete_trustpub_github_config(
.collect::<Vec<_>>();

for (recipient, email_address) in &recipients {
let context = context! {
recipient => recipient,
user => auth_user.gh_login,
krate => crate_name,
repository_owner => config.repository_owner,
repository_name => config.repository_name,
workflow_filename => config.workflow_filename,
environment => config.environment
};
let context = context! { recipient, auth_user, krate, config };

if let Err(err) = send_notification_email(&state, email_address, context).await {
warn!("Failed to send trusted publishing notification to {email_address}: {err}");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ Content-Transfer-Encoding: quoted-printable

Hello foo!

crates.io user foo removed a "Trusted Publishing" configuration for GitHub Actions from a crate that you manage ("foo").
You removed a "Trusted Publishing" configuration for GitHub Actions from your crate "foo".

Trusted Publishing configuration:

Expand Down
14 changes: 9 additions & 5 deletions src/email/templates/config_created/body.txt.j2
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,18 @@
{% block content %}
Hello {{ recipient }}!

crates.io user {{ user }} added a new "Trusted Publishing" configuration for GitHub Actions to a crate that you manage ("{{ krate }}"). Trusted publishers act as trusted users and can publish new versions of the crate automatically.
{% if recipient == auth_user.gh_login -%}
You added a new "Trusted Publishing" configuration for GitHub Actions to your crate "{{ krate.name }}". Trusted publishers act as trusted users and can publish new versions of the crate automatically.
{%- else -%}
crates.io user {{ auth_user.gh_login }} added a new "Trusted Publishing" configuration for GitHub Actions to a crate that you manage ("{{ krate.name }}"). Trusted publishers act as trusted users and can publish new versions of the crate automatically.
{%- endif %}

Trusted Publishing configuration:

- Repository owner: {{ repository_owner }}
- Repository name: {{ repository_name }}
- Workflow filename: {{ workflow_filename }}
- Environment: {{ environment or "(not set)" }}
- Repository owner: {{ saved_config.repository_owner }}
- Repository name: {{ saved_config.repository_name }}
- Workflow filename: {{ saved_config.workflow_filename }}
- Environment: {{ saved_config.environment or "(not set)" }}

If you did not make this change and you think it was made maliciously, you can remove the configuration from the crate via the "Settings" tab on the crate's page.

Expand Down
2 changes: 1 addition & 1 deletion src/email/templates/config_created/subject.txt.j2
Original file line number Diff line number Diff line change
@@ -1 +1 @@
crates.io: Trusted Publishing configuration added to {{ krate }}
crates.io: Trusted Publishing configuration added to {{ krate.name }}
14 changes: 9 additions & 5 deletions src/email/templates/config_deleted/body.txt.j2
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,18 @@
{% block content %}
Hello {{ recipient }}!

crates.io user {{ user }} removed a "Trusted Publishing" configuration for GitHub Actions from a crate that you manage ("{{ krate }}").
{% if recipient == auth_user.gh_login -%}
You removed a "Trusted Publishing" configuration for GitHub Actions from your crate "{{ krate.name }}".
{%- else -%}
crates.io user {{ auth_user.gh_login }} removed a "Trusted Publishing" configuration for GitHub Actions from a crate that you manage ("{{ krate.name }}").
{%- endif %}

Trusted Publishing configuration:

- Repository owner: {{ repository_owner }}
- Repository name: {{ repository_name }}
- Workflow filename: {{ workflow_filename }}
- Environment: {{ environment or "(not set)" }}
- Repository owner: {{ config.repository_owner }}
- Repository name: {{ config.repository_name }}
- Workflow filename: {{ config.workflow_filename }}
- Environment: {{ config.environment or "(not set)" }}

If you did not make this change and you think it was made maliciously, you can email [email protected] for assistance.
{% endblock %}
2 changes: 1 addition & 1 deletion src/email/templates/config_deleted/subject.txt.j2
Original file line number Diff line number Diff line change
@@ -1 +1 @@
crates.io: Trusted Publishing configuration removed from {{ krate }}
crates.io: Trusted Publishing configuration removed from {{ krate.name }}
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ Content-Transfer-Encoding: quoted-printable

Hello foo!

crates.io user foo added a new "Trusted Publishing" configuration for GitHub Actions to a crate that you manage ("foo"). Trusted publishers act as trusted users and can publish new versions of the crate automatically.
You added a new "Trusted Publishing" configuration for GitHub Actions to your crate "foo". Trusted publishers act as trusted users and can publish new versions of the crate automatically.

Trusted Publishing configuration:

Expand Down