diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 74c663431..b35434d42 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -15,10 +15,11 @@ add_subdirectory(query) add_subdirectory(glue) add_subdirectory(slk) add_subdirectory(rpc) +add_subdirectory(license) add_subdirectory(auth) -if (MG_ENTERPRISE) - add_subdirectory(audit) +if(MG_ENTERPRISE) + add_subdirectory(audit) endif() string(TOLOWER ${CMAKE_BUILD_TYPE} lower_build_type) @@ -36,68 +37,76 @@ set(mg_single_node_v2_sources ) set(mg_single_node_v2_libs stdc++fs Threads::Threads - telemetry_lib mg-query mg-communication mg-memory mg-utils mg-auth mg-license mg-settings mg-glue) -if (MG_ENTERPRISE) - # These are enterprise subsystems - set(mg_single_node_v2_libs ${mg_single_node_v2_libs} mg-audit) + mg-telemetry mg-query mg-communication mg-memory mg-utils mg-auth mg-license mg-settings mg-glue) + +if(MG_ENTERPRISE) + # These are enterprise subsystems + set(mg_single_node_v2_libs ${mg_single_node_v2_libs} mg-audit) endif() # memgraph main executable add_executable(memgraph ${mg_single_node_v2_sources}) target_include_directories(memgraph PUBLIC ${CMAKE_SOURCE_DIR}/include) target_link_libraries(memgraph ${mg_single_node_v2_libs}) + # NOTE: `include/mg_procedure.syms` describes a pattern match for symbols which # should be dynamically exported, so that `dlopen` can correctly link the # symbols in custom procedure module libraries. target_link_libraries(memgraph "-Wl,--dynamic-list=${CMAKE_SOURCE_DIR}/include/mg_procedure.syms") set_target_properties(memgraph PROPERTIES - # Set the executable output name to include version information. - OUTPUT_NAME "memgraph-${MEMGRAPH_VERSION}_${CMAKE_BUILD_TYPE}" - # Output the executable in main binary dir. - RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) + + # Set the executable output name to include version information. + OUTPUT_NAME "memgraph-${MEMGRAPH_VERSION}_${CMAKE_BUILD_TYPE}" + + # Output the executable in main binary dir. + RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) + # Create symlink to the built executable. add_custom_command(TARGET memgraph POST_BUILD - COMMAND ${CMAKE_COMMAND} -E create_symlink $ ${CMAKE_BINARY_DIR}/memgraph - BYPRODUCTS ${CMAKE_BINARY_DIR}/memgraph - COMMENT "Creating symlink to memgraph executable") + COMMAND ${CMAKE_COMMAND} -E create_symlink $ ${CMAKE_BINARY_DIR}/memgraph + BYPRODUCTS ${CMAKE_BINARY_DIR}/memgraph + COMMENT "Creating symlink to memgraph executable") + # Emulate the installed python_support, by creating a symlink add_custom_command(TARGET memgraph POST_BUILD - COMMAND ${CMAKE_COMMAND} -E create_symlink ${CMAKE_SOURCE_DIR}/include ${CMAKE_BINARY_DIR}/python_support - BYPRODUCTS ${CMAKE_BINARY_DIR}/python_support - COMMENT "Creating symlink for python_support") + COMMAND ${CMAKE_COMMAND} -E create_symlink ${CMAKE_SOURCE_DIR}/include ${CMAKE_BINARY_DIR}/python_support + BYPRODUCTS ${CMAKE_BINARY_DIR}/python_support + COMMENT "Creating symlink for python_support") # Strip the executable in release build. -if (lower_build_type STREQUAL "release") - add_custom_command(TARGET memgraph POST_BUILD - COMMAND strip -s $ - COMMENT "Stripping symbols and sections from memgraph") +if(lower_build_type STREQUAL "release") + add_custom_command(TARGET memgraph POST_BUILD + COMMAND strip -s $ + COMMENT "Stripping symbols and sections from memgraph") endif() # Generate the configuration file. add_custom_command(TARGET memgraph POST_BUILD - COMMAND ${CMAKE_SOURCE_DIR}/config/generate.py - ${CMAKE_BINARY_DIR}/memgraph - ${CMAKE_BINARY_DIR}/config/memgraph.conf - DEPENDS ${CMAKE_SOURCE_DIR}/config/generate.py - ${CMAKE_SOURCE_DIR}/config/flags.yaml - BYPRODUCTS ${CMAKE_BINARY_DIR}/config/memgraph.conf - COMMENT "Generating memgraph configuration file") + COMMAND ${CMAKE_SOURCE_DIR}/config/generate.py + ${CMAKE_BINARY_DIR}/memgraph + ${CMAKE_BINARY_DIR}/config/memgraph.conf + DEPENDS ${CMAKE_SOURCE_DIR}/config/generate.py + ${CMAKE_SOURCE_DIR}/config/flags.yaml + BYPRODUCTS ${CMAKE_BINARY_DIR}/config/memgraph.conf + COMMENT "Generating memgraph configuration file") # Everything here is under "memgraph" install component. set(CMAKE_INSTALL_DEFAULT_COMPONENT_NAME "memgraph") # TODO: Default directory permissions to 755 # NOTE: This is added in CMake 3.11, so enable it then -#set(CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS -# OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ WORLD_READ) +# set(CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS +# OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ WORLD_READ) # Install and rename executable to just 'memgraph' Since we have to rename, # we cannot use the recommended `install(TARGETS ...)`. install(PROGRAMS $ DESTINATION lib/memgraph RENAME memgraph) + # Install Python source for supporting our embedded Python. install(FILES ${CMAKE_SOURCE_DIR}/include/mgp.py DESTINATION lib/memgraph/python_support) + # Install the includes file for writing custom procedures in C and C++> install(FILES ${CMAKE_SOURCE_DIR}/include/mg_procedure.h DESTINATION include/memgraph) @@ -107,9 +116,11 @@ install(FILES ${CMAKE_SOURCE_DIR}/include/mg_exceptions.hpp DESTINATION include/memgraph) install(FILES ${CMAKE_SOURCE_DIR}/include/mgp.hpp DESTINATION include/memgraph) + # Install the config file (must use absolute path). install(FILES ${CMAKE_BINARY_DIR}/config/memgraph.conf DESTINATION /etc/memgraph RENAME memgraph.conf) + # Install logrotate configuration (must use absolute path). install(FILES ${CMAKE_SOURCE_DIR}/release/logrotate.conf DESTINATION /etc/logrotate.d RENAME memgraph) @@ -125,15 +136,14 @@ install(CODE "file(MAKE_DIRECTORY \$ENV{DESTDIR}/var/log/memgraph # ---------------------------------------------------------------------------- # Memgraph CSV Import Tool Executable # ---------------------------------------------------------------------------- - add_executable(mg_import_csv mg_import_csv.cpp) target_link_libraries(mg_import_csv mg-storage-v2) # Strip the executable in release build. -if (lower_build_type STREQUAL "release") - add_custom_command(TARGET mg_import_csv POST_BUILD - COMMAND strip -s mg_import_csv - COMMENT "Stripping symbols and sections from mg_import_csv") +if(lower_build_type STREQUAL "release") + add_custom_command(TARGET mg_import_csv POST_BUILD + COMMAND strip -s mg_import_csv + COMMENT "Stripping symbols and sections from mg_import_csv") endif() install(TARGETS mg_import_csv RUNTIME DESTINATION bin) diff --git a/src/auth/auth.cpp b/src/auth/auth.cpp index d325fba2a..03ce329df 100644 --- a/src/auth/auth.cpp +++ b/src/auth/auth.cpp @@ -16,8 +16,8 @@ #include #include "auth/exceptions.hpp" +#include "license/license.hpp" #include "utils/flag_validation.hpp" -#include "utils/license.hpp" #include "utils/logging.hpp" #include "utils/message.hpp" #include "utils/settings.hpp" @@ -68,10 +68,9 @@ Auth::Auth(const std::string &storage_directory) : storage_(storage_directory), std::optional Auth::Authenticate(const std::string &username, const std::string &password) { if (module_.IsUsed()) { - const auto license_check_result = utils::license::global_license_checker.IsValidLicense(utils::global_settings); + const auto license_check_result = license::global_license_checker.IsEnterpriseValid(utils::global_settings); if (license_check_result.HasError()) { - spdlog::warn( - utils::license::LicenseCheckErrorToString(license_check_result.GetError(), "authentication modules")); + spdlog::warn(license::LicenseCheckErrorToString(license_check_result.GetError(), "authentication modules")); return std::nullopt; } diff --git a/src/auth/models.cpp b/src/auth/models.cpp index 7a4481447..78276bbae 100644 --- a/src/auth/models.cpp +++ b/src/auth/models.cpp @@ -15,8 +15,8 @@ #include "auth/crypto.hpp" #include "auth/exceptions.hpp" +#include "license/license.hpp" #include "utils/cast.hpp" -#include "utils/license.hpp" #include "utils/logging.hpp" #include "utils/settings.hpp" #include "utils/string.hpp" @@ -242,7 +242,7 @@ FineGrainedAccessPermissions::FineGrainedAccessPermissions(const std::unordered_ PermissionLevel FineGrainedAccessPermissions::Has(const std::string &permission, const FineGrainedPermission fine_grained_permission) const { - if (!memgraph::utils::license::global_license_checker.IsValidLicenseFast()) { + if (!memgraph::license::global_license_checker.IsEnterpriseValidFast()) { return PermissionLevel::GRANT; } const auto concrete_permission = std::invoke([&]() -> uint64_t { @@ -281,7 +281,7 @@ void FineGrainedAccessPermissions::Revoke(const std::string &permission) { } nlohmann::json FineGrainedAccessPermissions::Serialize() const { - if (!memgraph::utils::license::global_license_checker.IsValidLicenseFast()) { + if (!memgraph::license::global_license_checker.IsEnterpriseValidFast()) { return {}; } nlohmann::json data = nlohmann::json::object(); @@ -294,7 +294,7 @@ FineGrainedAccessPermissions FineGrainedAccessPermissions::Deserialize(const nlo if (!data.is_object()) { throw AuthException("Couldn't load permissions data!"); } - if (!memgraph::utils::license::global_license_checker.IsValidLicenseFast()) { + if (!memgraph::license::global_license_checker.IsEnterpriseValidFast()) { return FineGrainedAccessPermissions{}; } std::optional global_permission; @@ -347,7 +347,7 @@ const FineGrainedAccessPermissions &FineGrainedAccessHandler::edge_type_permissi FineGrainedAccessPermissions &FineGrainedAccessHandler::edge_type_permissions() { return edge_type_permissions_; } nlohmann::json FineGrainedAccessHandler::Serialize() const { - if (!memgraph::utils::license::global_license_checker.IsValidLicenseFast()) { + if (!memgraph::license::global_license_checker.IsEnterpriseValidFast()) { return {}; } nlohmann::json data = nlohmann::json::object(); @@ -363,7 +363,7 @@ FineGrainedAccessHandler FineGrainedAccessHandler::Deserialize(const nlohmann::j if (!data["label_permissions"].is_object() || !data["edge_type_permissions"].is_object()) { throw AuthException("Couldn't load label_permissions or edge_type_permissions data!"); } - if (!memgraph::utils::license::global_license_checker.IsValidLicenseFast()) { + if (!memgraph::license::global_license_checker.IsEnterpriseValidFast()) { return FineGrainedAccessHandler{}; } auto label_permissions = FineGrainedAccessPermissions::Deserialize(data["label_permissions"]); @@ -414,7 +414,7 @@ nlohmann::json Role::Serialize() const { data["rolename"] = rolename_; data["permissions"] = permissions_.Serialize(); #ifdef MG_ENTERPRISE - if (memgraph::utils::license::global_license_checker.IsValidLicenseFast()) { + if (memgraph::license::global_license_checker.IsEnterpriseValidFast()) { data["fine_grained_access_handler"] = fine_grained_access_handler_.Serialize(); } else { data["fine_grained_access_handler"] = {}; @@ -432,7 +432,7 @@ Role Role::Deserialize(const nlohmann::json &data) { } auto permissions = Permissions::Deserialize(data["permissions"]); #ifdef MG_ENTERPRISE - if (memgraph::utils::license::global_license_checker.IsValidLicenseFast()) { + if (memgraph::license::global_license_checker.IsEnterpriseValidFast()) { if (!data["fine_grained_access_handler"].is_object()) { throw AuthException("Couldn't load user data!"); } @@ -445,7 +445,7 @@ Role Role::Deserialize(const nlohmann::json &data) { bool operator==(const Role &first, const Role &second) { #ifdef MG_ENTERPRISE - if (memgraph::utils::license::global_license_checker.IsValidLicenseFast()) { + if (memgraph::license::global_license_checker.IsEnterpriseValidFast()) { return first.rolename_ == second.rolename_ && first.permissions_ == second.permissions_ && first.fine_grained_access_handler_ == second.fine_grained_access_handler_; } @@ -483,13 +483,13 @@ void User::UpdatePassword(const std::optional &password) { } if (FLAGS_auth_password_strength_regex != default_password_regex) { - if (const auto license_check_result = utils::license::global_license_checker.IsValidLicense(utils::global_settings); + if (const auto license_check_result = license::global_license_checker.IsEnterpriseValid(utils::global_settings); license_check_result.HasError()) { throw AuthException( "Custom password regex is a Memgraph Enterprise feature. Please set the config " "(\"--auth-password-strength-regex\") to its default value (\"{}\") or remove the flag.\n{}", default_password_regex, - utils::license::LicenseCheckErrorToString(license_check_result.GetError(), "password regex")); + license::LicenseCheckErrorToString(license_check_result.GetError(), "password regex")); } } std::regex re(FLAGS_auth_password_strength_regex); @@ -517,7 +517,7 @@ Permissions User::GetPermissions() const { #ifdef MG_ENTERPRISE FineGrainedAccessPermissions User::GetFineGrainedAccessLabelPermissions() const { - if (!memgraph::utils::license::global_license_checker.IsValidLicenseFast()) { + if (!memgraph::license::global_license_checker.IsEnterpriseValidFast()) { return FineGrainedAccessPermissions{}; } @@ -530,7 +530,7 @@ FineGrainedAccessPermissions User::GetFineGrainedAccessLabelPermissions() const } FineGrainedAccessPermissions User::GetFineGrainedAccessEdgeTypePermissions() const { - if (!memgraph::utils::license::global_license_checker.IsValidLicenseFast()) { + if (!memgraph::license::global_license_checker.IsEnterpriseValidFast()) { return FineGrainedAccessPermissions{}; } if (role_) { @@ -563,7 +563,7 @@ nlohmann::json User::Serialize() const { data["password_hash"] = password_hash_; data["permissions"] = permissions_.Serialize(); #ifdef MG_ENTERPRISE - if (memgraph::utils::license::global_license_checker.IsValidLicenseFast()) { + if (memgraph::license::global_license_checker.IsEnterpriseValidFast()) { data["fine_grained_access_handler"] = fine_grained_access_handler_.Serialize(); } else { data["fine_grained_access_handler"] = {}; @@ -582,7 +582,7 @@ User User::Deserialize(const nlohmann::json &data) { } auto permissions = Permissions::Deserialize(data["permissions"]); #ifdef MG_ENTERPRISE - if (memgraph::utils::license::global_license_checker.IsValidLicenseFast()) { + if (memgraph::license::global_license_checker.IsEnterpriseValidFast()) { if (!data["fine_grained_access_handler"].is_object()) { throw AuthException("Couldn't load user data!"); } @@ -595,7 +595,7 @@ User User::Deserialize(const nlohmann::json &data) { bool operator==(const User &first, const User &second) { #ifdef MG_ENTERPRISE - if (memgraph::utils::license::global_license_checker.IsValidLicenseFast()) { + if (memgraph::license::global_license_checker.IsEnterpriseValidFast()) { return first.username_ == second.username_ && first.password_hash_ == second.password_hash_ && first.permissions_ == second.permissions_ && first.role_ == second.role_ && first.fine_grained_access_handler_ == second.fine_grained_access_handler_; diff --git a/src/glue/auth_checker.cpp b/src/glue/auth_checker.cpp index 80c996ad4..1c58daed4 100644 --- a/src/glue/auth_checker.cpp +++ b/src/glue/auth_checker.cpp @@ -14,8 +14,8 @@ #include "auth/auth.hpp" #include "auth/models.hpp" #include "glue/auth.hpp" +#include "license/license.hpp" #include "query/frontend/ast/ast.hpp" -#include "utils/license.hpp" #include "utils/synchronized.hpp" #ifdef MG_ENTERPRISE @@ -23,7 +23,7 @@ namespace { bool IsUserAuthorizedLabels(const memgraph::auth::User &user, const memgraph::query::DbAccessor *dba, const std::vector &labels, const memgraph::query::AuthQuery::FineGrainedPrivilege fine_grained_privilege) { - if (!memgraph::utils::license::global_license_checker.IsValidLicenseFast()) { + if (!memgraph::license::global_license_checker.IsEnterpriseValidFast()) { return true; } return std::all_of(labels.begin(), labels.end(), [dba, &user, fine_grained_privilege](const auto &label) { @@ -35,7 +35,7 @@ bool IsUserAuthorizedLabels(const memgraph::auth::User &user, const memgraph::qu bool IsUserAuthorizedGloballyLabels(const memgraph::auth::User &user, const memgraph::auth::FineGrainedPermission fine_grained_permission) { - if (!memgraph::utils::license::global_license_checker.IsValidLicenseFast()) { + if (!memgraph::license::global_license_checker.IsEnterpriseValidFast()) { return true; } return user.GetFineGrainedAccessLabelPermissions().Has(memgraph::auth::kAsterisk, fine_grained_permission) == @@ -44,7 +44,7 @@ bool IsUserAuthorizedGloballyLabels(const memgraph::auth::User &user, bool IsUserAuthorizedGloballyEdges(const memgraph::auth::User &user, const memgraph::auth::FineGrainedPermission fine_grained_permission) { - if (!memgraph::utils::license::global_license_checker.IsValidLicenseFast()) { + if (!memgraph::license::global_license_checker.IsEnterpriseValidFast()) { return true; } return user.GetFineGrainedAccessEdgeTypePermissions().Has(memgraph::auth::kAsterisk, fine_grained_permission) == @@ -54,7 +54,7 @@ bool IsUserAuthorizedGloballyEdges(const memgraph::auth::User &user, bool IsUserAuthorizedEdgeType(const memgraph::auth::User &user, const memgraph::query::DbAccessor *dba, const memgraph::storage::EdgeTypeId &edgeType, const memgraph::query::AuthQuery::FineGrainedPrivilege fine_grained_privilege) { - if (!memgraph::utils::license::global_license_checker.IsValidLicenseFast()) { + if (!memgraph::license::global_license_checker.IsEnterpriseValidFast()) { return true; } return user.GetFineGrainedAccessEdgeTypePermissions().Has( @@ -87,7 +87,7 @@ bool AuthChecker::IsUserAuthorized(const std::optional &username, #ifdef MG_ENTERPRISE std::unique_ptr AuthChecker::GetFineGrainedAuthChecker( const std::string &username, const memgraph::query::DbAccessor *dba) const { - if (!memgraph::utils::license::global_license_checker.IsValidLicenseFast()) { + if (!memgraph::license::global_license_checker.IsEnterpriseValidFast()) { return {}; } try { @@ -154,7 +154,7 @@ bool FineGrainedAuthChecker::Has(const memgraph::storage::EdgeTypeId &edge_type, bool FineGrainedAuthChecker::HasGlobalPrivilegeOnVertices( const memgraph::query::AuthQuery::FineGrainedPrivilege fine_grained_privilege) const { - if (!memgraph::utils::license::global_license_checker.IsValidLicenseFast()) { + if (!memgraph::license::global_license_checker.IsEnterpriseValidFast()) { return true; } return IsUserAuthorizedGloballyLabels(user_, FineGrainedPrivilegeToFineGrainedPermission(fine_grained_privilege)); @@ -162,7 +162,7 @@ bool FineGrainedAuthChecker::HasGlobalPrivilegeOnVertices( bool FineGrainedAuthChecker::HasGlobalPrivilegeOnEdges( const memgraph::query::AuthQuery::FineGrainedPrivilege fine_grained_privilege) const { - if (!memgraph::utils::license::global_license_checker.IsValidLicenseFast()) { + if (!memgraph::license::global_license_checker.IsEnterpriseValidFast()) { return true; } return IsUserAuthorizedGloballyEdges(user_, FineGrainedPrivilegeToFineGrainedPermission(fine_grained_privilege)); diff --git a/src/glue/auth_handler.cpp b/src/glue/auth_handler.cpp index 0428186c0..b08d47dfe 100644 --- a/src/glue/auth_handler.cpp +++ b/src/glue/auth_handler.cpp @@ -17,7 +17,7 @@ #include "auth/models.hpp" #include "glue/auth.hpp" -#include "utils/license.hpp" +#include "license/license.hpp" namespace { @@ -125,7 +125,7 @@ std::vector GetFineGrainedPermissionFor const memgraph::auth::FineGrainedAccessPermissions &permissions, const std::string &permission_type, const std::string &user_or_role) { std::vector fine_grained_permissions; - if (!memgraph::utils::license::global_license_checker.IsValidLicenseFast()) { + if (!memgraph::license::global_license_checker.IsEnterpriseValidFast()) { return fine_grained_permissions; } const auto global_permission = permissions.GetGlobalPermission(); @@ -166,7 +166,7 @@ std::vector GetFineGrainedPermissionFor std::vector> ConstructFineGrainedPrivilegesResult( const std::vector &privileges) { std::vector> grants; - if (!memgraph::utils::license::global_license_checker.IsValidLicenseFast()) { + if (!memgraph::license::global_license_checker.IsEnterpriseValidFast()) { return {}; } grants.reserve(privileges.size()); @@ -182,7 +182,7 @@ std::vector> ConstructFineGrainedPrivil std::vector> ShowFineGrainedUserPrivileges( const std::optional &user) { - if (!memgraph::utils::license::global_license_checker.IsValidLicenseFast()) { + if (!memgraph::license::global_license_checker.IsEnterpriseValidFast()) { return {}; } const auto &label_permissions = user->GetFineGrainedAccessLabelPermissions(); @@ -201,7 +201,7 @@ std::vector> ShowFineGrainedUserPrivile std::vector> ShowFineGrainedRolePrivileges( const std::optional &role) { - if (!memgraph::utils::license::global_license_checker.IsValidLicenseFast()) { + if (!memgraph::license::global_license_checker.IsEnterpriseValidFast()) { return {}; } const auto &label_permissions = role->GetFineGrainedAccessLabelPermissions(); @@ -231,13 +231,13 @@ AuthQueryHandler::AuthQueryHandler( bool AuthQueryHandler::CreateUser(const std::string &username, const std::optional &password) { if (name_regex_string_ != kDefaultUserRoleRegex) { if (const auto license_check_result = - memgraph::utils::license::global_license_checker.IsValidLicense(memgraph::utils::global_settings); + memgraph::license::global_license_checker.IsEnterpriseValid(memgraph::utils::global_settings); license_check_result.HasError()) { throw memgraph::auth::AuthException( "Custom user/role regex is a Memgraph Enterprise feature. Please set the config " "(\"--auth-user-or-role-name-regex\") to its default value (\"{}\") or remove the flag.\n{}", kDefaultUserRoleRegex, - memgraph::utils::license::LicenseCheckErrorToString(license_check_result.GetError(), "user/role regex")); + memgraph::license::LicenseCheckErrorToString(license_check_result.GetError(), "user/role regex")); } } if (!std::regex_match(username, name_regex_)) { @@ -473,20 +473,20 @@ std::vector> AuthQueryHandler::GetPrivi if (user) { grants = ShowUserPrivileges(user); #ifdef MG_ENTERPRISE - if (memgraph::utils::license::global_license_checker.IsValidLicenseFast()) { + if (memgraph::license::global_license_checker.IsEnterpriseValidFast()) { fine_grained_grants = ShowFineGrainedUserPrivileges(user); } #endif } else { grants = ShowRolePrivileges(role); #ifdef MG_ENTERPRISE - if (memgraph::utils::license::global_license_checker.IsValidLicenseFast()) { + if (memgraph::license::global_license_checker.IsEnterpriseValidFast()) { fine_grained_grants = ShowFineGrainedRolePrivileges(role); } #endif } #ifdef MG_ENTERPRISE - if (memgraph::utils::license::global_license_checker.IsValidLicenseFast()) { + if (memgraph::license::global_license_checker.IsEnterpriseValidFast()) { grants.insert(grants.end(), fine_grained_grants.begin(), fine_grained_grants.end()); } #endif @@ -627,7 +627,7 @@ void AuthQueryHandler::EditPermissions( edit_permissions_fun(user->permissions(), permission); } #ifdef MG_ENTERPRISE - if (memgraph::utils::license::global_license_checker.IsValidLicenseFast()) { + if (memgraph::license::global_license_checker.IsEnterpriseValidFast()) { for (const auto &label_privilege_collection : label_privileges) { edit_fine_grained_permissions_fun(user->fine_grained_access_handler().label_permissions(), label_privilege_collection); @@ -644,7 +644,7 @@ void AuthQueryHandler::EditPermissions( edit_permissions_fun(role->permissions(), permission); } #ifdef MG_ENTERPRISE - if (memgraph::utils::license::global_license_checker.IsValidLicenseFast()) { + if (memgraph::license::global_license_checker.IsEnterpriseValidFast()) { for (const auto &label_privilege : label_privileges) { edit_fine_grained_permissions_fun(role->fine_grained_access_handler().label_permissions(), label_privilege); } diff --git a/src/glue/auth_handler.hpp b/src/glue/auth_handler.hpp index 440e9a835..508d770ab 100644 --- a/src/glue/auth_handler.hpp +++ b/src/glue/auth_handler.hpp @@ -15,8 +15,8 @@ #include "auth/auth.hpp" #include "glue/auth.hpp" +#include "license/license.hpp" #include "query/interpreter.hpp" -#include "utils/license.hpp" #include "utils/string.hpp" namespace memgraph::glue { diff --git a/src/license/CMakeLists.txt b/src/license/CMakeLists.txt new file mode 100644 index 000000000..8e7a38c36 --- /dev/null +++ b/src/license/CMakeLists.txt @@ -0,0 +1,6 @@ +set(license_src_files + license_sender.cpp + license.cpp) +add_library(mg-license STATIC ${license_src_files}) + +target_link_libraries(mg-license mg-settings mg-utils mg-requests spdlog::spdlog) diff --git a/src/utils/license.cpp b/src/license/license.cpp similarity index 79% rename from src/utils/license.cpp rename to src/license/license.cpp index b3a2845a9..ff5306dab 100644 --- a/src/utils/license.cpp +++ b/src/license/license.cpp @@ -9,17 +9,19 @@ // by the Apache License, Version 2.0, included in the file // licenses/APL.txt. -#include "utils/license.hpp" +#include "license/license.hpp" #include #include #include +#include #include #include #include #include "slk/serialization.hpp" #include "utils/base64.hpp" +#include "utils/cast.hpp" #include "utils/exceptions.hpp" #include "utils/logging.hpp" #include "utils/memory_tracker.hpp" @@ -27,7 +29,7 @@ #include "utils/spin_lock.hpp" #include "utils/synchronized.hpp" -namespace memgraph::utils::license { +namespace memgraph::license { namespace { inline constexpr std::string_view license_key_prefix = "mglk-"; @@ -69,6 +71,17 @@ LicenseCheckResult IsValidLicenseInternal(const License &license, const std::str } } // namespace +std::string LicenseTypeToString(const LicenseType license_type) { + switch (license_type) { + case LicenseType::ENTERPRISE: { + return "enterprise"; + } + case LicenseType::OEM: { + return "oem"; + } + } +} + void RegisterLicenseSettings(LicenseChecker &license_checker, utils::Settings &settings) { settings.RegisterSetting(std::string{kEnterpriseLicenseSettingKey}, "", [&] { license_checker.RevalidateLicense(settings); }); @@ -81,7 +94,7 @@ LicenseChecker global_license_checker; LicenseChecker::~LicenseChecker() { scheduler_.Stop(); } -std::pair LicenseChecker::GetLicenseInfo(const utils::Settings &settings) const { +std::pair LicenseChecker::ExtractLicenseInfo(const utils::Settings &settings) const { if (license_info_override_) { spdlog::warn("Ignoring license info stored in the settings because a different source was specified."); return *license_info_override_; @@ -96,7 +109,7 @@ std::pair LicenseChecker::GetLicenseInfo(const utils:: } void LicenseChecker::RevalidateLicense(const utils::Settings &settings) { - const auto license_info = GetLicenseInfo(settings); + const auto license_info = ExtractLicenseInfo(settings); RevalidateLicense(license_info.first, license_info.second); } @@ -117,18 +130,7 @@ void LicenseChecker::RevalidateLicense(const std::string &license_key, const std return; } - struct PreviousLicenseInfo { - PreviousLicenseInfo(std::string license_key, std::string organization_name) - : license_key(std::move(license_key)), organization_name(std::move(organization_name)) {} - - std::string license_key; - std::string organization_name; - bool is_valid{false}; - }; - - static utils::Synchronized, utils::SpinLock> previous_license_info; - - auto locked_previous_license_info_ptr = previous_license_info.Lock(); + auto locked_previous_license_info_ptr = previous_license_info_.Lock(); auto &locked_previous_license_info = *locked_previous_license_info_ptr; const bool same_license_info = locked_previous_license_info && locked_previous_license_info->license_key == license_key && @@ -140,7 +142,7 @@ void LicenseChecker::RevalidateLicense(const std::string &license_key, const std locked_previous_license_info.emplace(license_key, organization_name); - const auto maybe_license = GetLicense(locked_previous_license_info->license_key); + auto maybe_license = GetLicense(locked_previous_license_info->license_key); if (!maybe_license) { spdlog::warn(LicenseCheckErrorToString(LicenseCheckError::INVALID_LICENSE_KEY_STRING, "Enterprise features")); is_valid_.store(false, std::memory_order_relaxed); @@ -156,22 +158,30 @@ void LicenseChecker::RevalidateLicense(const std::string &license_key, const std spdlog::warn(LicenseCheckErrorToString(license_check_result.GetError(), "Enterprise features")); is_valid_.store(false, std::memory_order_relaxed); locked_previous_license_info->is_valid = false; + license_type_ = maybe_license->type; set_memory_limit(0); return; } if (!same_license_info) { - spdlog::info("All Enterprise features are active."); + license_type_ = maybe_license->type; + if (license_type_ == LicenseType::ENTERPRISE) { + spdlog::info("Enterprise license is active."); + } else { + spdlog::info("OEM license is active."); + } is_valid_.store(true, std::memory_order_relaxed); locked_previous_license_info->is_valid = true; set_memory_limit(maybe_license->memory_limit); + locked_previous_license_info->license = std::move(*maybe_license); } } -void LicenseChecker::EnableTesting() { +void LicenseChecker::EnableTesting(const LicenseType license_type) { enterprise_enabled_ = true; is_valid_.store(true, std::memory_order_relaxed); - spdlog::info("All Enterprise features are activated for testing."); + license_type_ = license_type; + spdlog::info("The license type {} is set for testing.", LicenseTypeToString(license_type)); } void LicenseChecker::CheckEnvLicense() { @@ -216,20 +226,26 @@ std::string LicenseCheckErrorToString(LicenseCheckError error, const std::string "following query:\n" "SET DATABASE SETTING \"enterprise.license\" TO \"your-license-key\"", feature); + case LicenseCheckError::NOT_ENTERPRISE_LICENSE: + return fmt::format("Your license has an invalid type. To use {} you need to have an enterprise license. \n", + feature); } } -LicenseCheckResult LicenseChecker::IsValidLicense(const utils::Settings &settings) const { +LicenseCheckResult LicenseChecker::IsEnterpriseValid(const utils::Settings &settings) const { if (enterprise_enabled_) [[unlikely]] { return {}; } - const auto license_info = GetLicenseInfo(settings); + const auto license_info = ExtractLicenseInfo(settings); const auto maybe_license = GetLicense(license_info.first); if (!maybe_license) { return LicenseCheckError::INVALID_LICENSE_KEY_STRING; } + if (maybe_license->type != LicenseType::ENTERPRISE) { + return LicenseCheckError::NOT_ENTERPRISE_LICENSE; + } return IsValidLicenseInternal(*maybe_license, license_info.second); } @@ -239,7 +255,13 @@ void LicenseChecker::StartBackgroundLicenseChecker(const utils::Settings &settin scheduler_.Run("licensechecker", std::chrono::minutes{5}, [&, this] { RevalidateLicense(settings); }); } -bool LicenseChecker::IsValidLicenseFast() const { return is_valid_.load(std::memory_order_relaxed); } +utils::Synchronized, utils::SpinLock> &LicenseChecker::GetLicenseInfo() { + return previous_license_info_; +} + +bool LicenseChecker::IsEnterpriseValidFast() const { + return license_type_ == LicenseType::ENTERPRISE && is_valid_.load(std::memory_order_relaxed); +} std::string Encode(const License &license) { std::vector buffer; @@ -252,9 +274,10 @@ std::string Encode(const License &license) { slk::Save(license.organization_name, &builder); slk::Save(license.valid_until, &builder); slk::Save(license.memory_limit, &builder); + slk::Save(utils::UnderlyingCast(license.type), &builder); builder.Finalize(); - return std::string{license_key_prefix} + base64_encode(buffer.data(), buffer.size()); + return std::string{license_key_prefix} + utils::base64_encode(buffer.data(), buffer.size()); } std::optional Decode(std::string_view license_key) { @@ -266,7 +289,7 @@ std::optional Decode(std::string_view license_key) { const auto decoded = std::invoke([license_key]() -> std::optional { try { - return base64_decode(license_key); + return utils::base64_decode(license_key); } catch (const std::runtime_error & /*exception*/) { return std::nullopt; } @@ -284,10 +307,12 @@ std::optional Decode(std::string_view license_key) { slk::Load(&valid_until, &reader); int64_t memory_limit{0}; slk::Load(&memory_limit, &reader); - return License{.organization_name = organization_name, .valid_until = valid_until, .memory_limit = memory_limit}; + std::underlying_type_t license_type{0}; + slk::Load(&license_type, &reader); + return {License{organization_name, valid_until, memory_limit, LicenseType(license_type)}}; } catch (const slk::SlkReaderException &e) { return std::nullopt; } } -} // namespace memgraph::utils::license +} // namespace memgraph::license diff --git a/src/utils/license.hpp b/src/license/license.hpp similarity index 61% rename from src/utils/license.hpp rename to src/license/license.hpp index 719f4d4ff..da47ae0ff 100644 --- a/src/utils/license.hpp +++ b/src/license/license.hpp @@ -12,26 +12,57 @@ #pragma once #include +#include #include #include "utils/result.hpp" #include "utils/scheduler.hpp" #include "utils/settings.hpp" +#include "utils/spin_lock.hpp" +#include "utils/synchronized.hpp" -namespace memgraph::utils::license { +namespace memgraph::license { + +enum class LicenseType : uint8_t { ENTERPRISE, OEM }; + +std::string LicenseTypeToString(LicenseType license_type); struct License { + License() = default; + + License(std::string organization_name, int64_t valid_until, int64_t memory_limit, LicenseType license_type) + : organization_name{std::move(organization_name)}, + valid_until{valid_until}, + memory_limit{memory_limit}, + type{license_type} {} + std::string organization_name; int64_t valid_until; int64_t memory_limit; + LicenseType type; bool operator==(const License &) const = default; }; +struct LicenseInfo { + LicenseInfo(std::string license_key, std::string organization_name) + : license_key(std::move(license_key)), organization_name{std::move(organization_name)} {} + + std::string license_key; + std::string organization_name; + bool is_valid{false}; + License license; +}; + inline constexpr std::string_view kEnterpriseLicenseSettingKey = "enterprise.license"; inline constexpr std::string_view kOrganizationNameSettingKey = "organization.name"; -enum class LicenseCheckError : uint8_t { INVALID_LICENSE_KEY_STRING, INVALID_ORGANIZATION_NAME, EXPIRED_LICENSE }; +enum class LicenseCheckError : uint8_t { + INVALID_LICENSE_KEY_STRING, + INVALID_ORGANIZATION_NAME, + EXPIRED_LICENSE, + NOT_ENTERPRISE_LICENSE +}; std::string LicenseCheckErrorToString(LicenseCheckError error, std::string_view feature); @@ -49,19 +80,25 @@ struct LicenseChecker { void CheckEnvLicense(); void SetLicenseInfoOverride(std::string license_key, std::string organization_name); - void EnableTesting(); - LicenseCheckResult IsValidLicense(const utils::Settings &settings) const; - bool IsValidLicenseFast() const; + void EnableTesting(LicenseType license_type = LicenseType::ENTERPRISE); + // Checks if license is valid and if enterprise is enabled + LicenseCheckResult IsEnterpriseValid(const utils::Settings &settings) const; + bool IsEnterpriseValidFast() const; + void StartBackgroundLicenseChecker(const utils::Settings &settings); + utils::Synchronized, utils::SpinLock> &GetLicenseInfo(); + private: - std::pair GetLicenseInfo(const utils::Settings &settings) const; + std::pair ExtractLicenseInfo(const utils::Settings &settings) const; void RevalidateLicense(const utils::Settings &settings); void RevalidateLicense(const std::string &license_key, const std::string &organization_name); std::optional> license_info_override_; + utils::Synchronized, utils::SpinLock> previous_license_info_{std::nullopt}; bool enterprise_enabled_{false}; std::atomic is_valid_{false}; + LicenseType license_type_; utils::Scheduler scheduler_; friend void RegisterLicenseSettings(LicenseChecker &license_checker, utils::Settings &settings); @@ -74,4 +111,4 @@ std::string Encode(const License &license); // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) extern LicenseChecker global_license_checker; -} // namespace memgraph::utils::license +} // namespace memgraph::license diff --git a/src/license/license_sender.cpp b/src/license/license_sender.cpp new file mode 100644 index 000000000..ac20c23a2 --- /dev/null +++ b/src/license/license_sender.cpp @@ -0,0 +1,71 @@ +// Copyright 2022 Memgraph Ltd. +// +// Use of this software is governed by the Business Source License +// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source +// License, and you may not use this file except in compliance with the Business Source License. +// +// As of the Change Date specified in that file, in accordance with +// the Business Source License, use of this software will be governed +// by the Apache License, Version 2.0, included in the file +// licenses/APL.txt. + +#include "license/license_sender.hpp" + +#include +#include + +#include "requests/requests.hpp" +#include "utils/memory_tracker.hpp" +#include "utils/stat.hpp" +#include "utils/synchronized.hpp" +#include "utils/system_info.hpp" +#include "utils/timestamp.hpp" + +namespace memgraph::license { + +LicenseInfoSender::LicenseInfoSender(std::string url, std::string uuid, std::string machine_id, int64_t memory_limit, + utils::Synchronized, utils::SpinLock> &license_info, + std::chrono::seconds request_frequency) + : url_{std::move(url)}, + uuid_{std::move(uuid)}, + machine_id_{std::move(machine_id)}, + memory_limit_{memory_limit}, + license_info_{license_info} { + scheduler_.Run("LicenseCheck", request_frequency, [&] { SendData(); }); +} + +LicenseInfoSender::~LicenseInfoSender() { scheduler_.Stop(); } + +void LicenseInfoSender::SendData() { + nlohmann::json data = nlohmann::json::object(); + + license_info_.WithLock([&data, this](const auto &license_info) mutable { + if (license_info && !license_info->organization_name.empty()) { + const auto memory_info = utils::GetMemoryInfo(); + const auto memory_usage = utils::GetMemoryUsage(); + data = {{"run_id", uuid_}, + {"machine_id", machine_id_}, + {"type", "license-check"}, + {"license_type", LicenseTypeToString(license_info->license.type)}, + {"license_key", license_info->license_key}, + {"organization", license_info->organization_name}, + {"valid", license_info->is_valid}, + {"physical_memory_size", memory_info.memory}, + {"swap_memory_size", memory_info.swap}, + {"memory_used", memory_usage}, + {"runtime_memory_limit", memory_limit_}, + {"license_memory_limit", license_info->license.memory_limit}, + {"timestamp", utils::Timestamp::Now().SecWithNsecSinceTheEpoch()}}; + } + }); + + if (data.empty()) { + return; + } + if (!requests::RequestPostJson(url_, data, + /* timeout_in_seconds = */ 2 * 60)) { + spdlog::trace("Cannot send license information, enable {} availability!", url_); + } +} + +} // namespace memgraph::license diff --git a/src/license/license_sender.hpp b/src/license/license_sender.hpp new file mode 100644 index 000000000..0adbd147c --- /dev/null +++ b/src/license/license_sender.hpp @@ -0,0 +1,50 @@ +// Copyright 2022 Memgraph Ltd. +// +// Use of this software is governed by the Business Source License +// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source +// License, and you may not use this file except in compliance with the Business Source License. +// +// As of the Change Date specified in that file, in accordance with +// the Business Source License, use of this software will be governed +// by the Apache License, Version 2.0, included in the file +// licenses/APL.txt. + +#pragma once + +#include +#include +#include + +#include + +#include "license/license.hpp" +#include "utils/scheduler.hpp" +#include "utils/timer.hpp" + +namespace memgraph::license { + +class LicenseInfoSender final { + public: + LicenseInfoSender(std::string url, std::string uuid, std::string machine_id, int64_t memory_limit, + utils::Synchronized, utils::SpinLock> &license_info, + std::chrono::seconds request_frequency = std::chrono::seconds(8 * 60 * 60)); + + LicenseInfoSender(const LicenseInfoSender &) = delete; + LicenseInfoSender(LicenseInfoSender &&) noexcept = delete; + LicenseInfoSender &operator=(const LicenseInfoSender &) = delete; + LicenseInfoSender &operator=(LicenseInfoSender &&) noexcept = delete; + ~LicenseInfoSender(); + + private: + void SendData(); + + const std::string url_; + const std::string uuid_; + const std::string machine_id_; + const int64_t memory_limit_; + + utils::Synchronized, utils::SpinLock> &license_info_; + utils::Scheduler scheduler_; +}; + +} // namespace memgraph::license diff --git a/src/memgraph.cpp b/src/memgraph.cpp index 9a813231e..c1a245a4c 100644 --- a/src/memgraph.cpp +++ b/src/memgraph.cpp @@ -40,6 +40,8 @@ #include "glue/auth_checker.hpp" #include "glue/auth_handler.hpp" #include "helpers.hpp" +#include "license/license.hpp" +#include "license/license_sender.hpp" #include "py/py.hpp" #include "query/auth_checker.hpp" #include "query/discard_value_stream.hpp" @@ -57,7 +59,6 @@ #include "utils/event_counter.hpp" #include "utils/file.hpp" #include "utils/flag_validation.hpp" -#include "utils/license.hpp" #include "utils/logging.hpp" #include "utils/memory_tracker.hpp" #include "utils/message.hpp" @@ -68,6 +69,7 @@ #include "utils/string.hpp" #include "utils/synchronized.hpp" #include "utils/sysinfo/memory.hpp" +#include "utils/system_info.hpp" #include "utils/terminate_handler.hpp" #include "version.hpp" @@ -506,7 +508,7 @@ class BoltSession final : public memgraph::communication::bolt::Sessionusername(); } #ifdef MG_ENTERPRISE - if (memgraph::utils::license::global_license_checker.IsValidLicenseFast()) { + if (memgraph::license::global_license_checker.IsEnterpriseValidFast()) { audit_log_->Record(endpoint_.address().to_string(), user_ ? *username : "", query, memgraph::storage::PropertyValue(params_pv)); } @@ -779,15 +781,15 @@ int main(int argc, char **argv) { memgraph::utils::OnScopeExit settings_finalizer([&] { memgraph::utils::global_settings.Finalize(); }); // register all runtime settings - memgraph::utils::license::RegisterLicenseSettings(memgraph::utils::license::global_license_checker, - memgraph::utils::global_settings); + memgraph::license::RegisterLicenseSettings(memgraph::license::global_license_checker, + memgraph::utils::global_settings); - memgraph::utils::license::global_license_checker.CheckEnvLicense(); + memgraph::license::global_license_checker.CheckEnvLicense(); if (!FLAGS_organization_name.empty() && !FLAGS_license_key.empty()) { - memgraph::utils::license::global_license_checker.SetLicenseInfoOverride(FLAGS_license_key, FLAGS_organization_name); + memgraph::license::global_license_checker.SetLicenseInfoOverride(FLAGS_license_key, FLAGS_organization_name); } - memgraph::utils::license::global_license_checker.StartBackgroundLicenseChecker(memgraph::utils::global_settings); + memgraph::license::global_license_checker.StartBackgroundLicenseChecker(memgraph::utils::global_settings); // All enterprise features should be constructed before the main database // storage. This will cause them to be destructed *after* the main database @@ -906,12 +908,15 @@ int main(int argc, char **argv) { ServerT server(server_endpoint, &session_data, &context, FLAGS_bolt_session_inactivity_timeout, service_name, FLAGS_bolt_num_workers); + const auto run_id = memgraph::utils::GenerateUUID(); + const auto machine_id = memgraph::utils::GetMachineId(); + session_data.run_id = run_id; + // Setup telemetry + static constexpr auto telemetry_server{"https://telemetry.memgraph.com/88b5e7e8-746a-11e8-9f85-538a9e9690cc/"}; std::optional telemetry; if (FLAGS_telemetry_enabled) { - telemetry.emplace("https://telemetry.memgraph.com/88b5e7e8-746a-11e8-9f85-538a9e9690cc/", - data_directory / "telemetry", std::chrono::minutes(10)); - session_data.run_id = telemetry->GetRunId(); + telemetry.emplace(telemetry_server, data_directory / "telemetry", run_id, machine_id, std::chrono::minutes(10)); telemetry->AddCollector("storage", [&db]() -> nlohmann::json { auto info = db.GetInfo(); return {{"vertices", info.vertex_count}, {"edges", info.edge_count}}; @@ -927,6 +932,8 @@ int main(int argc, char **argv) { return memgraph::query::plan::CallProcedure::GetAndResetCounters(); }); } + memgraph::license::LicenseInfoSender license_info_sender(telemetry_server, run_id, machine_id, memory_limit, + memgraph::license::global_license_checker.GetLicenseInfo()); memgraph::communication::websocket::SafeAuth websocket_auth{&auth}; memgraph::communication::websocket::Server websocket_server{ diff --git a/src/query/interpreter.cpp b/src/query/interpreter.cpp index 76970992b..d5f156bc4 100644 --- a/src/query/interpreter.cpp +++ b/src/query/interpreter.cpp @@ -25,6 +25,7 @@ #include "auth/models.hpp" #include "glue/communication.hpp" +#include "license/license.hpp" #include "memory/memory_control.hpp" #include "query/constants.hpp" #include "query/context.hpp" @@ -54,7 +55,6 @@ #include "utils/event_counter.hpp" #include "utils/exceptions.hpp" #include "utils/flag_validation.hpp" -#include "utils/license.hpp" #include "utils/likely.hpp" #include "utils/logging.hpp" #include "utils/memory.hpp" @@ -299,7 +299,7 @@ Callback HandleAuthQuery(AuthQuery *auth_query, AuthQueryHandler *auth, const Pa Callback callback; - const auto license_check_result = utils::license::global_license_checker.IsValidLicense(utils::global_settings); + const auto license_check_result = license::global_license_checker.IsEnterpriseValid(utils::global_settings); static const std::unordered_set enterprise_only_methods{ AuthQuery::Action::CREATE_ROLE, AuthQuery::Action::DROP_ROLE, AuthQuery::Action::SET_ROLE, @@ -309,7 +309,7 @@ Callback HandleAuthQuery(AuthQuery *auth_query, AuthQueryHandler *auth, const Pa if (license_check_result.HasError() && enterprise_only_methods.contains(auth_query->action_)) { throw utils::BasicException( - utils::license::LicenseCheckErrorToString(license_check_result.GetError(), "advanced authentication features")); + license::LicenseCheckErrorToString(license_check_result.GetError(), "advanced authentication features")); } switch (auth_query->action_) { @@ -1017,7 +1017,7 @@ PullPlan::PullPlan(const std::shared_ptr plan, const Parameters &par ctx_.evaluation_context.properties = NamesToProperties(plan->ast_storage().properties_, dba); ctx_.evaluation_context.labels = NamesToLabels(plan->ast_storage().labels_, dba); #ifdef MG_ENTERPRISE - if (utils::license::global_license_checker.IsValidLicenseFast() && username.has_value() && dba) { + if (license::global_license_checker.IsEnterpriseValidFast() && username.has_value() && dba) { ctx_.auth_checker = interpreter_context->auth_checker->GetFineGrainedAuthChecker(*username, dba); } #endif diff --git a/src/query/plan/operator.cpp b/src/query/plan/operator.cpp index f374a7c1c..0d1339c99 100644 --- a/src/query/plan/operator.cpp +++ b/src/query/plan/operator.cpp @@ -27,6 +27,7 @@ #include #include "spdlog/spdlog.h" +#include "license/license.hpp" #include "query/auth_checker.hpp" #include "query/context.hpp" #include "query/db_accessor.hpp" @@ -47,7 +48,6 @@ #include "utils/event_counter.hpp" #include "utils/exceptions.hpp" #include "utils/fnv.hpp" -#include "utils/license.hpp" #include "utils/likely.hpp" #include "utils/logging.hpp" #include "utils/memory.hpp" @@ -242,7 +242,7 @@ CreateNode::CreateNodeCursor::CreateNodeCursor(const CreateNode &self, utils::Me bool CreateNode::CreateNodeCursor::Pull(Frame &frame, ExecutionContext &context) { SCOPED_PROFILE_OP("CreateNode"); #ifdef MG_ENTERPRISE - if (utils::license::global_license_checker.IsValidLicenseFast() && context.auth_checker && + if (license::global_license_checker.IsEnterpriseValidFast() && context.auth_checker && !context.auth_checker->Has(self_.node_info_.labels, memgraph::query::AuthQuery::FineGrainedPrivilege::CREATE_DELETE)) { throw QueryRuntimeException("Vertex not created due to not having enough permission!"); @@ -334,7 +334,7 @@ bool CreateExpand::CreateExpandCursor::Pull(Frame &frame, ExecutionContext &cont if (!input_cursor_->Pull(frame, context)) return false; #ifdef MG_ENTERPRISE - if (utils::license::global_license_checker.IsValidLicenseFast()) { + if (license::global_license_checker.IsEnterpriseValidFast()) { const auto fine_grained_permission = self_.existing_node_ ? memgraph::query::AuthQuery::FineGrainedPrivilege::UPDATE @@ -433,8 +433,7 @@ class ScanAllCursor : public Cursor { vertices_it_.emplace(vertices_.value().begin()); } #ifdef MG_ENTERPRISE - if (utils::license::global_license_checker.IsValidLicenseFast() && context.auth_checker && - !FindNextVertex(context)) { + if (license::global_license_checker.IsEnterpriseValidFast() && context.auth_checker && !FindNextVertex(context)) { return false; } #endif @@ -731,7 +730,7 @@ bool Expand::ExpandCursor::Pull(Frame &frame, ExecutionContext &context) { if (in_edges_ && *in_edges_it_ != in_edges_->end()) { auto edge = *(*in_edges_it_)++; #ifdef MG_ENTERPRISE - if (utils::license::global_license_checker.IsValidLicenseFast() && context.auth_checker && + if (license::global_license_checker.IsEnterpriseValidFast() && context.auth_checker && !(context.auth_checker->Has(edge, memgraph::query::AuthQuery::FineGrainedPrivilege::READ) && context.auth_checker->Has(edge.From(), self_.view_, memgraph::query::AuthQuery::FineGrainedPrivilege::READ))) { @@ -752,7 +751,7 @@ bool Expand::ExpandCursor::Pull(Frame &frame, ExecutionContext &context) { // already done in the block above if (self_.common_.direction == EdgeAtom::Direction::BOTH && edge.IsCycle()) continue; #ifdef MG_ENTERPRISE - if (utils::license::global_license_checker.IsValidLicenseFast() && context.auth_checker && + if (license::global_license_checker.IsEnterpriseValidFast() && context.auth_checker && !(context.auth_checker->Has(edge, memgraph::query::AuthQuery::FineGrainedPrivilege::READ) && context.auth_checker->Has(edge.To(), self_.view_, memgraph::query::AuthQuery::FineGrainedPrivilege::READ))) { @@ -1089,7 +1088,7 @@ class ExpandVariableCursor : public Cursor { VertexAccessor current_vertex = current_edge.second == EdgeAtom::Direction::IN ? current_edge.first.From() : current_edge.first.To(); #ifdef MG_ENTERPRISE - if (utils::license::global_license_checker.IsValidLicenseFast() && context.auth_checker && + if (license::global_license_checker.IsEnterpriseValidFast() && context.auth_checker && !(context.auth_checker->Has(current_edge.first, memgraph::query::AuthQuery::FineGrainedPrivilege::READ) && context.auth_checker->Has(current_vertex, storage::View::OLD, memgraph::query::AuthQuery::FineGrainedPrivilege::READ))) { @@ -1258,7 +1257,7 @@ class STShortestPathCursor : public query::plan::Cursor { auto out_edges = UnwrapEdgesResult(vertex.OutEdges(storage::View::OLD, self_.common_.edge_types)); for (const auto &edge : out_edges) { #ifdef MG_ENTERPRISE - if (utils::license::global_license_checker.IsValidLicenseFast() && context.auth_checker && + if (license::global_license_checker.IsEnterpriseValidFast() && context.auth_checker && !(context.auth_checker->Has(edge, memgraph::query::AuthQuery::FineGrainedPrivilege::READ) && context.auth_checker->Has(edge.To(), storage::View::OLD, memgraph::query::AuthQuery::FineGrainedPrivilege::READ))) { @@ -1284,7 +1283,7 @@ class STShortestPathCursor : public query::plan::Cursor { auto in_edges = UnwrapEdgesResult(vertex.InEdges(storage::View::OLD, self_.common_.edge_types)); for (const auto &edge : in_edges) { #ifdef MG_ENTERPRISE - if (utils::license::global_license_checker.IsValidLicenseFast() && context.auth_checker && + if (license::global_license_checker.IsEnterpriseValidFast() && context.auth_checker && !(context.auth_checker->Has(edge, memgraph::query::AuthQuery::FineGrainedPrivilege::READ) && context.auth_checker->Has(edge.From(), storage::View::OLD, memgraph::query::AuthQuery::FineGrainedPrivilege::READ))) { @@ -1324,7 +1323,7 @@ class STShortestPathCursor : public query::plan::Cursor { auto out_edges = UnwrapEdgesResult(vertex.OutEdges(storage::View::OLD, self_.common_.edge_types)); for (const auto &edge : out_edges) { #ifdef MG_ENTERPRISE - if (utils::license::global_license_checker.IsValidLicenseFast() && context.auth_checker && + if (license::global_license_checker.IsEnterpriseValidFast() && context.auth_checker && !(context.auth_checker->Has(edge, memgraph::query::AuthQuery::FineGrainedPrivilege::READ) && context.auth_checker->Has(edge.To(), storage::View::OLD, memgraph::query::AuthQuery::FineGrainedPrivilege::READ))) { @@ -1349,7 +1348,7 @@ class STShortestPathCursor : public query::plan::Cursor { auto in_edges = UnwrapEdgesResult(vertex.InEdges(storage::View::OLD, self_.common_.edge_types)); for (const auto &edge : in_edges) { #ifdef MG_ENTERPRISE - if (utils::license::global_license_checker.IsValidLicenseFast() && context.auth_checker && + if (license::global_license_checker.IsEnterpriseValidFast() && context.auth_checker && !(context.auth_checker->Has(edge, memgraph::query::AuthQuery::FineGrainedPrivilege::READ) && context.auth_checker->Has(edge.From(), storage::View::OLD, memgraph::query::AuthQuery::FineGrainedPrivilege::READ))) { @@ -1406,7 +1405,7 @@ class SingleSourceShortestPathCursor : public query::plan::Cursor { // if we already processed the given vertex it doesn't get expanded if (processed_.find(vertex) != processed_.end()) return; #ifdef MG_ENTERPRISE - if (utils::license::global_license_checker.IsValidLicenseFast() && context.auth_checker && + if (license::global_license_checker.IsEnterpriseValidFast() && context.auth_checker && !(context.auth_checker->Has(vertex, storage::View::OLD, memgraph::query::AuthQuery::FineGrainedPrivilege::READ) && context.auth_checker->Has(edge, memgraph::query::AuthQuery::FineGrainedPrivilege::READ))) { @@ -1592,7 +1591,7 @@ class ExpandWeightedShortestPathCursor : public query::plan::Cursor { int64_t depth) { auto *memory = evaluator.GetMemoryResource(); #ifdef MG_ENTERPRISE - if (utils::license::global_license_checker.IsValidLicenseFast() && context.auth_checker && + if (license::global_license_checker.IsEnterpriseValidFast() && context.auth_checker && !(context.auth_checker->Has(vertex, storage::View::OLD, memgraph::query::AuthQuery::FineGrainedPrivilege::READ) && context.auth_checker->Has(edge, memgraph::query::AuthQuery::FineGrainedPrivilege::READ))) { @@ -1902,7 +1901,7 @@ class ExpandAllShortestPathsCursor : public query::plan::Cursor { auto out_edges = UnwrapEdgesResult(vertex.OutEdges(storage::View::OLD, self_.common_.edge_types)); for (const auto &edge : out_edges) { #ifdef MG_ENTERPRISE - if (utils::license::global_license_checker.IsValidLicenseFast() && context.auth_checker && + if (license::global_license_checker.IsEnterpriseValidFast() && context.auth_checker && !(context.auth_checker->Has(edge.To(), storage::View::OLD, memgraph::query::AuthQuery::FineGrainedPrivilege::READ) && context.auth_checker->Has(edge, memgraph::query::AuthQuery::FineGrainedPrivilege::READ))) { @@ -1916,7 +1915,7 @@ class ExpandAllShortestPathsCursor : public query::plan::Cursor { auto in_edges = UnwrapEdgesResult(vertex.InEdges(storage::View::OLD, self_.common_.edge_types)); for (const auto &edge : in_edges) { #ifdef MG_ENTERPRISE - if (utils::license::global_license_checker.IsValidLicenseFast() && context.auth_checker && + if (license::global_license_checker.IsEnterpriseValidFast() && context.auth_checker && !(context.auth_checker->Has(edge.From(), storage::View::OLD, memgraph::query::AuthQuery::FineGrainedPrivilege::READ) && context.auth_checker->Has(edge, memgraph::query::AuthQuery::FineGrainedPrivilege::READ))) { @@ -2366,7 +2365,7 @@ bool Delete::DeleteCursor::Pull(Frame &frame, ExecutionContext &context) { if (expression_result.type() == TypedValue::Type::Edge) { auto &ea = expression_result.ValueEdge(); #ifdef MG_ENTERPRISE - if (utils::license::global_license_checker.IsValidLicenseFast() && context.auth_checker && + if (license::global_license_checker.IsEnterpriseValidFast() && context.auth_checker && !(context.auth_checker->Has(ea, query::AuthQuery::FineGrainedPrivilege::CREATE_DELETE) && context.auth_checker->Has(ea.To(), storage::View::NEW, query::AuthQuery::FineGrainedPrivilege::UPDATE) && context.auth_checker->Has(ea.From(), storage::View::NEW, query::AuthQuery::FineGrainedPrivilege::UPDATE))) { @@ -2399,7 +2398,7 @@ bool Delete::DeleteCursor::Pull(Frame &frame, ExecutionContext &context) { case TypedValue::Type::Vertex: { auto &va = expression_result.ValueVertex(); #ifdef MG_ENTERPRISE - if (utils::license::global_license_checker.IsValidLicenseFast() && context.auth_checker && + if (license::global_license_checker.IsEnterpriseValidFast() && context.auth_checker && !context.auth_checker->Has(va, storage::View::NEW, query::AuthQuery::FineGrainedPrivilege::CREATE_DELETE)) { throw QueryRuntimeException("Vertex not deleted due to not having enough permission!"); } @@ -2508,7 +2507,7 @@ bool SetProperty::SetPropertyCursor::Pull(Frame &frame, ExecutionContext &contex switch (lhs.type()) { case TypedValue::Type::Vertex: { #ifdef MG_ENTERPRISE - if (utils::license::global_license_checker.IsValidLicenseFast() && context.auth_checker && + if (license::global_license_checker.IsEnterpriseValidFast() && context.auth_checker && !context.auth_checker->Has(lhs.ValueVertex(), storage::View::NEW, memgraph::query::AuthQuery::FineGrainedPrivilege::UPDATE)) { throw QueryRuntimeException("Vertex property not set due to not having enough permission!"); @@ -2525,7 +2524,7 @@ bool SetProperty::SetPropertyCursor::Pull(Frame &frame, ExecutionContext &contex } case TypedValue::Type::Edge: { #ifdef MG_ENTERPRISE - if (utils::license::global_license_checker.IsValidLicenseFast() && context.auth_checker && + if (license::global_license_checker.IsEnterpriseValidFast() && context.auth_checker && !context.auth_checker->Has(lhs.ValueEdge(), memgraph::query::AuthQuery::FineGrainedPrivilege::UPDATE)) { throw QueryRuntimeException("Edge property not set due to not having enough permission!"); } @@ -2724,7 +2723,7 @@ bool SetProperties::SetPropertiesCursor::Pull(Frame &frame, ExecutionContext &co switch (lhs.type()) { case TypedValue::Type::Vertex: #ifdef MG_ENTERPRISE - if (utils::license::global_license_checker.IsValidLicenseFast() && context.auth_checker && + if (license::global_license_checker.IsEnterpriseValidFast() && context.auth_checker && !context.auth_checker->Has(lhs.ValueVertex(), storage::View::NEW, memgraph::query::AuthQuery::FineGrainedPrivilege::UPDATE)) { throw QueryRuntimeException("Vertex properties not set due to not having enough permission!"); @@ -2735,7 +2734,7 @@ bool SetProperties::SetPropertiesCursor::Pull(Frame &frame, ExecutionContext &co break; case TypedValue::Type::Edge: #ifdef MG_ENTERPRISE - if (utils::license::global_license_checker.IsValidLicenseFast() && context.auth_checker && + if (license::global_license_checker.IsEnterpriseValidFast() && context.auth_checker && !context.auth_checker->Has(lhs.ValueEdge(), memgraph::query::AuthQuery::FineGrainedPrivilege::UPDATE)) { throw QueryRuntimeException("Edge properties not set due to not having enough permission!"); } @@ -2778,7 +2777,7 @@ bool SetLabels::SetLabelsCursor::Pull(Frame &frame, ExecutionContext &context) { SCOPED_PROFILE_OP("SetLabels"); #ifdef MG_ENTERPRISE - if (utils::license::global_license_checker.IsValidLicenseFast() && context.auth_checker && + if (license::global_license_checker.IsEnterpriseValidFast() && context.auth_checker && !context.auth_checker->Has(self_.labels_, memgraph::query::AuthQuery::FineGrainedPrivilege::CREATE_DELETE)) { throw QueryRuntimeException("Couldn't set label due to not having enough permission!"); } @@ -2793,7 +2792,7 @@ bool SetLabels::SetLabelsCursor::Pull(Frame &frame, ExecutionContext &context) { auto &vertex = vertex_value.ValueVertex(); #ifdef MG_ENTERPRISE - if (utils::license::global_license_checker.IsValidLicenseFast() && context.auth_checker && + if (license::global_license_checker.IsEnterpriseValidFast() && context.auth_checker && !context.auth_checker->Has(vertex, storage::View::OLD, memgraph::query::AuthQuery::FineGrainedPrivilege::UPDATE)) { throw QueryRuntimeException("Couldn't set label due to not having enough permission!"); @@ -2883,7 +2882,7 @@ bool RemoveProperty::RemovePropertyCursor::Pull(Frame &frame, ExecutionContext & switch (lhs.type()) { case TypedValue::Type::Vertex: #ifdef MG_ENTERPRISE - if (utils::license::global_license_checker.IsValidLicenseFast() && context.auth_checker && + if (license::global_license_checker.IsEnterpriseValidFast() && context.auth_checker && !context.auth_checker->Has(lhs.ValueVertex(), storage::View::NEW, memgraph::query::AuthQuery::FineGrainedPrivilege::UPDATE)) { throw QueryRuntimeException("Vertex property not removed due to not having enough permission!"); @@ -2893,7 +2892,7 @@ bool RemoveProperty::RemovePropertyCursor::Pull(Frame &frame, ExecutionContext & break; case TypedValue::Type::Edge: #ifdef MG_ENTERPRISE - if (utils::license::global_license_checker.IsValidLicenseFast() && context.auth_checker && + if (license::global_license_checker.IsEnterpriseValidFast() && context.auth_checker && !context.auth_checker->Has(lhs.ValueEdge(), memgraph::query::AuthQuery::FineGrainedPrivilege::UPDATE)) { throw QueryRuntimeException("Edge property not removed due to not having enough permission!"); } @@ -2936,7 +2935,7 @@ bool RemoveLabels::RemoveLabelsCursor::Pull(Frame &frame, ExecutionContext &cont SCOPED_PROFILE_OP("RemoveLabels"); #ifdef MG_ENTERPRISE - if (utils::license::global_license_checker.IsValidLicenseFast() && context.auth_checker && + if (license::global_license_checker.IsEnterpriseValidFast() && context.auth_checker && !context.auth_checker->Has(self_.labels_, memgraph::query::AuthQuery::FineGrainedPrivilege::CREATE_DELETE)) { throw QueryRuntimeException("Couldn't remove label due to not having enough permission!"); } @@ -2951,7 +2950,7 @@ bool RemoveLabels::RemoveLabelsCursor::Pull(Frame &frame, ExecutionContext &cont auto &vertex = vertex_value.ValueVertex(); #ifdef MG_ENTERPRISE - if (utils::license::global_license_checker.IsValidLicenseFast() && context.auth_checker && + if (license::global_license_checker.IsEnterpriseValidFast() && context.auth_checker && !context.auth_checker->Has(vertex, storage::View::OLD, memgraph::query::AuthQuery::FineGrainedPrivilege::UPDATE)) { throw QueryRuntimeException("Couldn't remove label due to not having enough permission!"); diff --git a/src/query/procedure/mg_procedure_impl.cpp b/src/query/procedure/mg_procedure_impl.cpp index 075496982..01ed39012 100644 --- a/src/query/procedure/mg_procedure_impl.cpp +++ b/src/query/procedure/mg_procedure_impl.cpp @@ -22,6 +22,7 @@ #include #include +#include "license/license.hpp" #include "mg_procedure.h" #include "module.hpp" #include "query/frontend/ast/ast.hpp" @@ -32,7 +33,6 @@ #include "storage/v2/view.hpp" #include "utils/algorithm.hpp" #include "utils/concepts.hpp" -#include "utils/license.hpp" #include "utils/logging.hpp" #include "utils/math.hpp" #include "utils/memory.hpp" @@ -1653,7 +1653,7 @@ mgp_error mgp_vertex_set_property(struct mgp_vertex *v, const char *property_nam auto *ctx = v->graph->ctx; #ifdef MG_ENTERPRISE - if (memgraph::utils::license::global_license_checker.IsValidLicenseFast() && ctx && ctx->auth_checker && + if (memgraph::license::global_license_checker.IsEnterpriseValidFast() && ctx && ctx->auth_checker && !ctx->auth_checker->Has(v->getImpl(), v->graph->view, memgraph::query::AuthQuery::FineGrainedPrivilege::UPDATE)) { throw AuthorizationException{"Insufficient permissions for setting a property on vertex!"}; @@ -1706,7 +1706,7 @@ mgp_error mgp_vertex_add_label(struct mgp_vertex *v, mgp_label label) { const auto label_id = std::visit([label](auto *impl) { return impl->NameToLabel(label.name); }, v->graph->impl); #ifdef MG_ENTERPRISE - if (memgraph::utils::license::global_license_checker.IsValidLicenseFast() && ctx && ctx->auth_checker && + if (memgraph::license::global_license_checker.IsEnterpriseValidFast() && ctx && ctx->auth_checker && !(ctx->auth_checker->Has(v->getImpl(), v->graph->view, memgraph::query::AuthQuery::FineGrainedPrivilege::UPDATE) && ctx->auth_checker->Has({label_id}, memgraph::query::AuthQuery::FineGrainedPrivilege::CREATE_DELETE))) { @@ -1750,7 +1750,7 @@ mgp_error mgp_vertex_remove_label(struct mgp_vertex *v, mgp_label label) { const auto label_id = std::visit([&label](auto *impl) { return impl->NameToLabel(label.name); }, v->graph->impl); #ifdef MG_ENTERPRISE - if (memgraph::utils::license::global_license_checker.IsValidLicenseFast() && ctx && ctx->auth_checker && + if (memgraph::license::global_license_checker.IsEnterpriseValidFast() && ctx && ctx->auth_checker && !(ctx->auth_checker->Has(v->getImpl(), v->graph->view, memgraph::query::AuthQuery::FineGrainedPrivilege::UPDATE) && ctx->auth_checker->Has({label_id}, memgraph::query::AuthQuery::FineGrainedPrivilege::CREATE_DELETE))) { @@ -1989,7 +1989,7 @@ mgp_error mgp_vertex_iter_in_edges(mgp_vertex *v, mgp_memory *memory, mgp_edges_ it->in.emplace(std::move(*maybe_edges)); it->in_it.emplace(it->in->begin()); #ifdef MG_ENTERPRISE - if (memgraph::utils::license::global_license_checker.IsValidLicenseFast()) { + if (memgraph::license::global_license_checker.IsEnterpriseValidFast()) { NextPermittedEdge(*it, true); } #endif @@ -2041,7 +2041,7 @@ mgp_error mgp_vertex_iter_out_edges(mgp_vertex *v, mgp_memory *memory, mgp_edges it->out_it.emplace(it->out->begin()); #ifdef MG_ENTERPRISE - if (memgraph::utils::license::global_license_checker.IsValidLicenseFast()) { + if (memgraph::license::global_license_checker.IsEnterpriseValidFast()) { NextPermittedEdge(*it, false); } #endif @@ -2099,7 +2099,7 @@ mgp_error mgp_edges_iterator_next(mgp_edges_iterator *it, mgp_edge **result) { ++*impl_it; #ifdef MG_ENTERPRISE - if (memgraph::utils::license::global_license_checker.IsValidLicenseFast()) { + if (memgraph::license::global_license_checker.IsEnterpriseValidFast()) { NextPermittedEdge(*it, for_in); } #endif @@ -2202,7 +2202,7 @@ mgp_error mgp_edge_set_property(struct mgp_edge *e, const char *property_name, m auto *ctx = e->from.graph->ctx; #ifdef MG_ENTERPRISE - if (memgraph::utils::license::global_license_checker.IsValidLicenseFast() && ctx && ctx->auth_checker && + if (memgraph::license::global_license_checker.IsEnterpriseValidFast() && ctx && ctx->auth_checker && !ctx->auth_checker->Has(e->impl, memgraph::query::AuthQuery::FineGrainedPrivilege::UPDATE)) { throw AuthorizationException{"Insufficient permissions for setting a property on edge!"}; } @@ -2310,7 +2310,7 @@ mgp_error mgp_graph_create_vertex(struct mgp_graph *graph, mgp_memory *memory, m [=]() -> mgp_vertex * { #ifdef MG_ENTERPRISE - if (memgraph::utils::license::global_license_checker.IsValidLicenseFast() && graph->ctx && + if (memgraph::license::global_license_checker.IsEnterpriseValidFast() && graph->ctx && graph->ctx->auth_checker && !graph->ctx->auth_checker->HasGlobalPrivilegeOnVertices( memgraph::query::AuthQuery::FineGrainedPrivilege::CREATE_DELETE)) { @@ -2340,7 +2340,7 @@ mgp_error mgp_graph_delete_vertex(struct mgp_graph *graph, mgp_vertex *vertex) { auto *ctx = graph->ctx; #ifdef MG_ENTERPRISE - if (memgraph::utils::license::global_license_checker.IsValidLicenseFast() && ctx && ctx->auth_checker && + if (memgraph::license::global_license_checker.IsEnterpriseValidFast() && ctx && ctx->auth_checker && !ctx->auth_checker->Has(vertex->getImpl(), graph->view, memgraph::query::AuthQuery::FineGrainedPrivilege::CREATE_DELETE)) { throw AuthorizationException{"Insufficient permissions for deleting a vertex!"}; @@ -2391,7 +2391,7 @@ mgp_error mgp_graph_detach_delete_vertex(struct mgp_graph *graph, mgp_vertex *ve return WrapExceptions([=] { auto *ctx = graph->ctx; #ifdef MG_ENTERPRISE - if (memgraph::utils::license::global_license_checker.IsValidLicenseFast() && ctx && ctx->auth_checker && + if (memgraph::license::global_license_checker.IsEnterpriseValidFast() && ctx && ctx->auth_checker && !ctx->auth_checker->Has(vertex->getImpl(), graph->view, memgraph::query::AuthQuery::FineGrainedPrivilege::CREATE_DELETE)) { throw AuthorizationException{"Insufficient permissions for deleting a vertex!"}; @@ -2455,7 +2455,7 @@ mgp_error mgp_graph_create_edge(mgp_graph *graph, mgp_vertex *from, mgp_vertex * #ifdef MG_ENTERPRISE const auto edge_id = std::visit([type](auto *impl) { return impl->NameToEdgeType(type.name); }, from->graph->impl); - if (memgraph::utils::license::global_license_checker.IsValidLicenseFast() && ctx && ctx->auth_checker && + if (memgraph::license::global_license_checker.IsEnterpriseValidFast() && ctx && ctx->auth_checker && !ctx->auth_checker->Has(edge_id, memgraph::query::AuthQuery::FineGrainedPrivilege::CREATE_DELETE)) { throw AuthorizationException{"Insufficient permissions for creating edges!"}; } @@ -2516,7 +2516,7 @@ mgp_error mgp_graph_delete_edge(struct mgp_graph *graph, mgp_edge *edge) { return WrapExceptions([=] { auto *ctx = graph->ctx; #ifdef MG_ENTERPRISE - if (memgraph::utils::license::global_license_checker.IsValidLicenseFast() && ctx && ctx->auth_checker && + if (memgraph::license::global_license_checker.IsEnterpriseValidFast() && ctx && ctx->auth_checker && !ctx->auth_checker->Has(edge->impl, memgraph::query::AuthQuery::FineGrainedPrivilege::CREATE_DELETE)) { throw AuthorizationException{"Insufficient permissions for deleting an edge!"}; } @@ -2578,7 +2578,7 @@ mgp_vertices_iterator::mgp_vertices_iterator(mgp_graph *graph, memgraph::utils:: vertices(std::visit([graph](auto *impl) { return impl->Vertices(graph->view); }, graph->impl)), current_it(vertices.begin()) { #ifdef MG_ENTERPRISE - if (memgraph::utils::license::global_license_checker.IsValidLicenseFast()) { + if (memgraph::license::global_license_checker.IsEnterpriseValidFast()) { NextPermitted(*this); } #endif @@ -2627,7 +2627,7 @@ mgp_error mgp_vertices_iterator_next(mgp_vertices_iterator *it, mgp_vertex **res ++it->current_it; #ifdef MG_ENTERPRISE - if (memgraph::utils::license::global_license_checker.IsValidLicenseFast()) { + if (memgraph::license::global_license_checker.IsEnterpriseValidFast()) { NextPermitted(*it); } #endif diff --git a/src/telemetry/CMakeLists.txt b/src/telemetry/CMakeLists.txt index 43597554f..af3a720ba 100644 --- a/src/telemetry/CMakeLists.txt +++ b/src/telemetry/CMakeLists.txt @@ -1,12 +1,12 @@ set(telemetry_src_files - collectors.cpp - telemetry.cpp - system_info.cpp) + collectors.cpp + telemetry.cpp) -add_library(telemetry_lib STATIC ${telemetry_src_files}) -target_link_libraries(telemetry_lib mg-requests mg-kvstore mg-utils) +add_library(mg-telemetry STATIC ${telemetry_src_files}) +target_link_libraries(mg-telemetry mg-requests mg-kvstore mg-utils) option(MG_TELEMETRY_ID_OVERRIDE "Override for the telemetry ID" STRING) -if (MG_TELEMETRY_ID_OVERRIDE) + +if(MG_TELEMETRY_ID_OVERRIDE) message(WARNING "Using telemetry ID override: ${MG_TELEMETRY_ID_OVERRIDE}") - target_compile_definitions(telemetry_lib PRIVATE MG_TELEMETRY_ID_OVERRIDE="${MG_TELEMETRY_ID_OVERRIDE}") + target_compile_definitions(mg-telemetry PRIVATE MG_TELEMETRY_ID_OVERRIDE="${MG_TELEMETRY_ID_OVERRIDE}") endif() diff --git a/src/telemetry/telemetry.cpp b/src/telemetry/telemetry.cpp index 464e16d9f..6963f7676 100644 --- a/src/telemetry/telemetry.cpp +++ b/src/telemetry/telemetry.cpp @@ -17,38 +17,24 @@ #include "requests/requests.hpp" #include "telemetry/collectors.hpp" -#include "telemetry/system_info.hpp" #include "utils/file.hpp" #include "utils/logging.hpp" +#include "utils/system_info.hpp" #include "utils/timestamp.hpp" #include "utils/uuid.hpp" namespace memgraph::telemetry { -namespace { -std::string GetMachineId() { -#ifdef MG_TELEMETRY_ID_OVERRIDE - return MG_TELEMETRY_ID_OVERRIDE; -#else - // We assume we're on linux and we need to read the machine id from /etc/machine-id - const auto machine_id_lines = utils::ReadLines("/etc/machine-id"); - if (machine_id_lines.size() != 1) { - return "UNKNOWN"; - } - return machine_id_lines[0]; -#endif -} -} // namespace -const int kMaxBatchSize = 100; +constexpr auto kMaxBatchSize{100}; -Telemetry::Telemetry(std::string url, std::filesystem::path storage_directory, +Telemetry::Telemetry(std::string url, std::filesystem::path storage_directory, std::string uuid, std::string machine_id, std::chrono::duration refresh_interval, const uint64_t send_every_n) : url_(std::move(url)), - uuid_(utils::GenerateUUID()), - machine_id_(GetMachineId()), + uuid_(uuid), + machine_id_(machine_id), send_every_n_(send_every_n), storage_(std::move(storage_directory)) { - StoreData("startup", GetSystemInfo()); + StoreData("startup", utils::GetSystemInfo()); AddCollector("resources", GetResourceUsage); AddCollector("uptime", [&]() -> nlohmann::json { return GetUptime(); }); scheduler_.Run("Telemetry", refresh_interval, [&] { CollectData(); }); @@ -59,19 +45,15 @@ void Telemetry::AddCollector(const std::string &name, const std::function refresh_interval = std::chrono::minutes(10), uint64_t send_every_n = 10); void AddCollector(const std::string &name, const std::function &func); - /// Required to expose run_id to Bolt server. - std::string GetRunId() const; - ~Telemetry(); Telemetry(const Telemetry &) = delete; diff --git a/src/utils/CMakeLists.txt b/src/utils/CMakeLists.txt index 1af78b426..727379bfe 100644 --- a/src/utils/CMakeLists.txt +++ b/src/utils/CMakeLists.txt @@ -14,6 +14,7 @@ set(utils_src_files thread.cpp thread_pool.cpp tsc.cpp + system_info.cpp uuid.cpp) find_package(Boost REQUIRED) @@ -23,16 +24,10 @@ find_package(Threads REQUIRED) add_library(mg-utils STATIC ${utils_src_files}) target_link_libraries(mg-utils PUBLIC Boost::headers fmt::fmt spdlog::spdlog) -target_link_libraries(mg-utils PRIVATE librdtsc stdc++fs Threads::Threads gflags uuid rt) +target_link_libraries(mg-utils PRIVATE librdtsc stdc++fs Threads::Threads gflags json uuid rt) set(settings_src_files settings.cpp) add_library(mg-settings STATIC ${settings_src_files}) target_link_libraries(mg-settings mg-kvstore mg-slk mg-utils) - -set(license_src_files - license.cpp) -add_library(mg-license STATIC ${license_src_files}) -target_link_libraries(mg-license mg-settings mg-utils) - diff --git a/src/utils/stat.hpp b/src/utils/stat.hpp index c8a683a53..a9b9bbee5 100644 --- a/src/utils/stat.hpp +++ b/src/utils/stat.hpp @@ -43,7 +43,7 @@ inline uint64_t GetMemoryUsage() { pid_t pid = getpid(); uint64_t memory = 0; auto statm_data = utils::ReadLines(fmt::format("/proc/{}/statm", pid)); - if (statm_data.size() >= 1) { + if (!statm_data.empty()) { auto split = utils::Split(statm_data[0]); if (split.size() >= 2) { memory = std::stoull(split[1]) * sysconf(_SC_PAGESIZE); diff --git a/src/telemetry/system_info.cpp b/src/utils/system_info.cpp similarity index 63% rename from src/telemetry/system_info.cpp rename to src/utils/system_info.cpp index 735dda3eb..f30683b8e 100644 --- a/src/telemetry/system_info.cpp +++ b/src/utils/system_info.cpp @@ -9,56 +9,35 @@ // by the Apache License, Version 2.0, included in the file // licenses/APL.txt. -#include "telemetry/system_info.hpp" +#include "utils/system_info.hpp" #include -#include - #include +#include #include "utils/file.hpp" #include "utils/string.hpp" -namespace memgraph::telemetry { +namespace memgraph::utils { -const nlohmann::json GetSystemInfo() { - // Get `uname`. - struct utsname info; - if (uname(&info) != 0) return {}; - - // Parse `/etc/os-release`. - std::string os_name, os_version, os_full; - auto os_data = utils::ReadLines("/etc/os-release"); - for (auto &row : os_data) { - auto split = utils::Split(row, "="); - if (split.size() < 2) continue; - if (split[0] == "NAME") { - os_name = utils::Trim(split[1], "\""); - } else if (split[0] == "VERSION") { - os_version = utils::Trim(split[1], "\""); - } - os_full = fmt::format("{} {}", os_name, os_version); - } - - // Parse `/proc/cpuinfo`. - std::string cpu_model; - uint64_t cpu_count = 0; - auto cpu_data = utils::ReadLines("/proc/cpuinfo"); - for (auto &row : cpu_data) { - auto tmp = utils::Trim(row); - if (tmp == "") { - ++cpu_count; - } else if (utils::StartsWith(tmp, "model name")) { - auto split = utils::Split(tmp, ":"); - if (split.size() != 2) continue; - cpu_model = utils::Trim(split[1]); - } +std::string GetMachineId() { +#ifdef MG_TELEMETRY_ID_OVERRIDE + return MG_TELEMETRY_ID_OVERRIDE; +#else + // We assume we're on linux and we need to read the machine id from /etc/machine-id + const auto machine_id_lines = memgraph::utils::ReadLines("/etc/machine-id"); + if (machine_id_lines.size() != 1) { + return "UNKNOWN"; } + return machine_id_lines[0]; +#endif +} +MemoryInfo GetMemoryInfo() { // Parse `/proc/meminfo`. - nlohmann::json ret; - uint64_t memory = 0, swap = 0; + uint64_t memory{0}; + uint64_t swap{0}; auto mem_data = utils::ReadLines("/proc/meminfo"); for (auto &row : mem_data) { auto tmp = utils::Trim(row); @@ -74,15 +53,55 @@ const nlohmann::json GetSystemInfo() { } memory *= 1024; swap *= 1024; - - return {{"architecture", info.machine}, - {"cpu_count", cpu_count}, - {"cpu_model", cpu_model}, - {"kernel", fmt::format("{} {}", info.release, info.version)}, - {"memory", memory}, - {"os", os_full}, - {"swap", swap}, - {"version", gflags::VersionString()}}; + return {memory, swap}; } -} // namespace memgraph::telemetry +CPUInfo GetCPUInfo() { + // Parse `/proc/cpuinfo`. + std::string cpu_model; + uint64_t cpu_count{0}; + auto cpu_data = utils::ReadLines("/proc/cpuinfo"); + for (auto &row : cpu_data) { + auto tmp = utils::Trim(row); + if (tmp.empty()) { + ++cpu_count; + } else if (utils::StartsWith(tmp, "model name")) { + auto split = utils::Split(tmp, ":"); + if (split.size() != 2) continue; + cpu_model = utils::Trim(split[1]); + } + } + return {cpu_model, cpu_count}; +} + +nlohmann::json GetSystemInfo() { + // Get `uname`. + struct utsname info; + if (uname(&info) != 0) return {}; + + // Parse `/etc/os-release`. + std::string os_name; + std::string os_version; + std::string os_full; + auto os_data = utils::ReadLines("/etc/os-release"); + for (auto &row : os_data) { + auto split = utils::Split(row, "="); + if (split.size() < 2) continue; + if (split[0] == "NAME") { + os_name = utils::Trim(split[1], "\""); + } else if (split[0] == "VERSION") { + os_version = utils::Trim(split[1], "\""); + } + os_full = fmt::format("{} {}", os_name, os_version); + } + + const auto cpu_info = GetCPUInfo(); + const auto mem_info = GetMemoryInfo(); + + return {{"architecture", info.machine}, {"cpu_count", cpu_info.cpu_count}, + {"cpu_model", cpu_info.cpu_model}, {"kernel", fmt::format("{} {}", info.release, info.version)}, + {"memory", mem_info.memory}, {"os", os_full}, + {"swap", mem_info.swap}, {"version", gflags::VersionString()}}; +} + +} // namespace memgraph::utils diff --git a/src/telemetry/system_info.hpp b/src/utils/system_info.hpp similarity index 62% rename from src/telemetry/system_info.hpp rename to src/utils/system_info.hpp index efaa81bf4..dd29da3a1 100644 --- a/src/telemetry/system_info.hpp +++ b/src/utils/system_info.hpp @@ -11,16 +11,33 @@ #pragma once +#include +#include + #include -namespace memgraph::telemetry { +namespace memgraph::utils { -// TODO (mferencevic): merge with `utils/sysinfo` +struct MemoryInfo { + uint64_t memory; + uint64_t swap; +}; + +struct CPUInfo { + std::string cpu_model; + uint64_t cpu_count; +}; + +std::string GetMachineId(); + +MemoryInfo GetMemoryInfo(); + +CPUInfo GetCPUInfo(); /** - * This function returs a dictionary containing some basic system information + * This function return a dictionary containing some basic system information * (eg. operating system name, cpu information, memory information, etc.). */ -const nlohmann::json GetSystemInfo(); +nlohmann::json GetSystemInfo(); -} // namespace memgraph::telemetry +} // namespace memgraph::utils diff --git a/tests/integration/CMakeLists.txt b/tests/integration/CMakeLists.txt index 8b50421ad..21920afce 100644 --- a/tests/integration/CMakeLists.txt +++ b/tests/integration/CMakeLists.txt @@ -13,24 +13,6 @@ add_subdirectory(auth) # lba test binaries add_subdirectory(fine_grained_access) -## distributed ha/basic binaries -#add_subdirectory(ha/basic) -# -## distributed ha/constraints binaries -#add_subdirectory(ha/constraints) -# -## distributed ha/index binaries -#add_subdirectory(ha/index) -# -## distributed ha/large_log_entries binaries -#add_subdirectory(ha/large_log_entries) -# -## distributed ha/leader_election binaries -#add_subdirectory(ha/leader_election) -# -## distributed ha/term_updates binaries -#add_subdirectory(ha/term_updates) - # audit test binaries add_subdirectory(audit) @@ -39,3 +21,6 @@ add_subdirectory(ldap) # mg_import_csv test binaries add_subdirectory(mg_import_csv) + +# license_check test binaries +add_subdirectory(license_info) diff --git a/tests/integration/license_info/CMakeLists.txt b/tests/integration/license_info/CMakeLists.txt new file mode 100644 index 000000000..f3c954102 --- /dev/null +++ b/tests/integration/license_info/CMakeLists.txt @@ -0,0 +1,6 @@ +set(target_name memgraph__integration__license_info) +set(client_target_name ${target_name}__client) + +add_executable(${client_target_name} client.cpp) +set_target_properties(${client_target_name} PROPERTIES OUTPUT_NAME client) +target_link_libraries(${client_target_name} mg-requests mg-license mg-utils) diff --git a/tests/integration/license_info/client.cpp b/tests/integration/license_info/client.cpp new file mode 100644 index 000000000..2f0f00364 --- /dev/null +++ b/tests/integration/license_info/client.cpp @@ -0,0 +1,62 @@ +// Copyright 2022 Memgraph Ltd. +// +// Use of this software is governed by the Business Source License +// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source +// License, and you may not use this file except in compliance with the Business Source License. +// +// As of the Change Date specified in that file, in accordance with +// the Business Source License, use of this software will be governed +// by the Apache License, Version 2.0, included in the file +// licenses/APL.txt. + +#include +#include + +#include + +#include "license/license.hpp" +#include "license/license_sender.hpp" +#include "requests/requests.hpp" +#include "spdlog/spdlog.h" +#include "utils/logging.hpp" +#include "utils/synchronized.hpp" +#include "utils/system_info.hpp" +#include "utils/uuid.hpp" + +DEFINE_string(endpoint, "http://127.0.0.1:5500/", "Endpoint that should be used for the test."); +DEFINE_string(license_type, "enterprise", "License type; can be oem or enterprise."); +DEFINE_int64(interval, 1, "Interval used for reporting telemetry in seconds."); +DEFINE_int64(duration, 10, "Duration of the test in seconds."); + +memgraph::license::LicenseType StringToLicenseType(const std::string_view license_type) { + if (license_type == "enterprise") { + return memgraph::license::LicenseType::ENTERPRISE; + } + if (license_type == "oem") { + return memgraph::license::LicenseType::OEM; + } + spdlog::critical("Invalid license type!"); + std::terminate(); +} + +int main(int argc, char **argv) { + gflags::SetVersionString("license-info"); + gflags::ParseCommandLineFlags(&argc, &argv, true); + + memgraph::requests::Init(); + + memgraph::license::License license{"Memgraph", 0, 0, StringToLicenseType(FLAGS_license_type)}; + memgraph::utils::Synchronized, memgraph::utils::SpinLock> license_info{ + memgraph::license::LicenseInfo{"mg-testkey", "Memgraph"}}; + license_info.WithLock([license = std::move(license)](auto &license_info) { + license_info->license = license; + license_info->is_valid = true; + }); + + memgraph::license::LicenseInfoSender license_sender(FLAGS_endpoint, memgraph::utils::GenerateUUID(), + memgraph::utils::GetMachineId(), 10000000, license_info, + std::chrono::seconds(FLAGS_interval)); + std::this_thread::sleep_for(std::chrono::seconds(FLAGS_duration)); + + return 0; +} diff --git a/tests/integration/license_info/runner.py b/tests/integration/license_info/runner.py new file mode 100755 index 000000000..9a794c4ca --- /dev/null +++ b/tests/integration/license_info/runner.py @@ -0,0 +1,96 @@ +#!/usr/bin/python3 -u + +# Copyright 2021 Memgraph Ltd. +# +# Use of this software is governed by the Business Source License +# included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source +# License, and you may not use this file except in compliance with the Business Source License. +# +# As of the Change Date specified in that file, in accordance with +# the Business Source License, use of this software will be governed +# by the Apache License, Version 2.0, included in the file +# licenses/APL.txt. + +import argparse +import json +import os +import subprocess +import sys +import time + +SCRIPT_DIR = os.path.dirname(os.path.realpath(__file__)) +PROJECT_DIR = os.path.normpath(os.path.join(SCRIPT_DIR, "..", "..", "..")) + + +def execute_test(**kwargs): + client_binary = kwargs.pop("client") + server_binary = kwargs.pop("server") + + start_server = kwargs.pop("start_server", True) + interval = kwargs.pop("interval", 1) + duration = kwargs.pop("duration", 5) + license_type = kwargs.pop("license-type", "enterprise") + + timeout = duration * 2 if "hang" not in kwargs else duration * 2 + 60 + success = False + + client_args = [client_binary, "--interval", interval, "--duration", duration, "--license-type", license_type] + + server = None + if start_server: + server = subprocess.Popen(server_binary) + time.sleep(0.4) + assert server.poll() is None, "Server process died prematurely!" + + try: + subprocess.run(list(map(str, client_args)), timeout=timeout, check=True) + finally: + if server is None: + success = True + else: + server.terminate() + try: + success = server.wait(timeout=5) == 0 + success = True + except subprocess.TimeoutExpired: + server.kill() + return success + + +def main(): + server_binary = os.path.join(SCRIPT_DIR, "server.py") + client_binary = os.path.join(PROJECT_DIR, "build", "tests", "integration", "license_info", "client") + + parser = argparse.ArgumentParser() + parser.add_argument("--client", default=client_binary) + parser.add_argument("--server", default=server_binary) + parser.add_argument("--server-url", default="127.0.0.1") + parser.add_argument("--server-port", default="5500") + args = parser.parse_args() + + tests = [ + {"interval": 2}, + {"duration": 10}, + {"interval": 2, "duration": 10}, + {"license-type": "oem"}, + {"license-type": "enterprise"}, + ] + for test in tests: + print("\033[1;36m~~ Executing test with arguments:", json.dumps(test, sort_keys=True), "~~\033[0m") + + try: + success = execute_test(client=args.client, server=args.server, **test) + except Exception as e: + print("\033[1;33m", e, "\033[0m", sep="") + success = False + + if not success: + print("\033[1;31m~~", "Test failed!", "~~\033[0m") + sys.exit(1) + else: + print("\033[1;32m~~", "Test ok!", "~~\033[0m") + sys.exit(0) + + +if __name__ == "__main__": + main() diff --git a/tests/integration/license_info/server.py b/tests/integration/license_info/server.py new file mode 100755 index 000000000..df62fbb84 --- /dev/null +++ b/tests/integration/license_info/server.py @@ -0,0 +1,69 @@ +#!/usr/bin/python3 -u + +# Copyright 2021 Memgraph Ltd. +# +# Use of this software is governed by the Business Source License +# included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source +# License, and you may not use this file except in compliance with the Business Source License. +# +# As of the Change Date specified in that file, in accordance with +# the Business Source License, use of this software will be governed +# by the Apache License, Version 2.0, included in the file +# licenses/APL.txt. + +import argparse +import json +from http.server import HTTPServer, SimpleHTTPRequestHandler + +EXPECTED_LICENSE_INFO_FIELDS = { + "run_id": str, + "machine_id": str, + "type": str, + "license_type": str, + "license_key": str, + "organization": str, + "valid": bool, + "physical_memory_size": int, + "swap_memory_size": int, + "memory_used": int, + "runtime_memory_limit": int, + "license_memory_limit": int, + "timestamp": float, +} + + +class ServerHandler(SimpleHTTPRequestHandler): + def do_POST(self): + assert self.headers["user-agent"] == "memgraph/license-info", f"The header is {self.headers['user-agent']}" + assert self.headers["accept"] == "application/json", f"The header is {self.headers['accept']}" + assert self.headers["content-type"] == "application/json", f"The header is {self.headers['content-type']}" + + content_len = int(self.headers.get("content-length", 0)) + data = json.loads(self.rfile.read(content_len).decode("utf-8")) + + assert isinstance(data, dict) + + for expected_field, expected_type in EXPECTED_LICENSE_INFO_FIELDS.items(): + assert expected_field in data, f"Field {expected_field} not found in received data" + assert isinstance( + data[expected_field], expected_type + ), f"Field {expected_field} is not correct type: expected {expected_type} got {type(data[expected_field])}" + assert len(EXPECTED_LICENSE_INFO_FIELDS) == len(data), "Expected data size does not match received" + + self.send_response(200) + self.end_headers() + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument("--address", type=str, default="127.0.0.1") + parser.add_argument("--port", type=int, default=5500) + args = parser.parse_args() + + with HTTPServer((args.address, args.port), ServerHandler) as srv: + print(f"Serving HTTP server at {args.address}:{args.port}") + srv.serve_forever() + + +if __name__ == "__main__": + main() diff --git a/tests/integration/telemetry/CMakeLists.txt b/tests/integration/telemetry/CMakeLists.txt index 68763cb6d..f55b9fb04 100644 --- a/tests/integration/telemetry/CMakeLists.txt +++ b/tests/integration/telemetry/CMakeLists.txt @@ -3,4 +3,4 @@ set(client_target_name ${target_name}__client) add_executable(${client_target_name} client.cpp) set_target_properties(${client_target_name} PROPERTIES OUTPUT_NAME client) -target_link_libraries(${client_target_name} mg-requests telemetry_lib) +target_link_libraries(${client_target_name} mg-requests mg-telemetry) diff --git a/tests/integration/telemetry/client.cpp b/tests/integration/telemetry/client.cpp index f9125aa5a..75f53dfbf 100644 --- a/tests/integration/telemetry/client.cpp +++ b/tests/integration/telemetry/client.cpp @@ -13,6 +13,8 @@ #include "requests/requests.hpp" #include "telemetry/telemetry.hpp" +#include "utils/system_info.hpp" +#include "utils/uuid.hpp" DEFINE_string(endpoint, "http://127.0.0.1:9000/", "Endpoint that should be used for the test."); DEFINE_int64(interval, 1, "Interval used for reporting telemetry in seconds."); @@ -24,8 +26,8 @@ int main(int argc, char **argv) { gflags::ParseCommandLineFlags(&argc, &argv, true); memgraph::requests::Init(); - memgraph::telemetry::Telemetry telemetry(FLAGS_endpoint, FLAGS_storage_directory, - std::chrono::seconds(FLAGS_interval), 1); + memgraph::telemetry::Telemetry telemetry(FLAGS_endpoint, FLAGS_storage_directory, memgraph::utils::GenerateUUID(), + memgraph::utils::GetMachineId(), std::chrono::seconds(FLAGS_interval), 1); uint64_t counter = 0; telemetry.AddCollector("db", [&counter]() -> nlohmann::json { diff --git a/tests/integration/telemetry/runner.py b/tests/integration/telemetry/runner.py index 6fa81d91f..0e9a589eb 100755 --- a/tests/integration/telemetry/runner.py +++ b/tests/integration/telemetry/runner.py @@ -36,8 +36,7 @@ def execute_test(**kwargs): timeout = duration * 2 if "hang" not in kwargs else duration * 2 + 60 success = False - server_args = [server_binary, "--interval", interval, - "--duration", duration] + server_args = [server_binary, "--interval", interval, "--duration", duration] for flag, value in kwargs.items(): flag = "--" + flag.replace("_", "-") # We handle boolean flags here. The type of value must be `bool`, and @@ -48,9 +47,15 @@ def execute_test(**kwargs): else: server_args.extend([flag, value]) - client_args = [client_binary, "--interval", interval, - "--duration", duration, - "--storage-directory", storage_directory] + client_args = [ + client_binary, + "--interval", + interval, + "--duration", + duration, + "--storage-directory", + storage_directory, + ] if endpoint: client_args.extend(["--endpoint", endpoint]) @@ -61,8 +66,7 @@ def execute_test(**kwargs): assert server.poll() is None, "Server process died prematurely!" try: - subprocess.run(list(map(str, client_args)), timeout=timeout, - check=True) + subprocess.run(list(map(str, client_args)), timeout=timeout, check=True) finally: if server is None: success = True @@ -88,16 +92,14 @@ TESTS = [ {"endpoint": "http://127.0.0.1:9000/nonexistant/", "no_check": True}, {"start_server": False}, {"startups": 4, "no_check_duration": True}, # the last 3 tests failed - # to send any data + this test - {"add_garbage": True} + # to send any data + this test + {"add_garbage": True}, ] if __name__ == "__main__": server_binary = os.path.join(SCRIPT_DIR, "server.py") - client_binary = os.path.join(PROJECT_DIR, "build", "tests", - "integration", "telemetry", "client") - kvstore_console_binary = os.path.join(PROJECT_DIR, "build", "tests", - "manual", "kvstore_console") + client_binary = os.path.join(PROJECT_DIR, "build", "tests", "integration", "telemetry", "client") + kvstore_console_binary = os.path.join(PROJECT_DIR, "build", "tests", "manual", "kvstore_console") parser = argparse.ArgumentParser() parser.add_argument("--client", default=client_binary) @@ -108,19 +110,17 @@ if __name__ == "__main__": storage = tempfile.TemporaryDirectory() for test in TESTS: - print("\033[1;36m~~ Executing test with arguments:", - json.dumps(test, sort_keys=True), "~~\033[0m") + print("\033[1;36m~~ Executing test with arguments:", json.dumps(test, sort_keys=True), "~~\033[0m") if test.pop("add_garbage", False): - proc = subprocess.Popen([args.kvstore_console, "--path", - storage.name], stdin=subprocess.PIPE, - stdout=subprocess.DEVNULL) + proc = subprocess.Popen( + [args.kvstore_console, "--path", storage.name], stdin=subprocess.PIPE, stdout=subprocess.DEVNULL + ) proc.communicate("put garbage garbage".encode("utf-8")) assert proc.wait() == 0 try: - success = execute_test(client=args.client, server=args.server, - storage=storage.name, **test) + success = execute_test(client=args.client, server=args.server, storage=storage.name, **test) except Exception as e: print("\033[1;33m", e, "\033[0m", sep="") success = False diff --git a/tests/integration/telemetry/server.py b/tests/integration/telemetry/server.py index 0fca6986d..3fa7eb716 100755 --- a/tests/integration/telemetry/server.py +++ b/tests/integration/telemetry/server.py @@ -12,13 +12,12 @@ # licenses/APL.txt. import argparse +import itertools import json import os import signal import sys import time -import itertools - from http.server import BaseHTTPRequestHandler, HTTPServer @@ -46,7 +45,7 @@ def build_handler(storage, args): assert self.headers["accept"] == "application/json" assert self.headers["content-type"] == "application/json" - content_len = int(self.headers.get('content-length', 0)) + content_len = int(self.headers.get("content-length", 0)) data = json.loads(self.rfile.read(content_len).decode("utf-8")) if self.path not in [args.path, args.redirect_path]: @@ -70,6 +69,7 @@ def build_handler(storage, args): assert type(item) == dict assert "event" in item assert "run_id" in item + assert "type" in item assert "machine_id" in item assert "data" in item assert "timestamp" in item @@ -188,11 +188,11 @@ if __name__ == "__main__": startups[-1].append(item) # Check that there were the correct number of startups. - assert len(startups) == args.startups + assert len(startups) == args.startups, f"Expected: {args.startups}, actual: {len(startups)}" # Verify each startup. for startup in startups: verify_storage(startup, args) # machine id has to be same for every run on the same machine - assert len(set(map(lambda x: x['machine_id'], itertools.chain(*startups)))) == 1 + assert len(set(map(lambda x: x["machine_id"], itertools.chain(*startups)))) == 1 diff --git a/tests/manual/single_query.cpp b/tests/manual/single_query.cpp index b48c8f74c..96407c41b 100644 --- a/tests/manual/single_query.cpp +++ b/tests/manual/single_query.cpp @@ -10,11 +10,11 @@ // licenses/APL.txt. #include "communication/result_stream_faker.hpp" +#include "license/license.hpp" #include "query/config.hpp" #include "query/interpreter.hpp" #include "storage/v2/isolation_level.hpp" #include "storage/v2/storage.hpp" -#include "utils/license.hpp" #include "utils/on_scope_exit.hpp" int main(int argc, char *argv[]) { @@ -30,7 +30,7 @@ int main(int argc, char *argv[]) { auto data_directory = std::filesystem::temp_directory_path() / "single_query_test"; memgraph::utils::OnScopeExit([&data_directory] { std::filesystem::remove_all(data_directory); }); - memgraph::utils::license::global_license_checker.EnableTesting(); + memgraph::license::global_license_checker.EnableTesting(); memgraph::query::InterpreterContext interpreter_context{&db, memgraph::query::InterpreterConfig{}, data_directory}; memgraph::query::Interpreter interpreter{&interpreter_context}; diff --git a/tests/unit/CMakeLists.txt b/tests/unit/CMakeLists.txt index 3831b6a9b..fe3cea930 100644 --- a/tests/unit/CMakeLists.txt +++ b/tests/unit/CMakeLists.txt @@ -269,8 +269,8 @@ target_link_libraries(${test_prefix}utils_csv_parsing mg-utils fmt) add_unit_test(utils_async_timer.cpp) target_link_libraries(${test_prefix}utils_async_timer mg-utils) -add_unit_test(utils_license.cpp) -target_link_libraries(${test_prefix}utils_license mg-utils mg-license) +add_unit_test(license.cpp) +target_link_libraries(${test_prefix}license mg-utils mg-license) add_unit_test(utils_settings.cpp) target_link_libraries(${test_prefix}utils_settings mg-utils mg-settings) diff --git a/tests/unit/auth.cpp b/tests/unit/auth.cpp index 9091d8fac..fdce7bc28 100644 --- a/tests/unit/auth.cpp +++ b/tests/unit/auth.cpp @@ -19,9 +19,9 @@ #include "auth/auth.hpp" #include "auth/crypto.hpp" #include "auth/models.hpp" +#include "license/license.hpp" #include "utils/cast.hpp" #include "utils/file.hpp" -#include "utils/license.hpp" using namespace memgraph::auth; namespace fs = std::filesystem; @@ -36,7 +36,7 @@ class AuthWithStorage : public ::testing::Test { FLAGS_auth_password_permit_null = true; FLAGS_auth_password_strength_regex = ".+"; - memgraph::utils::license::global_license_checker.EnableTesting(); + memgraph::license::global_license_checker.EnableTesting(); } virtual void TearDown() { fs::remove_all(test_folder_); } diff --git a/tests/unit/auth_checker.cpp b/tests/unit/auth_checker.cpp index 90d0ed234..9028f0d3c 100644 --- a/tests/unit/auth_checker.cpp +++ b/tests/unit/auth_checker.cpp @@ -15,9 +15,9 @@ #include "auth/models.hpp" #include "glue/auth_checker.hpp" +#include "license/license.hpp" #include "query_plan_common.hpp" #include "storage/v2/view.hpp" -#include "utils/license.hpp" #ifdef MG_ENTERPRISE class FineGrainedAuthCheckerFixture : public testing::Test { @@ -39,7 +39,7 @@ class FineGrainedAuthCheckerFixture : public testing::Test { memgraph::query::EdgeAccessor r4{*dba.InsertEdge(&v1, &v3, edge_type_two)}; void SetUp() override { - memgraph::utils::license::global_license_checker.EnableTesting(); + memgraph::license::global_license_checker.EnableTesting(); ASSERT_TRUE(v1.AddLabel(dba.NameToLabel("l1")).HasValue()); ASSERT_TRUE(v2.AddLabel(dba.NameToLabel("l2")).HasValue()); ASSERT_TRUE(v3.AddLabel(dba.NameToLabel("l3")).HasValue()); diff --git a/tests/unit/auth_handler.cpp b/tests/unit/auth_handler.cpp index fad55447f..961c6722b 100644 --- a/tests/unit/auth_handler.cpp +++ b/tests/unit/auth_handler.cpp @@ -37,7 +37,7 @@ class AuthQueryHandlerFixture : public testing::Test { #endif virtual void SetUp() { memgraph::utils::EnsureDir(test_folder_); - memgraph::utils::license::global_license_checker.EnableTesting(); + memgraph::license::global_license_checker.EnableTesting(); } virtual void TearDown() { diff --git a/tests/unit/bfs_fine_grained.cpp b/tests/unit/bfs_fine_grained.cpp index 594446e11..e628a4c6b 100644 --- a/tests/unit/bfs_fine_grained.cpp +++ b/tests/unit/bfs_fine_grained.cpp @@ -18,7 +18,7 @@ #include #include "auth/models.hpp" -#include "utils/license.hpp" +#include "license/license.hpp" using namespace memgraph::query; using namespace memgraph::query::plan; @@ -80,7 +80,7 @@ class FineGrainedBfsTest std::tuple, bool, FineGrainedTestType>> { public: static void SetUpTestCase() { - memgraph::utils::license::global_license_checker.EnableTesting(); + memgraph::license::global_license_checker.EnableTesting(); db_ = std::make_unique(); } static void TearDownTestCase() { db_ = nullptr; } diff --git a/tests/unit/utils_license.cpp b/tests/unit/license.cpp similarity index 50% rename from tests/unit/utils_license.cpp rename to tests/unit/license.cpp index 82b5cbe34..d7ef254f8 100644 --- a/tests/unit/utils_license.cpp +++ b/tests/unit/license.cpp @@ -10,8 +10,9 @@ // licenses/APL.txt. #include +#include -#include "utils/license.hpp" +#include "license/license.hpp" #include "utils/settings.hpp" class LicenseTest : public ::testing::Test { @@ -21,7 +22,7 @@ class LicenseTest : public ::testing::Test { settings->Initialize(settings_directory); license_checker.emplace(); - memgraph::utils::license::RegisterLicenseSettings(*license_checker, *settings); + memgraph::license::RegisterLicenseSettings(*license_checker, *settings); license_checker->StartBackgroundLicenseChecker(*settings); } @@ -33,24 +34,25 @@ class LicenseTest : public ::testing::Test { const std::filesystem::path settings_directory{test_directory / "settings"}; void CheckLicenseValidity(const bool expected_valid) { - ASSERT_EQ(!license_checker->IsValidLicense(*settings).HasError(), expected_valid); - ASSERT_EQ(license_checker->IsValidLicenseFast(), expected_valid); + ASSERT_EQ(!license_checker->IsEnterpriseValid(*settings).HasError(), expected_valid); + ASSERT_EQ(license_checker->IsEnterpriseValidFast(), expected_valid); } std::optional settings; - std::optional license_checker; + std::optional license_checker; }; TEST_F(LicenseTest, EncodeDecode) { const std::array licenses = { - memgraph::utils::license::License{"Organization", 1, 2}, - memgraph::utils::license::License{"", -1, 0}, - memgraph::utils::license::License{"Some very long name for the organization Ltd", -999, -9999}, + memgraph::license::License{"Organization", 1, 2, memgraph::license::LicenseType::OEM}, + memgraph::license::License{"", -1, 0, memgraph::license::LicenseType::ENTERPRISE}, + memgraph::license::License{"Some very long name for the organization Ltd", -999, -9999, + memgraph::license::LicenseType::ENTERPRISE}, }; for (const auto &license : licenses) { - const auto result = memgraph::utils::license::Encode(license); - auto maybe_license = memgraph::utils::license::Decode(result); + const auto result = memgraph::license::Encode(license); + auto maybe_license = memgraph::license::Decode(result); ASSERT_TRUE(maybe_license); ASSERT_EQ(*maybe_license, license); } @@ -69,10 +71,9 @@ TEST_F(LicenseTest, TestingFlag) { TEST_F(LicenseTest, LicenseOrganizationName) { const std::string organization_name{"Memgraph"}; - memgraph::utils::license::License license{ - .organization_name = organization_name, .valid_until = 0, .memory_limit = 0}; + memgraph::license::License license{organization_name, 0, 0, memgraph::license::LicenseType::ENTERPRISE}; - settings->SetValue("enterprise.license", memgraph::utils::license::Encode(license)); + settings->SetValue("enterprise.license", memgraph::license::Encode(license)); settings->SetValue("organization.name", organization_name); CheckLicenseValidity(true); @@ -91,22 +92,21 @@ TEST_F(LicenseTest, Expiration) { std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()); const auto delta = std::chrono::seconds(1); const auto valid_until = now + delta; - memgraph::utils::license::License license{ - .organization_name = organization_name, .valid_until = valid_until.count(), .memory_limit = 0}; + memgraph::license::License license{organization_name, valid_until.count(), 0, + memgraph::license::LicenseType::ENTERPRISE}; - settings->SetValue("enterprise.license", memgraph::utils::license::Encode(license)); + settings->SetValue("enterprise.license", memgraph::license::Encode(license)); settings->SetValue("organization.name", organization_name); CheckLicenseValidity(true); std::this_thread::sleep_for(delta + std::chrono::seconds(1)); - ASSERT_TRUE(license_checker->IsValidLicense(*settings).HasError()); + ASSERT_TRUE(license_checker->IsEnterpriseValid(*settings).HasError()); // We can't check fast checker because it has unknown refresh rate } { SCOPED_TRACE("License with valid_until = 0 is always valid"); - memgraph::utils::license::License license{ - .organization_name = organization_name, .valid_until = 0, .memory_limit = 0}; - settings->SetValue("enterprise.license", memgraph::utils::license::Encode(license)); + memgraph::license::License license{organization_name, 0, 0, memgraph::license::LicenseType::ENTERPRISE}; + settings->SetValue("enterprise.license", memgraph::license::Encode(license)); settings->SetValue("organization.name", organization_name); CheckLicenseValidity(true); } @@ -116,9 +116,8 @@ TEST_F(LicenseTest, LicenseInfoOverride) { CheckLicenseValidity(false); const std::string organization_name{"Memgraph"}; - memgraph::utils::license::License license{ - .organization_name = organization_name, .valid_until = 0, .memory_limit = 0}; - const std::string license_key = memgraph::utils::license::Encode(license); + memgraph::license::License license{organization_name, 0, 0, memgraph::license::LicenseType::ENTERPRISE}; + const std::string license_key = memgraph::license::Encode(license); { SCOPED_TRACE("Checker should use overrides instead of info from the settings"); @@ -139,3 +138,40 @@ TEST_F(LicenseTest, LicenseInfoOverride) { CheckLicenseValidity(false); } } + +TEST_F(LicenseTest, LicenseType) { + CheckLicenseValidity(false); + const std::string organization_name{"Memgraph"}; + { + memgraph::license::License license_entr{organization_name, 0, 0, memgraph::license::LicenseType::ENTERPRISE}; + const std::string license_key = memgraph::license::Encode(license_entr); + license_checker->SetLicenseInfoOverride(license_key, organization_name); + CheckLicenseValidity(true); + } + { + memgraph::license::License license_oem{organization_name, 0, 0, memgraph::license::LicenseType::OEM}; + const std::string license_key = memgraph::license::Encode(license_oem); + license_checker->SetLicenseInfoOverride(license_key, organization_name); + CheckLicenseValidity(false); + } + { + memgraph::license::License license_oem{organization_name, 0, 0, memgraph::license::LicenseType::OEM}; + const std::string license_key = memgraph::license::Encode(license_oem); + license_checker->SetLicenseInfoOverride(license_key, organization_name); + CheckLicenseValidity(false); + } + { + memgraph::license::License license_oem{organization_name, std::numeric_limits::min(), + std::numeric_limits::max(), memgraph::license::LicenseType::OEM}; + const std::string license_key = memgraph::license::Encode(license_oem); + license_checker->SetLicenseInfoOverride(license_key, organization_name); + CheckLicenseValidity(false); + } + { + memgraph::license::License license_oem{organization_name, std::numeric_limits::max(), + std::numeric_limits::min(), memgraph::license::LicenseType::OEM}; + const std::string license_key = memgraph::license::Encode(license_oem); + license_checker->SetLicenseInfoOverride(license_key, organization_name); + CheckLicenseValidity(false); + } +} diff --git a/tests/unit/query_plan_create_set_remove_delete.cpp b/tests/unit/query_plan_create_set_remove_delete.cpp index 30d7806f7..8985a4f28 100644 --- a/tests/unit/query_plan_create_set_remove_delete.cpp +++ b/tests/unit/query_plan_create_set_remove_delete.cpp @@ -20,11 +20,11 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +#include "license/license.hpp" #include "query/context.hpp" #include "query/exceptions.hpp" #include "query/interpret/frame.hpp" #include "query/plan/operator.hpp" -#include "utils/license.hpp" #include "query_plan_common.hpp" #include "storage/v2/id_types.hpp" @@ -80,7 +80,7 @@ TEST(QueryPlan, CreateNodeWithAttributes) { #ifdef MG_ENTERPRISE TEST(QueryPlan, FineGrainedCreateNodeWithAttributes) { - memgraph::utils::license::global_license_checker.EnableTesting(); + memgraph::license::global_license_checker.EnableTesting(); memgraph::query::AstStorage ast; memgraph::query::SymbolTable symbol_table; memgraph::storage::Storage db; @@ -164,7 +164,7 @@ TEST(QueryPlan, CreateReturn) { #ifdef MG_ENTERPRISE TEST(QueryPlan, FineGrainedCreateReturn) { - memgraph::utils::license::global_license_checker.EnableTesting(); + memgraph::license::global_license_checker.EnableTesting(); // test CREATE (n:Person {age: 42}) RETURN n, n.age memgraph::storage::Storage db; @@ -310,7 +310,7 @@ class CreateExpandWithAuthFixture : public testing::Test { AstStorage storage; SymbolTable symbol_table; - void SetUp() override { memgraph::utils::license::global_license_checker.EnableTesting(); } + void SetUp() override { memgraph::license::global_license_checker.EnableTesting(); } void ExecuteCreateExpand(bool cycle, memgraph::auth::User &user) { const auto label_node_1 = dba.NameToLabel("Node1"); @@ -470,7 +470,7 @@ class MatchCreateNodeWithAuthFixture : public testing::Test { AstStorage storage; SymbolTable symbol_table; - void SetUp() override { memgraph::utils::license::global_license_checker.EnableTesting(); } + void SetUp() override { memgraph::license::global_license_checker.EnableTesting(); } void InitGraph() { // add three nodes we'll match and expand-create from @@ -600,7 +600,7 @@ class MatchCreateExpandWithAuthFixture : public testing::Test { AstStorage storage; SymbolTable symbol_table; - void SetUp() override { memgraph::utils::license::global_license_checker.EnableTesting(); } + void SetUp() override { memgraph::license::global_license_checker.EnableTesting(); } void InitGraph() { // add three nodes we'll match and expand-create from @@ -818,7 +818,7 @@ class DeleteOperatorWithAuthFixture : public testing::Test { AstStorage storage; SymbolTable symbol_table; - void SetUp() override { memgraph::utils::license::global_license_checker.EnableTesting(); } + void SetUp() override { memgraph::license::global_license_checker.EnableTesting(); } void InitGraph() { std::vector vertices; @@ -1253,7 +1253,7 @@ TEST(QueryPlan, SetLabels) { #ifdef MG_ENTERPRISE TEST(QueryPlan, SetLabelsWithFineGrained) { - memgraph::utils::license::global_license_checker.EnableTesting(); + memgraph::license::global_license_checker.EnableTesting(); auto set_labels = [&](memgraph::auth::User user, memgraph::query::DbAccessor dba, std::vector labels) { ASSERT_TRUE(dba.InsertVertex().AddLabel(labels[0]).HasValue()); @@ -1426,7 +1426,7 @@ TEST(QueryPlan, RemoveLabels) { #ifdef MG_ENTERPRISE TEST(QueryPlan, RemoveLabelsFineGrainedFiltering) { - memgraph::utils::license::global_license_checker.EnableTesting(); + memgraph::license::global_license_checker.EnableTesting(); auto remove_labels = [&](memgraph::auth::User user, memgraph::query::DbAccessor dba, std::vector labels) { auto v1 = dba.InsertVertex(); @@ -1896,7 +1896,7 @@ class UpdatePropertiesWithAuthFixture : public testing::Test { const memgraph::storage::PropertyId edge_prop{dba.NameToProperty(edge_prop_name)}; const memgraph::storage::PropertyValue edge_prop_value{1}; - void SetUp() override { memgraph::utils::license::global_license_checker.EnableTesting(); } + void SetUp() override { memgraph::license::global_license_checker.EnableTesting(); } void SetVertexProperty(memgraph::query::VertexAccessor vertex) { static_cast(vertex.SetProperty(entity_prop, entity_prop_value)); diff --git a/tests/unit/query_plan_match_filter_return.cpp b/tests/unit/query_plan_match_filter_return.cpp index d970ac2c7..b11eb92cf 100644 --- a/tests/unit/query_plan_match_filter_return.cpp +++ b/tests/unit/query_plan_match_filter_return.cpp @@ -30,10 +30,10 @@ #include "auth/auth.hpp" #include "auth/models.hpp" #include "glue/auth_checker.hpp" +#include "license/license.hpp" #include "query/context.hpp" #include "query/exceptions.hpp" #include "query/plan/operator.hpp" -#include "utils/license.hpp" #include "utils/synchronized.hpp" using namespace memgraph::query; @@ -50,7 +50,7 @@ class MatchReturnFixture : public testing::Test { void AddVertices(int count) { for (int i = 0; i < count; i++) dba.InsertVertex(); } - void SetUp() override { memgraph::utils::license::global_license_checker.EnableTesting(); } + void SetUp() override { memgraph::license::global_license_checker.EnableTesting(); } std::vector PathResults(std::shared_ptr &op) { std::vector res; @@ -485,7 +485,7 @@ class ExpandFixture : public testing::Test { ASSERT_TRUE(v1.AddLabel(dba.NameToLabel("l1")).HasValue()); ASSERT_TRUE(v2.AddLabel(dba.NameToLabel("l2")).HasValue()); ASSERT_TRUE(v3.AddLabel(dba.NameToLabel("l3")).HasValue()); - memgraph::utils::license::global_license_checker.EnableTesting(); + memgraph::license::global_license_checker.EnableTesting(); dba.AdvanceCommand(); } @@ -628,7 +628,7 @@ class QueryPlanExpandVariable : public testing::Test { std::nullopt_t nullopt = std::nullopt; void SetUp() { - memgraph::utils::license::global_license_checker.EnableTesting(); + memgraph::license::global_license_checker.EnableTesting(); // create the graph int chain_length = 3; @@ -1778,7 +1778,7 @@ class QueryPlanExpandWeightedShortestPath : public testing::Test { Symbol total_weight = symbol_table.CreateSymbol("total_weight", true); void SetUp() { - memgraph::utils::license::global_license_checker.EnableTesting(); + memgraph::license::global_license_checker.EnableTesting(); for (int i = 0; i < 5; i++) { v.push_back(dba.InsertVertex()); @@ -2208,7 +2208,7 @@ class QueryPlanExpandAllShortestPaths : public testing::Test { Symbol total_weight = symbol_table.CreateSymbol("total_weight", true); void SetUp() { - memgraph::utils::license::global_license_checker.EnableTesting(); + memgraph::license::global_license_checker.EnableTesting(); for (int i = 0; i < 5; i++) { v.push_back(dba.InsertVertex()); diff --git a/tests/unit/query_required_privileges.cpp b/tests/unit/query_required_privileges.cpp index d65be9caf..55ab02cb9 100644 --- a/tests/unit/query_required_privileges.cpp +++ b/tests/unit/query_required_privileges.cpp @@ -13,11 +13,11 @@ #include #include +#include "license/license.hpp" #include "query/frontend/ast/ast.hpp" #include "query/frontend/ast/ast_visitor.hpp" #include "query/frontend/semantic/required_privileges.hpp" #include "storage/v2/id_types.hpp" -#include "utils/license.hpp" #include "query_common.hpp" @@ -100,7 +100,7 @@ TEST_F(TestPrivilegeExtractor, CreateIndex) { } #ifdef MG_ENTERPRISE TEST_F(TestPrivilegeExtractor, AuthQuery) { - memgraph::utils::license::global_license_checker.EnableTesting(); + memgraph::license::global_license_checker.EnableTesting(); auto label_privileges = std::vector>>{}; auto edge_type_privileges = std::vector>>{};