Add multiple license support (#618)
Make license info available through LicenseChecker Add LicenseInfoSender Move license library from utils Rename telemetry_lib to mg-telemetry
This commit is contained in:
parent
2a2b99b02a
commit
ff21c0705c
@ -15,6 +15,7 @@ add_subdirectory(query)
|
||||
add_subdirectory(glue)
|
||||
add_subdirectory(slk)
|
||||
add_subdirectory(rpc)
|
||||
add_subdirectory(license)
|
||||
add_subdirectory(auth)
|
||||
|
||||
if(MG_ENTERPRISE)
|
||||
@ -36,7 +37,8 @@ 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)
|
||||
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)
|
||||
@ -46,20 +48,25 @@ endif()
|
||||
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})
|
||||
|
||||
# Create symlink to the built executable.
|
||||
add_custom_command(TARGET memgraph POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E create_symlink $<TARGET_FILE:memgraph> ${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
|
||||
@ -95,9 +102,11 @@ set(CMAKE_INSTALL_DEFAULT_COMPONENT_NAME "memgraph")
|
||||
# we cannot use the recommended `install(TARGETS ...)`.
|
||||
install(PROGRAMS $<TARGET_FILE:memgraph>
|
||||
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,7 +136,6 @@ 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)
|
||||
|
||||
|
@ -16,8 +16,8 @@
|
||||
#include <fmt/format.h>
|
||||
|
||||
#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<User> 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;
|
||||
}
|
||||
|
||||
|
@ -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<uint64_t> 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<std::string> &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_;
|
||||
|
@ -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<memgraph::storage::LabelId> &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<std::string> &username,
|
||||
#ifdef MG_ENTERPRISE
|
||||
std::unique_ptr<memgraph::query::FineGrainedAuthChecker> 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));
|
||||
|
@ -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<FineGrainedPermissionForPrivilegeResult> GetFineGrainedPermissionFor
|
||||
const memgraph::auth::FineGrainedAccessPermissions &permissions, const std::string &permission_type,
|
||||
const std::string &user_or_role) {
|
||||
std::vector<FineGrainedPermissionForPrivilegeResult> 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<FineGrainedPermissionForPrivilegeResult> GetFineGrainedPermissionFor
|
||||
std::vector<std::vector<memgraph::query::TypedValue>> ConstructFineGrainedPrivilegesResult(
|
||||
const std::vector<FineGrainedPermissionForPrivilegeResult> &privileges) {
|
||||
std::vector<std::vector<memgraph::query::TypedValue>> 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<std::vector<memgraph::query::TypedValue>> ConstructFineGrainedPrivil
|
||||
|
||||
std::vector<std::vector<memgraph::query::TypedValue>> ShowFineGrainedUserPrivileges(
|
||||
const std::optional<memgraph::auth::User> &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<std::vector<memgraph::query::TypedValue>> ShowFineGrainedUserPrivile
|
||||
|
||||
std::vector<std::vector<memgraph::query::TypedValue>> ShowFineGrainedRolePrivileges(
|
||||
const std::optional<memgraph::auth::Role> &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<std::string> &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<std::vector<memgraph::query::TypedValue>> 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);
|
||||
}
|
||||
|
@ -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 {
|
||||
|
6
src/license/CMakeLists.txt
Normal file
6
src/license/CMakeLists.txt
Normal file
@ -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)
|
@ -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 <atomic>
|
||||
#include <charconv>
|
||||
#include <chrono>
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
#include <optional>
|
||||
#include <unordered_map>
|
||||
|
||||
#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<std::string, std::string> LicenseChecker::GetLicenseInfo(const utils::Settings &settings) const {
|
||||
std::pair<std::string, std::string> 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<std::string, std::string> 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<std::optional<PreviousLicenseInfo>, 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<std::optional<LicenseInfo>, 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<uint8_t> 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<License> Decode(std::string_view license_key) {
|
||||
@ -266,7 +289,7 @@ std::optional<License> Decode(std::string_view license_key) {
|
||||
|
||||
const auto decoded = std::invoke([license_key]() -> std::optional<std::string> {
|
||||
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<License> 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<LicenseType> 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
|
@ -12,26 +12,57 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
|
||||
#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<std::optional<LicenseInfo>, utils::SpinLock> &GetLicenseInfo();
|
||||
|
||||
private:
|
||||
std::pair<std::string, std::string> GetLicenseInfo(const utils::Settings &settings) const;
|
||||
std::pair<std::string, std::string> 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<std::pair<std::string, std::string>> license_info_override_;
|
||||
utils::Synchronized<std::optional<LicenseInfo>, utils::SpinLock> previous_license_info_{std::nullopt};
|
||||
bool enterprise_enabled_{false};
|
||||
std::atomic<bool> 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
|
71
src/license/license_sender.cpp
Normal file
71
src/license/license_sender.cpp
Normal file
@ -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 <spdlog/spdlog.h>
|
||||
#include <cstdint>
|
||||
|
||||
#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<std::optional<LicenseInfo>, 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
|
50
src/license/license_sender.hpp
Normal file
50
src/license/license_sender.hpp
Normal file
@ -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 <chrono>
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
#include <json/json.hpp>
|
||||
|
||||
#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<std::optional<LicenseInfo>, 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<std::optional<LicenseInfo>, utils::SpinLock> &license_info_;
|
||||
utils::Scheduler scheduler_;
|
||||
};
|
||||
|
||||
} // namespace memgraph::license
|
@ -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::Session<memgraph
|
||||
username = &user_->username();
|
||||
}
|
||||
#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::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<memgraph::telemetry::Telemetry> 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{
|
||||
|
@ -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<CachedPlan> 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
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include <cppitertools/imap.hpp>
|
||||
#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!");
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
#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
|
||||
|
@ -1,12 +1,12 @@
|
||||
set(telemetry_src_files
|
||||
collectors.cpp
|
||||
telemetry.cpp
|
||||
system_info.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)
|
||||
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()
|
||||
|
@ -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<int64_t> 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<const
|
||||
collectors_.emplace_back(name, func);
|
||||
}
|
||||
|
||||
std::string Telemetry::GetRunId() const { return uuid_; }
|
||||
|
||||
Telemetry::~Telemetry() {
|
||||
scheduler_.Stop();
|
||||
CollectData("shutdown");
|
||||
}
|
||||
|
||||
void Telemetry::StoreData(const nlohmann::json &event, const nlohmann::json &data) {
|
||||
nlohmann::json payload = {{"run_id", uuid_},
|
||||
{"machine_id", machine_id_},
|
||||
{"event", event},
|
||||
{"data", data},
|
||||
{"timestamp", utils::Timestamp::Now().SecWithNsecSinceTheEpoch()}};
|
||||
nlohmann::json payload = {
|
||||
{"run_id", uuid_}, {"type", "telemetry"}, {"machine_id", machine_id_},
|
||||
{"event", event}, {"data", data}, {"timestamp", utils::Timestamp::Now().SecWithNsecSinceTheEpoch()}};
|
||||
storage_.Put(fmt::format("{}:{}", uuid_, event.dump()), payload.dump());
|
||||
}
|
||||
|
||||
|
@ -26,7 +26,7 @@ namespace memgraph::telemetry {
|
||||
* This class implements the telemetry collector service. It periodically scapes
|
||||
* all registered collectors and stores their data. With periodically scraping
|
||||
* the collectors the service collects machine information in the constructor
|
||||
* and stores it. Also, it calles all collectors once more in the destructor so
|
||||
* and stores it. Also, it calls all collectors once more in the destructor so
|
||||
* that final stats can be collected. All data is stored persistently. If there
|
||||
* is no internet connection the data will be sent when the internet connection
|
||||
* is reestablished. If there is an issue with the internet connection that
|
||||
@ -34,14 +34,11 @@ namespace memgraph::telemetry {
|
||||
*/
|
||||
class Telemetry final {
|
||||
public:
|
||||
Telemetry(std::string url, std::filesystem::path storage_directory,
|
||||
Telemetry(std::string url, std::filesystem::path storage_directory, std::string uuid, std::string machine_id,
|
||||
std::chrono::duration<int64_t> refresh_interval = std::chrono::minutes(10), uint64_t send_every_n = 10);
|
||||
|
||||
void AddCollector(const std::string &name, const std::function<const nlohmann::json(void)> &func);
|
||||
|
||||
/// Required to expose run_id to Bolt server.
|
||||
std::string GetRunId() const;
|
||||
|
||||
~Telemetry();
|
||||
|
||||
Telemetry(const Telemetry &) = delete;
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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 <string>
|
||||
|
||||
#include <sys/utsname.h>
|
||||
|
||||
#include <gflags/gflags.h>
|
||||
#include <sys/utsname.h>
|
||||
|
||||
#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
|
@ -11,16 +11,33 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
#include <json/json.hpp>
|
||||
|
||||
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
|
@ -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)
|
||||
|
6
tests/integration/license_info/CMakeLists.txt
Normal file
6
tests/integration/license_info/CMakeLists.txt
Normal file
@ -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)
|
62
tests/integration/license_info/client.cpp
Normal file
62
tests/integration/license_info/client.cpp
Normal file
@ -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 <exception>
|
||||
#include <string>
|
||||
|
||||
#include <gflags/gflags.h>
|
||||
|
||||
#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<std::optional<memgraph::license::LicenseInfo>, 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;
|
||||
}
|
96
tests/integration/license_info/runner.py
Executable file
96
tests/integration/license_info/runner.py
Executable file
@ -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()
|
69
tests/integration/license_info/server.py
Executable file
69
tests/integration/license_info/server.py
Executable file
@ -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()
|
@ -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)
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
@ -89,15 +93,13 @@ TESTS = [
|
||||
{"start_server": False},
|
||||
{"startups": 4, "no_check_duration": True}, # the last 3 tests failed
|
||||
# to send any data + this test
|
||||
{"add_garbage": True}
|
||||
{"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
|
||||
|
@ -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
|
||||
|
@ -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};
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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_); }
|
||||
|
@ -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());
|
||||
|
@ -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() {
|
||||
|
@ -18,7 +18,7 @@
|
||||
#include <gtest/internal/gtest-param-util-generated.h>
|
||||
|
||||
#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<int, int, EdgeAtom::Direction, std::vector<std::string>, bool, FineGrainedTestType>> {
|
||||
public:
|
||||
static void SetUpTestCase() {
|
||||
memgraph::utils::license::global_license_checker.EnableTesting();
|
||||
memgraph::license::global_license_checker.EnableTesting();
|
||||
db_ = std::make_unique<VertexDb>();
|
||||
}
|
||||
static void TearDownTestCase() { db_ = nullptr; }
|
||||
|
@ -10,8 +10,9 @@
|
||||
// licenses/APL.txt.
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <cstdint>
|
||||
|
||||
#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<memgraph::utils::Settings> settings;
|
||||
std::optional<memgraph::utils::license::LicenseChecker> license_checker;
|
||||
std::optional<memgraph::license::LicenseChecker> 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::seconds>(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<int64_t>::min(),
|
||||
std::numeric_limits<int64_t>::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<int64_t>::max(),
|
||||
std::numeric_limits<int64_t>::min(), memgraph::license::LicenseType::OEM};
|
||||
const std::string license_key = memgraph::license::Encode(license_oem);
|
||||
license_checker->SetLicenseInfoOverride(license_key, organization_name);
|
||||
CheckLicenseValidity(false);
|
||||
}
|
||||
}
|
@ -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<memgraph::query::VertexAccessor> 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<memgraph::storage::LabelId> 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<memgraph::storage::LabelId> 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<void>(vertex.SetProperty(entity_prop, entity_prop_value));
|
||||
|
@ -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<Path> PathResults(std::shared_ptr<Produce> &op) {
|
||||
std::vector<Path> 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());
|
||||
|
@ -13,11 +13,11 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include <unordered_map>
|
||||
|
||||
#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<std::unordered_map<AuthQuery::FineGrainedPrivilege, std::vector<std::string>>>{};
|
||||
auto edge_type_privileges =
|
||||
std::vector<std::unordered_map<AuthQuery::FineGrainedPrivilege, std::vector<std::string>>>{};
|
||||
|
Loading…
Reference in New Issue
Block a user