[E129 < T0996] C-API: Implement using Fine Grained Access Checker in iterator over vertices (#494)
* implemented skipping vertices in Constructor and mgp_vertices_iterator_next * Added utility function for moving iterator to next permitted vertex * removed ifdef directive * NextPermitted parameter type changed from mgp_vertices_iterator* to mgp_vertices_iterator& * created support for lba-procedures e2e testing; Added test for vertex iterator skipping unauthorized vertices * removed fixture from tests; converted generator to regular function;
This commit is contained in:
parent
116262d9a0
commit
a98463b0bd
@ -2250,6 +2250,39 @@ mgp_error mgp_graph_delete_edge(struct mgp_graph *graph, mgp_edge *edge) {
|
||||
});
|
||||
}
|
||||
|
||||
namespace {
|
||||
void NextPermitted(mgp_vertices_iterator &it) {
|
||||
const auto *checker = it.graph->ctx->fine_grained_access_checker;
|
||||
|
||||
if (!checker) {
|
||||
return;
|
||||
}
|
||||
|
||||
while (it.current_it != it.vertices.end()) {
|
||||
auto labels = (*it.current_it).impl_.Labels(it.graph->view);
|
||||
if (!labels.HasValue()) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (checker->IsUserAuthorizedLabels(labels.GetValue(), it.graph->ctx->db_accessor)) {
|
||||
break;
|
||||
}
|
||||
|
||||
++it.current_it;
|
||||
}
|
||||
};
|
||||
} // namespace
|
||||
|
||||
/// @throw anything VerticesIterable may throw
|
||||
mgp_vertices_iterator::mgp_vertices_iterator(mgp_graph *graph, memgraph::utils::MemoryResource *memory)
|
||||
: memory(memory), graph(graph), vertices(graph->impl->Vertices(graph->view)), current_it(vertices.begin()) {
|
||||
NextPermitted(*this);
|
||||
|
||||
if (current_it != vertices.end()) {
|
||||
current_v.emplace(*current_it, graph, memory);
|
||||
}
|
||||
}
|
||||
|
||||
void mgp_vertices_iterator_destroy(mgp_vertices_iterator *it) { DeleteRawMgpObject(it); }
|
||||
|
||||
mgp_error mgp_graph_iter_vertices(mgp_graph *graph, mgp_memory *memory, mgp_vertices_iterator **result) {
|
||||
@ -2280,10 +2313,16 @@ mgp_error mgp_vertices_iterator_next(mgp_vertices_iterator *it, mgp_vertex **res
|
||||
"should have been set to std::nullopt");
|
||||
return nullptr;
|
||||
}
|
||||
if (++it->current_it == it->vertices.end()) {
|
||||
|
||||
++it->current_it;
|
||||
|
||||
NextPermitted(*it);
|
||||
|
||||
if (it->current_it == it->vertices.end()) {
|
||||
it->current_v = std::nullopt;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
memgraph::utils::OnScopeExit clean_up([it] { it->current_v = std::nullopt; });
|
||||
it->current_v.emplace(*it->current_it, it->graph, it->GetMemoryResource());
|
||||
clean_up.Disable();
|
||||
|
@ -673,12 +673,7 @@ struct mgp_vertices_iterator {
|
||||
using allocator_type = memgraph::utils::Allocator<mgp_vertices_iterator>;
|
||||
|
||||
/// @throw anything VerticesIterable may throw
|
||||
mgp_vertices_iterator(mgp_graph *graph, memgraph::utils::MemoryResource *memory)
|
||||
: memory(memory), graph(graph), vertices(graph->impl->Vertices(graph->view)), current_it(vertices.begin()) {
|
||||
if (current_it != vertices.end()) {
|
||||
current_v.emplace(*current_it, graph, memory);
|
||||
}
|
||||
}
|
||||
mgp_vertices_iterator(mgp_graph *graph, memgraph::utils::MemoryResource *memory);
|
||||
|
||||
memgraph::utils::MemoryResource *GetMemoryResource() const { return memory; }
|
||||
|
||||
|
@ -40,6 +40,7 @@ add_subdirectory(write_procedures)
|
||||
add_subdirectory(magic_functions)
|
||||
add_subdirectory(module_file_manager)
|
||||
add_subdirectory(monitoring_server)
|
||||
add_subdirectory(lba_procedures)
|
||||
|
||||
copy_e2e_python_files(pytest_runner pytest_runner.sh "")
|
||||
file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/memgraph-selfsigned.crt DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
8
tests/e2e/lba_procedures/CMakeLists.txt
Normal file
8
tests/e2e/lba_procedures/CMakeLists.txt
Normal file
@ -0,0 +1,8 @@
|
||||
function(copy_lba_procedures_e2e_python_files FILE_NAME)
|
||||
copy_e2e_python_files(lba_procedures ${FILE_NAME})
|
||||
endfunction()
|
||||
|
||||
copy_lba_procedures_e2e_python_files(common.py)
|
||||
copy_lba_procedures_e2e_python_files(lba_procedures.py)
|
||||
|
||||
add_subdirectory(procedures)
|
24
tests/e2e/lba_procedures/common.py
Normal file
24
tests/e2e/lba_procedures/common.py
Normal file
@ -0,0 +1,24 @@
|
||||
# Copyright 2021 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.
|
||||
|
||||
import mgclient
|
||||
import typing
|
||||
|
||||
|
||||
def execute_and_fetch_all(cursor: mgclient.Cursor, query: str, params: dict = {}) -> typing.List[tuple]:
|
||||
cursor.execute(query, params)
|
||||
return cursor.fetchall()
|
||||
|
||||
|
||||
def connect(**kwargs) -> mgclient.Connection:
|
||||
connection = mgclient.connect(host="localhost", port=7687, **kwargs)
|
||||
connection.autocommit = True
|
||||
return connection
|
30
tests/e2e/lba_procedures/lba_procedures.py
Normal file
30
tests/e2e/lba_procedures/lba_procedures.py
Normal file
@ -0,0 +1,30 @@
|
||||
# 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.
|
||||
|
||||
import sys
|
||||
import pytest
|
||||
from common import connect, execute_and_fetch_all
|
||||
|
||||
|
||||
def test_lba_procedures_vertices_iterator_count_only_permitted_vertices():
|
||||
cursor = connect(username="Josip", password="").cursor()
|
||||
result = execute_and_fetch_all(cursor, "CALL read.number_of_visible_nodes() YIELD nr_of_nodes RETURN nr_of_nodes ;")
|
||||
|
||||
assert result[0][0] == 10
|
||||
|
||||
cursor = connect(username="Boris", password="").cursor()
|
||||
result = execute_and_fetch_all(cursor, "CALL read.number_of_visible_nodes() YIELD nr_of_nodes RETURN nr_of_nodes ;")
|
||||
|
||||
assert result[0][0] == 6
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(pytest.main([__file__, "-rA"]))
|
1
tests/e2e/lba_procedures/procedures/CMakeLists.txt
Normal file
1
tests/e2e/lba_procedures/procedures/CMakeLists.txt
Normal file
@ -0,0 +1 @@
|
||||
copy_lba_procedures_e2e_python_files(read.py)
|
17
tests/e2e/lba_procedures/procedures/read.py
Normal file
17
tests/e2e/lba_procedures/procedures/read.py
Normal file
@ -0,0 +1,17 @@
|
||||
# Copyright 2021 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.
|
||||
|
||||
import mgp
|
||||
|
||||
|
||||
@mgp.read_proc
|
||||
def number_of_visible_nodes(ctx: mgp.ProcCtx) -> mgp.Record(nr_of_nodes=int):
|
||||
return mgp.Record(nr_of_nodes=len(mgp.Vertices(ctx.graph._graph)))
|
28
tests/e2e/lba_procedures/workloads.yaml
Normal file
28
tests/e2e/lba_procedures/workloads.yaml
Normal file
@ -0,0 +1,28 @@
|
||||
template_cluster: &template_cluster
|
||||
cluster:
|
||||
main:
|
||||
args: ["--bolt-port", "7687", "--log-level=TRACE"]
|
||||
log_file: "lba-e2e.log"
|
||||
setup_queries: [
|
||||
"Create (:Label1 {id: 1}) ;",
|
||||
"Create (:Label1 {id: 2}) ;",
|
||||
"Create (:Label1 {id: 3}) ;",
|
||||
"Create (:Label1 {id: 4}) ;",
|
||||
"Create (:Label1 {id: 5}) ;",
|
||||
"Create (:Label1 {id: 6}) ;",
|
||||
"Create (:Label2 {id: 1}) ;",
|
||||
"Create (:Label2 {id: 2}) ;",
|
||||
"Create (:Label2 {id: 3}) ;",
|
||||
"Create (:Label2 {id: 4}) ;",
|
||||
"Create User Josip ;",
|
||||
"Create User Boris ;",
|
||||
"Grant Labels :Label1 to Boris;",
|
||||
]
|
||||
validation_queries: []
|
||||
|
||||
workloads:
|
||||
- name: "Label-based auth"
|
||||
binary: "tests/e2e/pytest_runner.sh"
|
||||
proc: "tests/e2e/lba_procedures/procedures/"
|
||||
args: ["lba_procedures/lba_procedures.py"]
|
||||
<<: *template_cluster
|
Loading…
Reference in New Issue
Block a user