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
8 changes: 4 additions & 4 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions crates/defguard_core/src/handlers/openid_flow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ use defguard_common::db::{
oauth2client::OAuth2Client,
},
};
use defguard_mail::templates::new_device_ocid_login_mail;
use defguard_mail::templates::new_device_oidc_login_mail;
use openidconnect::{
AccessToken, AdditionalClaims, Audience, AuthUrl, AuthorizationCode,
EmptyAdditionalProviderMetadata, EmptyExtraTokenFields, EndUserEmail, EndUserFamilyName,
Expand Down Expand Up @@ -580,7 +580,7 @@ pub async fn secure_authorization(
app.save(&appstate.pool).await?;

let mut conn = appstate.pool.begin().await?;
new_device_ocid_login_mail(
new_device_oidc_login_mail(
&session_info.user.email,
&mut conn,
Some(&session_info.session.into()),
Expand Down
24 changes: 9 additions & 15 deletions crates/defguard_gateway_manager/src/handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,15 +51,18 @@ use tokio::{
time::sleep,
};
use tokio_stream::wrappers::UnboundedReceiverStream;
use tonic::{Code, Status, transport::Endpoint};
use tonic::{
Code, Status,
transport::{Channel, Endpoint},
};

use crate::{Client, TEN_SECS, error::GatewayError};

#[cfg(test)]
use crate::GatewayManagerTestSupport;

#[cfg(test)]
#[derive(Debug, Default)]
#[derive(Default)]
struct GatewayTestTransport {
socket_path: Option<PathBuf>,
}
Expand Down Expand Up @@ -129,17 +132,11 @@ impl GatewayHandler {
}

#[cfg(not(test))]
fn connect_channel(
&self,
endpoint: Endpoint,
) -> Result<tonic::transport::Channel, GatewayError> {
fn connect_channel(&self, endpoint: &Endpoint) -> Result<Channel, GatewayError> {
self.connect_tls_channel(endpoint)
}

fn connect_tls_channel(
&self,
endpoint: Endpoint,
) -> Result<tonic::transport::Channel, GatewayError> {
fn connect_tls_channel(&self, endpoint: &Endpoint) -> Result<Channel, GatewayError> {
let settings = Settings::get_current_settings();
let Some(ca_cert_der) = settings.ca_cert_der else {
return Err(GatewayError::EndpointError(
Expand Down Expand Up @@ -371,7 +368,7 @@ impl GatewayHandler {
let endpoint = self.endpoint()?;
let uri = endpoint.uri().to_string();

let channel = self.connect_channel(endpoint)?;
let channel = self.connect_channel(&endpoint)?;

debug!("Connecting to Gateway {uri}");
let interceptor = ClientVersionInterceptor::new(
Expand Down Expand Up @@ -553,10 +550,7 @@ impl GatewayHandler {
.map_or(TEN_SECS, GatewayManagerTestSupport::handler_reconnect_delay)
}

fn connect_channel(
&self,
endpoint: Endpoint,
) -> Result<tonic::transport::Channel, GatewayError> {
fn connect_channel(&self, endpoint: &Endpoint) -> Result<Channel, GatewayError> {
if let Some(socket_path) = self.test_transport.socket_path().cloned() {
return Ok(endpoint.connect_with_connector_lazy(tower::service_fn(
move |_: tonic::transport::Uri| {
Expand Down
60 changes: 44 additions & 16 deletions crates/defguard_mail/src/mail.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,11 +79,15 @@ pub enum MailError {
InvalidPort(i32),
}

/// Mail message
#[derive(Debug)]
pub struct Mail {
pub(crate) to: String,
pub(crate) subject: String,
content: String,
// HTML version of the message.
html: String,
// Plain text version of the message.
text: String,
context: Context,
attachments: Vec<Attachment>, // text/plain
images: Vec<(String, Vec<u8>)>, // image/png
Expand All @@ -92,7 +96,7 @@ pub struct Mail {
impl Mail {
/// Create new [`Mail`].
#[must_use]
pub fn new<T>(to: T, subject: String, content: String) -> Mail
pub fn new<T>(to: T, subject: String, html: String, text: String) -> Mail
where
T: Into<String>,
{
Expand All @@ -107,7 +111,8 @@ impl Mail {
Self {
to: to.into(),
subject,
content,
html,
text,
context: Context::new(),
attachments: Vec::new(),
images,
Expand All @@ -126,12 +131,6 @@ impl Mail {
&self.subject
}

/// Getter for `content`.
#[must_use]
pub fn content(&self) -> &str {
&self.content
}

/// Add to context.
pub fn add_to_context<K, V>(&mut self, key: K, value: &V)
where
Expand Down Expand Up @@ -171,8 +170,8 @@ impl Mail {
.to(Mailbox::from_str(&self.to)?)
.subject(self.subject);

let plain = SinglePart::plain("PLAIN IS NOT AVAILABLE AT THE MOMENT.".to_string());
let html = SinglePart::html(self.content);
let plain = SinglePart::plain(self.text);
let html = SinglePart::html(self.html);
let image_png = "image/png".parse::<ContentType>().unwrap();
let mut related = MultiPart::related().singlepart(html);
for (name, bytes) in self.images {
Expand Down Expand Up @@ -284,7 +283,7 @@ pub enum MailMessage {
NewAccount,
NewDevice,
NewDeviceLogin,
NewDeviceOCIDLogin,
NewDeviceOIDCLogin,
/// Gateway has disconnected.
GatewayDisconnect,
/// Gateway has reconnected.
Expand Down Expand Up @@ -319,7 +318,7 @@ impl MailMessage {
Self::NewAccount => "Defguard: User enrollment",
Self::NewDevice => "Defguard: new device added to your account",
Self::NewDeviceLogin => "Defguard: New device logged in to your account",
Self::NewDeviceOCIDLogin => "New login to OCID application",
Self::NewDeviceOIDCLogin => "New login to OIDC application",
Self::GatewayDisconnect => "Defguard: Gateway disconnected",
Self::GatewayReconnect => "Defguard: Gateway reconnected",
Self::MFAActivation => "Multi-Factor Authentication activation",
Expand All @@ -342,7 +341,7 @@ impl MailMessage {
Self::NewAccount => "new-account",
Self::NewDevice => "new-device",
Self::NewDeviceLogin => "new-device-login",
Self::NewDeviceOCIDLogin => "new-device-ocid-login",
Self::NewDeviceOIDCLogin => "new-device-oidc-login",
Self::GatewayDisconnect => "gateway-disconnect",
Self::GatewayReconnect => "gateway-reconnect",
Self::MFAActivation => "mfa-activation",
Expand All @@ -364,7 +363,7 @@ impl MailMessage {
Self::NewAccount => include_str!("../templates/new-account.mjml"),
Self::NewDevice => include_str!("../templates/new-device.mjml"),
Self::NewDeviceLogin => include_str!("../templates/new-device-login.mjml"),
Self::NewDeviceOCIDLogin => include_str!("../templates/new-device-ocid-login.mjml"),
Self::NewDeviceOIDCLogin => include_str!("../templates/new-device-oidc-login.mjml"),
Self::GatewayDisconnect => include_str!("../templates/gateway-disconnected.mjml"),
Self::GatewayReconnect => include_str!("../templates/gateway-reconnected.mjml"),
Self::MFAActivation => include_str!("../templates/mfa-activation.mjml"),
Expand All @@ -379,6 +378,30 @@ impl MailMessage {
}
}

pub(crate) const fn text_template(&self) -> &str {
match self {
Self::Test => include_str!("../templates/test.text"),
Self::Welcome => include_str!("../templates/enrollment-welcome.text"),
Self::SupportData => include_str!("../templates/support-data.text"),
Self::DesktopStart => include_str!("../templates/desktop-start.text"),
Self::NewAccount => include_str!("../templates/new-account.text"),
Self::NewDevice => include_str!("../templates/new-device.text"),
Self::NewDeviceLogin => include_str!("../templates/new-device-login.text"),
Self::NewDeviceOIDCLogin => include_str!("../templates/new-device-oidc-login.text"),
Self::GatewayDisconnect => include_str!("../templates/gateway-disconnected.text"),
Self::GatewayReconnect => include_str!("../templates/gateway-reconnected.text"),
Self::MFAActivation => include_str!("../templates/mfa-activation.text"),
Self::MFAConfigured => include_str!("../templates/mfa-configured.text"),
Self::MFACode => include_str!("../templates/mfa-code.text"),
Self::PasswordReset => include_str!("../templates/password-reset.text"),
Self::PasswordResetDone => include_str!("../templates/password-reset-done.text"),
Self::UserImportBlocked => include_str!("../templates/plain-notification.text"),
Self::EnrollmentNotification => {
include_str!("../templates/enrollment-admin-notification.text")
}
}
}

/// Fill `Context` from database.
pub(crate) async fn fill_context(
&self,
Expand All @@ -401,13 +424,18 @@ impl MailMessage {
context: &Context,
to: &str,
) -> Result<Mail, TemplateError> {
// Build HTML message.
tera.add_raw_template(self.template_name(), self.mjml_template())?;
let processed = tera.render(self.template_name(), context)?;
let parsed = mrml::parse(processed)?;
let opts = mrml::prelude::render::RenderOptions::default();
let html = parsed.element.render(&opts)?;

let mut mail = Mail::new(to, self.subject(), html);
// Build plain text message.
tera.add_raw_template(self.template_name(), self.text_template())?;
let text = tera.render(self.template_name(), context)?;

let mut mail = Mail::new(to, self.subject(), html, text);
// Add PNG images.
match self {
Self::NewAccount => {
Expand Down
4 changes: 2 additions & 2 deletions crates/defguard_mail/src/templates.rs
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,7 @@ pub async fn new_device_login_mail(
}

/// New device login from OpenID Connect.
pub async fn new_device_ocid_login_mail(
pub async fn new_device_oidc_login_mail(
to: &str,
conn: &mut PgConnection,
session: Option<&SessionContext>,
Expand All @@ -334,7 +334,7 @@ pub async fn new_device_ocid_login_mail(
context.insert("oauth2client_name", &oauth2client_name);
context.insert("profile_url", &url);

let message = MailMessage::NewDeviceOCIDLogin;
let message = MailMessage::NewDeviceOIDCLogin;
message.fill_context(conn, &mut context).await?;
message.mail(&mut tera, &context, to)?.send_and_forget();

Expand Down
4 changes: 2 additions & 2 deletions crates/defguard_mail/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -286,13 +286,13 @@ fn send_new_device_login_mail(_: PgPoolOptions, options: PgConnectOptions) {

#[ignore = "requires SMTP server"]
#[sqlx::test]
fn send_new_device_ocid_login_mail(_: PgPoolOptions, options: PgConnectOptions) {
fn send_new_device_oidc_login_mail(_: PgPoolOptions, options: PgConnectOptions) {
let pool = setup_pool(options).await;
set_smtp_settings(&pool).await;

let mut conn = pool.begin().await.unwrap();
let client_name = "RemoteApp";
templates::new_device_ocid_login_mail(
templates::new_device_oidc_login_mail(
&env::var("SMTP_TO").unwrap(),
&mut conn,
None,
Expand Down
26 changes: 13 additions & 13 deletions crates/defguard_mail/templates/base.mjml
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@
<mj-font name="Geist" href="https://fonts.googleapis.com/css2?family=Geist:wght@100..900&family=IBM+Plex+Mono&display=swaphttps://fonts.googleapis.com/css2?family=Geist:wght@100..900&display=swap" />
<mj-attributes>
<mj-all padding="0" />
<mj-class name="t-title-h1" font-size="32px" font-weight="600" line-height="44px" font-family="Geist" color="inherit" />
<mj-class name="t-title-h3" font-size="24px" font-weight="600" line-height="32px" font-family="Geist" color="inherit" />
<mj-class name="t-body-primary-600" font-size="16px" font-weight="600" line-height="24px" font-family="Geist" color="inherit" />
<mj-class name="t-body-primary-400" font-size="16px" font-weight="400" line-height="24px" font-family="Geist" color="inherit" />
<mj-class name="t-body-sm-400" font-size="14px" font-weight="400" line-height="20px" font-family="Geist" color="inherit" />
<mj-class name="t-body-sm-500" font-size="14px" font-weight="500" line-height="20px" font-family="Geist" color="inherit" />
<mj-class name="t-body-xs-400" font-size="12px" font-weight="400" line-height="16px" font-family="Geist" color="inherit" />
<mj-class name="t-body-xs-500" font-size="12px" font-weight="500" line-height="16px" font-family="Geist" color="inherit" />
<mj-class name="t-title-h1" font-size="32px" font-weight="600" line-height="44px" font-family="Geist, Arial, sans-serif" color="inherit" />
<mj-class name="t-title-h3" font-size="24px" font-weight="600" line-height="32px" font-family="Geist, Arial, sans-serif" color="inherit" />
<mj-class name="t-body-primary-600" font-size="16px" font-weight="600" line-height="24px" font-family="Geist, Arial, sans-serif" color="inherit" />
<mj-class name="t-body-primary-400" font-size="16px" font-weight="400" line-height="24px" font-family="Geist, Arial, sans-serif" color="inherit" />
<mj-class name="t-body-sm-400" font-size="14px" font-weight="400" line-height="20px" font-family="Geist, Arial, sans-serif" color="inherit" />
<mj-class name="t-body-sm-500" font-size="14px" font-weight="500" line-height="20px" font-family="Geist, Arial, sans-serif" color="inherit" />
<mj-class name="t-body-xs-400" font-size="12px" font-weight="400" line-height="16px" font-family="Geist, Arial, sans-serif" color="inherit" />
<mj-class name="t-body-xs-500" font-size="12px" font-weight="500" line-height="16px" font-family="Geist, Arial, sans-serif" color="inherit" />
<mj-class name="divider" border-width="1px" border-style="solid" border-color="#DFE3E9" />
<mj-class name="s-5xl" padding="0px 0px 48px 0px" />
<mj-class name="s-4xl" padding="0px 0px 40px 0px" />
Expand All @@ -21,8 +21,8 @@
<mj-class name="s-md" padding="0px 0px 12px 0px" />
<mj-class name="s-sm" padding="0px 0px 8px 0px" />
<mj-class name="s-xs" padding="0px 0px 4px 0px" />
<mj-class name="dg-button" border="1px solid #3961DB" padding="0" margin="0" inner-padding="13px 15px" background-color="#3961DB" border-radius="8px" color="#ffffff" font-family="Geist" font-size="14px" font-weight="400" />
<mj-class name="dg-button-outlined" border="1px solid #3961DB" padding="0" margin="0" inner-padding="13px 15px" background-color="#fff" border-radius="8px" color="#3961DB" font-family="Geist" font-size="14px" font-weight="400" />
<mj-class name="dg-button" border="1px solid #3961DB" padding="0" margin="0" inner-padding="13px 15px" background-color="#3961DB" border-radius="8px" color="#ffffff" font-family="Geist, Arial, sans-serif" font-size="14px" font-weight="400" />
<mj-class name="dg-button-outlined" border="1px solid #3961DB" padding="0" margin="0" inner-padding="13px 15px" background-color="#fff" border-radius="8px" color="#3961DB" font-family="Geist, Arial, sans-serif" font-size="14px" font-weight="400" />
{% block attributes %}
{% endblock attributes %}
</mj-attributes>
Expand All @@ -33,7 +33,7 @@
}

.t-titles-h1 {
font-family: Geist;
font-family: Geist, Arial, sans-serif;
font-size: 32px;
line-height: 44px;
font-weight: 600;
Expand Down Expand Up @@ -147,14 +147,14 @@
}

.dg-table td:not(:first-child) {
font-family: Geist;
font-family: Geist, Arial, sans-serif;
font-size: 14px;
font-weight: 500;
color: #141517;
}

.dg-table td:first-child {
font-family: Geist;
font-family: Geist, Arial, sans-serif;
font-size: 14px;
line-height: 20px;
font-weight: 400;
Expand Down
2 changes: 1 addition & 1 deletion crates/defguard_mail/templates/desktop-start.text
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{{ title }}
{{ subtitle }}
{% if subtitle %}{{ subtitle }}{% endif %}

{{ label_url }}: {{ url }}
{{ label_token }}: {{ token }}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{{ title }}
{% if subtitle %}{{ subtitle }}{% endif %}

{{ user_name }} {{ message }}
{{ goodday }}
2 changes: 2 additions & 0 deletions crates/defguard_mail/templates/enrollment-welcome.mjml
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,6 @@
</mj-column>
</mj-section>

{{ macros::footer_divider() }}

{% endblock content %}
1 change: 1 addition & 0 deletions crates/defguard_mail/templates/enrollment-welcome.text
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{{ welcome_message_content }}
6 changes: 6 additions & 0 deletions crates/defguard_mail/templates/gateway-disconnected.text
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{{ title }}
{% if subtitle %}{{ subtitle }}{% endif %}

{{ gateway_label }}: {{ gateway_name }}
{{ ip_address_label }}: {{ ip_address }}
{{ location_label }}: {{ location_name }}
6 changes: 6 additions & 0 deletions crates/defguard_mail/templates/gateway-reconnected.text
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{{ title }}
{% if subtitle %}{{ subtitle }}{% endif %}

{{ gateway_label }}: {{ gateway_name }}
{{ ip_address_label }}: {{ ip_address }}
{{ location_label }}: {{ location_name }}
2 changes: 1 addition & 1 deletion crates/defguard_mail/templates/macros.mjml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@

{% macro action_link(text, href, css_class="", mj_class="") %}
<mj-text css-class="{{ css_class }}" mj-class="{{ mj_class }}">
<a mj-class="t-body-sm-400" css-class="fg-action-c link" href="{{ href }}" style="color: #3961DB; text-decoration: none; font-family: Geist; font-weight: 400; font-size: 14px;">
<a mj-class="t-body-sm-400" css-class="fg-action-c link" href="{{ href }}" style="color: #3961DB; text-decoration: none; font-family: Geist, Arial, sans-serif; font-weight: 400; font-size: 14px;">
{{ text }}
</a>
</mj-text>
Expand Down
7 changes: 7 additions & 0 deletions crates/defguard_mail/templates/mfa-activation.text
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{{ title }}
{% if subtitle %}{{ subtitle }}{% endif %}

{{ code }}

{{ code_is_valid }} {{ timeout }}
{{ datetime }}
Loading
Loading