Review pass
This commit is contained in:
parent
2a05930ae7
commit
99fa298b92
2 changed files with 621 additions and 94 deletions
|
|
@ -7,7 +7,7 @@ use crate::consts::{
|
|||
DEFAULT_MERGEABLE_FILE_EXTENSIONS, DEFAULT_PORT, DEFAULT_RESPONSE_TIMEOUT_SECONDS,
|
||||
};
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize, Clone, Default)]
|
||||
#[derive(Debug, Deserialize, Serialize, Clone)]
|
||||
pub struct ServerConfig {
|
||||
#[serde(default = "default_host")]
|
||||
pub host: String,
|
||||
|
|
@ -28,6 +28,19 @@ pub struct ServerConfig {
|
|||
pub mergeable_file_extensions: Vec<String>,
|
||||
}
|
||||
|
||||
impl Default for ServerConfig {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
host: default_host(),
|
||||
port: default_port(),
|
||||
max_body_size_mb: default_max_body_size_mb(),
|
||||
max_clients_per_vault: default_max_clients_per_vault(),
|
||||
response_timeout: default_response_timeout(),
|
||||
mergeable_file_extensions: default_mergeable_file_extensions(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn default_host() -> String {
|
||||
debug!("Using default server host: {DEFAULT_HOST}");
|
||||
DEFAULT_HOST.to_owned()
|
||||
|
|
@ -60,3 +73,36 @@ fn default_mergeable_file_extensions() -> Vec<String> {
|
|||
.map(|s| (*s).to_owned())
|
||||
.collect()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::config::Config;
|
||||
|
||||
#[tokio::test]
|
||||
async fn fresh_and_omitted_server_configs_use_the_documented_defaults() {
|
||||
let directory = tempfile::tempdir().unwrap();
|
||||
let path = directory.path().join("config.yml");
|
||||
let fresh = Config::read_or_create(&path).await.unwrap();
|
||||
let reread = Config::load_from_file(&path).await.unwrap();
|
||||
let omitted: Config = serde_yaml::from_str("{}").unwrap();
|
||||
let explicit: Config = serde_yaml::from_str("server: {}").unwrap();
|
||||
for config in [fresh, reread, omitted, explicit] {
|
||||
assert_eq!(config.server.host, DEFAULT_HOST);
|
||||
assert_eq!(config.server.port, DEFAULT_PORT);
|
||||
assert_eq!(config.server.max_body_size_mb, DEFAULT_MAX_BODY_SIZE_MB);
|
||||
assert_eq!(
|
||||
config.server.max_clients_per_vault,
|
||||
DEFAULT_MAX_CLIENTS_PER_VAULT
|
||||
);
|
||||
assert_eq!(
|
||||
config.server.response_timeout,
|
||||
DEFAULT_RESPONSE_TIMEOUT_SECONDS
|
||||
);
|
||||
assert_eq!(
|
||||
config.server.mergeable_file_extensions,
|
||||
DEFAULT_MERGEABLE_FILE_EXTENSIONS
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,10 @@ use bimap::BiHashMap;
|
|||
use rand::{Rng, distr::Alphanumeric, rng};
|
||||
use serde::{Deserialize, Deserializer, Serialize, de::Error};
|
||||
|
||||
use crate::app_state::database::models::VaultId;
|
||||
use crate::{
|
||||
app_state::database::models::VaultId,
|
||||
utils::normalize_vault_id::{normalize_string, validate_vault_id},
|
||||
};
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize, Clone)]
|
||||
pub struct UserConfig {
|
||||
|
|
@ -71,9 +74,23 @@ pub enum VaultAccess {
|
|||
|
||||
#[derive(Debug, Deserialize, Serialize, Clone, Default)]
|
||||
pub struct AllowListedVaults {
|
||||
#[serde(deserialize_with = "deserialize_allowed_vaults")]
|
||||
pub allowed: Vec<VaultId>,
|
||||
}
|
||||
|
||||
fn deserialize_allowed_vaults<'de, D: Deserializer<'de>>(
|
||||
deserializer: D,
|
||||
) -> Result<Vec<VaultId>, D::Error> {
|
||||
Vec::<String>::deserialize(deserializer)?
|
||||
.into_iter()
|
||||
.map(|name| {
|
||||
let vault = normalize_string(&name);
|
||||
validate_vault_id(&vault).map_err(D::Error::custom)?;
|
||||
Ok(vault)
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn default_users() -> Vec<User> {
|
||||
vec![User {
|
||||
name: "admin".to_owned(),
|
||||
|
|
@ -95,6 +112,24 @@ mod tests {
|
|||
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn allowlists_normalize_case_and_whitespace_but_preserve_unicode_identity() {
|
||||
let list: AllowListedVaults = serde_json::from_value(json!({
|
||||
"allowed": [" MyVault ", "CAFÉ", "CAFE\u{301}"]
|
||||
}))
|
||||
.unwrap();
|
||||
assert_eq!(list.allowed, ["myvault", "café", "cafe\u{301}"]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn allowlists_reject_invalid_vault_names() {
|
||||
for name in ["", " ", ".", "..", "../escaped", "a/b", "a\\b", "a\0b"] {
|
||||
assert!(
|
||||
serde_json::from_value::<AllowListedVaults>(json!({"allowed": [name]})).is_err()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_validate_users_unique_names_and_tokens() {
|
||||
let config_json = json!({
|
||||
|
|
|
|||
Loading…
Reference in a new issue