Compare commits
34 Commits
cpp23
...
T444-FL-no
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3f5cb9c81d | ||
|
|
ec68d53404 | ||
|
|
a5cfc617fd | ||
|
|
3c87a5d939 | ||
|
|
3a183986c9 | ||
|
|
db655dab5e | ||
|
|
efa64fc864 | ||
|
|
19dff1ae5c | ||
|
|
41ae33c671 | ||
|
|
10f2c416bd | ||
|
|
216abaa0ef | ||
|
|
b0af87ed9b | ||
|
|
5b92aae0d3 | ||
|
|
6f2aaee91b | ||
|
|
83aa71a29f | ||
|
|
a821827dc3 | ||
|
|
ace8608dd7 | ||
|
|
c2a1328dcc | ||
|
|
b63db202d6 | ||
|
|
1abe8f8bfc | ||
|
|
4366085d89 | ||
|
|
d626b49cc4 | ||
|
|
9369ae9085 | ||
|
|
d657a77a57 | ||
|
|
20da673583 | ||
|
|
ca95ac253b | ||
|
|
b1c06e4d9f | ||
|
|
86a15331d1 | ||
|
|
0c8b35b151 | ||
|
|
11d60c203e | ||
|
|
38c0a08342 | ||
|
|
7e1d39bf86 | ||
|
|
dd85b428bf | ||
|
|
2f9ed0146e |
43
libs/antlr4.patch
Normal file
43
libs/antlr4.patch
Normal file
@@ -0,0 +1,43 @@
|
||||
diff --git a/runtime/Cpp/runtime/CMakeLists.txt b/runtime/Cpp/runtime/CMakeLists.txt
|
||||
index a8503bb..11362cf 100644
|
||||
--- a/runtime/Cpp/runtime/CMakeLists.txt
|
||||
+++ b/runtime/Cpp/runtime/CMakeLists.txt
|
||||
@@ -5,8 +5,8 @@ set(THIRDPARTY_DIR ${CMAKE_BINARY_DIR}/runtime/thirdparty)
|
||||
set(UTFCPP_DIR ${THIRDPARTY_DIR}/utfcpp)
|
||||
ExternalProject_Add(
|
||||
utfcpp
|
||||
- GIT_REPOSITORY "git://github.com/nemtrif/utfcpp"
|
||||
- GIT_TAG "v3.1.1"
|
||||
+ GIT_REPOSITORY "https://github.com/nemtrif/utfcpp"
|
||||
+ GIT_TAG "v3.2.1"
|
||||
SOURCE_DIR ${UTFCPP_DIR}
|
||||
UPDATE_DISCONNECTED 1
|
||||
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${UTFCPP_DIR}/install -Dgtest_force_shared_crt=ON
|
||||
@@ -118,7 +118,7 @@ set_target_properties(antlr4_static
|
||||
ARCHIVE_OUTPUT_DIRECTORY ${LIB_OUTPUT_DIR}
|
||||
COMPILE_FLAGS "${disabled_compile_warnings} ${extra_static_compile_flags}")
|
||||
|
||||
-install(TARGETS antlr4_shared
|
||||
+install(TARGETS antlr4_shared OPTIONAL
|
||||
DESTINATION lib
|
||||
EXPORT antlr4-targets)
|
||||
install(TARGETS antlr4_static
|
||||
diff --git a/runtime/Cpp/runtime/src/support/Any.h b/runtime/Cpp/runtime/src/support/Any.h
|
||||
index 468db98..65a473b 100644
|
||||
--- a/runtime/Cpp/runtime/src/support/Any.h
|
||||
+++ b/runtime/Cpp/runtime/src/support/Any.h
|
||||
@@ -122,12 +122,12 @@ private:
|
||||
}
|
||||
|
||||
private:
|
||||
- template<int N = 0, typename std::enable_if<N == N && std::is_nothrow_copy_constructible<T>::value, int>::type = 0>
|
||||
+ template<int N = 0, typename std::enable_if<N == N && std::is_copy_constructible<T>::value, int>::type = 0>
|
||||
Base* clone() const {
|
||||
return new Derived<T>(value);
|
||||
}
|
||||
|
||||
- template<int N = 0, typename std::enable_if<N == N && !std::is_nothrow_copy_constructible<T>::value, int>::type = 0>
|
||||
+ template<int N = 0, typename std::enable_if<N == N && !std::is_copy_constructible<T>::value, int>::type = 0>
|
||||
Base* clone() const {
|
||||
return nullptr;
|
||||
}
|
||||
@@ -8,7 +8,10 @@
|
||||
|
||||
#include "auth/models.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <regex>
|
||||
#include <unordered_set>
|
||||
|
||||
#include <gflags/gflags.h>
|
||||
|
||||
@@ -84,6 +87,8 @@ std::string PermissionToString(Permission permission) {
|
||||
return "MODULE_WRITE";
|
||||
case Permission::WEBSOCKET:
|
||||
return "WEBSOCKET";
|
||||
case Permission::LABELS:
|
||||
return "LABELS";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -98,12 +103,9 @@ std::string PermissionLevelToString(PermissionLevel level) {
|
||||
}
|
||||
}
|
||||
|
||||
Permissions::Permissions(uint64_t grants, uint64_t denies) {
|
||||
// The deny bitmask has higher priority than the grant bitmask.
|
||||
denies_ = denies;
|
||||
// Mask out the grant bitmask to make sure that it is correct.
|
||||
grants_ = grants & (~denies);
|
||||
}
|
||||
const std::string ASTERISK = "*";
|
||||
|
||||
Permissions::Permissions(uint64_t grants, uint64_t denies) : grants_(grants & (~denies)), denies_(denies) {}
|
||||
|
||||
PermissionLevel Permissions::Has(Permission permission) const {
|
||||
// Check for the deny first because it has greater priority than a grant.
|
||||
@@ -183,8 +185,6 @@ bool operator==(const Permissions &first, const Permissions &second) {
|
||||
|
||||
bool operator!=(const Permissions &first, const Permissions &second) { return !(first == second); }
|
||||
|
||||
const std::string ASTERISK = "*";
|
||||
|
||||
FineGrainedAccessPermissions::FineGrainedAccessPermissions(const std::unordered_set<std::string> &grants,
|
||||
const std::unordered_set<std::string> &denies)
|
||||
: grants_(grants), denies_(denies) {}
|
||||
@@ -332,7 +332,8 @@ Role Role::Deserialize(const nlohmann::json &data) {
|
||||
}
|
||||
|
||||
bool operator==(const Role &first, const Role &second) {
|
||||
return first.rolename_ == second.rolename_ && first.permissions_ == second.permissions_;
|
||||
return first.rolename_ == second.rolename_ && first.permissions_ == second.permissions_ &&
|
||||
first.fine_grained_access_permissions_ == second.fine_grained_access_permissions_;
|
||||
}
|
||||
|
||||
User::User(const std::string &username) : username_(utils::ToLowerCase(username)) {}
|
||||
@@ -385,8 +386,8 @@ void User::ClearRole() { role_ = std::nullopt; }
|
||||
|
||||
Permissions User::GetPermissions() const {
|
||||
if (role_) {
|
||||
return Permissions(permissions_.grants() | role_->permissions().grants(),
|
||||
permissions_.denies() | role_->permissions().denies());
|
||||
return {permissions_.grants() | role_->permissions().grants(),
|
||||
permissions_.denies() | role_->permissions().denies()};
|
||||
}
|
||||
return permissions_;
|
||||
}
|
||||
@@ -453,6 +454,9 @@ User User::Deserialize(const nlohmann::json &data) {
|
||||
|
||||
bool operator==(const User &first, const User &second) {
|
||||
return first.username_ == second.username_ && first.password_hash_ == second.password_hash_ &&
|
||||
first.permissions_ == second.permissions_ && first.role_ == second.role_;
|
||||
first.permissions_ == second.permissions_ &&
|
||||
first.fine_grained_access_permissions_ == second.fine_grained_access_permissions_ &&
|
||||
first.role_ == second.role_;
|
||||
}
|
||||
|
||||
} // namespace memgraph::auth
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include <unordered_set>
|
||||
|
||||
#include <json/json.hpp>
|
||||
#include <unordered_set>
|
||||
|
||||
namespace memgraph::auth {
|
||||
// These permissions must have values that are applicable for usage in a
|
||||
@@ -39,7 +40,8 @@ enum class Permission : uint64_t {
|
||||
STREAM = 1U << 17U,
|
||||
MODULE_READ = 1U << 18U,
|
||||
MODULE_WRITE = 1U << 19U,
|
||||
WEBSOCKET = 1U << 20U
|
||||
WEBSOCKET = 1U << 20U,
|
||||
LABELS = 1U << 21U
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
@@ -193,4 +195,5 @@ class User final {
|
||||
};
|
||||
|
||||
bool operator==(const User &first, const User &second);
|
||||
|
||||
} // namespace memgraph::auth
|
||||
|
||||
@@ -18,19 +18,24 @@ roles_config = config["roles"]
|
||||
# Initialize LDAP server.
|
||||
tls = None
|
||||
if server_config["encryption"] != "disabled":
|
||||
cert_file = server_config["cert_file"] if server_config["cert_file"] \
|
||||
else None
|
||||
cert_file = server_config["cert_file"] if server_config["cert_file"] else None
|
||||
key_file = server_config["key_file"] if server_config["key_file"] else None
|
||||
ca_file = server_config["ca_file"] if server_config["ca_file"] else None
|
||||
validate = ssl.CERT_REQUIRED if server_config["validate_cert"] \
|
||||
else ssl.CERT_NONE
|
||||
tls = ldap3.Tls(local_private_key_file=key_file,
|
||||
local_certificate_file=cert_file,
|
||||
ca_certs_file=ca_file,
|
||||
validate=validate)
|
||||
validate = ssl.CERT_REQUIRED if server_config["validate_cert"] else ssl.CERT_NONE
|
||||
tls = ldap3.Tls(
|
||||
local_private_key_file=key_file,
|
||||
local_certificate_file=cert_file,
|
||||
ca_certs_file=ca_file,
|
||||
validate=validate,
|
||||
)
|
||||
use_ssl = server_config["encryption"] == "ssl"
|
||||
server = ldap3.Server(server_config["host"], port=server_config["port"],
|
||||
tls=tls, use_ssl=use_ssl, get_info=ldap3.ALL)
|
||||
server = ldap3.Server(
|
||||
server_config["host"],
|
||||
port=server_config["port"],
|
||||
tls=tls,
|
||||
use_ssl=use_ssl,
|
||||
get_info=ldap3.ALL,
|
||||
)
|
||||
|
||||
|
||||
# Main authentication/authorization function.
|
||||
@@ -40,14 +45,12 @@ def authenticate(username, password):
|
||||
return {"authenticated": False, "role": ""}
|
||||
|
||||
# Create the DN of the user
|
||||
dn = users_config["prefix"] + ldap3.utils.dn.escape_rdn(username) + \
|
||||
users_config["suffix"]
|
||||
dn = users_config["prefix"] + ldap3.utils.dn.escape_rdn(username) + users_config["suffix"]
|
||||
|
||||
# Bind to the server
|
||||
conn = ldap3.Connection(server, dn, password)
|
||||
if server_config["encryption"] == "starttls" and not conn.start_tls():
|
||||
print("ERROR: Couldn't issue STARTTLS to the LDAP server!",
|
||||
file=sys.stderr)
|
||||
print("ERROR: Couldn't issue STARTTLS to the LDAP server!", file=sys.stderr)
|
||||
return {"authenticated": False, "role": ""}
|
||||
if not conn.bind():
|
||||
return {"authenticated": False, "role": ""}
|
||||
@@ -56,25 +59,32 @@ def authenticate(username, password):
|
||||
if roles_config["root_dn"] != "":
|
||||
# search for role
|
||||
search_filter = "(&(objectclass={objclass})({attr}={value}))".format(
|
||||
objclass=roles_config["root_objectclass"],
|
||||
attr=roles_config["user_attribute"],
|
||||
value=ldap3.utils.conv.escape_filter_chars(dn))
|
||||
succ = conn.search(roles_config["root_dn"], search_filter,
|
||||
search_scope=ldap3.LEVEL,
|
||||
attributes=[roles_config["role_attribute"]])
|
||||
objclass=roles_config["root_objectclass"],
|
||||
attr=roles_config["user_attribute"],
|
||||
value=ldap3.utils.conv.escape_filter_chars(dn),
|
||||
)
|
||||
succ = conn.search(
|
||||
roles_config["root_dn"],
|
||||
search_filter,
|
||||
search_scope=ldap3.LEVEL,
|
||||
attributes=[roles_config["role_attribute"]],
|
||||
)
|
||||
if not succ or len(conn.entries) == 0:
|
||||
return {"authenticated": True, "role": ""}
|
||||
if len(conn.entries) > 1:
|
||||
roles = list(map(lambda x: x[roles_config["role_attribute"]].value,
|
||||
conn.entries))
|
||||
roles = list(map(lambda x: x[roles_config["role_attribute"]].value, conn.entries))
|
||||
# Because we don't know exactly which role the user should have
|
||||
# we authorize the user with an empty role.
|
||||
print("WARNING: Found more than one role for "
|
||||
"user '" + username + "':", ", ".join(roles) + "!",
|
||||
file=sys.stderr)
|
||||
print(
|
||||
"WARNING: Found more than one role for " "user '" + username + "':",
|
||||
", ".join(roles) + "!",
|
||||
file=sys.stderr,
|
||||
)
|
||||
return {"authenticated": True, "role": ""}
|
||||
return {"authenticated": True,
|
||||
"role": conn.entries[0][roles_config["role_attribute"]].value}
|
||||
return {
|
||||
"authenticated": True,
|
||||
"role": conn.entries[0][roles_config["role_attribute"]].value,
|
||||
}
|
||||
else:
|
||||
return {"authenticated": True, "role": ""}
|
||||
|
||||
|
||||
@@ -57,6 +57,8 @@ auth::Permission PrivilegeToPermission(query::AuthQuery::Privilege privilege) {
|
||||
return auth::Permission::MODULE_WRITE;
|
||||
case query::AuthQuery::Privilege::WEBSOCKET:
|
||||
return auth::Permission::WEBSOCKET;
|
||||
case query::AuthQuery::Privilege::LABELS:
|
||||
return auth::Permission::LABELS;
|
||||
}
|
||||
}
|
||||
} // namespace memgraph::glue
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
#include "helpers.hpp"
|
||||
#include "py/py.hpp"
|
||||
#include "query/auth_checker.hpp"
|
||||
#include "query/db_accessor.hpp"
|
||||
#include "query/discard_value_stream.hpp"
|
||||
#include "query/exceptions.hpp"
|
||||
#include "query/frontend/ast/ast.hpp"
|
||||
|
||||
@@ -13,9 +13,11 @@
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
#include "auth/models.hpp"
|
||||
#include "query/common.hpp"
|
||||
#include "query/fine_grained_access_checker.hpp"
|
||||
#include "query/frontend/semantic/symbol_table.hpp"
|
||||
#include "query/label_checker.hpp"
|
||||
#include "query/metadata.hpp"
|
||||
#include "query/parameters.hpp"
|
||||
#include "query/plan/profile.hpp"
|
||||
|
||||
@@ -2240,6 +2240,7 @@ cpp<#
|
||||
(user "std::string" :scope :public)
|
||||
(role "std::string" :scope :public)
|
||||
(user-or-role "std::string" :scope :public)
|
||||
|
||||
(password "Expression *" :initval "nullptr" :scope :public
|
||||
:slk-save #'slk-save-ast-pointer
|
||||
:slk-load (slk-load-ast-pointer "Expression"))
|
||||
@@ -2255,7 +2256,7 @@ cpp<#
|
||||
(lcp:define-enum privilege
|
||||
(create delete match merge set remove index stats auth constraint
|
||||
dump replication durability read_file free_memory trigger config stream module_read module_write
|
||||
websocket)
|
||||
websocket labels)
|
||||
(:serialize))
|
||||
#>cpp
|
||||
AuthQuery() = default;
|
||||
@@ -2298,7 +2299,8 @@ const std::vector<AuthQuery::Privilege> kPrivilegesAll = {
|
||||
AuthQuery::Privilege::FREE_MEMORY, AuthQuery::Privilege::TRIGGER,
|
||||
AuthQuery::Privilege::CONFIG, AuthQuery::Privilege::STREAM,
|
||||
AuthQuery::Privilege::MODULE_READ, AuthQuery::Privilege::MODULE_WRITE,
|
||||
AuthQuery::Privilege::WEBSOCKET};
|
||||
AuthQuery::Privilege::WEBSOCKET,
|
||||
AuthQuery::Privilege::LABELS};
|
||||
cpp<#
|
||||
|
||||
(lcp:define-class info-query (query)
|
||||
|
||||
@@ -1372,6 +1372,10 @@ antlrcpp::Any CypherMainVisitor::visitPrivilege(MemgraphCypher::PrivilegeContext
|
||||
if (ctx->MODULE_READ()) return AuthQuery::Privilege::MODULE_READ;
|
||||
if (ctx->MODULE_WRITE()) return AuthQuery::Privilege::MODULE_WRITE;
|
||||
if (ctx->WEBSOCKET()) return AuthQuery::Privilege::WEBSOCKET;
|
||||
if (ctx->LABELS()) {
|
||||
// fill labels in authquery
|
||||
return AuthQuery::Privilege::LABELS;
|
||||
}
|
||||
LOG_FATAL("Should not get here - unknown privilege!");
|
||||
}
|
||||
|
||||
|
||||
@@ -473,16 +473,16 @@ class CypherMainVisitor : public antlropencypher::MemgraphCypherBaseVisitor {
|
||||
*/
|
||||
antlrcpp::Any visitPrivilege(MemgraphCypher::PrivilegeContext *ctx) override;
|
||||
|
||||
/**
|
||||
* @return AuthQuery*
|
||||
*/
|
||||
antlrcpp::Any visitShowPrivileges(MemgraphCypher::ShowPrivilegesContext *ctx) override;
|
||||
|
||||
/**
|
||||
* @return AuthQuery::LabelList
|
||||
*/
|
||||
antlrcpp::Any visitLabelList(MemgraphCypher::LabelListContext *ctx) override;
|
||||
|
||||
/**
|
||||
* @return AuthQuery*
|
||||
*/
|
||||
antlrcpp::Any visitShowPrivileges(MemgraphCypher::ShowPrivilegesContext *ctx) override;
|
||||
|
||||
/**
|
||||
* @return AuthQuery*
|
||||
*/
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
#include "query/frontend/semantic/required_privileges.hpp"
|
||||
#include "query/frontend/semantic/symbol_generator.hpp"
|
||||
#include "query/interpret/eval.hpp"
|
||||
#include "query/label_checker.hpp"
|
||||
#include "query/metadata.hpp"
|
||||
#include "query/plan/planner.hpp"
|
||||
#include "query/plan/profile.hpp"
|
||||
@@ -292,6 +293,7 @@ Callback HandleAuthQuery(AuthQuery *auth_query, AuthQueryHandler *auth, const Pa
|
||||
// TODO: MemoryResource for EvaluationContext, it should probably be passed as
|
||||
// the argument to Callback.
|
||||
evaluation_context.timestamp = QueryTimestamp();
|
||||
|
||||
evaluation_context.parameters = parameters;
|
||||
ExpressionEvaluator evaluator(&frame, symbol_table, evaluation_context, db_accessor, storage::View::OLD);
|
||||
|
||||
@@ -1146,6 +1148,7 @@ PreparedQuery PrepareCypherQuery(ParsedQuery parsed_query, std::map<std::string,
|
||||
EvaluationContext evaluation_context;
|
||||
evaluation_context.timestamp = QueryTimestamp();
|
||||
evaluation_context.parameters = parsed_query.parameters;
|
||||
|
||||
ExpressionEvaluator evaluator(&frame, symbol_table, evaluation_context, dba, storage::View::OLD);
|
||||
const auto memory_limit = EvaluateMemoryLimit(&evaluator, cypher_query->memory_limit_, cypher_query->memory_scale_);
|
||||
if (memory_limit) {
|
||||
|
||||
@@ -91,6 +91,9 @@ class AuthQueryHandler {
|
||||
/// @throw QueryRuntimeException if an error ocurred.
|
||||
virtual std::vector<TypedValue> GetUsernamesForRole(const std::string &rolename) = 0;
|
||||
|
||||
/// @throw QueryRuntimeException if an error ocurred.
|
||||
virtual memgraph::auth::User *GetUser(const std::string &username) = 0;
|
||||
|
||||
/// @throw QueryRuntimeException if an error ocurred.
|
||||
virtual void SetRole(const std::string &username, const std::string &rolename) = 0;
|
||||
|
||||
@@ -99,9 +102,6 @@ class AuthQueryHandler {
|
||||
|
||||
virtual std::vector<std::vector<TypedValue>> GetPrivileges(const std::string &user_or_role) = 0;
|
||||
|
||||
/// @throw QueryRuntimeException if an error ocurred.
|
||||
virtual memgraph::auth::User *GetUser(const std::string &username) = 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) = 0;
|
||||
|
||||
24
src/query/label_checker.hpp
Normal file
24
src/query/label_checker.hpp
Normal file
@@ -0,0 +1,24 @@
|
||||
// Copyright 2022 Memgraph Ltd.
|
||||
//
|
||||
// Use of this software is governed by the Business Source License
|
||||
// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
|
||||
// License, and you may not use this file except in compliance with the Business Source License.
|
||||
//
|
||||
// As of the Change Date specified in that file, in accordance with
|
||||
// the Business Source License, use of this software will be governed
|
||||
// by the Apache License, Version 2.0, included in the file
|
||||
// licenses/APL.txt.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "auth/models.hpp"
|
||||
#include "query/frontend/ast/ast.hpp"
|
||||
#include "storage/v2/id_types.hpp"
|
||||
|
||||
namespace memgraph::query {
|
||||
class LabelChecker {
|
||||
public:
|
||||
virtual bool IsUserAuthorized(const std::vector<memgraph::storage::LabelId> &label,
|
||||
memgraph::query::DbAccessor *dba) const = 0;
|
||||
};
|
||||
} // namespace memgraph::query
|
||||
@@ -32,6 +32,7 @@
|
||||
#include "query/frontend/ast/ast.hpp"
|
||||
#include "query/frontend/semantic/symbol_table.hpp"
|
||||
#include "query/interpret/eval.hpp"
|
||||
#include "query/label_checker.hpp"
|
||||
#include "query/path.hpp"
|
||||
#include "query/plan/scoped_profile.hpp"
|
||||
#include "query/procedure/cypher_types.hpp"
|
||||
@@ -394,8 +395,8 @@ class ScanAllCursor : public Cursor {
|
||||
|
||||
while (!vertices_ || vertices_it_.value() == vertices_.value().end()) {
|
||||
if (!input_cursor_->Pull(frame, context)) return false;
|
||||
// We need a getter function, because in case of exhausting a lazy
|
||||
// iterable, we cannot simply reset it by calling begin().
|
||||
// We need a getter function, because in case of exhausting a lazy iterable,
|
||||
// we cannot simply reset it by calling begin().
|
||||
auto next_vertices = get_vertices_(frame, context);
|
||||
if (!next_vertices) continue;
|
||||
// Since vertices iterator isn't nothrow_move_assignable, we have to use
|
||||
@@ -405,11 +406,29 @@ class ScanAllCursor : public Cursor {
|
||||
vertices_it_.emplace(vertices_.value().begin());
|
||||
}
|
||||
|
||||
#ifdef MG_ENTERPRISE
|
||||
FilterNodes(context.label_checker, context.db_accessor);
|
||||
if (vertices_it_.value() == vertices_.value().end()) return false;
|
||||
#endif
|
||||
|
||||
frame[output_symbol_] = *vertices_it_.value();
|
||||
++vertices_it_.value();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void FilterNodes(const LabelChecker *label_checker, DbAccessor *dba) {
|
||||
if (!label_checker) return;
|
||||
while (vertices_it_.value() != vertices_.value().end()) {
|
||||
VertexAccessor vertex = *vertices_it_.value();
|
||||
auto vertex_labels = vertex.Labels(memgraph::storage::View::NEW).GetValue();
|
||||
if (label_checker->IsUserAuthorized(vertex_labels, dba)) {
|
||||
break;
|
||||
}
|
||||
++vertices_it_.value();
|
||||
}
|
||||
}
|
||||
|
||||
void Shutdown() override { input_cursor_->Shutdown(); }
|
||||
|
||||
void Reset() override {
|
||||
|
||||
Reference in New Issue
Block a user