Skip to content
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
94 changes: 85 additions & 9 deletions src/controllers/trustpub/emails.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
use crate::email::EmailMessage;
use crates_io_database::models::trustpub::GitHubConfig;
use crates_io_database::models::trustpub::{GitHubConfig, GitLabConfig};
use crates_io_database::models::{Crate, User};

#[derive(Debug, Clone, Copy, serde::Serialize)]
#[serde(tag = "type")]
pub enum ConfigType<'a> {
GitHub(&'a GitHubConfig),
GitLab(&'a GitLabConfig),
}

#[derive(serde::Serialize)]
pub struct ConfigCreatedEmail<'a> {
/// The GitHub login of the email recipient.
Expand All @@ -11,7 +18,7 @@ pub struct ConfigCreatedEmail<'a> {
/// The crate for which the trusted publishing configuration was created.
pub krate: &'a Crate,
/// The trusted publishing configuration that was created.
pub saved_config: &'a GitHubConfig,
pub saved_config: ConfigType<'a>,
}

impl ConfigCreatedEmail<'_> {
Expand All @@ -29,7 +36,7 @@ pub struct ConfigDeletedEmail<'a> {
/// The crate for which the trusted publishing configuration was deleted.
pub krate: &'a Crate,
/// The trusted publishing configuration that was deleted.
pub config: &'a GitHubConfig,
pub config: ConfigType<'a>,
}

impl ConfigDeletedEmail<'_> {
Expand Down Expand Up @@ -88,13 +95,26 @@ mod tests {
}
}

fn test_gitlab_config(environment: Option<&str>) -> GitLabConfig {
GitLabConfig {
id: 1,
created_at: Utc::now(),
crate_id: 1,
namespace_id: None,
namespace: "rust-lang".into(),
project: "my-crate".into(),
workflow_filepath: ".gitlab-ci.yml".into(),
environment: environment.map(String::from),
}
}

#[test]
fn test_config_created_email() {
let email = ConfigCreatedEmail {
recipient: "octocat",
auth_user: &test_user(),
krate: &test_crate(),
saved_config: &test_github_config(None),
saved_config: ConfigType::GitHub(&test_github_config(None)),
};

let rendered = assert_ok!(email.render());
Expand All @@ -108,7 +128,7 @@ mod tests {
recipient: "octocat",
auth_user: &test_user(),
krate: &test_crate(),
saved_config: &test_github_config(Some("production")),
saved_config: ConfigType::GitHub(&test_github_config(Some("production"))),
};

let rendered = assert_ok!(email.render());
Expand All @@ -122,7 +142,35 @@ mod tests {
recipient: "team-member",
auth_user: &test_user(),
krate: &test_crate(),
saved_config: &test_github_config(None),
saved_config: ConfigType::GitHub(&test_github_config(None)),
};

let rendered = assert_ok!(email.render());
assert_snapshot!(rendered.subject, @"crates.io: Trusted Publishing configuration added to my-crate");
assert_snapshot!(rendered.body_text);
}

#[test]
fn test_config_created_email_gitlab() {
let email = ConfigCreatedEmail {
recipient: "octocat",
auth_user: &test_user(),
krate: &test_crate(),
saved_config: ConfigType::GitLab(&test_gitlab_config(None)),
};

let rendered = assert_ok!(email.render());
assert_snapshot!(rendered.subject, @"crates.io: Trusted Publishing configuration added to my-crate");
assert_snapshot!(rendered.body_text);
}

#[test]
fn test_config_created_email_gitlab_with_environment() {
let email = ConfigCreatedEmail {
recipient: "octocat",
auth_user: &test_user(),
krate: &test_crate(),
saved_config: ConfigType::GitLab(&test_gitlab_config(Some("production"))),
};

let rendered = assert_ok!(email.render());
Expand All @@ -136,7 +184,7 @@ mod tests {
recipient: "octocat",
auth_user: &test_user(),
krate: &test_crate(),
config: &test_github_config(None),
config: ConfigType::GitHub(&test_github_config(None)),
};

let rendered = assert_ok!(email.render());
Expand All @@ -150,7 +198,7 @@ mod tests {
recipient: "octocat",
auth_user: &test_user(),
krate: &test_crate(),
config: &test_github_config(Some("production")),
config: ConfigType::GitHub(&test_github_config(Some("production"))),
};

let rendered = assert_ok!(email.render());
Expand All @@ -164,7 +212,35 @@ mod tests {
recipient: "team-member",
auth_user: &test_user(),
krate: &test_crate(),
config: &test_github_config(None),
config: ConfigType::GitHub(&test_github_config(None)),
};

let rendered = assert_ok!(email.render());
assert_snapshot!(rendered.subject, @"crates.io: Trusted Publishing configuration removed from my-crate");
assert_snapshot!(rendered.body_text);
}

#[test]
fn test_config_deleted_email_gitlab() {
let email = ConfigDeletedEmail {
recipient: "octocat",
auth_user: &test_user(),
krate: &test_crate(),
config: ConfigType::GitLab(&test_gitlab_config(None)),
};

let rendered = assert_ok!(email.render());
assert_snapshot!(rendered.subject, @"crates.io: Trusted Publishing configuration removed from my-crate");
assert_snapshot!(rendered.body_text);
}

#[test]
fn test_config_deleted_email_gitlab_with_environment() {
let email = ConfigDeletedEmail {
recipient: "octocat",
auth_user: &test_user(),
krate: &test_crate(),
config: ConfigType::GitLab(&test_gitlab_config(Some("production"))),
};

let rendered = assert_ok!(email.render());
Expand Down
6 changes: 4 additions & 2 deletions src/controllers/trustpub/github_configs/create/mod.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::app::AppState;
use crate::auth::AuthCheck;
use crate::controllers::krate::load_crate;
use crate::controllers::trustpub::emails::ConfigCreatedEmail;
use crate::controllers::trustpub::emails::{ConfigCreatedEmail, ConfigType};
use crate::controllers::trustpub::github_configs::json;
use crate::util::errors::{AppResult, bad_request, forbidden, server_error};
use anyhow::Context;
Expand Down Expand Up @@ -117,11 +117,13 @@ pub async fn create_trustpub_github_config(
.collect::<Vec<_>>();

for (recipient, email_address) in &recipients {
let saved_config = ConfigType::GitHub(&saved_config);

let context = ConfigCreatedEmail {
recipient,
auth_user,
krate: &krate,
saved_config: &saved_config,
saved_config,
};

if let Err(err) = send_notification_email(&state, email_address, context).await {
Expand Down
6 changes: 4 additions & 2 deletions src/controllers/trustpub/github_configs/delete/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::app::AppState;
use crate::auth::AuthCheck;
use crate::controllers::trustpub::emails::ConfigDeletedEmail;
use crate::controllers::trustpub::emails::{ConfigDeletedEmail, ConfigType};
use crate::util::errors::{AppResult, bad_request, not_found};
use anyhow::Context;
use axum::extract::Path;
Expand Down Expand Up @@ -82,11 +82,13 @@ pub async fn delete_trustpub_github_config(
.collect::<Vec<_>>();

for (recipient, email_address) in &recipients {
let config = ConfigType::GitHub(&config);

let context = ConfigDeletedEmail {
recipient,
auth_user,
krate: &krate,
config: &config,
config,
};

if let Err(err) = send_notification_email(&state, email_address, context).await {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
---
source: src/controllers/trustpub/emails.rs
expression: rendered.body_text
---
Hello octocat!

You added a new "Trusted Publishing" configuration for GitLab CI to your crate "my-crate". Trusted publishers act as trusted users and can publish new versions of the crate automatically.

This configuration allows the workflow file at https://gitlab.com/rust-lang/my-crate/-/blob/HEAD/.gitlab-ci.yml to publish new versions of this crate.

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.

If you are unable to revert the change and need to do so, you can email [email protected] for assistance.

--
The crates.io Team
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
---
source: src/controllers/trustpub/emails.rs
expression: rendered.body_text
---
Hello octocat!

You added a new "Trusted Publishing" configuration for GitLab CI to your crate "my-crate". Trusted publishers act as trusted users and can publish new versions of the crate automatically.

This configuration allows the workflow file at https://gitlab.com/rust-lang/my-crate/-/blob/HEAD/.gitlab-ci.yml to publish new versions of this crate. The workflow must use the `production` environment.

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.

If you are unable to revert the change and need to do so, you can email [email protected] for assistance.

--
The crates.io Team
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
---
source: src/controllers/trustpub/emails.rs
expression: rendered.body_text
---
Hello octocat!

You removed a "Trusted Publishing" configuration for GitLab CI from your crate "my-crate".

The removed configuration was for the workflow file at https://gitlab.com/rust-lang/my-crate/-/blob/HEAD/.gitlab-ci.yml.

If you did not make this change and you think it was made maliciously, you can email [email protected] for assistance.

--
The crates.io Team
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
---
source: src/controllers/trustpub/emails.rs
expression: rendered.body_text
---
Hello octocat!

You removed a "Trusted Publishing" configuration for GitLab CI from your crate "my-crate".

The removed configuration was for the workflow file at https://gitlab.com/rust-lang/my-crate/-/blob/HEAD/.gitlab-ci.yml using the `production` environment.

If you did not make this change and you think it was made maliciously, you can email [email protected] for assistance.

--
The crates.io Team
17 changes: 14 additions & 3 deletions src/email/templates/trustpub_config_created/body.txt.j2
Original file line number Diff line number Diff line change
@@ -1,18 +1,29 @@
{% extends "base.txt.j2" %}

{% if saved_config.type == "GitHub" %}
{% set ci_provider = "GitHub Actions" %}
{% elif saved_config.type == "GitLab" %}
{% set ci_provider = "GitLab CI" %}
{% endif %}

{% block content %}
Hello {{ recipient }}!

{% 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.
You added a new "Trusted Publishing" configuration for {{ ci_provider }} 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.
crates.io user {{ auth_user.gh_login }} added a new "Trusted Publishing" configuration for {{ ci_provider }} to a crate that you manage ("{{ krate.name }}"). Trusted publishers act as trusted users and can publish new versions of the crate automatically.
{%- endif %}

{% if saved_config.type == "GitHub" -%}
This configuration allows the workflow file at https://github.com/{{ saved_config.repository_owner }}/{{ saved_config.repository_name }}/blob/HEAD/.github/workflows/{{ saved_config.workflow_filename }} to publish new versions of this crate.
{%- if saved_config.environment %} The workflow must use the `{{ saved_config.environment }}` environment (https://github.com/{{ saved_config.repository_owner }}/{{ saved_config.repository_name }}/deployments/{{ saved_config.environment }}).
{%- endif %}

{% elif saved_config.type == "GitLab" -%}
This configuration allows the workflow file at https://gitlab.com/{{ saved_config.namespace }}/{{ saved_config.project }}/-/blob/HEAD/{{ saved_config.workflow_filepath }} to publish new versions of this crate.
{%- if saved_config.environment %} The workflow must use the `{{ saved_config.environment }}` environment.
{%- endif %}
{% endif %}
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.

If you are unable to revert the change and need to do so, you can email [email protected] for assistance.
Expand Down
18 changes: 15 additions & 3 deletions src/email/templates/trustpub_config_deleted/body.txt.j2
Original file line number Diff line number Diff line change
@@ -1,18 +1,30 @@
{% extends "base.txt.j2" %}

{% if config.type == "GitHub" %}
{% set ci_provider = "GitHub Actions" %}
{% elif config.type == "GitLab" %}
{% set ci_provider = "GitLab CI" %}
{% endif %}

{% block content %}
Hello {{ recipient }}!

{% if recipient == auth_user.gh_login -%}
You removed a "Trusted Publishing" configuration for GitHub Actions from your crate "{{ krate.name }}".
You removed a "Trusted Publishing" configuration for {{ ci_provider }} 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 }}").
crates.io user {{ auth_user.gh_login }} removed a "Trusted Publishing" configuration for {{ ci_provider }} from a crate that you manage ("{{ krate.name }}").
{%- endif %}

{% if config.type == "GitHub" -%}
The removed configuration was for the workflow file at https://github.com/{{ config.repository_owner }}/{{ config.repository_name }}/blob/HEAD/.github/workflows/{{ config.workflow_filename }}
{%- if config.environment %} using the `{{ config.environment }}` environment
{%- endif -%}
.

{% elif config.type == "GitLab" -%}
The removed configuration was for the workflow file at https://gitlab.com/{{ config.namespace }}/{{ config.project }}/-/blob/HEAD/{{ config.workflow_filepath }}
{%- if config.environment %} using the `{{ config.environment }}` environment
{%- endif -%}
.
{% endif %}
If you did not make this change and you think it was made maliciously, you can email [email protected] for assistance.
{% endblock %}