From: Christoph Heiss <c.heiss@proxmox.com>
To: pve-devel@lists.proxmox.com
Subject: [pve-devel] [PATCH installer v2 5/7] tui: use email regex from HTML specification for validation
Date: Wed, 2 Oct 2024 14:27:26 +0200 [thread overview]
Message-ID: <20241002122933.628461-6-c.heiss@proxmox.com> (raw)
In-Reply-To: <20241002122933.628461-1-c.heiss@proxmox.com>
That regex should be a lot more accurate in what it allows - if it's
good enough for the HTML spec, it should be for us too.
Signed-off-by: Christoph Heiss <c.heiss@proxmox.com>
---
Changes v1 -> v2:
* move `EMAIL_DEFAULT_PLACEHOLDER` constant to
proxmox-installer-common/lib.rs
proxmox-installer-common/Cargo.toml | 1 +
proxmox-installer-common/src/lib.rs | 3 +++
proxmox-installer-common/src/options.rs | 25 +++++++++++++++++++++++++
proxmox-tui-installer/Cargo.toml | 1 -
proxmox-tui-installer/src/main.rs | 18 +++++-------------
proxmox-tui-installer/src/options.rs | 3 ++-
6 files changed, 36 insertions(+), 15 deletions(-)
diff --git a/proxmox-installer-common/Cargo.toml b/proxmox-installer-common/Cargo.toml
index 70f828a..e151b0e 100644
--- a/proxmox-installer-common/Cargo.toml
+++ b/proxmox-installer-common/Cargo.toml
@@ -8,6 +8,7 @@ exclude = [ "build", "debian" ]
homepage = "https://www.proxmox.com"
[dependencies]
+anyhow.workspace = true
regex = "1.7"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
diff --git a/proxmox-installer-common/src/lib.rs b/proxmox-installer-common/src/lib.rs
index 850e825..028b43c 100644
--- a/proxmox-installer-common/src/lib.rs
+++ b/proxmox-installer-common/src/lib.rs
@@ -4,3 +4,6 @@ pub mod setup;
pub mod utils;
pub const RUNTIME_DIR: &str = "/run/proxmox-installer";
+
+/// Default placeholder value for the administrator email address.
+pub const EMAIL_DEFAULT_PLACEHOLDER: &str = "mail@example.invalid";
diff --git a/proxmox-installer-common/src/options.rs b/proxmox-installer-common/src/options.rs
index 9375ded..ea06eee 100644
--- a/proxmox-installer-common/src/options.rs
+++ b/proxmox-installer-common/src/options.rs
@@ -1,5 +1,8 @@
+use anyhow::{bail, Result};
+use regex::Regex;
use serde::Deserialize;
use std::net::{IpAddr, Ipv4Addr};
+use std::sync::OnceLock;
use std::{cmp, fmt};
use crate::setup::{
@@ -403,6 +406,28 @@ impl NetworkOptions {
}
}
+/// Validates an email address using the regex for <input type="email" /> elements
+/// as defined in the HTML specification [0].
+/// Using that /should/ cover all possible cases that are encountered in the wild.
+///
+/// It additionally checks whether the email our default email placeholder value.
+///
+/// [0] https://html.spec.whatwg.org/multipage/input.html#valid-e-mail-address
+pub fn email_validate(email: &str) -> Result<()> {
+ static RE: OnceLock<Regex> = OnceLock::new();
+ let re = RE.get_or_init(|| {
+ Regex::new(r"^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$").unwrap()
+ });
+
+ if !re.is_match(email) {
+ bail!("Email does not look like a valid address (user@domain.tld)")
+ } else if email == crate::EMAIL_DEFAULT_PLACEHOLDER {
+ bail!("Invalid (default) email address")
+ }
+
+ Ok(())
+}
+
#[cfg(test)]
mod tests {
use super::*;
diff --git a/proxmox-tui-installer/Cargo.toml b/proxmox-tui-installer/Cargo.toml
index 2516468..618904c 100644
--- a/proxmox-tui-installer/Cargo.toml
+++ b/proxmox-tui-installer/Cargo.toml
@@ -11,5 +11,4 @@ homepage = "https://www.proxmox.com"
cursive = { version = "0.21", default-features = false, features = ["crossterm-backend"] }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
-regex = "1.7"
proxmox-installer-common = { path = "../proxmox-installer-common" }
diff --git a/proxmox-tui-installer/src/main.rs b/proxmox-tui-installer/src/main.rs
index c36daa5..d306969 100644
--- a/proxmox-tui-installer/src/main.rs
+++ b/proxmox-tui-installer/src/main.rs
@@ -13,13 +13,11 @@ use cursive::{
Cursive, CursiveRunnable, ScreenId, View, XY,
};
-use regex::Regex;
-
mod options;
use options::{InstallerOptions, PasswordOptions};
use proxmox_installer_common::{
- options::{BootdiskOptions, NetworkOptions, TimezoneOptions},
+ options::{email_validate, BootdiskOptions, NetworkOptions, TimezoneOptions},
setup::{installer_setup, LocaleInfo, ProxmoxProduct, RuntimeInfo, SetupInfo},
utils::Fqdn,
};
@@ -448,18 +446,12 @@ fn password_dialog(siv: &mut Cursive) -> InstallerView {
.get_value::<EditView, _>(2)
.ok_or("failed to retrieve email")?;
- let email_regex =
- Regex::new(r"^[\w\+\-\~]+(\.[\w\+\-\~]+)*@[a-zA-Z0-9\-]+(\.[a-zA-Z0-9\-]+)*$")
- .unwrap();
-
if root_password.len() < 5 {
- Err("password too short, must be at least 5 characters long")
+ Err("password too short, must be at least 5 characters long".to_owned())
} else if root_password != confirm_password {
- Err("passwords do not match")
- } else if email == "mail@example.invalid" {
- Err("invalid email address")
- } else if !email_regex.is_match(&email) {
- Err("Email does not look like a valid address (user@domain.tld)")
+ Err("passwords do not match".to_owned())
+ } else if let Err(err) = email_validate(&email) {
+ Err(err.to_string())
} else {
Ok(PasswordOptions {
root_password,
diff --git a/proxmox-tui-installer/src/options.rs b/proxmox-tui-installer/src/options.rs
index 19992ca..b14ecf7 100644
--- a/proxmox-tui-installer/src/options.rs
+++ b/proxmox-tui-installer/src/options.rs
@@ -5,6 +5,7 @@ use proxmox_installer_common::{
BootdiskOptions, BtrfsRaidLevel, FsType, NetworkOptions, TimezoneOptions, ZfsRaidLevel,
},
setup::LocaleInfo,
+ EMAIL_DEFAULT_PLACEHOLDER,
};
pub const FS_TYPES: &[FsType] = {
@@ -33,7 +34,7 @@ pub struct PasswordOptions {
impl Default for PasswordOptions {
fn default() -> Self {
Self {
- email: "mail@example.invalid".to_string(),
+ email: EMAIL_DEFAULT_PLACEHOLDER.to_string(),
root_password: String::new(),
}
}
--
2.46.0
_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
next prev parent reply other threads:[~2024-10-02 12:30 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-10-02 12:27 [pve-devel] [PATCH installer v2 0/7] use email regex from HTML spec " Christoph Heiss
2024-10-02 12:27 ` [pve-devel] [PATCH installer v2 1/7] cargo: convert `anyhow` to workspace dependency Christoph Heiss
2024-10-02 12:27 ` [pve-devel] [PATCH installer v2 2/7] tui: fix new clippy lint Christoph Heiss
2024-10-02 12:27 ` [pve-devel] [PATCH installer v2 3/7] auto-installer: drop some unneeded `pub` modifiers Christoph Heiss
2024-10-02 12:27 ` [pve-devel] [PATCH installer v2 4/7] auto-installer: print full anyhow message on failure Christoph Heiss
2024-10-02 12:27 ` Christoph Heiss [this message]
2024-10-02 12:27 ` [pve-devel] [PATCH installer v2 6/7] auto-installer: validate `global.mailto` answer option Christoph Heiss
2024-10-02 12:27 ` [pve-devel] [PATCH installer v2 7/7] proxinstall: use email regex from HTML specification for validation Christoph Heiss
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20241002122933.628461-6-c.heiss@proxmox.com \
--to=c.heiss@proxmox.com \
--cc=pve-devel@lists.proxmox.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox