* [pbs-devel] [PATCH proxmox 1/4] proxmox-schema: use const_format to define static strings.
@ 2024-03-15 11:27 Dietmar Maurer
2024-03-15 11:27 ` [pbs-devel] [PATCH proxmox 2/4] proxmox-auth-api: " Dietmar Maurer
` (3 more replies)
0 siblings, 4 replies; 5+ messages in thread
From: Dietmar Maurer @ 2024-03-15 11:27 UTC (permalink / raw)
To: pbs-devel
Macro rules are not hygienic, and current rust macro visibility rules
are a nightmare. Using const_format::concatcp!() is a much cleaner
solution.
Signed-off-by: Dietmar Maurer <dietmar@proxmox.com>
---
Cargo.toml | 1 +
proxmox-schema/Cargo.toml | 3 ++-
proxmox-schema/src/api_types.rs | 12 +++++++-----
3 files changed, 10 insertions(+), 6 deletions(-)
diff --git a/Cargo.toml b/Cargo.toml
index 58d5a67..032ef65 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -55,6 +55,7 @@ base32 = "0.4"
base64 = "0.13"
bitflags = "1.2.1"
bytes = "1.0"
+const_format = "0.2"
crc32fast = "1"
crossbeam-channel = "0.5"
endian_trait = "0.6"
diff --git a/proxmox-schema/Cargo.toml b/proxmox-schema/Cargo.toml
index ae06818..1c150b2 100644
--- a/proxmox-schema/Cargo.toml
+++ b/proxmox-schema/Cargo.toml
@@ -11,6 +11,7 @@ exclude.workspace = true
[dependencies]
anyhow.workspace = true
+const_format = { workspace = true, optional = true }
lazy_static.workspace = true
regex.workspace = true
serde.workspace = true
@@ -33,7 +34,7 @@ default = []
api-macro = ["dep:proxmox-api-macro"]
upid-api-impl = [ "dep:libc", "dep:nix" ]
-api-types = []
+api-types = [ "dep:const_format" ]
# Testing only
test-harness = []
diff --git a/proxmox-schema/src/api_types.rs b/proxmox-schema/src/api_types.rs
index 0cec043..4e10ebb 100644
--- a/proxmox-schema/src/api_types.rs
+++ b/proxmox-schema/src/api_types.rs
@@ -1,10 +1,10 @@
//! The "basic" api types we generally require along with some of their macros.
+use const_format::concatcp;
use crate::{ApiStringFormat, Schema, StringSchema};
#[rustfmt::skip]
-#[macro_export]
-macro_rules! SAFE_ID_REGEX_STR { () => { r"(?:[A-Za-z0-9_][A-Za-z0-9._\-]*)" }; }
+const SAFE_ID_REGEX_STR: &str = r"(?:[A-Za-z0-9_][A-Za-z0-9._\-]*)";
const_regex! {
/// Regex for safe identifiers.
@@ -14,9 +14,11 @@ const_regex! {
/// contains further information why it is reasonable to restict
/// names this way. This is not only useful for filenames, but for
/// any identifier command line tools work with.
- pub SAFE_ID_REGEX = concat!(r"^", SAFE_ID_REGEX_STR!(), r"$");
- pub PASSWORD_REGEX = r"^[[:^cntrl:]]*$"; // everything but control characters
- pub SINGLE_LINE_COMMENT_REGEX = r"^[[:^cntrl:]]*$"; // everything but control characters
+ pub SAFE_ID_REGEX = concatcp!(r"^", SAFE_ID_REGEX_STR, r"$");
+ /// Password. Allow everything but control characters.
+ pub PASSWORD_REGEX = r"^[[:^cntrl:]]*$";
+ /// Single line comment. Allow everything but control characters.
+ pub SINGLE_LINE_COMMENT_REGEX = r"^[[:^cntrl:]]*$";
}
pub const SAFE_ID_FORMAT: ApiStringFormat = ApiStringFormat::Pattern(&SAFE_ID_REGEX);
--
2.39.2
^ permalink raw reply [flat|nested] 5+ messages in thread
* [pbs-devel] [PATCH proxmox 2/4] proxmox-auth-api: use const_format to define static strings
2024-03-15 11:27 [pbs-devel] [PATCH proxmox 1/4] proxmox-schema: use const_format to define static strings Dietmar Maurer
@ 2024-03-15 11:27 ` Dietmar Maurer
2024-03-15 11:27 ` [pbs-devel] [PATCH proxmox 3/4] proxmox-schema: add IP address regex/api-types Dietmar Maurer
` (2 subsequent siblings)
3 siblings, 0 replies; 5+ messages in thread
From: Dietmar Maurer @ 2024-03-15 11:27 UTC (permalink / raw)
To: pbs-devel
Signed-off-by: Dietmar Maurer <dietmar@proxmox.com>
---
proxmox-auth-api/Cargo.toml | 4 +--
proxmox-auth-api/src/types.rs | 62 ++++++++++-------------------------
2 files changed, 20 insertions(+), 46 deletions(-)
diff --git a/proxmox-auth-api/Cargo.toml b/proxmox-auth-api/Cargo.toml
index 6e4a626..ecea701 100644
--- a/proxmox-auth-api/Cargo.toml
+++ b/proxmox-auth-api/Cargo.toml
@@ -14,7 +14,7 @@ required-features = [ "pam-authenticator" ]
[dependencies]
anyhow.workspace = true
-
+const_format = { workspace = true, optional = true }
base64 = { workspace = true, optional = true }
lazy_static = { workspace = true, optional = true }
libc = { workspace = true, optional = true }
@@ -37,7 +37,7 @@ proxmox-tfa = { workspace = true, optional = true, features = [ "api" ] }
default = []
ticket = [ "dep:base64", "dep:percent-encoding", "dep:openssl" ]
-api-types = [ "dep:lazy_static", "dep:regex", "dep:serde", "dep:serde_plain", "dep:proxmox-schema" ]
+api-types = [ "dep:const_format", "dep:lazy_static", "dep:regex", "dep:serde", "dep:serde_plain", "dep:proxmox-schema" ]
api = [
"api-types",
"ticket",
diff --git a/proxmox-auth-api/src/types.rs b/proxmox-auth-api/src/types.rs
index 319ac4b..e11d0b1 100644
--- a/proxmox-auth-api/src/types.rs
+++ b/proxmox-auth-api/src/types.rs
@@ -27,62 +27,36 @@ use std::fmt;
use anyhow::{bail, format_err, Error};
use lazy_static::lazy_static;
use serde::{Deserialize, Serialize};
+use const_format::concatcp;
use proxmox_schema::{
api, const_regex, ApiStringFormat, ApiType, Schema, StringSchema, UpdaterType,
};
+use proxmox_schema::api_types::SAFE_ID_REGEX_STR;
+
// we only allow a limited set of characters
// colon is not allowed, because we store usernames in
// colon separated lists)!
// slash is not allowed because it is used as pve API delimiter
// also see "man useradd"
-#[macro_export]
-macro_rules! USER_NAME_REGEX_STR {
- () => {
- r"(?:[^\s:/[:cntrl:]]+)"
- };
-}
-#[macro_export]
-macro_rules! GROUP_NAME_REGEX_STR {
- () => {
- $crate::USER_NAME_REGEX_STR!()
- };
-}
-#[macro_export]
-macro_rules! TOKEN_NAME_REGEX_STR {
- () => {
- proxmox_schema::SAFE_ID_REGEX_STR!()
- };
-}
-#[macro_export]
-macro_rules! USER_ID_REGEX_STR {
- () => {
- concat!(
- $crate::USER_NAME_REGEX_STR!(),
- r"@",
- proxmox_schema::SAFE_ID_REGEX_STR!()
- )
- };
-}
-#[macro_export]
-macro_rules! APITOKEN_ID_REGEX_STR {
- () => {
- concat!(
- $crate::USER_ID_REGEX_STR!(),
- r"!",
- $crate::TOKEN_NAME_REGEX_STR!()
- )
- };
-}
+pub const USER_NAME_REGEX_STR: &str = r"(?:[^\s:/[:cntrl:]]+)";
+
+pub const GROUP_NAME_REGEX_STR: &str = USER_NAME_REGEX_STR;
+
+pub const TOKEN_NAME_REGEX_STR: &str = SAFE_ID_REGEX_STR;
+
+pub const USER_ID_REGEX_STR: &str = concatcp!(USER_NAME_REGEX_STR, r"@", SAFE_ID_REGEX_STR);
+
+pub const APITOKEN_ID_REGEX_STR: &str = concatcp!(USER_ID_REGEX_STR, r"!", TOKEN_NAME_REGEX_STR);
const_regex! {
- pub PROXMOX_USER_NAME_REGEX = concat!(r"^", USER_NAME_REGEX_STR!(), r"$");
- pub PROXMOX_TOKEN_NAME_REGEX = concat!(r"^", TOKEN_NAME_REGEX_STR!(), r"$");
- pub PROXMOX_USER_ID_REGEX = concat!(r"^", USER_ID_REGEX_STR!(), r"$");
- pub PROXMOX_APITOKEN_ID_REGEX = concat!(r"^", APITOKEN_ID_REGEX_STR!(), r"$");
- pub PROXMOX_AUTH_ID_REGEX = concat!(r"^", r"(?:", USER_ID_REGEX_STR!(), r"|", APITOKEN_ID_REGEX_STR!(), r")$");
- pub PROXMOX_GROUP_ID_REGEX = concat!(r"^", GROUP_NAME_REGEX_STR!(), r"$");
+ pub PROXMOX_USER_NAME_REGEX = concatcp!(r"^", USER_NAME_REGEX_STR, r"$");
+ pub PROXMOX_TOKEN_NAME_REGEX = concatcp!(r"^", TOKEN_NAME_REGEX_STR, r"$");
+ pub PROXMOX_USER_ID_REGEX = concatcp!(r"^", USER_ID_REGEX_STR, r"$");
+ pub PROXMOX_APITOKEN_ID_REGEX = concatcp!(r"^", APITOKEN_ID_REGEX_STR, r"$");
+ pub PROXMOX_AUTH_ID_REGEX = concatcp!(r"^", r"(?:", USER_ID_REGEX_STR, r"|", APITOKEN_ID_REGEX_STR, r")$");
+ pub PROXMOX_GROUP_ID_REGEX = concatcp!(r"^", GROUP_NAME_REGEX_STR, r"$");
}
pub const PROXMOX_USER_NAME_FORMAT: ApiStringFormat =
--
2.39.2
^ permalink raw reply [flat|nested] 5+ messages in thread
* [pbs-devel] [PATCH proxmox 3/4] proxmox-schema: add IP address regex/api-types
2024-03-15 11:27 [pbs-devel] [PATCH proxmox 1/4] proxmox-schema: use const_format to define static strings Dietmar Maurer
2024-03-15 11:27 ` [pbs-devel] [PATCH proxmox 2/4] proxmox-auth-api: " Dietmar Maurer
@ 2024-03-15 11:27 ` Dietmar Maurer
2024-03-15 11:27 ` [pbs-devel] [PATCH proxmox 4/4] proxmox-schema: moved common api types from pbs-api-types Dietmar Maurer
2024-03-19 10:14 ` [pbs-devel] applied-series: [PATCH proxmox 1/4] proxmox-schema: use const_format to define static strings Wolfgang Bumiller
3 siblings, 0 replies; 5+ messages in thread
From: Dietmar Maurer @ 2024-03-15 11:27 UTC (permalink / raw)
To: pbs-devel
Signed-off-by: Dietmar Maurer <dietmar@proxmox.com>
---
proxmox-schema/src/api_types.rs | 84 +++++++++++++++++++++++++++++++++
1 file changed, 84 insertions(+)
diff --git a/proxmox-schema/src/api_types.rs b/proxmox-schema/src/api_types.rs
index 4e10ebb..381d4cb 100644
--- a/proxmox-schema/src/api_types.rs
+++ b/proxmox-schema/src/api_types.rs
@@ -3,10 +3,68 @@ use const_format::concatcp;
use crate::{ApiStringFormat, Schema, StringSchema};
+#[rustfmt::skip]
+const IPV4OCTET: &str = r"(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9])";
+
+#[rustfmt::skip]
+const IPV6H16: &str = r"(?:[0-9a-fA-F]{1,4})";
+
+/// Returns the regular expression string to match IPv4 addresses
+#[rustfmt::skip]
+pub const IPV4RE_STR: &str = concatcp!(r"(?:(?:", IPV4OCTET, r"\.){3}", IPV4OCTET, ")");
+
+#[rustfmt::skip]
+const IPV6LS32: &str = concatcp!(r"(?:(?:", IPV4RE_STR, "|", IPV6H16, ":", IPV6H16, "))" );
+
+/// Returns the regular expression string to match IPv6 addresses
+#[rustfmt::skip]
+pub const IPV6RE_STR: &str = concatcp!(r"(?:",
+ r"(?:(?:", r"(?:", IPV6H16, r":){6})", IPV6LS32, r")|",
+ r"(?:(?:", r"::(?:", IPV6H16, r":){5})", IPV6LS32, r")|",
+ r"(?:(?:(?:", IPV6H16, r")?::(?:", IPV6H16, r":){4})", IPV6LS32, r")|",
+ r"(?:(?:(?:(?:", IPV6H16, r":){0,1}", IPV6H16, r")?::(?:", IPV6H16, r":){3})", IPV6LS32, r")|",
+ r"(?:(?:(?:(?:", IPV6H16, r":){0,2}", IPV6H16, r")?::(?:", IPV6H16, r":){2})", IPV6LS32, r")|",
+ r"(?:(?:(?:(?:", IPV6H16, r":){0,3}", IPV6H16, r")?::(?:", IPV6H16, r":){1})", IPV6LS32, r")|",
+ r"(?:(?:(?:(?:", IPV6H16, r":){0,4}", IPV6H16, r")?::", ")", IPV6LS32, r")|",
+ r"(?:(?:(?:(?:", IPV6H16, r":){0,5}", IPV6H16, r")?::", ")", IPV6H16, r")|",
+ r"(?:(?:(?:(?:", IPV6H16, r":){0,6}", IPV6H16, r")?::", ")))");
+
+/// Returns the regular expression string to match IP addresses (v4 or v6)
+#[rustfmt::skip]
+pub const IPRE_STR: &str = concatcp!(r"(?:", IPV4RE_STR, "|", IPV6RE_STR, ")");
+
+/// Regular expression string to match IP addresses where IPv6 addresses require brackets around
+/// them, while for IPv4 they are forbidden.
+#[rustfmt::skip]
+pub const IPRE_BRACKET_STR: &str = concatcp!(r"(?:", IPV4RE_STR, r"|\[(?:", IPV6RE_STR, r")\]", r")");
+
+#[rustfmt::skip]
+pub const CIDR_V4_REGEX_STR: &str = concatcp!(r"(?:", IPV4RE_STR, r"/\d{1,2})$");
+
+#[rustfmt::skip]
+pub const CIDR_V6_REGEX_STR: &str = concatcp!(r"(?:", IPV6RE_STR, r"/\d{1,3})$");
+
#[rustfmt::skip]
const SAFE_ID_REGEX_STR: &str = r"(?:[A-Za-z0-9_][A-Za-z0-9._\-]*)";
const_regex! {
+ /// IPv4 regular expression.
+ pub IP_V4_REGEX = concatcp!(r"^", IPV4RE_STR, r"$");
+
+ /// IPv6 regular expression.
+ pub IP_V6_REGEX = concatcp!(r"^", IPV6RE_STR, r"$");
+
+ /// Regex to match IP addresses (V4 or V6)
+ pub IP_REGEX = concatcp!(r"^", IPRE_STR, r"$");
+
+ /// Regex to match IP addresses where IPv6 addresses require brackets around
+ /// them, while for IPv4 they are forbidden.
+ pub IP_BRACKET_REGEX = concatcp!(r"^", IPRE_BRACKET_STR, r"$");
+
+ pub CIDR_V4_REGEX = concatcp!(r"^", CIDR_V4_REGEX_STR, r"$");
+ pub CIDR_V6_REGEX = concatcp!(r"^", CIDR_V6_REGEX_STR, r"$");
+ pub CIDR_REGEX = concatcp!(r"^(?:", CIDR_V4_REGEX_STR, "|", CIDR_V6_REGEX_STR, r")$");
+
/// Regex for safe identifiers.
///
/// This
@@ -36,3 +94,29 @@ pub const COMMENT_SCHEMA: Schema = StringSchema::new("Comment.")
.format(&SINGLE_LINE_COMMENT_FORMAT)
.max_length(128)
.schema();
+
+#[test]
+fn test_regexes() {
+ assert!(IP_REGEX.is_match("127.0.0.1"));
+ assert!(IP_V4_REGEX.is_match("127.0.0.1"));
+ assert!(!IP_V6_REGEX.is_match("127.0.0.1"));
+
+ assert!(CIDR_V4_REGEX.is_match("127.0.0.1/24"));
+ assert!(CIDR_REGEX.is_match("127.0.0.1/24"));
+
+ assert!(IP_REGEX.is_match("::1"));
+ assert!(IP_REGEX.is_match("2014:b3a::27"));
+ assert!(IP_REGEX.is_match("2014:b3a::192.168.0.1"));
+ assert!(IP_REGEX.is_match("2014:b3a:0102:adf1:1234:4321:4afA:BCDF"));
+ assert!(!IP_V4_REGEX.is_match("2014:b3a:0102:adf1:1234:4321:4afA:BCDF"));
+ assert!(IP_V6_REGEX.is_match("2014:b3a:0102:adf1:1234:4321:4afA:BCDF"));
+
+ assert!(CIDR_V6_REGEX.is_match("2014:b3a:0102:adf1:1234:4321:4afA:BCDF/60"));
+ assert!(CIDR_REGEX.is_match("2014:b3a:0102:adf1:1234:4321:4afA:BCDF/60"));
+
+ assert!(IP_BRACKET_REGEX.is_match("127.0.0.1"));
+ assert!(IP_BRACKET_REGEX.is_match("[::1]"));
+ assert!(IP_BRACKET_REGEX.is_match("[2014:b3a::27]"));
+ assert!(IP_BRACKET_REGEX.is_match("[2014:b3a::192.168.0.1]"));
+ assert!(IP_BRACKET_REGEX.is_match("[2014:b3a:0102:adf1:1234:4321:4afA:BCDF]"));
+}
--
2.39.2
^ permalink raw reply [flat|nested] 5+ messages in thread
* [pbs-devel] [PATCH proxmox 4/4] proxmox-schema: moved common api types from pbs-api-types
2024-03-15 11:27 [pbs-devel] [PATCH proxmox 1/4] proxmox-schema: use const_format to define static strings Dietmar Maurer
2024-03-15 11:27 ` [pbs-devel] [PATCH proxmox 2/4] proxmox-auth-api: " Dietmar Maurer
2024-03-15 11:27 ` [pbs-devel] [PATCH proxmox 3/4] proxmox-schema: add IP address regex/api-types Dietmar Maurer
@ 2024-03-15 11:27 ` Dietmar Maurer
2024-03-19 10:14 ` [pbs-devel] applied-series: [PATCH proxmox 1/4] proxmox-schema: use const_format to define static strings Wolfgang Bumiller
3 siblings, 0 replies; 5+ messages in thread
From: Dietmar Maurer @ 2024-03-15 11:27 UTC (permalink / raw)
To: pbs-devel
We want to use those types in all of our products.
Signed-off-by: Dietmar Maurer <dietmar@proxmox.com>
---
proxmox-schema/src/api_types.rs | 144 ++++++++++++++++++++++++++++++--
1 file changed, 139 insertions(+), 5 deletions(-)
diff --git a/proxmox-schema/src/api_types.rs b/proxmox-schema/src/api_types.rs
index 381d4cb..149d389 100644
--- a/proxmox-schema/src/api_types.rs
+++ b/proxmox-schema/src/api_types.rs
@@ -1,7 +1,7 @@
//! The "basic" api types we generally require along with some of their macros.
use const_format::concatcp;
-use crate::{ApiStringFormat, Schema, StringSchema};
+use crate::{ApiStringFormat, ArraySchema, Schema, StringSchema};
#[rustfmt::skip]
const IPV4OCTET: &str = r"(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9])";
@@ -9,14 +9,14 @@ const IPV4OCTET: &str = r"(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9])";
#[rustfmt::skip]
const IPV6H16: &str = r"(?:[0-9a-fA-F]{1,4})";
-/// Returns the regular expression string to match IPv4 addresses
+/// Regular expression string to match IPv4 addresses
#[rustfmt::skip]
pub const IPV4RE_STR: &str = concatcp!(r"(?:(?:", IPV4OCTET, r"\.){3}", IPV4OCTET, ")");
#[rustfmt::skip]
const IPV6LS32: &str = concatcp!(r"(?:(?:", IPV4RE_STR, "|", IPV6H16, ":", IPV6H16, "))" );
-/// Returns the regular expression string to match IPv6 addresses
+/// Regular expression string to match IPv6 addresses
#[rustfmt::skip]
pub const IPV6RE_STR: &str = concatcp!(r"(?:",
r"(?:(?:", r"(?:", IPV6H16, r":){6})", IPV6LS32, r")|",
@@ -29,7 +29,7 @@ pub const IPV6RE_STR: &str = concatcp!(r"(?:",
r"(?:(?:(?:(?:", IPV6H16, r":){0,5}", IPV6H16, r")?::", ")", IPV6H16, r")|",
r"(?:(?:(?:(?:", IPV6H16, r":){0,6}", IPV6H16, r")?::", ")))");
-/// Returns the regular expression string to match IP addresses (v4 or v6)
+/// Regular expression string to match IP addresses (v4 or v6)
#[rustfmt::skip]
pub const IPRE_STR: &str = concatcp!(r"(?:", IPV4RE_STR, "|", IPV6RE_STR, ")");
@@ -38,14 +38,32 @@ pub const IPRE_STR: &str = concatcp!(r"(?:", IPV4RE_STR, "|", IPV6RE_STR, ")");
#[rustfmt::skip]
pub const IPRE_BRACKET_STR: &str = concatcp!(r"(?:", IPV4RE_STR, r"|\[(?:", IPV6RE_STR, r")\]", r")");
+/// Regular expression string to match CIDRv4 network
#[rustfmt::skip]
pub const CIDR_V4_REGEX_STR: &str = concatcp!(r"(?:", IPV4RE_STR, r"/\d{1,2})$");
+/// Regular expression string to match CIDRv6 network
#[rustfmt::skip]
pub const CIDR_V6_REGEX_STR: &str = concatcp!(r"(?:", IPV6RE_STR, r"/\d{1,3})$");
+/// Regular expression string for safe identifiers.
#[rustfmt::skip]
-const SAFE_ID_REGEX_STR: &str = r"(?:[A-Za-z0-9_][A-Za-z0-9._\-]*)";
+pub const SAFE_ID_REGEX_STR: &str = r"(?:[A-Za-z0-9_][A-Za-z0-9._\-]*)";
+
+#[rustfmt::skip]
+pub const DNS_LABEL_STR: &str = r"(?:[a-zA-Z0-9](?:[a-zA-Z0-9\-]*[a-zA-Z0-9])?)";
+
+#[rustfmt::skip]
+pub const DNS_NAME_STR: &str = concatcp!(r"(?:(?:", DNS_LABEL_STR, r"\.)*", DNS_LABEL_STR, ")");
+
+#[rustfmt::skip]
+pub const DNS_ALIAS_LABEL_STR: &str = r"(?:[a-zA-Z0-9_](?:[a-zA-Z0-9\-]*[a-zA-Z0-9])?)";
+
+#[rustfmt::skip]
+pub const DNS_ALIAS_NAME_STR: &str = concatcp!(r"(?:(?:", DNS_ALIAS_LABEL_STR , r"\.)*", DNS_ALIAS_LABEL_STR, ")");
+
+#[rustfmt::skip]
+pub const PORT_REGEX_STR: &str = r"(?:[0-9]{1,4}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])";
const_regex! {
/// IPv4 regular expression.
@@ -77,12 +95,72 @@ const_regex! {
pub PASSWORD_REGEX = r"^[[:^cntrl:]]*$";
/// Single line comment. Allow everything but control characters.
pub SINGLE_LINE_COMMENT_REGEX = r"^[[:^cntrl:]]*$";
+ /// Comment spawning multiple lines. Allow everything but control characters.
+ pub MULTI_LINE_COMMENT_REGEX = r"(?m)^([[:^cntrl:]]*)$";
+
+ pub HOSTNAME_REGEX = r"^(?:[a-zA-Z0-9](?:[a-zA-Z0-9\-]*[a-zA-Z0-9])?)$";
+ pub DNS_NAME_REGEX = concatcp!(r"^", DNS_NAME_STR, r"$");
+ pub DNS_ALIAS_REGEX = concatcp!(r"^", DNS_ALIAS_NAME_STR, r"$");
+ pub DNS_NAME_OR_IP_REGEX = concatcp!(r"^(?:", DNS_NAME_STR, "|", IPRE_STR, r")$");
+ pub HOST_PORT_REGEX = concatcp!(r"^(?:", DNS_NAME_STR, "|", IPRE_BRACKET_STR, "):", PORT_REGEX_STR ,"$");
+ pub HTTP_URL_REGEX = concatcp!(r"^https?://(?:(?:(?:", DNS_NAME_STR, "|", IPRE_BRACKET_STR, ")(?::", PORT_REGEX_STR ,")?)|", IPV6RE_STR,")(?:/[^\x00-\x1F\x7F]*)?$");
+
+ /// Regex to match SHA256 Digest.
+ pub SHA256_HEX_REGEX = r"^[a-f0-9]{64}$";
+
+ pub FINGERPRINT_SHA256_REGEX = r"^(?:[0-9a-fA-F][0-9a-fA-F])(?::[0-9a-fA-F][0-9a-fA-F]){31}$";
+
+ pub UUID_REGEX = r"^[0-9a-f]{8}(?:-[0-9a-f]{4}){3}-[0-9a-f]{12}$";
+
+ /// Regex to match systemd date/time format.
+ pub SYSTEMD_DATETIME_REGEX = r"^\d{4}-\d{2}-\d{2}( \d{2}:\d{2}(:\d{2})?)?$";
+
+ /// Regex that (loosely) matches URIs according to [RFC 2396](https://www.rfc-editor.org/rfc/rfc2396.txt)
+ /// This does not completely match a URI, but rather disallows all the prohibited characters
+ /// specified in the RFC.
+ pub GENERIC_URI_REGEX = r#"^[^\x00-\x1F\x7F <>#"]*$"#;
+
+ pub BLOCKDEVICE_NAME_REGEX = r"^(?:(?:h|s|x?v)d[a-z]+)|(?:nvme\d+n\d+)$";
+ pub BLOCKDEVICE_DISK_AND_PARTITION_NAME_REGEX = r"^(?:(?:h|s|x?v)d[a-z]+\d*)|(?:nvme\d+n\d+(p\d+)?)$";
}
pub const SAFE_ID_FORMAT: ApiStringFormat = ApiStringFormat::Pattern(&SAFE_ID_REGEX);
pub const PASSWORD_FORMAT: ApiStringFormat = ApiStringFormat::Pattern(&PASSWORD_REGEX);
pub const SINGLE_LINE_COMMENT_FORMAT: ApiStringFormat =
ApiStringFormat::Pattern(&SINGLE_LINE_COMMENT_REGEX);
+pub const MULTI_LINE_COMMENT_FORMAT: ApiStringFormat =
+ ApiStringFormat::Pattern(&MULTI_LINE_COMMENT_REGEX);
+
+pub const IP_V4_FORMAT: ApiStringFormat = ApiStringFormat::Pattern(&IP_V4_REGEX);
+pub const IP_V6_FORMAT: ApiStringFormat = ApiStringFormat::Pattern(&IP_V6_REGEX);
+pub const IP_FORMAT: ApiStringFormat = ApiStringFormat::Pattern(&IP_REGEX);
+pub const CIDR_V4_FORMAT: ApiStringFormat = ApiStringFormat::Pattern(&CIDR_V4_REGEX);
+pub const CIDR_V6_FORMAT: ApiStringFormat = ApiStringFormat::Pattern(&CIDR_V6_REGEX);
+pub const CIDR_FORMAT: ApiStringFormat = ApiStringFormat::Pattern(&CIDR_REGEX);
+pub const UUID_FORMAT: ApiStringFormat = ApiStringFormat::Pattern(&UUID_REGEX);
+pub const BLOCKDEVICE_NAME_FORMAT: ApiStringFormat =
+ ApiStringFormat::Pattern(&BLOCKDEVICE_NAME_REGEX);
+pub const BLOCKDEVICE_DISK_AND_PARTITION_NAME_FORMAT: ApiStringFormat =
+ ApiStringFormat::Pattern(&BLOCKDEVICE_DISK_AND_PARTITION_NAME_REGEX);
+
+pub const SYSTEMD_DATETIME_FORMAT: ApiStringFormat =
+ ApiStringFormat::Pattern(&SYSTEMD_DATETIME_REGEX);
+
+pub const HOSTNAME_FORMAT: ApiStringFormat = ApiStringFormat::Pattern(&HOSTNAME_REGEX);
+pub const HOST_PORT_FORMAT: ApiStringFormat = ApiStringFormat::Pattern(&HOST_PORT_REGEX);
+pub const HTTP_URL_FORMAT: ApiStringFormat = ApiStringFormat::Pattern(&HTTP_URL_REGEX);
+
+pub const DNS_ALIAS_FORMAT: ApiStringFormat = ApiStringFormat::Pattern(&DNS_ALIAS_REGEX);
+pub const DNS_NAME_FORMAT: ApiStringFormat = ApiStringFormat::Pattern(&DNS_NAME_REGEX);
+pub const DNS_NAME_OR_IP_FORMAT: ApiStringFormat = ApiStringFormat::Pattern(&DNS_NAME_OR_IP_REGEX);
+
+pub const FINGERPRINT_SHA256_FORMAT: ApiStringFormat =
+ ApiStringFormat::Pattern(&FINGERPRINT_SHA256_REGEX);
+
+pub const CERT_FINGERPRINT_SHA256_SCHEMA: Schema =
+ StringSchema::new("X509 certificate fingerprint (sha256).")
+ .format(&FINGERPRINT_SHA256_FORMAT)
+ .schema();
pub const PASSWORD_SCHEMA: Schema = StringSchema::new("Password.")
.format(&PASSWORD_FORMAT)
@@ -95,6 +173,62 @@ pub const COMMENT_SCHEMA: Schema = StringSchema::new("Comment.")
.max_length(128)
.schema();
+pub const MULTI_LINE_COMMENT_SCHEMA: Schema = StringSchema::new("Comment (multiple lines).")
+ .format(&MULTI_LINE_COMMENT_FORMAT)
+ .schema();
+
+pub const HOSTNAME_SCHEMA: Schema = StringSchema::new("Hostname (as defined in RFC1123).")
+ .format(&HOSTNAME_FORMAT)
+ .schema();
+
+pub const DNS_NAME_OR_IP_SCHEMA: Schema = StringSchema::new("DNS name or IP address.")
+ .format(&DNS_NAME_OR_IP_FORMAT)
+ .schema();
+
+pub const HOST_PORT_SCHEMA: Schema =
+ StringSchema::new("host:port combination (Host can be DNS name or IP address).")
+ .format(&HOST_PORT_FORMAT)
+ .schema();
+
+pub const HTTP_URL_SCHEMA: Schema = StringSchema::new("HTTP(s) url with optional port.")
+ .format(&HTTP_URL_FORMAT)
+ .schema();
+
+pub const NODE_SCHEMA: Schema = StringSchema::new("Node name (or 'localhost')")
+ .format(&HOSTNAME_FORMAT)
+ .schema();
+
+pub const SERVICE_ID_SCHEMA: Schema = StringSchema::new("Service ID.").max_length(256).schema();
+
+pub const TIME_ZONE_SCHEMA: Schema = StringSchema::new(
+ "Time zone. The file '/usr/share/zoneinfo/zone.tab' contains the list of valid names.",
+)
+.format(&SINGLE_LINE_COMMENT_FORMAT)
+.min_length(2)
+.max_length(64)
+.schema();
+
+pub const BLOCKDEVICE_NAME_SCHEMA: Schema =
+ StringSchema::new("Block device name (/sys/block/<name>).")
+ .format(&BLOCKDEVICE_NAME_FORMAT)
+ .min_length(3)
+ .max_length(64)
+ .schema();
+
+pub const BLOCKDEVICE_DISK_AND_PARTITION_NAME_SCHEMA: Schema =
+ StringSchema::new("(Partition) block device name (/sys/class/block/<name>).")
+ .format(&BLOCKDEVICE_DISK_AND_PARTITION_NAME_FORMAT)
+ .min_length(3)
+ .max_length(64)
+ .schema();
+
+pub const DISK_ARRAY_SCHEMA: Schema =
+ ArraySchema::new("Disk name list.", &BLOCKDEVICE_NAME_SCHEMA).schema();
+
+pub const DISK_LIST_SCHEMA: Schema = StringSchema::new("A list of disk names, comma separated.")
+ .format(&ApiStringFormat::PropertyString(&DISK_ARRAY_SCHEMA))
+ .schema();
+
#[test]
fn test_regexes() {
assert!(IP_REGEX.is_match("127.0.0.1"));
--
2.39.2
^ permalink raw reply [flat|nested] 5+ messages in thread
* [pbs-devel] applied-series: [PATCH proxmox 1/4] proxmox-schema: use const_format to define static strings.
2024-03-15 11:27 [pbs-devel] [PATCH proxmox 1/4] proxmox-schema: use const_format to define static strings Dietmar Maurer
` (2 preceding siblings ...)
2024-03-15 11:27 ` [pbs-devel] [PATCH proxmox 4/4] proxmox-schema: moved common api types from pbs-api-types Dietmar Maurer
@ 2024-03-19 10:14 ` Wolfgang Bumiller
3 siblings, 0 replies; 5+ messages in thread
From: Wolfgang Bumiller @ 2024-03-19 10:14 UTC (permalink / raw)
To: Dietmar Maurer; +Cc: pbs-devel
applied series, adapted the notify crate & bumped the 3
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2024-03-19 10:15 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-03-15 11:27 [pbs-devel] [PATCH proxmox 1/4] proxmox-schema: use const_format to define static strings Dietmar Maurer
2024-03-15 11:27 ` [pbs-devel] [PATCH proxmox 2/4] proxmox-auth-api: " Dietmar Maurer
2024-03-15 11:27 ` [pbs-devel] [PATCH proxmox 3/4] proxmox-schema: add IP address regex/api-types Dietmar Maurer
2024-03-15 11:27 ` [pbs-devel] [PATCH proxmox 4/4] proxmox-schema: moved common api types from pbs-api-types Dietmar Maurer
2024-03-19 10:14 ` [pbs-devel] applied-series: [PATCH proxmox 1/4] proxmox-schema: use const_format to define static strings Wolfgang Bumiller
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.