Skip to content

Commit

Permalink
Merge pull request #1741 from fastn-stack/auth/html-email
Browse files Browse the repository at this point in the history
Auth/html email
  • Loading branch information
amitu authored Feb 8, 2024
2 parents eaf615f + 87452ae commit f5bcc27
Show file tree
Hide file tree
Showing 5 changed files with 105 additions and 19 deletions.
72 changes: 56 additions & 16 deletions fastn-core/src/auth/email_password.rs
Original file line number Diff line number Diff line change
Expand Up @@ -154,14 +154,9 @@ pub(crate) async fn create_user(

tracing::info!("fastn_user email inserted");

let conf_link = create_and_send_confirmation_email(
email.0.to_string(),
db_pool,
req,
&req_config.config.ds,
next,
)
.await?;
let conf_link =
create_and_send_confirmation_email(email.0.to_string(), db_pool, req, req_config, next)
.await?;

let resp_body = serde_json::json!({
"user": user,
Expand Down Expand Up @@ -433,7 +428,7 @@ pub(crate) async fn confirm_email(

pub(crate) async fn resend_email(
req: &fastn_core::http::Request,
ds: &fastn_ds::DocumentStore,
req_config: &mut fastn_core::RequestConfig,
db_pool: &fastn_core::db::PgPool,
next: String,
) -> fastn_core::Result<fastn_core::http::Response> {
Expand All @@ -457,7 +452,7 @@ pub(crate) async fn resend_email(
}
};

create_and_send_confirmation_email(email, db_pool, req, ds, next.clone()).await?;
create_and_send_confirmation_email(email, db_pool, req, req_config, next.clone()).await?;

// TODO: there's no GET /-/auth/login/ yet
// the client will have to create one for now
Expand All @@ -472,7 +467,7 @@ async fn create_and_send_confirmation_email(
email: String,
db_pool: &fastn_core::db::PgPool,
req: &fastn_core::http::Request,
ds: &fastn_ds::DocumentStore,
req_config: &mut fastn_core::RequestConfig,
next: String,
) -> fastn_core::Result<String> {
use diesel::prelude::*;
Expand Down Expand Up @@ -524,7 +519,7 @@ async fn create_and_send_confirmation_email(

let confirmation_link = confirmation_link(req, stored_key, next);

let mailer = fastn_core::mail::Mailer::from_env(ds).await;
let mailer = fastn_core::mail::Mailer::from_env(&req_config.config.ds).await;

if mailer.is_err() {
return Err(fastn_core::Error::generic(
Expand All @@ -539,7 +534,7 @@ async fn create_and_send_confirmation_email(

let mut mailer = mailer.unwrap();

if let Ok(debug_mode) = ds.env("DEBUG").await {
if let Ok(debug_mode) = req_config.config.ds.env("DEBUG").await {
if debug_mode == "true" {
mailer.mock();
}
Expand All @@ -551,13 +546,55 @@ async fn create_and_send_confirmation_email(
.first(&mut conn)
.await?;

// To use auth. The package has to have auto import with alias `auth` setup
let path = req_config
.config
.package
.eval_auto_import("auth")
.unwrap()
.to_owned();

let path = path
.strip_prefix(format!("{}/", req_config.config.package.name).as_str())
.unwrap();

let content = req_config
.config
.ds
.read_to_string(&fastn_ds::Path::new(format!("{}.ftd", path)))
.await?;

let auth_doc = fastn_core::Document {
package_name: req_config.config.package.name.clone(),
id: path.to_string(),
content,
parent_path: fastn_ds::Path::new("/"),
};

let main_ftd_doc = fastn_core::doc::interpret_helper(
auth_doc.id_with_package().as_str(),
auth_doc.content.as_str(),
req_config,
"/",
false,
0,
)
.await?;

let html_email_templ = format!(
"{}/{}#confirmation-mail-html",
req_config.config.package.name, path
);

let html: String = main_ftd_doc.get(&html_email_templ).unwrap();

mailer
.send_raw(
format!("{} <{}>", name, email)
.parse::<lettre::message::Mailbox>()
.unwrap(),
"Verify your email",
confirmation_mail_body(&confirmation_link),
confirmation_mail_body(html, &confirmation_link),
)
.await
.map_err(|e| fastn_core::Error::generic(format!("failed to send email: {e}")))?;
Expand All @@ -581,8 +618,11 @@ async fn key_expired(ds: &fastn_ds::DocumentStore, sent_at: chrono::DateTime<chr
<= chrono::offset::Utc::now()
}

fn confirmation_mail_body(link: &str) -> String {
format!("Use this link to verify your email: {link}")
fn confirmation_mail_body(content: String, link: &str) -> String {
// content will have a placeholder for the link
let content = content.replace("{{link}}", link);

content.to_string()
}

fn generate_key(length: usize) -> String {
Expand Down
3 changes: 1 addition & 2 deletions fastn-core/src/auth/routes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,8 +103,7 @@ pub async fn handle_auth(
.await
}
"/-/auth/resend-confirmation-email/" => {
fastn_core::auth::email_password::resend_email(&req, &req_config.config.ds, pool, next)
.await
fastn_core::auth::email_password::resend_email(&req, req_config, pool, next).await
}
"/-/auth/onboarding/" => {
fastn_core::auth::email_password::onboarding(&req, req_config, config, next).await
Expand Down
2 changes: 1 addition & 1 deletion fastn-core/src/library2022/processor/user_details.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/// currently returns the github user details
/// returns details of the logged in user
pub async fn process(
value: ftd::ast::VariableValue,
kind: ftd::interpreter::Kind,
Expand Down
2 changes: 2 additions & 0 deletions integration-tests/FASTN.ftd
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

-- fastn.package: integration-tests

-- fastn.auto-import: integration-tests/authy as auth

-- fastn.url-mappings:

/ftd/* -> http+proxy://fastn.com/ftd/*
Expand Down
45 changes: 45 additions & 0 deletions integration-tests/authy.ftd
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
-- string test: fsdkjflk

-- string confirmation-mail-html:
$always-include$: true

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Confirm your email</title>
</head>
<body>
<h1>Hello</h1>
<a href="{{link}}">Click on this text to confirm your email</a>
</body>
</html>


-- component email-confirmation-request-sent:

-- ftd.column:

-- ftd.text: We have sent you an email. Please verify.

-- end: ftd.column

-- end: email-confirmation-request-sent


-- component onboarding:

-- ftd.column:
-- ftd.text: welcome aboard, meine freundin
color: green

-- ftd.text: glad you're here, the next time you refresh this page you won't be here

-- ftd.text:

This is useful for doing onboarding stuff. collecting extra information about the user. Use sql processor or endpoint for now to do this stuff

-- end: ftd.column

-- end: onboarding

0 comments on commit f5bcc27

Please sign in to comment.