api types: rust fmt

Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
This commit is contained in:
Thomas Lamprecht 2022-04-10 17:53:42 +02:00
parent 4ad118c613
commit b22d785c18
18 changed files with 497 additions and 469 deletions

View File

@ -62,18 +62,16 @@ fn as_fingerprint(bytes: &[u8]) -> String {
.as_bytes() .as_bytes()
.chunks(2) .chunks(2)
.map(|v| unsafe { std::str::from_utf8_unchecked(v) }) // it's a hex string .map(|v| unsafe { std::str::from_utf8_unchecked(v) }) // it's a hex string
.collect::<Vec<&str>>().join(":") .collect::<Vec<&str>>()
.join(":")
} }
pub mod bytes_as_fingerprint { pub mod bytes_as_fingerprint {
use std::mem::MaybeUninit; use std::mem::MaybeUninit;
use serde::{Deserialize, Serializer, Deserializer}; use serde::{Deserialize, Deserializer, Serializer};
pub fn serialize<S>( pub fn serialize<S>(bytes: &[u8; 32], serializer: S) -> Result<S::Ok, S::Error>
bytes: &[u8; 32],
serializer: S,
) -> Result<S::Ok, S::Error>
where where
S: Serializer, S: Serializer,
{ {
@ -81,9 +79,7 @@ pub mod bytes_as_fingerprint {
serializer.serialize_str(&s) serializer.serialize_str(&s)
} }
pub fn deserialize<'de, D>( pub fn deserialize<'de, D>(deserializer: D) -> Result<[u8; 32], D::Error>
deserializer: D,
) -> Result<[u8; 32], D::Error>
where where
D: Deserializer<'de>, D: Deserializer<'de>,
{ {

View File

@ -6,10 +6,9 @@ use proxmox_schema::{
}; };
use crate::{ use crate::{
PROXMOX_SAFE_ID_FORMAT, SHA256_HEX_REGEX, SINGLE_LINE_COMMENT_SCHEMA, CryptMode, UPID, Authid, CryptMode, Fingerprint, Userid, DATASTORE_NOTIFY_STRING_SCHEMA, GC_SCHEDULE_SCHEMA,
Fingerprint, Userid, Authid, PROXMOX_SAFE_ID_FORMAT, PRUNE_SCHEDULE_SCHEMA, SHA256_HEX_REGEX, SINGLE_LINE_COMMENT_SCHEMA,
GC_SCHEDULE_SCHEMA, DATASTORE_NOTIFY_STRING_SCHEMA, PRUNE_SCHEDULE_SCHEMA, UPID,
}; };
const_regex! { const_regex! {
@ -81,16 +80,18 @@ pub const DATASTORE_MAP_SCHEMA: Schema = StringSchema::new("Datastore mapping.")
.type_text("(<source>=)?<target>") .type_text("(<source>=)?<target>")
.schema(); .schema();
pub const DATASTORE_MAP_ARRAY_SCHEMA: Schema = ArraySchema::new( pub const DATASTORE_MAP_ARRAY_SCHEMA: Schema =
"Datastore mapping list.", &DATASTORE_MAP_SCHEMA) ArraySchema::new("Datastore mapping list.", &DATASTORE_MAP_SCHEMA).schema();
.schema();
pub const DATASTORE_MAP_LIST_SCHEMA: Schema = StringSchema::new( pub const DATASTORE_MAP_LIST_SCHEMA: Schema = StringSchema::new(
"A list of Datastore mappings (or single datastore), comma separated. \ "A list of Datastore mappings (or single datastore), comma separated. \
For example 'a=b,e' maps the source datastore 'a' to target 'b and \ For example 'a=b,e' maps the source datastore 'a' to target 'b and \
all other sources to the default 'e'. If no default is given, only the \ all other sources to the default 'e'. If no default is given, only the \
specified sources are mapped.") specified sources are mapped.",
.format(&ApiStringFormat::PropertyString(&DATASTORE_MAP_ARRAY_SCHEMA)) )
.format(&ApiStringFormat::PropertyString(
&DATASTORE_MAP_ARRAY_SCHEMA,
))
.schema(); .schema();
pub const PRUNE_SCHEMA_KEEP_DAILY: Schema = IntegerSchema::new("Number of daily backups to keep.") pub const PRUNE_SCHEMA_KEEP_DAILY: Schema = IntegerSchema::new("Number of daily backups to keep.")
@ -194,9 +195,10 @@ pub struct DatastoreTuning {
pub chunk_order: Option<ChunkOrder>, pub chunk_order: Option<ChunkOrder>,
} }
pub const DATASTORE_TUNING_STRING_SCHEMA: Schema = StringSchema::new( pub const DATASTORE_TUNING_STRING_SCHEMA: Schema = StringSchema::new("Datastore tuning options")
"Datastore tuning options") .format(&ApiStringFormat::PropertyString(
.format(&ApiStringFormat::PropertyString(&DatastoreTuning::API_SCHEMA)) &DatastoreTuning::API_SCHEMA,
))
.schema(); .schema();
#[api( #[api(
@ -375,7 +377,6 @@ pub struct SnapshotVerifyState {
pub state: VerifyState, pub state: VerifyState,
} }
#[api( #[api(
properties: { properties: {
"backup-type": { "backup-type": {
@ -685,7 +686,8 @@ pub const ADMIN_DATASTORE_LIST_SNAPSHOTS_RETURN_TYPE: ReturnType = ReturnType {
schema: &ArraySchema::new( schema: &ArraySchema::new(
"Returns the list of snapshots.", "Returns the list of snapshots.",
&SnapshotListItem::API_SCHEMA, &SnapshotListItem::API_SCHEMA,
).schema(), )
.schema(),
}; };
pub const ADMIN_DATASTORE_LIST_SNAPSHOT_FILES_RETURN_TYPE: ReturnType = ReturnType { pub const ADMIN_DATASTORE_LIST_SNAPSHOT_FILES_RETURN_TYPE: ReturnType = ReturnType {
@ -693,7 +695,8 @@ pub const ADMIN_DATASTORE_LIST_SNAPSHOT_FILES_RETURN_TYPE: ReturnType = ReturnTy
schema: &ArraySchema::new( schema: &ArraySchema::new(
"Returns the list of archive files inside a backup snapshots.", "Returns the list of archive files inside a backup snapshots.",
&BackupContent::API_SCHEMA, &BackupContent::API_SCHEMA,
).schema(), )
.schema(),
}; };
pub const ADMIN_DATASTORE_LIST_GROUPS_RETURN_TYPE: ReturnType = ReturnType { pub const ADMIN_DATASTORE_LIST_GROUPS_RETURN_TYPE: ReturnType = ReturnType {
@ -701,7 +704,8 @@ pub const ADMIN_DATASTORE_LIST_GROUPS_RETURN_TYPE: ReturnType = ReturnType {
schema: &ArraySchema::new( schema: &ArraySchema::new(
"Returns the list of backup groups.", "Returns the list of backup groups.",
&GroupListItem::API_SCHEMA, &GroupListItem::API_SCHEMA,
).schema(), )
.schema(),
}; };
pub const ADMIN_DATASTORE_PRUNE_RETURN_TYPE: ReturnType = ReturnType { pub const ADMIN_DATASTORE_PRUNE_RETURN_TYPE: ReturnType = ReturnType {
@ -709,5 +713,6 @@ pub const ADMIN_DATASTORE_PRUNE_RETURN_TYPE: ReturnType = ReturnType {
schema: &ArraySchema::new( schema: &ArraySchema::new(
"Returns the list of snapshots and a flag indicating if there are kept or removed.", "Returns the list of snapshots and a flag indicating if there are kept or removed.",
&PruneListItem::API_SCHEMA, &PruneListItem::API_SCHEMA,
).schema(), )
.schema(),
}; };

View File

@ -101,7 +101,8 @@ fn strip_unit(v: &str) -> (&str, SizeUnit) {
}; };
let mut unit = SizeUnit::Byte; let mut unit = SizeUnit::Byte;
(v.strip_suffix(|c: char| match c { #[rustfmt::skip]
let value = v.strip_suffix(|c: char| match c {
'k' | 'K' if !binary => { unit = SizeUnit::KByte; true } 'k' | 'K' if !binary => { unit = SizeUnit::KByte; true }
'm' | 'M' if !binary => { unit = SizeUnit::MByte; true } 'm' | 'M' if !binary => { unit = SizeUnit::MByte; true }
'g' | 'G' if !binary => { unit = SizeUnit::GByte; true } 'g' | 'G' if !binary => { unit = SizeUnit::GByte; true }
@ -114,7 +115,9 @@ fn strip_unit(v: &str) -> (&str, SizeUnit) {
't' | 'T' if binary => { unit = SizeUnit::Tebi; true } 't' | 'T' if binary => { unit = SizeUnit::Tebi; true }
'p' | 'P' if binary => { unit = SizeUnit::Pebi; true } 'p' | 'P' if binary => { unit = SizeUnit::Pebi; true }
_ => false _ => false
}).unwrap_or(v).trim_end(), unit) }).unwrap_or(v).trim_end();
(value, unit)
} }
/// Byte size which can be displayed in a human friendly way /// Byte size which can be displayed in a human friendly way
@ -154,13 +157,19 @@ impl HumanByte {
/// Create a new instance with optimal binary unit computed /// Create a new instance with optimal binary unit computed
pub fn new_binary(size: f64) -> Self { pub fn new_binary(size: f64) -> Self {
let unit = SizeUnit::auto_scale(size, true); let unit = SizeUnit::auto_scale(size, true);
HumanByte { size: size / unit.factor(), unit } HumanByte {
size: size / unit.factor(),
unit,
}
} }
/// Create a new instance with optimal decimal unit computed /// Create a new instance with optimal decimal unit computed
pub fn new_decimal(size: f64) -> Self { pub fn new_decimal(size: f64) -> Self {
let unit = SizeUnit::auto_scale(size, false); let unit = SizeUnit::auto_scale(size, false);
HumanByte { size: size / unit.factor(), unit } HumanByte {
size: size / unit.factor(),
unit,
}
} }
/// Returns the size as u64 number of bytes /// Returns the size as u64 number of bytes
@ -228,7 +237,12 @@ fn test_human_byte_parser() -> Result<(), Error> {
bail!("got unexpected size for '{}' ({} != {})", v, h.size, size); bail!("got unexpected size for '{}' ({} != {})", v, h.size, size);
} }
if h.unit != unit { if h.unit != unit {
bail!("got unexpected unit for '{}' ({:?} != {:?})", v, h.unit, unit); bail!(
"got unexpected unit for '{}' ({:?} != {:?})",
v,
h.unit,
unit
);
} }
let new = h.to_string(); let new = h.to_string();
@ -265,7 +279,12 @@ fn test_human_byte_parser() -> Result<(), Error> {
assert_eq!(&format!("{:.7}", h), "1.2345678 B"); assert_eq!(&format!("{:.7}", h), "1.2345678 B");
assert_eq!(&format!("{:.8}", h), "1.2345678 B"); assert_eq!(&format!("{:.8}", h), "1.2345678 B");
assert!(test("987654321", 987654321.0, SizeUnit::Byte, "987654321 B")); assert!(test(
"987654321",
987654321.0,
SizeUnit::Byte,
"987654321 B"
));
assert!(test("1300b", 1300.0, SizeUnit::Byte, "1300 B")); assert!(test("1300b", 1300.0, SizeUnit::Byte, "1300 B"));
assert!(test("1300B", 1300.0, SizeUnit::Byte, "1300 B")); assert!(test("1300B", 1300.0, SizeUnit::Byte, "1300 B"));

View File

@ -7,10 +7,9 @@ use serde::{Deserialize, Serialize};
use proxmox_schema::*; use proxmox_schema::*;
use crate::{ use crate::{
Userid, Authid, RateLimitConfig, Authid, RateLimitConfig, Userid, BACKUP_GROUP_SCHEMA, BACKUP_TYPE_SCHEMA, DATASTORE_SCHEMA,
REMOTE_ID_SCHEMA, DRIVE_NAME_SCHEMA, MEDIA_POOL_NAME_SCHEMA, DRIVE_NAME_SCHEMA, MEDIA_POOL_NAME_SCHEMA, PROXMOX_SAFE_ID_FORMAT, REMOTE_ID_SCHEMA,
SINGLE_LINE_COMMENT_SCHEMA, PROXMOX_SAFE_ID_FORMAT, DATASTORE_SCHEMA, SINGLE_LINE_COMMENT_SCHEMA,
BACKUP_GROUP_SCHEMA, BACKUP_TYPE_SCHEMA,
}; };
const_regex! { const_regex! {
@ -27,32 +26,39 @@ pub const JOB_ID_SCHEMA: Schema = StringSchema::new("Job ID.")
.max_length(32) .max_length(32)
.schema(); .schema();
pub const SYNC_SCHEDULE_SCHEMA: Schema = StringSchema::new( pub const SYNC_SCHEDULE_SCHEMA: Schema = StringSchema::new("Run sync job at specified schedule.")
"Run sync job at specified schedule.") .format(&ApiStringFormat::VerifyFn(
.format(&ApiStringFormat::VerifyFn(proxmox_time::verify_calendar_event)) proxmox_time::verify_calendar_event,
))
.type_text("<calendar-event>") .type_text("<calendar-event>")
.schema(); .schema();
pub const GC_SCHEDULE_SCHEMA: Schema = StringSchema::new( pub const GC_SCHEDULE_SCHEMA: Schema =
"Run garbage collection job at specified schedule.") StringSchema::new("Run garbage collection job at specified schedule.")
.format(&ApiStringFormat::VerifyFn(proxmox_time::verify_calendar_event)) .format(&ApiStringFormat::VerifyFn(
proxmox_time::verify_calendar_event,
))
.type_text("<calendar-event>") .type_text("<calendar-event>")
.schema(); .schema();
pub const PRUNE_SCHEDULE_SCHEMA: Schema = StringSchema::new( pub const PRUNE_SCHEDULE_SCHEMA: Schema = StringSchema::new("Run prune job at specified schedule.")
"Run prune job at specified schedule.") .format(&ApiStringFormat::VerifyFn(
.format(&ApiStringFormat::VerifyFn(proxmox_time::verify_calendar_event)) proxmox_time::verify_calendar_event,
))
.type_text("<calendar-event>") .type_text("<calendar-event>")
.schema(); .schema();
pub const VERIFICATION_SCHEDULE_SCHEMA: Schema = StringSchema::new( pub const VERIFICATION_SCHEDULE_SCHEMA: Schema =
"Run verify job at specified schedule.") StringSchema::new("Run verify job at specified schedule.")
.format(&ApiStringFormat::VerifyFn(proxmox_time::verify_calendar_event)) .format(&ApiStringFormat::VerifyFn(
proxmox_time::verify_calendar_event,
))
.type_text("<calendar-event>") .type_text("<calendar-event>")
.schema(); .schema();
pub const REMOVE_VANISHED_BACKUPS_SCHEMA: Schema = BooleanSchema::new( pub const REMOVE_VANISHED_BACKUPS_SCHEMA: Schema = BooleanSchema::new(
"Delete vanished backups. This remove the local copy if the remote backup was deleted.") "Delete vanished backups. This remove the local copy if the remote backup was deleted.",
)
.default(false) .default(false)
.schema(); .schema();
@ -134,18 +140,21 @@ pub struct DatastoreNotify {
pub sync: Option<Notify>, pub sync: Option<Notify>,
} }
pub const DATASTORE_NOTIFY_STRING_SCHEMA: Schema = StringSchema::new( pub const DATASTORE_NOTIFY_STRING_SCHEMA: Schema =
"Datastore notification setting") StringSchema::new("Datastore notification setting")
.format(&ApiStringFormat::PropertyString(&DatastoreNotify::API_SCHEMA)) .format(&ApiStringFormat::PropertyString(
&DatastoreNotify::API_SCHEMA,
))
.schema(); .schema();
pub const IGNORE_VERIFIED_BACKUPS_SCHEMA: Schema = BooleanSchema::new( pub const IGNORE_VERIFIED_BACKUPS_SCHEMA: Schema = BooleanSchema::new(
"Do not verify backups that are already verified if their verification is not outdated.") "Do not verify backups that are already verified if their verification is not outdated.",
)
.default(true) .default(true)
.schema(); .schema();
pub const VERIFICATION_OUTDATED_AFTER_SCHEMA: Schema = IntegerSchema::new( pub const VERIFICATION_OUTDATED_AFTER_SCHEMA: Schema =
"Days after that a verification becomes outdated. (0 means always)") IntegerSchema::new("Days after that a verification becomes outdated. (0 means always)")
.minimum(0) .minimum(0)
.schema(); .schema();
@ -378,7 +387,8 @@ pub const GROUP_FILTER_SCHEMA: Schema = StringSchema::new(
.type_text("<type:<vm|ct|host>|group:GROUP|regex:RE>") .type_text("<type:<vm|ct|host>|group:GROUP|regex:RE>")
.schema(); .schema();
pub const GROUP_FILTER_LIST_SCHEMA: Schema = ArraySchema::new("List of group filters.", &GROUP_FILTER_SCHEMA).schema(); pub const GROUP_FILTER_LIST_SCHEMA: Schema =
ArraySchema::new("List of group filters.", &GROUP_FILTER_SCHEMA).schema();
#[api( #[api(
properties: { properties: {
@ -452,7 +462,6 @@ pub struct SyncJobConfig {
}, },
}, },
)] )]
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
#[serde(rename_all = "kebab-case")] #[serde(rename_all = "kebab-case")]
/// Status of Sync Job /// Status of Sync Job

View File

@ -53,4 +53,3 @@ pub struct KeyInfo {
#[serde(skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "Option::is_none")]
pub hint: Option<String>, pub hint: Option<String>,
} }

View File

@ -6,7 +6,7 @@ pub mod common_regex;
pub mod percent_encoding; pub mod percent_encoding;
use proxmox_schema::{ use proxmox_schema::{
api, const_regex, ApiStringFormat, ApiType, ArraySchema, Schema, StringSchema, ReturnType, api, const_regex, ApiStringFormat, ApiType, ArraySchema, ReturnType, Schema, StringSchema,
}; };
use proxmox_time::parse_daily_duration; use proxmox_time::parse_daily_duration;
@ -68,7 +68,7 @@ pub use user::*;
pub use proxmox_schema::upid::*; pub use proxmox_schema::upid::*;
mod crypto; mod crypto;
pub use crypto::{CryptMode, Fingerprint, bytes_as_fingerprint}; pub use crypto::{bytes_as_fingerprint, CryptMode, Fingerprint};
pub mod file_restore; pub mod file_restore;
@ -87,7 +87,6 @@ pub use traffic_control::*;
mod zfs; mod zfs;
pub use zfs::*; pub use zfs::*;
#[rustfmt::skip] #[rustfmt::skip]
#[macro_use] #[macro_use]
mod local_macros { mod local_macros {
@ -160,14 +159,17 @@ pub const CIDR_FORMAT: ApiStringFormat = ApiStringFormat::Pattern(&CIDR_REGEX);
pub const PVE_CONFIG_DIGEST_FORMAT: ApiStringFormat = ApiStringFormat::Pattern(&SHA256_HEX_REGEX); pub const PVE_CONFIG_DIGEST_FORMAT: ApiStringFormat = ApiStringFormat::Pattern(&SHA256_HEX_REGEX);
pub const PASSWORD_FORMAT: ApiStringFormat = ApiStringFormat::Pattern(&PASSWORD_REGEX); pub const PASSWORD_FORMAT: ApiStringFormat = ApiStringFormat::Pattern(&PASSWORD_REGEX);
pub const UUID_FORMAT: ApiStringFormat = ApiStringFormat::Pattern(&UUID_REGEX); pub const UUID_FORMAT: ApiStringFormat = ApiStringFormat::Pattern(&UUID_REGEX);
pub const BLOCKDEVICE_NAME_FORMAT: ApiStringFormat = ApiStringFormat::Pattern(&BLOCKDEVICE_NAME_REGEX); pub const BLOCKDEVICE_NAME_FORMAT: ApiStringFormat =
pub const SUBSCRIPTION_KEY_FORMAT: ApiStringFormat = ApiStringFormat::Pattern(&SUBSCRIPTION_KEY_REGEX); ApiStringFormat::Pattern(&BLOCKDEVICE_NAME_REGEX);
pub const SYSTEMD_DATETIME_FORMAT: ApiStringFormat = ApiStringFormat::Pattern(&SYSTEMD_DATETIME_REGEX); pub const SUBSCRIPTION_KEY_FORMAT: ApiStringFormat =
ApiStringFormat::Pattern(&SUBSCRIPTION_KEY_REGEX);
pub const SYSTEMD_DATETIME_FORMAT: ApiStringFormat =
ApiStringFormat::Pattern(&SYSTEMD_DATETIME_REGEX);
pub const HOSTNAME_FORMAT: ApiStringFormat = ApiStringFormat::Pattern(&HOSTNAME_REGEX); pub const HOSTNAME_FORMAT: ApiStringFormat = ApiStringFormat::Pattern(&HOSTNAME_REGEX);
pub const OPENSSL_CIPHERS_TLS_FORMAT: ApiStringFormat = ApiStringFormat::Pattern(&OPENSSL_CIPHERS_REGEX); pub const OPENSSL_CIPHERS_TLS_FORMAT: ApiStringFormat =
ApiStringFormat::Pattern(&OPENSSL_CIPHERS_REGEX);
pub const DNS_ALIAS_FORMAT: ApiStringFormat = pub const DNS_ALIAS_FORMAT: ApiStringFormat = ApiStringFormat::Pattern(&DNS_ALIAS_REGEX);
ApiStringFormat::Pattern(&DNS_ALIAS_REGEX);
pub const DAILY_DURATION_FORMAT: ApiStringFormat = pub const DAILY_DURATION_FORMAT: ApiStringFormat =
ApiStringFormat::VerifyFn(|s| parse_daily_duration(s).map(drop)); ApiStringFormat::VerifyFn(|s| parse_daily_duration(s).map(drop));
@ -175,18 +177,15 @@ pub const DAILY_DURATION_FORMAT: ApiStringFormat =
pub const SEARCH_DOMAIN_SCHEMA: Schema = pub const SEARCH_DOMAIN_SCHEMA: Schema =
StringSchema::new("Search domain for host-name lookup.").schema(); StringSchema::new("Search domain for host-name lookup.").schema();
pub const FIRST_DNS_SERVER_SCHEMA: Schema = pub const FIRST_DNS_SERVER_SCHEMA: Schema = StringSchema::new("First name server IP address.")
StringSchema::new("First name server IP address.")
.format(&IP_FORMAT) .format(&IP_FORMAT)
.schema(); .schema();
pub const SECOND_DNS_SERVER_SCHEMA: Schema = pub const SECOND_DNS_SERVER_SCHEMA: Schema = StringSchema::new("Second name server IP address.")
StringSchema::new("Second name server IP address.")
.format(&IP_FORMAT) .format(&IP_FORMAT)
.schema(); .schema();
pub const THIRD_DNS_SERVER_SCHEMA: Schema = pub const THIRD_DNS_SERVER_SCHEMA: Schema = StringSchema::new("Third name server IP address.")
StringSchema::new("Third name server IP address.")
.format(&IP_FORMAT) .format(&IP_FORMAT)
.schema(); .schema();
@ -194,48 +193,47 @@ pub const HOSTNAME_SCHEMA: Schema = StringSchema::new("Hostname (as defined in R
.format(&HOSTNAME_FORMAT) .format(&HOSTNAME_FORMAT)
.schema(); .schema();
pub const OPENSSL_CIPHERS_TLS_1_2_SCHEMA: Schema = StringSchema::new("OpenSSL cipher list used by the proxy for TLS <= 1.2") pub const OPENSSL_CIPHERS_TLS_1_2_SCHEMA: Schema =
StringSchema::new("OpenSSL cipher list used by the proxy for TLS <= 1.2")
.format(&OPENSSL_CIPHERS_TLS_FORMAT) .format(&OPENSSL_CIPHERS_TLS_FORMAT)
.schema(); .schema();
pub const OPENSSL_CIPHERS_TLS_1_3_SCHEMA: Schema = StringSchema::new("OpenSSL ciphersuites list used by the proxy for TLS 1.3") pub const OPENSSL_CIPHERS_TLS_1_3_SCHEMA: Schema =
StringSchema::new("OpenSSL ciphersuites list used by the proxy for TLS 1.3")
.format(&OPENSSL_CIPHERS_TLS_FORMAT) .format(&OPENSSL_CIPHERS_TLS_FORMAT)
.schema(); .schema();
pub const DNS_NAME_FORMAT: ApiStringFormat = pub const DNS_NAME_FORMAT: ApiStringFormat = ApiStringFormat::Pattern(&DNS_NAME_REGEX);
ApiStringFormat::Pattern(&DNS_NAME_REGEX);
pub const DNS_NAME_OR_IP_FORMAT: ApiStringFormat = pub const DNS_NAME_OR_IP_FORMAT: ApiStringFormat = ApiStringFormat::Pattern(&DNS_NAME_OR_IP_REGEX);
ApiStringFormat::Pattern(&DNS_NAME_OR_IP_REGEX);
pub const DNS_NAME_OR_IP_SCHEMA: Schema = StringSchema::new("DNS name or IP address.") pub const DNS_NAME_OR_IP_SCHEMA: Schema = StringSchema::new("DNS name or IP address.")
.format(&DNS_NAME_OR_IP_FORMAT) .format(&DNS_NAME_OR_IP_FORMAT)
.schema(); .schema();
pub const NODE_SCHEMA: Schema = StringSchema::new("Node name (or 'localhost')") pub const NODE_SCHEMA: Schema = StringSchema::new("Node name (or 'localhost')")
.format(&HOSTNAME_FORMAT) .format(&HOSTNAME_FORMAT)
.schema(); .schema();
pub const TIME_ZONE_SCHEMA: Schema = StringSchema::new( pub const TIME_ZONE_SCHEMA: Schema = StringSchema::new(
"Time zone. The file '/usr/share/zoneinfo/zone.tab' contains the list of valid names.") "Time zone. The file '/usr/share/zoneinfo/zone.tab' contains the list of valid names.",
)
.format(&SINGLE_LINE_COMMENT_FORMAT) .format(&SINGLE_LINE_COMMENT_FORMAT)
.min_length(2) .min_length(2)
.max_length(64) .max_length(64)
.schema(); .schema();
pub const BLOCKDEVICE_NAME_SCHEMA: Schema = StringSchema::new("Block device name (/sys/block/<name>).") pub const BLOCKDEVICE_NAME_SCHEMA: Schema =
StringSchema::new("Block device name (/sys/block/<name>).")
.format(&BLOCKDEVICE_NAME_FORMAT) .format(&BLOCKDEVICE_NAME_FORMAT)
.min_length(3) .min_length(3)
.max_length(64) .max_length(64)
.schema(); .schema();
pub const DISK_ARRAY_SCHEMA: Schema = ArraySchema::new( pub const DISK_ARRAY_SCHEMA: Schema =
"Disk name list.", &BLOCKDEVICE_NAME_SCHEMA) ArraySchema::new("Disk name list.", &BLOCKDEVICE_NAME_SCHEMA).schema();
.schema();
pub const DISK_LIST_SCHEMA: Schema = StringSchema::new( pub const DISK_LIST_SCHEMA: Schema = StringSchema::new("A list of disk names, comma separated.")
"A list of disk names, comma separated.")
.format(&ApiStringFormat::PropertyString(&DISK_ARRAY_SCHEMA)) .format(&ApiStringFormat::PropertyString(&DISK_ARRAY_SCHEMA))
.schema(); .schema();
@ -282,15 +280,14 @@ pub const MULTI_LINE_COMMENT_SCHEMA: Schema = StringSchema::new("Comment (multip
.format(&MULTI_LINE_COMMENT_FORMAT) .format(&MULTI_LINE_COMMENT_FORMAT)
.schema(); .schema();
pub const SUBSCRIPTION_KEY_SCHEMA: Schema = StringSchema::new("Proxmox Backup Server subscription key.") pub const SUBSCRIPTION_KEY_SCHEMA: Schema =
StringSchema::new("Proxmox Backup Server subscription key.")
.format(&SUBSCRIPTION_KEY_FORMAT) .format(&SUBSCRIPTION_KEY_FORMAT)
.min_length(15) .min_length(15)
.max_length(16) .max_length(16)
.schema(); .schema();
pub const SERVICE_ID_SCHEMA: Schema = StringSchema::new("Service ID.") pub const SERVICE_ID_SCHEMA: Schema = StringSchema::new("Service ID.").max_length(256).schema();
.max_length(256)
.schema();
pub const PROXMOX_CONFIG_DIGEST_SCHEMA: Schema = StringSchema::new( pub const PROXMOX_CONFIG_DIGEST_SCHEMA: Schema = StringSchema::new(
"Prevent changes if current configuration file has different \ "Prevent changes if current configuration file has different \
@ -303,10 +300,8 @@ pub const PROXMOX_CONFIG_DIGEST_SCHEMA: Schema = StringSchema::new(
/// API schema format definition for repository URLs /// API schema format definition for repository URLs
pub const BACKUP_REPO_URL: ApiStringFormat = ApiStringFormat::Pattern(&BACKUP_REPO_URL_REGEX); pub const BACKUP_REPO_URL: ApiStringFormat = ApiStringFormat::Pattern(&BACKUP_REPO_URL_REGEX);
// Complex type definitions // Complex type definitions
#[api()] #[api()]
#[derive(Default, Serialize, Deserialize)] #[derive(Default, Serialize, Deserialize)]
/// Storage space usage information. /// Storage space usage information.
@ -325,7 +320,6 @@ pub const PASSWORD_HINT_SCHEMA: Schema = StringSchema::new("Password hint.")
.max_length(64) .max_length(64)
.schema(); .schema();
#[api()] #[api()]
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "PascalCase")] #[serde(rename_all = "PascalCase")]
@ -356,7 +350,6 @@ pub struct APTUpdateInfo {
pub extra_info: Option<String>, pub extra_info: Option<String>,
} }
#[api()] #[api()]
#[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize)] #[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")] #[serde(rename_all = "lowercase")]
@ -368,7 +361,6 @@ pub enum NodePowerCommand {
Shutdown, Shutdown,
} }
#[api()] #[api()]
#[derive(Eq, PartialEq, Debug, Serialize, Deserialize)] #[derive(Eq, PartialEq, Debug, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")] #[serde(rename_all = "lowercase")]
@ -416,10 +408,7 @@ pub struct TaskListItem {
pub const NODE_TASKS_LIST_TASKS_RETURN_TYPE: ReturnType = ReturnType { pub const NODE_TASKS_LIST_TASKS_RETURN_TYPE: ReturnType = ReturnType {
optional: false, optional: false,
schema: &ArraySchema::new( schema: &ArraySchema::new("A list of tasks.", &TaskListItem::API_SCHEMA).schema(),
"A list of tasks.",
&TaskListItem::API_SCHEMA,
).schema(),
}; };
#[api()] #[api()]

View File

@ -3,40 +3,34 @@ use serde::{Deserialize, Serialize};
use proxmox_schema::*; use proxmox_schema::*;
use crate::{ use crate::{
CIDR_FORMAT, CIDR_V4_FORMAT, CIDR_V6_FORMAT, IP_FORMAT, IP_V4_FORMAT, IP_V6_FORMAT,
PROXMOX_SAFE_ID_REGEX, PROXMOX_SAFE_ID_REGEX,
IP_V4_FORMAT, IP_V6_FORMAT, IP_FORMAT,
CIDR_V4_FORMAT, CIDR_V6_FORMAT, CIDR_FORMAT,
}; };
pub const NETWORK_INTERFACE_FORMAT: ApiStringFormat = pub const NETWORK_INTERFACE_FORMAT: ApiStringFormat =
ApiStringFormat::Pattern(&PROXMOX_SAFE_ID_REGEX); ApiStringFormat::Pattern(&PROXMOX_SAFE_ID_REGEX);
pub const IP_V4_SCHEMA: Schema = pub const IP_V4_SCHEMA: Schema = StringSchema::new("IPv4 address.")
StringSchema::new("IPv4 address.")
.format(&IP_V4_FORMAT) .format(&IP_V4_FORMAT)
.max_length(15) .max_length(15)
.schema(); .schema();
pub const IP_V6_SCHEMA: Schema = pub const IP_V6_SCHEMA: Schema = StringSchema::new("IPv6 address.")
StringSchema::new("IPv6 address.")
.format(&IP_V6_FORMAT) .format(&IP_V6_FORMAT)
.max_length(39) .max_length(39)
.schema(); .schema();
pub const IP_SCHEMA: Schema = pub const IP_SCHEMA: Schema = StringSchema::new("IP (IPv4 or IPv6) address.")
StringSchema::new("IP (IPv4 or IPv6) address.")
.format(&IP_FORMAT) .format(&IP_FORMAT)
.max_length(39) .max_length(39)
.schema(); .schema();
pub const CIDR_V4_SCHEMA: Schema = pub const CIDR_V4_SCHEMA: Schema = StringSchema::new("IPv4 address with netmask (CIDR notation).")
StringSchema::new("IPv4 address with netmask (CIDR notation).")
.format(&CIDR_V4_FORMAT) .format(&CIDR_V4_FORMAT)
.max_length(18) .max_length(18)
.schema(); .schema();
pub const CIDR_V6_SCHEMA: Schema = pub const CIDR_V6_SCHEMA: Schema = StringSchema::new("IPv6 address with netmask (CIDR notation).")
StringSchema::new("IPv6 address with netmask (CIDR notation).")
.format(&CIDR_V6_FORMAT) .format(&CIDR_V6_FORMAT)
.max_length(43) .max_length(43)
.schema(); .schema();
@ -130,13 +124,14 @@ pub const NETWORK_INTERFACE_NAME_SCHEMA: Schema = StringSchema::new("Network int
.max_length(15) // libc::IFNAMSIZ-1 .max_length(15) // libc::IFNAMSIZ-1
.schema(); .schema();
pub const NETWORK_INTERFACE_ARRAY_SCHEMA: Schema = ArraySchema::new( pub const NETWORK_INTERFACE_ARRAY_SCHEMA: Schema =
"Network interface list.", &NETWORK_INTERFACE_NAME_SCHEMA) ArraySchema::new("Network interface list.", &NETWORK_INTERFACE_NAME_SCHEMA).schema();
.schema();
pub const NETWORK_INTERFACE_LIST_SCHEMA: Schema = StringSchema::new( pub const NETWORK_INTERFACE_LIST_SCHEMA: Schema =
"A list of network devices, comma separated.") StringSchema::new("A list of network devices, comma separated.")
.format(&ApiStringFormat::PropertyString(&NETWORK_INTERFACE_ARRAY_SCHEMA)) .format(&ApiStringFormat::PropertyString(
&NETWORK_INTERFACE_ARRAY_SCHEMA,
))
.schema(); .schema();
#[api( #[api(

View File

@ -1,23 +1,19 @@
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use proxmox_schema::{ use proxmox_schema::{api, ApiStringFormat, ArraySchema, Schema, StringSchema, Updater};
api, ApiStringFormat, ArraySchema, Schema, StringSchema, Updater,
};
use super::{ use super::{
PROXMOX_SAFE_ID_REGEX, PROXMOX_SAFE_ID_FORMAT, REALM_ID_SCHEMA, PROXMOX_SAFE_ID_FORMAT, PROXMOX_SAFE_ID_REGEX, REALM_ID_SCHEMA, SINGLE_LINE_COMMENT_SCHEMA,
SINGLE_LINE_COMMENT_SCHEMA,
}; };
pub const OPENID_SCOPE_FORMAT: ApiStringFormat = pub const OPENID_SCOPE_FORMAT: ApiStringFormat = ApiStringFormat::Pattern(&PROXMOX_SAFE_ID_REGEX);
ApiStringFormat::Pattern(&PROXMOX_SAFE_ID_REGEX);
pub const OPENID_SCOPE_SCHEMA: Schema = StringSchema::new("OpenID Scope Name.") pub const OPENID_SCOPE_SCHEMA: Schema = StringSchema::new("OpenID Scope Name.")
.format(&OPENID_SCOPE_FORMAT) .format(&OPENID_SCOPE_FORMAT)
.schema(); .schema();
pub const OPENID_SCOPE_ARRAY_SCHEMA: Schema = ArraySchema::new( pub const OPENID_SCOPE_ARRAY_SCHEMA: Schema =
"Array of OpenId Scopes.", &OPENID_SCOPE_SCHEMA).schema(); ArraySchema::new("Array of OpenId Scopes.", &OPENID_SCOPE_SCHEMA).schema();
pub const OPENID_SCOPE_LIST_FORMAT: ApiStringFormat = pub const OPENID_SCOPE_LIST_FORMAT: ApiStringFormat =
ApiStringFormat::PropertyString(&OPENID_SCOPE_ARRAY_SCHEMA); ApiStringFormat::PropertyString(&OPENID_SCOPE_ARRAY_SCHEMA);
@ -28,15 +24,15 @@ pub const OPENID_SCOPE_LIST_SCHEMA: Schema = StringSchema::new("OpenID Scope Lis
.default(OPENID_DEFAILT_SCOPE_LIST) .default(OPENID_DEFAILT_SCOPE_LIST)
.schema(); .schema();
pub const OPENID_ACR_FORMAT: ApiStringFormat = pub const OPENID_ACR_FORMAT: ApiStringFormat = ApiStringFormat::Pattern(&PROXMOX_SAFE_ID_REGEX);
ApiStringFormat::Pattern(&PROXMOX_SAFE_ID_REGEX);
pub const OPENID_ACR_SCHEMA: Schema = StringSchema::new("OpenID Authentication Context Class Reference.") pub const OPENID_ACR_SCHEMA: Schema =
StringSchema::new("OpenID Authentication Context Class Reference.")
.format(&OPENID_SCOPE_FORMAT) .format(&OPENID_SCOPE_FORMAT)
.schema(); .schema();
pub const OPENID_ACR_ARRAY_SCHEMA: Schema = ArraySchema::new( pub const OPENID_ACR_ARRAY_SCHEMA: Schema =
"Array of OpenId ACRs.", &OPENID_ACR_SCHEMA).schema(); ArraySchema::new("Array of OpenId ACRs.", &OPENID_ACR_SCHEMA).schema();
pub const OPENID_ACR_LIST_FORMAT: ApiStringFormat = pub const OPENID_ACR_LIST_FORMAT: ApiStringFormat =
ApiStringFormat::PropertyString(&OPENID_ACR_ARRAY_SCHEMA); ApiStringFormat::PropertyString(&OPENID_ACR_ARRAY_SCHEMA);
@ -50,10 +46,12 @@ pub const OPENID_USERNAME_CLAIM_SCHEMA: Schema = StringSchema::new(
is up to the identity provider to guarantee the uniqueness. The \ is up to the identity provider to guarantee the uniqueness. The \
OpenID specification only guarantees that Subject ('sub') is \ OpenID specification only guarantees that Subject ('sub') is \
unique. Also make sure that the user is not allowed to change that \ unique. Also make sure that the user is not allowed to change that \
attribute by himself!") attribute by himself!",
)
.max_length(64) .max_length(64)
.min_length(1) .min_length(1)
.format(&PROXMOX_SAFE_ID_FORMAT) .schema(); .format(&PROXMOX_SAFE_ID_FORMAT)
.schema();
#[api( #[api(
properties: { properties: {

View File

@ -3,13 +3,15 @@ use serde::{Deserialize, Serialize};
use super::*; use super::*;
use proxmox_schema::*; use proxmox_schema::*;
pub const REMOTE_PASSWORD_SCHEMA: Schema = StringSchema::new("Password or auth token for remote host.") pub const REMOTE_PASSWORD_SCHEMA: Schema =
StringSchema::new("Password or auth token for remote host.")
.format(&PASSWORD_FORMAT) .format(&PASSWORD_FORMAT)
.min_length(1) .min_length(1)
.max_length(1024) .max_length(1024)
.schema(); .schema();
pub const REMOTE_PASSWORD_BASE64_SCHEMA: Schema = StringSchema::new("Password or auth token for remote host (stored as base64 string).") pub const REMOTE_PASSWORD_BASE64_SCHEMA: Schema =
StringSchema::new("Password or auth token for remote host (stored as base64 string).")
.format(&PASSWORD_FORMAT) .format(&PASSWORD_FORMAT)
.min_length(1) .min_length(1)
.max_length(1024) .max_length(1024)
@ -21,7 +23,6 @@ pub const REMOTE_ID_SCHEMA: Schema = StringSchema::new("Remote ID.")
.max_length(32) .max_length(32)
.schema(); .schema();
#[api( #[api(
properties: { properties: {
comment: { comment: {

View File

@ -4,13 +4,9 @@ use std::convert::TryFrom;
use anyhow::{bail, Error}; use anyhow::{bail, Error};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use proxmox_schema::{api, Schema, IntegerSchema, StringSchema, Updater}; use proxmox_schema::{api, IntegerSchema, Schema, StringSchema, Updater};
use crate::{ use crate::{OptionalDeviceIdentification, CHANGER_NAME_SCHEMA, PROXMOX_SAFE_ID_FORMAT};
PROXMOX_SAFE_ID_FORMAT,
CHANGER_NAME_SCHEMA,
OptionalDeviceIdentification,
};
pub const DRIVE_NAME_SCHEMA: Schema = StringSchema::new("Drive Identifier.") pub const DRIVE_NAME_SCHEMA: Schema = StringSchema::new("Drive Identifier.")
.format(&PROXMOX_SAFE_ID_FORMAT) .format(&PROXMOX_SAFE_ID_FORMAT)
@ -18,12 +14,11 @@ pub const DRIVE_NAME_SCHEMA: Schema = StringSchema::new("Drive Identifier.")
.max_length(32) .max_length(32)
.schema(); .schema();
pub const LTO_DRIVE_PATH_SCHEMA: Schema = StringSchema::new( pub const LTO_DRIVE_PATH_SCHEMA: Schema =
"The path to a LTO SCSI-generic tape device (i.e. '/dev/sg0')") StringSchema::new("The path to a LTO SCSI-generic tape device (i.e. '/dev/sg0')").schema();
.schema();
pub const CHANGER_DRIVENUM_SCHEMA: Schema = IntegerSchema::new( pub const CHANGER_DRIVENUM_SCHEMA: Schema =
"Associated changer drive number (requires option changer)") IntegerSchema::new("Associated changer drive number (requires option changer)")
.minimum(0) .minimum(0)
.maximum(255) .maximum(255)
.default(0) .default(0)

View File

@ -3,19 +3,15 @@ use ::serde::{Deserialize, Serialize};
use proxmox_schema::*; use proxmox_schema::*;
use proxmox_uuid::Uuid; use proxmox_uuid::Uuid;
use crate::{ use crate::{MediaLocation, MediaStatus, UUID_FORMAT};
UUID_FORMAT,
MediaStatus,
MediaLocation,
};
pub const MEDIA_SET_UUID_SCHEMA: Schema = pub const MEDIA_SET_UUID_SCHEMA: Schema = StringSchema::new(
StringSchema::new("MediaSet Uuid (We use the all-zero Uuid to reseve an empty media for a specific pool).") "MediaSet Uuid (We use the all-zero Uuid to reseve an empty media for a specific pool).",
)
.format(&UUID_FORMAT) .format(&UUID_FORMAT)
.schema(); .schema();
pub const MEDIA_UUID_SCHEMA: Schema = pub const MEDIA_UUID_SCHEMA: Schema = StringSchema::new("Media Uuid.")
StringSchema::new("Media Uuid.")
.format(&UUID_FORMAT) .format(&UUID_FORMAT)
.schema(); .schema();

View File

@ -9,14 +9,12 @@ use std::str::FromStr;
use anyhow::Error; use anyhow::Error;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use proxmox_schema::{api, Schema, StringSchema, ApiStringFormat, Updater}; use proxmox_schema::{api, ApiStringFormat, Schema, StringSchema, Updater};
use proxmox_time::{CalendarEvent, TimeSpan}; use proxmox_time::{CalendarEvent, TimeSpan};
use crate::{ use crate::{
PROXMOX_SAFE_ID_FORMAT, PROXMOX_SAFE_ID_FORMAT, SINGLE_LINE_COMMENT_FORMAT, SINGLE_LINE_COMMENT_SCHEMA,
SINGLE_LINE_COMMENT_FORMAT,
SINGLE_LINE_COMMENT_SCHEMA,
TAPE_ENCRYPTION_KEY_FINGERPRINT_SCHEMA, TAPE_ENCRYPTION_KEY_FINGERPRINT_SCHEMA,
}; };
@ -27,17 +25,20 @@ pub const MEDIA_POOL_NAME_SCHEMA: Schema = StringSchema::new("Media pool name.")
.schema(); .schema();
pub const MEDIA_SET_NAMING_TEMPLATE_SCHEMA: Schema = StringSchema::new( pub const MEDIA_SET_NAMING_TEMPLATE_SCHEMA: Schema = StringSchema::new(
"Media set naming template (may contain strftime() time format specifications).") "Media set naming template (may contain strftime() time format specifications).",
)
.format(&SINGLE_LINE_COMMENT_FORMAT) .format(&SINGLE_LINE_COMMENT_FORMAT)
.min_length(2) .min_length(2)
.max_length(64) .max_length(64)
.schema(); .schema();
pub const MEDIA_SET_ALLOCATION_POLICY_FORMAT: ApiStringFormat = pub const MEDIA_SET_ALLOCATION_POLICY_FORMAT: ApiStringFormat = ApiStringFormat::VerifyFn(|s| {
ApiStringFormat::VerifyFn(|s| { MediaSetPolicy::from_str(s)?; Ok(()) }); MediaSetPolicy::from_str(s)?;
Ok(())
});
pub const MEDIA_SET_ALLOCATION_POLICY_SCHEMA: Schema = StringSchema::new( pub const MEDIA_SET_ALLOCATION_POLICY_SCHEMA: Schema =
"Media set allocation policy ('continue', 'always', or a calendar event).") StringSchema::new("Media set allocation policy ('continue', 'always', or a calendar event).")
.format(&MEDIA_SET_ALLOCATION_POLICY_FORMAT) .format(&MEDIA_SET_ALLOCATION_POLICY_FORMAT)
.schema(); .schema();
@ -68,11 +69,13 @@ impl std::str::FromStr for MediaSetPolicy {
} }
} }
pub const MEDIA_RETENTION_POLICY_FORMAT: ApiStringFormat = pub const MEDIA_RETENTION_POLICY_FORMAT: ApiStringFormat = ApiStringFormat::VerifyFn(|s| {
ApiStringFormat::VerifyFn(|s| { RetentionPolicy::from_str(s)?; Ok(()) }); RetentionPolicy::from_str(s)?;
Ok(())
});
pub const MEDIA_RETENTION_POLICY_SCHEMA: Schema = StringSchema::new( pub const MEDIA_RETENTION_POLICY_SCHEMA: Schema =
"Media retention policy ('overwrite', 'keep', or time span).") StringSchema::new("Media retention policy ('overwrite', 'keep', or time span).")
.format(&MEDIA_RETENTION_POLICY_FORMAT) .format(&MEDIA_RETENTION_POLICY_FORMAT)
.schema(); .schema();

View File

@ -24,12 +24,10 @@ pub use media::*;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use proxmox_schema::{api, const_regex, Schema, StringSchema, ApiStringFormat}; use proxmox_schema::{api, const_regex, ApiStringFormat, Schema, StringSchema};
use proxmox_uuid::Uuid; use proxmox_uuid::Uuid;
use crate::{ use crate::{BACKUP_ID_SCHEMA, BACKUP_TYPE_SCHEMA, FINGERPRINT_SHA256_FORMAT};
FINGERPRINT_SHA256_FORMAT, BACKUP_ID_SCHEMA, BACKUP_TYPE_SCHEMA,
};
const_regex! { const_regex! {
pub TAPE_RESTORE_SNAPSHOT_REGEX = concat!(r"^", PROXMOX_SAFE_ID_REGEX_STR!(), r":", SNAPSHOT_PATH_REGEX_STR!(), r"$"); pub TAPE_RESTORE_SNAPSHOT_REGEX = concat!(r"^", PROXMOX_SAFE_ID_REGEX_STR!(), r":", SNAPSHOT_PATH_REGEX_STR!(), r"$");
@ -38,14 +36,13 @@ const_regex!{
pub const TAPE_RESTORE_SNAPSHOT_FORMAT: ApiStringFormat = pub const TAPE_RESTORE_SNAPSHOT_FORMAT: ApiStringFormat =
ApiStringFormat::Pattern(&TAPE_RESTORE_SNAPSHOT_REGEX); ApiStringFormat::Pattern(&TAPE_RESTORE_SNAPSHOT_REGEX);
pub const TAPE_ENCRYPTION_KEY_FINGERPRINT_SCHEMA: Schema = StringSchema::new( pub const TAPE_ENCRYPTION_KEY_FINGERPRINT_SCHEMA: Schema =
"Tape encryption key fingerprint (sha256)." StringSchema::new("Tape encryption key fingerprint (sha256).")
)
.format(&FINGERPRINT_SHA256_FORMAT) .format(&FINGERPRINT_SHA256_FORMAT)
.schema(); .schema();
pub const TAPE_RESTORE_SNAPSHOT_SCHEMA: Schema = StringSchema::new( pub const TAPE_RESTORE_SNAPSHOT_SCHEMA: Schema =
"A snapshot in the format: 'store:type/id/time") StringSchema::new("A snapshot in the format: 'store:type/id/time")
.format(&TAPE_RESTORE_SNAPSHOT_FORMAT) .format(&TAPE_RESTORE_SNAPSHOT_FORMAT)
.type_text("store:type/id/time") .type_text("store:type/id/time")
.schema(); .schema();

View File

@ -1,14 +1,14 @@
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use proxmox_schema::{api, Schema, IntegerSchema, StringSchema, Updater}; use proxmox_schema::{api, IntegerSchema, Schema, StringSchema, Updater};
use crate::{ use crate::{
HumanByte, CIDR_SCHEMA, DAILY_DURATION_FORMAT, HumanByte, CIDR_SCHEMA, DAILY_DURATION_FORMAT, PROXMOX_SAFE_ID_FORMAT,
PROXMOX_SAFE_ID_FORMAT, SINGLE_LINE_COMMENT_SCHEMA, SINGLE_LINE_COMMENT_SCHEMA,
}; };
pub const TRAFFIC_CONTROL_TIMEFRAME_SCHEMA: Schema = StringSchema::new( pub const TRAFFIC_CONTROL_TIMEFRAME_SCHEMA: Schema =
"Timeframe to specify when the rule is actice.") StringSchema::new("Timeframe to specify when the rule is actice.")
.format(&DAILY_DURATION_FORMAT) .format(&DAILY_DURATION_FORMAT)
.schema(); .schema();
@ -18,13 +18,13 @@ pub const TRAFFIC_CONTROL_ID_SCHEMA: Schema = StringSchema::new("Rule ID.")
.max_length(32) .max_length(32)
.schema(); .schema();
pub const TRAFFIC_CONTROL_RATE_SCHEMA: Schema = IntegerSchema::new( pub const TRAFFIC_CONTROL_RATE_SCHEMA: Schema =
"Rate limit (for Token bucket filter) in bytes/second.") IntegerSchema::new("Rate limit (for Token bucket filter) in bytes/second.")
.minimum(100_000) .minimum(100_000)
.schema(); .schema();
pub const TRAFFIC_CONTROL_BURST_SCHEMA: Schema = IntegerSchema::new( pub const TRAFFIC_CONTROL_BURST_SCHEMA: Schema =
"Size of the token bucket (for Token bucket filter) in bytes.") IntegerSchema::new("Size of the token bucket (for Token bucket filter) in bytes.")
.minimum(1000) .minimum(1000)
.schema(); .schema();

View File

@ -1,19 +1,19 @@
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use proxmox_schema::{ use proxmox_schema::{api, BooleanSchema, IntegerSchema, Schema, StringSchema, Updater};
api, BooleanSchema, IntegerSchema, Schema, StringSchema, Updater,
};
use super::{SINGLE_LINE_COMMENT_FORMAT, SINGLE_LINE_COMMENT_SCHEMA};
use super::userid::{Authid, Userid, PROXMOX_TOKEN_ID_SCHEMA}; use super::userid::{Authid, Userid, PROXMOX_TOKEN_ID_SCHEMA};
use super::{SINGLE_LINE_COMMENT_FORMAT, SINGLE_LINE_COMMENT_SCHEMA};
pub const ENABLE_USER_SCHEMA: Schema = BooleanSchema::new( pub const ENABLE_USER_SCHEMA: Schema = BooleanSchema::new(
"Enable the account (default). You can set this to '0' to disable the account.") "Enable the account (default). You can set this to '0' to disable the account.",
)
.default(true) .default(true)
.schema(); .schema();
pub const EXPIRE_USER_SCHEMA: Schema = IntegerSchema::new( pub const EXPIRE_USER_SCHEMA: Schema = IntegerSchema::new(
"Account expiration date (seconds since epoch). '0' means no expiration date.") "Account expiration date (seconds since epoch). '0' means no expiration date.",
)
.default(0) .default(0)
.minimum(0) .minimum(0)
.schema(); .schema();

View File

@ -39,15 +39,35 @@ use proxmox_schema::{
// slash is not allowed because it is used as pve API delimiter // slash is not allowed because it is used as pve API delimiter
// also see "man useradd" // also see "man useradd"
#[macro_export] #[macro_export]
macro_rules! USER_NAME_REGEX_STR { () => (r"(?:[^\s:/[:cntrl:]]+)") } macro_rules! USER_NAME_REGEX_STR {
() => {
r"(?:[^\s:/[:cntrl:]]+)"
};
}
#[macro_export] #[macro_export]
macro_rules! GROUP_NAME_REGEX_STR { () => (USER_NAME_REGEX_STR!()) } macro_rules! GROUP_NAME_REGEX_STR {
() => {
USER_NAME_REGEX_STR!()
};
}
#[macro_export] #[macro_export]
macro_rules! TOKEN_NAME_REGEX_STR { () => (PROXMOX_SAFE_ID_REGEX_STR!()) } macro_rules! TOKEN_NAME_REGEX_STR {
() => {
PROXMOX_SAFE_ID_REGEX_STR!()
};
}
#[macro_export] #[macro_export]
macro_rules! USER_ID_REGEX_STR { () => (concat!(USER_NAME_REGEX_STR!(), r"@", PROXMOX_SAFE_ID_REGEX_STR!())) } macro_rules! USER_ID_REGEX_STR {
() => {
concat!(USER_NAME_REGEX_STR!(), r"@", PROXMOX_SAFE_ID_REGEX_STR!())
};
}
#[macro_export] #[macro_export]
macro_rules! APITOKEN_ID_REGEX_STR { () => (concat!(USER_ID_REGEX_STR!() , r"!", TOKEN_NAME_REGEX_STR!())) } macro_rules! APITOKEN_ID_REGEX_STR {
() => {
concat!(USER_ID_REGEX_STR!(), r"!", TOKEN_NAME_REGEX_STR!())
};
}
const_regex! { const_regex! {
pub PROXMOX_USER_NAME_REGEX = concat!(r"^", USER_NAME_REGEX_STR!(), r"$"); pub PROXMOX_USER_NAME_REGEX = concat!(r"^", USER_NAME_REGEX_STR!(), r"$");
@ -238,7 +258,8 @@ impl TryFrom<String> for Realm {
type Error = Error; type Error = Error;
fn try_from(s: String) -> Result<Self, Error> { fn try_from(s: String) -> Result<Self, Error> {
PROXMOX_AUTH_REALM_STRING_SCHEMA.check_constraints(&s) PROXMOX_AUTH_REALM_STRING_SCHEMA
.check_constraints(&s)
.map_err(|_| format_err!("invalid realm"))?; .map_err(|_| format_err!("invalid realm"))?;
Ok(Self(s)) Ok(Self(s))
@ -249,7 +270,8 @@ impl<'a> TryFrom<&'a str> for &'a RealmRef {
type Error = Error; type Error = Error;
fn try_from(s: &'a str) -> Result<&'a RealmRef, Error> { fn try_from(s: &'a str) -> Result<&'a RealmRef, Error> {
PROXMOX_AUTH_REALM_STRING_SCHEMA.check_constraints(s) PROXMOX_AUTH_REALM_STRING_SCHEMA
.check_constraints(s)
.map_err(|_| format_err!("invalid realm"))?; .map_err(|_| format_err!("invalid realm"))?;
Ok(RealmRef::new(s)) Ok(RealmRef::new(s))
@ -482,7 +504,8 @@ impl std::str::FromStr for Userid {
bail!("invalid user name in user id"); bail!("invalid user name in user id");
} }
PROXMOX_AUTH_REALM_STRING_SCHEMA.check_constraints(realm) PROXMOX_AUTH_REALM_STRING_SCHEMA
.check_constraints(realm)
.map_err(|_| format_err!("invalid realm in user id"))?; .map_err(|_| format_err!("invalid realm in user id"))?;
Ok(Self::from((UsernameRef::new(name), RealmRef::new(realm)))) Ok(Self::from((UsernameRef::new(name), RealmRef::new(realm))))
@ -503,7 +526,8 @@ impl TryFrom<String> for Userid {
bail!("invalid user name in user id"); bail!("invalid user name in user id");
} }
PROXMOX_AUTH_REALM_STRING_SCHEMA.check_constraints(&data[(name_len + 1)..]) PROXMOX_AUTH_REALM_STRING_SCHEMA
.check_constraints(&data[(name_len + 1)..])
.map_err(|_| format_err!("invalid realm in user id"))?; .map_err(|_| format_err!("invalid realm in user id"))?;
Ok(Self { data, name_len }) Ok(Self { data, name_len })
@ -532,7 +556,7 @@ impl PartialEq<String> for Userid {
#[derive(Clone, Debug, Eq, PartialEq, Hash, UpdaterType)] #[derive(Clone, Debug, Eq, PartialEq, Hash, UpdaterType)]
pub struct Authid { pub struct Authid {
user: Userid, user: Userid,
tokenname: Option<Tokenname> tokenname: Option<Tokenname>,
} }
impl ApiType for Authid { impl ApiType for Authid {
@ -679,7 +703,10 @@ fn test_token_id() {
let token_userid = auth_id.user(); let token_userid = auth_id.user();
assert_eq!(&userid, token_userid); assert_eq!(&userid, token_userid);
assert!(auth_id.is_token()); assert!(auth_id.is_token());
assert_eq!(auth_id.tokenname().expect("Token has tokenname").as_str(), TokennameRef::new("bar").as_str()); assert_eq!(
auth_id.tokenname().expect("Token has tokenname").as_str(),
TokennameRef::new("bar").as_str()
);
assert_eq!(auth_id.to_string(), "test@pam!bar".to_string()); assert_eq!(auth_id.to_string(), "test@pam!bar".to_string());
} }

View File

@ -6,8 +6,7 @@ const_regex! {
pub ZPOOL_NAME_REGEX = r"^[a-zA-Z][a-z0-9A-Z\-_.:]+$"; pub ZPOOL_NAME_REGEX = r"^[a-zA-Z][a-z0-9A-Z\-_.:]+$";
} }
pub const ZFS_ASHIFT_SCHEMA: Schema = IntegerSchema::new( pub const ZFS_ASHIFT_SCHEMA: Schema = IntegerSchema::new("Pool sector size exponent.")
"Pool sector size exponent.")
.minimum(9) .minimum(9)
.maximum(16) .maximum(16)
.default(12) .default(12)