Add MG_ENTERPRISE and license checks (#547)
This commit is contained in:
parent
dc8dad9794
commit
201f75e809
@ -101,6 +101,7 @@ std::string PermissionLevelToString(PermissionLevel level) {
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef MG_ENTERPRISE
|
||||
FineGrainedPermission PermissionToFineGrainedPermission(const uint64_t permission) {
|
||||
if (permission & FineGrainedPermission::CREATE_DELETE) {
|
||||
return FineGrainedPermission::CREATE_DELETE;
|
||||
@ -147,6 +148,7 @@ FineGrainedAccessPermissions Merge(const FineGrainedAccessPermissions &first,
|
||||
|
||||
return FineGrainedAccessPermissions(permissions, global_permission);
|
||||
}
|
||||
#endif
|
||||
|
||||
Permissions::Permissions(uint64_t grants, uint64_t denies) {
|
||||
// The deny bitmask has higher priority than the grant bitmask.
|
||||
@ -233,12 +235,16 @@ bool operator==(const Permissions &first, const Permissions &second) {
|
||||
|
||||
bool operator!=(const Permissions &first, const Permissions &second) { return !(first == second); }
|
||||
|
||||
#ifdef MG_ENTERPRISE
|
||||
FineGrainedAccessPermissions::FineGrainedAccessPermissions(const std::unordered_map<std::string, uint64_t> &permissions,
|
||||
const std::optional<uint64_t> &global_permission)
|
||||
: permissions_(permissions), global_permission_(global_permission) {}
|
||||
|
||||
PermissionLevel FineGrainedAccessPermissions::Has(const std::string &permission,
|
||||
const FineGrainedPermission fine_grained_permission) const {
|
||||
if (!memgraph::utils::license::global_license_checker.IsValidLicenseFast()) {
|
||||
return PermissionLevel::GRANT;
|
||||
}
|
||||
const auto concrete_permission = std::invoke([&]() -> uint64_t {
|
||||
if (permissions_.contains(permission)) {
|
||||
return permissions_.at(permission);
|
||||
@ -284,6 +290,9 @@ void FineGrainedAccessPermissions::Deny(const std::string &permission,
|
||||
}
|
||||
|
||||
nlohmann::json FineGrainedAccessPermissions::Serialize() const {
|
||||
if (!memgraph::utils::license::global_license_checker.IsValidLicenseFast()) {
|
||||
return {};
|
||||
}
|
||||
nlohmann::json data = nlohmann::json::object();
|
||||
data["permissions"] = permissions_;
|
||||
data["global_permission"] = global_permission_.has_value() ? global_permission_.value() : -1;
|
||||
@ -294,7 +303,9 @@ FineGrainedAccessPermissions FineGrainedAccessPermissions::Deserialize(const nlo
|
||||
if (!data.is_object()) {
|
||||
throw AuthException("Couldn't load permissions data!");
|
||||
}
|
||||
|
||||
if (!memgraph::utils::license::global_license_checker.IsValidLicenseFast()) {
|
||||
return FineGrainedAccessPermissions{};
|
||||
}
|
||||
std::optional<uint64_t> global_permission;
|
||||
|
||||
if (data["global_permission"].empty() || data["global_permission"] == -1) {
|
||||
@ -358,6 +369,9 @@ 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()) {
|
||||
return {};
|
||||
}
|
||||
nlohmann::json data = nlohmann::json::object();
|
||||
data["label_permissions"] = label_permissions_.Serialize();
|
||||
data["edge_type_permissions"] = edge_type_permissions_.Serialize();
|
||||
@ -371,6 +385,9 @@ 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()) {
|
||||
return FineGrainedAccessHandler{};
|
||||
}
|
||||
auto label_permissions = FineGrainedAccessPermissions::Deserialize(data["label_permissions"]);
|
||||
auto edge_type_permissions = FineGrainedAccessPermissions::Deserialize(data["edge_type_permissions"]);
|
||||
|
||||
@ -385,18 +402,23 @@ bool operator==(const FineGrainedAccessHandler &first, const FineGrainedAccessHa
|
||||
bool operator!=(const FineGrainedAccessHandler &first, const FineGrainedAccessHandler &second) {
|
||||
return !(first == second);
|
||||
}
|
||||
#endif
|
||||
|
||||
Role::Role(const std::string &rolename) : rolename_(utils::ToLowerCase(rolename)) {}
|
||||
|
||||
Role::Role(const std::string &rolename, const Permissions &permissions)
|
||||
: rolename_(utils::ToLowerCase(rolename)), permissions_(permissions) {}
|
||||
#ifdef MG_ENTERPRISE
|
||||
Role::Role(const std::string &rolename, const Permissions &permissions,
|
||||
FineGrainedAccessHandler fine_grained_access_handler)
|
||||
: rolename_(utils::ToLowerCase(rolename)),
|
||||
permissions_(permissions),
|
||||
fine_grained_access_handler_(std::move(fine_grained_access_handler)) {}
|
||||
#endif
|
||||
|
||||
const std::string &Role::rolename() const { return rolename_; }
|
||||
const Permissions &Role::permissions() const { return permissions_; }
|
||||
Permissions &Role::permissions() { return permissions_; }
|
||||
#ifdef MG_ENTERPRISE
|
||||
const FineGrainedAccessHandler &Role::fine_grained_access_handler() const { return fine_grained_access_handler_; }
|
||||
FineGrainedAccessHandler &Role::fine_grained_access_handler() { return fine_grained_access_handler_; }
|
||||
|
||||
@ -407,12 +429,19 @@ const FineGrainedAccessPermissions &Role::GetFineGrainedAccessLabelPermissions()
|
||||
const FineGrainedAccessPermissions &Role::GetFineGrainedAccessEdgeTypePermissions() const {
|
||||
return fine_grained_access_handler_.edge_type_permissions();
|
||||
}
|
||||
#endif
|
||||
|
||||
nlohmann::json Role::Serialize() const {
|
||||
nlohmann::json data = nlohmann::json::object();
|
||||
data["rolename"] = rolename_;
|
||||
data["permissions"] = permissions_.Serialize();
|
||||
data["fine_grained_access_handler"] = fine_grained_access_handler_.Serialize();
|
||||
#ifdef MG_ENTERPRISE
|
||||
if (memgraph::utils::license::global_license_checker.IsValidLicenseFast()) {
|
||||
data["fine_grained_access_handler"] = fine_grained_access_handler_.Serialize();
|
||||
} else {
|
||||
data["fine_grained_access_handler"] = {};
|
||||
}
|
||||
#endif
|
||||
return data;
|
||||
}
|
||||
|
||||
@ -420,30 +449,46 @@ Role Role::Deserialize(const nlohmann::json &data) {
|
||||
if (!data.is_object()) {
|
||||
throw AuthException("Couldn't load role data!");
|
||||
}
|
||||
if (!data["rolename"].is_string() || !data["permissions"].is_object() ||
|
||||
!data["fine_grained_access_handler"].is_object()) {
|
||||
if (!data["rolename"].is_string() || !data["permissions"].is_object()) {
|
||||
throw AuthException("Couldn't load role data!");
|
||||
}
|
||||
auto permissions = Permissions::Deserialize(data["permissions"]);
|
||||
auto fine_grained_access_handler = FineGrainedAccessHandler::Deserialize(data["fine_grained_access_handler"]);
|
||||
return {data["rolename"], permissions, std::move(fine_grained_access_handler)};
|
||||
#ifdef MG_ENTERPRISE
|
||||
if (memgraph::utils::license::global_license_checker.IsValidLicenseFast()) {
|
||||
if (!data["fine_grained_access_handler"].is_object()) {
|
||||
throw AuthException("Couldn't load user data!");
|
||||
}
|
||||
auto fine_grained_access_handler = FineGrainedAccessHandler::Deserialize(data["fine_grained_access_handler"]);
|
||||
return {data["rolename"], permissions, std::move(fine_grained_access_handler)};
|
||||
}
|
||||
#endif
|
||||
return {data["rolename"], permissions};
|
||||
}
|
||||
|
||||
bool operator==(const Role &first, const Role &second) {
|
||||
return first.rolename_ == second.rolename_ && first.permissions_ == second.permissions_ &&
|
||||
first.fine_grained_access_handler_ == second.fine_grained_access_handler_;
|
||||
#ifdef MG_ENTERPRISE
|
||||
if (memgraph::utils::license::global_license_checker.IsValidLicenseFast()) {
|
||||
return first.rolename_ == second.rolename_ && first.permissions_ == second.permissions_ &&
|
||||
first.fine_grained_access_handler_ == second.fine_grained_access_handler_;
|
||||
}
|
||||
#endif
|
||||
return first.rolename_ == second.rolename_ && first.permissions_ == second.permissions_;
|
||||
}
|
||||
|
||||
User::User() {}
|
||||
|
||||
User::User(const std::string &username) : username_(utils::ToLowerCase(username)) {}
|
||||
User::User(const std::string &username, const std::string &password_hash, const Permissions &permissions)
|
||||
: username_(utils::ToLowerCase(username)), password_hash_(password_hash), permissions_(permissions) {}
|
||||
|
||||
#ifdef MG_ENTERPRISE
|
||||
User::User(const std::string &username, const std::string &password_hash, const Permissions &permissions,
|
||||
FineGrainedAccessHandler fine_grained_access_handler)
|
||||
: username_(utils::ToLowerCase(username)),
|
||||
password_hash_(password_hash),
|
||||
permissions_(permissions),
|
||||
fine_grained_access_handler_(std::move(fine_grained_access_handler)) {}
|
||||
#endif
|
||||
|
||||
bool User::CheckPassword(const std::string &password) {
|
||||
if (password_hash_.empty()) return true;
|
||||
@ -492,29 +537,41 @@ Permissions User::GetPermissions() const {
|
||||
return permissions_;
|
||||
}
|
||||
|
||||
#ifdef MG_ENTERPRISE
|
||||
FineGrainedAccessPermissions User::GetFineGrainedAccessLabelPermissions() const {
|
||||
if (!memgraph::utils::license::global_license_checker.IsValidLicenseFast()) {
|
||||
return FineGrainedAccessPermissions{};
|
||||
}
|
||||
|
||||
if (role_) {
|
||||
return Merge(role()->fine_grained_access_handler().label_permissions(),
|
||||
fine_grained_access_handler_.label_permissions());
|
||||
}
|
||||
|
||||
return fine_grained_access_handler_.label_permissions();
|
||||
}
|
||||
|
||||
FineGrainedAccessPermissions User::GetFineGrainedAccessEdgeTypePermissions() const {
|
||||
if (!memgraph::utils::license::global_license_checker.IsValidLicenseFast()) {
|
||||
return FineGrainedAccessPermissions{};
|
||||
}
|
||||
if (role_) {
|
||||
return Merge(role()->fine_grained_access_handler().edge_type_permissions(),
|
||||
fine_grained_access_handler_.edge_type_permissions());
|
||||
}
|
||||
return fine_grained_access_handler_.edge_type_permissions();
|
||||
}
|
||||
#endif
|
||||
|
||||
const std::string &User::username() const { return username_; }
|
||||
|
||||
const Permissions &User::permissions() const { return permissions_; }
|
||||
Permissions &User::permissions() { return permissions_; }
|
||||
#ifdef MG_ENTERPRISE
|
||||
const FineGrainedAccessHandler &User::fine_grained_access_handler() const { return fine_grained_access_handler_; }
|
||||
FineGrainedAccessHandler &User::fine_grained_access_handler() { return fine_grained_access_handler_; }
|
||||
|
||||
FineGrainedAccessHandler &User::fine_grained_access_handler() { return fine_grained_access_handler_; }
|
||||
#endif
|
||||
const Role *User::role() const {
|
||||
if (role_.has_value()) {
|
||||
return &role_.value();
|
||||
@ -527,7 +584,13 @@ nlohmann::json User::Serialize() const {
|
||||
data["username"] = username_;
|
||||
data["password_hash"] = password_hash_;
|
||||
data["permissions"] = permissions_.Serialize();
|
||||
data["fine_grained_access_handler"] = fine_grained_access_handler_.Serialize();
|
||||
#ifdef MG_ENTERPRISE
|
||||
if (memgraph::utils::license::global_license_checker.IsValidLicenseFast()) {
|
||||
data["fine_grained_access_handler"] = fine_grained_access_handler_.Serialize();
|
||||
} else {
|
||||
data["fine_grained_access_handler"] = {};
|
||||
}
|
||||
#endif
|
||||
// The role shouldn't be serialized here, it is stored as a foreign key.
|
||||
return data;
|
||||
}
|
||||
@ -536,19 +599,32 @@ User User::Deserialize(const nlohmann::json &data) {
|
||||
if (!data.is_object()) {
|
||||
throw AuthException("Couldn't load user data!");
|
||||
}
|
||||
if (!data["username"].is_string() || !data["password_hash"].is_string() || !data["permissions"].is_object() ||
|
||||
!data["fine_grained_access_handler"].is_object()) {
|
||||
if (!data["username"].is_string() || !data["password_hash"].is_string() || !data["permissions"].is_object()) {
|
||||
throw AuthException("Couldn't load user data!");
|
||||
}
|
||||
auto permissions = Permissions::Deserialize(data["permissions"]);
|
||||
auto fine_grained_access_handler = FineGrainedAccessHandler::Deserialize(data["fine_grained_access_handler"]);
|
||||
return {data["username"], data["password_hash"], permissions, fine_grained_access_handler};
|
||||
#ifdef MG_ENTERPRISE
|
||||
if (memgraph::utils::license::global_license_checker.IsValidLicenseFast()) {
|
||||
if (!data["fine_grained_access_handler"].is_object()) {
|
||||
throw AuthException("Couldn't load user data!");
|
||||
}
|
||||
auto fine_grained_access_handler = FineGrainedAccessHandler::Deserialize(data["fine_grained_access_handler"]);
|
||||
return {data["username"], data["password_hash"], permissions, fine_grained_access_handler};
|
||||
}
|
||||
#endif
|
||||
return {data["username"], data["password_hash"], permissions};
|
||||
}
|
||||
|
||||
bool operator==(const User &first, const User &second) {
|
||||
#ifdef MG_ENTERPRISE
|
||||
if (memgraph::utils::license::global_license_checker.IsValidLicenseFast()) {
|
||||
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_;
|
||||
}
|
||||
#endif
|
||||
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_;
|
||||
first.permissions_ == second.permissions_ && first.role_ == second.role_;
|
||||
}
|
||||
|
||||
} // namespace memgraph::auth
|
||||
|
@ -44,6 +44,7 @@ enum class Permission : uint64_t {
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
#ifdef MG_ENTERPRISE
|
||||
// clang-format off
|
||||
enum class FineGrainedPermission : uint64_t {
|
||||
NO_PERMISSION = 0,
|
||||
@ -70,6 +71,7 @@ constexpr uint64_t kLabelPermissionAll = memgraph::auth::FineGrainedPermission::
|
||||
memgraph::auth::FineGrainedPermission::READ;
|
||||
constexpr uint64_t kLabelPermissionMax = static_cast<uint64_t>(memgraph::auth::FineGrainedPermission::CREATE_DELETE);
|
||||
constexpr uint64_t kLabelPermissionMin = static_cast<uint64_t>(memgraph::auth::FineGrainedPermission::READ);
|
||||
#endif
|
||||
|
||||
// Function that converts a permission to its string representation.
|
||||
std::string PermissionToString(Permission permission);
|
||||
@ -80,11 +82,13 @@ enum class PermissionLevel : uint8_t { GRANT, NEUTRAL, DENY };
|
||||
// Function that converts a permission level to its string representation.
|
||||
std::string PermissionLevelToString(PermissionLevel level);
|
||||
|
||||
#ifdef MG_ENTERPRISE
|
||||
// Function that converts a label permission level to its string representation.
|
||||
std::string FineGrainedPermissionToString(FineGrainedPermission level);
|
||||
|
||||
// Constructs a label permission from a permission
|
||||
FineGrainedPermission PermissionToFineGrainedPermission(uint64_t permission);
|
||||
#endif
|
||||
|
||||
class Permissions final {
|
||||
public:
|
||||
@ -125,6 +129,7 @@ bool operator==(const Permissions &first, const Permissions &second);
|
||||
|
||||
bool operator!=(const Permissions &first, const Permissions &second);
|
||||
|
||||
#ifdef MG_ENTERPRISE
|
||||
class FineGrainedAccessPermissions final {
|
||||
public:
|
||||
explicit FineGrainedAccessPermissions(const std::unordered_map<std::string, uint64_t> &permissions = {},
|
||||
@ -192,14 +197,16 @@ class FineGrainedAccessHandler final {
|
||||
};
|
||||
|
||||
bool operator==(const FineGrainedAccessHandler &first, const FineGrainedAccessHandler &second);
|
||||
#endif
|
||||
|
||||
class Role final {
|
||||
public:
|
||||
explicit Role(const std::string &rolename);
|
||||
|
||||
Role(const std::string &rolename, const Permissions &permissions);
|
||||
#ifdef MG_ENTERPRISE
|
||||
Role(const std::string &rolename, const Permissions &permissions,
|
||||
FineGrainedAccessHandler fine_grained_access_handler);
|
||||
|
||||
#endif
|
||||
Role(const Role &) = default;
|
||||
Role &operator=(const Role &) = default;
|
||||
Role(Role &&) noexcept = default;
|
||||
@ -209,11 +216,12 @@ class Role final {
|
||||
const std::string &rolename() const;
|
||||
const Permissions &permissions() const;
|
||||
Permissions &permissions();
|
||||
#ifdef MG_ENTERPRISE
|
||||
const FineGrainedAccessHandler &fine_grained_access_handler() const;
|
||||
FineGrainedAccessHandler &fine_grained_access_handler();
|
||||
const FineGrainedAccessPermissions &GetFineGrainedAccessLabelPermissions() const;
|
||||
const FineGrainedAccessPermissions &GetFineGrainedAccessEdgeTypePermissions() const;
|
||||
|
||||
#endif
|
||||
nlohmann::json Serialize() const;
|
||||
|
||||
/// @throw AuthException if unable to deserialize.
|
||||
@ -224,7 +232,9 @@ class Role final {
|
||||
private:
|
||||
std::string rolename_;
|
||||
Permissions permissions_;
|
||||
#ifdef MG_ENTERPRISE
|
||||
FineGrainedAccessHandler fine_grained_access_handler_;
|
||||
#endif
|
||||
};
|
||||
|
||||
bool operator==(const Role &first, const Role &second);
|
||||
@ -235,10 +245,11 @@ class User final {
|
||||
User();
|
||||
|
||||
explicit User(const std::string &username);
|
||||
|
||||
User(const std::string &username, const std::string &password_hash, const Permissions &permissions);
|
||||
#ifdef MG_ENTERPRISE
|
||||
User(const std::string &username, const std::string &password_hash, const Permissions &permissions,
|
||||
FineGrainedAccessHandler fine_grained_access_handler);
|
||||
|
||||
#endif
|
||||
User(const User &) = default;
|
||||
User &operator=(const User &) = default;
|
||||
User(User &&) noexcept = default;
|
||||
@ -256,15 +267,17 @@ class User final {
|
||||
void ClearRole();
|
||||
|
||||
Permissions GetPermissions() const;
|
||||
|
||||
#ifdef MG_ENTERPRISE
|
||||
FineGrainedAccessPermissions GetFineGrainedAccessLabelPermissions() const;
|
||||
FineGrainedAccessPermissions GetFineGrainedAccessEdgeTypePermissions() const;
|
||||
|
||||
const FineGrainedAccessHandler &fine_grained_access_handler() const;
|
||||
FineGrainedAccessHandler &fine_grained_access_handler();
|
||||
#endif
|
||||
const std::string &username() const;
|
||||
|
||||
const Permissions &permissions() const;
|
||||
Permissions &permissions();
|
||||
const FineGrainedAccessHandler &fine_grained_access_handler() const;
|
||||
FineGrainedAccessHandler &fine_grained_access_handler();
|
||||
|
||||
const Role *role() const;
|
||||
|
||||
@ -279,12 +292,16 @@ class User final {
|
||||
std::string username_;
|
||||
std::string password_hash_;
|
||||
Permissions permissions_;
|
||||
#ifdef MG_ENTERPRISE
|
||||
FineGrainedAccessHandler fine_grained_access_handler_;
|
||||
#endif
|
||||
std::optional<Role> role_;
|
||||
};
|
||||
|
||||
bool operator==(const User &first, const User &second);
|
||||
|
||||
#ifdef MG_ENTERPRISE
|
||||
FineGrainedAccessPermissions Merge(const FineGrainedAccessPermissions &first,
|
||||
const FineGrainedAccessPermissions &second);
|
||||
#endif
|
||||
} // namespace memgraph::auth
|
||||
|
@ -61,6 +61,7 @@ auth::Permission PrivilegeToPermission(query::AuthQuery::Privilege privilege) {
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef MG_ENTERPRISE
|
||||
auth::FineGrainedPermission FineGrainedPrivilegeToFineGrainedPermission(
|
||||
const query::AuthQuery::FineGrainedPrivilege fine_grained_privilege) {
|
||||
switch (fine_grained_privilege) {
|
||||
@ -72,4 +73,5 @@ auth::FineGrainedPermission FineGrainedPrivilegeToFineGrainedPermission(
|
||||
return auth::FineGrainedPermission::CREATE_DELETE;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
} // namespace memgraph::glue
|
||||
|
@ -20,11 +20,12 @@ namespace memgraph::glue {
|
||||
*/
|
||||
auth::Permission PrivilegeToPermission(query::AuthQuery::Privilege privilege);
|
||||
|
||||
#ifdef MG_ENTERPRISE
|
||||
/**
|
||||
* Converts query::AuthQuery::FineGrainedPrivilege to its corresponding
|
||||
* auth::EntityPermission.
|
||||
*/
|
||||
auth::FineGrainedPermission FineGrainedPrivilegeToFineGrainedPermission(
|
||||
query::AuthQuery::FineGrainedPrivilege fine_grained_privilege);
|
||||
|
||||
#endif
|
||||
} // namespace memgraph::glue
|
||||
|
@ -15,12 +15,17 @@
|
||||
#include "auth/models.hpp"
|
||||
#include "glue/auth.hpp"
|
||||
#include "query/frontend/ast/ast.hpp"
|
||||
#include "utils/license.hpp"
|
||||
#include "utils/synchronized.hpp"
|
||||
|
||||
#ifdef MG_ENTERPRISE
|
||||
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()) {
|
||||
return true;
|
||||
}
|
||||
return std::all_of(labels.begin(), labels.end(), [dba, &user, fine_grained_privilege](const auto &label) {
|
||||
return user.GetFineGrainedAccessLabelPermissions().Has(
|
||||
dba->LabelToName(label), memgraph::glue::FineGrainedPrivilegeToFineGrainedPermission(
|
||||
@ -30,12 +35,18 @@ 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()) {
|
||||
return true;
|
||||
}
|
||||
return user.GetFineGrainedAccessLabelPermissions().Has(memgraph::auth::kAsterisk, fine_grained_permission) ==
|
||||
memgraph::auth::PermissionLevel::GRANT;
|
||||
}
|
||||
|
||||
bool IsUserAuthorizedGloballyEdges(const memgraph::auth::User &user,
|
||||
const memgraph::auth::FineGrainedPermission fine_grained_permission) {
|
||||
if (!memgraph::utils::license::global_license_checker.IsValidLicenseFast()) {
|
||||
return true;
|
||||
}
|
||||
return user.GetFineGrainedAccessEdgeTypePermissions().Has(memgraph::auth::kAsterisk, fine_grained_permission) ==
|
||||
memgraph::auth::PermissionLevel::GRANT;
|
||||
}
|
||||
@ -43,12 +54,15 @@ 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()) {
|
||||
return true;
|
||||
}
|
||||
return user.GetFineGrainedAccessEdgeTypePermissions().Has(
|
||||
dba->EdgeTypeToName(edgeType), memgraph::glue::FineGrainedPrivilegeToFineGrainedPermission(
|
||||
fine_grained_privilege)) == memgraph::auth::PermissionLevel::GRANT;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
#endif
|
||||
namespace memgraph::glue {
|
||||
|
||||
AuthChecker::AuthChecker(
|
||||
@ -70,9 +84,12 @@ bool AuthChecker::IsUserAuthorized(const std::optional<std::string> &username,
|
||||
|
||||
return maybe_user.has_value() && IsUserAuthorized(*maybe_user, privileges);
|
||||
}
|
||||
|
||||
#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()) {
|
||||
return {};
|
||||
}
|
||||
try {
|
||||
auto locked_auth = auth_->Lock();
|
||||
auto user = locked_auth->GetUser(username);
|
||||
@ -86,6 +103,7 @@ std::unique_ptr<memgraph::query::FineGrainedAuthChecker> AuthChecker::GetFineGra
|
||||
throw memgraph::query::QueryRuntimeException(e.what());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
bool AuthChecker::IsUserAuthorized(const memgraph::auth::User &user,
|
||||
const std::vector<memgraph::query::AuthQuery::Privilege> &privileges) {
|
||||
@ -96,6 +114,7 @@ bool AuthChecker::IsUserAuthorized(const memgraph::auth::User &user,
|
||||
});
|
||||
}
|
||||
|
||||
#ifdef MG_ENTERPRISE
|
||||
FineGrainedAuthChecker::FineGrainedAuthChecker(auth::User user, const memgraph::query::DbAccessor *dba)
|
||||
: user_{std::move(user)}, dba_(dba){};
|
||||
|
||||
@ -135,11 +154,18 @@ 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()) {
|
||||
return true;
|
||||
}
|
||||
return IsUserAuthorizedGloballyLabels(user_, FineGrainedPrivilegeToFineGrainedPermission(fine_grained_privilege));
|
||||
}
|
||||
|
||||
bool FineGrainedAuthChecker::HasGlobalPrivilegeOnEdges(
|
||||
const memgraph::query::AuthQuery::FineGrainedPrivilege fine_grained_privilege) const {
|
||||
if (!memgraph::utils::license::global_license_checker.IsValidLicenseFast()) {
|
||||
return true;
|
||||
}
|
||||
return IsUserAuthorizedGloballyEdges(user_, FineGrainedPrivilegeToFineGrainedPermission(fine_grained_privilege));
|
||||
};
|
||||
#endif
|
||||
} // namespace memgraph::glue
|
||||
|
@ -26,17 +26,17 @@ class AuthChecker : public query::AuthChecker {
|
||||
|
||||
bool IsUserAuthorized(const std::optional<std::string> &username,
|
||||
const std::vector<query::AuthQuery::Privilege> &privileges) const override;
|
||||
|
||||
#ifdef MG_ENTERPRISE
|
||||
std::unique_ptr<memgraph::query::FineGrainedAuthChecker> GetFineGrainedAuthChecker(
|
||||
const std::string &username, const memgraph::query::DbAccessor *dba) const override;
|
||||
|
||||
#endif
|
||||
[[nodiscard]] static bool IsUserAuthorized(const memgraph::auth::User &user,
|
||||
const std::vector<memgraph::query::AuthQuery::Privilege> &privileges);
|
||||
|
||||
private:
|
||||
memgraph::utils::Synchronized<memgraph::auth::Auth, memgraph::utils::WritePrioritizedRWLock> *auth_;
|
||||
};
|
||||
|
||||
#ifdef MG_ENTERPRISE
|
||||
class FineGrainedAuthChecker : public query::FineGrainedAuthChecker {
|
||||
public:
|
||||
explicit FineGrainedAuthChecker(auth::User user, const memgraph::query::DbAccessor *dba);
|
||||
@ -63,4 +63,5 @@ class FineGrainedAuthChecker : public query::FineGrainedAuthChecker {
|
||||
auth::User user_;
|
||||
const memgraph::query::DbAccessor *dba_;
|
||||
};
|
||||
#endif
|
||||
} // namespace memgraph::glue
|
||||
|
@ -17,6 +17,7 @@
|
||||
|
||||
#include "auth/models.hpp"
|
||||
#include "glue/auth.hpp"
|
||||
#include "utils/license.hpp"
|
||||
|
||||
namespace {
|
||||
|
||||
@ -28,7 +29,9 @@ struct PermissionForPrivilegeResult {
|
||||
|
||||
struct FineGrainedPermissionForPrivilegeResult {
|
||||
std::string permission;
|
||||
#ifdef MG_ENTERPRISE
|
||||
memgraph::auth::FineGrainedPermission permission_level;
|
||||
#endif
|
||||
std::string description;
|
||||
};
|
||||
|
||||
@ -117,10 +120,14 @@ std::vector<std::vector<memgraph::query::TypedValue>> ShowRolePrivileges(
|
||||
return ConstructPrivilegesResult(privilege_results);
|
||||
}
|
||||
|
||||
#ifdef MG_ENTERPRISE
|
||||
std::vector<FineGrainedPermissionForPrivilegeResult> GetFineGrainedPermissionForPrivilegeForUserOrRole(
|
||||
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()) {
|
||||
return fine_grained_permissions;
|
||||
}
|
||||
const auto global_permission = permissions.GetGlobalPermission();
|
||||
if (global_permission.has_value()) {
|
||||
const auto &permission_level = memgraph::auth::PermissionToFineGrainedPermission(global_permission.value());
|
||||
@ -159,7 +166,9 @@ 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()) {
|
||||
return {};
|
||||
}
|
||||
grants.reserve(privileges.size());
|
||||
for (const auto &permission : privileges) {
|
||||
grants.push_back(
|
||||
@ -173,6 +182,9 @@ 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()) {
|
||||
return {};
|
||||
}
|
||||
const auto &label_permissions = user->GetFineGrainedAccessLabelPermissions();
|
||||
const auto &edge_type_permissions = user->GetFineGrainedAccessEdgeTypePermissions();
|
||||
|
||||
@ -189,6 +201,9 @@ 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()) {
|
||||
return {};
|
||||
}
|
||||
const auto &label_permissions = role->GetFineGrainedAccessLabelPermissions();
|
||||
const auto &edge_type_permissions = role->GetFineGrainedAccessEdgeTypePermissions();
|
||||
|
||||
@ -202,6 +217,8 @@ std::vector<std::vector<memgraph::query::TypedValue>> ShowFineGrainedRolePrivile
|
||||
|
||||
return ConstructFineGrainedPrivilegesResult(all_fine_grained_permissions);
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace memgraph::glue {
|
||||
@ -236,10 +253,21 @@ bool AuthQueryHandler::CreateUser(const std::string &username, const std::option
|
||||
|
||||
if (first_user) {
|
||||
spdlog::info("{} is first created user. Granting all privileges.", username);
|
||||
GrantPrivilege(
|
||||
username, memgraph::query::kPrivilegesAll,
|
||||
{{{memgraph::query::AuthQuery::FineGrainedPrivilege::CREATE_DELETE, {memgraph::auth::kAsterisk}}}},
|
||||
{{{memgraph::query::AuthQuery::FineGrainedPrivilege::CREATE_DELETE, {memgraph::auth::kAsterisk}}}});
|
||||
GrantPrivilege(username, memgraph::query::kPrivilegesAll
|
||||
#ifdef MG_ENTERPRISE
|
||||
,
|
||||
{{{memgraph::query::AuthQuery::FineGrainedPrivilege::CREATE_DELETE, {memgraph::auth::kAsterisk}}}},
|
||||
{
|
||||
{
|
||||
{
|
||||
memgraph::query::AuthQuery::FineGrainedPrivilege::CREATE_DELETE, {
|
||||
memgraph::auth::kAsterisk
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
);
|
||||
}
|
||||
|
||||
return user_added;
|
||||
@ -433,7 +461,9 @@ std::vector<std::vector<memgraph::query::TypedValue>> AuthQueryHandler::GetPrivi
|
||||
try {
|
||||
auto locked_auth = auth_->ReadLock();
|
||||
std::vector<std::vector<memgraph::query::TypedValue>> grants;
|
||||
#ifdef MG_ENTERPRISE
|
||||
std::vector<std::vector<memgraph::query::TypedValue>> fine_grained_grants;
|
||||
#endif
|
||||
auto user = locked_auth->GetUser(user_or_role);
|
||||
auto role = locked_auth->GetRole(user_or_role);
|
||||
if (!user && !role) {
|
||||
@ -442,14 +472,24 @@ std::vector<std::vector<memgraph::query::TypedValue>> AuthQueryHandler::GetPrivi
|
||||
|
||||
if (user) {
|
||||
grants = ShowUserPrivileges(user);
|
||||
fine_grained_grants = ShowFineGrainedUserPrivileges(user);
|
||||
#ifdef MG_ENTERPRISE
|
||||
if (memgraph::utils::license::global_license_checker.IsValidLicenseFast()) {
|
||||
fine_grained_grants = ShowFineGrainedUserPrivileges(user);
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
grants = ShowRolePrivileges(role);
|
||||
fine_grained_grants = ShowFineGrainedRolePrivileges(role);
|
||||
#ifdef MG_ENTERPRISE
|
||||
if (memgraph::utils::license::global_license_checker.IsValidLicenseFast()) {
|
||||
fine_grained_grants = ShowFineGrainedRolePrivileges(role);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
grants.insert(grants.end(), fine_grained_grants.begin(), fine_grained_grants.end());
|
||||
|
||||
#ifdef MG_ENTERPRISE
|
||||
if (memgraph::utils::license::global_license_checker.IsValidLicenseFast()) {
|
||||
grants.insert(grants.end(), fine_grained_grants.begin(), fine_grained_grants.end());
|
||||
}
|
||||
#endif
|
||||
return grants;
|
||||
} catch (const memgraph::auth::AuthException &e) {
|
||||
throw memgraph::query::QueryRuntimeException(e.what());
|
||||
@ -457,19 +497,28 @@ std::vector<std::vector<memgraph::query::TypedValue>> AuthQueryHandler::GetPrivi
|
||||
}
|
||||
|
||||
void AuthQueryHandler::GrantPrivilege(
|
||||
const std::string &user_or_role, const std::vector<memgraph::query::AuthQuery::Privilege> &privileges,
|
||||
const std::string &user_or_role, const std::vector<memgraph::query::AuthQuery::Privilege> &privileges
|
||||
#ifdef MG_ENTERPRISE
|
||||
,
|
||||
const std::vector<std::unordered_map<memgraph::query::AuthQuery::FineGrainedPrivilege, std::vector<std::string>>>
|
||||
&label_privileges,
|
||||
const std::vector<std::unordered_map<memgraph::query::AuthQuery::FineGrainedPrivilege, std::vector<std::string>>>
|
||||
&edge_type_privileges) {
|
||||
&edge_type_privileges
|
||||
#endif
|
||||
) {
|
||||
EditPermissions(
|
||||
user_or_role, privileges, label_privileges, edge_type_privileges,
|
||||
user_or_role, privileges,
|
||||
#ifdef MG_ENTERPRISE
|
||||
label_privileges, edge_type_privileges,
|
||||
#endif
|
||||
[](auto &permissions, const auto &permission) {
|
||||
// TODO (mferencevic): should we first check that the
|
||||
// privilege is granted/denied/revoked before
|
||||
// unconditionally granting/denying/revoking it?
|
||||
permissions.Grant(permission);
|
||||
},
|
||||
}
|
||||
#ifdef MG_ENTERPRISE
|
||||
,
|
||||
[](auto &fine_grained_permissions, const auto &privilege_collection) {
|
||||
for (const auto &[privilege, entities] : privilege_collection) {
|
||||
const auto &permission = memgraph::glue::FineGrainedPrivilegeToFineGrainedPermission(privilege);
|
||||
@ -477,23 +526,34 @@ void AuthQueryHandler::GrantPrivilege(
|
||||
fine_grained_permissions.Grant(entity, permission);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
#endif
|
||||
);
|
||||
} // namespace memgraph::glue
|
||||
|
||||
void AuthQueryHandler::DenyPrivilege(
|
||||
const std::string &user_or_role, const std::vector<memgraph::query::AuthQuery::Privilege> &privileges,
|
||||
const std::string &user_or_role, const std::vector<memgraph::query::AuthQuery::Privilege> &privileges
|
||||
#ifdef MG_ENTERPRISE
|
||||
,
|
||||
const std::vector<std::unordered_map<memgraph::query::AuthQuery::FineGrainedPrivilege, std::vector<std::string>>>
|
||||
&label_privileges,
|
||||
const std::vector<std::unordered_map<memgraph::query::AuthQuery::FineGrainedPrivilege, std::vector<std::string>>>
|
||||
&edge_type_privileges) {
|
||||
&edge_type_privileges
|
||||
#endif
|
||||
) {
|
||||
EditPermissions(
|
||||
user_or_role, privileges, label_privileges, edge_type_privileges,
|
||||
user_or_role, privileges,
|
||||
#ifdef MG_ENTERPRISE
|
||||
label_privileges, edge_type_privileges,
|
||||
#endif
|
||||
[](auto &permissions, const auto &permission) {
|
||||
// TODO (mferencevic): should we first check that the
|
||||
// privilege is granted/denied/revoked before
|
||||
// unconditionally granting/denying/revoking it?
|
||||
permissions.Deny(permission);
|
||||
},
|
||||
}
|
||||
#ifdef MG_ENTERPRISE
|
||||
,
|
||||
[](auto &fine_grained_permissions, const auto &privilege_collection) {
|
||||
for (const auto &[privilege, entities] : privilege_collection) {
|
||||
const auto &permission = memgraph::glue::FineGrainedPrivilegeToFineGrainedPermission(privilege);
|
||||
@ -501,41 +561,67 @@ void AuthQueryHandler::DenyPrivilege(
|
||||
fine_grained_permissions.Deny(entity, permission);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
#endif
|
||||
);
|
||||
} // namespace memgraph::glue
|
||||
|
||||
void AuthQueryHandler::RevokePrivilege(
|
||||
const std::string &user_or_role, const std::vector<memgraph::query::AuthQuery::Privilege> &privileges,
|
||||
const std::string &user_or_role, const std::vector<memgraph::query::AuthQuery::Privilege> &privileges
|
||||
#ifdef MG_ENTERPRISE
|
||||
,
|
||||
const std::vector<std::unordered_map<memgraph::query::AuthQuery::FineGrainedPrivilege, std::vector<std::string>>>
|
||||
&label_privileges,
|
||||
const std::vector<std::unordered_map<memgraph::query::AuthQuery::FineGrainedPrivilege, std::vector<std::string>>>
|
||||
&edge_type_privileges) {
|
||||
&edge_type_privileges
|
||||
#endif
|
||||
) {
|
||||
EditPermissions(
|
||||
user_or_role, privileges, label_privileges, edge_type_privileges,
|
||||
user_or_role, privileges,
|
||||
#ifdef MG_ENTERPRISE
|
||||
label_privileges, edge_type_privileges,
|
||||
#endif
|
||||
[](auto &permissions, const auto &permission) {
|
||||
// TODO (mferencevic): should we first check that the
|
||||
// privilege is granted/denied/revoked before
|
||||
// unconditionally granting/denying/revoking it?
|
||||
permissions.Revoke(permission);
|
||||
},
|
||||
}
|
||||
#ifdef MG_ENTERPRISE
|
||||
,
|
||||
[](auto &fine_grained_permissions, const auto &privilege_collection) {
|
||||
for ([[maybe_unused]] const auto &[privilege, entities] : privilege_collection) {
|
||||
for (const auto &entity : entities) {
|
||||
fine_grained_permissions.Revoke(entity);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
#endif
|
||||
);
|
||||
} // namespace memgraph::glue
|
||||
|
||||
template <class TEditPermissionsFun, class TEditFineGrainedPermissionsFun>
|
||||
template <class TEditPermissionsFun
|
||||
#ifdef MG_ENTERPRISE
|
||||
,
|
||||
class TEditFineGrainedPermissionsFun
|
||||
#endif
|
||||
>
|
||||
void AuthQueryHandler::EditPermissions(
|
||||
const std::string &user_or_role, const std::vector<memgraph::query::AuthQuery::Privilege> &privileges,
|
||||
const std::string &user_or_role, const std::vector<memgraph::query::AuthQuery::Privilege> &privileges
|
||||
#ifdef MG_ENTERPRISE
|
||||
,
|
||||
const std::vector<std::unordered_map<memgraph::query::AuthQuery::FineGrainedPrivilege, std::vector<std::string>>>
|
||||
&label_privileges,
|
||||
const std::vector<std::unordered_map<memgraph::query::AuthQuery::FineGrainedPrivilege, std::vector<std::string>>>
|
||||
&edge_type_privileges,
|
||||
const TEditPermissionsFun &edit_permissions_fun,
|
||||
const TEditFineGrainedPermissionsFun &edit_fine_grained_permissions_fun) {
|
||||
&edge_type_privileges
|
||||
#endif
|
||||
,
|
||||
const TEditPermissionsFun &edit_permissions_fun
|
||||
#ifdef MG_ENTERPRISE
|
||||
,
|
||||
const TEditFineGrainedPermissionsFun &edit_fine_grained_permissions_fun
|
||||
#endif
|
||||
) {
|
||||
if (!std::regex_match(user_or_role, name_regex_)) {
|
||||
throw memgraph::query::QueryRuntimeException("Invalid user or role name.");
|
||||
}
|
||||
@ -555,28 +641,34 @@ void AuthQueryHandler::EditPermissions(
|
||||
for (const auto &permission : permissions) {
|
||||
edit_permissions_fun(user->permissions(), permission);
|
||||
}
|
||||
for (const auto &label_privilege_collection : label_privileges) {
|
||||
edit_fine_grained_permissions_fun(user->fine_grained_access_handler().label_permissions(),
|
||||
label_privilege_collection);
|
||||
#ifdef MG_ENTERPRISE
|
||||
if (memgraph::utils::license::global_license_checker.IsValidLicenseFast()) {
|
||||
for (const auto &label_privilege_collection : label_privileges) {
|
||||
edit_fine_grained_permissions_fun(user->fine_grained_access_handler().label_permissions(),
|
||||
label_privilege_collection);
|
||||
}
|
||||
for (const auto &edge_type_privilege_collection : edge_type_privileges) {
|
||||
edit_fine_grained_permissions_fun(user->fine_grained_access_handler().edge_type_permissions(),
|
||||
edge_type_privilege_collection);
|
||||
}
|
||||
}
|
||||
for (const auto &edge_type_privilege_collection : edge_type_privileges) {
|
||||
edit_fine_grained_permissions_fun(user->fine_grained_access_handler().edge_type_permissions(),
|
||||
edge_type_privilege_collection);
|
||||
}
|
||||
|
||||
#endif
|
||||
locked_auth->SaveUser(*user);
|
||||
} else {
|
||||
for (const auto &permission : permissions) {
|
||||
edit_permissions_fun(role->permissions(), permission);
|
||||
}
|
||||
for (const auto &label_privilege : label_privileges) {
|
||||
edit_fine_grained_permissions_fun(user->fine_grained_access_handler().label_permissions(), label_privilege);
|
||||
#ifdef MG_ENTERPRISE
|
||||
if (memgraph::utils::license::global_license_checker.IsValidLicenseFast()) {
|
||||
for (const auto &label_privilege : label_privileges) {
|
||||
edit_fine_grained_permissions_fun(user->fine_grained_access_handler().label_permissions(), label_privilege);
|
||||
}
|
||||
for (const auto &edge_type_privilege : edge_type_privileges) {
|
||||
edit_fine_grained_permissions_fun(role->fine_grained_access_handler().edge_type_permissions(),
|
||||
edge_type_privilege);
|
||||
}
|
||||
}
|
||||
for (const auto &edge_type_privilege : edge_type_privileges) {
|
||||
edit_fine_grained_permissions_fun(role->fine_grained_access_handler().edge_type_permissions(),
|
||||
edge_type_privilege);
|
||||
}
|
||||
|
||||
#endif
|
||||
locked_auth->SaveRole(*role);
|
||||
}
|
||||
} catch (const memgraph::auth::AuthException &e) {
|
||||
|
@ -57,35 +57,62 @@ class AuthQueryHandler final : public memgraph::query::AuthQueryHandler {
|
||||
std::vector<std::vector<memgraph::query::TypedValue>> GetPrivileges(const std::string &user_or_role) override;
|
||||
|
||||
void GrantPrivilege(
|
||||
const std::string &user_or_role, const std::vector<memgraph::query::AuthQuery::Privilege> &privileges,
|
||||
const std::string &user_or_role, const std::vector<memgraph::query::AuthQuery::Privilege> &privileges
|
||||
#ifdef MG_ENTERPRISE
|
||||
,
|
||||
const std::vector<std::unordered_map<memgraph::query::AuthQuery::FineGrainedPrivilege, std::vector<std::string>>>
|
||||
&label_privileges,
|
||||
|
||||
const std::vector<std::unordered_map<memgraph::query::AuthQuery::FineGrainedPrivilege, std::vector<std::string>>>
|
||||
&edge_type_privileges) override;
|
||||
&edge_type_privileges
|
||||
#endif
|
||||
) override;
|
||||
|
||||
void DenyPrivilege(
|
||||
const std::string &user_or_role, const std::vector<memgraph::query::AuthQuery::Privilege> &privileges,
|
||||
const std::string &user_or_role, const std::vector<memgraph::query::AuthQuery::Privilege> &privileges
|
||||
#ifdef MG_ENTERPRISE
|
||||
,
|
||||
const std::vector<std::unordered_map<memgraph::query::AuthQuery::FineGrainedPrivilege, std::vector<std::string>>>
|
||||
&label_privileges,
|
||||
|
||||
const std::vector<std::unordered_map<memgraph::query::AuthQuery::FineGrainedPrivilege, std::vector<std::string>>>
|
||||
&edge_type_privileges) override;
|
||||
&edge_type_privileges
|
||||
#endif
|
||||
) override;
|
||||
|
||||
void RevokePrivilege(
|
||||
const std::string &user_or_role, const std::vector<memgraph::query::AuthQuery::Privilege> &privileges,
|
||||
const std::string &user_or_role, const std::vector<memgraph::query::AuthQuery::Privilege> &privileges
|
||||
#ifdef MG_ENTERPRISE
|
||||
,
|
||||
const std::vector<std::unordered_map<memgraph::query::AuthQuery::FineGrainedPrivilege, std::vector<std::string>>>
|
||||
&label_privileges,
|
||||
const std::vector<std::unordered_map<memgraph::query::AuthQuery::FineGrainedPrivilege, std::vector<std::string>>>
|
||||
&edge_type_privileges) override;
|
||||
&edge_type_privileges
|
||||
#endif
|
||||
) override;
|
||||
|
||||
private:
|
||||
template <class TEditPermissionsFun, class TEditFineGrainedPermissionsFun>
|
||||
template <class TEditPermissionsFun
|
||||
#ifdef MG_ENTERPRISE
|
||||
,
|
||||
class TEditFineGrainedPermissionsFun
|
||||
#endif
|
||||
>
|
||||
void EditPermissions(
|
||||
const std::string &user_or_role, const std::vector<memgraph::query::AuthQuery::Privilege> &privileges,
|
||||
const std::string &user_or_role, const std::vector<memgraph::query::AuthQuery::Privilege> &privileges
|
||||
#ifdef MG_ENTERPRISE
|
||||
,
|
||||
const std::vector<std::unordered_map<memgraph::query::AuthQuery::FineGrainedPrivilege, std::vector<std::string>>>
|
||||
&label_privileges,
|
||||
const std::vector<std::unordered_map<memgraph::query::AuthQuery::FineGrainedPrivilege, std::vector<std::string>>>
|
||||
&edge_type_privileges,
|
||||
const TEditPermissionsFun &edit_permissions_fun,
|
||||
const TEditFineGrainedPermissionsFun &edit_fine_grained_permissions_fun);
|
||||
&edge_type_privileges
|
||||
#endif
|
||||
,
|
||||
const TEditPermissionsFun &edit_permissions_fun
|
||||
#ifdef MG_ENTERPRISE
|
||||
,
|
||||
const TEditFineGrainedPermissionsFun &edit_fine_grained_permissions_fun
|
||||
#endif
|
||||
);
|
||||
};
|
||||
} // namespace memgraph::glue
|
||||
|
@ -26,10 +26,12 @@ class AuthChecker {
|
||||
[[nodiscard]] virtual bool IsUserAuthorized(const std::optional<std::string> &username,
|
||||
const std::vector<query::AuthQuery::Privilege> &privileges) const = 0;
|
||||
|
||||
#ifdef MG_ENTERPRISE
|
||||
[[nodiscard]] virtual std::unique_ptr<FineGrainedAuthChecker> GetFineGrainedAuthChecker(
|
||||
const std::string &username, const memgraph::query::DbAccessor *db_accessor) const = 0;
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifdef MG_ENTERPRISE
|
||||
class FineGrainedAuthChecker {
|
||||
public:
|
||||
virtual ~FineGrainedAuthChecker() = default;
|
||||
@ -85,6 +87,7 @@ class AllowEverythingFineGrainedAuthChecker final : public query::FineGrainedAut
|
||||
return true;
|
||||
}
|
||||
}; // namespace memgraph::query
|
||||
#endif
|
||||
|
||||
class AllowEverythingAuthChecker final : public query::AuthChecker {
|
||||
public:
|
||||
@ -93,10 +96,12 @@ class AllowEverythingAuthChecker final : public query::AuthChecker {
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef MG_ENTERPRISE
|
||||
std::unique_ptr<FineGrainedAuthChecker> GetFineGrainedAuthChecker(const std::string & /*username*/,
|
||||
const query::DbAccessor * /*dba*/) const override {
|
||||
return std::make_unique<AllowEverythingFineGrainedAuthChecker>();
|
||||
}
|
||||
};
|
||||
#endif
|
||||
}; // namespace memgraph::query
|
||||
|
||||
} // namespace memgraph::query
|
||||
|
@ -73,7 +73,9 @@ struct ExecutionContext {
|
||||
ExecutionStats execution_stats;
|
||||
TriggerContextCollector *trigger_context_collector{nullptr};
|
||||
utils::AsyncTimer timer;
|
||||
#ifdef MG_ENTERPRISE
|
||||
std::unique_ptr<FineGrainedAuthChecker> auth_checker{nullptr};
|
||||
#endif
|
||||
};
|
||||
|
||||
static_assert(std::is_move_assignable_v<ExecutionContext>, "ExecutionContext must be move assignable!");
|
||||
|
@ -289,10 +289,12 @@ Callback HandleAuthQuery(AuthQuery *auth_query, AuthQueryHandler *auth, const Pa
|
||||
std::string rolename = auth_query->role_;
|
||||
std::string user_or_role = auth_query->user_or_role_;
|
||||
std::vector<AuthQuery::Privilege> privileges = auth_query->privileges_;
|
||||
#ifdef MG_ENTERPRISE
|
||||
std::vector<std::unordered_map<AuthQuery::FineGrainedPrivilege, std::vector<std::string>>> label_privileges =
|
||||
auth_query->label_privileges_;
|
||||
std::vector<std::unordered_map<AuthQuery::FineGrainedPrivilege, std::vector<std::string>>> edge_type_privileges =
|
||||
auth_query->edge_type_privileges_;
|
||||
#endif
|
||||
auto password = EvaluateOptionalExpression(auth_query->password_, &evaluator);
|
||||
|
||||
Callback callback;
|
||||
@ -322,9 +324,19 @@ Callback HandleAuthQuery(AuthQuery *auth_query, AuthQueryHandler *auth, const Pa
|
||||
// If the license is not valid we create users with admin access
|
||||
if (!valid_enterprise_license) {
|
||||
spdlog::warn("Granting all the privileges to {}.", username);
|
||||
auth->GrantPrivilege(username, kPrivilegesAll,
|
||||
auth->GrantPrivilege(username, kPrivilegesAll
|
||||
#ifdef MG_ENTERPRISE
|
||||
,
|
||||
{{{AuthQuery::FineGrainedPrivilege::CREATE_DELETE, {auth::kAsterisk}}}},
|
||||
{{{AuthQuery::FineGrainedPrivilege::CREATE_DELETE, {auth::kAsterisk}}}});
|
||||
{
|
||||
{
|
||||
{
|
||||
AuthQuery::FineGrainedPrivilege::CREATE_DELETE, { auth::kAsterisk }
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
);
|
||||
}
|
||||
|
||||
return std::vector<std::vector<TypedValue>>();
|
||||
@ -399,20 +411,50 @@ Callback HandleAuthQuery(AuthQuery *auth_query, AuthQueryHandler *auth, const Pa
|
||||
};
|
||||
return callback;
|
||||
case AuthQuery::Action::GRANT_PRIVILEGE:
|
||||
callback.fn = [auth, user_or_role, privileges, label_privileges, edge_type_privileges] {
|
||||
auth->GrantPrivilege(user_or_role, privileges, label_privileges, edge_type_privileges);
|
||||
callback.fn = [auth, user_or_role, privileges
|
||||
#ifdef MG_ENTERPRISE
|
||||
,
|
||||
label_privileges, edge_type_privileges
|
||||
#endif
|
||||
] {
|
||||
auth->GrantPrivilege(user_or_role, privileges
|
||||
#ifdef MG_ENTERPRISE
|
||||
,
|
||||
label_privileges, edge_type_privileges
|
||||
#endif
|
||||
);
|
||||
return std::vector<std::vector<TypedValue>>();
|
||||
};
|
||||
return callback;
|
||||
case AuthQuery::Action::DENY_PRIVILEGE:
|
||||
callback.fn = [auth, user_or_role, privileges, label_privileges, edge_type_privileges] {
|
||||
auth->DenyPrivilege(user_or_role, privileges, label_privileges, edge_type_privileges);
|
||||
callback.fn = [auth, user_or_role, privileges
|
||||
#ifdef MG_ENTERPRISE
|
||||
,
|
||||
label_privileges, edge_type_privileges
|
||||
#endif
|
||||
] {
|
||||
auth->DenyPrivilege(user_or_role, privileges
|
||||
#ifdef MG_ENTERPRISE
|
||||
,
|
||||
label_privileges, edge_type_privileges
|
||||
#endif
|
||||
);
|
||||
return std::vector<std::vector<TypedValue>>();
|
||||
};
|
||||
return callback;
|
||||
case AuthQuery::Action::REVOKE_PRIVILEGE: {
|
||||
callback.fn = [auth, user_or_role, privileges, label_privileges, edge_type_privileges] {
|
||||
auth->RevokePrivilege(user_or_role, privileges, label_privileges, edge_type_privileges);
|
||||
callback.fn = [auth, user_or_role, privileges
|
||||
#ifdef MG_ENTERPRISE
|
||||
,
|
||||
label_privileges, edge_type_privileges
|
||||
#endif
|
||||
] {
|
||||
auth->RevokePrivilege(user_or_role, privileges
|
||||
#ifdef MG_ENTERPRISE
|
||||
,
|
||||
label_privileges, edge_type_privileges
|
||||
#endif
|
||||
);
|
||||
return std::vector<std::vector<TypedValue>>();
|
||||
};
|
||||
return callback;
|
||||
@ -444,7 +486,7 @@ Callback HandleAuthQuery(AuthQuery *auth_query, AuthQueryHandler *auth, const Pa
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
Callback HandleReplicationQuery(ReplicationQuery *repl_query, const Parameters ¶meters,
|
||||
InterpreterContext *interpreter_context, DbAccessor *db_accessor,
|
||||
@ -985,7 +1027,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 (username.has_value() && dba) {
|
||||
if (utils::license::global_license_checker.IsValidLicenseFast() && username.has_value() && dba) {
|
||||
ctx_.auth_checker = interpreter_context->auth_checker->GetFineGrainedAuthChecker(*username, dba);
|
||||
}
|
||||
#endif
|
||||
|
@ -100,27 +100,42 @@ class AuthQueryHandler {
|
||||
|
||||
/// @throw QueryRuntimeException if an error ocurred.
|
||||
virtual void GrantPrivilege(
|
||||
const std::string &user_or_role, const std::vector<AuthQuery::Privilege> &privileges,
|
||||
const std::vector<std::unordered_map<AuthQuery::FineGrainedPrivilege, std::vector<std::string>>>
|
||||
const std::string &user_or_role, const std::vector<AuthQuery::Privilege> &privileges
|
||||
#ifdef MG_ENTERPRISE
|
||||
,
|
||||
const std::vector<std::unordered_map<memgraph::query::AuthQuery::FineGrainedPrivilege, std::vector<std::string>>>
|
||||
&label_privileges,
|
||||
const std::vector<std::unordered_map<AuthQuery::FineGrainedPrivilege, std::vector<std::string>>>
|
||||
&edge_type_privileges) = 0;
|
||||
|
||||
const std::vector<std::unordered_map<memgraph::query::AuthQuery::FineGrainedPrivilege, std::vector<std::string>>>
|
||||
&edge_type_privileges
|
||||
#endif
|
||||
) = 0;
|
||||
|
||||
/// @throw QueryRuntimeException if an error ocurred.
|
||||
virtual void DenyPrivilege(
|
||||
const std::string &user_or_role, const std::vector<AuthQuery::Privilege> &privileges,
|
||||
const std::vector<std::unordered_map<AuthQuery::FineGrainedPrivilege, std::vector<std::string>>>
|
||||
const std::string &user_or_role, const std::vector<AuthQuery::Privilege> &privileges
|
||||
#ifdef MG_ENTERPRISE
|
||||
,
|
||||
const std::vector<std::unordered_map<memgraph::query::AuthQuery::FineGrainedPrivilege, std::vector<std::string>>>
|
||||
&label_privileges,
|
||||
const std::vector<std::unordered_map<AuthQuery::FineGrainedPrivilege, std::vector<std::string>>>
|
||||
&edge_type_privileges) = 0;
|
||||
|
||||
const std::vector<std::unordered_map<memgraph::query::AuthQuery::FineGrainedPrivilege, std::vector<std::string>>>
|
||||
&edge_type_privileges
|
||||
#endif
|
||||
) = 0;
|
||||
|
||||
/// @throw QueryRuntimeException if an error ocurred.
|
||||
virtual void RevokePrivilege(
|
||||
const std::string &user_or_role, const std::vector<AuthQuery::Privilege> &privileges,
|
||||
const std::vector<std::unordered_map<AuthQuery::FineGrainedPrivilege, std::vector<std::string>>>
|
||||
const std::string &user_or_role, const std::vector<AuthQuery::Privilege> &privileges
|
||||
#ifdef MG_ENTERPRISE
|
||||
,
|
||||
const std::vector<std::unordered_map<memgraph::query::AuthQuery::FineGrainedPrivilege, std::vector<std::string>>>
|
||||
&label_privileges,
|
||||
const std::vector<std::unordered_map<AuthQuery::FineGrainedPrivilege, std::vector<std::string>>>
|
||||
&edge_type_privileges) = 0;
|
||||
|
||||
const std::vector<std::unordered_map<memgraph::query::AuthQuery::FineGrainedPrivilege, std::vector<std::string>>>
|
||||
&edge_type_privileges
|
||||
#endif
|
||||
) = 0;
|
||||
};
|
||||
|
||||
enum class QueryHandlerResult { COMMIT, ABORT, NOTHING };
|
||||
|
@ -46,6 +46,7 @@
|
||||
#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"
|
||||
@ -239,12 +240,13 @@ CreateNode::CreateNodeCursor::CreateNodeCursor(const CreateNode &self, utils::Me
|
||||
|
||||
bool CreateNode::CreateNodeCursor::Pull(Frame &frame, ExecutionContext &context) {
|
||||
SCOPED_PROFILE_OP("CreateNode");
|
||||
|
||||
if (context.auth_checker &&
|
||||
#ifdef MG_ENTERPRISE
|
||||
if (utils::license::global_license_checker.IsValidLicenseFast() && 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!");
|
||||
}
|
||||
#endif
|
||||
|
||||
if (input_cursor_->Pull(frame, context)) {
|
||||
auto created_vertex = CreateLocalVertex(self_.node_info_, &frame, context);
|
||||
@ -330,15 +332,21 @@ bool CreateExpand::CreateExpandCursor::Pull(Frame &frame, ExecutionContext &cont
|
||||
|
||||
if (!input_cursor_->Pull(frame, context)) return false;
|
||||
|
||||
const auto fine_grained_permission = self_.existing_node_
|
||||
? memgraph::query::AuthQuery::FineGrainedPrivilege::UPDATE
|
||||
: memgraph::query::AuthQuery::FineGrainedPrivilege::CREATE_DELETE;
|
||||
if (context.auth_checker &&
|
||||
!(context.auth_checker->Has(self_.edge_info_.edge_type,
|
||||
memgraph::query::AuthQuery::FineGrainedPrivilege::CREATE_DELETE) &&
|
||||
context.auth_checker->Has(self_.node_info_.labels, fine_grained_permission))) {
|
||||
throw QueryRuntimeException("Edge not created due to not having enough permission!");
|
||||
#ifdef MG_ENTERPRISE
|
||||
if (utils::license::global_license_checker.IsValidLicenseFast()) {
|
||||
const auto fine_grained_permission = self_.existing_node_
|
||||
? memgraph::query::AuthQuery::FineGrainedPrivilege::UPDATE
|
||||
|
||||
: memgraph::query::AuthQuery::FineGrainedPrivilege::CREATE_DELETE;
|
||||
|
||||
if (context.auth_checker &&
|
||||
!(context.auth_checker->Has(self_.edge_info_.edge_type,
|
||||
memgraph::query::AuthQuery::FineGrainedPrivilege::CREATE_DELETE) &&
|
||||
context.auth_checker->Has(self_.node_info_.labels, fine_grained_permission))) {
|
||||
throw QueryRuntimeException("Edge not created due to not having enough permission!");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
// get the origin vertex
|
||||
TypedValue &vertex_value = frame[self_.input_symbol_];
|
||||
ExpectType(self_.input_symbol_, vertex_value, TypedValue::Type::Vertex);
|
||||
@ -423,16 +431,19 @@ class ScanAllCursor : public Cursor {
|
||||
vertices_.emplace(std::move(next_vertices.value()));
|
||||
vertices_it_.emplace(vertices_.value().begin());
|
||||
}
|
||||
|
||||
if (context.auth_checker && !FindNextVertex(context)) {
|
||||
#ifdef MG_ENTERPRISE
|
||||
if (utils::license::global_license_checker.IsValidLicenseFast() && context.auth_checker &&
|
||||
!FindNextVertex(context)) {
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
frame[output_symbol_] = *vertices_it_.value();
|
||||
++vertices_it_.value();
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef MG_ENTERPRISE
|
||||
bool FindNextVertex(const ExecutionContext &context) {
|
||||
while (vertices_it_.value() != vertices_.value().end()) {
|
||||
if (context.auth_checker->Has(*vertices_it_.value(), memgraph::storage::View::OLD,
|
||||
@ -441,9 +452,9 @@ class ScanAllCursor : public Cursor {
|
||||
}
|
||||
++vertices_it_.value();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
void Shutdown() override { input_cursor_->Shutdown(); }
|
||||
|
||||
@ -718,12 +729,14 @@ bool Expand::ExpandCursor::Pull(Frame &frame, ExecutionContext &context) {
|
||||
// attempt to get a value from the incoming edges
|
||||
if (in_edges_ && *in_edges_it_ != in_edges_->end()) {
|
||||
auto edge = *(*in_edges_it_)++;
|
||||
if (context.auth_checker &&
|
||||
#ifdef MG_ENTERPRISE
|
||||
if (utils::license::global_license_checker.IsValidLicenseFast() && 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))) {
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
|
||||
frame[self_.common_.edge_symbol] = edge;
|
||||
pull_node(edge, EdgeAtom::Direction::IN);
|
||||
@ -737,13 +750,14 @@ bool Expand::ExpandCursor::Pull(Frame &frame, ExecutionContext &context) {
|
||||
// we should do only one expansion for cycles, and it was
|
||||
// already done in the block above
|
||||
if (self_.common_.direction == EdgeAtom::Direction::BOTH && edge.IsCycle()) continue;
|
||||
if (context.auth_checker &&
|
||||
#ifdef MG_ENTERPRISE
|
||||
if (utils::license::global_license_checker.IsValidLicenseFast() && 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))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
#endif
|
||||
frame[self_.common_.edge_symbol] = edge;
|
||||
pull_node(edge, EdgeAtom::Direction::OUT);
|
||||
return true;
|
||||
@ -1073,13 +1087,14 @@ class ExpandVariableCursor : public Cursor {
|
||||
|
||||
VertexAccessor current_vertex =
|
||||
current_edge.second == EdgeAtom::Direction::IN ? current_edge.first.From() : current_edge.first.To();
|
||||
|
||||
if (context.auth_checker &&
|
||||
#ifdef MG_ENTERPRISE
|
||||
if (utils::license::global_license_checker.IsValidLicenseFast() && 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))) {
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
AppendEdge(current_edge.first, &edges_on_frame);
|
||||
|
||||
if (!self_.common_.existing_node) {
|
||||
@ -1241,12 +1256,14 @@ class STShortestPathCursor : public query::plan::Cursor {
|
||||
if (self_.common_.direction != EdgeAtom::Direction::IN) {
|
||||
auto out_edges = UnwrapEdgesResult(vertex.OutEdges(storage::View::OLD, self_.common_.edge_types));
|
||||
for (const auto &edge : out_edges) {
|
||||
if (context.auth_checker &&
|
||||
#ifdef MG_ENTERPRISE
|
||||
if (utils::license::global_license_checker.IsValidLicenseFast() && 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))) {
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (ShouldExpand(edge.To(), edge, frame, evaluator) && !Contains(in_edge, edge.To())) {
|
||||
in_edge.emplace(edge.To(), edge);
|
||||
@ -1265,12 +1282,14 @@ class STShortestPathCursor : public query::plan::Cursor {
|
||||
if (self_.common_.direction != EdgeAtom::Direction::OUT) {
|
||||
auto in_edges = UnwrapEdgesResult(vertex.InEdges(storage::View::OLD, self_.common_.edge_types));
|
||||
for (const auto &edge : in_edges) {
|
||||
if (context.auth_checker &&
|
||||
#ifdef MG_ENTERPRISE
|
||||
if (utils::license::global_license_checker.IsValidLicenseFast() && 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))) {
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (ShouldExpand(edge.From(), edge, frame, evaluator) && !Contains(in_edge, edge.From())) {
|
||||
in_edge.emplace(edge.From(), edge);
|
||||
@ -1303,12 +1322,14 @@ class STShortestPathCursor : public query::plan::Cursor {
|
||||
if (self_.common_.direction != EdgeAtom::Direction::OUT) {
|
||||
auto out_edges = UnwrapEdgesResult(vertex.OutEdges(storage::View::OLD, self_.common_.edge_types));
|
||||
for (const auto &edge : out_edges) {
|
||||
if (context.auth_checker &&
|
||||
#ifdef MG_ENTERPRISE
|
||||
if (utils::license::global_license_checker.IsValidLicenseFast() && 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))) {
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
if (ShouldExpand(vertex, edge, frame, evaluator) && !Contains(out_edge, edge.To())) {
|
||||
out_edge.emplace(edge.To(), edge);
|
||||
if (Contains(in_edge, edge.To())) {
|
||||
@ -1326,12 +1347,14 @@ class STShortestPathCursor : public query::plan::Cursor {
|
||||
if (self_.common_.direction != EdgeAtom::Direction::IN) {
|
||||
auto in_edges = UnwrapEdgesResult(vertex.InEdges(storage::View::OLD, self_.common_.edge_types));
|
||||
for (const auto &edge : in_edges) {
|
||||
if (context.auth_checker &&
|
||||
#ifdef MG_ENTERPRISE
|
||||
if (utils::license::global_license_checker.IsValidLicenseFast() && 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))) {
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
if (ShouldExpand(vertex, edge, frame, evaluator) && !Contains(out_edge, edge.From())) {
|
||||
out_edge.emplace(edge.From(), edge);
|
||||
if (Contains(in_edge, edge.From())) {
|
||||
@ -1381,13 +1404,14 @@ class SingleSourceShortestPathCursor : public query::plan::Cursor {
|
||||
auto expand_pair = [this, &evaluator, &frame, &context](EdgeAccessor edge, VertexAccessor vertex) {
|
||||
// if we already processed the given vertex it doesn't get expanded
|
||||
if (processed_.find(vertex) != processed_.end()) return;
|
||||
|
||||
if (context.auth_checker &&
|
||||
#ifdef MG_ENTERPRISE
|
||||
if (utils::license::global_license_checker.IsValidLicenseFast() && 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))) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
frame[self_.filter_lambda_.inner_edge_symbol] = edge;
|
||||
frame[self_.filter_lambda_.inner_node_symbol] = vertex;
|
||||
|
||||
@ -1566,13 +1590,14 @@ class ExpandWeightedShortestPathCursor : public query::plan::Cursor {
|
||||
const EdgeAccessor &edge, const VertexAccessor &vertex, const TypedValue &total_weight,
|
||||
int64_t depth) {
|
||||
auto *memory = evaluator.GetMemoryResource();
|
||||
|
||||
if (context.auth_checker &&
|
||||
#ifdef MG_ENTERPRISE
|
||||
if (utils::license::global_license_checker.IsValidLicenseFast() && 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))) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
if (self_.filter_lambda_.expression) {
|
||||
frame[self_.filter_lambda_.inner_edge_symbol] = edge;
|
||||
frame[self_.filter_lambda_.inner_node_symbol] = vertex;
|
||||
@ -1875,24 +1900,28 @@ class ExpandAllShortestPathsCursor : public query::plan::Cursor {
|
||||
if (self_.common_.direction != EdgeAtom::Direction::IN) {
|
||||
auto out_edges = UnwrapEdgesResult(vertex.OutEdges(storage::View::OLD, self_.common_.edge_types));
|
||||
for (const auto &edge : out_edges) {
|
||||
if (context.auth_checker &&
|
||||
#ifdef MG_ENTERPRISE
|
||||
if (utils::license::global_license_checker.IsValidLicenseFast() && 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))) {
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
expand_vertex(edge, EdgeAtom::Direction::OUT, weight, depth);
|
||||
}
|
||||
}
|
||||
if (self_.common_.direction != EdgeAtom::Direction::OUT) {
|
||||
auto in_edges = UnwrapEdgesResult(vertex.InEdges(storage::View::OLD, self_.common_.edge_types));
|
||||
for (const auto &edge : in_edges) {
|
||||
if (context.auth_checker &&
|
||||
#ifdef MG_ENTERPRISE
|
||||
if (utils::license::global_license_checker.IsValidLicenseFast() && 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))) {
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
expand_vertex(edge, EdgeAtom::Direction::IN, weight, depth);
|
||||
}
|
||||
}
|
||||
@ -1915,8 +1944,8 @@ class ExpandAllShortestPathsCursor : public query::plan::Cursor {
|
||||
// Check if there is an external error.
|
||||
if (MustAbort(context)) throw HintedAbortError();
|
||||
|
||||
// If traversal stack if filled, the DFS traversal tree is created. Traverse the tree iteratively by preserving
|
||||
// the traversal state on stack.
|
||||
// If traversal stack if filled, the DFS traversal tree is created. Traverse the tree iteratively by
|
||||
// preserving the traversal state on stack.
|
||||
while (!traversal_stack_.empty()) {
|
||||
auto ¤t_level = traversal_stack_.back();
|
||||
auto &edges_on_frame = frame[self_.common_.edge_symbol].ValueList();
|
||||
@ -2335,12 +2364,14 @@ bool Delete::DeleteCursor::Pull(Frame &frame, ExecutionContext &context) {
|
||||
if (MustAbort(context)) throw HintedAbortError();
|
||||
if (expression_result.type() == TypedValue::Type::Edge) {
|
||||
auto &ea = expression_result.ValueEdge();
|
||||
if (context.auth_checker &&
|
||||
#ifdef MG_ENTERPRISE
|
||||
if (utils::license::global_license_checker.IsValidLicenseFast() && 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))) {
|
||||
throw QueryRuntimeException("Edge not deleted due to not having enough permission!");
|
||||
}
|
||||
#endif
|
||||
auto maybe_value = dba.RemoveEdge(&ea);
|
||||
if (maybe_value.HasError()) {
|
||||
switch (maybe_value.GetError()) {
|
||||
@ -2366,10 +2397,12 @@ bool Delete::DeleteCursor::Pull(Frame &frame, ExecutionContext &context) {
|
||||
switch (expression_result.type()) {
|
||||
case TypedValue::Type::Vertex: {
|
||||
auto &va = expression_result.ValueVertex();
|
||||
if (context.auth_checker &&
|
||||
#ifdef MG_ENTERPRISE
|
||||
if (utils::license::global_license_checker.IsValidLicenseFast() && 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!");
|
||||
}
|
||||
#endif
|
||||
if (self_.detach_) {
|
||||
auto res = dba.DetachRemoveVertex(&va);
|
||||
if (res.HasError()) {
|
||||
@ -2473,12 +2506,13 @@ bool SetProperty::SetPropertyCursor::Pull(Frame &frame, ExecutionContext &contex
|
||||
|
||||
switch (lhs.type()) {
|
||||
case TypedValue::Type::Vertex: {
|
||||
if (context.auth_checker &&
|
||||
#ifdef MG_ENTERPRISE
|
||||
if (utils::license::global_license_checker.IsValidLicenseFast() && 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!");
|
||||
}
|
||||
|
||||
#endif
|
||||
auto old_value = PropsSetChecked(&lhs.ValueVertex(), self_.property_, rhs);
|
||||
context.execution_stats[ExecutionStats::Key::UPDATED_PROPERTIES] += 1;
|
||||
if (context.trigger_context_collector) {
|
||||
@ -2489,15 +2523,17 @@ bool SetProperty::SetPropertyCursor::Pull(Frame &frame, ExecutionContext &contex
|
||||
break;
|
||||
}
|
||||
case TypedValue::Type::Edge: {
|
||||
if (context.auth_checker &&
|
||||
#ifdef MG_ENTERPRISE
|
||||
if (utils::license::global_license_checker.IsValidLicenseFast() && 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!");
|
||||
}
|
||||
|
||||
#endif
|
||||
auto old_value = PropsSetChecked(&lhs.ValueEdge(), self_.property_, rhs);
|
||||
context.execution_stats[ExecutionStats::Key::UPDATED_PROPERTIES] += 1;
|
||||
if (context.trigger_context_collector) {
|
||||
// rhs cannot be moved because it was created with the allocator that is only valid during current pull
|
||||
// rhs cannot be moved because it was created with the allocator that is only valid
|
||||
// during current pull
|
||||
context.trigger_context_collector->RegisterSetObjectProperty(lhs.ValueEdge(), self_.property_,
|
||||
TypedValue{std::move(old_value)}, TypedValue{rhs});
|
||||
}
|
||||
@ -2686,20 +2722,23 @@ bool SetProperties::SetPropertiesCursor::Pull(Frame &frame, ExecutionContext &co
|
||||
|
||||
switch (lhs.type()) {
|
||||
case TypedValue::Type::Vertex:
|
||||
if (context.auth_checker &&
|
||||
#ifdef MG_ENTERPRISE
|
||||
if (utils::license::global_license_checker.IsValidLicenseFast() && 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!");
|
||||
}
|
||||
#endif
|
||||
|
||||
SetPropertiesOnRecord(&lhs.ValueVertex(), rhs, self_.op_, &context);
|
||||
break;
|
||||
case TypedValue::Type::Edge:
|
||||
if (context.auth_checker &&
|
||||
#ifdef MG_ENTERPRISE
|
||||
if (utils::license::global_license_checker.IsValidLicenseFast() && 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!");
|
||||
}
|
||||
|
||||
#endif
|
||||
SetPropertiesOnRecord(&lhs.ValueEdge(), rhs, self_.op_, &context);
|
||||
break;
|
||||
case TypedValue::Type::Null:
|
||||
@ -2737,10 +2776,12 @@ SetLabels::SetLabelsCursor::SetLabelsCursor(const SetLabels &self, utils::Memory
|
||||
bool SetLabels::SetLabelsCursor::Pull(Frame &frame, ExecutionContext &context) {
|
||||
SCOPED_PROFILE_OP("SetLabels");
|
||||
|
||||
if (context.auth_checker &&
|
||||
#ifdef MG_ENTERPRISE
|
||||
if (utils::license::global_license_checker.IsValidLicenseFast() && 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!");
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!input_cursor_->Pull(frame, context)) return false;
|
||||
|
||||
@ -2750,10 +2791,13 @@ bool SetLabels::SetLabelsCursor::Pull(Frame &frame, ExecutionContext &context) {
|
||||
ExpectType(self_.input_symbol_, vertex_value, TypedValue::Type::Vertex);
|
||||
auto &vertex = vertex_value.ValueVertex();
|
||||
|
||||
if (context.auth_checker && !context.auth_checker->Has(vertex, storage::View::OLD,
|
||||
memgraph::query::AuthQuery::FineGrainedPrivilege::UPDATE)) {
|
||||
#ifdef MG_ENTERPRISE
|
||||
if (utils::license::global_license_checker.IsValidLicenseFast() && 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!");
|
||||
}
|
||||
#endif
|
||||
|
||||
for (auto label : self_.labels_) {
|
||||
auto maybe_value = vertex.AddLabel(label);
|
||||
@ -2837,20 +2881,22 @@ bool RemoveProperty::RemovePropertyCursor::Pull(Frame &frame, ExecutionContext &
|
||||
|
||||
switch (lhs.type()) {
|
||||
case TypedValue::Type::Vertex:
|
||||
if (context.auth_checker &&
|
||||
#ifdef MG_ENTERPRISE
|
||||
if (utils::license::global_license_checker.IsValidLicenseFast() && 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!");
|
||||
}
|
||||
|
||||
#endif
|
||||
remove_prop(&lhs.ValueVertex());
|
||||
break;
|
||||
case TypedValue::Type::Edge:
|
||||
if (context.auth_checker &&
|
||||
#ifdef MG_ENTERPRISE
|
||||
if (utils::license::global_license_checker.IsValidLicenseFast() && 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!");
|
||||
}
|
||||
|
||||
#endif
|
||||
remove_prop(&lhs.ValueEdge());
|
||||
break;
|
||||
case TypedValue::Type::Null:
|
||||
@ -2888,10 +2934,12 @@ RemoveLabels::RemoveLabelsCursor::RemoveLabelsCursor(const RemoveLabels &self, u
|
||||
bool RemoveLabels::RemoveLabelsCursor::Pull(Frame &frame, ExecutionContext &context) {
|
||||
SCOPED_PROFILE_OP("RemoveLabels");
|
||||
|
||||
if (context.auth_checker &&
|
||||
#ifdef MG_ENTERPRISE
|
||||
if (utils::license::global_license_checker.IsValidLicenseFast() && 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!");
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!input_cursor_->Pull(frame, context)) return false;
|
||||
|
||||
@ -2900,10 +2948,14 @@ bool RemoveLabels::RemoveLabelsCursor::Pull(Frame &frame, ExecutionContext &cont
|
||||
if (vertex_value.IsNull()) return true;
|
||||
ExpectType(self_.input_symbol_, vertex_value, TypedValue::Type::Vertex);
|
||||
auto &vertex = vertex_value.ValueVertex();
|
||||
if (context.auth_checker && !context.auth_checker->Has(vertex, storage::View::OLD,
|
||||
memgraph::query::AuthQuery::FineGrainedPrivilege::UPDATE)) {
|
||||
|
||||
#ifdef MG_ENTERPRISE
|
||||
if (utils::license::global_license_checker.IsValidLicenseFast() && 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!");
|
||||
}
|
||||
#endif
|
||||
|
||||
for (auto label : self_.labels_) {
|
||||
auto maybe_value = vertex.RemoveLabel(label);
|
||||
|
@ -32,6 +32,7 @@
|
||||
#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"
|
||||
@ -1589,11 +1590,12 @@ mgp_error mgp_vertex_set_property(struct mgp_vertex *v, const char *property_nam
|
||||
return WrapExceptions([=] {
|
||||
auto *ctx = v->graph->ctx;
|
||||
|
||||
if (ctx && ctx->auth_checker &&
|
||||
#ifdef MG_ENTERPRISE
|
||||
if (memgraph::utils::license::global_license_checker.IsValidLicenseFast() && ctx && ctx->auth_checker &&
|
||||
!ctx->auth_checker->Has(v->impl, v->graph->view, memgraph::query::AuthQuery::FineGrainedPrivilege::UPDATE)) {
|
||||
throw AuthorizationException{"Insufficient permissions for setting a property on vertex!"};
|
||||
}
|
||||
|
||||
#endif
|
||||
if (!MgpVertexIsMutable(*v)) {
|
||||
throw ImmutableObjectException{"Cannot set a property on an immutable vertex!"};
|
||||
}
|
||||
@ -1635,12 +1637,14 @@ mgp_error mgp_vertex_add_label(struct mgp_vertex *v, mgp_label label) {
|
||||
return WrapExceptions([=] {
|
||||
auto *ctx = v->graph->ctx;
|
||||
|
||||
if (ctx && ctx->auth_checker &&
|
||||
#ifdef MG_ENTERPRISE
|
||||
if (memgraph::utils::license::global_license_checker.IsValidLicenseFast() && ctx && ctx->auth_checker &&
|
||||
!(ctx->auth_checker->Has(v->impl, v->graph->view, memgraph::query::AuthQuery::FineGrainedPrivilege::UPDATE) &&
|
||||
ctx->auth_checker->Has({v->graph->impl->NameToLabel(label.name)},
|
||||
memgraph::query::AuthQuery::FineGrainedPrivilege::CREATE_DELETE))) {
|
||||
throw AuthorizationException{"Insufficient permissions for adding a label to vertex!"};
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!MgpVertexIsMutable(*v)) {
|
||||
throw ImmutableObjectException{"Cannot add a label to an immutable vertex!"};
|
||||
@ -1674,13 +1678,14 @@ mgp_error mgp_vertex_remove_label(struct mgp_vertex *v, mgp_label label) {
|
||||
return WrapExceptions([=] {
|
||||
auto *ctx = v->graph->ctx;
|
||||
|
||||
if (ctx && ctx->auth_checker &&
|
||||
#ifdef MG_ENTERPRISE
|
||||
if (memgraph::utils::license::global_license_checker.IsValidLicenseFast() && ctx && ctx->auth_checker &&
|
||||
!(ctx->auth_checker->Has(v->impl, v->graph->view, memgraph::query::AuthQuery::FineGrainedPrivilege::UPDATE) &&
|
||||
ctx->auth_checker->Has({v->graph->impl->NameToLabel(label.name)},
|
||||
memgraph::query::AuthQuery::FineGrainedPrivilege::CREATE_DELETE))) {
|
||||
throw AuthorizationException{"Insufficient permissions for removing a label from vertex!"};
|
||||
}
|
||||
|
||||
#endif
|
||||
if (!MgpVertexIsMutable(*v)) {
|
||||
throw ImmutableObjectException{"Cannot remove a label from an immutable vertex!"};
|
||||
}
|
||||
@ -1856,6 +1861,7 @@ mgp_error mgp_vertex_iter_properties(mgp_vertex *v, mgp_memory *memory, mgp_prop
|
||||
|
||||
void mgp_edges_iterator_destroy(mgp_edges_iterator *it) { DeleteRawMgpObject(it); }
|
||||
|
||||
#ifdef MG_ENTERPRISE
|
||||
namespace {
|
||||
void NextPermittedEdge(mgp_edges_iterator &it, const bool for_in) {
|
||||
if (const auto *ctx = it.source_vertex.graph->ctx; !ctx || !ctx->auth_checker) return;
|
||||
@ -1879,6 +1885,7 @@ void NextPermittedEdge(mgp_edges_iterator &it, const bool for_in) {
|
||||
}
|
||||
};
|
||||
} // namespace
|
||||
#endif
|
||||
|
||||
mgp_error mgp_vertex_iter_in_edges(mgp_vertex *v, mgp_memory *memory, mgp_edges_iterator **result) {
|
||||
return WrapExceptions(
|
||||
@ -1903,8 +1910,11 @@ 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());
|
||||
|
||||
NextPermittedEdge(*it, true);
|
||||
#ifdef MG_ENTERPRISE
|
||||
if (memgraph::utils::license::global_license_checker.IsValidLicenseFast()) {
|
||||
NextPermittedEdge(*it, true);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (*it->in_it != it->in->end()) {
|
||||
it->current_e.emplace(**it->in_it, v->graph, it->GetMemoryResource());
|
||||
@ -1939,7 +1949,11 @@ mgp_error mgp_vertex_iter_out_edges(mgp_vertex *v, mgp_memory *memory, mgp_edges
|
||||
it->out.emplace(std::move(*maybe_edges));
|
||||
it->out_it.emplace(it->out->begin());
|
||||
|
||||
NextPermittedEdge(*it, false);
|
||||
#ifdef MG_ENTERPRISE
|
||||
if (memgraph::utils::license::global_license_checker.IsValidLicenseFast()) {
|
||||
NextPermittedEdge(*it, false);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (*it->out_it != it->out->end()) {
|
||||
it->current_e.emplace(**it->out_it, v->graph, it->GetMemoryResource());
|
||||
@ -1981,7 +1995,11 @@ mgp_error mgp_edges_iterator_next(mgp_edges_iterator *it, mgp_edge **result) {
|
||||
|
||||
++*impl_it;
|
||||
|
||||
NextPermittedEdge(*it, for_in);
|
||||
#ifdef MG_ENTERPRISE
|
||||
if (memgraph::utils::license::global_license_checker.IsValidLicenseFast()) {
|
||||
NextPermittedEdge(*it, for_in);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (*impl_it == end) {
|
||||
it->current_e = std::nullopt;
|
||||
@ -2073,10 +2091,12 @@ mgp_error mgp_edge_set_property(struct mgp_edge *e, const char *property_name, m
|
||||
return WrapExceptions([=] {
|
||||
auto *ctx = e->from.graph->ctx;
|
||||
|
||||
if (ctx && ctx->auth_checker &&
|
||||
#ifdef MG_ENTERPRISE
|
||||
if (memgraph::utils::license::global_license_checker.IsValidLicenseFast() && 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!"};
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!MgpEdgeIsMutable(*e)) {
|
||||
throw ImmutableObjectException{"Cannot set a property on an immutable edge!"};
|
||||
@ -2164,11 +2184,15 @@ mgp_error mgp_graph_is_mutable(mgp_graph *graph, int *result) {
|
||||
mgp_error mgp_graph_create_vertex(struct mgp_graph *graph, mgp_memory *memory, mgp_vertex **result) {
|
||||
return WrapExceptions(
|
||||
[=]() -> mgp_vertex * {
|
||||
if (graph->ctx && graph->ctx->auth_checker &&
|
||||
|
||||
#ifdef MG_ENTERPRISE
|
||||
if (memgraph::utils::license::global_license_checker.IsValidLicenseFast() && graph->ctx &&
|
||||
graph->ctx->auth_checker &&
|
||||
!graph->ctx->auth_checker->HasGlobalPrivilegeOnVertices(
|
||||
memgraph::query::AuthQuery::FineGrainedPrivilege::CREATE_DELETE)) {
|
||||
throw AuthorizationException{"Insufficient permissions for creating vertices!"};
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!MgpGraphIsMutable(*graph)) {
|
||||
throw ImmutableObjectException{"Cannot create a vertex in an immutable graph!"};
|
||||
@ -2190,11 +2214,13 @@ mgp_error mgp_graph_delete_vertex(struct mgp_graph *graph, mgp_vertex *vertex) {
|
||||
return WrapExceptions([=] {
|
||||
auto *ctx = graph->ctx;
|
||||
|
||||
if (ctx && ctx->auth_checker &&
|
||||
#ifdef MG_ENTERPRISE
|
||||
if (memgraph::utils::license::global_license_checker.IsValidLicenseFast() && ctx && ctx->auth_checker &&
|
||||
!ctx->auth_checker->Has(vertex->impl, graph->view,
|
||||
memgraph::query::AuthQuery::FineGrainedPrivilege::CREATE_DELETE)) {
|
||||
throw AuthorizationException{"Insufficient permissions for deleting a vertex!"};
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!MgpGraphIsMutable(*graph)) {
|
||||
throw ImmutableObjectException{"Cannot remove a vertex from an immutable graph!"};
|
||||
@ -2230,12 +2256,13 @@ mgp_error mgp_graph_delete_vertex(struct mgp_graph *graph, mgp_vertex *vertex) {
|
||||
mgp_error mgp_graph_detach_delete_vertex(struct mgp_graph *graph, mgp_vertex *vertex) {
|
||||
return WrapExceptions([=] {
|
||||
auto *ctx = graph->ctx;
|
||||
|
||||
if (ctx && ctx->auth_checker &&
|
||||
#ifdef MG_ENTERPRISE
|
||||
if (memgraph::utils::license::global_license_checker.IsValidLicenseFast() && ctx && ctx->auth_checker &&
|
||||
!ctx->auth_checker->Has(vertex->impl, graph->view,
|
||||
memgraph::query::AuthQuery::FineGrainedPrivilege::CREATE_DELETE)) {
|
||||
throw AuthorizationException{"Insufficient permissions for deleting a vertex!"};
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!MgpGraphIsMutable(*graph)) {
|
||||
throw ImmutableObjectException{"Cannot remove a vertex from an immutable graph!"};
|
||||
@ -2283,13 +2310,13 @@ mgp_error mgp_graph_create_edge(mgp_graph *graph, mgp_vertex *from, mgp_vertex *
|
||||
return WrapExceptions(
|
||||
[=]() -> mgp_edge * {
|
||||
auto *ctx = graph->ctx;
|
||||
|
||||
if (ctx && ctx->auth_checker &&
|
||||
#ifdef MG_ENTERPRISE
|
||||
if (memgraph::utils::license::global_license_checker.IsValidLicenseFast() && ctx && ctx->auth_checker &&
|
||||
!ctx->auth_checker->Has(from->graph->impl->NameToEdgeType(type.name),
|
||||
memgraph::query::AuthQuery::FineGrainedPrivilege::CREATE_DELETE)) {
|
||||
throw AuthorizationException{"Insufficient permissions for creating edges!"};
|
||||
}
|
||||
|
||||
#endif
|
||||
if (!MgpGraphIsMutable(*graph)) {
|
||||
throw ImmutableObjectException{"Cannot create an edge in an immutable graph!"};
|
||||
}
|
||||
@ -2322,11 +2349,12 @@ mgp_error mgp_graph_create_edge(mgp_graph *graph, mgp_vertex *from, mgp_vertex *
|
||||
mgp_error mgp_graph_delete_edge(struct mgp_graph *graph, mgp_edge *edge) {
|
||||
return WrapExceptions([=] {
|
||||
auto *ctx = graph->ctx;
|
||||
|
||||
if (ctx && ctx->auth_checker &&
|
||||
#ifdef MG_ENTERPRISE
|
||||
if (memgraph::utils::license::global_license_checker.IsValidLicenseFast() && ctx && ctx->auth_checker &&
|
||||
!ctx->auth_checker->Has(edge->impl, memgraph::query::AuthQuery::FineGrainedPrivilege::CREATE_DELETE)) {
|
||||
throw AuthorizationException{"Insufficient permissions for deleting an edge!"};
|
||||
}
|
||||
#endif
|
||||
if (!MgpGraphIsMutable(*graph)) {
|
||||
throw ImmutableObjectException{"Cannot remove an edge from an immutable graph!"};
|
||||
}
|
||||
@ -2356,6 +2384,7 @@ mgp_error mgp_graph_delete_edge(struct mgp_graph *graph, mgp_edge *edge) {
|
||||
});
|
||||
}
|
||||
|
||||
#ifdef MG_ENTERPRISE
|
||||
namespace {
|
||||
void NextPermitted(mgp_vertices_iterator &it) {
|
||||
const auto *ctx = it.graph->ctx;
|
||||
@ -2374,11 +2403,16 @@ void NextPermitted(mgp_vertices_iterator &it) {
|
||||
}
|
||||
};
|
||||
} // namespace
|
||||
#endif
|
||||
|
||||
/// @throw anything VerticesIterable may throw
|
||||
mgp_vertices_iterator::mgp_vertices_iterator(mgp_graph *graph, memgraph::utils::MemoryResource *memory)
|
||||
: memory(memory), graph(graph), vertices(graph->impl->Vertices(graph->view)), current_it(vertices.begin()) {
|
||||
NextPermitted(*this);
|
||||
#ifdef MG_ENTERPRISE
|
||||
if (memgraph::utils::license::global_license_checker.IsValidLicenseFast()) {
|
||||
NextPermitted(*this);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (current_it != vertices.end()) {
|
||||
current_v.emplace(*current_it, graph, memory);
|
||||
@ -2417,9 +2451,11 @@ mgp_error mgp_vertices_iterator_next(mgp_vertices_iterator *it, mgp_vertex **res
|
||||
}
|
||||
|
||||
++it->current_it;
|
||||
|
||||
NextPermitted(*it);
|
||||
|
||||
#ifdef MG_ENTERPRISE
|
||||
if (memgraph::utils::license::global_license_checker.IsValidLicenseFast()) {
|
||||
NextPermitted(*it);
|
||||
}
|
||||
#endif
|
||||
if (it->current_it == it->vertices.end()) {
|
||||
it->current_v = std::nullopt;
|
||||
return nullptr;
|
||||
|
@ -161,6 +161,7 @@ TEST_F(AuthWithStorage, UserRolePermissions) {
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef MG_ENTERPRISE
|
||||
TEST_F(AuthWithStorage, UserRoleFineGrainedAccessHandler) {
|
||||
ASSERT_FALSE(auth.HasUsers());
|
||||
ASSERT_TRUE(auth.AddUser("test"));
|
||||
@ -239,6 +240,7 @@ TEST_F(AuthWithStorage, UserRoleFineGrainedAccessHandler) {
|
||||
PermissionLevel::DENY);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
TEST_F(AuthWithStorage, RoleManipulations) {
|
||||
{
|
||||
@ -488,6 +490,7 @@ TEST(AuthWithoutStorage, PermissionsMaskTest) {
|
||||
ASSERT_EQ(p4.denies(), 2);
|
||||
}
|
||||
|
||||
#ifdef MG_ENTERPRISE
|
||||
TEST(AuthWithoutStorage, FineGrainedAccessPermissions) {
|
||||
const std::string any_label = "AnyString";
|
||||
const std::string check_label = "Label";
|
||||
@ -776,6 +779,7 @@ TEST(AuthWithoutStorage, FineGrainedAccessPermissions) {
|
||||
ASSERT_EQ(fga_permissions.Has(non_check_label, FineGrainedPermission::READ), PermissionLevel::DENY);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(AuthWithStorage, FineGrainedAccessCheckerMerge) {
|
||||
auto any_label = "AnyString";
|
||||
auto check_label = "Label";
|
||||
@ -842,6 +846,7 @@ TEST_F(AuthWithStorage, FineGrainedAccessCheckerMerge) {
|
||||
ASSERT_EQ(fga_permissions3.Has(check_label, FineGrainedPermission::READ), PermissionLevel::GRANT);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
TEST(AuthWithoutStorage, UserSerializeDeserialize) {
|
||||
auto user = User("test");
|
||||
|
@ -17,7 +17,9 @@
|
||||
|
||||
#include "query_plan_common.hpp"
|
||||
#include "storage/v2/view.hpp"
|
||||
#include "utils/license.hpp"
|
||||
|
||||
#ifdef MG_ENTERPRISE
|
||||
class FineGrainedAuthCheckerFixture : public testing::Test {
|
||||
protected:
|
||||
memgraph::storage::Storage db;
|
||||
@ -37,6 +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();
|
||||
ASSERT_TRUE(v1.AddLabel(dba.NameToLabel("l1")).HasValue());
|
||||
ASSERT_TRUE(v2.AddLabel(dba.NameToLabel("l2")).HasValue());
|
||||
ASSERT_TRUE(v3.AddLabel(dba.NameToLabel("l3")).HasValue());
|
||||
@ -205,3 +208,4 @@ TEST_F(FineGrainedAuthCheckerFixture, GrantAndDenySpecificEdgeTypes) {
|
||||
ASSERT_FALSE(auth_checker.Has(r3, memgraph::query::AuthQuery::FineGrainedPrivilege::READ));
|
||||
ASSERT_FALSE(auth_checker.Has(r4, memgraph::query::AuthQuery::FineGrainedPrivilege::READ));
|
||||
}
|
||||
#endif
|
||||
|
@ -32,8 +32,9 @@ class AuthQueryHandlerFixture : public testing::Test {
|
||||
std::string edge_type_repr = "EdgeType1";
|
||||
std::string label_repr = "Label1";
|
||||
memgraph::auth::Permissions perms{};
|
||||
#ifdef MG_ENTERPRISE
|
||||
memgraph::auth::FineGrainedAccessHandler handler{};
|
||||
|
||||
#endif
|
||||
virtual void SetUp() {
|
||||
memgraph::utils::EnsureDir(test_folder_);
|
||||
memgraph::utils::license::global_license_checker.EnableTesting();
|
||||
@ -42,7 +43,9 @@ class AuthQueryHandlerFixture : public testing::Test {
|
||||
virtual void TearDown() {
|
||||
std::filesystem::remove_all(test_folder_);
|
||||
perms = memgraph::auth::Permissions{};
|
||||
#ifdef MG_ENTERPRISE
|
||||
handler = memgraph::auth::FineGrainedAccessHandler{};
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
@ -52,7 +55,7 @@ TEST_F(AuthQueryHandlerFixture, GivenAuthQueryHandlerWhenInitializedHaveNoUserna
|
||||
}
|
||||
|
||||
TEST_F(AuthQueryHandlerFixture, GivenUserWhenNoDeniesOrGrantsThenNothingIsReturned) {
|
||||
memgraph::auth::User user = memgraph::auth::User{user_name, "", perms, handler};
|
||||
memgraph::auth::User user = memgraph::auth::User{user_name, "", perms};
|
||||
auth->SaveUser(user);
|
||||
|
||||
{ ASSERT_EQ(auth_handler.GetUsernames().size(), 1); }
|
||||
@ -66,7 +69,7 @@ TEST_F(AuthQueryHandlerFixture, GivenUserWhenNoDeniesOrGrantsThenNothingIsReturn
|
||||
|
||||
TEST_F(AuthQueryHandlerFixture, GivenUserWhenAddedGrantPermissionThenItIsReturned) {
|
||||
perms.Grant(memgraph::auth::Permission::MATCH);
|
||||
memgraph::auth::User user = memgraph::auth::User{user_name, "", perms, handler};
|
||||
memgraph::auth::User user = memgraph::auth::User{user_name, "", perms};
|
||||
auth->SaveUser(user);
|
||||
|
||||
auto privileges = auth_handler.GetPrivileges(user_name);
|
||||
@ -87,7 +90,7 @@ TEST_F(AuthQueryHandlerFixture, GivenUserWhenAddedGrantPermissionThenItIsReturne
|
||||
|
||||
TEST_F(AuthQueryHandlerFixture, GivenUserWhenAddedDenyPermissionThenItIsReturned) {
|
||||
perms.Deny(memgraph::auth::Permission::MATCH);
|
||||
memgraph::auth::User user = memgraph::auth::User{user_name, "", perms, handler};
|
||||
memgraph::auth::User user = memgraph::auth::User{user_name, "", perms};
|
||||
auth->SaveUser(user);
|
||||
|
||||
auto privileges = auth_handler.GetPrivileges(user_name);
|
||||
@ -109,7 +112,7 @@ TEST_F(AuthQueryHandlerFixture, GivenUserWhenAddedDenyPermissionThenItIsReturned
|
||||
TEST_F(AuthQueryHandlerFixture, GivenUserWhenPrivilegeRevokedThenNothingIsReturned) {
|
||||
perms.Deny(memgraph::auth::Permission::MATCH);
|
||||
perms.Revoke(memgraph::auth::Permission::MATCH);
|
||||
memgraph::auth::User user = memgraph::auth::User{user_name, "", perms, handler};
|
||||
memgraph::auth::User user = memgraph::auth::User{user_name, "", perms};
|
||||
auth->SaveUser(user);
|
||||
|
||||
auto privileges = auth_handler.GetPrivileges(user_name);
|
||||
@ -118,7 +121,7 @@ TEST_F(AuthQueryHandlerFixture, GivenUserWhenPrivilegeRevokedThenNothingIsReturn
|
||||
|
||||
TEST_F(AuthQueryHandlerFixture, GivenRoleWhenPrivilegeGrantedThenItIsReturned) {
|
||||
perms.Grant(memgraph::auth::Permission::MATCH);
|
||||
memgraph::auth::Role role = memgraph::auth::Role{"Mates_role", perms, handler};
|
||||
memgraph::auth::Role role = memgraph::auth::Role{"Mates_role", perms};
|
||||
auth->SaveRole(role);
|
||||
|
||||
{ ASSERT_EQ(auth_handler.GetRolenames().size(), 1); }
|
||||
@ -143,7 +146,7 @@ TEST_F(AuthQueryHandlerFixture, GivenRoleWhenPrivilegeGrantedThenItIsReturned) {
|
||||
|
||||
TEST_F(AuthQueryHandlerFixture, GivenRoleWhenPrivilegeDeniedThenItIsReturned) {
|
||||
perms.Deny(memgraph::auth::Permission::MATCH);
|
||||
memgraph::auth::Role role = memgraph::auth::Role{"Mates_role", perms, handler};
|
||||
memgraph::auth::Role role = memgraph::auth::Role{"Mates_role", perms};
|
||||
auth->SaveRole(role);
|
||||
|
||||
auto privileges = auth_handler.GetPrivileges("Mates_role");
|
||||
@ -165,7 +168,7 @@ TEST_F(AuthQueryHandlerFixture, GivenRoleWhenPrivilegeDeniedThenItIsReturned) {
|
||||
TEST_F(AuthQueryHandlerFixture, GivenRoleWhenPrivilegeRevokedThenNothingIsReturned) {
|
||||
perms.Deny(memgraph::auth::Permission::MATCH);
|
||||
perms.Revoke(memgraph::auth::Permission::MATCH);
|
||||
memgraph::auth::Role role = memgraph::auth::Role{"Mates_role", perms, handler};
|
||||
memgraph::auth::Role role = memgraph::auth::Role{"Mates_role", perms};
|
||||
auth->SaveRole(role);
|
||||
|
||||
auto privileges = auth_handler.GetPrivileges("Mates_role");
|
||||
@ -175,7 +178,7 @@ TEST_F(AuthQueryHandlerFixture, GivenRoleWhenPrivilegeRevokedThenNothingIsReturn
|
||||
TEST_F(AuthQueryHandlerFixture, GivenUserWhenGrantedTwoPrivilegesThenBothAreReturned) {
|
||||
perms.Grant(memgraph::auth::Permission::MATCH);
|
||||
perms.Grant(memgraph::auth::Permission::CREATE);
|
||||
memgraph::auth::User user = memgraph::auth::User{user_name, "", perms, handler};
|
||||
memgraph::auth::User user = memgraph::auth::User{user_name, "", perms};
|
||||
auth->SaveUser(user);
|
||||
|
||||
auto privileges = auth_handler.GetPrivileges(user_name);
|
||||
@ -184,9 +187,9 @@ TEST_F(AuthQueryHandlerFixture, GivenUserWhenGrantedTwoPrivilegesThenBothAreRetu
|
||||
|
||||
TEST_F(AuthQueryHandlerFixture, GivenUserAndRoleWhenOneGrantedAndOtherGrantedThenBothArePrinted) {
|
||||
perms.Grant(memgraph::auth::Permission::MATCH);
|
||||
memgraph::auth::Role role = memgraph::auth::Role{"Mates_role", perms, handler};
|
||||
memgraph::auth::Role role = memgraph::auth::Role{"Mates_role", perms};
|
||||
auth->SaveRole(role);
|
||||
memgraph::auth::User user = memgraph::auth::User{user_name, "", perms, handler};
|
||||
memgraph::auth::User user = memgraph::auth::User{user_name, "", perms};
|
||||
user.SetRole(role);
|
||||
auth->SaveUser(user);
|
||||
|
||||
@ -208,9 +211,9 @@ TEST_F(AuthQueryHandlerFixture, GivenUserAndRoleWhenOneGrantedAndOtherGrantedThe
|
||||
|
||||
TEST_F(AuthQueryHandlerFixture, GivenUserAndRoleWhenOneDeniedAndOtherDeniedThenBothArePrinted) {
|
||||
perms.Deny(memgraph::auth::Permission::MATCH);
|
||||
memgraph::auth::Role role = memgraph::auth::Role{"Mates_role", perms, handler};
|
||||
memgraph::auth::Role role = memgraph::auth::Role{"Mates_role", perms};
|
||||
auth->SaveRole(role);
|
||||
memgraph::auth::User user = memgraph::auth::User{user_name, "", perms, handler};
|
||||
memgraph::auth::User user = memgraph::auth::User{user_name, "", perms};
|
||||
user.SetRole(role);
|
||||
auth->SaveUser(user);
|
||||
|
||||
@ -233,12 +236,16 @@ TEST_F(AuthQueryHandlerFixture, GivenUserAndRoleWhenOneDeniedAndOtherDeniedThenB
|
||||
TEST_F(AuthQueryHandlerFixture, GivenUserAndRoleWhenOneGrantedAndOtherDeniedThenBothArePrinted) {
|
||||
memgraph::auth::Permissions role_perms{};
|
||||
role_perms.Deny(memgraph::auth::Permission::MATCH);
|
||||
memgraph::auth::Role role = memgraph::auth::Role{"Mates_role", role_perms, handler};
|
||||
memgraph::auth::Role role = memgraph::auth::Role{"Mates_role", role_perms};
|
||||
auth->SaveRole(role);
|
||||
|
||||
memgraph::auth::Permissions user_perms{};
|
||||
user_perms.Grant(memgraph::auth::Permission::MATCH);
|
||||
memgraph::auth::User user = memgraph::auth::User{user_name, "", user_perms, handler};
|
||||
memgraph::auth::User user = memgraph::auth::User{
|
||||
user_name,
|
||||
"",
|
||||
user_perms,
|
||||
};
|
||||
user.SetRole(role);
|
||||
auth->SaveUser(user);
|
||||
|
||||
@ -261,12 +268,12 @@ TEST_F(AuthQueryHandlerFixture, GivenUserAndRoleWhenOneGrantedAndOtherDeniedThen
|
||||
TEST_F(AuthQueryHandlerFixture, GivenUserAndRoleWhenOneDeniedAndOtherGrantedThenBothArePrinted) {
|
||||
memgraph::auth::Permissions role_perms{};
|
||||
role_perms.Grant(memgraph::auth::Permission::MATCH);
|
||||
memgraph::auth::Role role = memgraph::auth::Role{"Mates_role", role_perms, handler};
|
||||
memgraph::auth::Role role = memgraph::auth::Role{"Mates_role", role_perms};
|
||||
auth->SaveRole(role);
|
||||
|
||||
memgraph::auth::Permissions user_perms{};
|
||||
user_perms.Deny(memgraph::auth::Permission::MATCH);
|
||||
memgraph::auth::User user = memgraph::auth::User{user_name, "", user_perms, handler};
|
||||
memgraph::auth::User user = memgraph::auth::User{user_name, "", user_perms};
|
||||
user.SetRole(role);
|
||||
auth->SaveUser(user);
|
||||
|
||||
@ -286,6 +293,7 @@ TEST_F(AuthQueryHandlerFixture, GivenUserAndRoleWhenOneDeniedAndOtherGrantedThen
|
||||
ASSERT_EQ(result[2].ValueString(), "DENIED TO USER, GRANTED TO ROLE");
|
||||
}
|
||||
|
||||
#ifdef MG_ENTERPRISE
|
||||
TEST_F(AuthQueryHandlerFixture, GivenUserWhenGrantedPrivilegeOnLabelThenIsDisplayed) {
|
||||
auto read_permission = memgraph::auth::FineGrainedAccessPermissions();
|
||||
read_permission.Grant(label_repr, memgraph::auth::FineGrainedPermission::READ);
|
||||
@ -722,3 +730,4 @@ TEST_F(AuthQueryHandlerFixture, GivenUserWhenGrantedReadAndDeniedUpdateThenOneIs
|
||||
ASSERT_TRUE(result[2].IsString());
|
||||
ASSERT_EQ(result[2].ValueString(), "EDGE_TYPE PERMISSION GRANTED TO USER");
|
||||
}
|
||||
#endif
|
||||
|
@ -451,6 +451,7 @@ void BfsTest(Database *db, int lower_bound, int upper_bound, memgraph::query::Ed
|
||||
dba.Abort();
|
||||
}
|
||||
|
||||
#ifdef MG_ENTERPRISE
|
||||
void BfsTestWithFineGrainedFiltering(Database *db, int lower_bound, int upper_bound,
|
||||
memgraph::query::EdgeAtom::Direction direction,
|
||||
std::vector<std::string> edge_types, bool known_sink,
|
||||
@ -718,3 +719,4 @@ void BfsTestWithFineGrainedFiltering(Database *db, int lower_bound, int upper_bo
|
||||
|
||||
db_accessor.Abort();
|
||||
}
|
||||
#endif
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include <gtest/internal/gtest-param-util-generated.h>
|
||||
|
||||
#include "auth/models.hpp"
|
||||
#include "utils/license.hpp"
|
||||
|
||||
using namespace memgraph::query;
|
||||
using namespace memgraph::query::plan;
|
||||
@ -73,11 +74,15 @@ class VertexDb : public Database {
|
||||
memgraph::storage::Storage db_;
|
||||
};
|
||||
|
||||
#ifdef MG_ENTERPRISE
|
||||
class FineGrainedBfsTest
|
||||
: public ::testing::TestWithParam<
|
||||
std::tuple<int, int, EdgeAtom::Direction, std::vector<std::string>, bool, FineGrainedTestType>> {
|
||||
public:
|
||||
static void SetUpTestCase() { db_ = std::make_unique<VertexDb>(); }
|
||||
static void SetUpTestCase() {
|
||||
memgraph::utils::license::global_license_checker.EnableTesting();
|
||||
db_ = std::make_unique<VertexDb>();
|
||||
}
|
||||
static void TearDownTestCase() { db_ = nullptr; }
|
||||
|
||||
protected:
|
||||
@ -99,7 +104,6 @@ TEST_P(FineGrainedBfsTest, All) {
|
||||
}
|
||||
|
||||
std::unique_ptr<VertexDb> FineGrainedBfsTest::db_{nullptr};
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
FineGrained, FineGrainedBfsTest,
|
||||
testing::Combine(testing::Values(3), testing::Values(-1),
|
||||
@ -108,3 +112,4 @@ INSTANTIATE_TEST_CASE_P(
|
||||
testing::Values(FineGrainedTestType::ALL_GRANTED, FineGrainedTestType::ALL_DENIED,
|
||||
FineGrainedTestType::EDGE_TYPE_A_DENIED, FineGrainedTestType::EDGE_TYPE_B_DENIED,
|
||||
FineGrainedTestType::LABEL_0_DENIED, FineGrainedTestType::LABEL_3_DENIED)));
|
||||
#endif
|
||||
|
@ -41,7 +41,7 @@ ExecutionContext MakeContext(const AstStorage &storage, const SymbolTable &symbo
|
||||
context.evaluation_context.labels = NamesToLabels(storage.labels_, dba);
|
||||
return context;
|
||||
}
|
||||
|
||||
#ifdef MG_ENTERPRISE
|
||||
ExecutionContext MakeContextWithFineGrainedChecker(const AstStorage &storage, const SymbolTable &symbol_table,
|
||||
memgraph::query::DbAccessor *dba,
|
||||
memgraph::glue::FineGrainedAuthChecker *auth_checker) {
|
||||
@ -53,6 +53,7 @@ ExecutionContext MakeContextWithFineGrainedChecker(const AstStorage &storage, co
|
||||
|
||||
return context;
|
||||
}
|
||||
#endif
|
||||
|
||||
/** Helper function that collects all the results from the given Produce. */
|
||||
std::vector<std::vector<TypedValue>> CollectProduce(const Produce &produce, ExecutionContext *context) {
|
||||
|
@ -24,6 +24,7 @@
|
||||
#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"
|
||||
@ -77,7 +78,9 @@ TEST(QueryPlan, CreateNodeWithAttributes) {
|
||||
EXPECT_EQ(vertex_count, 1);
|
||||
}
|
||||
|
||||
#ifdef MG_ENTERPRISE
|
||||
TEST(QueryPlan, FineGrainedCreateNodeWithAttributes) {
|
||||
memgraph::utils::license::global_license_checker.EnableTesting();
|
||||
memgraph::query::AstStorage ast;
|
||||
memgraph::query::SymbolTable symbol_table;
|
||||
memgraph::storage::Storage db;
|
||||
@ -117,6 +120,7 @@ TEST(QueryPlan, FineGrainedCreateNodeWithAttributes) {
|
||||
ASSERT_THROW(test_create(user), QueryRuntimeException);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
TEST(QueryPlan, CreateReturn) {
|
||||
// test CREATE (n:Person {age: 42}) RETURN n, n.age
|
||||
@ -158,7 +162,10 @@ TEST(QueryPlan, CreateReturn) {
|
||||
EXPECT_EQ(1, CountIterable(dba.Vertices(memgraph::storage::View::OLD)));
|
||||
}
|
||||
|
||||
#ifdef MG_ENTERPRISE
|
||||
TEST(QueryPlan, FineGrainedCreateReturn) {
|
||||
memgraph::utils::license::global_license_checker.EnableTesting();
|
||||
|
||||
// test CREATE (n:Person {age: 42}) RETURN n, n.age
|
||||
memgraph::storage::Storage db;
|
||||
auto storage_dba = db.Access();
|
||||
@ -215,6 +222,7 @@ TEST(QueryPlan, FineGrainedCreateReturn) {
|
||||
ASSERT_THROW(CollectProduce(*produce, &context), QueryRuntimeException);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
TEST(QueryPlan, CreateExpand) {
|
||||
memgraph::storage::Storage db;
|
||||
@ -293,6 +301,7 @@ TEST(QueryPlan, CreateExpand) {
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef MG_ENTERPRISE
|
||||
class CreateExpandWithAuthFixture : public testing::Test {
|
||||
protected:
|
||||
memgraph::storage::Storage db;
|
||||
@ -301,6 +310,8 @@ class CreateExpandWithAuthFixture : public testing::Test {
|
||||
AstStorage storage;
|
||||
SymbolTable symbol_table;
|
||||
|
||||
void SetUp() override { memgraph::utils::license::global_license_checker.EnableTesting(); }
|
||||
|
||||
void ExecuteCreateExpand(bool cycle, memgraph::auth::User &user) {
|
||||
const auto label_node_1 = dba.NameToLabel("Node1");
|
||||
const auto label_node_2 = dba.NameToLabel("Node2");
|
||||
@ -465,6 +476,8 @@ class MatchCreateNodeWithAuthFixture : public testing::Test {
|
||||
AstStorage storage;
|
||||
SymbolTable symbol_table;
|
||||
|
||||
void SetUp() override { memgraph::utils::license::global_license_checker.EnableTesting(); }
|
||||
|
||||
void InitGraph() {
|
||||
// add three nodes we'll match and expand-create from
|
||||
memgraph::query::VertexAccessor v1{dba.InsertVertex()};
|
||||
@ -536,6 +549,7 @@ TEST_F(MatchCreateNodeWithAuthFixture, MatchCreateWithOneLabelDeniedThrows) {
|
||||
|
||||
ASSERT_THROW(ExecuteMatchCreateTestSuite(user, 3), QueryRuntimeException);
|
||||
}
|
||||
#endif
|
||||
|
||||
TEST(QueryPlan, MatchCreateExpand) {
|
||||
memgraph::storage::Storage db;
|
||||
@ -585,6 +599,7 @@ TEST(QueryPlan, MatchCreateExpand) {
|
||||
test_create_path(true, 0, 6);
|
||||
}
|
||||
|
||||
#ifdef MG_ENTERPRISE
|
||||
class MatchCreateExpandWithAuthFixture : public testing::Test {
|
||||
protected:
|
||||
memgraph::storage::Storage db;
|
||||
@ -593,6 +608,8 @@ class MatchCreateExpandWithAuthFixture : public testing::Test {
|
||||
AstStorage storage;
|
||||
SymbolTable symbol_table;
|
||||
|
||||
void SetUp() override { memgraph::utils::license::global_license_checker.EnableTesting(); }
|
||||
|
||||
void InitGraph() {
|
||||
// add three nodes we'll match and expand-create from
|
||||
memgraph::query::VertexAccessor v1{dba.InsertVertex()};
|
||||
@ -730,6 +747,7 @@ TEST_F(MatchCreateExpandWithAuthFixture, MatchCreateExpandWithCycleExecutesWhenG
|
||||
|
||||
ExecuteMatchCreateExpandTestSuite(true, 3, 3, user);
|
||||
}
|
||||
#endif
|
||||
|
||||
TEST(QueryPlan, Delete) {
|
||||
memgraph::storage::Storage db;
|
||||
@ -802,6 +820,7 @@ TEST(QueryPlan, Delete) {
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef MG_ENTERPRISE
|
||||
class DeleteOperatorWithAuthFixture : public testing::Test {
|
||||
protected:
|
||||
memgraph::storage::Storage db;
|
||||
@ -810,6 +829,8 @@ class DeleteOperatorWithAuthFixture : public testing::Test {
|
||||
AstStorage storage;
|
||||
SymbolTable symbol_table;
|
||||
|
||||
void SetUp() override { memgraph::utils::license::global_license_checker.EnableTesting(); }
|
||||
|
||||
void InitGraph() {
|
||||
std::vector<memgraph::query::VertexAccessor> vertices;
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
@ -949,6 +970,7 @@ TEST_F(DeleteOperatorWithAuthFixture, DeleteNodeAndDeleteEdgePerformWhenGranted)
|
||||
TestDeleteNodesHypothesis(0);
|
||||
TestDeleteEdgesHypothesis(0);
|
||||
}
|
||||
#endif
|
||||
|
||||
TEST(QueryPlan, DeleteTwiceDeleteBlockingEdge) {
|
||||
// test deleting the same vertex and edge multiple times
|
||||
@ -1242,7 +1264,9 @@ TEST(QueryPlan, SetLabels) {
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef MG_ENTERPRISE
|
||||
TEST(QueryPlan, SetLabelsWithFineGrained) {
|
||||
memgraph::utils::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());
|
||||
@ -1315,6 +1339,7 @@ TEST(QueryPlan, SetLabelsWithFineGrained) {
|
||||
QueryRuntimeException);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
TEST(QueryPlan, RemoveProperty) {
|
||||
memgraph::storage::Storage db;
|
||||
@ -1413,7 +1438,9 @@ TEST(QueryPlan, RemoveLabels) {
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef MG_ENTERPRISE
|
||||
TEST(QueryPlan, RemoveLabelsFineGrainedFiltering) {
|
||||
memgraph::utils::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();
|
||||
@ -1492,6 +1519,7 @@ TEST(QueryPlan, RemoveLabelsFineGrainedFiltering) {
|
||||
QueryRuntimeException);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
TEST(QueryPlan, NodeFilterSet) {
|
||||
memgraph::storage::Storage db;
|
||||
@ -1858,6 +1886,7 @@ TEST(QueryPlan, DeleteRemoveProperty) {
|
||||
//////////////////////////////////////////////
|
||||
//// FINE GRAINED AUTHORIZATION /////
|
||||
//////////////////////////////////////////////
|
||||
#ifdef MG_ENTERPRISE
|
||||
class UpdatePropertiesWithAuthFixture : public testing::Test {
|
||||
protected:
|
||||
memgraph::storage::Storage db;
|
||||
@ -1882,6 +1911,8 @@ 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 SetVertexProperty(memgraph::query::VertexAccessor vertex) {
|
||||
static_cast<void>(vertex.SetProperty(entity_prop, entity_prop_value));
|
||||
}
|
||||
@ -2484,3 +2515,4 @@ TEST_F(UpdatePropertiesWithAuthFixture, SetPropertyExpandWithAuthChecker) {
|
||||
test_remove_hypothesis(1);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -33,6 +33,7 @@
|
||||
#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;
|
||||
@ -49,6 +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(); }
|
||||
|
||||
std::vector<Path> PathResults(std::shared_ptr<Produce> &op) {
|
||||
std::vector<Path> res;
|
||||
@ -58,12 +60,15 @@ class MatchReturnFixture : public testing::Test {
|
||||
}
|
||||
|
||||
int PullCountAuthorized(ScanAllTuple scan_all, memgraph::auth::User user) {
|
||||
#ifdef MG_ENTERPRISE
|
||||
auto output =
|
||||
NEXPR("n", IDENT("n")->MapTo(scan_all.sym_))->MapTo(symbol_table.CreateSymbol("named_expression_1", true));
|
||||
auto produce = MakeProduce(scan_all.op_, output);
|
||||
memgraph::glue::FineGrainedAuthChecker auth_checker{user, &dba};
|
||||
auto context = MakeContextWithFineGrainedChecker(storage, symbol_table, &dba, &auth_checker);
|
||||
return PullAll(*produce, &context);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
@ -107,6 +112,7 @@ TEST_F(MatchReturnFixture, MatchReturnPath) {
|
||||
EXPECT_TRUE(std::is_permutation(expected_paths.begin(), expected_paths.end(), results.begin()));
|
||||
}
|
||||
|
||||
#ifdef MG_ENTERPRISE
|
||||
TEST_F(MatchReturnFixture, ScanAllWithAuthChecker) {
|
||||
std::string labelName = "l1";
|
||||
const auto label = dba.NameToLabel(labelName);
|
||||
@ -192,6 +198,7 @@ TEST_F(MatchReturnFixture, ScanAllWithAuthChecker) {
|
||||
test_hypothesis(user, memgraph::storage::View::NEW, 0);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
TEST(QueryPlan, MatchReturnCartesian) {
|
||||
memgraph::storage::Storage db;
|
||||
@ -474,6 +481,8 @@ 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();
|
||||
|
||||
dba.AdvanceCommand();
|
||||
}
|
||||
};
|
||||
@ -506,6 +515,7 @@ TEST_F(ExpandFixture, Expand) {
|
||||
EXPECT_EQ(8, test_expand(EdgeAtom::Direction::BOTH, memgraph::storage::View::OLD));
|
||||
}
|
||||
|
||||
#ifdef MG_ENTERPRISE
|
||||
TEST_F(ExpandFixture, ExpandWithEdgeFiltering) {
|
||||
auto test_expand = [&](memgraph::auth::User user, EdgeAtom::Direction direction, memgraph::storage::View view) {
|
||||
auto n = MakeScanAll(storage, symbol_table, "n");
|
||||
@ -560,6 +570,7 @@ TEST_F(ExpandFixture, ExpandWithEdgeFiltering) {
|
||||
EXPECT_EQ(4, test_expand(user, EdgeAtom::Direction::IN, memgraph::storage::View::OLD));
|
||||
EXPECT_EQ(8, test_expand(user, EdgeAtom::Direction::BOTH, memgraph::storage::View::OLD));
|
||||
}
|
||||
#endif
|
||||
|
||||
TEST_F(ExpandFixture, ExpandPath) {
|
||||
auto n = MakeScanAll(storage, symbol_table, "n");
|
||||
@ -613,6 +624,8 @@ class QueryPlanExpandVariable : public testing::Test {
|
||||
std::nullopt_t nullopt = std::nullopt;
|
||||
|
||||
void SetUp() {
|
||||
memgraph::utils::license::global_license_checker.EnableTesting();
|
||||
|
||||
// create the graph
|
||||
int chain_length = 3;
|
||||
std::vector<memgraph::query::VertexAccessor> layer;
|
||||
@ -703,8 +716,10 @@ class QueryPlanExpandVariable : public testing::Test {
|
||||
auto cursor = input_op->MakeCursor(memgraph::utils::NewDeleteResource());
|
||||
ExecutionContext context;
|
||||
if (user) {
|
||||
#ifdef MG_ENTERPRISE
|
||||
memgraph::glue::FineGrainedAuthChecker auth_checker{*user, &dba};
|
||||
context = MakeContextWithFineGrainedChecker(storage, symbol_table, &dba, &auth_checker);
|
||||
#endif
|
||||
} else {
|
||||
context = MakeContext(storage, symbol_table, &dba);
|
||||
}
|
||||
@ -721,8 +736,10 @@ class QueryPlanExpandVariable : public testing::Test {
|
||||
auto cursor = input_op->MakeCursor(memgraph::utils::NewDeleteResource());
|
||||
ExecutionContext context;
|
||||
if (user) {
|
||||
#ifdef MG_ENTERPRISE
|
||||
memgraph::glue::FineGrainedAuthChecker auth_checker{*user, &dba};
|
||||
context = MakeContextWithFineGrainedChecker(storage, symbol_table, &dba, &auth_checker);
|
||||
#endif
|
||||
} else {
|
||||
context = MakeContext(storage, symbol_table, &dba);
|
||||
}
|
||||
@ -788,6 +805,7 @@ TEST_F(QueryPlanExpandVariable, OneVariableExpansion) {
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef MG_ENTERPRISE
|
||||
TEST_F(QueryPlanExpandVariable, FineGrainedOneVariableExpansion) {
|
||||
auto test_expand = [&](int layer, EdgeAtom::Direction direction, std::optional<size_t> lower,
|
||||
std::optional<size_t> upper, bool reverse, memgraph::auth::User &user) {
|
||||
@ -989,6 +1007,7 @@ TEST_F(QueryPlanExpandVariable, FineGrainedOneVariableExpansion) {
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
TEST_F(QueryPlanExpandVariable, EdgeUniquenessSingleAndVariableExpansion) {
|
||||
auto test_expand = [&](int layer, EdgeAtom::Direction direction, std::optional<size_t> lower,
|
||||
@ -1049,6 +1068,7 @@ TEST_F(QueryPlanExpandVariable, EdgeUniquenessTwoVariableExpansions) {
|
||||
EXPECT_EQ(test_expand(0, EdgeAtom::Direction::OUT, 2, 2, true), (map_int{{2, 5 * 8}}));
|
||||
}
|
||||
|
||||
#ifdef MG_ENTERPRISE
|
||||
TEST_F(QueryPlanExpandVariable, FineGrainedEdgeUniquenessTwoVariableExpansions) {
|
||||
auto test_expand = [&](int layer, EdgeAtom::Direction direction, std::optional<size_t> lower,
|
||||
std::optional<size_t> upper, bool add_uniqueness_check, memgraph::auth::User &user) {
|
||||
@ -1139,6 +1159,7 @@ TEST_F(QueryPlanExpandVariable, FineGrainedEdgeUniquenessTwoVariableExpansions)
|
||||
EXPECT_EQ(test_expand(1, EdgeAtom::Direction::OUT, 0, 2, true, user), (map_int{{0, 4}}));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
TEST_F(QueryPlanExpandVariable, NamedPath) {
|
||||
auto e = Edge("r", EdgeAtom::Direction::OUT);
|
||||
@ -1172,6 +1193,7 @@ TEST_F(QueryPlanExpandVariable, NamedPath) {
|
||||
EXPECT_TRUE(std::is_permutation(results.begin(), results.end(), expected_paths.begin()));
|
||||
}
|
||||
|
||||
#ifdef MG_ENTERPRISE
|
||||
TEST_F(QueryPlanExpandVariable, FineGrainedFilterNamedPath) {
|
||||
auto e = Edge("r", EdgeAtom::Direction::OUT);
|
||||
auto expand = AddMatch<ExpandVariable>(nullptr, "n", 0, EdgeAtom::Direction::OUT, {}, 0, 2, e, "m",
|
||||
@ -1310,6 +1332,7 @@ TEST_F(QueryPlanExpandVariable, FineGrainedFilterNamedPath) {
|
||||
EXPECT_TRUE(std::is_permutation(results.begin(), results.end(), expected_paths.begin()));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
TEST_F(QueryPlanExpandVariable, ExpandToSameSymbol) {
|
||||
auto test_expand = [&](int layer, EdgeAtom::Direction direction, std::optional<size_t> lower,
|
||||
@ -1501,6 +1524,7 @@ TEST_F(QueryPlanExpandVariable, ExpandToSameSymbol) {
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef MG_ENTERPRISE
|
||||
TEST_F(QueryPlanExpandVariable, FineGrainedExpandToSameSymbol) {
|
||||
auto test_expand = [&](int layer, EdgeAtom::Direction direction, std::optional<size_t> lower,
|
||||
std::optional<size_t> upper, bool reverse, memgraph::auth::User &user) {
|
||||
@ -1699,6 +1723,7 @@ TEST_F(QueryPlanExpandVariable, FineGrainedExpandToSameSymbol) {
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
namespace std {
|
||||
template <>
|
||||
@ -1743,6 +1768,8 @@ class QueryPlanExpandWeightedShortestPath : public testing::Test {
|
||||
Symbol total_weight = symbol_table.CreateSymbol("total_weight", true);
|
||||
|
||||
void SetUp() {
|
||||
memgraph::utils::license::global_license_checker.EnableTesting();
|
||||
|
||||
for (int i = 0; i < 5; i++) {
|
||||
v.push_back(dba.InsertVertex());
|
||||
ASSERT_TRUE(v.back().SetProperty(prop.second, memgraph::storage::PropertyValue(i)).HasValue());
|
||||
@ -1796,8 +1823,10 @@ class QueryPlanExpandWeightedShortestPath : public testing::Test {
|
||||
std::vector<ResultType> results;
|
||||
memgraph::query::ExecutionContext context;
|
||||
if (user) {
|
||||
#ifdef MG_ENTERPRISE
|
||||
memgraph::glue::FineGrainedAuthChecker auth_checker{*user, &dba};
|
||||
context = MakeContextWithFineGrainedChecker(storage, symbol_table, &dba, &auth_checker);
|
||||
#endif
|
||||
} else {
|
||||
context = MakeContext(storage, symbol_table, &dba);
|
||||
}
|
||||
@ -2030,6 +2059,7 @@ TEST_F(QueryPlanExpandWeightedShortestPath, NegativeUpperBound) {
|
||||
EXPECT_THROW(ExpandWShortest(EdgeAtom::Direction::BOTH, -1, LITERAL(true)), QueryRuntimeException);
|
||||
}
|
||||
|
||||
#if MG_ENTERPRISE
|
||||
TEST_F(QueryPlanExpandWeightedShortestPath, FineGrainedFiltering) {
|
||||
// All edge_types and labels allowed
|
||||
{
|
||||
@ -2129,6 +2159,7 @@ TEST_F(QueryPlanExpandWeightedShortestPath, FineGrainedFiltering) {
|
||||
ASSERT_EQ(filtered_results.size(), 4);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/** A test fixture for all shortest paths expansion */
|
||||
class QueryPlanExpandAllShortestPaths : public testing::Test {
|
||||
@ -2166,6 +2197,8 @@ class QueryPlanExpandAllShortestPaths : public testing::Test {
|
||||
Symbol total_weight = symbol_table.CreateSymbol("total_weight", true);
|
||||
|
||||
void SetUp() {
|
||||
memgraph::utils::license::global_license_checker.EnableTesting();
|
||||
|
||||
for (int i = 0; i < 5; i++) {
|
||||
v.push_back(dba.InsertVertex());
|
||||
ASSERT_TRUE(v.back().SetProperty(prop.second, memgraph::storage::PropertyValue(i)).HasValue());
|
||||
@ -2219,8 +2252,10 @@ class QueryPlanExpandAllShortestPaths : public testing::Test {
|
||||
std::vector<ResultType> results;
|
||||
ExecutionContext context;
|
||||
if (user) {
|
||||
#ifdef MG_ENTERPRISE
|
||||
memgraph::glue::FineGrainedAuthChecker auth_checker{*user, &dba};
|
||||
context = MakeContextWithFineGrainedChecker(storage, symbol_table, &dba, &auth_checker);
|
||||
#endif
|
||||
} else {
|
||||
context = MakeContext(storage, symbol_table, &dba);
|
||||
}
|
||||
@ -2492,6 +2527,7 @@ TEST_F(QueryPlanExpandAllShortestPaths, MultiEdge) {
|
||||
EXPECT_EQ(results[5].total_weight, 9);
|
||||
}
|
||||
|
||||
#ifdef MG_ENTERPRISE
|
||||
TEST_F(QueryPlanExpandAllShortestPaths, BasicWithFineGrainedFiltering) {
|
||||
// All edge_types and labels allowed
|
||||
{
|
||||
@ -2571,6 +2607,7 @@ TEST_F(QueryPlanExpandAllShortestPaths, BasicWithFineGrainedFiltering) {
|
||||
ASSERT_EQ(filtered_results.size(), 4);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
TEST(QueryPlan, ExpandOptional) {
|
||||
memgraph::storage::Storage db;
|
||||
|
@ -17,6 +17,7 @@
|
||||
#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"
|
||||
|
||||
@ -97,8 +98,9 @@ TEST_F(TestPrivilegeExtractor, CreateIndex) {
|
||||
auto *query = CREATE_INDEX_ON(storage.GetLabelIx(LABEL_0), storage.GetPropertyIx(PROP_0));
|
||||
EXPECT_THAT(GetRequiredPrivileges(query), UnorderedElementsAre(AuthQuery::Privilege::INDEX));
|
||||
}
|
||||
|
||||
#ifdef MG_ENTERPRISE
|
||||
TEST_F(TestPrivilegeExtractor, AuthQuery) {
|
||||
memgraph::utils::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>>>{};
|
||||
@ -106,6 +108,7 @@ TEST_F(TestPrivilegeExtractor, AuthQuery) {
|
||||
label_privileges, edge_type_privileges);
|
||||
EXPECT_THAT(GetRequiredPrivileges(query), UnorderedElementsAre(AuthQuery::Privilege::AUTH));
|
||||
}
|
||||
#endif
|
||||
|
||||
TEST_F(TestPrivilegeExtractor, ShowIndexInfo) {
|
||||
auto *query = storage.Create<InfoQuery>();
|
||||
|
@ -39,9 +39,12 @@ class MockAuthChecker : public memgraph::query::AuthChecker {
|
||||
public:
|
||||
MOCK_CONST_METHOD2(IsUserAuthorized, bool(const std::optional<std::string> &username,
|
||||
const std::vector<memgraph::query::AuthQuery::Privilege> &privileges));
|
||||
|
||||
#ifdef MG_ENTERPRISE
|
||||
MOCK_CONST_METHOD2(GetFineGrainedAuthChecker,
|
||||
std::unique_ptr<memgraph::query::FineGrainedAuthChecker>(
|
||||
const std::string &username, const memgraph::query::DbAccessor *db_accessor));
|
||||
#endif
|
||||
};
|
||||
} // namespace
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user