diff --git a/config/default.conf b/config/default.conf index ebdc898..d1356eb 100644 --- a/config/default.conf +++ b/config/default.conf @@ -28,7 +28,7 @@ server { autoindex off; root ./static_site/; index index2.html index.html; - allowed_methods GET POST DELETE; + allowed_methods GET POST DELETE UPDATE; } location /uploads { diff --git a/webserv/config/AConfig.cpp b/webserv/config/AConfig.cpp index daf7622..896c7ca 100644 --- a/webserv/config/AConfig.cpp +++ b/webserv/config/AConfig.cpp @@ -34,6 +34,17 @@ const ADirective *AConfig::getDirective(const std::string &name) const return nullptr; } +std::vector AConfig::getDirectives() const +{ + std::vector result; + result.reserve(directives_.size()); + for (const auto &directive : directives_) + { + result.push_back(directive.get()); + } + return result; +} + bool AConfig::hasDirective(const std::string &name) const { for (const auto &directive : directives_) diff --git a/webserv/config/AConfig.hpp b/webserv/config/AConfig.hpp index 4895a91..a194a01 100644 --- a/webserv/config/AConfig.hpp +++ b/webserv/config/AConfig.hpp @@ -19,11 +19,14 @@ class AConfig AConfig &operator=(AConfig &&other) noexcept = delete; virtual ~AConfig() = default; - + [[nodiscard]] virtual std::string getName() const = 0; + [[nodiscard]] virtual std::string getType() const = 0; void addDirective(const std::string &line); [[nodiscard]] std::string getErrorPage(int statusCode) const; [[nodiscard]] bool hasDirective(const std::string &name) const; + [[nodiscard]] const ADirective *getDirective(const std::string &name) const; + [[nodiscard]] std::vector getDirectives() const; template std::optional get(const std::string &name) const @@ -37,7 +40,6 @@ class AConfig } protected: - [[nodiscard]] const ADirective *getDirective(const std::string &name) const; virtual void parseBlock(const std::string &block) = 0; void parseDirectives(const std::string &declarations); std::vector> diff --git a/webserv/config/GlobalConfig.cpp b/webserv/config/GlobalConfig.cpp index 2fa4ae7..3bb8bce 100644 --- a/webserv/config/GlobalConfig.cpp +++ b/webserv/config/GlobalConfig.cpp @@ -12,6 +12,16 @@ GlobalConfig::GlobalConfig(const std::string &block) parseBlock(block); } +std::string GlobalConfig::getName() const +{ + return "global"; +} + +std::string GlobalConfig::getType() const +{ + return "global"; +} + void GlobalConfig::parseBlock(const std::string &block) { std::string directives; diff --git a/webserv/config/GlobalConfig.hpp b/webserv/config/GlobalConfig.hpp index 6ce3411..0a980cf 100644 --- a/webserv/config/GlobalConfig.hpp +++ b/webserv/config/GlobalConfig.hpp @@ -19,6 +19,10 @@ class GlobalConfig : public AConfig GlobalConfig &operator=(GlobalConfig &&other) noexcept = delete; ~GlobalConfig() override = default; + + [[nodiscard]] std::string getName() const override; + [[nodiscard]] std::string getType() const override; + [[nodiscard]] std::vector getServerConfigs() const; private: diff --git a/webserv/config/LocationConfig.cpp b/webserv/config/LocationConfig.cpp index 8c8d945..1dfa4a6 100644 --- a/webserv/config/LocationConfig.cpp +++ b/webserv/config/LocationConfig.cpp @@ -8,6 +8,17 @@ LocationConfig::LocationConfig(const std::string &block, const std::string &path parseBlock(block); } +std::string LocationConfig::getName() const +{ + auto parentName = parent_ != nullptr ? parent_->getName() : "root"; + return parentName + ", location: " + _path; +} + +std::string LocationConfig::getType() const +{ + return "location"; +} + void LocationConfig::parseBlock(const std::string &block) { Log::trace(LOCATION); diff --git a/webserv/config/LocationConfig.hpp b/webserv/config/LocationConfig.hpp index 7fbcad6..3728e91 100644 --- a/webserv/config/LocationConfig.hpp +++ b/webserv/config/LocationConfig.hpp @@ -17,6 +17,8 @@ class LocationConfig : public AConfig ~LocationConfig() override = default; + [[nodiscard]] std::string getName() const override; + [[nodiscard]] std::string getType() const override; [[nodiscard]] const std::string &getPath() const { return _path; } private: diff --git a/webserv/config/ServerConfig.cpp b/webserv/config/ServerConfig.cpp index 075b6be..75bfb3d 100644 --- a/webserv/config/ServerConfig.cpp +++ b/webserv/config/ServerConfig.cpp @@ -14,6 +14,17 @@ ServerConfig::ServerConfig(const std::string &block, const AConfig *parent) : AC parseBlock(block); } +std::string ServerConfig::getName() const +{ + return "server: " + get("server_name").value_or("unnamed") + " (port " + + std::to_string(get("listen").value_or(-1)) + ")"; +} + +std::string ServerConfig::getType() const +{ + return "server"; +} + void ServerConfig::parseBlock(const std::string &block) { Log::trace(LOCATION); @@ -67,4 +78,5 @@ std::vector ServerConfig::getLocationPaths() const paths.push_back(pair.first); } return paths; -} \ No newline at end of file +} + diff --git a/webserv/config/ServerConfig.hpp b/webserv/config/ServerConfig.hpp index 10d6db0..5e6a7de 100644 --- a/webserv/config/ServerConfig.hpp +++ b/webserv/config/ServerConfig.hpp @@ -21,9 +21,13 @@ class ServerConfig : public AConfig ~ServerConfig() override = default; + [[nodiscard]] std::string getName() const override; + [[nodiscard]] std::string getType() const override; + [[nodiscard]] const LocationConfig *getLocation(const std::string &path) const; [[nodiscard]] std::vector getLocationPaths() const; + private: std::map> locations_; AConfig *parent_ = nullptr; diff --git a/webserv/config/config_validator/AValidationRule.cpp b/webserv/config/config_validator/AValidationRule.cpp new file mode 100644 index 0000000..262299c --- /dev/null +++ b/webserv/config/config_validator/AValidationRule.cpp @@ -0,0 +1,44 @@ +#include +#include +#include +#include +#include + +AValidationRule::AValidationRule(std::string ruleName, std::string description, bool requiresValue) + : ruleName_(std::move(ruleName)), description_(std::move(description)), requiresValue_(requiresValue) +{ +} + +ValidationResult AValidationRule::validate(const AConfig *config, const std::string &directiveName) const +{ + Log::trace(LOCATION); + if (config == nullptr || directiveName.empty()) + { + return ValidationResult::error("Invalid config or directive name"); + } + + if (!config->hasDirective(directiveName)) + { + if (requiresValue_) + { + return ValidationResult::error("Directive '" + directiveName + "' is missing"); + } + return ValidationResult::success(); + } + return validateValue(config, directiveName); +} + +std::string AValidationRule::getRuleName() const +{ + return ruleName_; +} + +std::string AValidationRule::getDescription() const +{ + return description_; +} + +bool AValidationRule::isRequired() const +{ + return requiresValue_; +} \ No newline at end of file diff --git a/webserv/config/config_validator/AValidationRule.hpp b/webserv/config/config_validator/AValidationRule.hpp new file mode 100644 index 0000000..75aeafe --- /dev/null +++ b/webserv/config/config_validator/AValidationRule.hpp @@ -0,0 +1,32 @@ +#pragma once +#include + + +class ValidationResult; +class ADirective; +class AConfig; + +class AValidationRule +{ + public: + virtual ~AValidationRule() = default; + + AValidationRule(const AValidationRule &other) = delete; + AValidationRule &operator=(const AValidationRule &other) = delete; + AValidationRule(AValidationRule &&other) noexcept = delete; + AValidationRule &operator=(AValidationRule &&other) noexcept = delete; + + [[nodiscard]] ValidationResult validate(const AConfig *config, const std::string &directiveName) const; + [[nodiscard]] bool isRequired() const; + [[nodiscard]] virtual ValidationResult validateValue(const AConfig *config, const std::string &directiveName) const = 0; + [[nodiscard]] std::string getRuleName() const; + [[nodiscard]] std::string getDescription() const; + + protected: + AValidationRule(std::string ruleName, std::string description, bool requiresValue = true); + + private: + std::string ruleName_; + std::string description_; + bool requiresValue_; +}; \ No newline at end of file diff --git a/webserv/config/config_validator/AllowedValuesRule.cpp b/webserv/config/config_validator/AllowedValuesRule.cpp new file mode 100644 index 0000000..75ab0e4 --- /dev/null +++ b/webserv/config/config_validator/AllowedValuesRule.cpp @@ -0,0 +1,60 @@ +#include +#include +#include +#include + +#include // for find + +#include // for string, basic_string, operator+, char_traits +#include // for vector + +AllowedValuesRule::AllowedValuesRule(const std::vector &allowedValues, bool requiresValue) + : AValidationRule("AllowedValuesRule", "Ensures that the directive's value is within the allowed set", + requiresValue), + allowedValues_(allowedValues) +{ +} + +ValidationResult AllowedValuesRule::validateValue(const AConfig *config, const std::string &directiveName) const +{ + const ADirective *directive = config->getDirective(directiveName); + if (directive == nullptr) + { + return ValidationResult::error("Directive '" + directiveName + "' is missing"); + } + + auto checkValueAllowed = [&](const std::string &val) -> bool { + return std::ranges::find(allowedValues_, val) != allowedValues_.end(); + }; + + auto makeErrorMsg = [&](const std::string &val) -> std::string { + return "Value '" + val + "' of directive '" + directiveName + "' is not in the allowed set"; + }; + + if (directive->getValue().holds()) + { + const std::string &value = directive->getValue().get(); + + if (!checkValueAllowed(value)) + { + return ValidationResult::error(makeErrorMsg(value)); + } + } + else if (directive->getValue().holds>()) + { + const std::vector &values = directive->getValue().get>(); + for (const std::string &val : values) + { + if (!checkValueAllowed(val)) + { + return ValidationResult::error(makeErrorMsg(val)); + } + } + } + else + { + return ValidationResult::error("Directive '" + directiveName + "' has an unsupported value type"); + } + + return ValidationResult::success(); +} \ No newline at end of file diff --git a/webserv/config/config_validator/AllowedValuesRule.hpp b/webserv/config/config_validator/AllowedValuesRule.hpp new file mode 100644 index 0000000..e43252f --- /dev/null +++ b/webserv/config/config_validator/AllowedValuesRule.hpp @@ -0,0 +1,18 @@ +#pragma once + +#include "webserv/config/config_validator/AValidationRule.hpp" +#include "webserv/config/config_validator/ValidationResult.hpp" +#include +#include + +class AConfig; + +class AllowedValuesRule : public AValidationRule +{ + public: + explicit AllowedValuesRule(const std::vector &allowedValues, bool requiresValue = true); + + private: + [[nodiscard]] ValidationResult validateValue(const AConfig *config, const std::string &directiveName) const override; + std::vector allowedValues_; +}; \ No newline at end of file diff --git a/webserv/config/config_validator/ConfigValidator.cpp b/webserv/config/config_validator/ConfigValidator.cpp new file mode 100644 index 0000000..b2854ee --- /dev/null +++ b/webserv/config/config_validator/ConfigValidator.cpp @@ -0,0 +1,38 @@ +#include "webserv/config/config_validator/ConfigValidator.hpp" + +#include "webserv/config/GlobalConfig.hpp" +#include "webserv/config/config_validator/AllowedValuesRule.hpp" +#include "webserv/config/config_validator/PortValidationRule.hpp" +#include "webserv/log/Log.hpp" +#include + +ConfigValidator::ConfigValidator(const GlobalConfig *config) + : engine_(std::make_unique(config)) +{ + Log::trace(LOCATION); + + engine_->addServerRule("listen", std::make_unique()); + engine_->addLocationRule("allowed_methods", std::make_unique(std::vector{"GET", "POST", "DELETE"})); + engine_->validate(); +} + +std::vector ConfigValidator::getValidationResults() const +{ + return engine_->getValidationResults(); +} + +std::vector ConfigValidator::getErrors() const +{ + return engine_->getErrors(); +} + +std::vector ConfigValidator::getWarnings() const +{ + return engine_->getWarnings(); +} + +bool ConfigValidator::hasErrors() const +{ + return engine_->hasErrors(); +} + diff --git a/webserv/config/config_validator/ConfigValidator.hpp b/webserv/config/config_validator/ConfigValidator.hpp new file mode 100644 index 0000000..60c9576 --- /dev/null +++ b/webserv/config/config_validator/ConfigValidator.hpp @@ -0,0 +1,26 @@ +#pragma once + + +#include "webserv/config/config_validator/ValidationEngine.hpp" +#include +class GlobalConfig; +class ConfigValidator +{ + public: + ConfigValidator(const GlobalConfig *config); + + ConfigValidator(const ConfigValidator &other) = delete; + ConfigValidator &operator=(const ConfigValidator &other) = delete; + ConfigValidator(ConfigValidator &&other) noexcept = delete; + ConfigValidator &operator=(ConfigValidator &&other) noexcept = delete; + ~ConfigValidator() = default; + + [[nodiscard]] std::vector getValidationResults() const; + [[nodiscard]] std::vector getErrors() const; + [[nodiscard]] std::vector getWarnings() const; + [[nodiscard]] bool hasErrors() const; + + private: + std::unique_ptr engine_; + +}; \ No newline at end of file diff --git a/webserv/config/config_validator/IValidationRule.hpp b/webserv/config/config_validator/IValidationRule.hpp deleted file mode 100644 index 314d3a5..0000000 --- a/webserv/config/config_validator/IValidationRule.hpp +++ /dev/null @@ -1,21 +0,0 @@ -#pragma once -#include - - -class ValidationResult; - -class IValidationRule -{ - public: - virtual ~IValidationRule() = default; - - IValidationRule(const IValidationRule &other) = delete; - IValidationRule &operator=(const IValidationRule &other) = delete; - IValidationRule(IValidationRule &&other) noexcept = delete; - IValidationRule &operator=(IValidationRule &&other) noexcept = delete; - - [[nodiscard]] virtual ValidationResult validate(const std::string &Adirective) const = 0; - [[nodiscard]] virtual std::string getRuleName() const = 0; - [[nodiscard]] virtual std::string getDescription() const = 0; - -}; \ No newline at end of file diff --git a/webserv/config/config_validator/PortValidationRule.cpp b/webserv/config/config_validator/PortValidationRule.cpp new file mode 100644 index 0000000..a53cbe0 --- /dev/null +++ b/webserv/config/config_validator/PortValidationRule.cpp @@ -0,0 +1,32 @@ +#include "webserv/config/config_validator/PortValidationRule.hpp" + +#include "webserv/config/AConfig.hpp" +#include "webserv/config/config_validator/ValidationResult.hpp" +#include "webserv/config/directive/ADirective.hpp" +#include "webserv/config/directive/DirectiveValue.hpp" +#include "webserv/log/Log.hpp" + +#include // for string, basic_string, operator+, char_traits + +PortValidationRule::PortValidationRule(bool requiresValue) + : AValidationRule("PortValidationRule", "Validates that the port number is within the valid range (1-65535)", requiresValue) +{ +} + +ValidationResult PortValidationRule::validateValue(const AConfig *config, const std::string &directiveName) const +{ + Log::trace(LOCATION); + const ADirective *directive = config->getDirective(directiveName); + if (!directive->getValue().holds()) + { + return ValidationResult::error("Directive '" + directive->getName() + "' does not hold an integer value"); + } + + int port = directive->getValue().get(); + if (port < 1 || port > 65535) + { + return ValidationResult::error("Port number " + std::to_string(port) + " is out of valid range (1-65535)"); + } + + return ValidationResult::success(); +} diff --git a/webserv/config/config_validator/PortValidationRule.hpp b/webserv/config/config_validator/PortValidationRule.hpp index 23bac7c..0960999 100644 --- a/webserv/config/config_validator/PortValidationRule.hpp +++ b/webserv/config/config_validator/PortValidationRule.hpp @@ -1,18 +1,14 @@ #pragma once -#include "webserv/config/config_validator/IValidationRule.hpp" -class PortValidationRule : public IValidationRule +#include "webserv/config/config_validator/AValidationRule.hpp" +#include + +class AConfig; +class PortValidationRule : public AValidationRule { public: - PortValidationRule() = default; - ~PortValidationRule() override = default; + PortValidationRule(bool requiresValue = true); - PortValidationRule(const PortValidationRule &other) = delete; - PortValidationRule &operator=(const PortValidationRule &other) = delete; - PortValidationRule(PortValidationRule &&other) noexcept = delete; - PortValidationRule &operator=(PortValidationRule &&other) noexcept = delete; - - [[nodiscard]] ValidationResult validate(const std::string &value) const override; - [[nodiscard]] std::string getRuleName() const override { return "PortValidationRule"; } - [[nodiscard]] std::string getDescription() const override { return "Validates that a port number is between 1 and 65535"; } + private: + [[nodiscard]] ValidationResult validateValue(const AConfig *config, const std::string &directiveName) const override; }; \ No newline at end of file diff --git a/webserv/config/config_validator/RequiredDirectiveRule.cpp b/webserv/config/config_validator/RequiredDirectiveRule.cpp new file mode 100644 index 0000000..caedc17 --- /dev/null +++ b/webserv/config/config_validator/RequiredDirectiveRule.cpp @@ -0,0 +1,14 @@ +#include "webserv/config/config_validator/ValidationResult.hpp" +#include "webserv/config/config_validator/RequiredDirectiveRule.hpp" +#include +#include + +RequiredDirectiveRule::RequiredDirectiveRule() + : AValidationRule("RequiredDirectiveRule", "Ensures that a required directive is present in the configuration", true) +{ +} + +ValidationResult RequiredDirectiveRule::validateValue(const AConfig *config, const std::string &directiveName) const +{ + return ValidationResult::success(); +} \ No newline at end of file diff --git a/webserv/config/config_validator/RequiredDirectiveRule.hpp b/webserv/config/config_validator/RequiredDirectiveRule.hpp new file mode 100644 index 0000000..329c14b --- /dev/null +++ b/webserv/config/config_validator/RequiredDirectiveRule.hpp @@ -0,0 +1,17 @@ +#pragma once + +#include "webserv/config/config_validator/AValidationRule.hpp" + +#include + +class AConfig; + +class RequiredDirectiveRule : public AValidationRule +{ + public: + RequiredDirectiveRule(); + + private: + [[nodiscard]] ValidationResult validateValue(const AConfig *config, + const std::string &directiveName) const override; +}; \ No newline at end of file diff --git a/webserv/config/config_validator/ValidationEngine.cpp b/webserv/config/config_validator/ValidationEngine.cpp new file mode 100644 index 0000000..e66d4a6 --- /dev/null +++ b/webserv/config/config_validator/ValidationEngine.cpp @@ -0,0 +1,157 @@ +#include "webserv/config/config_validator/ValidationEngine.hpp" + +#include "webserv/config/AConfig.hpp" +#include "webserv/config/LocationConfig.hpp" +#include "webserv/config/config_validator/AValidationRule.hpp" +#include "webserv/config/config_validator/ValidationResult.hpp" +#include "webserv/config/directive/ADirective.hpp" +#include "webserv/log/Log.hpp" + +void ValidationEngine::addGlobalRule(const std::string &directiveName, std::unique_ptr rule) +{ + Log::trace(LOCATION); + addRule(globalRules_, directiveName, std::move(rule)); +} + +void ValidationEngine::addServerRule(const std::string &directiveName, std::unique_ptr rule) +{ + Log::trace(LOCATION); + addRule(serverRules_, directiveName, std::move(rule)); +} + +void ValidationEngine::addLocationRule(const std::string &directiveName, std::unique_ptr rule) +{ + Log::trace(LOCATION); + addRule(locationRules_, directiveName, std::move(rule)); +} + +void ValidationEngine::addRule(RuleMap &ruleMap, const std::string &directiveName, + std::unique_ptr rule) +{ + Log::trace(LOCATION); + ruleMap[directiveName].emplace_back(std::move(rule)); +} + +std::vector ValidationEngine::getValidationResults() const +{ + return results_; +} + +std::vector ValidationEngine::getErrors() const +{ + std::vector errors; + for (const auto &result : results_) + { + if (!result.isValidResult()) + { + errors.push_back(result); + } + } + return errors; +} + +std::vector ValidationEngine::getWarnings() const +{ + std::vector warnings; + for (const auto &result : results_) + { + if (result.getType() == ValidationResult::Type::WARNING) + { + warnings.push_back(result); + } + } + return warnings; +} + +bool ValidationEngine::hasErrors() const +{ + for (const auto &result : results_) + { + if (!result.isValidResult()) + { + return true; + } + } + return false; +} + +void ValidationEngine::validateConfig(RuleMap const &rulesMap, const AConfig *config) +{ + Log::trace(LOCATION); + for (const auto &[directiveName, rules] : rulesMap) + { + if (!config->hasDirective(directiveName)) + { + // Check if any rule requires the directive + for (const auto &rule : rules) + { + if (rule->isRequired()) + { + ValidationResult result = rule->validate(config, directiveName); + if (!result.isValidResult()) + { + results_.push_back(result); // Only failures + } + } + } + continue; // Directive not present, skip to next + } + // Validate each rule for this directive + for (const auto &rule : rules) + { + ValidationResult result = rule->validate(config, directiveName); // ✅ + if (!result.isValidResult()) + { + results_.push_back(result); // Only failures + } + } + } +} + +void ValidationEngine::validateLocationConfig(const std::string &path, const LocationConfig *config) +{ + Log::trace(LOCATION); + validateConfig(locationRules_, config); +} + +void ValidationEngine::validateServerConfig(const ServerConfig *config) +{ + Log::trace(LOCATION); + validateConfig(serverRules_, config); + for (const auto &path : config->getLocationPaths()) + { + const LocationConfig *locationConfig = config->getLocation(path); + if (locationConfig != nullptr) + { + validateLocationConfig(path, locationConfig); + } + } +} + +void ValidationEngine::validateGlobalConfig(const GlobalConfig *config) +{ + Log::trace(LOCATION); + validateConfig(globalRules_, config); + for (const auto *serverConfig : config->getServerConfigs()) + { + validateServerConfig(serverConfig); + } +} + +ValidationEngine::ValidationEngine(const GlobalConfig *globalConfig) : globalConfig_(globalConfig) +{ + Log::trace(LOCATION); +} + +void ValidationEngine::validate() +{ + Log::trace(LOCATION); + if (globalConfig_ != nullptr) + { + validateGlobalConfig(globalConfig_); + } + else + { + Log::warning("No GlobalConfig set for ValidationEngine; skipping validation."); + } +} \ No newline at end of file diff --git a/webserv/config/config_validator/ValidationEngine.hpp b/webserv/config/config_validator/ValidationEngine.hpp new file mode 100644 index 0000000..50cc901 --- /dev/null +++ b/webserv/config/config_validator/ValidationEngine.hpp @@ -0,0 +1,50 @@ +#pragma once + +#include "webserv/config/GlobalConfig.hpp" +#include "webserv/config/config_validator/AValidationRule.hpp" +#include "webserv/config/config_validator/ValidationResult.hpp" +#include "webserv/config/LocationConfig.hpp" +#include "webserv/config/ServerConfig.hpp" +#include "webserv/config/AConfig.hpp" +#include +#include +#include +#include + +class ValidationEngine +{ + using RuleMap = std::map>>; + + public: + ValidationEngine(const GlobalConfig *globalConfig = nullptr); + ValidationEngine(const ValidationEngine &other) = delete; + ValidationEngine &operator=(const ValidationEngine &other) = delete; + ValidationEngine(ValidationEngine &&other) noexcept = delete; + ValidationEngine &operator=(ValidationEngine &&other) noexcept = delete; + ~ValidationEngine() = default; + + void addGlobalRule(const std::string &directiveName, std::unique_ptr rule); + void addServerRule(const std::string &directiveName, std::unique_ptr rule); + void addLocationRule(const std::string &directiveName, std::unique_ptr rule); + + void validate(); + + [[nodiscard]] std::vector getValidationResults() const; + [[nodiscard]] std::vector getErrors() const; + [[nodiscard]] std::vector getWarnings() const; + [[nodiscard]] bool hasErrors() const; + + private: + static void addRule(RuleMap &ruleMap, const std::string &directiveName, std::unique_ptr rule); + + void validateConfig(RuleMap const &rules, const AConfig *config); + void validateGlobalConfig(const GlobalConfig *config); + void validateServerConfig(const ServerConfig *config); + void validateLocationConfig(const std::string &path, const LocationConfig *config); + RuleMap globalRules_; + RuleMap serverRules_; + RuleMap locationRules_; + const GlobalConfig *globalConfig_; + + std::vector results_; +}; \ No newline at end of file diff --git a/webserv/config/config_validator/ValidationResult.cpp b/webserv/config/config_validator/ValidationResult.cpp new file mode 100644 index 0000000..a45be6d --- /dev/null +++ b/webserv/config/config_validator/ValidationResult.cpp @@ -0,0 +1,36 @@ +#include +#include + +ValidationResult::ValidationResult(Type type, std::string message) : type_(type), message_(std::move(message)) {} + +ValidationResult ValidationResult::success() +{ + return {ValidationResult::Type::SUCCESS}; +} + +ValidationResult ValidationResult::error(const std::string &message) +{ + Log::error(message); + return {ValidationResult::Type::ERROR, message}; +} + +ValidationResult ValidationResult::warning(const std::string &message) +{ + Log::warning(message); + return {ValidationResult::Type::WARNING, message}; +} + +bool ValidationResult::isValidResult() const +{ + return type_ == Type::SUCCESS; +} + +ValidationResult::Type ValidationResult::getType() const +{ + return type_; +} + +std::string ValidationResult::getMessage() const +{ + return message_; +} \ No newline at end of file diff --git a/webserv/config/config_validator/ValidationResult.hpp b/webserv/config/config_validator/ValidationResult.hpp index 08f436f..8874cf5 100644 --- a/webserv/config/config_validator/ValidationResult.hpp +++ b/webserv/config/config_validator/ValidationResult.hpp @@ -1,22 +1,35 @@ #pragma once #include +#include class ValidationResult { public: + enum class Type : uint8_t + { + SUCCESS, + ERROR, + WARNING + }; + ~ValidationResult() = default; - ValidationResult(const ValidationResult &other) = delete; - ValidationResult &operator=(const ValidationResult &other) = delete; + ValidationResult(const ValidationResult &other) = default; + ValidationResult &operator=(const ValidationResult &other) = default; ValidationResult(ValidationResult &&other) noexcept = default; ValidationResult &operator=(ValidationResult &&other) noexcept = default; static ValidationResult success(); static ValidationResult error(const std::string &message); + static ValidationResult warning(const std::string &message); + + [[nodiscard]] bool isValidResult() const; + [[nodiscard]] ValidationResult::Type getType() const ; + [[nodiscard]] std::string getMessage() const; private: - ValidationResult(bool isValid, std::string errorMessage = ""); - bool isValid; - std::string errorMessage; + ValidationResult(Type type, std::string message = ""); + Type type_; + std::string message_; }; \ No newline at end of file diff --git a/webserv/main.cpp b/webserv/main.cpp index aaf45f0..6b13eba 100644 --- a/webserv/main.cpp +++ b/webserv/main.cpp @@ -1,6 +1,7 @@ #include // for ConfigManager #include // for Log, LOCATION #include // for Server +#include // for ConfigValidator #include // for basic_ostream, operator<<, cerr, ios_base #include // for basic_string, char_traits, allocator, operator+, operator<=> @@ -17,8 +18,19 @@ int main(int argc, char **argv) Log::setStdoutChannel(Log::Level::Info); Log::info("\n======================\nStarting webserv...\n======================\n"); - ConfigManager::getInstance().init(argv[1]); // NOLINT ConfigManager &configManager = ConfigManager::getInstance(); + configManager.init(argv[1]); // NOLINT + + ConfigValidator validator{configManager.getGlobalConfig()}; + if (validator.hasErrors()) + { + Log::error("Configuration validation failed with the following errors:"); + for (const auto &error : validator.getErrors()) + { + Log::error(" - " + error.getMessage()); + } + return 1; + } Log::debug("ConfigManager initialized successfully."); Server server(configManager);