Simplify auth::Auth (#1663)

Moved various auth flags under a single config
Moved all regex logic under auth::Auth
This commit is contained in:
andrejtonev 2024-01-29 13:52:32 +01:00 committed by GitHub
parent f1484240a0
commit ff44d68843
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
16 changed files with 331 additions and 315 deletions

View File

@ -1,4 +1,4 @@
// Copyright 2023 Memgraph Ltd. // Copyright 2024 Memgraph Ltd.
// //
// Licensed as a Memgraph Enterprise file under the Memgraph Enterprise // Licensed as a Memgraph Enterprise file under the Memgraph Enterprise
// License (the "License"); by using this file, you agree to be bound by the terms of the License, and you may not use // License (the "License"); by using this file, you agree to be bound by the terms of the License, and you may not use
@ -8,9 +8,7 @@
#include "auth/auth.hpp" #include "auth/auth.hpp"
#include <cstring>
#include <iostream> #include <iostream>
#include <limits>
#include <utility> #include <utility>
#include <fmt/format.h> #include <fmt/format.h>
@ -18,7 +16,6 @@
#include "auth/exceptions.hpp" #include "auth/exceptions.hpp"
#include "license/license.hpp" #include "license/license.hpp"
#include "utils/flag_validation.hpp" #include "utils/flag_validation.hpp"
#include "utils/logging.hpp"
#include "utils/message.hpp" #include "utils/message.hpp"
#include "utils/settings.hpp" #include "utils/settings.hpp"
#include "utils/string.hpp" #include "utils/string.hpp"
@ -64,7 +61,8 @@ const std::string kLinkPrefix = "link:";
* key="link:<username>", value="<rolename>" * key="link:<username>", value="<rolename>"
*/ */
Auth::Auth(const std::string &storage_directory) : storage_(storage_directory), module_(FLAGS_auth_module_executable) {} Auth::Auth(std::string storage_directory, Config config)
: storage_(std::move(storage_directory)), module_(FLAGS_auth_module_executable), config_{std::move(config)} {}
std::optional<User> Auth::Authenticate(const std::string &username, const std::string &password) { std::optional<User> Auth::Authenticate(const std::string &username, const std::string &password) {
if (module_.IsUsed()) { if (module_.IsUsed()) {
@ -113,7 +111,7 @@ std::optional<User> Auth::Authenticate(const std::string &username, const std::s
return std::nullopt; return std::nullopt;
} }
} else { } else {
user->UpdatePassword(password); UpdatePassword(*user, password);
} }
if (FLAGS_auth_module_manage_roles) { if (FLAGS_auth_module_manage_roles) {
if (!rolename.empty()) { if (!rolename.empty()) {
@ -197,13 +195,46 @@ void Auth::SaveUser(const User &user) {
} }
} }
void Auth::UpdatePassword(auth::User &user, const std::optional<std::string> &password) {
// Check if null
if (!password) {
if (!config_.password_permit_null) {
throw AuthException("Null passwords aren't permitted!");
}
} else {
// Check if compliant with our filter
if (config_.custom_password_regex) {
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{}",
glue::kDefaultPasswordRegex,
license::LicenseCheckErrorToString(license_check_result.GetError(), "password regex"));
}
}
if (!std::regex_match(*password, config_.password_regex)) {
throw AuthException(
"The user password doesn't conform to the required strength! Regex: "
"\"{}\"",
config_.password_regex_str);
}
}
// All checks passed; update
user.UpdatePassword(password);
}
std::optional<User> Auth::AddUser(const std::string &username, const std::optional<std::string> &password) { std::optional<User> Auth::AddUser(const std::string &username, const std::optional<std::string> &password) {
if (!NameRegexMatch(username)) {
throw AuthException("Invalid user name.");
}
auto existing_user = GetUser(username); auto existing_user = GetUser(username);
if (existing_user) return std::nullopt; if (existing_user) return std::nullopt;
auto existing_role = GetRole(username); auto existing_role = GetRole(username);
if (existing_role) return std::nullopt; if (existing_role) return std::nullopt;
auto new_user = User(username); auto new_user = User(username);
new_user.UpdatePassword(password); UpdatePassword(new_user, password);
SaveUser(new_user); SaveUser(new_user);
return new_user; return new_user;
} }
@ -255,6 +286,9 @@ void Auth::SaveRole(const Role &role) {
} }
std::optional<Role> Auth::AddRole(const std::string &rolename) { std::optional<Role> Auth::AddRole(const std::string &rolename) {
if (!NameRegexMatch(rolename)) {
throw AuthException("Invalid role name.");
}
if (auto existing_role = GetRole(rolename)) return std::nullopt; if (auto existing_role = GetRole(rolename)) return std::nullopt;
if (auto existing_user = GetUser(rolename)) return std::nullopt; if (auto existing_user = GetUser(rolename)) return std::nullopt;
auto new_role = Role(rolename); auto new_role = Role(rolename);
@ -359,4 +393,19 @@ bool Auth::SetMainDatabase(std::string_view db, const std::string &name) {
} }
#endif #endif
bool Auth::NameRegexMatch(const std::string &user_or_role) const {
if (config_.custom_name_regex) {
if (const auto license_check_result =
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{}",
glue::kDefaultUserRoleRegex,
memgraph::license::LicenseCheckErrorToString(license_check_result.GetError(), "user/role regex"));
}
}
return std::regex_match(user_or_role, config_.name_regex);
}
} // namespace memgraph::auth } // namespace memgraph::auth

View File

@ -1,4 +1,4 @@
// Copyright 2023 Memgraph Ltd. // Copyright 2024 Memgraph Ltd.
// //
// Licensed as a Memgraph Enterprise file under the Memgraph Enterprise // Licensed as a Memgraph Enterprise file under the Memgraph Enterprise
// License (the "License"); by using this file, you agree to be bound by the terms of the License, and you may not use // License (the "License"); by using this file, you agree to be bound by the terms of the License, and you may not use
@ -10,11 +10,13 @@
#include <mutex> #include <mutex>
#include <optional> #include <optional>
#include <regex>
#include <vector> #include <vector>
#include "auth/exceptions.hpp" #include "auth/exceptions.hpp"
#include "auth/models.hpp" #include "auth/models.hpp"
#include "auth/module.hpp" #include "auth/module.hpp"
#include "glue/auth_global.hpp"
#include "kvstore/kvstore.hpp" #include "kvstore/kvstore.hpp"
#include "utils/settings.hpp" #include "utils/settings.hpp"
@ -31,7 +33,40 @@ static const constexpr char *const kAllDatabases = "*";
*/ */
class Auth final { class Auth final {
public: public:
explicit Auth(const std::string &storage_directory); struct Config {
Config() {}
Config(std::string name_regex, std::string password_regex, bool password_permit_null)
: name_regex_str{std::move(name_regex)},
password_regex_str{std::move(password_regex)},
password_permit_null{password_permit_null},
custom_name_regex{name_regex_str != glue::kDefaultUserRoleRegex},
name_regex{name_regex_str},
custom_password_regex{password_regex_str != glue::kDefaultPasswordRegex},
password_regex{password_regex_str} {}
std::string name_regex_str{glue::kDefaultUserRoleRegex};
std::string password_regex_str{glue::kDefaultPasswordRegex};
bool password_permit_null{true};
private:
friend class Auth;
bool custom_name_regex{false};
std::regex name_regex{name_regex_str};
bool custom_password_regex{false};
std::regex password_regex{password_regex_str};
};
explicit Auth(std::string storage_directory, Config config);
/**
* @brief Set the Config object
*
* @param config
*/
void SetConfig(Config config) {
// NOTE: The Auth class itself is not thread-safe, higher-level code needs to synchronize it when using it.
config_ = std::move(config);
}
/** /**
* Authenticates a user using his username and password. * Authenticates a user using his username and password.
@ -85,6 +120,14 @@ class Auth final {
*/ */
bool RemoveUser(const std::string &username); bool RemoveUser(const std::string &username);
/**
* @brief
*
* @param user
* @param password
*/
void UpdatePassword(auth::User &user, const std::optional<std::string> &password);
/** /**
* Gets all users from the storage. * Gets all users from the storage.
* *
@ -199,10 +242,20 @@ class Auth final {
#endif #endif
private: private:
/**
* @brief
*
* @param user_or_role
* @return true
* @return false
*/
bool NameRegexMatch(const std::string &user_or_role) const;
// Even though the `kvstore::KVStore` class is guaranteed to be thread-safe, // Even though the `kvstore::KVStore` class is guaranteed to be thread-safe,
// Auth is not thread-safe because modifying users and roles might require // Auth is not thread-safe because modifying users and roles might require
// more than one operation on the storage. // more than one operation on the storage.
kvstore::KVStore storage_; kvstore::KVStore storage_;
auth::Module module_; auth::Module module_;
Config config_;
}; };
} // namespace memgraph::auth } // namespace memgraph::auth

View File

@ -9,7 +9,6 @@
#include "auth/models.hpp" #include "auth/models.hpp"
#include <cstdint> #include <cstdint>
#include <regex>
#include <utility> #include <utility>
#include <gflags/gflags.h> #include <gflags/gflags.h>
@ -21,19 +20,8 @@
#include "query/constants.hpp" #include "query/constants.hpp"
#include "spdlog/spdlog.h" #include "spdlog/spdlog.h"
#include "utils/cast.hpp" #include "utils/cast.hpp"
#include "utils/logging.hpp"
#include "utils/settings.hpp"
#include "utils/string.hpp" #include "utils/string.hpp"
// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
DEFINE_bool(auth_password_permit_null, true, "Set to false to disable null passwords.");
inline constexpr std::string_view default_password_regex = ".+";
// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
DEFINE_string(auth_password_strength_regex, default_password_regex.data(),
"The regular expression that should be used to match the entire "
"entered password to ensure its strength.");
namespace memgraph::auth { namespace memgraph::auth {
namespace { namespace {
@ -587,31 +575,9 @@ bool User::CheckPassword(const std::string &password) {
void User::UpdatePassword(const std::optional<std::string> &password) { void User::UpdatePassword(const std::optional<std::string> &password) {
if (!password) { if (!password) {
if (!FLAGS_auth_password_permit_null) {
throw AuthException("Null passwords aren't permitted!");
}
password_hash_ = ""; password_hash_ = "";
return; return;
} }
if (FLAGS_auth_password_strength_regex != default_password_regex) {
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,
license::LicenseCheckErrorToString(license_check_result.GetError(), "password regex"));
}
}
std::regex re(FLAGS_auth_password_strength_regex);
if (!std::regex_match(*password, re)) {
throw AuthException(
"The user password doesn't conform to the required strength! Regex: "
"\"{}\"",
FLAGS_auth_password_strength_regex);
}
password_hash_ = EncryptPassword(*password); password_hash_ = EncryptPassword(*password);
} }

View File

@ -195,3 +195,9 @@ DEFINE_HIDDEN_string(organization_name, "", "Organization name.");
// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
DEFINE_string(auth_user_or_role_name_regex, memgraph::glue::kDefaultUserRoleRegex.data(), DEFINE_string(auth_user_or_role_name_regex, memgraph::glue::kDefaultUserRoleRegex.data(),
"Set to the regular expression that each user or role name must fulfill."); "Set to the regular expression that each user or role name must fulfill.");
// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
DEFINE_bool(auth_password_permit_null, true, "Set to false to disable null passwords.");
// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
DEFINE_string(auth_password_strength_regex, memgraph::glue::kDefaultPasswordRegex.data(),
"The regular expression that should be used to match the entire "
"entered password to ensure its strength.");

View File

@ -118,3 +118,7 @@ DECLARE_string(license_key);
DECLARE_string(organization_name); DECLARE_string(organization_name);
// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
DECLARE_string(auth_user_or_role_name_regex); DECLARE_string(auth_user_or_role_name_regex);
// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
DECLARE_bool(auth_password_permit_null);
// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
DECLARE_string(auth_password_strength_regex);

View File

@ -1,4 +1,4 @@
// Copyright 2023 Memgraph Ltd. // Copyright 2024 Memgraph Ltd.
// //
// Use of this software is governed by the Business Source License // 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 // included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
@ -13,4 +13,5 @@
namespace memgraph::glue { namespace memgraph::glue {
inline constexpr std::string_view kDefaultUserRoleRegex = "[a-zA-Z0-9_.+-@]+"; inline constexpr std::string_view kDefaultUserRoleRegex = "[a-zA-Z0-9_.+-@]+";
static constexpr std::string_view kDefaultPasswordRegex = ".+";
} // namespace memgraph::glue } // namespace memgraph::glue

View File

@ -1,4 +1,4 @@
// Copyright 2023 Memgraph Ltd. // Copyright 2024 Memgraph Ltd.
// //
// Use of this software is governed by the Business Source License // 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 // included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
@ -249,25 +249,10 @@ std::vector<std::vector<memgraph::query::TypedValue>> ShowFineGrainedRolePrivile
namespace memgraph::glue { namespace memgraph::glue {
AuthQueryHandler::AuthQueryHandler( AuthQueryHandler::AuthQueryHandler(
memgraph::utils::Synchronized<memgraph::auth::Auth, memgraph::utils::WritePrioritizedRWLock> *auth, memgraph::utils::Synchronized<memgraph::auth::Auth, memgraph::utils::WritePrioritizedRWLock> *auth)
std::string name_regex_string) : auth_(auth) {}
: auth_(auth), name_regex_string_(std::move(name_regex_string)), name_regex_(name_regex_string_) {}
bool AuthQueryHandler::CreateUser(const std::string &username, const std::optional<std::string> &password) { 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::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::license::LicenseCheckErrorToString(license_check_result.GetError(), "user/role regex"));
}
}
if (!std::regex_match(username, name_regex_)) {
throw query::QueryRuntimeException("Invalid user name.");
}
try { try {
const auto [first_user, user_added] = std::invoke([&, this] { const auto [first_user, user_added] = std::invoke([&, this] {
auto locked_auth = auth_->Lock(); auto locked_auth = auth_->Lock();
@ -305,9 +290,6 @@ bool AuthQueryHandler::CreateUser(const std::string &username, const std::option
} }
bool AuthQueryHandler::DropUser(const std::string &username) { bool AuthQueryHandler::DropUser(const std::string &username) {
if (!std::regex_match(username, name_regex_)) {
throw memgraph::query::QueryRuntimeException("Invalid user name.");
}
try { try {
auto locked_auth = auth_->Lock(); auto locked_auth = auth_->Lock();
auto user = locked_auth->GetUser(username); auto user = locked_auth->GetUser(username);
@ -319,16 +301,13 @@ bool AuthQueryHandler::DropUser(const std::string &username) {
} }
void AuthQueryHandler::SetPassword(const std::string &username, const std::optional<std::string> &password) { void AuthQueryHandler::SetPassword(const std::string &username, const std::optional<std::string> &password) {
if (!std::regex_match(username, name_regex_)) {
throw memgraph::query::QueryRuntimeException("Invalid user name.");
}
try { try {
auto locked_auth = auth_->Lock(); auto locked_auth = auth_->Lock();
auto user = locked_auth->GetUser(username); auto user = locked_auth->GetUser(username);
if (!user) { if (!user) {
throw memgraph::query::QueryRuntimeException("User '{}' doesn't exist.", username); throw memgraph::query::QueryRuntimeException("User '{}' doesn't exist.", username);
} }
user->UpdatePassword(password); locked_auth->UpdatePassword(*user, password);
locked_auth->SaveUser(*user); locked_auth->SaveUser(*user);
} catch (const memgraph::auth::AuthException &e) { } catch (const memgraph::auth::AuthException &e) {
throw memgraph::query::QueryRuntimeException(e.what()); throw memgraph::query::QueryRuntimeException(e.what());
@ -336,9 +315,6 @@ void AuthQueryHandler::SetPassword(const std::string &username, const std::optio
} }
bool AuthQueryHandler::CreateRole(const std::string &rolename) { bool AuthQueryHandler::CreateRole(const std::string &rolename) {
if (!std::regex_match(rolename, name_regex_)) {
throw memgraph::query::QueryRuntimeException("Invalid role name.");
}
try { try {
auto locked_auth = auth_->Lock(); auto locked_auth = auth_->Lock();
return locked_auth->AddRole(rolename).has_value(); return locked_auth->AddRole(rolename).has_value();
@ -349,9 +325,6 @@ bool AuthQueryHandler::CreateRole(const std::string &rolename) {
#ifdef MG_ENTERPRISE #ifdef MG_ENTERPRISE
bool AuthQueryHandler::RevokeDatabaseFromUser(const std::string &db, const std::string &username) { bool AuthQueryHandler::RevokeDatabaseFromUser(const std::string &db, const std::string &username) {
if (!std::regex_match(username, name_regex_)) {
throw memgraph::query::QueryRuntimeException("Invalid user name.");
}
try { try {
auto locked_auth = auth_->Lock(); auto locked_auth = auth_->Lock();
auto user = locked_auth->GetUser(username); auto user = locked_auth->GetUser(username);
@ -363,9 +336,6 @@ bool AuthQueryHandler::RevokeDatabaseFromUser(const std::string &db, const std::
} }
bool AuthQueryHandler::GrantDatabaseToUser(const std::string &db, const std::string &username) { bool AuthQueryHandler::GrantDatabaseToUser(const std::string &db, const std::string &username) {
if (!std::regex_match(username, name_regex_)) {
throw memgraph::query::QueryRuntimeException("Invalid user name.");
}
try { try {
auto locked_auth = auth_->Lock(); auto locked_auth = auth_->Lock();
auto user = locked_auth->GetUser(username); auto user = locked_auth->GetUser(username);
@ -378,9 +348,6 @@ bool AuthQueryHandler::GrantDatabaseToUser(const std::string &db, const std::str
std::vector<std::vector<memgraph::query::TypedValue>> AuthQueryHandler::GetDatabasePrivileges( std::vector<std::vector<memgraph::query::TypedValue>> AuthQueryHandler::GetDatabasePrivileges(
const std::string &username) { const std::string &username) {
if (!std::regex_match(username, name_regex_)) {
throw memgraph::query::QueryRuntimeException("Invalid user or role name.");
}
try { try {
auto locked_auth = auth_->ReadLock(); auto locked_auth = auth_->ReadLock();
auto user = locked_auth->GetUser(username); auto user = locked_auth->GetUser(username);
@ -394,9 +361,6 @@ std::vector<std::vector<memgraph::query::TypedValue>> AuthQueryHandler::GetDatab
} }
bool AuthQueryHandler::SetMainDatabase(std::string_view db, const std::string &username) { bool AuthQueryHandler::SetMainDatabase(std::string_view db, const std::string &username) {
if (!std::regex_match(username, name_regex_)) {
throw memgraph::query::QueryRuntimeException("Invalid user name.");
}
try { try {
auto locked_auth = auth_->Lock(); auto locked_auth = auth_->Lock();
auto user = locked_auth->GetUser(username); auto user = locked_auth->GetUser(username);
@ -417,9 +381,6 @@ void AuthQueryHandler::DeleteDatabase(std::string_view db) {
#endif #endif
bool AuthQueryHandler::DropRole(const std::string &rolename) { bool AuthQueryHandler::DropRole(const std::string &rolename) {
if (!std::regex_match(rolename, name_regex_)) {
throw memgraph::query::QueryRuntimeException("Invalid role name.");
}
try { try {
auto locked_auth = auth_->Lock(); auto locked_auth = auth_->Lock();
auto role = locked_auth->GetRole(rolename); auto role = locked_auth->GetRole(rolename);
@ -465,9 +426,6 @@ std::vector<memgraph::query::TypedValue> AuthQueryHandler::GetRolenames() {
} }
std::optional<std::string> AuthQueryHandler::GetRolenameForUser(const std::string &username) { std::optional<std::string> AuthQueryHandler::GetRolenameForUser(const std::string &username) {
if (!std::regex_match(username, name_regex_)) {
throw memgraph::query::QueryRuntimeException("Invalid user name.");
}
try { try {
auto locked_auth = auth_->ReadLock(); auto locked_auth = auth_->ReadLock();
auto user = locked_auth->GetUser(username); auto user = locked_auth->GetUser(username);
@ -485,9 +443,6 @@ std::optional<std::string> AuthQueryHandler::GetRolenameForUser(const std::strin
} }
std::vector<memgraph::query::TypedValue> AuthQueryHandler::GetUsernamesForRole(const std::string &rolename) { std::vector<memgraph::query::TypedValue> AuthQueryHandler::GetUsernamesForRole(const std::string &rolename) {
if (!std::regex_match(rolename, name_regex_)) {
throw memgraph::query::QueryRuntimeException("Invalid role name.");
}
try { try {
auto locked_auth = auth_->ReadLock(); auto locked_auth = auth_->ReadLock();
auto role = locked_auth->GetRole(rolename); auto role = locked_auth->GetRole(rolename);
@ -507,12 +462,6 @@ std::vector<memgraph::query::TypedValue> AuthQueryHandler::GetUsernamesForRole(c
} }
void AuthQueryHandler::SetRole(const std::string &username, const std::string &rolename) { void AuthQueryHandler::SetRole(const std::string &username, const std::string &rolename) {
if (!std::regex_match(username, name_regex_)) {
throw memgraph::query::QueryRuntimeException("Invalid user name.");
}
if (!std::regex_match(rolename, name_regex_)) {
throw memgraph::query::QueryRuntimeException("Invalid role name.");
}
try { try {
auto locked_auth = auth_->Lock(); auto locked_auth = auth_->Lock();
auto user = locked_auth->GetUser(username); auto user = locked_auth->GetUser(username);
@ -535,9 +484,6 @@ void AuthQueryHandler::SetRole(const std::string &username, const std::string &r
} }
void AuthQueryHandler::ClearRole(const std::string &username) { void AuthQueryHandler::ClearRole(const std::string &username) {
if (!std::regex_match(username, name_regex_)) {
throw memgraph::query::QueryRuntimeException("Invalid user name.");
}
try { try {
auto locked_auth = auth_->Lock(); auto locked_auth = auth_->Lock();
auto user = locked_auth->GetUser(username); auto user = locked_auth->GetUser(username);
@ -552,9 +498,6 @@ void AuthQueryHandler::ClearRole(const std::string &username) {
} }
std::vector<std::vector<memgraph::query::TypedValue>> AuthQueryHandler::GetPrivileges(const std::string &user_or_role) { std::vector<std::vector<memgraph::query::TypedValue>> AuthQueryHandler::GetPrivileges(const std::string &user_or_role) {
if (!std::regex_match(user_or_role, name_regex_)) {
throw memgraph::query::QueryRuntimeException("Invalid user or role name.");
}
try { try {
auto locked_auth = auth_->ReadLock(); auto locked_auth = auth_->ReadLock();
std::vector<std::vector<memgraph::query::TypedValue>> grants; std::vector<std::vector<memgraph::query::TypedValue>> grants;
@ -704,9 +647,6 @@ void AuthQueryHandler::EditPermissions(
const TEditFineGrainedPermissionsFun &edit_fine_grained_permissions_fun const TEditFineGrainedPermissionsFun &edit_fine_grained_permissions_fun
#endif #endif
) { ) {
if (!std::regex_match(user_or_role, name_regex_)) {
throw memgraph::query::QueryRuntimeException("Invalid user or role name.");
}
try { try {
std::vector<memgraph::auth::Permission> permissions; std::vector<memgraph::auth::Permission> permissions;
permissions.reserve(privileges.size()); permissions.reserve(privileges.size());

View File

@ -1,4 +1,4 @@
// Copyright 2023 Memgraph Ltd. // Copyright 2024 Memgraph Ltd.
// //
// Use of this software is governed by the Business Source License // 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 // included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
@ -24,12 +24,9 @@ namespace memgraph::glue {
class AuthQueryHandler final : public memgraph::query::AuthQueryHandler { class AuthQueryHandler final : public memgraph::query::AuthQueryHandler {
memgraph::utils::Synchronized<memgraph::auth::Auth, memgraph::utils::WritePrioritizedRWLock> *auth_; memgraph::utils::Synchronized<memgraph::auth::Auth, memgraph::utils::WritePrioritizedRWLock> *auth_;
std::string name_regex_string_;
std::regex name_regex_;
public: public:
AuthQueryHandler(memgraph::utils::Synchronized<memgraph::auth::Auth, memgraph::utils::WritePrioritizedRWLock> *auth, AuthQueryHandler(memgraph::utils::Synchronized<memgraph::auth::Auth, memgraph::utils::WritePrioritizedRWLock> *auth);
std::string name_regex_string);
bool CreateUser(const std::string &username, const std::optional<std::string> &password) override; bool CreateUser(const std::string &username, const std::optional<std::string> &password) override;

View File

@ -357,11 +357,10 @@ int main(int argc, char **argv) {
.stream_transaction_retry_interval = std::chrono::milliseconds(FLAGS_stream_transaction_retry_interval)}; .stream_transaction_retry_interval = std::chrono::milliseconds(FLAGS_stream_transaction_retry_interval)};
auto auth_glue = auto auth_glue =
[flag = FLAGS_auth_user_or_role_name_regex]( [](memgraph::utils::Synchronized<memgraph::auth::Auth, memgraph::utils::WritePrioritizedRWLock> *auth,
memgraph::utils::Synchronized<memgraph::auth::Auth, memgraph::utils::WritePrioritizedRWLock> *auth, std::unique_ptr<memgraph::query::AuthQueryHandler> &ah, std::unique_ptr<memgraph::query::AuthChecker> &ac) {
std::unique_ptr<memgraph::query::AuthQueryHandler> &ah, std::unique_ptr<memgraph::query::AuthChecker> &ac) {
// Glue high level auth implementations to the query side // Glue high level auth implementations to the query side
ah = std::make_unique<memgraph::glue::AuthQueryHandler>(auth, flag); ah = std::make_unique<memgraph::glue::AuthQueryHandler>(auth);
ac = std::make_unique<memgraph::glue::AuthChecker>(auth); ac = std::make_unique<memgraph::glue::AuthChecker>(auth);
// Handle users passed via arguments // Handle users passed via arguments
auto *maybe_username = std::getenv(kMgUser); auto *maybe_username = std::getenv(kMgUser);
@ -377,9 +376,10 @@ int main(int argc, char **argv) {
} }
}; };
// WIP memgraph::auth::Auth::Config auth_config{FLAGS_auth_user_or_role_name_regex, FLAGS_auth_password_strength_regex,
memgraph::utils::Synchronized<memgraph::auth::Auth, memgraph::utils::WritePrioritizedRWLock> auth_{data_directory / FLAGS_auth_password_permit_null};
"auth"}; memgraph::utils::Synchronized<memgraph::auth::Auth, memgraph::utils::WritePrioritizedRWLock> auth_{
data_directory / "auth", auth_config};
std::unique_ptr<memgraph::query::AuthQueryHandler> auth_handler; std::unique_ptr<memgraph::query::AuthQueryHandler> auth_handler;
std::unique_ptr<memgraph::query::AuthChecker> auth_checker; std::unique_ptr<memgraph::query::AuthChecker> auth_checker;
auth_glue(&auth_, auth_handler, auth_checker); auth_glue(&auth_, auth_handler, auth_checker);

View File

@ -1,4 +1,4 @@
// Copyright 2023 Memgraph Ltd. // Copyright 2024 Memgraph Ltd.
// //
// Use of this software is governed by the Business Source License // 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 // included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
@ -13,6 +13,7 @@
#include "dbms/dbms_handler.hpp" #include "dbms/dbms_handler.hpp"
#include "glue/auth_checker.hpp" #include "glue/auth_checker.hpp"
#include "glue/auth_global.hpp"
#include "glue/auth_handler.hpp" #include "glue/auth_handler.hpp"
#include "requests/requests.hpp" #include "requests/requests.hpp"
#include "storage/v2/config.hpp" #include "storage/v2/config.hpp"
@ -32,9 +33,10 @@ int main(int argc, char **argv) {
// Memgraph backend // Memgraph backend
std::filesystem::path data_directory{std::filesystem::temp_directory_path() / "MG_telemetry_integration_test"}; std::filesystem::path data_directory{std::filesystem::temp_directory_path() / "MG_telemetry_integration_test"};
memgraph::utils::Synchronized<memgraph::auth::Auth, memgraph::utils::WritePrioritizedRWLock> auth_{data_directory / memgraph::utils::Synchronized<memgraph::auth::Auth, memgraph::utils::WritePrioritizedRWLock> auth_{
"auth"}; data_directory / "auth",
memgraph::glue::AuthQueryHandler auth_handler(&auth_, ""); memgraph::auth::Auth::Config{std::string{memgraph::glue::kDefaultUserRoleRegex}, "", true}};
memgraph::glue::AuthQueryHandler auth_handler(&auth_);
memgraph::glue::AuthChecker auth_checker(&auth_); memgraph::glue::AuthChecker auth_checker(&auth_);
memgraph::storage::Config db_config; memgraph::storage::Config db_config;

View File

@ -1,4 +1,4 @@
// Copyright 2023 Memgraph Ltd. // Copyright 2024 Memgraph Ltd.
// //
// Use of this software is governed by the Business Source License // 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 // included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
@ -19,6 +19,7 @@
#include "auth/auth.hpp" #include "auth/auth.hpp"
#include "auth/crypto.hpp" #include "auth/crypto.hpp"
#include "auth/models.hpp" #include "auth/models.hpp"
#include "glue/auth_global.hpp"
#include "license/license.hpp" #include "license/license.hpp"
#include "utils/cast.hpp" #include "utils/cast.hpp"
#include "utils/file.hpp" #include "utils/file.hpp"
@ -26,90 +27,70 @@
using namespace memgraph::auth; using namespace memgraph::auth;
namespace fs = std::filesystem; namespace fs = std::filesystem;
DECLARE_bool(auth_password_permit_null);
DECLARE_string(auth_password_strength_regex);
DECLARE_string(password_encryption_algorithm); DECLARE_string(password_encryption_algorithm);
class AuthWithStorage : public ::testing::Test { class AuthWithStorage : public ::testing::Test {
protected: protected:
void SetUp() override { void SetUp() override {
memgraph::utils::EnsureDir(test_folder_); memgraph::utils::EnsureDir(test_folder_);
FLAGS_auth_password_permit_null = true;
FLAGS_auth_password_strength_regex = ".+";
memgraph::license::global_license_checker.EnableTesting(); memgraph::license::global_license_checker.EnableTesting();
auth.emplace(test_folder_ / ("unit_auth_test_" + std::to_string(static_cast<int>(getpid()))), auth_config);
} }
void TearDown() override { fs::remove_all(test_folder_); } void TearDown() override { fs::remove_all(test_folder_); }
fs::path test_folder_{fs::temp_directory_path() / "MG_tests_unit_auth"}; fs::path test_folder_{fs::temp_directory_path() / "MG_tests_unit_auth"};
Auth::Config auth_config{};
Auth auth{test_folder_ / ("unit_auth_test_" + std::to_string(static_cast<int>(getpid())))}; std::optional<Auth> auth{};
}; };
TEST_F(AuthWithStorage, AddRole) { TEST_F(AuthWithStorage, AddRole) {
ASSERT_TRUE(auth.AddRole("admin")); ASSERT_TRUE(auth->AddRole("admin"));
ASSERT_TRUE(auth.AddRole("user")); ASSERT_TRUE(auth->AddRole("user"));
ASSERT_FALSE(auth.AddRole("admin")); ASSERT_FALSE(auth->AddRole("admin"));
} }
TEST_F(AuthWithStorage, RemoveRole) { TEST_F(AuthWithStorage, RemoveRole) {
ASSERT_TRUE(auth.AddRole("admin")); ASSERT_TRUE(auth->AddRole("admin"));
ASSERT_TRUE(auth.RemoveRole("admin")); ASSERT_TRUE(auth->RemoveRole("admin"));
class AuthWithStorage : public ::testing::Test { ASSERT_FALSE(auth->HasUsers());
protected: ASSERT_FALSE(auth->RemoveUser("test2"));
void SetUp() override { ASSERT_FALSE(auth->RemoveUser("test"));
memgraph::utils::EnsureDir(test_folder_); ASSERT_FALSE(auth->HasUsers());
FLAGS_auth_password_permit_null = true;
FLAGS_auth_password_strength_regex = ".+";
memgraph::license::global_license_checker.EnableTesting();
}
void TearDown() override { fs::remove_all(test_folder_); }
fs::path test_folder_{fs::temp_directory_path() / "MG_tests_unit_auth"};
Auth auth{test_folder_ / ("unit_auth_test_" + std::to_string(static_cast<int>(getpid())))};
};
ASSERT_FALSE(auth.HasUsers());
ASSERT_FALSE(auth.RemoveUser("test2"));
ASSERT_FALSE(auth.RemoveUser("test"));
ASSERT_FALSE(auth.HasUsers());
} }
TEST_F(AuthWithStorage, Authenticate) { TEST_F(AuthWithStorage, Authenticate) {
ASSERT_FALSE(auth.HasUsers()); ASSERT_FALSE(auth->HasUsers());
auto user = auth.AddUser("test"); auto user = auth->AddUser("test");
ASSERT_NE(user, std::nullopt); ASSERT_NE(user, std::nullopt);
ASSERT_TRUE(auth.HasUsers()); ASSERT_TRUE(auth->HasUsers());
ASSERT_TRUE(auth.Authenticate("test", "123")); ASSERT_TRUE(auth->Authenticate("test", "123"));
user->UpdatePassword("123"); user->UpdatePassword("123");
auth.SaveUser(*user); auth->SaveUser(*user);
ASSERT_NE(auth.Authenticate("test", "123"), std::nullopt); ASSERT_NE(auth->Authenticate("test", "123"), std::nullopt);
ASSERT_EQ(auth.Authenticate("test", "456"), std::nullopt); ASSERT_EQ(auth->Authenticate("test", "456"), std::nullopt);
ASSERT_NE(auth.Authenticate("test", "123"), std::nullopt); ASSERT_NE(auth->Authenticate("test", "123"), std::nullopt);
user->UpdatePassword(); user->UpdatePassword();
auth.SaveUser(*user); auth->SaveUser(*user);
ASSERT_NE(auth.Authenticate("test", "123"), std::nullopt); ASSERT_NE(auth->Authenticate("test", "123"), std::nullopt);
ASSERT_NE(auth.Authenticate("test", "456"), std::nullopt); ASSERT_NE(auth->Authenticate("test", "456"), std::nullopt);
ASSERT_EQ(auth.Authenticate("nonexistant", "123"), std::nullopt); ASSERT_EQ(auth->Authenticate("nonexistant", "123"), std::nullopt);
} }
TEST_F(AuthWithStorage, UserRolePermissions) { TEST_F(AuthWithStorage, UserRolePermissions) {
ASSERT_FALSE(auth.HasUsers()); ASSERT_FALSE(auth->HasUsers());
ASSERT_TRUE(auth.AddUser("test")); ASSERT_TRUE(auth->AddUser("test"));
ASSERT_TRUE(auth.HasUsers()); ASSERT_TRUE(auth->HasUsers());
auto user = auth.GetUser("test"); auto user = auth->GetUser("test");
ASSERT_NE(user, std::nullopt); ASSERT_NE(user, std::nullopt);
// Test initial user permissions. // Test initial user permissions.
@ -130,8 +111,8 @@ TEST_F(AuthWithStorage, UserRolePermissions) {
ASSERT_EQ(user->permissions(), user->GetPermissions()); ASSERT_EQ(user->permissions(), user->GetPermissions());
// Create role. // Create role.
ASSERT_TRUE(auth.AddRole("admin")); ASSERT_TRUE(auth->AddRole("admin"));
auto role = auth.GetRole("admin"); auto role = auth->GetRole("admin");
ASSERT_NE(role, std::nullopt); ASSERT_NE(role, std::nullopt);
// Assign permissions to role and role to user. // Assign permissions to role and role to user.
@ -163,11 +144,11 @@ TEST_F(AuthWithStorage, UserRolePermissions) {
#ifdef MG_ENTERPRISE #ifdef MG_ENTERPRISE
TEST_F(AuthWithStorage, UserRoleFineGrainedAccessHandler) { TEST_F(AuthWithStorage, UserRoleFineGrainedAccessHandler) {
ASSERT_FALSE(auth.HasUsers()); ASSERT_FALSE(auth->HasUsers());
ASSERT_TRUE(auth.AddUser("test")); ASSERT_TRUE(auth->AddUser("test"));
ASSERT_TRUE(auth.HasUsers()); ASSERT_TRUE(auth->HasUsers());
auto user = auth.GetUser("test"); auto user = auth->GetUser("test");
ASSERT_NE(user, std::nullopt); ASSERT_NE(user, std::nullopt);
// Test initial user fine grained access permissions. // Test initial user fine grained access permissions.
@ -204,8 +185,8 @@ TEST_F(AuthWithStorage, UserRoleFineGrainedAccessHandler) {
user->GetFineGrainedAccessEdgeTypePermissions()); user->GetFineGrainedAccessEdgeTypePermissions());
// Create role. // Create role.
ASSERT_TRUE(auth.AddRole("admin")); ASSERT_TRUE(auth->AddRole("admin"));
auto role = auth.GetRole("admin"); auto role = auth->GetRole("admin");
ASSERT_NE(role, std::nullopt); ASSERT_NE(role, std::nullopt);
// Grant label and edge type to role and role to user. // Grant label and edge type to role and role to user.
@ -236,44 +217,44 @@ TEST_F(AuthWithStorage, UserRoleFineGrainedAccessHandler) {
TEST_F(AuthWithStorage, RoleManipulations) { TEST_F(AuthWithStorage, RoleManipulations) {
{ {
auto user1 = auth.AddUser("user1"); auto user1 = auth->AddUser("user1");
ASSERT_TRUE(user1); ASSERT_TRUE(user1);
auto role1 = auth.AddRole("role1"); auto role1 = auth->AddRole("role1");
ASSERT_TRUE(role1); ASSERT_TRUE(role1);
user1->SetRole(*role1); user1->SetRole(*role1);
auth.SaveUser(*user1); auth->SaveUser(*user1);
auto user2 = auth.AddUser("user2"); auto user2 = auth->AddUser("user2");
ASSERT_TRUE(user2); ASSERT_TRUE(user2);
auto role2 = auth.AddRole("role2"); auto role2 = auth->AddRole("role2");
ASSERT_TRUE(role2); ASSERT_TRUE(role2);
user2->SetRole(*role2); user2->SetRole(*role2);
auth.SaveUser(*user2); auth->SaveUser(*user2);
} }
{ {
auto user1 = auth.GetUser("user1"); auto user1 = auth->GetUser("user1");
ASSERT_TRUE(user1); ASSERT_TRUE(user1);
const auto *role1 = user1->role(); const auto *role1 = user1->role();
ASSERT_NE(role1, nullptr); ASSERT_NE(role1, nullptr);
ASSERT_EQ(role1->rolename(), "role1"); ASSERT_EQ(role1->rolename(), "role1");
auto user2 = auth.GetUser("user2"); auto user2 = auth->GetUser("user2");
ASSERT_TRUE(user2); ASSERT_TRUE(user2);
const auto *role2 = user2->role(); const auto *role2 = user2->role();
ASSERT_NE(role2, nullptr); ASSERT_NE(role2, nullptr);
ASSERT_EQ(role2->rolename(), "role2"); ASSERT_EQ(role2->rolename(), "role2");
} }
ASSERT_TRUE(auth.RemoveRole("role1")); ASSERT_TRUE(auth->RemoveRole("role1"));
{ {
auto user1 = auth.GetUser("user1"); auto user1 = auth->GetUser("user1");
ASSERT_TRUE(user1); ASSERT_TRUE(user1);
const auto *role = user1->role(); const auto *role = user1->role();
ASSERT_EQ(role, nullptr); ASSERT_EQ(role, nullptr);
auto user2 = auth.GetUser("user2"); auto user2 = auth->GetUser("user2");
ASSERT_TRUE(user2); ASSERT_TRUE(user2);
const auto *role2 = user2->role(); const auto *role2 = user2->role();
ASSERT_NE(role2, nullptr); ASSERT_NE(role2, nullptr);
@ -281,17 +262,17 @@ TEST_F(AuthWithStorage, RoleManipulations) {
} }
{ {
auto role1 = auth.AddRole("role1"); auto role1 = auth->AddRole("role1");
ASSERT_TRUE(role1); ASSERT_TRUE(role1);
} }
{ {
auto user1 = auth.GetUser("user1"); auto user1 = auth->GetUser("user1");
ASSERT_TRUE(user1); ASSERT_TRUE(user1);
const auto *role1 = user1->role(); const auto *role1 = user1->role();
ASSERT_EQ(role1, nullptr); ASSERT_EQ(role1, nullptr);
auto user2 = auth.GetUser("user2"); auto user2 = auth->GetUser("user2");
ASSERT_TRUE(user2); ASSERT_TRUE(user2);
const auto *role2 = user2->role(); const auto *role2 = user2->role();
ASSERT_NE(role2, nullptr); ASSERT_NE(role2, nullptr);
@ -299,7 +280,7 @@ TEST_F(AuthWithStorage, RoleManipulations) {
} }
{ {
auto users = auth.AllUsers(); auto users = auth->AllUsers();
std::sort(users.begin(), users.end(), [](const User &a, const User &b) { return a.username() < b.username(); }); std::sort(users.begin(), users.end(), [](const User &a, const User &b) { return a.username() < b.username(); });
ASSERT_EQ(users.size(), 2); ASSERT_EQ(users.size(), 2);
ASSERT_EQ(users[0].username(), "user1"); ASSERT_EQ(users[0].username(), "user1");
@ -307,7 +288,7 @@ TEST_F(AuthWithStorage, RoleManipulations) {
} }
{ {
auto roles = auth.AllRoles(); auto roles = auth->AllRoles();
std::sort(roles.begin(), roles.end(), [](const Role &a, const Role &b) { return a.rolename() < b.rolename(); }); std::sort(roles.begin(), roles.end(), [](const Role &a, const Role &b) { return a.rolename() < b.rolename(); });
ASSERT_EQ(roles.size(), 2); ASSERT_EQ(roles.size(), 2);
ASSERT_EQ(roles[0].rolename(), "role1"); ASSERT_EQ(roles[0].rolename(), "role1");
@ -315,7 +296,7 @@ TEST_F(AuthWithStorage, RoleManipulations) {
} }
{ {
auto users = auth.AllUsersForRole("role2"); auto users = auth->AllUsersForRole("role2");
ASSERT_EQ(users.size(), 1); ASSERT_EQ(users.size(), 1);
ASSERT_EQ(users[0].username(), "user2"); ASSERT_EQ(users[0].username(), "user2");
} }
@ -323,16 +304,16 @@ TEST_F(AuthWithStorage, RoleManipulations) {
TEST_F(AuthWithStorage, UserRoleLinkUnlink) { TEST_F(AuthWithStorage, UserRoleLinkUnlink) {
{ {
auto user = auth.AddUser("user"); auto user = auth->AddUser("user");
ASSERT_TRUE(user); ASSERT_TRUE(user);
auto role = auth.AddRole("role"); auto role = auth->AddRole("role");
ASSERT_TRUE(role); ASSERT_TRUE(role);
user->SetRole(*role); user->SetRole(*role);
auth.SaveUser(*user); auth->SaveUser(*user);
} }
{ {
auto user = auth.GetUser("user"); auto user = auth->GetUser("user");
ASSERT_TRUE(user); ASSERT_TRUE(user);
const auto *role = user->role(); const auto *role = user->role();
ASSERT_NE(role, nullptr); ASSERT_NE(role, nullptr);
@ -340,14 +321,14 @@ TEST_F(AuthWithStorage, UserRoleLinkUnlink) {
} }
{ {
auto user = auth.GetUser("user"); auto user = auth->GetUser("user");
ASSERT_TRUE(user); ASSERT_TRUE(user);
user->ClearRole(); user->ClearRole();
auth.SaveUser(*user); auth->SaveUser(*user);
} }
{ {
auto user = auth.GetUser("user"); auto user = auth->GetUser("user");
ASSERT_TRUE(user); ASSERT_TRUE(user);
ASSERT_EQ(user->role(), nullptr); ASSERT_EQ(user->role(), nullptr);
} }
@ -355,19 +336,19 @@ TEST_F(AuthWithStorage, UserRoleLinkUnlink) {
TEST_F(AuthWithStorage, UserPasswordCreation) { TEST_F(AuthWithStorage, UserPasswordCreation) {
{ {
auto user = auth.AddUser("test"); auto user = auth->AddUser("test");
ASSERT_TRUE(user); ASSERT_TRUE(user);
ASSERT_TRUE(auth.Authenticate("test", "123")); ASSERT_TRUE(auth->Authenticate("test", "123"));
ASSERT_TRUE(auth.Authenticate("test", "456")); ASSERT_TRUE(auth->Authenticate("test", "456"));
ASSERT_TRUE(auth.RemoveUser(user->username())); ASSERT_TRUE(auth->RemoveUser(user->username()));
} }
{ {
auto user = auth.AddUser("test", "123"); auto user = auth->AddUser("test", "123");
ASSERT_TRUE(user); ASSERT_TRUE(user);
ASSERT_TRUE(auth.Authenticate("test", "123")); ASSERT_TRUE(auth->Authenticate("test", "123"));
ASSERT_FALSE(auth.Authenticate("test", "456")); ASSERT_FALSE(auth->Authenticate("test", "456"));
ASSERT_TRUE(auth.RemoveUser(user->username())); ASSERT_TRUE(auth->RemoveUser(user->username()));
} }
} }
@ -382,36 +363,53 @@ TEST_F(AuthWithStorage, PasswordStrength) {
const std::string kAlmostStrongPassword = "ThisPasswordMeetsAllButOneCriterion1234"; const std::string kAlmostStrongPassword = "ThisPasswordMeetsAllButOneCriterion1234";
const std::string kStrongPassword = "ThisIsAVeryStrongPassword123$"; const std::string kStrongPassword = "ThisIsAVeryStrongPassword123$";
auto user = auth.AddUser("user"); {
ASSERT_TRUE(user); auth.reset();
auth.emplace(test_folder_ / ("unit_auth_test_" + std::to_string(static_cast<int>(getpid()))),
Auth::Config{std::string{memgraph::glue::kDefaultUserRoleRegex}, kWeakRegex, true});
auto user = auth->AddUser("user1");
ASSERT_TRUE(user);
ASSERT_NO_THROW(auth->UpdatePassword(*user, std::nullopt));
ASSERT_NO_THROW(auth->UpdatePassword(*user, kWeakPassword));
ASSERT_NO_THROW(auth->UpdatePassword(*user, kAlmostStrongPassword));
ASSERT_NO_THROW(auth->UpdatePassword(*user, kStrongPassword));
}
FLAGS_auth_password_permit_null = true; {
FLAGS_auth_password_strength_regex = kWeakRegex; auth.reset();
ASSERT_NO_THROW(user->UpdatePassword()); auth.emplace(test_folder_ / ("unit_auth_test_" + std::to_string(static_cast<int>(getpid()))),
ASSERT_NO_THROW(user->UpdatePassword(kWeakPassword)); Auth::Config{std::string{memgraph::glue::kDefaultUserRoleRegex}, kWeakRegex, false});
ASSERT_NO_THROW(user->UpdatePassword(kAlmostStrongPassword)); ASSERT_THROW(auth->AddUser("user2", std::nullopt), AuthException);
ASSERT_NO_THROW(user->UpdatePassword(kStrongPassword)); auto user = auth->AddUser("user2", kWeakPassword);
ASSERT_TRUE(user);
ASSERT_NO_THROW(auth->UpdatePassword(*user, kWeakPassword));
ASSERT_NO_THROW(auth->UpdatePassword(*user, kAlmostStrongPassword));
ASSERT_NO_THROW(auth->UpdatePassword(*user, kStrongPassword));
}
FLAGS_auth_password_permit_null = false; {
FLAGS_auth_password_strength_regex = kWeakRegex; auth.reset();
ASSERT_THROW(user->UpdatePassword(), AuthException); auth.emplace(test_folder_ / ("unit_auth_test_" + std::to_string(static_cast<int>(getpid()))),
ASSERT_NO_THROW(user->UpdatePassword(kWeakPassword)); Auth::Config{std::string{memgraph::glue::kDefaultUserRoleRegex}, kStrongRegex, true});
ASSERT_NO_THROW(user->UpdatePassword(kAlmostStrongPassword)); auto user = auth->AddUser("user3");
ASSERT_NO_THROW(user->UpdatePassword(kStrongPassword)); ASSERT_TRUE(user);
ASSERT_NO_THROW(auth->UpdatePassword(*user, std::nullopt));
ASSERT_THROW(auth->UpdatePassword(*user, kWeakPassword), AuthException);
ASSERT_THROW(auth->UpdatePassword(*user, kAlmostStrongPassword), AuthException);
ASSERT_NO_THROW(auth->UpdatePassword(*user, kStrongPassword));
}
FLAGS_auth_password_permit_null = true; {
FLAGS_auth_password_strength_regex = kStrongRegex; auth.reset();
ASSERT_NO_THROW(user->UpdatePassword()); auth.emplace(test_folder_ / ("unit_auth_test_" + std::to_string(static_cast<int>(getpid()))),
ASSERT_THROW(user->UpdatePassword(kWeakPassword), AuthException); Auth::Config{std::string{memgraph::glue::kDefaultUserRoleRegex}, kStrongRegex, false});
ASSERT_THROW(user->UpdatePassword(kAlmostStrongPassword), AuthException); ASSERT_THROW(auth->AddUser("user4", std::nullopt);, AuthException);
ASSERT_NO_THROW(user->UpdatePassword(kStrongPassword)); ASSERT_THROW(auth->AddUser("user4", kWeakPassword);, AuthException);
ASSERT_THROW(auth->AddUser("user4", kAlmostStrongPassword);, AuthException);
FLAGS_auth_password_permit_null = false; auto user = auth->AddUser("user4", kStrongPassword);
FLAGS_auth_password_strength_regex = kStrongRegex; ASSERT_TRUE(user);
ASSERT_THROW(user->UpdatePassword(), AuthException); ASSERT_NO_THROW(auth->UpdatePassword(*user, kStrongPassword));
ASSERT_THROW(user->UpdatePassword(kWeakPassword), AuthException); }
ASSERT_THROW(user->UpdatePassword(kAlmostStrongPassword), AuthException);
ASSERT_NO_THROW(user->UpdatePassword(kStrongPassword));
} }
TEST(AuthWithoutStorage, Permissions) { TEST(AuthWithoutStorage, Permissions) {
@ -680,30 +678,30 @@ TEST(AuthWithoutStorage, RoleSerializeDeserialize) {
} }
TEST_F(AuthWithStorage, UserWithRoleSerializeDeserialize) { TEST_F(AuthWithStorage, UserWithRoleSerializeDeserialize) {
auto role = auth.AddRole("role"); auto role = auth->AddRole("role");
ASSERT_TRUE(role); ASSERT_TRUE(role);
role->permissions().Grant(Permission::MATCH); role->permissions().Grant(Permission::MATCH);
role->permissions().Deny(Permission::MERGE); role->permissions().Deny(Permission::MERGE);
auth.SaveRole(*role); auth->SaveRole(*role);
auto user = auth.AddUser("user"); auto user = auth->AddUser("user");
ASSERT_TRUE(user); ASSERT_TRUE(user);
user->permissions().Grant(Permission::MATCH); user->permissions().Grant(Permission::MATCH);
user->permissions().Deny(Permission::MERGE); user->permissions().Deny(Permission::MERGE);
user->UpdatePassword("world"); user->UpdatePassword("world");
user->SetRole(*role); user->SetRole(*role);
auth.SaveUser(*user); auth->SaveUser(*user);
auto new_user = auth.GetUser("user"); auto new_user = auth->GetUser("user");
ASSERT_TRUE(new_user); ASSERT_TRUE(new_user);
ASSERT_EQ(*user, *new_user); ASSERT_EQ(*user, *new_user);
} }
TEST_F(AuthWithStorage, UserRoleUniqueName) { TEST_F(AuthWithStorage, UserRoleUniqueName) {
ASSERT_TRUE(auth.AddUser("user")); ASSERT_TRUE(auth->AddUser("user"));
ASSERT_TRUE(auth.AddRole("role")); ASSERT_TRUE(auth->AddRole("role"));
ASSERT_FALSE(auth.AddRole("user")); ASSERT_FALSE(auth->AddRole("user"));
ASSERT_FALSE(auth.AddUser("role")); ASSERT_FALSE(auth->AddUser("role"));
} }
TEST(AuthWithoutStorage, CaseInsensitivity) { TEST(AuthWithoutStorage, CaseInsensitivity) {
@ -748,58 +746,58 @@ TEST(AuthWithoutStorage, CaseInsensitivity) {
TEST_F(AuthWithStorage, CaseInsensitivity) { TEST_F(AuthWithStorage, CaseInsensitivity) {
// AddUser // AddUser
{ {
auto user = auth.AddUser("Alice", "alice"); auto user = auth->AddUser("Alice", "alice");
ASSERT_TRUE(user); ASSERT_TRUE(user);
ASSERT_EQ(user->username(), "alice"); ASSERT_EQ(user->username(), "alice");
ASSERT_FALSE(auth.AddUser("alice")); ASSERT_FALSE(auth->AddUser("alice"));
ASSERT_FALSE(auth.AddUser("alicE")); ASSERT_FALSE(auth->AddUser("alicE"));
} }
{ {
auto user = auth.AddUser("BoB", "bob"); auto user = auth->AddUser("BoB", "bob");
ASSERT_TRUE(user); ASSERT_TRUE(user);
ASSERT_EQ(user->username(), "bob"); ASSERT_EQ(user->username(), "bob");
ASSERT_FALSE(auth.AddUser("bob")); ASSERT_FALSE(auth->AddUser("bob"));
ASSERT_FALSE(auth.AddUser("bOb")); ASSERT_FALSE(auth->AddUser("bOb"));
} }
// Authenticate // Authenticate
{ {
auto user = auth.Authenticate("alice", "alice"); auto user = auth->Authenticate("alice", "alice");
ASSERT_TRUE(user); ASSERT_TRUE(user);
ASSERT_EQ(user->username(), "alice"); ASSERT_EQ(user->username(), "alice");
} }
{ {
auto user = auth.Authenticate("alICe", "alice"); auto user = auth->Authenticate("alICe", "alice");
ASSERT_TRUE(user); ASSERT_TRUE(user);
ASSERT_EQ(user->username(), "alice"); ASSERT_EQ(user->username(), "alice");
} }
// GetUser // GetUser
{ {
auto user = auth.GetUser("alice"); auto user = auth->GetUser("alice");
ASSERT_TRUE(user); ASSERT_TRUE(user);
ASSERT_EQ(user->username(), "alice"); ASSERT_EQ(user->username(), "alice");
} }
{ {
auto user = auth.GetUser("aLicE"); auto user = auth->GetUser("aLicE");
ASSERT_TRUE(user); ASSERT_TRUE(user);
ASSERT_EQ(user->username(), "alice"); ASSERT_EQ(user->username(), "alice");
} }
ASSERT_FALSE(auth.GetUser("carol")); ASSERT_FALSE(auth->GetUser("carol"));
// RemoveUser // RemoveUser
{ {
auto user = auth.AddUser("caRol", "carol"); auto user = auth->AddUser("caRol", "carol");
ASSERT_TRUE(user); ASSERT_TRUE(user);
ASSERT_EQ(user->username(), "carol"); ASSERT_EQ(user->username(), "carol");
ASSERT_TRUE(auth.RemoveUser("cAROl")); ASSERT_TRUE(auth->RemoveUser("cAROl"));
ASSERT_FALSE(auth.RemoveUser("carol")); ASSERT_FALSE(auth->RemoveUser("carol"));
ASSERT_FALSE(auth.GetUser("CAROL")); ASSERT_FALSE(auth->GetUser("CAROL"));
} }
// AllUsers // AllUsers
{ {
auto users = auth.AllUsers(); auto users = auth->AllUsers();
ASSERT_EQ(users.size(), 2); ASSERT_EQ(users.size(), 2);
std::sort(users.begin(), users.end(), [](const auto &a, const auto &b) { return a.username() < b.username(); }); std::sort(users.begin(), users.end(), [](const auto &a, const auto &b) { return a.username() < b.username(); });
ASSERT_EQ(users[0].username(), "alice"); ASSERT_EQ(users[0].username(), "alice");
@ -808,48 +806,48 @@ TEST_F(AuthWithStorage, CaseInsensitivity) {
// AddRole // AddRole
{ {
auto role = auth.AddRole("Moderator"); auto role = auth->AddRole("Moderator");
ASSERT_TRUE(role); ASSERT_TRUE(role);
ASSERT_EQ(role->rolename(), "moderator"); ASSERT_EQ(role->rolename(), "moderator");
ASSERT_FALSE(auth.AddRole("moderator")); ASSERT_FALSE(auth->AddRole("moderator"));
ASSERT_FALSE(auth.AddRole("MODERATOR")); ASSERT_FALSE(auth->AddRole("MODERATOR"));
} }
{ {
auto role = auth.AddRole("adMIN"); auto role = auth->AddRole("adMIN");
ASSERT_TRUE(role); ASSERT_TRUE(role);
ASSERT_EQ(role->rolename(), "admin"); ASSERT_EQ(role->rolename(), "admin");
ASSERT_FALSE(auth.AddRole("Admin")); ASSERT_FALSE(auth->AddRole("Admin"));
ASSERT_FALSE(auth.AddRole("ADMIn")); ASSERT_FALSE(auth->AddRole("ADMIn"));
} }
ASSERT_FALSE(auth.AddRole("ALICE")); ASSERT_FALSE(auth->AddRole("ALICE"));
ASSERT_FALSE(auth.AddUser("ModeRAtor")); ASSERT_FALSE(auth->AddUser("ModeRAtor"));
// GetRole // GetRole
{ {
auto role = auth.GetRole("moderator"); auto role = auth->GetRole("moderator");
ASSERT_TRUE(role); ASSERT_TRUE(role);
ASSERT_EQ(role->rolename(), "moderator"); ASSERT_EQ(role->rolename(), "moderator");
} }
{ {
auto role = auth.GetRole("MoDERATOR"); auto role = auth->GetRole("MoDERATOR");
ASSERT_TRUE(role); ASSERT_TRUE(role);
ASSERT_EQ(role->rolename(), "moderator"); ASSERT_EQ(role->rolename(), "moderator");
} }
ASSERT_FALSE(auth.GetRole("root")); ASSERT_FALSE(auth->GetRole("root"));
// RemoveRole // RemoveRole
{ {
auto role = auth.AddRole("RooT"); auto role = auth->AddRole("RooT");
ASSERT_TRUE(role); ASSERT_TRUE(role);
ASSERT_EQ(role->rolename(), "root"); ASSERT_EQ(role->rolename(), "root");
ASSERT_TRUE(auth.RemoveRole("rOOt")); ASSERT_TRUE(auth->RemoveRole("rOOt"));
ASSERT_FALSE(auth.RemoveRole("RoOt")); ASSERT_FALSE(auth->RemoveRole("RoOt"));
ASSERT_FALSE(auth.GetRole("RoOt")); ASSERT_FALSE(auth->GetRole("RoOt"));
} }
// AllRoles // AllRoles
{ {
auto roles = auth.AllRoles(); auto roles = auth->AllRoles();
ASSERT_EQ(roles.size(), 2); ASSERT_EQ(roles.size(), 2);
std::sort(roles.begin(), roles.end(), [](const auto &a, const auto &b) { return a.rolename() < b.rolename(); }); std::sort(roles.begin(), roles.end(), [](const auto &a, const auto &b) { return a.rolename() < b.rolename(); });
ASSERT_EQ(roles[0].rolename(), "admin"); ASSERT_EQ(roles[0].rolename(), "admin");
@ -858,14 +856,14 @@ TEST_F(AuthWithStorage, CaseInsensitivity) {
// SaveRole // SaveRole
{ {
auto role = auth.GetRole("MODErator"); auto role = auth->GetRole("MODErator");
ASSERT_TRUE(role); ASSERT_TRUE(role);
ASSERT_EQ(role->rolename(), "moderator"); ASSERT_EQ(role->rolename(), "moderator");
role->permissions().Grant(memgraph::auth::Permission::MATCH); role->permissions().Grant(memgraph::auth::Permission::MATCH);
auth.SaveRole(*role); auth->SaveRole(*role);
} }
{ {
auto role = auth.GetRole("modeRATOR"); auto role = auth->GetRole("modeRATOR");
ASSERT_TRUE(role); ASSERT_TRUE(role);
ASSERT_EQ(role->rolename(), "moderator"); ASSERT_EQ(role->rolename(), "moderator");
ASSERT_EQ(role->permissions().Has(memgraph::auth::Permission::MATCH), memgraph::auth::PermissionLevel::GRANT); ASSERT_EQ(role->permissions().Has(memgraph::auth::Permission::MATCH), memgraph::auth::PermissionLevel::GRANT);
@ -873,17 +871,17 @@ TEST_F(AuthWithStorage, CaseInsensitivity) {
// SaveUser // SaveUser
{ {
auto user = auth.GetUser("aLice"); auto user = auth->GetUser("aLice");
ASSERT_TRUE(user); ASSERT_TRUE(user);
ASSERT_EQ(user->username(), "alice"); ASSERT_EQ(user->username(), "alice");
auto role = auth.GetRole("moderAtor"); auto role = auth->GetRole("moderAtor");
ASSERT_TRUE(role); ASSERT_TRUE(role);
ASSERT_EQ(role->rolename(), "moderator"); ASSERT_EQ(role->rolename(), "moderator");
user->SetRole(*role); user->SetRole(*role);
auth.SaveUser(*user); auth->SaveUser(*user);
} }
{ {
auto user = auth.GetUser("aLIce"); auto user = auth->GetUser("aLIce");
ASSERT_TRUE(user); ASSERT_TRUE(user);
ASSERT_EQ(user->username(), "alice"); ASSERT_EQ(user->username(), "alice");
const auto *role = user->role(); const auto *role = user->role();
@ -893,27 +891,27 @@ TEST_F(AuthWithStorage, CaseInsensitivity) {
// AllUsersForRole // AllUsersForRole
{ {
auto carol = auth.AddUser("caROl"); auto carol = auth->AddUser("caROl");
ASSERT_TRUE(carol); ASSERT_TRUE(carol);
ASSERT_EQ(carol->username(), "carol"); ASSERT_EQ(carol->username(), "carol");
auto dave = auth.AddUser("daVe"); auto dave = auth->AddUser("daVe");
ASSERT_TRUE(dave); ASSERT_TRUE(dave);
ASSERT_EQ(dave->username(), "dave"); ASSERT_EQ(dave->username(), "dave");
auto admin = auth.GetRole("aDMin"); auto admin = auth->GetRole("aDMin");
ASSERT_TRUE(admin); ASSERT_TRUE(admin);
ASSERT_EQ(admin->rolename(), "admin"); ASSERT_EQ(admin->rolename(), "admin");
carol->SetRole(*admin); carol->SetRole(*admin);
auth.SaveUser(*carol); auth->SaveUser(*carol);
dave->SetRole(*admin); dave->SetRole(*admin);
auth.SaveUser(*dave); auth->SaveUser(*dave);
} }
{ {
auto users = auth.AllUsersForRole("modeRAtoR"); auto users = auth->AllUsersForRole("modeRAtoR");
ASSERT_EQ(users.size(), 1); ASSERT_EQ(users.size(), 1);
ASSERT_EQ(users[0].username(), "alice"); ASSERT_EQ(users[0].username(), "alice");
} }
{ {
auto users = auth.AllUsersForRole("AdmiN"); auto users = auth->AllUsersForRole("AdmiN");
ASSERT_EQ(users.size(), 2); ASSERT_EQ(users.size(), 2);
std::sort(users.begin(), users.end(), [](const auto &a, const auto &b) { return a.username() < b.username(); }); std::sort(users.begin(), users.end(), [](const auto &a, const auto &b) { return a.username() < b.username(); });
ASSERT_EQ(users[0].username(), "carol"); ASSERT_EQ(users[0].username(), "carol");
@ -966,18 +964,15 @@ class AuthWithStorageWithVariousEncryptionAlgorithms : public ::testing::Test {
protected: protected:
void SetUp() override { void SetUp() override {
memgraph::utils::EnsureDir(test_folder_); memgraph::utils::EnsureDir(test_folder_);
FLAGS_auth_password_permit_null = true;
FLAGS_auth_password_strength_regex = ".+";
FLAGS_password_encryption_algorithm = "bcrypt"; FLAGS_password_encryption_algorithm = "bcrypt";
memgraph::license::global_license_checker.EnableTesting(); memgraph::license::global_license_checker.EnableTesting();
} }
void TearDown() override { fs::remove_all(test_folder_); } void TearDown() override { fs::remove_all(test_folder_); }
fs::path test_folder_{fs::temp_directory_path() / "MG_tests_unit_auth"}; fs::path test_folder_{fs::temp_directory_path() / "MG_tests_unit_auth"};
Auth::Config auth_config{};
Auth auth{test_folder_ / ("unit_auth_test_" + std::to_string(static_cast<int>(getpid())))}; Auth auth{test_folder_ / ("unit_auth_test_" + std::to_string(static_cast<int>(getpid()))), auth_config};
}; };
TEST_F(AuthWithStorageWithVariousEncryptionAlgorithms, AddUserDefault) { TEST_F(AuthWithStorageWithVariousEncryptionAlgorithms, AddUserDefault) {

View File

@ -1,4 +1,4 @@
// Copyright 2023 Memgraph Ltd. // Copyright 2024 Memgraph Ltd.
// //
// Use of this software is governed by the Business Source License // 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 // included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
@ -26,8 +26,9 @@ class AuthQueryHandlerFixture : public testing::Test {
protected: protected:
std::filesystem::path test_folder_{std::filesystem::temp_directory_path() / "MG_tests_unit_auth_handler"}; std::filesystem::path test_folder_{std::filesystem::temp_directory_path() / "MG_tests_unit_auth_handler"};
memgraph::utils::Synchronized<memgraph::auth::Auth, memgraph::utils::WritePrioritizedRWLock> auth{ memgraph::utils::Synchronized<memgraph::auth::Auth, memgraph::utils::WritePrioritizedRWLock> auth{
test_folder_ / ("unit_auth_handler_test_" + std::to_string(static_cast<int>(getpid())))}; test_folder_ / ("unit_auth_handler_test_" + std::to_string(static_cast<int>(getpid()))),
memgraph::glue::AuthQueryHandler auth_handler{&auth, memgraph::glue::kDefaultUserRoleRegex.data()}; memgraph::auth::Auth::Config{/* default */}};
memgraph::glue::AuthQueryHandler auth_handler{&auth};
std::string user_name = "Mate"; std::string user_name = "Mate";
std::string edge_type_repr = "EdgeType1"; std::string edge_type_repr = "EdgeType1";

View File

@ -1,4 +1,4 @@
// Copyright 2023 Memgraph Ltd. // Copyright 2024 Memgraph Ltd.
// //
// Use of this software is governed by the Business Source License // 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 // included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
@ -66,7 +66,7 @@ class TestEnvironment : public ::testing::Environment {
} }
auth = auth =
std::make_unique<memgraph::utils::Synchronized<memgraph::auth::Auth, memgraph::utils::WritePrioritizedRWLock>>( std::make_unique<memgraph::utils::Synchronized<memgraph::auth::Auth, memgraph::utils::WritePrioritizedRWLock>>(
storage_directory / "auth"); storage_directory / "auth", memgraph::auth::Auth::Config{/* default */});
ptr_ = std::make_unique<memgraph::dbms::DbmsHandler>(storage_conf, auth.get(), false); ptr_ = std::make_unique<memgraph::dbms::DbmsHandler>(storage_conf, auth.get(), false);
} }

View File

@ -1,4 +1,4 @@
// Copyright 2023 Memgraph Ltd. // Copyright 2024 Memgraph Ltd.
// //
// Use of this software is governed by the Business Source License // 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 // included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
@ -51,7 +51,7 @@ class TestEnvironment : public ::testing::Environment {
} }
auth = auth =
std::make_unique<memgraph::utils::Synchronized<memgraph::auth::Auth, memgraph::utils::WritePrioritizedRWLock>>( std::make_unique<memgraph::utils::Synchronized<memgraph::auth::Auth, memgraph::utils::WritePrioritizedRWLock>>(
storage_directory / "auth"); storage_directory / "auth", memgraph::auth::Auth::Config{/* default */});
ptr_ = std::make_unique<memgraph::dbms::DbmsHandler>(storage_conf); ptr_ = std::make_unique<memgraph::dbms::DbmsHandler>(storage_conf);
} }

View File

@ -98,10 +98,8 @@ class MultiTenantTest : public ::testing::Test {
struct MinMemgraph { struct MinMemgraph {
explicit MinMemgraph(const memgraph::storage::Config &conf) explicit MinMemgraph(const memgraph::storage::Config &conf)
: dbms{conf, : auth{conf.durability.storage_directory / "auth", memgraph::auth::Auth::Config{/* default */}},
reinterpret_cast< dbms{conf, &auth, true},
memgraph::utils::Synchronized<memgraph::auth::Auth, memgraph::utils::WritePrioritizedRWLock> *>(0),
true},
interpreter_context{{}, &dbms, &dbms.ReplicationState()} { interpreter_context{{}, &dbms, &dbms.ReplicationState()} {
memgraph::utils::global_settings.Initialize(conf.durability.storage_directory / "settings"); memgraph::utils::global_settings.Initialize(conf.durability.storage_directory / "settings");
memgraph::license::RegisterLicenseSettings(memgraph::license::global_license_checker, memgraph::license::RegisterLicenseSettings(memgraph::license::global_license_checker,
@ -114,6 +112,7 @@ class MultiTenantTest : public ::testing::Test {
auto NewInterpreter() { return InterpreterFaker{&interpreter_context, dbms.Get()}; } auto NewInterpreter() { return InterpreterFaker{&interpreter_context, dbms.Get()}; }
memgraph::utils::Synchronized<memgraph::auth::Auth, memgraph::utils::WritePrioritizedRWLock> auth;
memgraph::dbms::DbmsHandler dbms; memgraph::dbms::DbmsHandler dbms;
memgraph::query::InterpreterContext interpreter_context; memgraph::query::InterpreterContext interpreter_context;
}; };

View File

@ -22,6 +22,7 @@
#include <storage/v2/inmemory/storage.hpp> #include <storage/v2/inmemory/storage.hpp>
#include <storage/v2/property_value.hpp> #include <storage/v2/property_value.hpp>
#include <storage/v2/replication/enums.hpp> #include <storage/v2/replication/enums.hpp>
#include "auth/auth.hpp"
#include "dbms/database.hpp" #include "dbms/database.hpp"
#include "dbms/dbms_handler.hpp" #include "dbms/dbms_handler.hpp"
#include "dbms/replication_handler.hpp" #include "dbms/replication_handler.hpp"
@ -31,6 +32,7 @@
#include "storage/v2/indices/label_index_stats.hpp" #include "storage/v2/indices/label_index_stats.hpp"
#include "storage/v2/storage.hpp" #include "storage/v2/storage.hpp"
#include "storage/v2/view.hpp" #include "storage/v2/view.hpp"
#include "utils/rw_lock.hpp"
#include "utils/synchronized.hpp" #include "utils/synchronized.hpp"
using testing::UnorderedElementsAre; using testing::UnorderedElementsAre;
@ -111,12 +113,11 @@ class ReplicationTest : public ::testing::Test {
struct MinMemgraph { struct MinMemgraph {
MinMemgraph(const memgraph::storage::Config &conf) MinMemgraph(const memgraph::storage::Config &conf)
: dbms{conf : auth{conf.durability.storage_directory / "auth", memgraph::auth::Auth::Config{/* default */}},
dbms{conf
#ifdef MG_ENTERPRISE #ifdef MG_ENTERPRISE
, ,
reinterpret_cast< &auth, true
memgraph::utils::Synchronized<memgraph::auth::Auth, memgraph::utils::WritePrioritizedRWLock> *>(0),
true
#endif #endif
}, },
repl_state{dbms.ReplicationState()}, repl_state{dbms.ReplicationState()},
@ -124,6 +125,8 @@ struct MinMemgraph {
db{*db_acc.get()}, db{*db_acc.get()},
repl_handler(dbms) { repl_handler(dbms) {
} }
memgraph::utils::Synchronized<memgraph::auth::Auth, memgraph::utils::WritePrioritizedRWLock> auth;
memgraph::dbms::DbmsHandler dbms; memgraph::dbms::DbmsHandler dbms;
memgraph::replication::ReplicationState &repl_state; memgraph::replication::ReplicationState &repl_state;
memgraph::dbms::DatabaseAccess db_acc; memgraph::dbms::DatabaseAccess db_acc;