[E129-MG < T1003-MG] Expand fine grained access checker with more granular permissions (#496)
* Added enum for more granular access control; Expanded functionality of fine grained access checker; Propagated changes to Edit, Deny and Revoke permissions methods in interpreter * Introduced Merge method for merging two colle with permissions * e2e tests implementation started * FineGrainedAccessChecker Grant and Deny methods reworked * removed faulty test addition * Naming fixes; FineGrainedAccessChecker unit tests introduced * unnecessary includes removed; minor code improvements * Access checker reworked; denies and grant merged into single permission object; Created global_permission that applies to all non-created permissions. Grant, Deny and Revoke reworked; Merge method reworked * Fixed wrong check; * PR review changes; Naming and const fixed, replaced double tertiary with lambda * unwrapping the iterator fix * minor spelling fixes
This commit is contained in:
parent
e15576f56c
commit
b489ac7cff
@ -8,10 +8,8 @@
|
||||
|
||||
#include "auth/models.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <cstdint>
|
||||
#include <regex>
|
||||
#include <unordered_set>
|
||||
|
||||
#include <gflags/gflags.h>
|
||||
|
||||
@ -19,6 +17,7 @@
|
||||
#include "auth/exceptions.hpp"
|
||||
#include "utils/cast.hpp"
|
||||
#include "utils/license.hpp"
|
||||
#include "utils/logging.hpp"
|
||||
#include "utils/settings.hpp"
|
||||
#include "utils/string.hpp"
|
||||
|
||||
@ -101,6 +100,24 @@ std::string PermissionLevelToString(PermissionLevel level) {
|
||||
}
|
||||
}
|
||||
|
||||
FineGrainedAccessPermissions Merge(const FineGrainedAccessPermissions &first,
|
||||
const FineGrainedAccessPermissions &second) {
|
||||
std::unordered_map<std::string, uint64_t> permissions{first.GetPermissions()};
|
||||
std::optional<uint64_t> global_permission;
|
||||
|
||||
if (second.GetGlobalPermission().has_value()) {
|
||||
global_permission = second.GetGlobalPermission().value();
|
||||
} else if (first.GetGlobalPermission().has_value()) {
|
||||
global_permission = first.GetGlobalPermission().value();
|
||||
}
|
||||
|
||||
for (const auto &[label_name, permission] : second.GetPermissions()) {
|
||||
permissions[label_name] = permission;
|
||||
}
|
||||
|
||||
return FineGrainedAccessPermissions(permissions, global_permission);
|
||||
}
|
||||
|
||||
Permissions::Permissions(uint64_t grants, uint64_t denies) {
|
||||
// The deny bitmask has higher priority than the grant bitmask.
|
||||
denies_ = denies;
|
||||
@ -186,96 +203,58 @@ bool operator==(const Permissions &first, const Permissions &second) {
|
||||
|
||||
bool operator!=(const Permissions &first, const Permissions &second) { return !(first == second); }
|
||||
|
||||
const std::string ASTERISK = "*";
|
||||
FineGrainedAccessPermissions::FineGrainedAccessPermissions(const std::unordered_map<std::string, uint64_t> &permissions,
|
||||
const std::optional<uint64_t> &global_permission)
|
||||
: permissions_(permissions), global_permission_(global_permission) {}
|
||||
|
||||
FineGrainedAccessPermissions::FineGrainedAccessPermissions(const std::unordered_set<std::string> &grants,
|
||||
const std::unordered_set<std::string> &denies)
|
||||
: grants_(grants), denies_(denies) {}
|
||||
PermissionLevel FineGrainedAccessPermissions::Has(const std::string &permission,
|
||||
const LabelPermission label_permission) const {
|
||||
const auto concrete_permission = std::invoke([&]() -> uint64_t {
|
||||
if (permissions_.contains(permission)) {
|
||||
return permissions_.at(permission);
|
||||
}
|
||||
|
||||
PermissionLevel FineGrainedAccessPermissions::Has(const std::string &permission) const {
|
||||
if ((denies_.size() == 1 && denies_.find(ASTERISK) != denies_.end()) || denies_.find(permission) != denies_.end()) {
|
||||
return PermissionLevel::DENY;
|
||||
}
|
||||
if (global_permission_.has_value()) {
|
||||
return global_permission_.value();
|
||||
}
|
||||
|
||||
if ((grants_.size() == 1 && grants_.find(ASTERISK) != grants_.end()) || grants_.find(permission) != denies_.end()) {
|
||||
return PermissionLevel::GRANT;
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
|
||||
return PermissionLevel::NEUTRAL;
|
||||
const auto temp_permission = concrete_permission & label_permission;
|
||||
|
||||
return temp_permission > 0 ? PermissionLevel::GRANT : PermissionLevel::DENY;
|
||||
}
|
||||
|
||||
void FineGrainedAccessPermissions::Grant(const std::string &permission) {
|
||||
void FineGrainedAccessPermissions::Grant(const std::string &permission, const LabelPermission label_permission) {
|
||||
if (permission == ASTERISK) {
|
||||
grants_.clear();
|
||||
denies_.clear();
|
||||
grants_.insert(permission);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
auto deniedPermissionIter = denies_.find(permission);
|
||||
|
||||
if (deniedPermissionIter != denies_.end()) {
|
||||
denies_.erase(deniedPermissionIter);
|
||||
}
|
||||
|
||||
if (grants_.size() == 1 && grants_.find(ASTERISK) != grants_.end()) {
|
||||
grants_.erase(ASTERISK);
|
||||
}
|
||||
|
||||
if (grants_.find(permission) == grants_.end()) {
|
||||
grants_.insert(permission);
|
||||
global_permission_ = CalculateGrant(label_permission);
|
||||
} else {
|
||||
permissions_[permission] |= CalculateGrant(label_permission);
|
||||
}
|
||||
}
|
||||
|
||||
void FineGrainedAccessPermissions::Revoke(const std::string &permission) {
|
||||
if (permission == ASTERISK) {
|
||||
grants_.clear();
|
||||
denies_.clear();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
auto deniedPermissionIter = denies_.find(permission);
|
||||
auto grantedPermissionIter = grants_.find(permission);
|
||||
|
||||
if (deniedPermissionIter != denies_.end()) {
|
||||
denies_.erase(deniedPermissionIter);
|
||||
}
|
||||
|
||||
if (grantedPermissionIter != grants_.end()) {
|
||||
grants_.erase(grantedPermissionIter);
|
||||
permissions_.clear();
|
||||
global_permission_ = std::nullopt;
|
||||
} else {
|
||||
permissions_.erase(permission);
|
||||
}
|
||||
}
|
||||
|
||||
void FineGrainedAccessPermissions::Deny(const std::string &permission) {
|
||||
void FineGrainedAccessPermissions::Deny(const std::string &permission, const LabelPermission label_permission) {
|
||||
if (permission == ASTERISK) {
|
||||
grants_.clear();
|
||||
denies_.clear();
|
||||
denies_.insert(permission);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
auto grantedPermissionIter = grants_.find(permission);
|
||||
|
||||
if (grantedPermissionIter != grants_.end()) {
|
||||
grants_.erase(grantedPermissionIter);
|
||||
}
|
||||
|
||||
if (denies_.size() == 1 && denies_.find(ASTERISK) != denies_.end()) {
|
||||
denies_.erase(ASTERISK);
|
||||
}
|
||||
|
||||
if (denies_.find(permission) == denies_.end()) {
|
||||
denies_.insert(permission);
|
||||
global_permission_ = CalculateDeny(label_permission);
|
||||
} else {
|
||||
permissions_[permission] = CalculateDeny(label_permission);
|
||||
}
|
||||
}
|
||||
|
||||
nlohmann::json FineGrainedAccessPermissions::Serialize() const {
|
||||
nlohmann::json data = nlohmann::json::object();
|
||||
data["grants"] = grants_;
|
||||
data["denies"] = denies_;
|
||||
data["permissions"] = permissions_;
|
||||
data["global_permission"] = global_permission_.has_value() ? global_permission_.value() : -1;
|
||||
return data;
|
||||
}
|
||||
|
||||
@ -284,14 +263,51 @@ FineGrainedAccessPermissions FineGrainedAccessPermissions::Deserialize(const nlo
|
||||
throw AuthException("Couldn't load permissions data!");
|
||||
}
|
||||
|
||||
return FineGrainedAccessPermissions(data["grants"], data["denies"]);
|
||||
std::optional<uint64_t> global_permission;
|
||||
|
||||
if (data["global_permission"].empty() || data["global_permission"] == -1) {
|
||||
global_permission = std::nullopt;
|
||||
} else {
|
||||
global_permission = data["global_permission"];
|
||||
}
|
||||
|
||||
return FineGrainedAccessPermissions(data["permissions"], global_permission);
|
||||
}
|
||||
|
||||
const std::unordered_set<std::string> &FineGrainedAccessPermissions::grants() const { return grants_; }
|
||||
const std::unordered_set<std::string> &FineGrainedAccessPermissions::denies() const { return denies_; }
|
||||
const std::unordered_map<std::string, uint64_t> &FineGrainedAccessPermissions::GetPermissions() const {
|
||||
return permissions_;
|
||||
}
|
||||
const std::optional<uint64_t> &FineGrainedAccessPermissions::GetGlobalPermission() const { return global_permission_; };
|
||||
|
||||
uint64_t FineGrainedAccessPermissions::CalculateGrant(LabelPermission label_permission) {
|
||||
uint64_t shift{1};
|
||||
uint64_t result{0};
|
||||
auto uint_label_permission = static_cast<uint64_t>(label_permission);
|
||||
|
||||
while (uint_label_permission > 0) {
|
||||
result |= uint_label_permission;
|
||||
uint_label_permission >>= shift;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
uint64_t FineGrainedAccessPermissions::CalculateDeny(LabelPermission label_permission) {
|
||||
uint64_t shift{1};
|
||||
uint64_t result{0};
|
||||
auto uint_label_permission = static_cast<uint64_t>(label_permission);
|
||||
|
||||
while (uint_label_permission <= LabelPermissionMax) {
|
||||
result |= uint_label_permission;
|
||||
uint_label_permission <<= shift;
|
||||
}
|
||||
|
||||
return LabelPermissionAll - result;
|
||||
}
|
||||
|
||||
bool operator==(const FineGrainedAccessPermissions &first, const FineGrainedAccessPermissions &second) {
|
||||
return first.grants() == second.grants() && first.denies() == second.denies();
|
||||
return first.GetPermissions() == second.GetPermissions() &&
|
||||
first.GetGlobalPermission() == second.GetGlobalPermission();
|
||||
}
|
||||
|
||||
bool operator!=(const FineGrainedAccessPermissions &first, const FineGrainedAccessPermissions &second) {
|
||||
@ -321,7 +337,7 @@ FineGrainedAccessHandler FineGrainedAccessHandler::Deserialize(const nlohmann::j
|
||||
if (!data.is_object()) {
|
||||
throw AuthException("Couldn't load role data!");
|
||||
}
|
||||
if (!data["label_permissions"].is_object() && !data["edge_type_permissions"].is_object()) {
|
||||
if (!data["label_permissions"].is_object() || !data["edge_type_permissions"].is_object()) {
|
||||
throw AuthException("Couldn't load label_permissions or edge_type_permissions data!");
|
||||
}
|
||||
auto label_permissions = FineGrainedAccessPermissions::Deserialize(data["label_permissions"]);
|
||||
@ -439,46 +455,16 @@ Permissions User::GetPermissions() const {
|
||||
|
||||
FineGrainedAccessPermissions User::GetFineGrainedAccessLabelPermissions() const {
|
||||
if (role_) {
|
||||
std::unordered_set<std::string> resultGrants;
|
||||
|
||||
std::set_union(fine_grained_access_handler_.label_permissions().grants().begin(),
|
||||
fine_grained_access_handler_.label_permissions().grants().end(),
|
||||
role_->fine_grained_access_handler().label_permissions().grants().begin(),
|
||||
role_->fine_grained_access_handler().label_permissions().grants().end(),
|
||||
std::inserter(resultGrants, resultGrants.begin()));
|
||||
|
||||
std::unordered_set<std::string> resultDenies;
|
||||
|
||||
std::set_union(fine_grained_access_handler_.label_permissions().denies().begin(),
|
||||
fine_grained_access_handler_.label_permissions().denies().end(),
|
||||
role_->fine_grained_access_handler().label_permissions().denies().begin(),
|
||||
role_->fine_grained_access_handler().label_permissions().denies().end(),
|
||||
std::inserter(resultDenies, resultDenies.begin()));
|
||||
|
||||
return FineGrainedAccessPermissions(resultGrants, resultDenies);
|
||||
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 (role_) {
|
||||
std::unordered_set<std::string> resultGrants;
|
||||
|
||||
std::set_union(fine_grained_access_handler_.edge_type_permissions().grants().begin(),
|
||||
fine_grained_access_handler_.edge_type_permissions().grants().end(),
|
||||
role_->fine_grained_access_handler().edge_type_permissions().grants().begin(),
|
||||
role_->fine_grained_access_handler().edge_type_permissions().grants().end(),
|
||||
std::inserter(resultGrants, resultGrants.begin()));
|
||||
|
||||
std::unordered_set<std::string> resultDenies;
|
||||
|
||||
std::set_union(fine_grained_access_handler_.edge_type_permissions().denies().begin(),
|
||||
fine_grained_access_handler_.edge_type_permissions().denies().end(),
|
||||
role_->fine_grained_access_handler().edge_type_permissions().denies().begin(),
|
||||
role_->fine_grained_access_handler().edge_type_permissions().denies().end(),
|
||||
std::inserter(resultDenies, resultDenies.begin()));
|
||||
|
||||
return FineGrainedAccessPermissions(resultGrants, resultDenies);
|
||||
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();
|
||||
}
|
||||
|
@ -10,12 +10,12 @@
|
||||
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <unordered_set>
|
||||
#include <unordered_map>
|
||||
|
||||
#include <json/json.hpp>
|
||||
#include <unordered_set>
|
||||
|
||||
namespace memgraph::auth {
|
||||
const std::string ASTERISK = "*";
|
||||
// These permissions must have values that are applicable for usage in a
|
||||
// bitmask.
|
||||
// clang-format off
|
||||
@ -44,15 +44,34 @@ enum class Permission : uint64_t {
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
// clang-format off
|
||||
enum class LabelPermission : uint64_t {
|
||||
READ = 1,
|
||||
EDIT = 1U << 1U,
|
||||
CREATE_DELETE = 1U << 2U
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
constexpr inline uint64_t operator|(LabelPermission lhs, LabelPermission rhs) {
|
||||
return static_cast<uint64_t>(lhs) | static_cast<uint64_t>(rhs);
|
||||
}
|
||||
|
||||
constexpr inline uint64_t operator|(uint64_t lhs, LabelPermission rhs) { return lhs | static_cast<uint64_t>(rhs); }
|
||||
|
||||
constexpr inline uint64_t operator&(uint64_t lhs, LabelPermission rhs) {
|
||||
return (lhs & static_cast<uint64_t>(rhs)) != 0;
|
||||
}
|
||||
|
||||
constexpr uint64_t LabelPermissionAll = memgraph::auth::LabelPermission::CREATE_DELETE |
|
||||
memgraph::auth::LabelPermission::EDIT | memgraph::auth::LabelPermission::READ;
|
||||
constexpr uint64_t LabelPermissionMax = static_cast<uint64_t>(memgraph::auth::LabelPermission::CREATE_DELETE);
|
||||
constexpr uint64_t LabelPermissionMin = static_cast<uint64_t>(memgraph::auth::LabelPermission::READ);
|
||||
|
||||
// Function that converts a permission to its string representation.
|
||||
std::string PermissionToString(Permission permission);
|
||||
|
||||
// Class that indicates what permission level the user/role has.
|
||||
enum class PermissionLevel {
|
||||
GRANT,
|
||||
NEUTRAL,
|
||||
DENY,
|
||||
};
|
||||
enum class PermissionLevel : uint8_t { GRANT, NEUTRAL, DENY };
|
||||
|
||||
// Function that converts a permission level to its string representation.
|
||||
std::string PermissionLevelToString(PermissionLevel level);
|
||||
@ -98,34 +117,36 @@ bool operator!=(const Permissions &first, const Permissions &second);
|
||||
|
||||
class FineGrainedAccessPermissions final {
|
||||
public:
|
||||
explicit FineGrainedAccessPermissions(const std::unordered_set<std::string> &grants = {},
|
||||
const std::unordered_set<std::string> &denies = {});
|
||||
|
||||
explicit FineGrainedAccessPermissions(const std::unordered_map<std::string, uint64_t> &permissions = {},
|
||||
const std::optional<uint64_t> &global_permission = std::nullopt);
|
||||
FineGrainedAccessPermissions(const FineGrainedAccessPermissions &) = default;
|
||||
FineGrainedAccessPermissions &operator=(const FineGrainedAccessPermissions &) = default;
|
||||
FineGrainedAccessPermissions(FineGrainedAccessPermissions &&) = default;
|
||||
FineGrainedAccessPermissions &operator=(FineGrainedAccessPermissions &&) = default;
|
||||
~FineGrainedAccessPermissions() = default;
|
||||
|
||||
PermissionLevel Has(const std::string &permission) const;
|
||||
PermissionLevel Has(const std::string &permission, LabelPermission label_permission) const;
|
||||
|
||||
void Grant(const std::string &permission);
|
||||
void Grant(const std::string &permission, LabelPermission label_permission);
|
||||
|
||||
void Revoke(const std::string &permission);
|
||||
|
||||
void Deny(const std::string &permission);
|
||||
void Deny(const std::string &permission, LabelPermission label_permission);
|
||||
|
||||
nlohmann::json Serialize() const;
|
||||
|
||||
/// @throw AuthException if unable to deserialize.
|
||||
static FineGrainedAccessPermissions Deserialize(const nlohmann::json &data);
|
||||
|
||||
const std::unordered_set<std::string> &grants() const;
|
||||
const std::unordered_set<std::string> &denies() const;
|
||||
const std::unordered_map<std::string, uint64_t> &GetPermissions() const;
|
||||
const std::optional<uint64_t> &GetGlobalPermission() const;
|
||||
|
||||
private:
|
||||
std::unordered_set<std::string> grants_{};
|
||||
std::unordered_set<std::string> denies_{};
|
||||
std::unordered_map<std::string, uint64_t> permissions_{};
|
||||
std::optional<uint64_t> global_permission_;
|
||||
|
||||
static uint64_t CalculateGrant(LabelPermission label_permission);
|
||||
static uint64_t CalculateDeny(LabelPermission label_permission);
|
||||
};
|
||||
|
||||
bool operator==(const FineGrainedAccessPermissions &first, const FineGrainedAccessPermissions &second);
|
||||
@ -252,4 +273,7 @@ class User final {
|
||||
};
|
||||
|
||||
bool operator==(const User &first, const User &second);
|
||||
|
||||
FineGrainedAccessPermissions Merge(const FineGrainedAccessPermissions &first,
|
||||
const FineGrainedAccessPermissions &second);
|
||||
} // namespace memgraph::auth
|
||||
|
@ -21,14 +21,15 @@ namespace {
|
||||
bool IsUserAuthorizedLabels(const memgraph::auth::User &user, const memgraph::query::DbAccessor &dba,
|
||||
const std::vector<memgraph::storage::LabelId> &labels) {
|
||||
return std::all_of(labels.begin(), labels.end(), [&dba, &user](const auto label) {
|
||||
return user.GetFineGrainedAccessLabelPermissions().Has(dba.LabelToName(label)) ==
|
||||
memgraph::auth::PermissionLevel::GRANT;
|
||||
return user.GetFineGrainedAccessLabelPermissions().Has(
|
||||
dba.LabelToName(label), memgraph::auth::LabelPermission::READ) == memgraph::auth::PermissionLevel::GRANT;
|
||||
});
|
||||
}
|
||||
|
||||
bool IsUserAuthorizedEdgeType(const memgraph::auth::User &user, const memgraph::query::DbAccessor &dba,
|
||||
const memgraph::storage::EdgeTypeId &edgeType) {
|
||||
return user.GetFineGrainedAccessEdgeTypePermissions().Has(dba.EdgeTypeToName(edgeType)) ==
|
||||
return user.GetFineGrainedAccessEdgeTypePermissions().Has(dba.EdgeTypeToName(edgeType),
|
||||
memgraph::auth::LabelPermission::READ) ==
|
||||
memgraph::auth::PermissionLevel::GRANT;
|
||||
}
|
||||
} // namespace
|
||||
|
@ -756,43 +756,57 @@ class AuthQueryHandler final : public memgraph::query::AuthQueryHandler {
|
||||
|
||||
void GrantPrivilege(const std::string &user_or_role,
|
||||
const std::vector<memgraph::query::AuthQuery::Privilege> &privileges,
|
||||
const std::vector<std::string> &labels, const std::vector<std::string> &edgeTypes) override {
|
||||
EditPermissions(user_or_role, privileges, labels, edgeTypes, [](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);
|
||||
});
|
||||
const std::vector<std::string> &labels, const std::vector<std::string> &edge_types) override {
|
||||
EditPermissions(
|
||||
user_or_role, privileges, labels, edge_types,
|
||||
[](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);
|
||||
},
|
||||
[](auto &label_permissions, const auto &label) {
|
||||
label_permissions.Grant(label, memgraph::auth::LabelPermission::CREATE_DELETE);
|
||||
});
|
||||
}
|
||||
|
||||
void DenyPrivilege(const std::string &user_or_role,
|
||||
const std::vector<memgraph::query::AuthQuery::Privilege> &privileges,
|
||||
const std::vector<std::string> &labels, const std::vector<std::string> &edgeTypes) override {
|
||||
EditPermissions(user_or_role, privileges, labels, edgeTypes, [](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);
|
||||
});
|
||||
const std::vector<std::string> &labels, const std::vector<std::string> &edge_types) override {
|
||||
EditPermissions(
|
||||
user_or_role, privileges, labels, edge_types,
|
||||
[](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);
|
||||
},
|
||||
[](auto &label_permissions, const auto &label) {
|
||||
label_permissions.Deny(label, memgraph::auth::LabelPermission::READ);
|
||||
});
|
||||
}
|
||||
|
||||
void RevokePrivilege(const std::string &user_or_role,
|
||||
const std::vector<memgraph::query::AuthQuery::Privilege> &privileges,
|
||||
const std::vector<std::string> &labels, const std::vector<std::string> &edgeTypes) override {
|
||||
EditPermissions(user_or_role, privileges, labels, edgeTypes, [](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);
|
||||
});
|
||||
const std::vector<std::string> &labels, const std::vector<std::string> &edge_types) override {
|
||||
EditPermissions(
|
||||
user_or_role, privileges, labels, edge_types,
|
||||
[](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);
|
||||
},
|
||||
[](auto &label_permissions, const auto &label) { label_permissions.Revoke(label); });
|
||||
}
|
||||
|
||||
private:
|
||||
template <class TEditFun>
|
||||
template <class TEditPermissionsFun, class TEditFineGrainedPermissionsFun>
|
||||
void EditPermissions(const std::string &user_or_role,
|
||||
const std::vector<memgraph::query::AuthQuery::Privilege> &privileges,
|
||||
const std::vector<std::string> &labels, const std::vector<std::string> &edgeTypes,
|
||||
const TEditFun &edit_fun) {
|
||||
const TEditPermissionsFun &edit_permissions_fun,
|
||||
const TEditFineGrainedPermissionsFun &edit_fine_grained_permissions_fun) {
|
||||
if (!std::regex_match(user_or_role, name_regex_)) {
|
||||
throw memgraph::query::QueryRuntimeException("Invalid user or role name.");
|
||||
}
|
||||
@ -810,25 +824,25 @@ class AuthQueryHandler final : public memgraph::query::AuthQueryHandler {
|
||||
}
|
||||
if (user) {
|
||||
for (const auto &permission : permissions) {
|
||||
edit_fun(&user->permissions(), permission);
|
||||
edit_permissions_fun(user->permissions(), permission);
|
||||
}
|
||||
for (const auto &label : labels) {
|
||||
edit_fun(&user->fine_grained_access_handler().label_permissions(), label);
|
||||
edit_fine_grained_permissions_fun(user->fine_grained_access_handler().label_permissions(), label);
|
||||
}
|
||||
for (const auto &edgeType : edgeTypes) {
|
||||
edit_fun(&user->fine_grained_access_handler().edge_type_permissions(), edgeType);
|
||||
edit_fine_grained_permissions_fun(user->fine_grained_access_handler().edge_type_permissions(), edgeType);
|
||||
}
|
||||
|
||||
locked_auth->SaveUser(*user);
|
||||
} else {
|
||||
for (const auto &permission : permissions) {
|
||||
edit_fun(&role->permissions(), permission);
|
||||
edit_permissions_fun(role->permissions(), permission);
|
||||
}
|
||||
for (const auto &label : labels) {
|
||||
edit_fun(&user->fine_grained_access_handler().label_permissions(), label);
|
||||
edit_fine_grained_permissions_fun(user->fine_grained_access_handler().label_permissions(), label);
|
||||
}
|
||||
for (const auto &edgeType : edgeTypes) {
|
||||
edit_fun(&role->fine_grained_access_handler().edge_type_permissions(), edgeType);
|
||||
edit_fine_grained_permissions_fun(role->fine_grained_access_handler().edge_type_permissions(), edgeType);
|
||||
}
|
||||
|
||||
locked_auth->SaveRole(*role);
|
||||
|
@ -13,8 +13,7 @@ import mgp
|
||||
|
||||
|
||||
@mgp.read_proc
|
||||
def underlying_graph_is_mutable(ctx: mgp.ProcCtx,
|
||||
object: mgp.Any) -> mgp.Record(mutable=bool):
|
||||
def underlying_graph_is_mutable(ctx: mgp.ProcCtx, object: mgp.Any) -> mgp.Record(mutable=bool):
|
||||
return mgp.Record(mutable=object.underlying_graph_is_mutable())
|
||||
|
||||
|
||||
|
@ -11,6 +11,7 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include <optional>
|
||||
|
||||
#include <gflags/gflags.h>
|
||||
#include <gtest/gtest.h>
|
||||
@ -176,25 +177,29 @@ TEST_F(AuthWithStorage, UserRoleFineGrainedAccessHandler) {
|
||||
user->GetFineGrainedAccessEdgeTypePermissions());
|
||||
|
||||
// Grant one label to user .
|
||||
user->fine_grained_access_handler().label_permissions().Grant("labelTest");
|
||||
user->fine_grained_access_handler().label_permissions().Grant("labelTest", LabelPermission::CREATE_DELETE);
|
||||
// Grant one edge type to user .
|
||||
user->fine_grained_access_handler().edge_type_permissions().Grant("edgeTypeTest");
|
||||
user->fine_grained_access_handler().edge_type_permissions().Grant("edgeTypeTest", LabelPermission::CREATE_DELETE);
|
||||
|
||||
// Check permissions.
|
||||
ASSERT_EQ(user->fine_grained_access_handler().label_permissions().Has("labelTest"), PermissionLevel::GRANT);
|
||||
ASSERT_EQ(user->fine_grained_access_handler().edge_type_permissions().Has("edgeTypeTest"), PermissionLevel::GRANT);
|
||||
ASSERT_EQ(user->fine_grained_access_handler().label_permissions().Has("labelTest", LabelPermission::READ),
|
||||
PermissionLevel::GRANT);
|
||||
ASSERT_EQ(user->fine_grained_access_handler().edge_type_permissions().Has("edgeTypeTest", LabelPermission::READ),
|
||||
PermissionLevel::GRANT);
|
||||
ASSERT_EQ(user->fine_grained_access_handler().label_permissions(), user->GetFineGrainedAccessLabelPermissions());
|
||||
ASSERT_EQ(user->fine_grained_access_handler().edge_type_permissions(),
|
||||
user->GetFineGrainedAccessEdgeTypePermissions());
|
||||
|
||||
// Deny one label to user .
|
||||
user->fine_grained_access_handler().label_permissions().Deny("labelTest1");
|
||||
user->fine_grained_access_handler().label_permissions().Deny("labelTest1", LabelPermission::READ);
|
||||
// Deny one edge type to user .
|
||||
user->fine_grained_access_handler().edge_type_permissions().Deny("edgeTypeTest1");
|
||||
user->fine_grained_access_handler().edge_type_permissions().Deny("edgeTypeTest1", LabelPermission::READ);
|
||||
|
||||
// Check permissions.
|
||||
ASSERT_EQ(user->fine_grained_access_handler().label_permissions().Has("labelTest1"), PermissionLevel::DENY);
|
||||
ASSERT_EQ(user->fine_grained_access_handler().edge_type_permissions().Has("edgeTypeTest1"), PermissionLevel::DENY);
|
||||
ASSERT_EQ(user->fine_grained_access_handler().label_permissions().Has("labelTest1", LabelPermission::READ),
|
||||
PermissionLevel::DENY);
|
||||
ASSERT_EQ(user->fine_grained_access_handler().edge_type_permissions().Has("edgeTypeTest1", LabelPermission::READ),
|
||||
PermissionLevel::DENY);
|
||||
ASSERT_EQ(user->fine_grained_access_handler().label_permissions(), user->GetFineGrainedAccessLabelPermissions());
|
||||
ASSERT_EQ(user->fine_grained_access_handler().edge_type_permissions(),
|
||||
user->GetFineGrainedAccessEdgeTypePermissions());
|
||||
@ -205,25 +210,29 @@ TEST_F(AuthWithStorage, UserRoleFineGrainedAccessHandler) {
|
||||
ASSERT_NE(role, std::nullopt);
|
||||
|
||||
// Grant label and edge type to role and role to user.
|
||||
role->fine_grained_access_handler().label_permissions().Grant("roleLabelTest");
|
||||
role->fine_grained_access_handler().edge_type_permissions().Grant("roleEdgeTypeTest");
|
||||
role->fine_grained_access_handler().label_permissions().Grant("roleLabelTest", LabelPermission::CREATE_DELETE);
|
||||
role->fine_grained_access_handler().edge_type_permissions().Grant("roleEdgeTypeTest", LabelPermission::CREATE_DELETE);
|
||||
user->SetRole(*role);
|
||||
|
||||
// Check permissions.
|
||||
{
|
||||
ASSERT_EQ(user->GetFineGrainedAccessLabelPermissions().Has("roleLabelTest"), PermissionLevel::GRANT);
|
||||
ASSERT_EQ(user->GetFineGrainedAccessEdgeTypePermissions().Has("roleEdgeTypeTest"), PermissionLevel::GRANT);
|
||||
ASSERT_EQ(user->GetFineGrainedAccessLabelPermissions().Has("roleLabelTest", LabelPermission::READ),
|
||||
PermissionLevel::GRANT);
|
||||
ASSERT_EQ(user->GetFineGrainedAccessEdgeTypePermissions().Has("roleEdgeTypeTest", LabelPermission::READ),
|
||||
PermissionLevel::GRANT);
|
||||
}
|
||||
|
||||
// Deny label and edge type to role and role to user.
|
||||
role->fine_grained_access_handler().label_permissions().Deny("roleLabelTest1");
|
||||
role->fine_grained_access_handler().edge_type_permissions().Deny("roleEdgeTypeTest1");
|
||||
role->fine_grained_access_handler().label_permissions().Deny("roleLabelTest1", LabelPermission::READ);
|
||||
role->fine_grained_access_handler().edge_type_permissions().Deny("roleEdgeTypeTest1", LabelPermission::READ);
|
||||
user->SetRole(*role);
|
||||
|
||||
// Check permissions.
|
||||
{
|
||||
ASSERT_EQ(user->GetFineGrainedAccessLabelPermissions().Has("roleLabelTest1"), PermissionLevel::DENY);
|
||||
ASSERT_EQ(user->GetFineGrainedAccessEdgeTypePermissions().Has("roleEdgeTypeTest1"), PermissionLevel::DENY);
|
||||
ASSERT_EQ(user->GetFineGrainedAccessLabelPermissions().Has("roleLabelTest1", LabelPermission::READ),
|
||||
PermissionLevel::DENY);
|
||||
ASSERT_EQ(user->GetFineGrainedAccessEdgeTypePermissions().Has("roleEdgeTypeTest1", LabelPermission::READ),
|
||||
PermissionLevel::DENY);
|
||||
}
|
||||
}
|
||||
|
||||
@ -475,6 +484,361 @@ TEST(AuthWithoutStorage, PermissionsMaskTest) {
|
||||
ASSERT_EQ(p4.denies(), 2);
|
||||
}
|
||||
|
||||
TEST(AuthWithoutStorage, FineGrainedAccessPermissions) {
|
||||
const std::string any_label = "AnyString";
|
||||
const std::string check_label = "Label";
|
||||
const std::string non_check_label = "OtherLabel";
|
||||
const std::string asterisk = "*";
|
||||
|
||||
{
|
||||
FineGrainedAccessPermissions fga_permissions1, fga_permissions2;
|
||||
ASSERT_TRUE(fga_permissions1 == fga_permissions2);
|
||||
}
|
||||
|
||||
{
|
||||
FineGrainedAccessPermissions fga_permissions;
|
||||
ASSERT_TRUE(fga_permissions.GetPermissions().empty());
|
||||
ASSERT_EQ(fga_permissions.GetGlobalPermission(), std::nullopt);
|
||||
|
||||
ASSERT_EQ(fga_permissions.Has(any_label, LabelPermission::CREATE_DELETE), PermissionLevel::DENY);
|
||||
ASSERT_EQ(fga_permissions.Has(any_label, LabelPermission::EDIT), PermissionLevel::DENY);
|
||||
ASSERT_EQ(fga_permissions.Has(any_label, LabelPermission::READ), PermissionLevel::DENY);
|
||||
}
|
||||
|
||||
{
|
||||
FineGrainedAccessPermissions fga_permissions;
|
||||
fga_permissions.Grant(any_label, LabelPermission::CREATE_DELETE);
|
||||
|
||||
ASSERT_EQ(fga_permissions.GetGlobalPermission(), std::nullopt);
|
||||
ASSERT_FALSE(fga_permissions.GetPermissions().empty());
|
||||
}
|
||||
|
||||
{
|
||||
FineGrainedAccessPermissions fga_permissions;
|
||||
fga_permissions.Deny(any_label, LabelPermission::CREATE_DELETE);
|
||||
|
||||
ASSERT_EQ(fga_permissions.GetGlobalPermission(), std::nullopt);
|
||||
ASSERT_FALSE(fga_permissions.GetPermissions().empty());
|
||||
}
|
||||
|
||||
{
|
||||
FineGrainedAccessPermissions fga_permissions;
|
||||
fga_permissions.Grant(asterisk, LabelPermission::CREATE_DELETE);
|
||||
fga_permissions.Deny(any_label, LabelPermission::CREATE_DELETE);
|
||||
|
||||
ASSERT_EQ(fga_permissions.GetGlobalPermission(), LabelPermissionAll);
|
||||
ASSERT_FALSE(fga_permissions.GetPermissions().empty());
|
||||
}
|
||||
|
||||
{
|
||||
FineGrainedAccessPermissions fga_permissions;
|
||||
fga_permissions.Grant(asterisk, LabelPermission::CREATE_DELETE);
|
||||
fga_permissions.Revoke(any_label);
|
||||
|
||||
ASSERT_EQ(fga_permissions.GetGlobalPermission(), LabelPermissionAll);
|
||||
ASSERT_TRUE(fga_permissions.GetPermissions().empty());
|
||||
}
|
||||
|
||||
{
|
||||
FineGrainedAccessPermissions fga_permissions;
|
||||
fga_permissions.Grant(any_label, LabelPermission::CREATE_DELETE);
|
||||
fga_permissions.Revoke(any_label);
|
||||
|
||||
ASSERT_EQ(fga_permissions.GetGlobalPermission(), std::nullopt);
|
||||
ASSERT_TRUE(fga_permissions.GetPermissions().empty());
|
||||
}
|
||||
|
||||
{
|
||||
FineGrainedAccessPermissions fga_permissions;
|
||||
fga_permissions.Grant(any_label, LabelPermission::CREATE_DELETE);
|
||||
fga_permissions.Revoke(asterisk);
|
||||
|
||||
ASSERT_EQ(fga_permissions.GetGlobalPermission(), std::nullopt);
|
||||
ASSERT_TRUE(fga_permissions.GetPermissions().empty());
|
||||
}
|
||||
|
||||
{
|
||||
FineGrainedAccessPermissions fga_permissions;
|
||||
fga_permissions.Deny(asterisk, LabelPermission::CREATE_DELETE);
|
||||
fga_permissions.Revoke(any_label);
|
||||
|
||||
ASSERT_EQ(fga_permissions.GetGlobalPermission(), LabelPermission::EDIT | LabelPermission::READ);
|
||||
ASSERT_TRUE(fga_permissions.GetPermissions().empty());
|
||||
}
|
||||
|
||||
{
|
||||
FineGrainedAccessPermissions fga_permissions;
|
||||
fga_permissions.Deny(any_label, LabelPermission::CREATE_DELETE);
|
||||
fga_permissions.Revoke(any_label);
|
||||
|
||||
ASSERT_EQ(fga_permissions.GetGlobalPermission(), std::nullopt);
|
||||
ASSERT_TRUE(fga_permissions.GetPermissions().empty());
|
||||
}
|
||||
|
||||
{
|
||||
FineGrainedAccessPermissions fga_permissions;
|
||||
fga_permissions.Deny(any_label, LabelPermission::CREATE_DELETE);
|
||||
fga_permissions.Revoke(asterisk);
|
||||
|
||||
ASSERT_EQ(fga_permissions.GetGlobalPermission(), std::nullopt);
|
||||
ASSERT_TRUE(fga_permissions.GetPermissions().empty());
|
||||
}
|
||||
|
||||
{
|
||||
FineGrainedAccessPermissions fga_permissions;
|
||||
fga_permissions.Grant(check_label, LabelPermission::CREATE_DELETE);
|
||||
fga_permissions.Deny(non_check_label, LabelPermission::CREATE_DELETE);
|
||||
fga_permissions.Revoke(asterisk);
|
||||
|
||||
ASSERT_EQ(fga_permissions.GetGlobalPermission(), std::nullopt);
|
||||
ASSERT_TRUE(fga_permissions.GetPermissions().empty());
|
||||
}
|
||||
|
||||
{
|
||||
FineGrainedAccessPermissions fga_permissions;
|
||||
fga_permissions.Grant(asterisk, LabelPermission::CREATE_DELETE);
|
||||
|
||||
ASSERT_EQ(fga_permissions.Has(any_label, LabelPermission::CREATE_DELETE), PermissionLevel::GRANT);
|
||||
ASSERT_EQ(fga_permissions.Has(any_label, LabelPermission::EDIT), PermissionLevel::GRANT);
|
||||
ASSERT_EQ(fga_permissions.Has(any_label, LabelPermission::READ), PermissionLevel::GRANT);
|
||||
}
|
||||
|
||||
{
|
||||
FineGrainedAccessPermissions fga_permissions;
|
||||
fga_permissions.Grant(asterisk, LabelPermission::EDIT);
|
||||
|
||||
ASSERT_EQ(fga_permissions.Has(any_label, LabelPermission::CREATE_DELETE), PermissionLevel::DENY);
|
||||
ASSERT_EQ(fga_permissions.Has(any_label, LabelPermission::EDIT), PermissionLevel::GRANT);
|
||||
ASSERT_EQ(fga_permissions.Has(any_label, LabelPermission::READ), PermissionLevel::GRANT);
|
||||
}
|
||||
|
||||
{
|
||||
FineGrainedAccessPermissions fga_permissions;
|
||||
fga_permissions.Grant(asterisk, LabelPermission::CREATE_DELETE);
|
||||
|
||||
ASSERT_EQ(fga_permissions.Has(any_label, LabelPermission::CREATE_DELETE), PermissionLevel::GRANT);
|
||||
ASSERT_EQ(fga_permissions.Has(any_label, LabelPermission::EDIT), PermissionLevel::GRANT);
|
||||
ASSERT_EQ(fga_permissions.Has(any_label, LabelPermission::READ), PermissionLevel::GRANT);
|
||||
}
|
||||
|
||||
{
|
||||
FineGrainedAccessPermissions fga_permissions;
|
||||
fga_permissions.Deny(asterisk, LabelPermission::CREATE_DELETE);
|
||||
|
||||
ASSERT_EQ(fga_permissions.Has(any_label, LabelPermission::CREATE_DELETE), PermissionLevel::DENY);
|
||||
ASSERT_EQ(fga_permissions.Has(any_label, LabelPermission::EDIT), PermissionLevel::GRANT);
|
||||
ASSERT_EQ(fga_permissions.Has(any_label, LabelPermission::READ), PermissionLevel::GRANT);
|
||||
}
|
||||
|
||||
{
|
||||
FineGrainedAccessPermissions fga_permissions;
|
||||
fga_permissions.Deny(asterisk, LabelPermission::EDIT);
|
||||
|
||||
ASSERT_EQ(fga_permissions.Has(any_label, LabelPermission::CREATE_DELETE), PermissionLevel::DENY);
|
||||
ASSERT_EQ(fga_permissions.Has(any_label, LabelPermission::EDIT), PermissionLevel::DENY);
|
||||
ASSERT_EQ(fga_permissions.Has(any_label, LabelPermission::READ), PermissionLevel::GRANT);
|
||||
}
|
||||
|
||||
{
|
||||
FineGrainedAccessPermissions fga_permissions;
|
||||
fga_permissions.Deny(asterisk, LabelPermission::READ);
|
||||
|
||||
ASSERT_EQ(fga_permissions.Has(any_label, LabelPermission::CREATE_DELETE), PermissionLevel::DENY);
|
||||
ASSERT_EQ(fga_permissions.Has(any_label, LabelPermission::EDIT), PermissionLevel::DENY);
|
||||
ASSERT_EQ(fga_permissions.Has(any_label, LabelPermission::READ), PermissionLevel::DENY);
|
||||
}
|
||||
|
||||
{
|
||||
FineGrainedAccessPermissions fga_permissions;
|
||||
fga_permissions.Grant(asterisk, LabelPermission::READ);
|
||||
fga_permissions.Grant(check_label, LabelPermission::EDIT);
|
||||
|
||||
ASSERT_EQ(fga_permissions.Has(check_label, LabelPermission::CREATE_DELETE), PermissionLevel::DENY);
|
||||
ASSERT_EQ(fga_permissions.Has(check_label, LabelPermission::EDIT), PermissionLevel::GRANT);
|
||||
ASSERT_EQ(fga_permissions.Has(check_label, LabelPermission::READ), PermissionLevel::GRANT);
|
||||
ASSERT_EQ(fga_permissions.Has(non_check_label, LabelPermission::CREATE_DELETE), PermissionLevel::DENY);
|
||||
ASSERT_EQ(fga_permissions.Has(non_check_label, LabelPermission::EDIT), PermissionLevel::DENY);
|
||||
ASSERT_EQ(fga_permissions.Has(non_check_label, LabelPermission::READ), PermissionLevel::GRANT);
|
||||
}
|
||||
|
||||
{
|
||||
FineGrainedAccessPermissions fga_permissions;
|
||||
fga_permissions.Grant(asterisk, LabelPermission::READ);
|
||||
fga_permissions.Deny(check_label, LabelPermission::CREATE_DELETE);
|
||||
|
||||
ASSERT_EQ(fga_permissions.Has(check_label, LabelPermission::CREATE_DELETE), PermissionLevel::DENY);
|
||||
ASSERT_EQ(fga_permissions.Has(check_label, LabelPermission::EDIT), PermissionLevel::GRANT);
|
||||
ASSERT_EQ(fga_permissions.Has(check_label, LabelPermission::READ), PermissionLevel::GRANT);
|
||||
ASSERT_EQ(fga_permissions.Has(non_check_label, LabelPermission::CREATE_DELETE), PermissionLevel::DENY);
|
||||
ASSERT_EQ(fga_permissions.Has(non_check_label, LabelPermission::EDIT), PermissionLevel::DENY);
|
||||
ASSERT_EQ(fga_permissions.Has(non_check_label, LabelPermission::READ), PermissionLevel::GRANT);
|
||||
}
|
||||
|
||||
{
|
||||
FineGrainedAccessPermissions fga_permissions;
|
||||
fga_permissions.Grant(asterisk, LabelPermission::CREATE_DELETE);
|
||||
fga_permissions.Deny(check_label, LabelPermission::EDIT);
|
||||
|
||||
ASSERT_EQ(fga_permissions.Has(check_label, LabelPermission::CREATE_DELETE), PermissionLevel::DENY);
|
||||
ASSERT_EQ(fga_permissions.Has(check_label, LabelPermission::EDIT), PermissionLevel::DENY);
|
||||
ASSERT_EQ(fga_permissions.Has(check_label, LabelPermission::READ), PermissionLevel::GRANT);
|
||||
ASSERT_EQ(fga_permissions.Has(non_check_label, LabelPermission::CREATE_DELETE), PermissionLevel::GRANT);
|
||||
ASSERT_EQ(fga_permissions.Has(non_check_label, LabelPermission::EDIT), PermissionLevel::GRANT);
|
||||
ASSERT_EQ(fga_permissions.Has(non_check_label, LabelPermission::READ), PermissionLevel::GRANT);
|
||||
}
|
||||
|
||||
{
|
||||
FineGrainedAccessPermissions fga_permissions;
|
||||
fga_permissions.Grant(asterisk, LabelPermission::CREATE_DELETE);
|
||||
fga_permissions.Deny(check_label, LabelPermission::CREATE_DELETE);
|
||||
|
||||
ASSERT_EQ(fga_permissions.Has(check_label, LabelPermission::CREATE_DELETE), PermissionLevel::DENY);
|
||||
ASSERT_EQ(fga_permissions.Has(check_label, LabelPermission::EDIT), PermissionLevel::GRANT);
|
||||
ASSERT_EQ(fga_permissions.Has(check_label, LabelPermission::READ), PermissionLevel::GRANT);
|
||||
ASSERT_EQ(fga_permissions.Has(non_check_label, LabelPermission::CREATE_DELETE), PermissionLevel::GRANT);
|
||||
ASSERT_EQ(fga_permissions.Has(non_check_label, LabelPermission::EDIT), PermissionLevel::GRANT);
|
||||
ASSERT_EQ(fga_permissions.Has(non_check_label, LabelPermission::READ), PermissionLevel::GRANT);
|
||||
}
|
||||
|
||||
{
|
||||
FineGrainedAccessPermissions fga_permissions;
|
||||
fga_permissions.Grant(asterisk, LabelPermission::CREATE_DELETE);
|
||||
fga_permissions.Deny(asterisk, LabelPermission::CREATE_DELETE);
|
||||
|
||||
ASSERT_EQ(fga_permissions.Has(any_label, LabelPermission::CREATE_DELETE), PermissionLevel::DENY);
|
||||
ASSERT_EQ(fga_permissions.Has(any_label, LabelPermission::EDIT), PermissionLevel::GRANT);
|
||||
ASSERT_EQ(fga_permissions.Has(any_label, LabelPermission::READ), PermissionLevel::GRANT);
|
||||
}
|
||||
|
||||
{
|
||||
FineGrainedAccessPermissions fga_permissions;
|
||||
fga_permissions.Grant(asterisk, LabelPermission::CREATE_DELETE);
|
||||
fga_permissions.Deny(asterisk, LabelPermission::EDIT);
|
||||
|
||||
ASSERT_EQ(fga_permissions.Has(any_label, LabelPermission::CREATE_DELETE), PermissionLevel::DENY);
|
||||
ASSERT_EQ(fga_permissions.Has(any_label, LabelPermission::EDIT), PermissionLevel::DENY);
|
||||
ASSERT_EQ(fga_permissions.Has(any_label, LabelPermission::READ), PermissionLevel::GRANT);
|
||||
}
|
||||
|
||||
{
|
||||
FineGrainedAccessPermissions fga_permissions;
|
||||
fga_permissions.Grant(asterisk, LabelPermission::CREATE_DELETE);
|
||||
fga_permissions.Deny(asterisk, LabelPermission::READ);
|
||||
|
||||
ASSERT_EQ(fga_permissions.Has(any_label, LabelPermission::CREATE_DELETE), PermissionLevel::DENY);
|
||||
ASSERT_EQ(fga_permissions.Has(any_label, LabelPermission::EDIT), PermissionLevel::DENY);
|
||||
ASSERT_EQ(fga_permissions.Has(any_label, LabelPermission::READ), PermissionLevel::DENY);
|
||||
}
|
||||
|
||||
{
|
||||
FineGrainedAccessPermissions fga_permissions;
|
||||
fga_permissions.Grant(asterisk, LabelPermission::CREATE_DELETE);
|
||||
fga_permissions.Deny(check_label, LabelPermission::READ);
|
||||
fga_permissions.Revoke(asterisk);
|
||||
|
||||
ASSERT_EQ(fga_permissions.Has(check_label, LabelPermission::CREATE_DELETE), PermissionLevel::DENY);
|
||||
ASSERT_EQ(fga_permissions.Has(check_label, LabelPermission::EDIT), PermissionLevel::DENY);
|
||||
ASSERT_EQ(fga_permissions.Has(check_label, LabelPermission::READ), PermissionLevel::DENY);
|
||||
ASSERT_EQ(fga_permissions.Has(non_check_label, LabelPermission::CREATE_DELETE), PermissionLevel::DENY);
|
||||
ASSERT_EQ(fga_permissions.Has(non_check_label, LabelPermission::EDIT), PermissionLevel::DENY);
|
||||
ASSERT_EQ(fga_permissions.Has(non_check_label, LabelPermission::READ), PermissionLevel::DENY);
|
||||
}
|
||||
|
||||
{
|
||||
FineGrainedAccessPermissions fga_permissions;
|
||||
fga_permissions.Grant(asterisk, LabelPermission::CREATE_DELETE);
|
||||
fga_permissions.Deny(check_label, LabelPermission::EDIT);
|
||||
fga_permissions.Revoke(asterisk);
|
||||
|
||||
ASSERT_EQ(fga_permissions.Has(check_label, LabelPermission::CREATE_DELETE), PermissionLevel::DENY);
|
||||
ASSERT_EQ(fga_permissions.Has(check_label, LabelPermission::EDIT), PermissionLevel::DENY);
|
||||
ASSERT_EQ(fga_permissions.Has(check_label, LabelPermission::READ), PermissionLevel::DENY);
|
||||
ASSERT_EQ(fga_permissions.Has(non_check_label, LabelPermission::CREATE_DELETE), PermissionLevel::DENY);
|
||||
ASSERT_EQ(fga_permissions.Has(non_check_label, LabelPermission::EDIT), PermissionLevel::DENY);
|
||||
ASSERT_EQ(fga_permissions.Has(non_check_label, LabelPermission::READ), PermissionLevel::DENY);
|
||||
}
|
||||
|
||||
{
|
||||
FineGrainedAccessPermissions fga_permissions;
|
||||
fga_permissions.Grant(asterisk, LabelPermission::CREATE_DELETE);
|
||||
fga_permissions.Deny(check_label, LabelPermission::CREATE_DELETE);
|
||||
fga_permissions.Revoke(asterisk);
|
||||
|
||||
ASSERT_EQ(fga_permissions.Has(check_label, LabelPermission::CREATE_DELETE), PermissionLevel::DENY);
|
||||
ASSERT_EQ(fga_permissions.Has(check_label, LabelPermission::EDIT), PermissionLevel::DENY);
|
||||
ASSERT_EQ(fga_permissions.Has(check_label, LabelPermission::READ), PermissionLevel::DENY);
|
||||
ASSERT_EQ(fga_permissions.Has(non_check_label, LabelPermission::CREATE_DELETE), PermissionLevel::DENY);
|
||||
ASSERT_EQ(fga_permissions.Has(non_check_label, LabelPermission::EDIT), PermissionLevel::DENY);
|
||||
ASSERT_EQ(fga_permissions.Has(non_check_label, LabelPermission::READ), PermissionLevel::DENY);
|
||||
}
|
||||
}
|
||||
TEST_F(AuthWithStorage, FineGrainedAccessCheckerMerge) {
|
||||
auto any_label = "AnyString";
|
||||
auto check_label = "Label";
|
||||
auto asterisk = "*";
|
||||
|
||||
{
|
||||
FineGrainedAccessPermissions fga_permissions1, fga_permissions2;
|
||||
fga_permissions1.Grant(asterisk, LabelPermission::READ);
|
||||
|
||||
auto fga_permissions3 = memgraph::auth::Merge(fga_permissions1, fga_permissions2);
|
||||
|
||||
ASSERT_EQ(fga_permissions3.Has(any_label, LabelPermission::CREATE_DELETE), PermissionLevel::DENY);
|
||||
ASSERT_EQ(fga_permissions3.Has(any_label, LabelPermission::EDIT), PermissionLevel::DENY);
|
||||
ASSERT_EQ(fga_permissions3.Has(any_label, LabelPermission::READ), PermissionLevel::GRANT);
|
||||
}
|
||||
|
||||
{
|
||||
FineGrainedAccessPermissions fga_permissions1, fga_permissions2;
|
||||
fga_permissions2.Grant(asterisk, LabelPermission::READ);
|
||||
|
||||
auto fga_permissions3 = memgraph::auth::Merge(fga_permissions1, fga_permissions2);
|
||||
|
||||
ASSERT_EQ(fga_permissions3.Has(any_label, LabelPermission::CREATE_DELETE), PermissionLevel::DENY);
|
||||
ASSERT_EQ(fga_permissions3.Has(any_label, LabelPermission::EDIT), PermissionLevel::DENY);
|
||||
ASSERT_EQ(fga_permissions3.Has(any_label, LabelPermission::READ), PermissionLevel::GRANT);
|
||||
}
|
||||
|
||||
{
|
||||
FineGrainedAccessPermissions fga_permissions1, fga_permissions2;
|
||||
fga_permissions1.Grant(asterisk, LabelPermission::READ);
|
||||
fga_permissions2.Grant(asterisk, LabelPermission::EDIT);
|
||||
|
||||
auto fga_permissions3 = memgraph::auth::Merge(fga_permissions1, fga_permissions2);
|
||||
|
||||
ASSERT_EQ(fga_permissions3.Has(any_label, LabelPermission::CREATE_DELETE), PermissionLevel::DENY);
|
||||
ASSERT_EQ(fga_permissions3.Has(any_label, LabelPermission::EDIT), PermissionLevel::GRANT);
|
||||
ASSERT_EQ(fga_permissions3.Has(any_label, LabelPermission::READ), PermissionLevel::GRANT);
|
||||
}
|
||||
|
||||
{
|
||||
FineGrainedAccessPermissions fga_permissions1, fga_permissions2;
|
||||
fga_permissions1.Grant(asterisk, LabelPermission::READ);
|
||||
fga_permissions1.Grant(check_label, LabelPermission::EDIT);
|
||||
fga_permissions2.Grant(asterisk, LabelPermission::EDIT);
|
||||
|
||||
auto fga_permissions3 = memgraph::auth::Merge(fga_permissions1, fga_permissions2);
|
||||
|
||||
ASSERT_EQ(fga_permissions3.Has(check_label, LabelPermission::CREATE_DELETE), PermissionLevel::DENY);
|
||||
ASSERT_EQ(fga_permissions3.Has(check_label, LabelPermission::EDIT), PermissionLevel::GRANT);
|
||||
ASSERT_EQ(fga_permissions3.Has(check_label, LabelPermission::READ), PermissionLevel::GRANT);
|
||||
}
|
||||
|
||||
{
|
||||
FineGrainedAccessPermissions fga_permissions1, fga_permissions2;
|
||||
fga_permissions1.Grant(asterisk, LabelPermission::READ);
|
||||
fga_permissions1.Grant(check_label, LabelPermission::CREATE_DELETE);
|
||||
fga_permissions2.Grant(asterisk, LabelPermission::EDIT);
|
||||
fga_permissions2.Grant(check_label, LabelPermission::READ);
|
||||
|
||||
auto fga_permissions3 = memgraph::auth::Merge(fga_permissions1, fga_permissions2);
|
||||
|
||||
ASSERT_EQ(fga_permissions3.Has(check_label, LabelPermission::CREATE_DELETE), PermissionLevel::DENY);
|
||||
ASSERT_EQ(fga_permissions3.Has(check_label, LabelPermission::EDIT), PermissionLevel::DENY);
|
||||
ASSERT_EQ(fga_permissions3.Has(check_label, LabelPermission::READ), PermissionLevel::GRANT);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(AuthWithoutStorage, UserSerializeDeserialize) {
|
||||
auto user = User("test");
|
||||
user.permissions().Grant(Permission::MATCH);
|
||||
|
@ -46,7 +46,7 @@ class FineGrainedAuthCheckerFixture : public testing::Test {
|
||||
|
||||
TEST_F(FineGrainedAuthCheckerFixture, GrantedAllLabels) {
|
||||
memgraph::auth::User user{"test"};
|
||||
user.fine_grained_access_handler().label_permissions().Grant("*");
|
||||
user.fine_grained_access_handler().label_permissions().Grant("*", memgraph::auth::LabelPermission::CREATE_DELETE);
|
||||
memgraph::glue::FineGrainedAuthChecker auth_checker{user};
|
||||
|
||||
ASSERT_TRUE(auth_checker.Accept(dba, v1, memgraph::storage::View::NEW));
|
||||
@ -59,7 +59,7 @@ TEST_F(FineGrainedAuthCheckerFixture, GrantedAllLabels) {
|
||||
|
||||
TEST_F(FineGrainedAuthCheckerFixture, GrantedAllEdgeTypes) {
|
||||
memgraph::auth::User user{"test"};
|
||||
user.fine_grained_access_handler().edge_type_permissions().Grant("*");
|
||||
user.fine_grained_access_handler().edge_type_permissions().Grant("*", memgraph::auth::LabelPermission::CREATE_DELETE);
|
||||
memgraph::glue::FineGrainedAuthChecker auth_checker{user};
|
||||
|
||||
ASSERT_TRUE(auth_checker.Accept(dba, r1));
|
||||
@ -70,7 +70,7 @@ TEST_F(FineGrainedAuthCheckerFixture, GrantedAllEdgeTypes) {
|
||||
|
||||
TEST_F(FineGrainedAuthCheckerFixture, DeniedAllLabels) {
|
||||
memgraph::auth::User user{"test"};
|
||||
user.fine_grained_access_handler().label_permissions().Deny("*");
|
||||
user.fine_grained_access_handler().label_permissions().Deny("*", memgraph::auth::LabelPermission::READ);
|
||||
memgraph::glue::FineGrainedAuthChecker auth_checker{user};
|
||||
|
||||
ASSERT_FALSE(auth_checker.Accept(dba, v1, memgraph::storage::View::NEW));
|
||||
@ -83,7 +83,7 @@ TEST_F(FineGrainedAuthCheckerFixture, DeniedAllLabels) {
|
||||
|
||||
TEST_F(FineGrainedAuthCheckerFixture, DeniedAllEdgeTypes) {
|
||||
memgraph::auth::User user{"test"};
|
||||
user.fine_grained_access_handler().edge_type_permissions().Deny("*");
|
||||
user.fine_grained_access_handler().edge_type_permissions().Deny("*", memgraph::auth::LabelPermission::READ);
|
||||
memgraph::glue::FineGrainedAuthChecker auth_checker{user};
|
||||
|
||||
ASSERT_FALSE(auth_checker.Accept(dba, r1));
|
||||
@ -94,7 +94,7 @@ TEST_F(FineGrainedAuthCheckerFixture, DeniedAllEdgeTypes) {
|
||||
|
||||
TEST_F(FineGrainedAuthCheckerFixture, GrantLabel) {
|
||||
memgraph::auth::User user{"test"};
|
||||
user.fine_grained_access_handler().label_permissions().Grant("l1");
|
||||
user.fine_grained_access_handler().label_permissions().Grant("l1", memgraph::auth::LabelPermission::CREATE_DELETE);
|
||||
memgraph::glue::FineGrainedAuthChecker auth_checker{user};
|
||||
|
||||
ASSERT_TRUE(auth_checker.Accept(dba, v1, memgraph::storage::View::NEW));
|
||||
@ -103,7 +103,7 @@ TEST_F(FineGrainedAuthCheckerFixture, GrantLabel) {
|
||||
|
||||
TEST_F(FineGrainedAuthCheckerFixture, DenyLabel) {
|
||||
memgraph::auth::User user{"test"};
|
||||
user.fine_grained_access_handler().label_permissions().Deny("l3");
|
||||
user.fine_grained_access_handler().label_permissions().Deny("l3", memgraph::auth::LabelPermission::READ);
|
||||
memgraph::glue::FineGrainedAuthChecker auth_checker{user};
|
||||
|
||||
ASSERT_FALSE(auth_checker.Accept(dba, v3, memgraph::storage::View::NEW));
|
||||
@ -112,9 +112,9 @@ TEST_F(FineGrainedAuthCheckerFixture, DenyLabel) {
|
||||
|
||||
TEST_F(FineGrainedAuthCheckerFixture, GrantAndDenySpecificLabels) {
|
||||
memgraph::auth::User user{"test"};
|
||||
user.fine_grained_access_handler().label_permissions().Grant("l1");
|
||||
user.fine_grained_access_handler().label_permissions().Grant("l2");
|
||||
user.fine_grained_access_handler().label_permissions().Deny("l3");
|
||||
user.fine_grained_access_handler().label_permissions().Grant("l1", memgraph::auth::LabelPermission::CREATE_DELETE);
|
||||
user.fine_grained_access_handler().label_permissions().Grant("l2", memgraph::auth::LabelPermission::CREATE_DELETE);
|
||||
user.fine_grained_access_handler().label_permissions().Deny("l3", memgraph::auth::LabelPermission::READ);
|
||||
memgraph::glue::FineGrainedAuthChecker auth_checker{user};
|
||||
|
||||
ASSERT_TRUE(auth_checker.Accept(dba, v1, memgraph::storage::View::NEW));
|
||||
@ -127,9 +127,9 @@ TEST_F(FineGrainedAuthCheckerFixture, GrantAndDenySpecificLabels) {
|
||||
|
||||
TEST_F(FineGrainedAuthCheckerFixture, MultipleVertexLabels) {
|
||||
memgraph::auth::User user{"test"};
|
||||
user.fine_grained_access_handler().label_permissions().Grant("l1");
|
||||
user.fine_grained_access_handler().label_permissions().Grant("l2");
|
||||
user.fine_grained_access_handler().label_permissions().Deny("l3");
|
||||
user.fine_grained_access_handler().label_permissions().Grant("l1", memgraph::auth::LabelPermission::CREATE_DELETE);
|
||||
user.fine_grained_access_handler().label_permissions().Grant("l2", memgraph::auth::LabelPermission::CREATE_DELETE);
|
||||
user.fine_grained_access_handler().label_permissions().Deny("l3", memgraph::auth::LabelPermission::READ);
|
||||
memgraph::glue::FineGrainedAuthChecker auth_checker{user};
|
||||
ASSERT_TRUE(v1.AddLabel(dba.NameToLabel("l3")).HasValue());
|
||||
ASSERT_TRUE(v2.AddLabel(dba.NameToLabel("l1")).HasValue());
|
||||
@ -143,7 +143,8 @@ TEST_F(FineGrainedAuthCheckerFixture, MultipleVertexLabels) {
|
||||
|
||||
TEST_F(FineGrainedAuthCheckerFixture, GrantEdgeType) {
|
||||
memgraph::auth::User user{"test"};
|
||||
user.fine_grained_access_handler().edge_type_permissions().Grant("edge_type_1");
|
||||
user.fine_grained_access_handler().edge_type_permissions().Grant("edge_type_1",
|
||||
memgraph::auth::LabelPermission::CREATE_DELETE);
|
||||
memgraph::glue::FineGrainedAuthChecker auth_checker{user};
|
||||
|
||||
ASSERT_TRUE(auth_checker.Accept(dba, r1));
|
||||
@ -151,7 +152,7 @@ TEST_F(FineGrainedAuthCheckerFixture, GrantEdgeType) {
|
||||
|
||||
TEST_F(FineGrainedAuthCheckerFixture, DenyEdgeType) {
|
||||
memgraph::auth::User user{"test"};
|
||||
user.fine_grained_access_handler().edge_type_permissions().Deny("edge_type_1");
|
||||
user.fine_grained_access_handler().edge_type_permissions().Deny("edge_type_1", memgraph::auth::LabelPermission::READ);
|
||||
memgraph::glue::FineGrainedAuthChecker auth_checker{user};
|
||||
|
||||
ASSERT_FALSE(auth_checker.Accept(dba, r1));
|
||||
@ -159,8 +160,9 @@ TEST_F(FineGrainedAuthCheckerFixture, DenyEdgeType) {
|
||||
|
||||
TEST_F(FineGrainedAuthCheckerFixture, GrantAndDenySpecificEdgeTypes) {
|
||||
memgraph::auth::User user{"test"};
|
||||
user.fine_grained_access_handler().edge_type_permissions().Grant("edge_type_1");
|
||||
user.fine_grained_access_handler().edge_type_permissions().Deny("edge_type_2");
|
||||
user.fine_grained_access_handler().edge_type_permissions().Grant("edge_type_1",
|
||||
memgraph::auth::LabelPermission::CREATE_DELETE);
|
||||
user.fine_grained_access_handler().edge_type_permissions().Deny("edge_type_2", memgraph::auth::LabelPermission::READ);
|
||||
memgraph::glue::FineGrainedAuthChecker auth_checker{user};
|
||||
|
||||
ASSERT_TRUE(auth_checker.Accept(dba, r1));
|
||||
|
@ -427,9 +427,11 @@ TEST_F(ExpandFixture, ExpandWithEdgeFiltering) {
|
||||
|
||||
auto user = memgraph::auth::User("test");
|
||||
|
||||
user.fine_grained_access_handler().edge_type_permissions().Grant("Edge");
|
||||
user.fine_grained_access_handler().edge_type_permissions().Deny("edge_type_test");
|
||||
user.fine_grained_access_handler().label_permissions().Grant("*");
|
||||
user.fine_grained_access_handler().edge_type_permissions().Grant("Edge",
|
||||
memgraph::auth::LabelPermission::CREATE_DELETE);
|
||||
user.fine_grained_access_handler().edge_type_permissions().Deny("edge_type_test",
|
||||
memgraph::auth::LabelPermission::READ);
|
||||
user.fine_grained_access_handler().label_permissions().Grant("*", memgraph::auth::LabelPermission::CREATE_DELETE);
|
||||
memgraph::storage::EdgeTypeId edge_type_test{db.NameToEdgeType("edge_type_test")};
|
||||
|
||||
ASSERT_TRUE(dba.InsertEdge(&v1, &v2, edge_type_test).HasValue());
|
||||
@ -448,7 +450,8 @@ TEST_F(ExpandFixture, ExpandWithEdgeFiltering) {
|
||||
EXPECT_EQ(2, test_expand(user, EdgeAtom::Direction::IN, memgraph::storage::View::OLD));
|
||||
EXPECT_EQ(4, test_expand(user, EdgeAtom::Direction::BOTH, memgraph::storage::View::OLD));
|
||||
|
||||
user.fine_grained_access_handler().edge_type_permissions().Grant("edge_type_test");
|
||||
user.fine_grained_access_handler().edge_type_permissions().Grant("edge_type_test",
|
||||
memgraph::auth::LabelPermission::CREATE_DELETE);
|
||||
|
||||
EXPECT_EQ(4, test_expand(user, EdgeAtom::Direction::OUT, memgraph::storage::View::OLD));
|
||||
EXPECT_EQ(4, test_expand(user, EdgeAtom::Direction::IN, memgraph::storage::View::OLD));
|
||||
|
Loading…
Reference in New Issue
Block a user