committed by
nitnelave
parent
f0bbcfd2c8
commit
d0cdfa97c7
@@ -1,6 +1,7 @@
|
||||
use clap::{builder::EnumValueParser, Parser};
|
||||
use lettre::message::Mailbox;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use url::Url;
|
||||
|
||||
/// lldap is a lightweight LDAP server
|
||||
#[derive(Debug, Parser, Clone)]
|
||||
@@ -82,7 +83,7 @@ pub struct RunOpts {
|
||||
|
||||
/// URL of the server, for password reset links.
|
||||
#[clap(long, env = "LLDAP_HTTP_URL")]
|
||||
pub http_url: Option<String>,
|
||||
pub http_url: Option<Url>,
|
||||
|
||||
/// Database connection URL
|
||||
#[clap(short, long, env = "LLDAP_DATABASE_URL")]
|
||||
|
||||
@@ -11,6 +11,7 @@ use lettre::message::Mailbox;
|
||||
use lldap_auth::opaque::{server::ServerSetup, KeyPair};
|
||||
use secstr::SecUtf8;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use url::Url;
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Serialize, derive_builder::Builder)]
|
||||
#[builder(pattern = "owned")]
|
||||
@@ -100,8 +101,8 @@ pub struct Configuration {
|
||||
pub smtp_options: MailOptions,
|
||||
#[builder(default)]
|
||||
pub ldaps_options: LdapsOptions,
|
||||
#[builder(default = r#"String::from("http://localhost")"#)]
|
||||
pub http_url: String,
|
||||
#[builder(default = r#"Url::parse("http://localhost").unwrap()"#)]
|
||||
pub http_url: Url,
|
||||
#[serde(skip)]
|
||||
#[builder(field(private), default = "None")]
|
||||
server_setup: Option<ServerSetup>,
|
||||
@@ -237,7 +238,7 @@ impl ConfigOverrider for RunOpts {
|
||||
}
|
||||
|
||||
if let Some(url) = self.http_url.as_ref() {
|
||||
config.http_url = url.to_string();
|
||||
config.http_url = url.clone();
|
||||
}
|
||||
|
||||
if let Some(database_url) = self.database_url.as_ref() {
|
||||
|
||||
@@ -6,7 +6,13 @@ use lettre::{
|
||||
};
|
||||
use tracing::debug;
|
||||
|
||||
async fn send_email(to: Mailbox, subject: &str, body: String, options: &MailOptions) -> Result<()> {
|
||||
async fn send_email(
|
||||
to: Mailbox,
|
||||
subject: &str,
|
||||
body: String,
|
||||
options: &MailOptions,
|
||||
server_url: &url::Url,
|
||||
) -> Result<()> {
|
||||
let from = options
|
||||
.from
|
||||
.clone()
|
||||
@@ -17,6 +23,14 @@ async fn send_email(to: Mailbox, subject: &str, body: String, options: &MailOpti
|
||||
&to, &from, &options.user, &options.server, options.port
|
||||
);
|
||||
let email = Message::builder()
|
||||
.message_id(Some(format!(
|
||||
"<{}@{}>",
|
||||
uuid::Uuid::new_v1(
|
||||
uuid::Timestamp::now(uuid::NoContext),
|
||||
"lldap!".as_bytes().try_into().unwrap()
|
||||
),
|
||||
server_url.domain().unwrap_or_default()
|
||||
)))
|
||||
.from(from)
|
||||
.reply_to(reply_to)
|
||||
.to(to)
|
||||
@@ -58,24 +72,34 @@ pub async fn send_password_reset_email(
|
||||
username: &str,
|
||||
to: &str,
|
||||
token: &str,
|
||||
domain: &str,
|
||||
server_url: &url::Url,
|
||||
options: &MailOptions,
|
||||
) -> Result<()> {
|
||||
let to = to.parse()?;
|
||||
let mut reset_url = server_url.clone();
|
||||
reset_url
|
||||
.path_segments_mut()
|
||||
.unwrap()
|
||||
.extend(["reset-password", "step2", token]);
|
||||
let body = format!(
|
||||
"Hello {},
|
||||
This email has been sent to you in order to validate your identity.
|
||||
If you did not initiate the process your credentials might have been
|
||||
compromised. You should reset your password and contact an administrator.
|
||||
|
||||
To reset your password please visit the following URL: {}/reset-password/step2/{}
|
||||
To reset your password please visit the following URL: {}
|
||||
|
||||
Please contact an administrator if you did not initiate the process.",
|
||||
username,
|
||||
domain.trim_end_matches('/'),
|
||||
token
|
||||
username, reset_url
|
||||
);
|
||||
send_email(to, "[LLDAP] Password reset requested", body, options).await
|
||||
send_email(
|
||||
to,
|
||||
"[LLDAP] Password reset requested",
|
||||
body,
|
||||
options,
|
||||
server_url,
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn send_test_email(to: Mailbox, options: &MailOptions) -> Result<()> {
|
||||
@@ -84,6 +108,7 @@ pub async fn send_test_email(to: Mailbox, options: &MailOptions) -> Result<()> {
|
||||
"LLDAP test email",
|
||||
"The test is successful! You can send emails from LLDAP".to_string(),
|
||||
options,
|
||||
&url::Url::parse("http://localhost").unwrap(),
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
@@ -87,7 +87,7 @@ fn http_config<Backend>(
|
||||
backend_handler: Backend,
|
||||
jwt_secret: secstr::SecUtf8,
|
||||
jwt_blacklist: HashSet<u64>,
|
||||
server_url: String,
|
||||
server_url: url::Url,
|
||||
mail_options: MailOptions,
|
||||
) where
|
||||
Backend: TcpBackendHandler + BackendHandler + LoginHandler + OpaqueHandler + Clone + 'static,
|
||||
@@ -132,7 +132,7 @@ pub(crate) struct AppState<Backend> {
|
||||
pub backend_handler: AccessControlledBackendHandler<Backend>,
|
||||
pub jwt_key: Hmac<Sha512>,
|
||||
pub jwt_blacklist: RwLock<HashSet<u64>>,
|
||||
pub server_url: String,
|
||||
pub server_url: url::Url,
|
||||
pub mail_options: MailOptions,
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user