diff --git a/src/auth/models.cpp b/src/auth/models.cpp index 2753b7df5..8485685dc 100644 --- a/src/auth/models.cpp +++ b/src/auth/models.cpp @@ -32,6 +32,7 @@ DEFINE_string(auth_password_strength_regex, default_password_regex.data(), namespace memgraph::auth { namespace { + // Constant list of all available permissions. const std::vector<Permission> kPermissionsAll = { Permission::MATCH, Permission::CREATE, Permission::MERGE, Permission::DELETE, @@ -208,7 +209,7 @@ FineGrainedAccessPermissions::FineGrainedAccessPermissions(const std::unordered_ : permissions_(permissions), global_permission_(global_permission) {} PermissionLevel FineGrainedAccessPermissions::Has(const std::string &permission, - const LabelPermission label_permission) const { + const FineGrainedPermission label_permission) const { const auto concrete_permission = std::invoke([&]() -> uint64_t { if (permissions_.contains(permission)) { return permissions_.at(permission); @@ -226,8 +227,8 @@ PermissionLevel FineGrainedAccessPermissions::Has(const std::string &permission, return temp_permission > 0 ? PermissionLevel::GRANT : PermissionLevel::DENY; } -void FineGrainedAccessPermissions::Grant(const std::string &permission, const LabelPermission label_permission) { - if (permission == ASTERISK) { +void FineGrainedAccessPermissions::Grant(const std::string &permission, const FineGrainedPermission label_permission) { + if (permission == kAsterisk) { global_permission_ = CalculateGrant(label_permission); } else { permissions_[permission] |= CalculateGrant(label_permission); @@ -235,7 +236,7 @@ void FineGrainedAccessPermissions::Grant(const std::string &permission, const La } void FineGrainedAccessPermissions::Revoke(const std::string &permission) { - if (permission == ASTERISK) { + if (permission == kAsterisk) { permissions_.clear(); global_permission_ = std::nullopt; } else { @@ -243,8 +244,8 @@ void FineGrainedAccessPermissions::Revoke(const std::string &permission) { } } -void FineGrainedAccessPermissions::Deny(const std::string &permission, const LabelPermission label_permission) { - if (permission == ASTERISK) { +void FineGrainedAccessPermissions::Deny(const std::string &permission, const FineGrainedPermission label_permission) { + if (permission == kAsterisk) { global_permission_ = CalculateDeny(label_permission); } else { permissions_[permission] = CalculateDeny(label_permission); @@ -279,7 +280,7 @@ const std::unordered_map<std::string, uint64_t> &FineGrainedAccessPermissions::G } const std::optional<uint64_t> &FineGrainedAccessPermissions::GetGlobalPermission() const { return global_permission_; }; -uint64_t FineGrainedAccessPermissions::CalculateGrant(LabelPermission label_permission) { +uint64_t FineGrainedAccessPermissions::CalculateGrant(FineGrainedPermission label_permission) { uint64_t shift{1}; uint64_t result{0}; auto uint_label_permission = static_cast<uint64_t>(label_permission); @@ -292,17 +293,17 @@ uint64_t FineGrainedAccessPermissions::CalculateGrant(LabelPermission label_perm return result; } -uint64_t FineGrainedAccessPermissions::CalculateDeny(LabelPermission label_permission) { +uint64_t FineGrainedAccessPermissions::CalculateDeny(FineGrainedPermission 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) { + while (uint_label_permission <= kLabelPermissionMax) { result |= uint_label_permission; uint_label_permission <<= shift; } - return LabelPermissionAll - result; + return kLabelPermissionAll - result; } bool operator==(const FineGrainedAccessPermissions &first, const FineGrainedAccessPermissions &second) { diff --git a/src/auth/models.hpp b/src/auth/models.hpp index 5556f4361..3a9ec3260 100644 --- a/src/auth/models.hpp +++ b/src/auth/models.hpp @@ -15,7 +15,7 @@ #include <json/json.hpp> namespace memgraph::auth { -const std::string ASTERISK = "*"; +const std::string kAsterisk = "*"; // These permissions must have values that are applicable for usage in a // bitmask. // clang-format off @@ -45,27 +45,30 @@ enum class Permission : uint64_t { // clang-format on // clang-format off -enum class LabelPermission : uint64_t { +enum class FineGrainedPermission : uint64_t { READ = 1, - EDIT = 1U << 1U, + UPDATE = 1U << 1U, CREATE_DELETE = 1U << 2U }; // clang-format on -constexpr inline uint64_t operator|(LabelPermission lhs, LabelPermission rhs) { +constexpr inline uint64_t operator|(FineGrainedPermission lhs, FineGrainedPermission 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, FineGrainedPermission rhs) { + return lhs | static_cast<uint64_t>(rhs); +} -constexpr inline uint64_t operator&(uint64_t lhs, LabelPermission rhs) { +constexpr inline uint64_t operator&(uint64_t lhs, FineGrainedPermission 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); +constexpr uint64_t kLabelPermissionAll = memgraph::auth::FineGrainedPermission::CREATE_DELETE | + memgraph::auth::FineGrainedPermission::UPDATE | + 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); // Function that converts a permission to its string representation. std::string PermissionToString(Permission permission); @@ -125,13 +128,13 @@ class FineGrainedAccessPermissions final { FineGrainedAccessPermissions &operator=(FineGrainedAccessPermissions &&) = default; ~FineGrainedAccessPermissions() = default; - PermissionLevel Has(const std::string &permission, LabelPermission label_permission) const; + PermissionLevel Has(const std::string &permission, FineGrainedPermission label_permission) const; - void Grant(const std::string &permission, LabelPermission label_permission); + void Grant(const std::string &permission, FineGrainedPermission label_permission); void Revoke(const std::string &permission); - void Deny(const std::string &permission, LabelPermission label_permission); + void Deny(const std::string &permission, FineGrainedPermission label_permission); nlohmann::json Serialize() const; @@ -145,8 +148,8 @@ class FineGrainedAccessPermissions final { 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); + static uint64_t CalculateGrant(FineGrainedPermission label_permission); + static uint64_t CalculateDeny(FineGrainedPermission label_permission); }; bool operator==(const FineGrainedAccessPermissions &first, const FineGrainedAccessPermissions &second); diff --git a/src/glue/auth.cpp b/src/glue/auth.cpp index 7f05d8045..f7ce72e0f 100644 --- a/src/glue/auth.cpp +++ b/src/glue/auth.cpp @@ -10,6 +10,7 @@ // licenses/APL.txt. #include "glue/auth.hpp" +#include "auth/models.hpp" namespace memgraph::glue { @@ -59,4 +60,16 @@ auth::Permission PrivilegeToPermission(query::AuthQuery::Privilege privilege) { return auth::Permission::WEBSOCKET; } } + +auth::FineGrainedPermission FineGrainedPrivilegeToFineGrainedPermission( + const query::AuthQuery::FineGrainedPrivilege fine_grained_privilege) { + switch (fine_grained_privilege) { + case query::AuthQuery::FineGrainedPrivilege::READ: + return auth::FineGrainedPermission::READ; + case query::AuthQuery::FineGrainedPrivilege::UPDATE: + return auth::FineGrainedPermission::UPDATE; + case query::AuthQuery::FineGrainedPrivilege::CREATE_DELETE: + return auth::FineGrainedPermission::CREATE_DELETE; + } +} } // namespace memgraph::glue diff --git a/src/glue/auth.hpp b/src/glue/auth.hpp index 96e8b4b44..50e4e70e0 100644 --- a/src/glue/auth.hpp +++ b/src/glue/auth.hpp @@ -20,4 +20,11 @@ namespace memgraph::glue { */ auth::Permission PrivilegeToPermission(query::AuthQuery::Privilege privilege); +/** + * Converts query::AuthQuery::FineGrainedPrivilege to its corresponding + * auth::EntityPermission. + */ +auth::FineGrainedPermission FineGrainedPrivilegeToFineGrainedPermission( + query::AuthQuery::FineGrainedPrivilege fine_grained_privilege); + } // namespace memgraph::glue diff --git a/src/glue/auth_checker.cpp b/src/glue/auth_checker.cpp index b29561289..ddc591c3b 100644 --- a/src/glue/auth_checker.cpp +++ b/src/glue/auth_checker.cpp @@ -21,15 +21,16 @@ 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::LabelPermission::READ) == memgraph::auth::PermissionLevel::GRANT; + return user.GetFineGrainedAccessLabelPermissions().Has(dba.LabelToName(label), + memgraph::auth::FineGrainedPermission::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), - memgraph::auth::LabelPermission::READ) == + memgraph::auth::FineGrainedPermission::READ) == memgraph::auth::PermissionLevel::GRANT; } } // namespace diff --git a/src/memgraph.cpp b/src/memgraph.cpp index b611186d0..b5ceff715 100644 --- a/src/memgraph.cpp +++ b/src/memgraph.cpp @@ -509,7 +509,10 @@ class AuthQueryHandler final : public memgraph::query::AuthQueryHandler { if (first_user) { spdlog::info("{} is first created user. Granting all privileges.", username); - GrantPrivilege(username, memgraph::query::kPrivilegesAll, {"*"}, {"*"}); + GrantPrivilege( + username, memgraph::query::kPrivilegesAll, + {{{memgraph::query::AuthQuery::FineGrainedPrivilege::CREATE_DELETE, {memgraph::auth::kAsterisk}}}}, + {{{memgraph::query::AuthQuery::FineGrainedPrivilege::CREATE_DELETE, {memgraph::auth::kAsterisk}}}}); } return user_added; @@ -754,59 +757,87 @@ 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> &edge_types) override { + void GrantPrivilege( + const std::string &user_or_role, const std::vector<memgraph::query::AuthQuery::Privilege> &privileges, + 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 { EditPermissions( - user_or_role, privileges, labels, edge_types, + user_or_role, privileges, label_privileges, edge_type_privileges, [](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); + [](auto &fine_grained_permissions, const auto &privilege_collection) { + for (const auto &[privilege, entities] : privilege_collection) { + const auto &permission = memgraph::glue::FineGrainedPrivilegeToFineGrainedPermission(privilege); + for (const auto &entity : entities) { + fine_grained_permissions.Grant(entity, permission); + } + } }); } - 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> &edge_types) override { + void DenyPrivilege( + const std::string &user_or_role, const std::vector<memgraph::query::AuthQuery::Privilege> &privileges, + 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 { EditPermissions( - user_or_role, privileges, labels, edge_types, + user_or_role, privileges, label_privileges, edge_type_privileges, [](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); + [](auto &fine_grained_permissions, const auto &privilege_collection) { + for (const auto &[privilege, entities] : privilege_collection) { + const auto &permission = memgraph::glue::FineGrainedPrivilegeToFineGrainedPermission(privilege); + for (const auto &entity : entities) { + fine_grained_permissions.Deny(entity, permission); + } + } }); } - 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> &edge_types) override { + void RevokePrivilege( + const std::string &user_or_role, const std::vector<memgraph::query::AuthQuery::Privilege> &privileges, + 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 { EditPermissions( - user_or_role, privileges, labels, edge_types, + user_or_role, privileges, label_privileges, edge_type_privileges, [](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); }); + [](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); + } + } + }); } private: 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 TEditPermissionsFun &edit_permissions_fun, - const TEditFineGrainedPermissionsFun &edit_fine_grained_permissions_fun) { + void EditPermissions( + const std::string &user_or_role, const std::vector<memgraph::query::AuthQuery::Privilege> &privileges, + 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) { if (!std::regex_match(user_or_role, name_regex_)) { throw memgraph::query::QueryRuntimeException("Invalid user or role name."); } @@ -826,11 +857,13 @@ class AuthQueryHandler final : public memgraph::query::AuthQueryHandler { for (const auto &permission : permissions) { edit_permissions_fun(user->permissions(), permission); } - for (const auto &label : labels) { - edit_fine_grained_permissions_fun(user->fine_grained_access_handler().label_permissions(), label); + 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 &edgeType : edgeTypes) { - edit_fine_grained_permissions_fun(user->fine_grained_access_handler().edge_type_permissions(), edgeType); + 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); } locked_auth->SaveUser(*user); @@ -838,11 +871,12 @@ class AuthQueryHandler final : public memgraph::query::AuthQueryHandler { for (const auto &permission : permissions) { edit_permissions_fun(role->permissions(), permission); } - for (const auto &label : labels) { - edit_fine_grained_permissions_fun(user->fine_grained_access_handler().label_permissions(), label); + for (const auto &label_privilege : label_privileges) { + edit_fine_grained_permissions_fun(user->fine_grained_access_handler().label_permissions(), label_privilege); } - for (const auto &edgeType : edgeTypes) { - edit_fine_grained_permissions_fun(role->fine_grained_access_handler().edge_type_permissions(), edgeType); + 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); } locked_auth->SaveRole(*role); diff --git a/src/query/frontend/ast/ast.lcp b/src/query/frontend/ast/ast.lcp index c88edb38d..99772a70f 100644 --- a/src/query/frontend/ast/ast.lcp +++ b/src/query/frontend/ast/ast.lcp @@ -2244,8 +2244,8 @@ cpp<# :slk-save #'slk-save-ast-pointer :slk-load (slk-load-ast-pointer "Expression")) (privileges "std::vector<Privilege>" :scope :public) - (labels "std::vector<std::string>" :scope :public) - (edge-types "std::vector<std::string>" :scope :public)) + (label-privileges "std::vector<std::unordered_map<FineGrainedPrivilege, std::vector<std::string>>>" :scope :public) + (edge-type-privileges "std::vector<std::unordered_map<FineGrainedPrivilege, std::vector<std::string>>>" :scope :public)) (:public (lcp:define-enum action (create-role drop-role show-roles create-user set-password drop-user @@ -2258,6 +2258,9 @@ cpp<# dump replication durability read_file free_memory trigger config stream module_read module_write websocket) (:serialize)) + (lcp:define-enum fine-grained-privilege + (read update create_delete) + (:serialize)) #>cpp AuthQuery() = default; @@ -2267,16 +2270,17 @@ cpp<# #>cpp AuthQuery(Action action, std::string user, std::string role, std::string user_or_role, Expression *password, - std::vector<Privilege> privileges, std::vector<std::string> labels, - std::vector<std::string> edge_types) + std::vector<Privilege> privileges, + std::vector<std::unordered_map<FineGrainedPrivilege, std::vector<std::string>>> label_privileges, + std::vector<std::unordered_map<FineGrainedPrivilege, std::vector<std::string>>> edge_type_privileges) : action_(action), user_(user), role_(role), user_or_role_(user_or_role), password_(password), privileges_(privileges), - labels_(labels), - edge_types_(edge_types) {} + label_privileges_(label_privileges), + edge_type_privileges_(edge_type_privileges) {} cpp<#) (:private #>cpp diff --git a/src/query/frontend/ast/cypher_main_visitor.cpp b/src/query/frontend/ast/cypher_main_visitor.cpp index c46e4efd4..dd589d7e4 100644 --- a/src/query/frontend/ast/cypher_main_visitor.cpp +++ b/src/query/frontend/ast/cypher_main_visitor.cpp @@ -45,6 +45,8 @@ namespace memgraph::query::frontend { const std::string CypherMainVisitor::kAnonPrefix = "anon"; namespace { +enum class EntityType : uint8_t { LABELS, EDGE_TYPES }; + template <typename TVisitor> std::optional<std::pair<memgraph::query::Expression *, size_t>> VisitMemoryLimit( MemgraphCypher::MemoryLimitContext *memory_limit_ctx, TVisitor *visitor) { @@ -1269,17 +1271,6 @@ antlrcpp::Any CypherMainVisitor::visitClearRole(MemgraphCypher::ClearRoleContext return auth; } -void CypherMainVisitor::extractPrivilege(AuthQuery *auth, - antlropencypher::MemgraphCypher::PrivilegeContext *privilege) { - if (privilege->EDGE_TYPES()) { - auth->edge_types_ = std::any_cast<std::vector<std::string>>(privilege->edgeTypeList()->accept(this)); - } else if (privilege->LABELS()) { - auth->labels_ = std::any_cast<std::vector<std::string>>(privilege->labelList()->accept(this)); - } else { - auth->privileges_.push_back(std::any_cast<AuthQuery::Privilege>(privilege->accept(this))); - } -} - /** * @return AuthQuery* */ @@ -1287,10 +1278,14 @@ antlrcpp::Any CypherMainVisitor::visitGrantPrivilege(MemgraphCypher::GrantPrivil AuthQuery *auth = storage_->Create<AuthQuery>(); auth->action_ = AuthQuery::Action::GRANT_PRIVILEGE; auth->user_or_role_ = std::any_cast<std::string>(ctx->userOrRole->accept(this)); - if (ctx->privilegeList()) { - for (auto *privilege : ctx->privilegeList()->privilege()) { - extractPrivilege(auth, privilege); - } + if (ctx->privilegesList()) { + const auto [label_privileges, edge_type_privileges, privileges] = std::any_cast< + std::tuple<std::vector<std::unordered_map<AuthQuery::FineGrainedPrivilege, std::vector<std::string>>>, + std::vector<std::unordered_map<AuthQuery::FineGrainedPrivilege, std::vector<std::string>>>, + std::vector<memgraph::query::AuthQuery::Privilege>>>(ctx->privilegesList()->accept(this)); + auth->label_privileges_ = label_privileges; + auth->edge_type_privileges_ = edge_type_privileges; + auth->privileges_ = privileges; } else { /* grant all privileges */ auth->privileges_ = kPrivilegesAll; @@ -1305,10 +1300,11 @@ antlrcpp::Any CypherMainVisitor::visitDenyPrivilege(MemgraphCypher::DenyPrivileg AuthQuery *auth = storage_->Create<AuthQuery>(); auth->action_ = AuthQuery::Action::DENY_PRIVILEGE; auth->user_or_role_ = std::any_cast<std::string>(ctx->userOrRole->accept(this)); - if (ctx->privilegeList()) { - for (auto *privilege : ctx->privilegeList()->privilege()) { - extractPrivilege(auth, privilege); - } + if (ctx->privilegesList()) { + std::tie(auth->label_privileges_, auth->edge_type_privileges_, auth->privileges_) = std::any_cast< + std::tuple<std::vector<std::unordered_map<AuthQuery::FineGrainedPrivilege, std::vector<std::string>>>, + std::vector<std::unordered_map<AuthQuery::FineGrainedPrivilege, std::vector<std::string>>>, + std::vector<memgraph::query::AuthQuery::Privilege>>>(ctx->privilegesList()->accept(this)); } else { /* deny all privileges */ auth->privileges_ = kPrivilegesAll; @@ -1316,6 +1312,38 @@ antlrcpp::Any CypherMainVisitor::visitDenyPrivilege(MemgraphCypher::DenyPrivileg return auth; } +/** + * @return std::tuple<std::vector<std::unordered_map<AuthQuery::FineGrainedPrivilege, std::vector<std::string>>>, + std::vector<std::unordered_map<AuthQuery::FineGrainedPrivilege, std::vector<std::string>>>, + std::vector<memgraph::query::AuthQuery::Privilege>> + */ +antlrcpp::Any CypherMainVisitor::visitPrivilegesList(MemgraphCypher::PrivilegesListContext *ctx) { + std::vector<std::unordered_map<AuthQuery::FineGrainedPrivilege, std::vector<std::string>>> label_privileges; + std::vector<std::unordered_map<AuthQuery::FineGrainedPrivilege, std::vector<std::string>>> edge_type_privileges; + std::vector<memgraph::query::AuthQuery::Privilege> privileges; + for (auto *it : ctx->privilegeOrEntityPrivileges()) { + if (it->entityPrivilegeList()) { + const auto result = + std::any_cast<std::pair<std::unordered_map<AuthQuery::FineGrainedPrivilege, std::vector<std::string>>, + std::unordered_map<AuthQuery::FineGrainedPrivilege, std::vector<std::string>>>>( + it->entityPrivilegeList()->accept(this)); + if (!result.first.empty()) { + label_privileges.emplace_back(result.first); + } + if (!result.second.empty()) { + edge_type_privileges.emplace_back(result.second); + } + } else { + privileges.push_back(std::any_cast<AuthQuery::Privilege>(it->privilege()->accept(this))); + } + } + + return std::tuple<std::vector<std::unordered_map<AuthQuery::FineGrainedPrivilege, std::vector<std::string>>>, + std::vector<std::unordered_map<AuthQuery::FineGrainedPrivilege, std::vector<std::string>>>, + std::vector<memgraph::query::AuthQuery::Privilege>>(label_privileges, edge_type_privileges, + privileges); +} + /** * @return AuthQuery* */ @@ -1323,9 +1351,22 @@ antlrcpp::Any CypherMainVisitor::visitRevokePrivilege(MemgraphCypher::RevokePriv AuthQuery *auth = storage_->Create<AuthQuery>(); auth->action_ = AuthQuery::Action::REVOKE_PRIVILEGE; auth->user_or_role_ = std::any_cast<std::string>(ctx->userOrRole->accept(this)); - if (ctx->privilegeList()) { - for (auto *privilege : ctx->privilegeList()->privilege()) { - extractPrivilege(auth, privilege); + if (ctx->revokePrivilegesList()) { + for (auto *it : ctx->revokePrivilegesList()->privilegeOrEntities()) { + if (it->entitiesList()) { + const auto entity_type = std::any_cast<EntityType>(it->entityType()->accept(this)); + if (entity_type == EntityType::LABELS) { + auth->label_privileges_.push_back( + {{AuthQuery::FineGrainedPrivilege::CREATE_DELETE, + std::any_cast<std::vector<std::string>>(it->entitiesList()->accept(this))}}); + } else { + auth->edge_type_privileges_.push_back( + {{AuthQuery::FineGrainedPrivilege::CREATE_DELETE, + std::any_cast<std::vector<std::string>>(it->entitiesList()->accept(this))}}); + } + } else { + auth->privileges_.push_back(std::any_cast<AuthQuery::Privilege>(it->privilege()->accept(this))); + } } } else { /* revoke all privileges */ @@ -1334,33 +1375,46 @@ antlrcpp::Any CypherMainVisitor::visitRevokePrivilege(MemgraphCypher::RevokePriv return auth; } -antlrcpp::Any CypherMainVisitor::visitLabelList(MemgraphCypher::LabelListContext *ctx) { - std::vector<std::string> labels; - if (ctx->listOfLabels()) { - for (auto *label : ctx->listOfLabels()->label()) { - labels.push_back(std::any_cast<std::string>(label->symbolicName()->accept(this))); - } - } else { - labels.emplace_back("*"); - } +/** + * @return std::pair<std::unordered_map<AuthQuery::FineGrainedPrivilege, std::vector<std::string>>, + std::unordered_map<AuthQuery::FineGrainedPrivilege, std::vector<std::string>>> + */ +antlrcpp::Any CypherMainVisitor::visitEntityPrivilegeList(MemgraphCypher::EntityPrivilegeListContext *ctx) { + std::pair<std::unordered_map<AuthQuery::FineGrainedPrivilege, std::vector<std::string>>, + std::unordered_map<AuthQuery::FineGrainedPrivilege, std::vector<std::string>>> + result; - return labels; + for (auto *it : ctx->entityPrivilege()) { + const auto key = std::any_cast<AuthQuery::FineGrainedPrivilege>(it->granularPrivilege()->accept(this)); + const auto entityType = std::any_cast<EntityType>(it->entityType()->accept(this)); + auto value = std::any_cast<std::vector<std::string>>(it->entitiesList()->accept(this)); + + switch (entityType) { + case EntityType::LABELS: + result.first[key] = std::move(value); + break; + case EntityType::EDGE_TYPES: + result.second[key] = std::move(value); + break; + } + } + return result; } /** - * @return AuthQuery* + * @return std::vector<std::string> */ -antlrcpp::Any CypherMainVisitor::visitEdgeTypeList(MemgraphCypher::EdgeTypeListContext *ctx) { - std::vector<std::string> edgeTypes; - if (ctx->listOfEdgeTypes()) { - for (auto *edgeType : ctx->listOfEdgeTypes()->edgeType()) { - edgeTypes.push_back(std::any_cast<std::string>(edgeType->symbolicName()->accept(this))); +antlrcpp::Any CypherMainVisitor::visitEntitiesList(MemgraphCypher::EntitiesListContext *ctx) { + std::vector<std::string> entities; + if (ctx->listOfEntities()) { + for (auto *entity : ctx->listOfEntities()->entity()) { + entities.push_back(std::any_cast<std::string>(entity->symbolicName()->accept(this))); } } else { - edgeTypes.emplace_back("*"); + entities.emplace_back("*"); } - return edgeTypes; + return entities; } /** @@ -1391,6 +1445,25 @@ antlrcpp::Any CypherMainVisitor::visitPrivilege(MemgraphCypher::PrivilegeContext LOG_FATAL("Should not get here - unknown privilege!"); } +/** + * @return AuthQuery::FineGrainedPrivilege + */ +antlrcpp::Any CypherMainVisitor::visitGranularPrivilege(MemgraphCypher::GranularPrivilegeContext *ctx) { + if (ctx->READ()) return AuthQuery::FineGrainedPrivilege::READ; + if (ctx->UPDATE()) return AuthQuery::FineGrainedPrivilege::UPDATE; + if (ctx->CREATE_DELETE()) return AuthQuery::FineGrainedPrivilege::CREATE_DELETE; + LOG_FATAL("Should not get here - unknown label privilege!"); +} + +/** + * @return EntityType + */ +antlrcpp::Any CypherMainVisitor::visitEntityType(MemgraphCypher::EntityTypeContext *ctx) { + if (ctx->LABELS()) return EntityType::LABELS; + if (ctx->EDGE_TYPES()) return EntityType::EDGE_TYPES; + LOG_FATAL("Should not get here - unknown entity type!"); +} + /** * @return AuthQuery* */ @@ -2166,8 +2239,8 @@ antlrcpp::Any CypherMainVisitor::visitFunctionInvocation(MemgraphCypher::Functio } auto is_user_defined_function = [](const std::string &function_name) { - // Dots are present only in user-defined functions, since modules are case-sensitive, so must be user-defined - // functions. Builtin functions should be case insensitive. + // Dots are present only in user-defined functions, since modules are case-sensitive, so must be + // user-defined functions. Builtin functions should be case insensitive. return function_name.find('.') != std::string::npos; }; @@ -2183,8 +2256,8 @@ antlrcpp::Any CypherMainVisitor::visitFunctionInvocation(MemgraphCypher::Functio antlrcpp::Any CypherMainVisitor::visitFunctionName(MemgraphCypher::FunctionNameContext *ctx) { auto function_name = ctx->getText(); - // Dots are present only in user-defined functions, since modules are case-sensitive, so must be user-defined - // functions. Builtin functions should be case insensitive. + // Dots are present only in user-defined functions, since modules are case-sensitive, so must be + // user-defined functions. Builtin functions should be case insensitive. if (function_name.find('.') != std::string::npos) { return function_name; } diff --git a/src/query/frontend/ast/cypher_main_visitor.hpp b/src/query/frontend/ast/cypher_main_visitor.hpp index 7ee4d0552..542b90801 100644 --- a/src/query/frontend/ast/cypher_main_visitor.hpp +++ b/src/query/frontend/ast/cypher_main_visitor.hpp @@ -468,12 +468,33 @@ class CypherMainVisitor : public antlropencypher::MemgraphCypherBaseVisitor { /** * @return AuthQuery* */ - antlrcpp::Any visitRevokePrivilege(MemgraphCypher::RevokePrivilegeContext *ctx) override; + antlrcpp::Any visitPrivilegesList(MemgraphCypher::PrivilegesListContext *ctx) override; /** * @return AuthQuery* */ - antlrcpp::Any visitEdgeTypeList(MemgraphCypher::EdgeTypeListContext *ctx) override; + antlrcpp::Any visitRevokePrivilege(MemgraphCypher::RevokePrivilegeContext *ctx) override; + + /** + * @return std::pair<std::unordered_map<AuthQuery::FineGrainedPrivilege, std::vector<std::string>>, + std::unordered_map<AuthQuery::FineGrainedPrivilege, std::vector<std::string>>> + */ + antlrcpp::Any visitEntityPrivilegeList(MemgraphCypher::EntityPrivilegeListContext *ctx) override; + + /** + * @return std::vector<std::string> + */ + antlrcpp::Any visitEntitiesList(MemgraphCypher::EntitiesListContext *ctx) override; + + /** + * @return AuthQuery::FineGrainedPrivilege + */ + antlrcpp::Any visitGranularPrivilege(MemgraphCypher::GranularPrivilegeContext *ctx) override; + + /** + * @return std::string + */ + antlrcpp::Any visitEntityType(MemgraphCypher::EntityTypeContext *ctx) override; /** * @return AuthQuery::Privilege @@ -485,11 +506,6 @@ class CypherMainVisitor : public antlropencypher::MemgraphCypherBaseVisitor { */ antlrcpp::Any visitShowPrivileges(MemgraphCypher::ShowPrivilegesContext *ctx) override; - /** - * @return AuthQuery::LabelList - */ - antlrcpp::Any visitLabelList(MemgraphCypher::LabelListContext *ctx) override; - /** * @return AuthQuery* */ diff --git a/src/query/frontend/opencypher/grammar/MemgraphCypher.g4 b/src/query/frontend/opencypher/grammar/MemgraphCypher.g4 index 3f5b70c7b..f5da954ba 100644 --- a/src/query/frontend/opencypher/grammar/MemgraphCypher.g4 +++ b/src/query/frontend/opencypher/grammar/MemgraphCypher.g4 @@ -37,6 +37,7 @@ memgraphCypherKeyword : cypherKeyword | CONFIG | CONFIGS | CONSUMER_GROUP + | CREATE_DELETE | CREDENTIALS | CSV | DATA @@ -229,11 +230,11 @@ setRole : SET ROLE FOR user=userOrRoleName TO role=userOrRoleName; clearRole : CLEAR ROLE FOR user=userOrRoleName ; -grantPrivilege : GRANT ( ALL PRIVILEGES | privileges=privilegeList ) TO userOrRole=userOrRoleName ; +grantPrivilege : GRANT ( ALL PRIVILEGES | privileges=privilegesList ) TO userOrRole=userOrRoleName ; -denyPrivilege : DENY ( ALL PRIVILEGES | privileges=privilegeList ) TO userOrRole=userOrRoleName ; +denyPrivilege : DENY ( ALL PRIVILEGES | privileges=privilegesList ) TO userOrRole=userOrRoleName ; -revokePrivilege : REVOKE ( ALL PRIVILEGES | privileges=privilegeList ) FROM userOrRole=userOrRoleName ; +revokePrivilege : REVOKE ( ALL PRIVILEGES | privileges=revokePrivilegesList ) FROM userOrRole=userOrRoleName ; privilege : CREATE | DELETE @@ -256,23 +257,29 @@ privilege : CREATE | MODULE_READ | MODULE_WRITE | WEBSOCKET - | EDGE_TYPES edgeTypes=edgeTypeList - | LABELS labels=labelList ; -privilegeList : privilege ( ',' privilege )* ; +granularPrivilege : READ | UPDATE | CREATE_DELETE ; -edgeTypeList : '*' | listOfEdgeTypes ; +entityType : LABELS | EDGE_TYPES ; -listOfEdgeTypes : edgeType ( ',' edgeType )* ; +privilegeOrEntityPrivileges : privilege | entityPrivileges=entityPrivilegeList ; -edgeType : COLON symbolicName ; +privilegesList : privilegeOrEntityPrivileges ( ',' privilegeOrEntityPrivileges )* ; -labelList : '*' | listOfLabels ; +entityPrivilegeList : entityPrivilege ( ',' entityPrivilege )* ; -listOfLabels : label ( ',' label )* ; +entityPrivilege : granularPrivilege ON entityType entities=entitiesList ; -label : COLON symbolicName ; +privilegeOrEntities : privilege | entityType entities=entitiesList ; + +revokePrivilegesList : privilegeOrEntities ( ',' privilegeOrEntities )* ; + +entitiesList : ASTERISK | listOfEntities ; + +listOfEntities : entity ( ',' entity )* ; + +entity : COLON symbolicName ; showPrivileges : SHOW PRIVILEGES FOR userOrRole=userOrRoleName ; diff --git a/src/query/frontend/opencypher/grammar/MemgraphCypherLexer.g4 b/src/query/frontend/opencypher/grammar/MemgraphCypherLexer.g4 index 35b94d9db..acbbcc08e 100644 --- a/src/query/frontend/opencypher/grammar/MemgraphCypherLexer.g4 +++ b/src/query/frontend/opencypher/grammar/MemgraphCypherLexer.g4 @@ -42,6 +42,7 @@ COMMITTED : C O M M I T T E D ; CONFIG : C O N F I G ; CONFIGS : C O N F I G S; CONSUMER_GROUP : C O N S U M E R UNDERSCORE G R O U P ; +CREATE_DELETE : C R E A T E UNDERSCORE D E L E T E ; CREDENTIALS : C R E D E N T I A L S ; CSV : C S V ; DATA : D A T A ; diff --git a/src/query/interpreter.cpp b/src/query/interpreter.cpp index 93c89f12e..4ece1d73e 100644 --- a/src/query/interpreter.cpp +++ b/src/query/interpreter.cpp @@ -20,7 +20,9 @@ #include <functional> #include <limits> #include <optional> +#include <unordered_map> +#include "auth/models.hpp" #include "glue/communication.hpp" #include "memory/memory_control.hpp" #include "query/constants.hpp" @@ -283,8 +285,10 @@ 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_; - std::vector<std::string> edgeTypes = auth_query->edge_types_; - std::vector<std::string> labels = auth_query->labels_; + 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_; auto password = EvaluateOptionalExpression(auth_query->password_, &evaluator); Callback callback; @@ -314,7 +318,9 @@ 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, + {{{AuthQuery::FineGrainedPrivilege::CREATE_DELETE, {auth::kAsterisk}}}}, + {{{AuthQuery::FineGrainedPrivilege::CREATE_DELETE, {auth::kAsterisk}}}}); } return std::vector<std::vector<TypedValue>>(); @@ -389,20 +395,20 @@ Callback HandleAuthQuery(AuthQuery *auth_query, AuthQueryHandler *auth, const Pa }; return callback; case AuthQuery::Action::GRANT_PRIVILEGE: - callback.fn = [auth, user_or_role, privileges, labels, edgeTypes] { - auth->GrantPrivilege(user_or_role, privileges, labels, edgeTypes); + callback.fn = [auth, user_or_role, privileges, label_privileges, edge_type_privileges] { + auth->GrantPrivilege(user_or_role, privileges, label_privileges, edge_type_privileges); return std::vector<std::vector<TypedValue>>(); }; return callback; case AuthQuery::Action::DENY_PRIVILEGE: - callback.fn = [auth, user_or_role, privileges, labels, edgeTypes] { - auth->DenyPrivilege(user_or_role, privileges, labels, edgeTypes); + callback.fn = [auth, user_or_role, privileges, label_privileges, edge_type_privileges] { + auth->DenyPrivilege(user_or_role, privileges, label_privileges, edge_type_privileges); return std::vector<std::vector<TypedValue>>(); }; return callback; case AuthQuery::Action::REVOKE_PRIVILEGE: { - callback.fn = [auth, user_or_role, privileges, labels, edgeTypes] { - auth->RevokePrivilege(user_or_role, privileges, labels, edgeTypes); + callback.fn = [auth, user_or_role, privileges, label_privileges, edge_type_privileges] { + auth->RevokePrivilege(user_or_role, privileges, label_privileges, edge_type_privileges); return std::vector<std::vector<TypedValue>>(); }; return callback; diff --git a/src/query/interpreter.hpp b/src/query/interpreter.hpp index efe37ba34..81c37d812 100644 --- a/src/query/interpreter.hpp +++ b/src/query/interpreter.hpp @@ -99,16 +99,28 @@ class AuthQueryHandler { virtual std::vector<std::vector<TypedValue>> GetPrivileges(const std::string &user_or_role) = 0; /// @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::string> &labels, const std::vector<std::string> &edgeTypes) = 0; + 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>>> + &label_privileges, + const std::vector<std::unordered_map<AuthQuery::FineGrainedPrivilege, std::vector<std::string>>> + &edge_type_privileges) = 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::string> &labels, const std::vector<std::string> &edgeTypes) = 0; + 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>>> + &label_privileges, + const std::vector<std::unordered_map<AuthQuery::FineGrainedPrivilege, std::vector<std::string>>> + &edge_type_privileges) = 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::string> &labels, const std::vector<std::string> &edgeTypes) = 0; + 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>>> + &label_privileges, + const std::vector<std::unordered_map<AuthQuery::FineGrainedPrivilege, std::vector<std::string>>> + &edge_type_privileges) = 0; }; enum class QueryHandlerResult { COMMIT, ABORT, NOTHING }; diff --git a/tests/e2e/fine_grained_access/edge_type_filtering_tests.py b/tests/e2e/fine_grained_access/edge_type_filtering_tests.py index 8e9a04196..e2f0003d0 100644 --- a/tests/e2e/fine_grained_access/edge_type_filtering_tests.py +++ b/tests/e2e/fine_grained_access/edge_type_filtering_tests.py @@ -6,20 +6,42 @@ import pytest def test_all_edge_types_all_labels_granted(): admin_connection = common.connect(username="admin", password="test") user_connnection = common.connect(username="user", password="test") - common.execute_and_fetch_all(admin_connection.cursor(), "GRANT LABELS * TO user;") - common.execute_and_fetch_all(admin_connection.cursor(), "GRANT EDGE_TYPES * TO user;") + common.execute_and_fetch_all(admin_connection.cursor(), "GRANT READ ON LABELS * TO user;") + common.execute_and_fetch_all(admin_connection.cursor(), "GRANT READ ON EDGE_TYPES * TO user;") results = common.execute_and_fetch_all(user_connnection.cursor(), "MATCH (n)-[r]->(m) RETURN n,r,m;") assert len(results) == 3 +def test_deny_all_edge_types_and_all_labels(): + admin_connection = common.connect(username="admin", password="test") + user_connnection = common.connect(username="user", password="test") + common.execute_and_fetch_all(admin_connection.cursor(), "DENY READ ON LABELS * TO user;") + common.execute_and_fetch_all(admin_connection.cursor(), "DENY READ ON EDGE_TYPES * TO user;") + + results = common.execute_and_fetch_all(user_connnection.cursor(), "MATCH (n)-[r]->(m) RETURN n,r,m;") + + assert len(results) == 0 + + +def test_revoke_all_edge_types_and_all_labels(): + admin_connection = common.connect(username="admin", password="test") + user_connnection = common.connect(username="user", password="test") + common.execute_and_fetch_all(admin_connection.cursor(), "REVOKE LABELS * FROM user;") + common.execute_and_fetch_all(admin_connection.cursor(), "REVOKE EDGE_TYPES * FROM user;") + + results = common.execute_and_fetch_all(user_connnection.cursor(), "MATCH (n)-[r]->(m) RETURN n,r,m;") + + assert len(results) == 0 + + def test_deny_edge_type(): admin_connection = common.connect(username="admin", password="test") user_connnection = common.connect(username="user", password="test") - common.execute_and_fetch_all(admin_connection.cursor(), "GRANT LABELS :label1, :label2, :label3 TO user;") - common.execute_and_fetch_all(admin_connection.cursor(), "GRANT EDGE_TYPES :edgeType2 TO user;") - common.execute_and_fetch_all(admin_connection.cursor(), "DENY EDGE_TYPES :edgeType1 TO user;") + common.execute_and_fetch_all(admin_connection.cursor(), "GRANT READ ON LABELS :label1, :label2, :label3 TO user;") + common.execute_and_fetch_all(admin_connection.cursor(), "GRANT READ ON EDGE_TYPES :edgeType2 TO user;") + common.execute_and_fetch_all(admin_connection.cursor(), "DENY READ ON EDGE_TYPES :edgeType1 TO user;") results = common.execute_and_fetch_all(user_connnection.cursor(), "MATCH (n)-[r]->(m) RETURN n,r,m;") @@ -29,9 +51,9 @@ def test_deny_edge_type(): def test_denied_node_label(): admin_connection = common.connect(username="admin", password="test") user_connnection = common.connect(username="user", password="test") - common.execute_and_fetch_all(admin_connection.cursor(), "GRANT LABELS :label1,:label3 TO user;") - common.execute_and_fetch_all(admin_connection.cursor(), "GRANT EDGE_TYPES :edgeType1, :edgeType2 TO user;") - common.execute_and_fetch_all(admin_connection.cursor(), "DENY LABELS :label2 TO user;") + common.execute_and_fetch_all(admin_connection.cursor(), "GRANT READ ON LABELS :label1,:label3 TO user;") + common.execute_and_fetch_all(admin_connection.cursor(), "GRANT READ ON EDGE_TYPES :edgeType1, :edgeType2 TO user;") + common.execute_and_fetch_all(admin_connection.cursor(), "DENY READ ON LABELS :label2 TO user;") results = common.execute_and_fetch_all(user_connnection.cursor(), "MATCH (n)-[r]->(m) RETURN n,r,m;") @@ -41,9 +63,9 @@ def test_denied_node_label(): def test_denied_one_of_node_label(): admin_connection = common.connect(username="admin", password="test") user_connnection = common.connect(username="user", password="test") - common.execute_and_fetch_all(admin_connection.cursor(), "GRANT LABELS :label1,:label2 TO user;") - common.execute_and_fetch_all(admin_connection.cursor(), "GRANT EDGE_TYPES :edgeType1, :edgeType2 TO user;") - common.execute_and_fetch_all(admin_connection.cursor(), "DENY LABELS :label3 TO user;") + common.execute_and_fetch_all(admin_connection.cursor(), "GRANT READ ON LABELS :label1,:label2 TO user;") + common.execute_and_fetch_all(admin_connection.cursor(), "GRANT READ ON EDGE_TYPES :edgeType1, :edgeType2 TO user;") + common.execute_and_fetch_all(admin_connection.cursor(), "DENY READ ON LABELS :label3 TO user;") results = common.execute_and_fetch_all(user_connnection.cursor(), "MATCH (n)-[r]->(m) RETURN n,r,m;") diff --git a/tests/e2e/lba_procedures/workloads.yaml b/tests/e2e/lba_procedures/workloads.yaml index 24cda0629..046a28397 100644 --- a/tests/e2e/lba_procedures/workloads.yaml +++ b/tests/e2e/lba_procedures/workloads.yaml @@ -16,7 +16,7 @@ template_cluster: &template_cluster "Create (:Label2 {id: 4}) ;", "Create User Josip ;", "Create User Boris ;", - "Grant Labels :Label1 to Boris;", + "Grant Read On Labels :Label1 to Boris;", ] validation_queries: [] diff --git a/tests/unit/auth.cpp b/tests/unit/auth.cpp index 49cb72d1a..c50d78dfc 100644 --- a/tests/unit/auth.cpp +++ b/tests/unit/auth.cpp @@ -177,29 +177,32 @@ TEST_F(AuthWithStorage, UserRoleFineGrainedAccessHandler) { user->GetFineGrainedAccessEdgeTypePermissions()); // Grant one label to user . - user->fine_grained_access_handler().label_permissions().Grant("labelTest", LabelPermission::CREATE_DELETE); + user->fine_grained_access_handler().label_permissions().Grant("labelTest", FineGrainedPermission::CREATE_DELETE); // Grant one edge type to user . - user->fine_grained_access_handler().edge_type_permissions().Grant("edgeTypeTest", LabelPermission::CREATE_DELETE); + user->fine_grained_access_handler().edge_type_permissions().Grant("edgeTypeTest", + FineGrainedPermission::CREATE_DELETE); // Check permissions. - 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), + ASSERT_EQ(user->fine_grained_access_handler().label_permissions().Has("labelTest", FineGrainedPermission::READ), PermissionLevel::GRANT); + ASSERT_EQ( + user->fine_grained_access_handler().edge_type_permissions().Has("edgeTypeTest", FineGrainedPermission::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", LabelPermission::READ); + user->fine_grained_access_handler().label_permissions().Deny("labelTest1", FineGrainedPermission::READ); // Deny one edge type to user . - user->fine_grained_access_handler().edge_type_permissions().Deny("edgeTypeTest1", LabelPermission::READ); + user->fine_grained_access_handler().edge_type_permissions().Deny("edgeTypeTest1", FineGrainedPermission::READ); // Check permissions. - 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), + ASSERT_EQ(user->fine_grained_access_handler().label_permissions().Has("labelTest1", FineGrainedPermission::READ), PermissionLevel::DENY); + ASSERT_EQ( + user->fine_grained_access_handler().edge_type_permissions().Has("edgeTypeTest1", FineGrainedPermission::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()); @@ -210,28 +213,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", LabelPermission::CREATE_DELETE); - role->fine_grained_access_handler().edge_type_permissions().Grant("roleEdgeTypeTest", LabelPermission::CREATE_DELETE); + role->fine_grained_access_handler().label_permissions().Grant("roleLabelTest", FineGrainedPermission::CREATE_DELETE); + role->fine_grained_access_handler().edge_type_permissions().Grant("roleEdgeTypeTest", + FineGrainedPermission::CREATE_DELETE); user->SetRole(*role); // Check permissions. { - ASSERT_EQ(user->GetFineGrainedAccessLabelPermissions().Has("roleLabelTest", LabelPermission::READ), + ASSERT_EQ(user->GetFineGrainedAccessLabelPermissions().Has("roleLabelTest", FineGrainedPermission::READ), PermissionLevel::GRANT); - ASSERT_EQ(user->GetFineGrainedAccessEdgeTypePermissions().Has("roleEdgeTypeTest", LabelPermission::READ), + ASSERT_EQ(user->GetFineGrainedAccessEdgeTypePermissions().Has("roleEdgeTypeTest", FineGrainedPermission::READ), PermissionLevel::GRANT); } // Deny label and edge type to role and role to user. - role->fine_grained_access_handler().label_permissions().Deny("roleLabelTest1", LabelPermission::READ); - role->fine_grained_access_handler().edge_type_permissions().Deny("roleEdgeTypeTest1", LabelPermission::READ); + role->fine_grained_access_handler().label_permissions().Deny("roleLabelTest1", FineGrainedPermission::READ); + role->fine_grained_access_handler().edge_type_permissions().Deny("roleEdgeTypeTest1", FineGrainedPermission::READ); user->SetRole(*role); // Check permissions. { - ASSERT_EQ(user->GetFineGrainedAccessLabelPermissions().Has("roleLabelTest1", LabelPermission::READ), + ASSERT_EQ(user->GetFineGrainedAccessLabelPermissions().Has("roleLabelTest1", FineGrainedPermission::READ), PermissionLevel::DENY); - ASSERT_EQ(user->GetFineGrainedAccessEdgeTypePermissions().Has("roleEdgeTypeTest1", LabelPermission::READ), + ASSERT_EQ(user->GetFineGrainedAccessEdgeTypePermissions().Has("roleEdgeTypeTest1", FineGrainedPermission::READ), PermissionLevel::DENY); } } @@ -500,14 +504,14 @@ TEST(AuthWithoutStorage, FineGrainedAccessPermissions) { 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); + ASSERT_EQ(fga_permissions.Has(any_label, FineGrainedPermission::CREATE_DELETE), PermissionLevel::DENY); + ASSERT_EQ(fga_permissions.Has(any_label, FineGrainedPermission::UPDATE), PermissionLevel::DENY); + ASSERT_EQ(fga_permissions.Has(any_label, FineGrainedPermission::READ), PermissionLevel::DENY); } { FineGrainedAccessPermissions fga_permissions; - fga_permissions.Grant(any_label, LabelPermission::CREATE_DELETE); + fga_permissions.Grant(any_label, FineGrainedPermission::CREATE_DELETE); ASSERT_EQ(fga_permissions.GetGlobalPermission(), std::nullopt); ASSERT_FALSE(fga_permissions.GetPermissions().empty()); @@ -515,7 +519,7 @@ TEST(AuthWithoutStorage, FineGrainedAccessPermissions) { { FineGrainedAccessPermissions fga_permissions; - fga_permissions.Deny(any_label, LabelPermission::CREATE_DELETE); + fga_permissions.Deny(any_label, FineGrainedPermission::CREATE_DELETE); ASSERT_EQ(fga_permissions.GetGlobalPermission(), std::nullopt); ASSERT_FALSE(fga_permissions.GetPermissions().empty()); @@ -523,25 +527,25 @@ TEST(AuthWithoutStorage, FineGrainedAccessPermissions) { { FineGrainedAccessPermissions fga_permissions; - fga_permissions.Grant(asterisk, LabelPermission::CREATE_DELETE); - fga_permissions.Deny(any_label, LabelPermission::CREATE_DELETE); + fga_permissions.Grant(asterisk, FineGrainedPermission::CREATE_DELETE); + fga_permissions.Deny(any_label, FineGrainedPermission::CREATE_DELETE); - ASSERT_EQ(fga_permissions.GetGlobalPermission(), LabelPermissionAll); + ASSERT_EQ(fga_permissions.GetGlobalPermission(), kLabelPermissionAll); ASSERT_FALSE(fga_permissions.GetPermissions().empty()); } { FineGrainedAccessPermissions fga_permissions; - fga_permissions.Grant(asterisk, LabelPermission::CREATE_DELETE); + fga_permissions.Grant(asterisk, FineGrainedPermission::CREATE_DELETE); fga_permissions.Revoke(any_label); - ASSERT_EQ(fga_permissions.GetGlobalPermission(), LabelPermissionAll); + ASSERT_EQ(fga_permissions.GetGlobalPermission(), kLabelPermissionAll); ASSERT_TRUE(fga_permissions.GetPermissions().empty()); } { FineGrainedAccessPermissions fga_permissions; - fga_permissions.Grant(any_label, LabelPermission::CREATE_DELETE); + fga_permissions.Grant(any_label, FineGrainedPermission::CREATE_DELETE); fga_permissions.Revoke(any_label); ASSERT_EQ(fga_permissions.GetGlobalPermission(), std::nullopt); @@ -550,7 +554,7 @@ TEST(AuthWithoutStorage, FineGrainedAccessPermissions) { { FineGrainedAccessPermissions fga_permissions; - fga_permissions.Grant(any_label, LabelPermission::CREATE_DELETE); + fga_permissions.Grant(any_label, FineGrainedPermission::CREATE_DELETE); fga_permissions.Revoke(asterisk); ASSERT_EQ(fga_permissions.GetGlobalPermission(), std::nullopt); @@ -559,16 +563,16 @@ TEST(AuthWithoutStorage, FineGrainedAccessPermissions) { { FineGrainedAccessPermissions fga_permissions; - fga_permissions.Deny(asterisk, LabelPermission::CREATE_DELETE); + fga_permissions.Deny(asterisk, FineGrainedPermission::CREATE_DELETE); fga_permissions.Revoke(any_label); - ASSERT_EQ(fga_permissions.GetGlobalPermission(), LabelPermission::EDIT | LabelPermission::READ); + ASSERT_EQ(fga_permissions.GetGlobalPermission(), FineGrainedPermission::UPDATE | FineGrainedPermission::READ); ASSERT_TRUE(fga_permissions.GetPermissions().empty()); } { FineGrainedAccessPermissions fga_permissions; - fga_permissions.Deny(any_label, LabelPermission::CREATE_DELETE); + fga_permissions.Deny(any_label, FineGrainedPermission::CREATE_DELETE); fga_permissions.Revoke(any_label); ASSERT_EQ(fga_permissions.GetGlobalPermission(), std::nullopt); @@ -577,7 +581,7 @@ TEST(AuthWithoutStorage, FineGrainedAccessPermissions) { { FineGrainedAccessPermissions fga_permissions; - fga_permissions.Deny(any_label, LabelPermission::CREATE_DELETE); + fga_permissions.Deny(any_label, FineGrainedPermission::CREATE_DELETE); fga_permissions.Revoke(asterisk); ASSERT_EQ(fga_permissions.GetGlobalPermission(), std::nullopt); @@ -586,8 +590,8 @@ TEST(AuthWithoutStorage, FineGrainedAccessPermissions) { { FineGrainedAccessPermissions fga_permissions; - fga_permissions.Grant(check_label, LabelPermission::CREATE_DELETE); - fga_permissions.Deny(non_check_label, LabelPermission::CREATE_DELETE); + fga_permissions.Grant(check_label, FineGrainedPermission::CREATE_DELETE); + fga_permissions.Deny(non_check_label, FineGrainedPermission::CREATE_DELETE); fga_permissions.Revoke(asterisk); ASSERT_EQ(fga_permissions.GetGlobalPermission(), std::nullopt); @@ -596,180 +600,180 @@ TEST(AuthWithoutStorage, FineGrainedAccessPermissions) { { FineGrainedAccessPermissions fga_permissions; - fga_permissions.Grant(asterisk, LabelPermission::CREATE_DELETE); + fga_permissions.Grant(asterisk, FineGrainedPermission::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); + ASSERT_EQ(fga_permissions.Has(any_label, FineGrainedPermission::CREATE_DELETE), PermissionLevel::GRANT); + ASSERT_EQ(fga_permissions.Has(any_label, FineGrainedPermission::UPDATE), PermissionLevel::GRANT); + ASSERT_EQ(fga_permissions.Has(any_label, FineGrainedPermission::READ), PermissionLevel::GRANT); } { FineGrainedAccessPermissions fga_permissions; - fga_permissions.Grant(asterisk, LabelPermission::EDIT); + fga_permissions.Grant(asterisk, FineGrainedPermission::UPDATE); - 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); + ASSERT_EQ(fga_permissions.Has(any_label, FineGrainedPermission::CREATE_DELETE), PermissionLevel::DENY); + ASSERT_EQ(fga_permissions.Has(any_label, FineGrainedPermission::UPDATE), PermissionLevel::GRANT); + ASSERT_EQ(fga_permissions.Has(any_label, FineGrainedPermission::READ), PermissionLevel::GRANT); } { FineGrainedAccessPermissions fga_permissions; - fga_permissions.Grant(asterisk, LabelPermission::CREATE_DELETE); + fga_permissions.Grant(asterisk, FineGrainedPermission::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); + ASSERT_EQ(fga_permissions.Has(any_label, FineGrainedPermission::CREATE_DELETE), PermissionLevel::GRANT); + ASSERT_EQ(fga_permissions.Has(any_label, FineGrainedPermission::UPDATE), PermissionLevel::GRANT); + ASSERT_EQ(fga_permissions.Has(any_label, FineGrainedPermission::READ), PermissionLevel::GRANT); } { FineGrainedAccessPermissions fga_permissions; - fga_permissions.Deny(asterisk, LabelPermission::CREATE_DELETE); + fga_permissions.Deny(asterisk, FineGrainedPermission::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); + ASSERT_EQ(fga_permissions.Has(any_label, FineGrainedPermission::CREATE_DELETE), PermissionLevel::DENY); + ASSERT_EQ(fga_permissions.Has(any_label, FineGrainedPermission::UPDATE), PermissionLevel::GRANT); + ASSERT_EQ(fga_permissions.Has(any_label, FineGrainedPermission::READ), PermissionLevel::GRANT); } { FineGrainedAccessPermissions fga_permissions; - fga_permissions.Deny(asterisk, LabelPermission::EDIT); + fga_permissions.Deny(asterisk, FineGrainedPermission::UPDATE); - 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); + ASSERT_EQ(fga_permissions.Has(any_label, FineGrainedPermission::CREATE_DELETE), PermissionLevel::DENY); + ASSERT_EQ(fga_permissions.Has(any_label, FineGrainedPermission::UPDATE), PermissionLevel::DENY); + ASSERT_EQ(fga_permissions.Has(any_label, FineGrainedPermission::READ), PermissionLevel::GRANT); } { FineGrainedAccessPermissions fga_permissions; - fga_permissions.Deny(asterisk, LabelPermission::READ); + fga_permissions.Deny(asterisk, FineGrainedPermission::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); + ASSERT_EQ(fga_permissions.Has(any_label, FineGrainedPermission::CREATE_DELETE), PermissionLevel::DENY); + ASSERT_EQ(fga_permissions.Has(any_label, FineGrainedPermission::UPDATE), PermissionLevel::DENY); + ASSERT_EQ(fga_permissions.Has(any_label, FineGrainedPermission::READ), PermissionLevel::DENY); } { FineGrainedAccessPermissions fga_permissions; - fga_permissions.Grant(asterisk, LabelPermission::READ); - fga_permissions.Grant(check_label, LabelPermission::EDIT); + fga_permissions.Grant(asterisk, FineGrainedPermission::READ); + fga_permissions.Grant(check_label, FineGrainedPermission::UPDATE); - 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); + ASSERT_EQ(fga_permissions.Has(check_label, FineGrainedPermission::CREATE_DELETE), PermissionLevel::DENY); + ASSERT_EQ(fga_permissions.Has(check_label, FineGrainedPermission::UPDATE), PermissionLevel::GRANT); + ASSERT_EQ(fga_permissions.Has(check_label, FineGrainedPermission::READ), PermissionLevel::GRANT); + ASSERT_EQ(fga_permissions.Has(non_check_label, FineGrainedPermission::CREATE_DELETE), PermissionLevel::DENY); + ASSERT_EQ(fga_permissions.Has(non_check_label, FineGrainedPermission::UPDATE), PermissionLevel::DENY); + ASSERT_EQ(fga_permissions.Has(non_check_label, FineGrainedPermission::READ), PermissionLevel::GRANT); } { FineGrainedAccessPermissions fga_permissions; - fga_permissions.Grant(asterisk, LabelPermission::READ); - fga_permissions.Deny(check_label, LabelPermission::CREATE_DELETE); + fga_permissions.Grant(asterisk, FineGrainedPermission::READ); + fga_permissions.Deny(check_label, FineGrainedPermission::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); + ASSERT_EQ(fga_permissions.Has(check_label, FineGrainedPermission::CREATE_DELETE), PermissionLevel::DENY); + ASSERT_EQ(fga_permissions.Has(check_label, FineGrainedPermission::UPDATE), PermissionLevel::GRANT); + ASSERT_EQ(fga_permissions.Has(check_label, FineGrainedPermission::READ), PermissionLevel::GRANT); + ASSERT_EQ(fga_permissions.Has(non_check_label, FineGrainedPermission::CREATE_DELETE), PermissionLevel::DENY); + ASSERT_EQ(fga_permissions.Has(non_check_label, FineGrainedPermission::UPDATE), PermissionLevel::DENY); + ASSERT_EQ(fga_permissions.Has(non_check_label, FineGrainedPermission::READ), PermissionLevel::GRANT); } { FineGrainedAccessPermissions fga_permissions; - fga_permissions.Grant(asterisk, LabelPermission::CREATE_DELETE); - fga_permissions.Deny(check_label, LabelPermission::EDIT); + fga_permissions.Grant(asterisk, FineGrainedPermission::CREATE_DELETE); + fga_permissions.Deny(check_label, FineGrainedPermission::UPDATE); - 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); + ASSERT_EQ(fga_permissions.Has(check_label, FineGrainedPermission::CREATE_DELETE), PermissionLevel::DENY); + ASSERT_EQ(fga_permissions.Has(check_label, FineGrainedPermission::UPDATE), PermissionLevel::DENY); + ASSERT_EQ(fga_permissions.Has(check_label, FineGrainedPermission::READ), PermissionLevel::GRANT); + ASSERT_EQ(fga_permissions.Has(non_check_label, FineGrainedPermission::CREATE_DELETE), PermissionLevel::GRANT); + ASSERT_EQ(fga_permissions.Has(non_check_label, FineGrainedPermission::UPDATE), PermissionLevel::GRANT); + ASSERT_EQ(fga_permissions.Has(non_check_label, FineGrainedPermission::READ), PermissionLevel::GRANT); } { FineGrainedAccessPermissions fga_permissions; - fga_permissions.Grant(asterisk, LabelPermission::CREATE_DELETE); - fga_permissions.Deny(check_label, LabelPermission::CREATE_DELETE); + fga_permissions.Grant(asterisk, FineGrainedPermission::CREATE_DELETE); + fga_permissions.Deny(check_label, FineGrainedPermission::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); + ASSERT_EQ(fga_permissions.Has(check_label, FineGrainedPermission::CREATE_DELETE), PermissionLevel::DENY); + ASSERT_EQ(fga_permissions.Has(check_label, FineGrainedPermission::UPDATE), PermissionLevel::GRANT); + ASSERT_EQ(fga_permissions.Has(check_label, FineGrainedPermission::READ), PermissionLevel::GRANT); + ASSERT_EQ(fga_permissions.Has(non_check_label, FineGrainedPermission::CREATE_DELETE), PermissionLevel::GRANT); + ASSERT_EQ(fga_permissions.Has(non_check_label, FineGrainedPermission::UPDATE), PermissionLevel::GRANT); + ASSERT_EQ(fga_permissions.Has(non_check_label, FineGrainedPermission::READ), PermissionLevel::GRANT); } { FineGrainedAccessPermissions fga_permissions; - fga_permissions.Grant(asterisk, LabelPermission::CREATE_DELETE); - fga_permissions.Deny(asterisk, LabelPermission::CREATE_DELETE); + fga_permissions.Grant(asterisk, FineGrainedPermission::CREATE_DELETE); + fga_permissions.Deny(asterisk, FineGrainedPermission::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); + ASSERT_EQ(fga_permissions.Has(any_label, FineGrainedPermission::CREATE_DELETE), PermissionLevel::DENY); + ASSERT_EQ(fga_permissions.Has(any_label, FineGrainedPermission::UPDATE), PermissionLevel::GRANT); + ASSERT_EQ(fga_permissions.Has(any_label, FineGrainedPermission::READ), PermissionLevel::GRANT); } { FineGrainedAccessPermissions fga_permissions; - fga_permissions.Grant(asterisk, LabelPermission::CREATE_DELETE); - fga_permissions.Deny(asterisk, LabelPermission::EDIT); + fga_permissions.Grant(asterisk, FineGrainedPermission::CREATE_DELETE); + fga_permissions.Deny(asterisk, FineGrainedPermission::UPDATE); - 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); + ASSERT_EQ(fga_permissions.Has(any_label, FineGrainedPermission::CREATE_DELETE), PermissionLevel::DENY); + ASSERT_EQ(fga_permissions.Has(any_label, FineGrainedPermission::UPDATE), PermissionLevel::DENY); + ASSERT_EQ(fga_permissions.Has(any_label, FineGrainedPermission::READ), PermissionLevel::GRANT); } { FineGrainedAccessPermissions fga_permissions; - fga_permissions.Grant(asterisk, LabelPermission::CREATE_DELETE); - fga_permissions.Deny(asterisk, LabelPermission::READ); + fga_permissions.Grant(asterisk, FineGrainedPermission::CREATE_DELETE); + fga_permissions.Deny(asterisk, FineGrainedPermission::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); + ASSERT_EQ(fga_permissions.Has(any_label, FineGrainedPermission::CREATE_DELETE), PermissionLevel::DENY); + ASSERT_EQ(fga_permissions.Has(any_label, FineGrainedPermission::UPDATE), PermissionLevel::DENY); + ASSERT_EQ(fga_permissions.Has(any_label, FineGrainedPermission::READ), PermissionLevel::DENY); } { FineGrainedAccessPermissions fga_permissions; - fga_permissions.Grant(asterisk, LabelPermission::CREATE_DELETE); - fga_permissions.Deny(check_label, LabelPermission::READ); + fga_permissions.Grant(asterisk, FineGrainedPermission::CREATE_DELETE); + fga_permissions.Deny(check_label, FineGrainedPermission::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); + ASSERT_EQ(fga_permissions.Has(check_label, FineGrainedPermission::CREATE_DELETE), PermissionLevel::DENY); + ASSERT_EQ(fga_permissions.Has(check_label, FineGrainedPermission::UPDATE), PermissionLevel::DENY); + ASSERT_EQ(fga_permissions.Has(check_label, FineGrainedPermission::READ), PermissionLevel::DENY); + ASSERT_EQ(fga_permissions.Has(non_check_label, FineGrainedPermission::CREATE_DELETE), PermissionLevel::DENY); + ASSERT_EQ(fga_permissions.Has(non_check_label, FineGrainedPermission::UPDATE), PermissionLevel::DENY); + ASSERT_EQ(fga_permissions.Has(non_check_label, FineGrainedPermission::READ), PermissionLevel::DENY); } { FineGrainedAccessPermissions fga_permissions; - fga_permissions.Grant(asterisk, LabelPermission::CREATE_DELETE); - fga_permissions.Deny(check_label, LabelPermission::EDIT); + fga_permissions.Grant(asterisk, FineGrainedPermission::CREATE_DELETE); + fga_permissions.Deny(check_label, FineGrainedPermission::UPDATE); 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); + ASSERT_EQ(fga_permissions.Has(check_label, FineGrainedPermission::CREATE_DELETE), PermissionLevel::DENY); + ASSERT_EQ(fga_permissions.Has(check_label, FineGrainedPermission::UPDATE), PermissionLevel::DENY); + ASSERT_EQ(fga_permissions.Has(check_label, FineGrainedPermission::READ), PermissionLevel::DENY); + ASSERT_EQ(fga_permissions.Has(non_check_label, FineGrainedPermission::CREATE_DELETE), PermissionLevel::DENY); + ASSERT_EQ(fga_permissions.Has(non_check_label, FineGrainedPermission::UPDATE), PermissionLevel::DENY); + ASSERT_EQ(fga_permissions.Has(non_check_label, FineGrainedPermission::READ), PermissionLevel::DENY); } { FineGrainedAccessPermissions fga_permissions; - fga_permissions.Grant(asterisk, LabelPermission::CREATE_DELETE); - fga_permissions.Deny(check_label, LabelPermission::CREATE_DELETE); + fga_permissions.Grant(asterisk, FineGrainedPermission::CREATE_DELETE); + fga_permissions.Deny(check_label, FineGrainedPermission::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); + ASSERT_EQ(fga_permissions.Has(check_label, FineGrainedPermission::CREATE_DELETE), PermissionLevel::DENY); + ASSERT_EQ(fga_permissions.Has(check_label, FineGrainedPermission::UPDATE), PermissionLevel::DENY); + ASSERT_EQ(fga_permissions.Has(check_label, FineGrainedPermission::READ), PermissionLevel::DENY); + ASSERT_EQ(fga_permissions.Has(non_check_label, FineGrainedPermission::CREATE_DELETE), PermissionLevel::DENY); + ASSERT_EQ(fga_permissions.Has(non_check_label, FineGrainedPermission::UPDATE), PermissionLevel::DENY); + ASSERT_EQ(fga_permissions.Has(non_check_label, FineGrainedPermission::READ), PermissionLevel::DENY); } } TEST_F(AuthWithStorage, FineGrainedAccessCheckerMerge) { @@ -779,63 +783,63 @@ TEST_F(AuthWithStorage, FineGrainedAccessCheckerMerge) { { FineGrainedAccessPermissions fga_permissions1, fga_permissions2; - fga_permissions1.Grant(asterisk, LabelPermission::READ); + fga_permissions1.Grant(asterisk, FineGrainedPermission::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); + ASSERT_EQ(fga_permissions3.Has(any_label, FineGrainedPermission::CREATE_DELETE), PermissionLevel::DENY); + ASSERT_EQ(fga_permissions3.Has(any_label, FineGrainedPermission::UPDATE), PermissionLevel::DENY); + ASSERT_EQ(fga_permissions3.Has(any_label, FineGrainedPermission::READ), PermissionLevel::GRANT); } { FineGrainedAccessPermissions fga_permissions1, fga_permissions2; - fga_permissions2.Grant(asterisk, LabelPermission::READ); + fga_permissions2.Grant(asterisk, FineGrainedPermission::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); + ASSERT_EQ(fga_permissions3.Has(any_label, FineGrainedPermission::CREATE_DELETE), PermissionLevel::DENY); + ASSERT_EQ(fga_permissions3.Has(any_label, FineGrainedPermission::UPDATE), PermissionLevel::DENY); + ASSERT_EQ(fga_permissions3.Has(any_label, FineGrainedPermission::READ), PermissionLevel::GRANT); } { FineGrainedAccessPermissions fga_permissions1, fga_permissions2; - fga_permissions1.Grant(asterisk, LabelPermission::READ); - fga_permissions2.Grant(asterisk, LabelPermission::EDIT); + fga_permissions1.Grant(asterisk, FineGrainedPermission::READ); + fga_permissions2.Grant(asterisk, FineGrainedPermission::UPDATE); 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); + ASSERT_EQ(fga_permissions3.Has(any_label, FineGrainedPermission::CREATE_DELETE), PermissionLevel::DENY); + ASSERT_EQ(fga_permissions3.Has(any_label, FineGrainedPermission::UPDATE), PermissionLevel::GRANT); + ASSERT_EQ(fga_permissions3.Has(any_label, FineGrainedPermission::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); + fga_permissions1.Grant(asterisk, FineGrainedPermission::READ); + fga_permissions1.Grant(check_label, FineGrainedPermission::UPDATE); + fga_permissions2.Grant(asterisk, FineGrainedPermission::UPDATE); 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); + ASSERT_EQ(fga_permissions3.Has(check_label, FineGrainedPermission::CREATE_DELETE), PermissionLevel::DENY); + ASSERT_EQ(fga_permissions3.Has(check_label, FineGrainedPermission::UPDATE), PermissionLevel::GRANT); + ASSERT_EQ(fga_permissions3.Has(check_label, FineGrainedPermission::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); + fga_permissions1.Grant(asterisk, FineGrainedPermission::READ); + fga_permissions1.Grant(check_label, FineGrainedPermission::CREATE_DELETE); + fga_permissions2.Grant(asterisk, FineGrainedPermission::UPDATE); + fga_permissions2.Grant(check_label, FineGrainedPermission::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); + ASSERT_EQ(fga_permissions3.Has(check_label, FineGrainedPermission::CREATE_DELETE), PermissionLevel::DENY); + ASSERT_EQ(fga_permissions3.Has(check_label, FineGrainedPermission::UPDATE), PermissionLevel::DENY); + ASSERT_EQ(fga_permissions3.Has(check_label, FineGrainedPermission::READ), PermissionLevel::GRANT); } } diff --git a/tests/unit/auth_checker.cpp b/tests/unit/auth_checker.cpp index 307e5742e..7cc2cbd93 100644 --- a/tests/unit/auth_checker.cpp +++ b/tests/unit/auth_checker.cpp @@ -46,7 +46,8 @@ class FineGrainedAuthCheckerFixture : public testing::Test { TEST_F(FineGrainedAuthCheckerFixture, GrantedAllLabels) { memgraph::auth::User user{"test"}; - user.fine_grained_access_handler().label_permissions().Grant("*", memgraph::auth::LabelPermission::CREATE_DELETE); + user.fine_grained_access_handler().label_permissions().Grant("*", + memgraph::auth::FineGrainedPermission::CREATE_DELETE); memgraph::glue::FineGrainedAuthChecker auth_checker{user}; ASSERT_TRUE(auth_checker.Accept(dba, v1, memgraph::storage::View::NEW)); @@ -59,7 +60,8 @@ TEST_F(FineGrainedAuthCheckerFixture, GrantedAllLabels) { TEST_F(FineGrainedAuthCheckerFixture, GrantedAllEdgeTypes) { memgraph::auth::User user{"test"}; - user.fine_grained_access_handler().edge_type_permissions().Grant("*", memgraph::auth::LabelPermission::CREATE_DELETE); + user.fine_grained_access_handler().edge_type_permissions().Grant( + "*", memgraph::auth::FineGrainedPermission::CREATE_DELETE); memgraph::glue::FineGrainedAuthChecker auth_checker{user}; ASSERT_TRUE(auth_checker.Accept(dba, r1)); @@ -70,7 +72,7 @@ TEST_F(FineGrainedAuthCheckerFixture, GrantedAllEdgeTypes) { TEST_F(FineGrainedAuthCheckerFixture, DeniedAllLabels) { memgraph::auth::User user{"test"}; - user.fine_grained_access_handler().label_permissions().Deny("*", memgraph::auth::LabelPermission::READ); + user.fine_grained_access_handler().label_permissions().Deny("*", memgraph::auth::FineGrainedPermission::READ); memgraph::glue::FineGrainedAuthChecker auth_checker{user}; ASSERT_FALSE(auth_checker.Accept(dba, v1, memgraph::storage::View::NEW)); @@ -83,7 +85,7 @@ TEST_F(FineGrainedAuthCheckerFixture, DeniedAllLabels) { TEST_F(FineGrainedAuthCheckerFixture, DeniedAllEdgeTypes) { memgraph::auth::User user{"test"}; - user.fine_grained_access_handler().edge_type_permissions().Deny("*", memgraph::auth::LabelPermission::READ); + user.fine_grained_access_handler().edge_type_permissions().Deny("*", memgraph::auth::FineGrainedPermission::READ); memgraph::glue::FineGrainedAuthChecker auth_checker{user}; ASSERT_FALSE(auth_checker.Accept(dba, r1)); @@ -94,7 +96,8 @@ TEST_F(FineGrainedAuthCheckerFixture, DeniedAllEdgeTypes) { TEST_F(FineGrainedAuthCheckerFixture, GrantLabel) { memgraph::auth::User user{"test"}; - user.fine_grained_access_handler().label_permissions().Grant("l1", memgraph::auth::LabelPermission::CREATE_DELETE); + user.fine_grained_access_handler().label_permissions().Grant("l1", + memgraph::auth::FineGrainedPermission::CREATE_DELETE); memgraph::glue::FineGrainedAuthChecker auth_checker{user}; ASSERT_TRUE(auth_checker.Accept(dba, v1, memgraph::storage::View::NEW)); @@ -103,7 +106,7 @@ TEST_F(FineGrainedAuthCheckerFixture, GrantLabel) { TEST_F(FineGrainedAuthCheckerFixture, DenyLabel) { memgraph::auth::User user{"test"}; - user.fine_grained_access_handler().label_permissions().Deny("l3", memgraph::auth::LabelPermission::READ); + user.fine_grained_access_handler().label_permissions().Deny("l3", memgraph::auth::FineGrainedPermission::READ); memgraph::glue::FineGrainedAuthChecker auth_checker{user}; ASSERT_FALSE(auth_checker.Accept(dba, v3, memgraph::storage::View::NEW)); @@ -112,9 +115,11 @@ TEST_F(FineGrainedAuthCheckerFixture, DenyLabel) { TEST_F(FineGrainedAuthCheckerFixture, GrantAndDenySpecificLabels) { memgraph::auth::User user{"test"}; - 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); + user.fine_grained_access_handler().label_permissions().Grant("l1", + memgraph::auth::FineGrainedPermission::CREATE_DELETE); + user.fine_grained_access_handler().label_permissions().Grant("l2", + memgraph::auth::FineGrainedPermission::CREATE_DELETE); + user.fine_grained_access_handler().label_permissions().Deny("l3", memgraph::auth::FineGrainedPermission::READ); memgraph::glue::FineGrainedAuthChecker auth_checker{user}; ASSERT_TRUE(auth_checker.Accept(dba, v1, memgraph::storage::View::NEW)); @@ -127,9 +132,11 @@ TEST_F(FineGrainedAuthCheckerFixture, GrantAndDenySpecificLabels) { TEST_F(FineGrainedAuthCheckerFixture, MultipleVertexLabels) { memgraph::auth::User user{"test"}; - 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); + user.fine_grained_access_handler().label_permissions().Grant("l1", + memgraph::auth::FineGrainedPermission::CREATE_DELETE); + user.fine_grained_access_handler().label_permissions().Grant("l2", + memgraph::auth::FineGrainedPermission::CREATE_DELETE); + user.fine_grained_access_handler().label_permissions().Deny("l3", memgraph::auth::FineGrainedPermission::READ); memgraph::glue::FineGrainedAuthChecker auth_checker{user}; ASSERT_TRUE(v1.AddLabel(dba.NameToLabel("l3")).HasValue()); ASSERT_TRUE(v2.AddLabel(dba.NameToLabel("l1")).HasValue()); @@ -143,8 +150,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", - memgraph::auth::LabelPermission::CREATE_DELETE); + user.fine_grained_access_handler().edge_type_permissions().Grant( + "edge_type_1", memgraph::auth::FineGrainedPermission::CREATE_DELETE); memgraph::glue::FineGrainedAuthChecker auth_checker{user}; ASSERT_TRUE(auth_checker.Accept(dba, r1)); @@ -152,7 +159,8 @@ 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", memgraph::auth::LabelPermission::READ); + user.fine_grained_access_handler().edge_type_permissions().Deny("edge_type_1", + memgraph::auth::FineGrainedPermission::READ); memgraph::glue::FineGrainedAuthChecker auth_checker{user}; ASSERT_FALSE(auth_checker.Accept(dba, r1)); @@ -160,9 +168,10 @@ 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", - memgraph::auth::LabelPermission::CREATE_DELETE); - user.fine_grained_access_handler().edge_type_permissions().Deny("edge_type_2", memgraph::auth::LabelPermission::READ); + user.fine_grained_access_handler().edge_type_permissions().Grant( + "edge_type_1", memgraph::auth::FineGrainedPermission::CREATE_DELETE); + user.fine_grained_access_handler().edge_type_permissions().Deny("edge_type_2", + memgraph::auth::FineGrainedPermission::READ); memgraph::glue::FineGrainedAuthChecker auth_checker{user}; ASSERT_TRUE(auth_checker.Accept(dba, r1)); diff --git a/tests/unit/cypher_main_visitor.cpp b/tests/unit/cypher_main_visitor.cpp index 40aeb0161..39609dc44 100644 --- a/tests/unit/cypher_main_visitor.cpp +++ b/tests/unit/cypher_main_visitor.cpp @@ -2056,9 +2056,11 @@ TEST_P(CypherMainVisitorTest, UnionAll) { ASSERT_FALSE(return_clause->body_.distinct); } -void check_auth_query(Base *ast_generator, std::string input, AuthQuery::Action action, std::string user, - std::string role, std::string user_or_role, std::optional<TypedValue> password, - std::vector<AuthQuery::Privilege> privileges) { +void check_auth_query( + Base *ast_generator, std::string input, AuthQuery::Action action, std::string user, std::string role, + std::string user_or_role, std::optional<TypedValue> password, std::vector<AuthQuery::Privilege> privileges, + std::vector<std::unordered_map<AuthQuery::FineGrainedPrivilege, std::vector<std::string>>> label_privileges, + std::vector<std::unordered_map<AuthQuery::FineGrainedPrivilege, std::vector<std::string>>> edge_type_privileges) { auto *auth_query = dynamic_cast<AuthQuery *>(ast_generator->ParseQuery(input)); ASSERT_TRUE(auth_query); EXPECT_EQ(auth_query->action_, action); @@ -2070,48 +2072,55 @@ void check_auth_query(Base *ast_generator, std::string input, AuthQuery::Action ast_generator->CheckLiteral(auth_query->password_, *password); } EXPECT_EQ(auth_query->privileges_, privileges); + EXPECT_EQ(auth_query->label_privileges_, label_privileges); + EXPECT_EQ(auth_query->edge_type_privileges_, edge_type_privileges); } TEST_P(CypherMainVisitorTest, UserOrRoleName) { auto &ast_generator = *GetParam(); - check_auth_query(&ast_generator, "CREATE ROLE `user`", AuthQuery::Action::CREATE_ROLE, "", "user", "", {}, {}); - check_auth_query(&ast_generator, "CREATE ROLE us___er", AuthQuery::Action::CREATE_ROLE, "", "us___er", "", {}, {}); - check_auth_query(&ast_generator, "CREATE ROLE `us+er`", AuthQuery::Action::CREATE_ROLE, "", "us+er", "", {}, {}); - check_auth_query(&ast_generator, "CREATE ROLE `us|er`", AuthQuery::Action::CREATE_ROLE, "", "us|er", "", {}, {}); - check_auth_query(&ast_generator, "CREATE ROLE `us er`", AuthQuery::Action::CREATE_ROLE, "", "us er", "", {}, {}); + check_auth_query(&ast_generator, "CREATE ROLE `user`", AuthQuery::Action::CREATE_ROLE, "", "user", "", {}, {}, {}, + {}); + check_auth_query(&ast_generator, "CREATE ROLE us___er", AuthQuery::Action::CREATE_ROLE, "", "us___er", "", {}, {}, {}, + {}); + check_auth_query(&ast_generator, "CREATE ROLE `us+er`", AuthQuery::Action::CREATE_ROLE, "", "us+er", "", {}, {}, {}, + {}); + check_auth_query(&ast_generator, "CREATE ROLE `us|er`", AuthQuery::Action::CREATE_ROLE, "", "us|er", "", {}, {}, {}, + {}); + check_auth_query(&ast_generator, "CREATE ROLE `us er`", AuthQuery::Action::CREATE_ROLE, "", "us er", "", {}, {}, {}, + {}); } TEST_P(CypherMainVisitorTest, CreateRole) { auto &ast_generator = *GetParam(); ASSERT_THROW(ast_generator.ParseQuery("CREATE ROLE"), SyntaxException); - check_auth_query(&ast_generator, "CREATE ROLE rola", AuthQuery::Action::CREATE_ROLE, "", "rola", "", {}, {}); + check_auth_query(&ast_generator, "CREATE ROLE rola", AuthQuery::Action::CREATE_ROLE, "", "rola", "", {}, {}, {}, {}); ASSERT_THROW(ast_generator.ParseQuery("CREATE ROLE lagano rolamo"), SyntaxException); } TEST_P(CypherMainVisitorTest, DropRole) { auto &ast_generator = *GetParam(); ASSERT_THROW(ast_generator.ParseQuery("DROP ROLE"), SyntaxException); - check_auth_query(&ast_generator, "DROP ROLE rola", AuthQuery::Action::DROP_ROLE, "", "rola", "", {}, {}); + check_auth_query(&ast_generator, "DROP ROLE rola", AuthQuery::Action::DROP_ROLE, "", "rola", "", {}, {}, {}, {}); ASSERT_THROW(ast_generator.ParseQuery("DROP ROLE lagano rolamo"), SyntaxException); } TEST_P(CypherMainVisitorTest, ShowRoles) { auto &ast_generator = *GetParam(); ASSERT_THROW(ast_generator.ParseQuery("SHOW ROLES ROLES"), SyntaxException); - check_auth_query(&ast_generator, "SHOW ROLES", AuthQuery::Action::SHOW_ROLES, "", "", "", {}, {}); + check_auth_query(&ast_generator, "SHOW ROLES", AuthQuery::Action::SHOW_ROLES, "", "", "", {}, {}, {}, {}); } TEST_P(CypherMainVisitorTest, CreateUser) { auto &ast_generator = *GetParam(); ASSERT_THROW(ast_generator.ParseQuery("CREATE USER"), SyntaxException); ASSERT_THROW(ast_generator.ParseQuery("CREATE USER 123"), SyntaxException); - check_auth_query(&ast_generator, "CREATE USER user", AuthQuery::Action::CREATE_USER, "user", "", "", {}, {}); + check_auth_query(&ast_generator, "CREATE USER user", AuthQuery::Action::CREATE_USER, "user", "", "", {}, {}, {}, {}); check_auth_query(&ast_generator, "CREATE USER user IDENTIFIED BY 'password'", AuthQuery::Action::CREATE_USER, "user", - "", "", TypedValue("password"), {}); + "", "", TypedValue("password"), {}, {}, {}); check_auth_query(&ast_generator, "CREATE USER user IDENTIFIED BY ''", AuthQuery::Action::CREATE_USER, "user", "", "", - TypedValue(""), {}); + TypedValue(""), {}, {}, {}); check_auth_query(&ast_generator, "CREATE USER user IDENTIFIED BY null", AuthQuery::Action::CREATE_USER, "user", "", - "", TypedValue(), {}); + "", TypedValue(), {}, {}, {}); ASSERT_THROW(ast_generator.ParseQuery("CRATE USER user IDENTIFIED BY password"), SyntaxException); ASSERT_THROW(ast_generator.ParseQuery("CREATE USER user IDENTIFIED BY 5"), SyntaxException); ASSERT_THROW(ast_generator.ParseQuery("CREATE USER user IDENTIFIED BY "), SyntaxException); @@ -2122,23 +2131,23 @@ TEST_P(CypherMainVisitorTest, SetPassword) { ASSERT_THROW(ast_generator.ParseQuery("SET PASSWORD FOR"), SyntaxException); ASSERT_THROW(ast_generator.ParseQuery("SET PASSWORD FOR user "), SyntaxException); check_auth_query(&ast_generator, "SET PASSWORD FOR user TO null", AuthQuery::Action::SET_PASSWORD, "user", "", "", - TypedValue(), {}); + TypedValue(), {}, {}, {}); check_auth_query(&ast_generator, "SET PASSWORD FOR user TO 'password'", AuthQuery::Action::SET_PASSWORD, "user", "", - "", TypedValue("password"), {}); + "", TypedValue("password"), {}, {}, {}); ASSERT_THROW(ast_generator.ParseQuery("SET PASSWORD FOR user To 5"), SyntaxException); } TEST_P(CypherMainVisitorTest, DropUser) { auto &ast_generator = *GetParam(); ASSERT_THROW(ast_generator.ParseQuery("DROP USER"), SyntaxException); - check_auth_query(&ast_generator, "DROP USER user", AuthQuery::Action::DROP_USER, "user", "", "", {}, {}); + check_auth_query(&ast_generator, "DROP USER user", AuthQuery::Action::DROP_USER, "user", "", "", {}, {}, {}, {}); ASSERT_THROW(ast_generator.ParseQuery("DROP USER lagano rolamo"), SyntaxException); } TEST_P(CypherMainVisitorTest, ShowUsers) { auto &ast_generator = *GetParam(); ASSERT_THROW(ast_generator.ParseQuery("SHOW USERS ROLES"), SyntaxException); - check_auth_query(&ast_generator, "SHOW USERS", AuthQuery::Action::SHOW_USERS, "", "", "", {}, {}); + check_auth_query(&ast_generator, "SHOW USERS", AuthQuery::Action::SHOW_USERS, "", "", "", {}, {}, {}, {}); } TEST_P(CypherMainVisitorTest, SetRole) { @@ -2147,10 +2156,10 @@ TEST_P(CypherMainVisitorTest, SetRole) { ASSERT_THROW(ast_generator.ParseQuery("SET ROLE user"), SyntaxException); ASSERT_THROW(ast_generator.ParseQuery("SET ROLE FOR user"), SyntaxException); ASSERT_THROW(ast_generator.ParseQuery("SET ROLE FOR user TO"), SyntaxException); - check_auth_query(&ast_generator, "SET ROLE FOR user TO role", AuthQuery::Action::SET_ROLE, "user", "role", "", {}, - {}); - check_auth_query(&ast_generator, "SET ROLE FOR user TO null", AuthQuery::Action::SET_ROLE, "user", "null", "", {}, - {}); + check_auth_query(&ast_generator, "SET ROLE FOR user TO role", AuthQuery::Action::SET_ROLE, "user", "role", "", {}, {}, + {}, {}); + check_auth_query(&ast_generator, "SET ROLE FOR user TO null", AuthQuery::Action::SET_ROLE, "user", "null", "", {}, {}, + {}, {}); } TEST_P(CypherMainVisitorTest, ClearRole) { @@ -2158,7 +2167,8 @@ TEST_P(CypherMainVisitorTest, ClearRole) { ASSERT_THROW(ast_generator.ParseQuery("CLEAR ROLE"), SyntaxException); ASSERT_THROW(ast_generator.ParseQuery("CLEAR ROLE user"), SyntaxException); ASSERT_THROW(ast_generator.ParseQuery("CLEAR ROLE FOR user TO"), SyntaxException); - check_auth_query(&ast_generator, "CLEAR ROLE FOR user", AuthQuery::Action::CLEAR_ROLE, "user", "", "", {}, {}); + check_auth_query(&ast_generator, "CLEAR ROLE FOR user", AuthQuery::Action::CLEAR_ROLE, "user", "", "", {}, {}, {}, + {}); } TEST_P(CypherMainVisitorTest, GrantPrivilege) { @@ -2169,50 +2179,97 @@ TEST_P(CypherMainVisitorTest, GrantPrivilege) { ASSERT_THROW(ast_generator.ParseQuery("GRANT MATCH, TO user"), SyntaxException); ASSERT_THROW(ast_generator.ParseQuery("GRANT MATCH, BLABLA TO user"), SyntaxException); check_auth_query(&ast_generator, "GRANT MATCH TO user", AuthQuery::Action::GRANT_PRIVILEGE, "", "", "user", {}, - {AuthQuery::Privilege::MATCH}); + {AuthQuery::Privilege::MATCH}, {}, {}); check_auth_query(&ast_generator, "GRANT MATCH, AUTH TO user", AuthQuery::Action::GRANT_PRIVILEGE, "", "", "user", {}, - {AuthQuery::Privilege::MATCH, AuthQuery::Privilege::AUTH}); + {AuthQuery::Privilege::MATCH, AuthQuery::Privilege::AUTH}, {}, {}); // Verify that all privileges are correctly visited. check_auth_query(&ast_generator, "GRANT CREATE TO user", AuthQuery::Action::GRANT_PRIVILEGE, "", "", "user", {}, - {AuthQuery::Privilege::CREATE}); + {AuthQuery::Privilege::CREATE}, {}, {}); check_auth_query(&ast_generator, "GRANT DELETE TO user", AuthQuery::Action::GRANT_PRIVILEGE, "", "", "user", {}, - {AuthQuery::Privilege::DELETE}); + {AuthQuery::Privilege::DELETE}, {}, {}); check_auth_query(&ast_generator, "GRANT MERGE TO user", AuthQuery::Action::GRANT_PRIVILEGE, "", "", "user", {}, - {AuthQuery::Privilege::MERGE}); + {AuthQuery::Privilege::MERGE}, {}, {}); check_auth_query(&ast_generator, "GRANT SET TO user", AuthQuery::Action::GRANT_PRIVILEGE, "", "", "user", {}, - {AuthQuery::Privilege::SET}); + {AuthQuery::Privilege::SET}, {}, {}); check_auth_query(&ast_generator, "GRANT REMOVE TO user", AuthQuery::Action::GRANT_PRIVILEGE, "", "", "user", {}, - {AuthQuery::Privilege::REMOVE}); + {AuthQuery::Privilege::REMOVE}, {}, {}); check_auth_query(&ast_generator, "GRANT INDEX TO user", AuthQuery::Action::GRANT_PRIVILEGE, "", "", "user", {}, - {AuthQuery::Privilege::INDEX}); + {AuthQuery::Privilege::INDEX}, {}, {}); check_auth_query(&ast_generator, "GRANT STATS TO user", AuthQuery::Action::GRANT_PRIVILEGE, "", "", "user", {}, - {AuthQuery::Privilege::STATS}); + {AuthQuery::Privilege::STATS}, {}, {}); check_auth_query(&ast_generator, "GRANT AUTH TO user", AuthQuery::Action::GRANT_PRIVILEGE, "", "", "user", {}, - {AuthQuery::Privilege::AUTH}); + {AuthQuery::Privilege::AUTH}, {}, {}); check_auth_query(&ast_generator, "GRANT CONSTRAINT TO user", AuthQuery::Action::GRANT_PRIVILEGE, "", "", "user", {}, - {AuthQuery::Privilege::CONSTRAINT}); + {AuthQuery::Privilege::CONSTRAINT}, {}, {}); check_auth_query(&ast_generator, "GRANT DUMP TO user", AuthQuery::Action::GRANT_PRIVILEGE, "", "", "user", {}, - {AuthQuery::Privilege::DUMP}); + {AuthQuery::Privilege::DUMP}, {}, {}); check_auth_query(&ast_generator, "GRANT REPLICATION TO user", AuthQuery::Action::GRANT_PRIVILEGE, "", "", "user", {}, - {AuthQuery::Privilege::REPLICATION}); + {AuthQuery::Privilege::REPLICATION}, {}, {}); check_auth_query(&ast_generator, "GRANT DURABILITY TO user", AuthQuery::Action::GRANT_PRIVILEGE, "", "", "user", {}, - {AuthQuery::Privilege::DURABILITY}); + {AuthQuery::Privilege::DURABILITY}, {}, {}); check_auth_query(&ast_generator, "GRANT READ_FILE TO user", AuthQuery::Action::GRANT_PRIVILEGE, "", "", "user", {}, - {AuthQuery::Privilege::READ_FILE}); + {AuthQuery::Privilege::READ_FILE}, {}, {}); check_auth_query(&ast_generator, "GRANT FREE_MEMORY TO user", AuthQuery::Action::GRANT_PRIVILEGE, "", "", "user", {}, - {AuthQuery::Privilege::FREE_MEMORY}); + {AuthQuery::Privilege::FREE_MEMORY}, {}, {}); check_auth_query(&ast_generator, "GRANT TRIGGER TO user", AuthQuery::Action::GRANT_PRIVILEGE, "", "", "user", {}, - {AuthQuery::Privilege::TRIGGER}); + {AuthQuery::Privilege::TRIGGER}, {}, {}); check_auth_query(&ast_generator, "GRANT CONFIG TO user", AuthQuery::Action::GRANT_PRIVILEGE, "", "", "user", {}, - {AuthQuery::Privilege::CONFIG}); + {AuthQuery::Privilege::CONFIG}, {}, {}); check_auth_query(&ast_generator, "GRANT STREAM TO user", AuthQuery::Action::GRANT_PRIVILEGE, "", "", "user", {}, - {AuthQuery::Privilege::STREAM}); + {AuthQuery::Privilege::STREAM}, {}, {}); check_auth_query(&ast_generator, "GRANT WEBSOCKET TO user", AuthQuery::Action::GRANT_PRIVILEGE, "", "", "user", {}, - {AuthQuery::Privilege::WEBSOCKET}); + {AuthQuery::Privilege::WEBSOCKET}, {}, {}); check_auth_query(&ast_generator, "GRANT MODULE_READ TO user", AuthQuery::Action::GRANT_PRIVILEGE, "", "", "user", {}, - {AuthQuery::Privilege::MODULE_READ}); + {AuthQuery::Privilege::MODULE_READ}, {}, {}); check_auth_query(&ast_generator, "GRANT MODULE_WRITE TO user", AuthQuery::Action::GRANT_PRIVILEGE, "", "", "user", {}, - {AuthQuery::Privilege::MODULE_WRITE}); + {AuthQuery::Privilege::MODULE_WRITE}, {}, {}); + + std::vector<std::unordered_map<AuthQuery::FineGrainedPrivilege, std::vector<std::string>>> label_privileges{}; + std::vector<std::unordered_map<AuthQuery::FineGrainedPrivilege, std::vector<std::string>>> edge_type_privileges{}; + + label_privileges.push_back({{{AuthQuery::FineGrainedPrivilege::READ}, {{"*"}}}}); + check_auth_query(&ast_generator, "GRANT READ ON LABELS * TO user", AuthQuery::Action::GRANT_PRIVILEGE, "", "", "user", + {}, {}, label_privileges, {}); + label_privileges.clear(); + + label_privileges.push_back({{{AuthQuery::FineGrainedPrivilege::UPDATE}, {{"*"}}}}); + check_auth_query(&ast_generator, "GRANT UPDATE ON LABELS * TO user", AuthQuery::Action::GRANT_PRIVILEGE, "", "", + "user", {}, {}, label_privileges, {}); + label_privileges.clear(); + + label_privileges.push_back({{{AuthQuery::FineGrainedPrivilege::CREATE_DELETE}, {{"*"}}}}); + check_auth_query(&ast_generator, "GRANT CREATE_DELETE ON LABELS * TO user", AuthQuery::Action::GRANT_PRIVILEGE, "", + "", "user", {}, {}, label_privileges, {}); + label_privileges.clear(); + + label_privileges.push_back({{{AuthQuery::FineGrainedPrivilege::READ}, {{"Label1"}, {"Label2"}}}}); + check_auth_query(&ast_generator, "GRANT READ ON LABELS :Label1, :Label2 TO user", AuthQuery::Action::GRANT_PRIVILEGE, + "", "", "user", {}, {}, label_privileges, {}); + label_privileges.clear(); + + label_privileges.push_back({{{AuthQuery::FineGrainedPrivilege::UPDATE}, {{"Label1"}, {"Label2"}}}}); + check_auth_query(&ast_generator, "GRANT UPDATE ON LABELS :Label1, :Label2 TO user", + AuthQuery::Action::GRANT_PRIVILEGE, "", "", "user", {}, {}, label_privileges, {}); + label_privileges.clear(); + + label_privileges.push_back({{{AuthQuery::FineGrainedPrivilege::CREATE_DELETE}, {{"Label1"}, {"Label2"}}}}); + check_auth_query(&ast_generator, "GRANT CREATE_DELETE ON LABELS :Label1, :Label2 TO user", + AuthQuery::Action::GRANT_PRIVILEGE, "", "", "user", {}, {}, label_privileges, {}); + label_privileges.clear(); + + label_privileges.push_back({{{AuthQuery::FineGrainedPrivilege::READ}, {{"Label1"}, {"Label2"}}}, + {{AuthQuery::FineGrainedPrivilege::UPDATE}, {{"Label3"}}}}); + check_auth_query(&ast_generator, "GRANT READ ON LABELS :Label1, :Label2, UPDATE ON LABELS :Label3 TO user", + AuthQuery::Action::GRANT_PRIVILEGE, "", "", "user", {}, {}, label_privileges, {}); + label_privileges.clear(); + + label_privileges.push_back({{{AuthQuery::FineGrainedPrivilege::READ}, {{"Label1"}, {"Label2"}}}}); + edge_type_privileges.push_back({{{AuthQuery::FineGrainedPrivilege::READ}, {{"Edge1"}, {"Edge2"}, {"Edge3"}}}}); + check_auth_query(&ast_generator, + "GRANT READ ON LABELS :Label1, :Label2, READ ON EDGE_TYPES :Edge1, :Edge2, :Edge3 TO user", + AuthQuery::Action::GRANT_PRIVILEGE, "", "", "user", {}, {}, label_privileges, edge_type_privileges); + label_privileges.clear(); + edge_type_privileges.clear(); } TEST_P(CypherMainVisitorTest, DenyPrivilege) { @@ -2223,36 +2280,83 @@ TEST_P(CypherMainVisitorTest, DenyPrivilege) { ASSERT_THROW(ast_generator.ParseQuery("DENY MATCH, TO user"), SyntaxException); ASSERT_THROW(ast_generator.ParseQuery("DENY MATCH, BLABLA TO user"), SyntaxException); check_auth_query(&ast_generator, "DENY MATCH TO user", AuthQuery::Action::DENY_PRIVILEGE, "", "", "user", {}, - {AuthQuery::Privilege::MATCH}); + {AuthQuery::Privilege::MATCH}, {}, {}); check_auth_query(&ast_generator, "DENY MATCH, AUTH TO user", AuthQuery::Action::DENY_PRIVILEGE, "", "", "user", {}, - {AuthQuery::Privilege::MATCH, AuthQuery::Privilege::AUTH}); + {AuthQuery::Privilege::MATCH, AuthQuery::Privilege::AUTH}, {}, {}); // Verify that all privileges are correctly visited. check_auth_query(&ast_generator, "DENY CREATE TO user", AuthQuery::Action::DENY_PRIVILEGE, "", "", "user", {}, - {AuthQuery::Privilege::CREATE}); + {AuthQuery::Privilege::CREATE}, {}, {}); check_auth_query(&ast_generator, "DENY DELETE TO user", AuthQuery::Action::DENY_PRIVILEGE, "", "", "user", {}, - {AuthQuery::Privilege::DELETE}); + {AuthQuery::Privilege::DELETE}, {}, {}); check_auth_query(&ast_generator, "DENY MERGE TO user", AuthQuery::Action::DENY_PRIVILEGE, "", "", "user", {}, - {AuthQuery::Privilege::MERGE}); + {AuthQuery::Privilege::MERGE}, {}, {}); check_auth_query(&ast_generator, "DENY SET TO user", AuthQuery::Action::DENY_PRIVILEGE, "", "", "user", {}, - {AuthQuery::Privilege::SET}); + {AuthQuery::Privilege::SET}, {}, {}); check_auth_query(&ast_generator, "DENY REMOVE TO user", AuthQuery::Action::DENY_PRIVILEGE, "", "", "user", {}, - {AuthQuery::Privilege::REMOVE}); + {AuthQuery::Privilege::REMOVE}, {}, {}); check_auth_query(&ast_generator, "DENY INDEX TO user", AuthQuery::Action::DENY_PRIVILEGE, "", "", "user", {}, - {AuthQuery::Privilege::INDEX}); + {AuthQuery::Privilege::INDEX}, {}, {}); check_auth_query(&ast_generator, "DENY STATS TO user", AuthQuery::Action::DENY_PRIVILEGE, "", "", "user", {}, - {AuthQuery::Privilege::STATS}); + {AuthQuery::Privilege::STATS}, {}, {}); check_auth_query(&ast_generator, "DENY AUTH TO user", AuthQuery::Action::DENY_PRIVILEGE, "", "", "user", {}, - {AuthQuery::Privilege::AUTH}); + {AuthQuery::Privilege::AUTH}, {}, {}); check_auth_query(&ast_generator, "DENY CONSTRAINT TO user", AuthQuery::Action::DENY_PRIVILEGE, "", "", "user", {}, - {AuthQuery::Privilege::CONSTRAINT}); + {AuthQuery::Privilege::CONSTRAINT}, {}, {}); check_auth_query(&ast_generator, "DENY DUMP TO user", AuthQuery::Action::DENY_PRIVILEGE, "", "", "user", {}, - {AuthQuery::Privilege::DUMP}); + {AuthQuery::Privilege::DUMP}, {}, {}); check_auth_query(&ast_generator, "DENY WEBSOCKET TO user", AuthQuery::Action::DENY_PRIVILEGE, "", "", "user", {}, - {AuthQuery::Privilege::WEBSOCKET}); + {AuthQuery::Privilege::WEBSOCKET}, {}, {}); check_auth_query(&ast_generator, "DENY MODULE_READ TO user", AuthQuery::Action::DENY_PRIVILEGE, "", "", "user", {}, - {AuthQuery::Privilege::MODULE_READ}); + {AuthQuery::Privilege::MODULE_READ}, {}, {}); check_auth_query(&ast_generator, "DENY MODULE_WRITE TO user", AuthQuery::Action::DENY_PRIVILEGE, "", "", "user", {}, - {AuthQuery::Privilege::MODULE_WRITE}); + {AuthQuery::Privilege::MODULE_WRITE}, {}, {}); + + std::vector<std::unordered_map<AuthQuery::FineGrainedPrivilege, std::vector<std::string>>> label_privileges{}; + std::vector<std::unordered_map<AuthQuery::FineGrainedPrivilege, std::vector<std::string>>> edge_type_privileges{}; + + label_privileges.push_back({{{AuthQuery::FineGrainedPrivilege::READ}, {{"*"}}}}); + check_auth_query(&ast_generator, "DENY READ ON LABELS * TO user", AuthQuery::Action::DENY_PRIVILEGE, "", "", "user", + {}, {}, label_privileges, {}); + label_privileges.clear(); + + label_privileges.push_back({{{AuthQuery::FineGrainedPrivilege::UPDATE}, {{"*"}}}}); + check_auth_query(&ast_generator, "DENY UPDATE ON LABELS * TO user", AuthQuery::Action::DENY_PRIVILEGE, "", "", "user", + {}, {}, label_privileges, {}); + label_privileges.clear(); + + label_privileges.push_back({{{AuthQuery::FineGrainedPrivilege::CREATE_DELETE}, {{"*"}}}}); + check_auth_query(&ast_generator, "DENY CREATE_DELETE ON LABELS * TO user", AuthQuery::Action::DENY_PRIVILEGE, "", "", + "user", {}, {}, label_privileges, {}); + label_privileges.clear(); + + label_privileges.push_back({{{AuthQuery::FineGrainedPrivilege::READ}, {{"Label1"}, {"Label2"}}}}); + check_auth_query(&ast_generator, "DENY READ ON LABELS :Label1, :Label2 TO user", AuthQuery::Action::DENY_PRIVILEGE, + "", "", "user", {}, {}, label_privileges, {}); + label_privileges.clear(); + + label_privileges.push_back({{{AuthQuery::FineGrainedPrivilege::UPDATE}, {{"Label1"}, {"Label2"}}}}); + check_auth_query(&ast_generator, "DENY UPDATE ON LABELS :Label1, :Label2 TO user", AuthQuery::Action::DENY_PRIVILEGE, + "", "", "user", {}, {}, label_privileges, {}); + label_privileges.clear(); + + label_privileges.push_back({{{AuthQuery::FineGrainedPrivilege::CREATE_DELETE}, {{"Label1"}, {"Label2"}}}}); + check_auth_query(&ast_generator, "DENY CREATE_DELETE ON LABELS :Label1, :Label2 TO user", + AuthQuery::Action::DENY_PRIVILEGE, "", "", "user", {}, {}, label_privileges, {}); + label_privileges.clear(); + + label_privileges.push_back({{{AuthQuery::FineGrainedPrivilege::READ}, {{"Label1"}, {"Label2"}}}, + {{AuthQuery::FineGrainedPrivilege::UPDATE}, {{"Label3"}}}}); + check_auth_query(&ast_generator, "DENY READ ON LABELS :Label1, :Label2, UPDATE ON LABELS :Label3 TO user", + AuthQuery::Action::DENY_PRIVILEGE, "", "", "user", {}, {}, label_privileges, {}); + label_privileges.clear(); + + label_privileges.push_back({{{AuthQuery::FineGrainedPrivilege::READ}, {{"Label1"}, {"Label2"}}}}); + edge_type_privileges.push_back({{{AuthQuery::FineGrainedPrivilege::READ}, {{"Edge1"}, {"Edge2"}, {"Edge3"}}}}); + check_auth_query(&ast_generator, + "DENY READ ON LABELS :Label1, :Label2, READ ON EDGE_TYPES :Edge1, :Edge2, :Edge3 TO user", + AuthQuery::Action::DENY_PRIVILEGE, "", "", "user", {}, {}, label_privileges, edge_type_privileges); + label_privileges.clear(); + edge_type_privileges.clear(); } TEST_P(CypherMainVisitorTest, RevokePrivilege) { @@ -2263,52 +2367,75 @@ TEST_P(CypherMainVisitorTest, RevokePrivilege) { ASSERT_THROW(ast_generator.ParseQuery("REVOKE MATCH, FROM user"), SyntaxException); ASSERT_THROW(ast_generator.ParseQuery("REVOKE MATCH, BLABLA FROM user"), SyntaxException); check_auth_query(&ast_generator, "REVOKE MATCH FROM user", AuthQuery::Action::REVOKE_PRIVILEGE, "", "", "user", {}, - {AuthQuery::Privilege::MATCH}); + {AuthQuery::Privilege::MATCH}, {}, {}); check_auth_query(&ast_generator, "REVOKE MATCH, AUTH FROM user", AuthQuery::Action::REVOKE_PRIVILEGE, "", "", "user", - {}, {AuthQuery::Privilege::MATCH, AuthQuery::Privilege::AUTH}); + {}, {AuthQuery::Privilege::MATCH, AuthQuery::Privilege::AUTH}, {}, {}); check_auth_query(&ast_generator, "REVOKE ALL PRIVILEGES FROM user", AuthQuery::Action::REVOKE_PRIVILEGE, "", "", - "user", {}, kPrivilegesAll); + "user", {}, kPrivilegesAll, {}, {}); // Verify that all privileges are correctly visited. check_auth_query(&ast_generator, "REVOKE CREATE FROM user", AuthQuery::Action::REVOKE_PRIVILEGE, "", "", "user", {}, - {AuthQuery::Privilege::CREATE}); + {AuthQuery::Privilege::CREATE}, {}, {}); check_auth_query(&ast_generator, "REVOKE DELETE FROM user", AuthQuery::Action::REVOKE_PRIVILEGE, "", "", "user", {}, - {AuthQuery::Privilege::DELETE}); + {AuthQuery::Privilege::DELETE}, {}, {}); check_auth_query(&ast_generator, "REVOKE MERGE FROM user", AuthQuery::Action::REVOKE_PRIVILEGE, "", "", "user", {}, - {AuthQuery::Privilege::MERGE}); + {AuthQuery::Privilege::MERGE}, {}, {}); check_auth_query(&ast_generator, "REVOKE SET FROM user", AuthQuery::Action::REVOKE_PRIVILEGE, "", "", "user", {}, - {AuthQuery::Privilege::SET}); + {AuthQuery::Privilege::SET}, {}, {}); check_auth_query(&ast_generator, "REVOKE REMOVE FROM user", AuthQuery::Action::REVOKE_PRIVILEGE, "", "", "user", {}, - {AuthQuery::Privilege::REMOVE}); + {AuthQuery::Privilege::REMOVE}, {}, {}); check_auth_query(&ast_generator, "REVOKE INDEX FROM user", AuthQuery::Action::REVOKE_PRIVILEGE, "", "", "user", {}, - {AuthQuery::Privilege::INDEX}); + {AuthQuery::Privilege::INDEX}, {}, {}); check_auth_query(&ast_generator, "REVOKE STATS FROM user", AuthQuery::Action::REVOKE_PRIVILEGE, "", "", "user", {}, - {AuthQuery::Privilege::STATS}); + {AuthQuery::Privilege::STATS}, {}, {}); check_auth_query(&ast_generator, "REVOKE AUTH FROM user", AuthQuery::Action::REVOKE_PRIVILEGE, "", "", "user", {}, - {AuthQuery::Privilege::AUTH}); + {AuthQuery::Privilege::AUTH}, {}, {}); check_auth_query(&ast_generator, "REVOKE CONSTRAINT FROM user", AuthQuery::Action::REVOKE_PRIVILEGE, "", "", "user", - {}, {AuthQuery::Privilege::CONSTRAINT}); + {}, {AuthQuery::Privilege::CONSTRAINT}, {}, {}); check_auth_query(&ast_generator, "REVOKE DUMP FROM user", AuthQuery::Action::REVOKE_PRIVILEGE, "", "", "user", {}, - {AuthQuery::Privilege::DUMP}); + {AuthQuery::Privilege::DUMP}, {}, {}); check_auth_query(&ast_generator, "REVOKE WEBSOCKET FROM user", AuthQuery::Action::REVOKE_PRIVILEGE, "", "", "user", - {}, {AuthQuery::Privilege::WEBSOCKET}); + {}, {AuthQuery::Privilege::WEBSOCKET}, {}, {}); check_auth_query(&ast_generator, "REVOKE MODULE_READ FROM user", AuthQuery::Action::REVOKE_PRIVILEGE, "", "", "user", - {}, {AuthQuery::Privilege::MODULE_READ}); + {}, {AuthQuery::Privilege::MODULE_READ}, {}, {}); check_auth_query(&ast_generator, "REVOKE MODULE_WRITE FROM user", AuthQuery::Action::REVOKE_PRIVILEGE, "", "", "user", - {}, {AuthQuery::Privilege::MODULE_WRITE}); + {}, {AuthQuery::Privilege::MODULE_WRITE}, {}, {}); + + std::vector<std::unordered_map<AuthQuery::FineGrainedPrivilege, std::vector<std::string>>> label_privileges{}; + std::vector<std::unordered_map<AuthQuery::FineGrainedPrivilege, std::vector<std::string>>> edge_type_privileges{}; + + label_privileges.push_back({{{AuthQuery::FineGrainedPrivilege::CREATE_DELETE}, {{"*"}}}}); + check_auth_query(&ast_generator, "REVOKE LABELS * FROM user", AuthQuery::Action::REVOKE_PRIVILEGE, "", "", "user", {}, + {}, label_privileges, {}); + label_privileges.clear(); + + label_privileges.push_back({{{AuthQuery::FineGrainedPrivilege::CREATE_DELETE}, {{"Label1"}, {"Label2"}}}}); + check_auth_query(&ast_generator, "REVOKE LABELS :Label1, :Label2 FROM user", AuthQuery::Action::REVOKE_PRIVILEGE, "", + "", "user", {}, {}, label_privileges, {}); + label_privileges.clear(); + + label_privileges.push_back({{{AuthQuery::FineGrainedPrivilege::CREATE_DELETE}, {{"Label1"}, {"Label2"}}}}); + edge_type_privileges.push_back( + {{{AuthQuery::FineGrainedPrivilege::CREATE_DELETE}, {{"Edge1"}, {"Edge2"}, {"Edge3"}}}}); + check_auth_query(&ast_generator, "REVOKE LABELS :Label1, :Label2, EDGE_TYPES :Edge1, :Edge2, :Edge3 FROM user", + AuthQuery::Action::REVOKE_PRIVILEGE, "", "", "user", {}, {}, label_privileges, edge_type_privileges); + + label_privileges.clear(); + edge_type_privileges.clear(); } TEST_P(CypherMainVisitorTest, ShowPrivileges) { auto &ast_generator = *GetParam(); ASSERT_THROW(ast_generator.ParseQuery("SHOW PRIVILEGES FOR"), SyntaxException); check_auth_query(&ast_generator, "SHOW PRIVILEGES FOR user", AuthQuery::Action::SHOW_PRIVILEGES, "", "", "user", {}, - {}); + {}, {}, {}); ASSERT_THROW(ast_generator.ParseQuery("SHOW PRIVILEGES FOR user1, user2"), SyntaxException); } TEST_P(CypherMainVisitorTest, ShowRoleForUser) { auto &ast_generator = *GetParam(); ASSERT_THROW(ast_generator.ParseQuery("SHOW ROLE FOR "), SyntaxException); - check_auth_query(&ast_generator, "SHOW ROLE FOR user", AuthQuery::Action::SHOW_ROLE_FOR_USER, "user", "", "", {}, {}); + check_auth_query(&ast_generator, "SHOW ROLE FOR user", AuthQuery::Action::SHOW_ROLE_FOR_USER, "user", "", "", {}, {}, + {}, {}); ASSERT_THROW(ast_generator.ParseQuery("SHOW ROLE FOR user1, user2"), SyntaxException); } @@ -2316,7 +2443,7 @@ TEST_P(CypherMainVisitorTest, ShowUsersForRole) { auto &ast_generator = *GetParam(); ASSERT_THROW(ast_generator.ParseQuery("SHOW USERS FOR "), SyntaxException); check_auth_query(&ast_generator, "SHOW USERS FOR role", AuthQuery::Action::SHOW_USERS_FOR_ROLE, "", "role", "", {}, - {}); + {}, {}, {}); ASSERT_THROW(ast_generator.ParseQuery("SHOW USERS FOR role1, role2"), SyntaxException); } diff --git a/tests/unit/query_plan_match_filter_return.cpp b/tests/unit/query_plan_match_filter_return.cpp index 3d6256db5..bfca686a7 100644 --- a/tests/unit/query_plan_match_filter_return.cpp +++ b/tests/unit/query_plan_match_filter_return.cpp @@ -427,11 +427,12 @@ TEST_F(ExpandFixture, ExpandWithEdgeFiltering) { auto user = memgraph::auth::User("test"); - user.fine_grained_access_handler().edge_type_permissions().Grant("Edge", - memgraph::auth::LabelPermission::CREATE_DELETE); + user.fine_grained_access_handler().edge_type_permissions().Grant( + "Edge", memgraph::auth::FineGrainedPermission::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::auth::FineGrainedPermission::READ); + user.fine_grained_access_handler().label_permissions().Grant("*", + memgraph::auth::FineGrainedPermission::CREATE_DELETE); memgraph::storage::EdgeTypeId edge_type_test{db.NameToEdgeType("edge_type_test")}; ASSERT_TRUE(dba.InsertEdge(&v1, &v2, edge_type_test).HasValue()); @@ -450,8 +451,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", - memgraph::auth::LabelPermission::CREATE_DELETE); + user.fine_grained_access_handler().edge_type_permissions().Grant( + "edge_type_test", memgraph::auth::FineGrainedPermission::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)); diff --git a/tests/unit/query_required_privileges.cpp b/tests/unit/query_required_privileges.cpp index 1a1fa1efa..82f607c12 100644 --- a/tests/unit/query_required_privileges.cpp +++ b/tests/unit/query_required_privileges.cpp @@ -11,6 +11,7 @@ #include <gmock/gmock.h> #include <gtest/gtest.h> +#include <unordered_map> #include "query/frontend/ast/ast.hpp" #include "query/frontend/ast/ast_visitor.hpp" @@ -98,8 +99,11 @@ TEST_F(TestPrivilegeExtractor, CreateIndex) { } TEST_F(TestPrivilegeExtractor, AuthQuery) { + 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>>>{}; auto *query = AUTH_QUERY(AuthQuery::Action::CREATE_ROLE, "", "role", "", nullptr, std::vector<AuthQuery::Privilege>{}, - std::vector<std::string>{}, std::vector<std::string>{}); + label_privileges, edge_type_privileges); EXPECT_THAT(GetRequiredPrivileges(query), UnorderedElementsAre(AuthQuery::Privilege::AUTH)); }