From 33592de8f32984419faa6464365c44af673a65fd Mon Sep 17 00:00:00 2001 From: naskya Date: Fri, 21 Jun 2024 03:13:58 +0900 Subject: [PATCH] fix validation --- src/command/config.rs | 4 +- src/command/config/migrate.rs | 4 +- src/command/config/migrate/v20240701.rs | 10 ++-- src/command/config/validate.rs | 70 +++++++++++++++++-------- src/config/client.rs | 5 +- src/config/server.rs | 8 ++- 6 files changed, 68 insertions(+), 33 deletions(-) diff --git a/src/command/config.rs b/src/command/config.rs index fdd2d21..506089a 100644 --- a/src/command/config.rs +++ b/src/command/config.rs @@ -22,9 +22,9 @@ pub(crate) enum ConfigVersion { #[derive(thiserror::Error, Debug)] pub(crate) enum Error { #[error(transparent)] - Migrate(#[from] migrate::ConfigMigrateError), + Migrate(#[from] migrate::MigrationError), #[error(transparent)] - Validate(#[from] validate::ConfigValidateError), + Validate(#[from] validate::ValidationError), } pub(crate) async fn run(command: Commands) -> Result<(), Error> { diff --git a/src/command/config/migrate.rs b/src/command/config/migrate.rs index e72402d..c544835 100644 --- a/src/command/config/migrate.rs +++ b/src/command/config/migrate.rs @@ -5,12 +5,12 @@ mod v20240701; use super::ConfigVersion; #[derive(thiserror::Error, Debug)] -pub(crate) enum ConfigMigrateError { +pub(crate) enum MigrationError { #[error(transparent)] V20240701(#[from] v20240701::Error), } -pub(super) async fn run(version: ConfigVersion) -> Result<(), ConfigMigrateError> { +pub(super) async fn run(version: ConfigVersion) -> Result<(), MigrationError> { match version { ConfigVersion::V20240701 => v20240701::run().await?, } diff --git a/src/command/config/migrate/v20240701.rs b/src/command/config/migrate/v20240701.rs index a14efbb..cb1b2ae 100644 --- a/src/command/config/migrate/v20240701.rs +++ b/src/command/config/migrate/v20240701.rs @@ -394,7 +394,7 @@ fn create_new_client_config(meta: Meta) -> Result { let mut config = client::Config { theme: None, image: None, - pinned_links: vec![], + pinned_links: None, }; if meta.theme_color.is_some() @@ -438,7 +438,7 @@ pub(super) async fn run() -> Result<(), Error> { } let mut server_toml = - fs::File::create_new("config/server.toml").map_err(WriteTomlConfigError::ServerWrite)?; + fs::File::create("config/server.toml").map_err(WriteTomlConfigError::ServerWrite)?; server_toml .write( toml::to_string_pretty(&server_config) @@ -446,10 +446,10 @@ pub(super) async fn run() -> Result<(), Error> { .as_bytes(), ) .map_err(WriteTomlConfigError::ServerWrite)?; - cprintln!("config/server.toml has been created!"); + cprintln!("config/server.toml has been created!"); let mut client_toml = - fs::File::create_new("config/client.toml").map_err(WriteTomlConfigError::ClientWrite)?; + fs::File::create("config/client.toml").map_err(WriteTomlConfigError::ClientWrite)?; client_toml .write( toml::to_string_pretty(&client_config) @@ -457,7 +457,7 @@ pub(super) async fn run() -> Result<(), Error> { .as_bytes(), ) .map_err(WriteTomlConfigError::ClientWrite)?; - cprintln!("config/client.toml has been created!"); + cprintln!("config/client.toml has been created!"); Ok(()) } diff --git a/src/command/config/validate.rs b/src/command/config/validate.rs index b809be7..c7d1edb 100644 --- a/src/command/config/validate.rs +++ b/src/command/config/validate.rs @@ -1,47 +1,73 @@ //! `config validate` subcommand use crate::config::{client, server}; +use color_print::cprintln; use std::{fs, io::Read}; -use validator::{Validate, ValidationErrors}; +use validator::Validate; #[derive(thiserror::Error, Debug)] -pub(crate) enum ConfigValidateError { - #[error(transparent)] - Read(#[from] ReadConfigError), - #[error(transparent)] - InvalidConfig(#[from] ValidationErrors), -} - -#[derive(thiserror::Error, Debug)] -pub(crate) enum ReadConfigError { +pub(crate) enum ValidationError { #[error(transparent)] ReadFile(#[from] std::io::Error), - #[error("config/server.toml is not written in the TOML format")] - InvalidServerTomlFormat(#[source] toml::de::Error), - #[error("config/client.toml is not written in the TOML format")] - InvalidClientTomlFormat(#[source] toml::de::Error), + #[error("invalid config file")] + InvalidConfig, } -pub(super) fn run() -> Result<(), ConfigValidateError> { - read_server_toml()?.validate()?; - read_client_toml()?.validate()?; - Ok(()) +#[derive(thiserror::Error, Debug)] +enum ReadError { + #[error(transparent)] + ReadFile(#[from] std::io::Error), + #[error("the config file is not written in the correct format")] + InvalidFormat(#[from] toml::de::Error), } -fn read_server_toml() -> Result { +pub(super) fn run() -> Result<(), ValidationError> { + let server_validation_result = match read_server_toml() { + Ok(config) => config.validate().map_err(|err| { + cprintln!("config/server.toml is invalid.\n{}", err); + ValidationError::InvalidConfig + }), + Err(ReadError::InvalidFormat(err)) => { + cprintln!("config/server.toml is invalid.\n{}", err); + Err(ValidationError::InvalidConfig) + } + Err(ReadError::ReadFile(err)) => Err(ValidationError::ReadFile(err)), + }; + + let client_validation_result = match read_client_toml() { + Ok(config) => config.validate().map_err(|err| { + cprintln!("config/client.toml is invalid.\n{}", err); + ValidationError::InvalidConfig + }), + Err(ReadError::InvalidFormat(err)) => { + cprintln!("config/client.toml is invalid.\n{}", err); + Err(ValidationError::InvalidConfig) + } + Err(ReadError::ReadFile(err)) => Err(ValidationError::ReadFile(err)), + }; + + if server_validation_result.is_ok() && client_validation_result.is_ok() { + cprintln!("config/server.toml and config/client.toml are valid!"); + cprintln!("Note: This is only a formal validation, so this does not guarantee that the settings are appropriate."); + } + + server_validation_result.and_then(|_| client_validation_result) +} + +fn read_server_toml() -> Result { let mut file = fs::File::open("config/server.toml")?; let mut buffer = String::new(); file.read_to_string(&mut buffer)?; - toml::from_str(&buffer).map_err(ReadConfigError::InvalidServerTomlFormat) + toml::from_str(&buffer).map_err(ReadError::InvalidFormat) } -fn read_client_toml() -> Result { +fn read_client_toml() -> Result { let mut file = fs::File::open("config/client.toml")?; let mut buffer = String::new(); file.read_to_string(&mut buffer)?; - toml::from_str(&buffer).map_err(ReadConfigError::InvalidClientTomlFormat) + toml::from_str(&buffer).map_err(ReadError::InvalidFormat) } diff --git a/src/config/client.rs b/src/config/client.rs index ea5ace5..863e6d2 100644 --- a/src/config/client.rs +++ b/src/config/client.rs @@ -10,9 +10,12 @@ use validator::{Validate, ValidationError}; #[derive(Deserialize, Serialize, Validate, Debug)] pub struct Config { + #[validate(nested)] pub theme: Option, + #[validate(nested)] pub image: Option, - pub pinned_links: Vec, + #[validate(nested)] + pub pinned_links: Option>, } #[derive(Deserialize, Serialize, Validate, Debug)] diff --git a/src/config/server.rs b/src/config/server.rs index 9593b93..c0cc8f5 100644 --- a/src/config/server.rs +++ b/src/config/server.rs @@ -6,15 +6,21 @@ // does not take care of it. use serde::{Deserialize, Serialize}; -use validator::Validate; +use validator::{Validate, ValidationErrors}; #[derive(Deserialize, Serialize, Validate, Debug)] pub struct Config { + #[validate(nested)] pub info: Option, + #[validate(nested)] pub timelines: Option, + #[validate(nested)] pub network: Network, + #[validate(nested)] pub database: Database, + #[validate(nested)] pub cache_server: CacheServer, + #[validate(nested)] pub id: Option, }