diff --git a/webserv/config/directive/DirectiveFactory.hpp b/webserv/config/directive/DirectiveFactory.hpp index 77f105b..9f6e319 100644 --- a/webserv/config/directive/DirectiveFactory.hpp +++ b/webserv/config/directive/DirectiveFactory.hpp @@ -13,12 +13,6 @@ class DirectiveFactory public: static std::unique_ptr createDirective(const std::string &line); - private: - using CreatorFunc = std::function(const std::string &, const std::string &arg)>; - - static const std::unordered_map &getFactories(); - static std::unique_ptr create(std::string_view type, const std::string &name, const std::string &arg); - struct DirectiveInfo { std::string_view name; @@ -26,21 +20,31 @@ class DirectiveFactory std::string_view context; }; + constexpr static std::array supportedDirectives = {{ - {.name = "listen", .type = "IntDirective", .context = "SL"}, - {.name = "host", .type = "StringDirective", .context = "SL"}, - {.name = "server_name", .type = "StringDirective", .context = "SL"}, - {.name = "root", .type = "StringDirective", .context = "SL"}, - {.name = "index", .type = "VectorDirective", .context = "SL"}, - {.name = "error_page", .type = "IntStringDirective", .context = "SL"}, - {.name = "client_max_body_size", .type = "SizeDirective", .context = "SL"}, - {.name = "autoindex", .type = "BoolDirective", .context = "L"}, - {.name = "allowed_methods", .type = "VectorDirective", .context = "L"}, - {.name = "cgi_enabled", .type = "BoolDirective", .context = "L"}, - {.name = "cgi_ext", .type = "VectorDirective", .context = "L"}, - {.name = "cgi_timeout", .type = "IntDirective", .context = "L"}, - {.name = "upload_enabled", .type = "BoolDirective", .context = "L"}, - {.name = "upload_store", .type = "StringDirective", .context = "L"}, - {.name = "redirect", .type = "VectorDirective", .context = "L"}, + {.name = "listen", .type = "IntDirective", .context = "S"}, + {.name = "host", .type = "StringDirective", .context = "S"}, + {.name = "server_name", .type = "StringDirective", .context = "S"}, + {.name = "root", .type = "StringDirective", .context = "Sl"}, + {.name = "index", .type = "VectorDirective", .context = "sl"}, + {.name = "error_page", .type = "IntStringDirective", .context = "gsl"}, + {.name = "client_max_body_size", .type = "SizeDirective", .context = "gsl"}, + {.name = "autoindex", .type = "BoolDirective", .context = "gsl"}, + {.name = "allowed_methods", .type = "VectorDirective", .context = "gsl"}, + {.name = "cgi_enabled", .type = "BoolDirective", .context = "gsl"}, + {.name = "cgi_ext", .type = "VectorDirective", .context = "gsl"}, + {.name = "cgi_timeout", .type = "IntDirective", .context = "gsl"}, + {.name = "upload_enabled", .type = "BoolDirective", .context = "gsl"}, + {.name = "upload_store", .type = "StringDirective", .context = "gsl"}, + {.name = "redirect", .type = "VectorDirective", .context = "l"}, }}; + private: + using CreatorFunc = std::function(const std::string &, const std::string &arg)>; + + static const std::unordered_map &getFactories(); + static std::unique_ptr create(std::string_view type, const std::string &name, const std::string &arg); + + + + }; \ No newline at end of file diff --git a/webserv/config/validation/ConfigValidator.cpp b/webserv/config/validation/ConfigValidator.cpp index f18027e..0165237 100644 --- a/webserv/config/validation/ConfigValidator.cpp +++ b/webserv/config/validation/ConfigValidator.cpp @@ -21,6 +21,7 @@ ConfigValidator::ConfigValidator(const GlobalConfig *config) : engine_(std::make engine_->addStructuralRule(std::make_unique(1)); engine_->addStructuralRule(std::make_unique(1)); engine_->addStructuralRule(std::make_unique()); + engine_->addStructuralRule(std::make_unique()); /*Global Directive Rules*/ diff --git a/webserv/config/validation/directive_rules/AValidationRule.cpp b/webserv/config/validation/directive_rules/AValidationRule.cpp index 1902610..3f4747c 100644 --- a/webserv/config/validation/directive_rules/AValidationRule.cpp +++ b/webserv/config/validation/directive_rules/AValidationRule.cpp @@ -1,7 +1,6 @@ -#include - #include // for AConfig #include // for ValidationResult +#include #include // for LOCATION, Log #include // for move @@ -19,7 +18,7 @@ ValidationResult AValidationRule::validate(const AConfig *config, const std::str return ValidationResult::error("Invalid config or directive name"); } - if (!config->hasDirective(directiveName)) + if (!config->has(directiveName)) { if (requiresValue_) { diff --git a/webserv/config/validation/directive_rules/DirectiveRules.hpp b/webserv/config/validation/directive_rules/DirectiveRules.hpp index 9357ac8..fb2666a 100644 --- a/webserv/config/validation/directive_rules/DirectiveRules.hpp +++ b/webserv/config/validation/directive_rules/DirectiveRules.hpp @@ -2,4 +2,3 @@ #include #include -#include \ No newline at end of file diff --git a/webserv/config/validation/structural_rules/RequiredDirectivesRule.cpp b/webserv/config/validation/structural_rules/RequiredDirectivesRule.cpp new file mode 100644 index 0000000..9efbea0 --- /dev/null +++ b/webserv/config/validation/structural_rules/RequiredDirectivesRule.cpp @@ -0,0 +1,72 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +RequiredDirectivesRule::RequiredDirectivesRule() + : AStructuralValidationRule("RequiredDirectivesRule", "Ensures required directives are present in each context") +{ +} + +ValidationResult validateUniversal(const AConfig *config, std::string configType) +{ + std::vector missingDirectives; + std::vector prohibitedDirectives; + + for (const auto &directive : DirectiveFactory::supportedDirectives) + { + if (directive.context.find(std::toupper(configType[0])) != std::string::npos && + !config->owns(std::string(directive.name))) + { + missingDirectives.emplace_back(directive.name); + } + if ((directive.context.find(std::toupper(configType[0])) == std::string::npos && + directive.context.find(std::tolower(configType[0])) == std::string::npos) && + config->owns(std::string(directive.name))) + { + prohibitedDirectives.emplace_back(directive.name); + } + } + + if (missingDirectives.empty() && prohibitedDirectives.empty()) + { + return ValidationResult::success(); + } + + std::string result; + + if (!missingDirectives.empty()) + { + result += "Missing " + configType + " directive: "; + result += utils::implode(missingDirectives, ", "); + } + if (!prohibitedDirectives.empty()) + { + result += "Prohibited " + configType + " directive: "; + result += utils::implode(prohibitedDirectives, ", "); + } + + return ValidationResult::error(result); +} + +ValidationResult RequiredDirectivesRule::validateGlobal(const GlobalConfig *config) const +{ + return validateUniversal(config, "global"); +} + +ValidationResult RequiredDirectivesRule::validateServer(const ServerConfig *config) const +{ + return validateUniversal(config, "server"); +} + +ValidationResult RequiredDirectivesRule::validateLocation(const LocationConfig *config) const +{ + return validateUniversal(config, "location"); +} \ No newline at end of file diff --git a/webserv/config/validation/structural_rules/RequiredDirectivesRule.hpp b/webserv/config/validation/structural_rules/RequiredDirectivesRule.hpp new file mode 100644 index 0000000..d5bb8c3 --- /dev/null +++ b/webserv/config/validation/structural_rules/RequiredDirectivesRule.hpp @@ -0,0 +1,26 @@ +#pragma once + +#include + +#include + +class GlobalConfig; +class ServerConfig; +class LocationConfig; + +class RequiredDirectivesRule : public AStructuralValidationRule +{ + public: + explicit RequiredDirectivesRule(); + + ~RequiredDirectivesRule() override = default; + + RequiredDirectivesRule(const RequiredDirectivesRule &other) = delete; + RequiredDirectivesRule &operator=(const RequiredDirectivesRule &other) = delete; + RequiredDirectivesRule(RequiredDirectivesRule &&other) noexcept = delete; + RequiredDirectivesRule &operator=(RequiredDirectivesRule &&other) noexcept = delete; + + [[nodiscard]] ValidationResult validateGlobal(const GlobalConfig *config) const override; + [[nodiscard]] ValidationResult validateServer(const ServerConfig *config) const override; + [[nodiscard]] ValidationResult validateLocation(const LocationConfig *config) const override; +}; \ No newline at end of file diff --git a/webserv/config/validation/structural_rules/StructuralRules.hpp b/webserv/config/validation/structural_rules/StructuralRules.hpp index 9ffa791..a9b93c1 100644 --- a/webserv/config/validation/structural_rules/StructuralRules.hpp +++ b/webserv/config/validation/structural_rules/StructuralRules.hpp @@ -7,3 +7,4 @@ #include #include #include +#include diff --git a/webserv/main.cpp b/webserv/main.cpp index b7aa868..aead3f8 100644 --- a/webserv/main.cpp +++ b/webserv/main.cpp @@ -8,6 +8,9 @@ #include // for allocator, basic_string, char_traits, operator+, string #include // for vector + + + int main(int argc, char **argv) { if (argc < 2) @@ -16,8 +19,8 @@ int main(int argc, char **argv) return 1; } - Log::setFileChannel("webserv.log", std::ios_base::trunc, Log::Level::Info); - Log::setStdoutChannel(Log::Level::Info); + Log::setFileChannel("webserv.log", std::ios_base::trunc); + Log::setStdoutChannel(); Log::info("\n======================\nStarting webserv...\n======================\n"); ConfigManager &configManager = ConfigManager::getInstance();