Better auth user/role handling (#1699)
* Stop auth module from creating users * Explicit about auth policy (check if no users defined OR auth module used) * Role supports database access definition * Authenticate() returns user or role * AuthChecker generates QueryUserOrRole (can be empty) * QueryUserOrRole actually authorizes * Add auth cache invalidation * Better database access queries (GRANT, DENY, REVOKE DATABASE)
This commit is contained in:
@@ -27,6 +27,7 @@ std::filesystem::path data_directory{std::filesystem::temp_directory_path() / "e
|
||||
class ExpansionBenchFixture : public benchmark::Fixture {
|
||||
protected:
|
||||
std::optional<memgraph::system::System> system;
|
||||
std::optional<memgraph::query::AllowEverythingAuthChecker> auth_checker;
|
||||
std::optional<memgraph::query::InterpreterContext> interpreter_context;
|
||||
std::optional<memgraph::query::Interpreter> interpreter;
|
||||
std::optional<memgraph::utils::Gatekeeper<memgraph::dbms::Database>> db_gk;
|
||||
@@ -43,6 +44,7 @@ class ExpansionBenchFixture : public benchmark::Fixture {
|
||||
auto &db_acc = *db_acc_opt;
|
||||
|
||||
system.emplace();
|
||||
auth_checker.emplace();
|
||||
interpreter_context.emplace(memgraph::query::InterpreterConfig{}, nullptr, &repl_state.value(), *system
|
||||
#ifdef MG_ENTERPRISE
|
||||
,
|
||||
@@ -73,13 +75,15 @@ class ExpansionBenchFixture : public benchmark::Fixture {
|
||||
}
|
||||
|
||||
interpreter.emplace(&*interpreter_context, std::move(db_acc));
|
||||
interpreter->SetUser(auth_checker->GenQueryUser(std::nullopt, std::nullopt));
|
||||
}
|
||||
|
||||
void TearDown(const benchmark::State &) override {
|
||||
interpreter = std::nullopt;
|
||||
interpreter_context = std::nullopt;
|
||||
system.reset();
|
||||
db_gk.reset();
|
||||
auth_checker.reset();
|
||||
system.reset();
|
||||
std::filesystem::remove_all(data_directory);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -14,14 +14,7 @@
|
||||
# If you wish to modify these, update the startup_config_dict and workloads.yaml !
|
||||
|
||||
startup_config_dict = {
|
||||
"auth_module_create_missing_role": ("true", "true", "Set to false to disable creation of missing roles."),
|
||||
"auth_module_create_missing_user": ("true", "true", "Set to false to disable creation of missing users."),
|
||||
"auth_module_executable": ("", "", "Absolute path to the auth module executable that should be used."),
|
||||
"auth_module_manage_roles": (
|
||||
"true",
|
||||
"true",
|
||||
"Set to false to disable management of roles through the auth module.",
|
||||
),
|
||||
"auth_module_timeout_ms": (
|
||||
"10000",
|
||||
"10000",
|
||||
|
||||
@@ -19,10 +19,10 @@ from mgclient import DatabaseError
|
||||
@pytest.mark.parametrize("switch", [False, True])
|
||||
def test_create_node_all_labels_granted(switch):
|
||||
admin_connection = common.connect(username="admin", password="test")
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
common.reset_and_prepare(admin_connection.cursor())
|
||||
common.create_multi_db(admin_connection.cursor(), switch)
|
||||
common.execute_and_fetch_all(admin_connection.cursor(), "GRANT CREATE_DELETE ON LABELS * TO user;")
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
if switch:
|
||||
common.switch_db(user_connection.cursor())
|
||||
results = common.execute_and_fetch_all(user_connection.cursor(), "CREATE (n:label1) RETURN n;")
|
||||
@@ -33,10 +33,10 @@ def test_create_node_all_labels_granted(switch):
|
||||
@pytest.mark.parametrize("switch", [False, True])
|
||||
def test_create_node_all_labels_denied(switch):
|
||||
admin_connection = common.connect(username="admin", password="test")
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
common.reset_and_prepare(admin_connection.cursor())
|
||||
common.create_multi_db(admin_connection.cursor(), switch)
|
||||
common.execute_and_fetch_all(admin_connection.cursor(), "GRANT UPDATE ON LABELS * TO user;")
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
|
||||
if switch:
|
||||
common.switch_db(user_connection.cursor())
|
||||
@@ -47,10 +47,10 @@ def test_create_node_all_labels_denied(switch):
|
||||
@pytest.mark.parametrize("switch", [False, True])
|
||||
def test_create_node_specific_label_granted(switch):
|
||||
admin_connection = common.connect(username="admin", password="test")
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
common.reset_and_prepare(admin_connection.cursor())
|
||||
common.create_multi_db(admin_connection.cursor(), switch)
|
||||
common.execute_and_fetch_all(admin_connection.cursor(), "GRANT CREATE_DELETE ON LABELS :label1 TO user;")
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
if switch:
|
||||
common.switch_db(user_connection.cursor())
|
||||
results = common.execute_and_fetch_all(user_connection.cursor(), "CREATE (n:label1) RETURN n;")
|
||||
@@ -61,10 +61,10 @@ def test_create_node_specific_label_granted(switch):
|
||||
@pytest.mark.parametrize("switch", [False, True])
|
||||
def test_create_node_specific_label_denied(switch):
|
||||
admin_connection = common.connect(username="admin", password="test")
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
common.reset_and_prepare(admin_connection.cursor())
|
||||
common.create_multi_db(admin_connection.cursor(), switch)
|
||||
common.execute_and_fetch_all(admin_connection.cursor(), "GRANT UPDATE ON LABELS :label1 TO user;")
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
|
||||
if switch:
|
||||
common.switch_db(user_connection.cursor())
|
||||
@@ -75,10 +75,10 @@ def test_create_node_specific_label_denied(switch):
|
||||
@pytest.mark.parametrize("switch", [False, True])
|
||||
def test_delete_node_all_labels_granted(switch):
|
||||
admin_connection = common.connect(username="admin", password="test")
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
common.reset_and_prepare(admin_connection.cursor())
|
||||
common.create_multi_db(admin_connection.cursor(), switch)
|
||||
common.execute_and_fetch_all(admin_connection.cursor(), "GRANT CREATE_DELETE ON LABELS * TO user;")
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
if switch:
|
||||
common.switch_db(user_connection.cursor())
|
||||
common.execute_and_fetch_all(user_connection.cursor(), "MATCH (n:test_delete) DELETE n;")
|
||||
@@ -91,10 +91,10 @@ def test_delete_node_all_labels_granted(switch):
|
||||
@pytest.mark.parametrize("switch", [False, True])
|
||||
def test_delete_node_all_labels_denied(switch):
|
||||
admin_connection = common.connect(username="admin", password="test")
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
common.reset_and_prepare(admin_connection.cursor())
|
||||
common.create_multi_db(admin_connection.cursor(), switch)
|
||||
common.execute_and_fetch_all(admin_connection.cursor(), "GRANT UPDATE ON LABELS * TO user;")
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
|
||||
if switch:
|
||||
common.switch_db(user_connection.cursor())
|
||||
@@ -105,10 +105,10 @@ def test_delete_node_all_labels_denied(switch):
|
||||
@pytest.mark.parametrize("switch", [False, True])
|
||||
def test_delete_node_specific_label_granted(switch):
|
||||
admin_connection = common.connect(username="admin", password="test")
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
common.reset_and_prepare(admin_connection.cursor())
|
||||
common.create_multi_db(admin_connection.cursor(), switch)
|
||||
common.execute_and_fetch_all(admin_connection.cursor(), "GRANT CREATE_DELETE ON LABELS :test_delete TO user;")
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
if switch:
|
||||
common.switch_db(user_connection.cursor())
|
||||
results = common.execute_and_fetch_all(user_connection.cursor(), "MATCH (n:test_delete) DELETE n;")
|
||||
@@ -123,10 +123,10 @@ def test_delete_node_specific_label_granted(switch):
|
||||
@pytest.mark.parametrize("switch", [False, True])
|
||||
def test_delete_node_specific_label_denied(switch):
|
||||
admin_connection = common.connect(username="admin", password="test")
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
common.reset_and_prepare(admin_connection.cursor())
|
||||
common.create_multi_db(admin_connection.cursor(), switch)
|
||||
common.execute_and_fetch_all(admin_connection.cursor(), "GRANT UPDATE ON LABELS :test_delete TO user;")
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
|
||||
if switch:
|
||||
common.switch_db(user_connection.cursor())
|
||||
@@ -137,11 +137,11 @@ def test_delete_node_specific_label_denied(switch):
|
||||
@pytest.mark.parametrize("switch", [False, True])
|
||||
def test_create_edge_all_labels_all_edge_types_granted(switch):
|
||||
admin_connection = common.connect(username="admin", password="test")
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
common.reset_and_prepare(admin_connection.cursor())
|
||||
common.create_multi_db(admin_connection.cursor(), switch)
|
||||
common.execute_and_fetch_all(admin_connection.cursor(), "GRANT CREATE_DELETE ON LABELS * TO user;")
|
||||
common.execute_and_fetch_all(admin_connection.cursor(), "GRANT CREATE_DELETE ON EDGE_TYPES * TO user;")
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
|
||||
if switch:
|
||||
common.switch_db(user_connection.cursor())
|
||||
@@ -156,11 +156,11 @@ def test_create_edge_all_labels_all_edge_types_granted(switch):
|
||||
@pytest.mark.parametrize("switch", [False, True])
|
||||
def test_create_edge_all_labels_all_edge_types_denied(switch):
|
||||
admin_connection = common.connect(username="admin", password="test")
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
common.reset_and_prepare(admin_connection.cursor())
|
||||
common.create_multi_db(admin_connection.cursor(), switch)
|
||||
common.execute_and_fetch_all(admin_connection.cursor(), "GRANT UPDATE ON LABELS * TO user;")
|
||||
common.execute_and_fetch_all(admin_connection.cursor(), "GRANT UPDATE ON EDGE_TYPES * TO user;")
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
|
||||
if switch:
|
||||
common.switch_db(user_connection.cursor())
|
||||
@@ -174,11 +174,11 @@ def test_create_edge_all_labels_all_edge_types_denied(switch):
|
||||
@pytest.mark.parametrize("switch", [False, True])
|
||||
def test_create_edge_all_labels_denied_all_edge_types_granted(switch):
|
||||
admin_connection = common.connect(username="admin", password="test")
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
common.reset_and_prepare(admin_connection.cursor())
|
||||
common.create_multi_db(admin_connection.cursor(), switch)
|
||||
common.execute_and_fetch_all(admin_connection.cursor(), "GRANT UPDATE ON LABELS * TO user;")
|
||||
common.execute_and_fetch_all(admin_connection.cursor(), "GRANT UPDATE ON EDGE_TYPES * TO user;")
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
|
||||
if switch:
|
||||
common.switch_db(user_connection.cursor())
|
||||
@@ -192,11 +192,11 @@ def test_create_edge_all_labels_denied_all_edge_types_granted(switch):
|
||||
@pytest.mark.parametrize("switch", [False, True])
|
||||
def test_create_edge_all_labels_granted_all_edge_types_denied(switch):
|
||||
admin_connection = common.connect(username="admin", password="test")
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
common.reset_and_prepare(admin_connection.cursor())
|
||||
common.create_multi_db(admin_connection.cursor(), switch)
|
||||
common.execute_and_fetch_all(admin_connection.cursor(), "GRANT CREATE_DELETE ON LABELS * TO user;")
|
||||
common.execute_and_fetch_all(admin_connection.cursor(), "GRANT UPDATE ON EDGE_TYPES * TO user;")
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
|
||||
if switch:
|
||||
common.switch_db(user_connection.cursor())
|
||||
@@ -210,7 +210,6 @@ def test_create_edge_all_labels_granted_all_edge_types_denied(switch):
|
||||
@pytest.mark.parametrize("switch", [False, True])
|
||||
def test_create_edge_all_labels_granted_specific_edge_types_denied(switch):
|
||||
admin_connection = common.connect(username="admin", password="test")
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
common.reset_and_prepare(admin_connection.cursor())
|
||||
common.create_multi_db(admin_connection.cursor(), switch)
|
||||
common.execute_and_fetch_all(admin_connection.cursor(), "GRANT CREATE_DELETE ON LABELS * TO user;")
|
||||
@@ -218,6 +217,7 @@ def test_create_edge_all_labels_granted_specific_edge_types_denied(switch):
|
||||
admin_connection.cursor(),
|
||||
"GRANT UPDATE ON EDGE_TYPES :edge_type TO user;",
|
||||
)
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
|
||||
if switch:
|
||||
common.switch_db(user_connection.cursor())
|
||||
@@ -231,7 +231,6 @@ def test_create_edge_all_labels_granted_specific_edge_types_denied(switch):
|
||||
@pytest.mark.parametrize("switch", [False, True])
|
||||
def test_create_edge_first_node_label_granted(switch):
|
||||
admin_connection = common.connect(username="admin", password="test")
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
common.reset_and_prepare(admin_connection.cursor())
|
||||
common.create_multi_db(admin_connection.cursor(), switch)
|
||||
common.execute_and_fetch_all(admin_connection.cursor(), "GRANT CREATE_DELETE ON LABELS :label1 TO user;")
|
||||
@@ -240,6 +239,7 @@ def test_create_edge_first_node_label_granted(switch):
|
||||
admin_connection.cursor(),
|
||||
"GRANT CREATE_DELETE ON EDGE_TYPES :edge_type TO user;",
|
||||
)
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
|
||||
if switch:
|
||||
common.switch_db(user_connection.cursor())
|
||||
@@ -253,7 +253,6 @@ def test_create_edge_first_node_label_granted(switch):
|
||||
@pytest.mark.parametrize("switch", [False, True])
|
||||
def test_create_edge_second_node_label_granted(switch):
|
||||
admin_connection = common.connect(username="admin", password="test")
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
common.reset_and_prepare(admin_connection.cursor())
|
||||
common.create_multi_db(admin_connection.cursor(), switch)
|
||||
common.execute_and_fetch_all(admin_connection.cursor(), "GRANT CREATE_DELETE ON LABELS :label2 TO user;")
|
||||
@@ -262,6 +261,7 @@ def test_create_edge_second_node_label_granted(switch):
|
||||
admin_connection.cursor(),
|
||||
"GRANT CREATE_DELETE ON EDGE_TYPES :edge_type TO user;",
|
||||
)
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
|
||||
if switch:
|
||||
common.switch_db(user_connection.cursor())
|
||||
@@ -275,11 +275,11 @@ def test_create_edge_second_node_label_granted(switch):
|
||||
@pytest.mark.parametrize("switch", [False, True])
|
||||
def test_delete_edge_all_labels_denied_all_edge_types_granted(switch):
|
||||
admin_connection = common.connect(username="admin", password="test")
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
common.reset_and_prepare(admin_connection.cursor())
|
||||
common.create_multi_db(admin_connection.cursor(), switch)
|
||||
common.execute_and_fetch_all(admin_connection.cursor(), "GRANT READ ON LABELS * TO user;")
|
||||
common.execute_and_fetch_all(admin_connection.cursor(), "GRANT CREATE_DELETE ON EDGE_TYPES * TO user;")
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
|
||||
if switch:
|
||||
common.switch_db(user_connection.cursor())
|
||||
@@ -293,11 +293,11 @@ def test_delete_edge_all_labels_denied_all_edge_types_granted(switch):
|
||||
@pytest.mark.parametrize("switch", [False, True])
|
||||
def test_delete_edge_all_labels_granted_all_edge_types_denied(switch):
|
||||
admin_connection = common.connect(username="admin", password="test")
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
common.reset_and_prepare(admin_connection.cursor())
|
||||
common.create_multi_db(admin_connection.cursor(), switch)
|
||||
common.execute_and_fetch_all(admin_connection.cursor(), "GRANT CREATE_DELETE ON LABELS * TO user;")
|
||||
common.execute_and_fetch_all(admin_connection.cursor(), "GRANT UPDATE ON EDGE_TYPES * TO user;")
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
|
||||
if switch:
|
||||
common.switch_db(user_connection.cursor())
|
||||
@@ -311,7 +311,6 @@ def test_delete_edge_all_labels_granted_all_edge_types_denied(switch):
|
||||
@pytest.mark.parametrize("switch", [False, True])
|
||||
def test_delete_edge_all_labels_granted_specific_edge_types_denied(switch):
|
||||
admin_connection = common.connect(username="admin", password="test")
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
common.reset_and_prepare(admin_connection.cursor())
|
||||
common.create_multi_db(admin_connection.cursor(), switch)
|
||||
common.execute_and_fetch_all(admin_connection.cursor(), "GRANT CREATE_DELETE ON LABELS * TO user;")
|
||||
@@ -319,6 +318,7 @@ def test_delete_edge_all_labels_granted_specific_edge_types_denied(switch):
|
||||
admin_connection.cursor(),
|
||||
"GRANT UPDATE ON EDGE_TYPES :edge_type_delete TO user;",
|
||||
)
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
|
||||
if switch:
|
||||
common.switch_db(user_connection.cursor())
|
||||
@@ -332,7 +332,6 @@ def test_delete_edge_all_labels_granted_specific_edge_types_denied(switch):
|
||||
@pytest.mark.parametrize("switch", [False, True])
|
||||
def test_delete_edge_first_node_label_granted(switch):
|
||||
admin_connection = common.connect(username="admin", password="test")
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
common.reset_and_prepare(admin_connection.cursor())
|
||||
common.create_multi_db(admin_connection.cursor(), switch)
|
||||
common.execute_and_fetch_all(admin_connection.cursor(), "GRANT UPDATE ON LABELS :test_delete_1 TO user;")
|
||||
@@ -341,6 +340,7 @@ def test_delete_edge_first_node_label_granted(switch):
|
||||
admin_connection.cursor(),
|
||||
"GRANT CREATE_DELETE ON EDGE_TYPES :edge_type_delete TO user;",
|
||||
)
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
|
||||
if switch:
|
||||
common.switch_db(user_connection.cursor())
|
||||
@@ -354,7 +354,6 @@ def test_delete_edge_first_node_label_granted(switch):
|
||||
@pytest.mark.parametrize("switch", [False, True])
|
||||
def test_delete_edge_second_node_label_granted(switch):
|
||||
admin_connection = common.connect(username="admin", password="test")
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
common.reset_and_prepare(admin_connection.cursor())
|
||||
common.create_multi_db(admin_connection.cursor(), switch)
|
||||
common.execute_and_fetch_all(admin_connection.cursor(), "GRANT UPDATE ON LABELS :test_delete_2 TO user;")
|
||||
@@ -363,6 +362,7 @@ def test_delete_edge_second_node_label_granted(switch):
|
||||
admin_connection.cursor(),
|
||||
"GRANT CREATE_DELETE ON EDGE_TYPES :edge_type_delete TO user;",
|
||||
)
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
|
||||
if switch:
|
||||
common.switch_db(user_connection.cursor())
|
||||
@@ -376,13 +376,13 @@ def test_delete_edge_second_node_label_granted(switch):
|
||||
@pytest.mark.parametrize("switch", [False, True])
|
||||
def test_delete_node_with_edge_label_denied(switch):
|
||||
admin_connection = common.connect(username="admin", password="test")
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
common.reset_and_prepare(admin_connection.cursor())
|
||||
common.create_multi_db(admin_connection.cursor(), switch)
|
||||
common.execute_and_fetch_all(
|
||||
admin_connection.cursor(),
|
||||
"GRANT UPDATE ON LABELS :test_delete_1 TO user;",
|
||||
)
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
|
||||
if switch:
|
||||
common.switch_db(user_connection.cursor())
|
||||
@@ -393,13 +393,13 @@ def test_delete_node_with_edge_label_denied(switch):
|
||||
@pytest.mark.parametrize("switch", [False, True])
|
||||
def test_delete_node_with_edge_label_granted(switch):
|
||||
admin_connection = common.connect(username="admin", password="test")
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
common.reset_and_prepare(admin_connection.cursor())
|
||||
common.create_multi_db(admin_connection.cursor(), switch)
|
||||
common.execute_and_fetch_all(
|
||||
admin_connection.cursor(),
|
||||
"GRANT CREATE_DELETE ON LABELS :test_delete_1 TO user;",
|
||||
)
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
|
||||
if switch:
|
||||
common.switch_db(user_connection.cursor())
|
||||
@@ -415,10 +415,10 @@ def test_delete_node_with_edge_label_granted(switch):
|
||||
@pytest.mark.parametrize("switch", [False, True])
|
||||
def test_merge_node_all_labels_granted(switch):
|
||||
admin_connection = common.connect(username="admin", password="test")
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
common.reset_and_prepare(admin_connection.cursor())
|
||||
common.create_multi_db(admin_connection.cursor(), switch)
|
||||
common.execute_and_fetch_all(admin_connection.cursor(), "GRANT CREATE_DELETE ON LABELS * TO user;")
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
if switch:
|
||||
common.switch_db(user_connection.cursor())
|
||||
results = common.execute_and_fetch_all(user_connection.cursor(), "MERGE (n:label1) RETURN n;")
|
||||
@@ -429,10 +429,10 @@ def test_merge_node_all_labels_granted(switch):
|
||||
@pytest.mark.parametrize("switch", [False, True])
|
||||
def test_merge_node_all_labels_denied(switch):
|
||||
admin_connection = common.connect(username="admin", password="test")
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
common.reset_and_prepare(admin_connection.cursor())
|
||||
common.create_multi_db(admin_connection.cursor(), switch)
|
||||
common.execute_and_fetch_all(admin_connection.cursor(), "GRANT UPDATE ON LABELS * TO user;")
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
|
||||
if switch:
|
||||
common.switch_db(user_connection.cursor())
|
||||
@@ -443,10 +443,10 @@ def test_merge_node_all_labels_denied(switch):
|
||||
@pytest.mark.parametrize("switch", [False, True])
|
||||
def test_merge_node_specific_label_granted(switch):
|
||||
admin_connection = common.connect(username="admin", password="test")
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
common.reset_and_prepare(admin_connection.cursor())
|
||||
common.create_multi_db(admin_connection.cursor(), switch)
|
||||
common.execute_and_fetch_all(admin_connection.cursor(), "GRANT CREATE_DELETE ON LABELS :label1 TO user;")
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
if switch:
|
||||
common.switch_db(user_connection.cursor())
|
||||
results = common.execute_and_fetch_all(user_connection.cursor(), "MERGE (n:label1) RETURN n;")
|
||||
@@ -457,10 +457,10 @@ def test_merge_node_specific_label_granted(switch):
|
||||
@pytest.mark.parametrize("switch", [False, True])
|
||||
def test_merge_node_specific_label_denied(switch):
|
||||
admin_connection = common.connect(username="admin", password="test")
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
common.reset_and_prepare(admin_connection.cursor())
|
||||
common.create_multi_db(admin_connection.cursor(), switch)
|
||||
common.execute_and_fetch_all(admin_connection.cursor(), "GRANT UPDATE ON LABELS :label1 TO user;")
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
|
||||
if switch:
|
||||
common.switch_db(user_connection.cursor())
|
||||
@@ -471,11 +471,11 @@ def test_merge_node_specific_label_denied(switch):
|
||||
@pytest.mark.parametrize("switch", [False, True])
|
||||
def test_merge_edge_all_labels_all_edge_types_granted(switch):
|
||||
admin_connection = common.connect(username="admin", password="test")
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
common.reset_and_prepare(admin_connection.cursor())
|
||||
common.create_multi_db(admin_connection.cursor(), switch)
|
||||
common.execute_and_fetch_all(admin_connection.cursor(), "GRANT CREATE_DELETE ON LABELS * TO user;")
|
||||
common.execute_and_fetch_all(admin_connection.cursor(), "GRANT CREATE_DELETE ON EDGE_TYPES * TO user;")
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
if switch:
|
||||
common.switch_db(user_connection.cursor())
|
||||
results = common.execute_and_fetch_all(
|
||||
@@ -489,11 +489,11 @@ def test_merge_edge_all_labels_all_edge_types_granted(switch):
|
||||
@pytest.mark.parametrize("switch", [False, True])
|
||||
def test_merge_edge_all_labels_all_edge_types_denied(switch):
|
||||
admin_connection = common.connect(username="admin", password="test")
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
common.reset_and_prepare(admin_connection.cursor())
|
||||
common.create_multi_db(admin_connection.cursor(), switch)
|
||||
common.execute_and_fetch_all(admin_connection.cursor(), "GRANT UPDATE ON LABELS * TO user;")
|
||||
common.execute_and_fetch_all(admin_connection.cursor(), "GRANT UPDATE ON EDGE_TYPES * TO user;")
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
|
||||
if switch:
|
||||
common.switch_db(user_connection.cursor())
|
||||
@@ -507,11 +507,11 @@ def test_merge_edge_all_labels_all_edge_types_denied(switch):
|
||||
@pytest.mark.parametrize("switch", [False, True])
|
||||
def test_merge_edge_all_labels_denied_all_edge_types_granted(switch):
|
||||
admin_connection = common.connect(username="admin", password="test")
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
common.reset_and_prepare(admin_connection.cursor())
|
||||
common.create_multi_db(admin_connection.cursor(), switch)
|
||||
common.execute_and_fetch_all(admin_connection.cursor(), "GRANT UPDATE ON LABELS * TO user;")
|
||||
common.execute_and_fetch_all(admin_connection.cursor(), "GRANT CREATE_DELETE ON EDGE_TYPES * TO user;")
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
|
||||
if switch:
|
||||
common.switch_db(user_connection.cursor())
|
||||
@@ -525,11 +525,11 @@ def test_merge_edge_all_labels_denied_all_edge_types_granted(switch):
|
||||
@pytest.mark.parametrize("switch", [False, True])
|
||||
def test_merge_edge_all_labels_granted_all_edge_types_denied(switch):
|
||||
admin_connection = common.connect(username="admin", password="test")
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
common.reset_and_prepare(admin_connection.cursor())
|
||||
common.create_multi_db(admin_connection.cursor(), switch)
|
||||
common.execute_and_fetch_all(admin_connection.cursor(), "GRANT CREATE_DELETE ON LABELS * TO user;")
|
||||
common.execute_and_fetch_all(admin_connection.cursor(), "GRANT UPDATE ON EDGE_TYPES * TO user;")
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
|
||||
if switch:
|
||||
common.switch_db(user_connection.cursor())
|
||||
@@ -543,7 +543,6 @@ def test_merge_edge_all_labels_granted_all_edge_types_denied(switch):
|
||||
@pytest.mark.parametrize("switch", [False, True])
|
||||
def test_merge_edge_all_labels_granted_specific_edge_types_denied(switch):
|
||||
admin_connection = common.connect(username="admin", password="test")
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
common.reset_and_prepare(admin_connection.cursor())
|
||||
common.create_multi_db(admin_connection.cursor(), switch)
|
||||
common.execute_and_fetch_all(admin_connection.cursor(), "GRANT CREATE_DELETE ON LABELS * TO user;")
|
||||
@@ -551,6 +550,7 @@ def test_merge_edge_all_labels_granted_specific_edge_types_denied(switch):
|
||||
admin_connection.cursor(),
|
||||
"GRANT UPDATE ON EDGE_TYPES :edge_type TO user;",
|
||||
)
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
|
||||
if switch:
|
||||
common.switch_db(user_connection.cursor())
|
||||
@@ -564,7 +564,6 @@ def test_merge_edge_all_labels_granted_specific_edge_types_denied(switch):
|
||||
@pytest.mark.parametrize("switch", [False, True])
|
||||
def test_merge_edge_first_node_label_granted(switch):
|
||||
admin_connection = common.connect(username="admin", password="test")
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
common.reset_and_prepare(admin_connection.cursor())
|
||||
common.create_multi_db(admin_connection.cursor(), switch)
|
||||
common.execute_and_fetch_all(admin_connection.cursor(), "GRANT CREATE_DELETE ON LABELS :label1 TO user;")
|
||||
@@ -573,6 +572,7 @@ def test_merge_edge_first_node_label_granted(switch):
|
||||
admin_connection.cursor(),
|
||||
"GRANT CREATE_DELETE ON EDGE_TYPES :edge_type TO user;",
|
||||
)
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
|
||||
if switch:
|
||||
common.switch_db(user_connection.cursor())
|
||||
@@ -586,7 +586,6 @@ def test_merge_edge_first_node_label_granted(switch):
|
||||
@pytest.mark.parametrize("switch", [False, True])
|
||||
def test_merge_edge_second_node_label_granted(switch):
|
||||
admin_connection = common.connect(username="admin", password="test")
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
common.reset_and_prepare(admin_connection.cursor())
|
||||
common.create_multi_db(admin_connection.cursor(), switch)
|
||||
common.execute_and_fetch_all(admin_connection.cursor(), "GRANT CREATE_DELETE ON LABELS :label2 TO user;")
|
||||
@@ -595,6 +594,7 @@ def test_merge_edge_second_node_label_granted(switch):
|
||||
admin_connection.cursor(),
|
||||
"GRANT CREATE_DELETE ON EDGE_TYPES :edge_type TO user;",
|
||||
)
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
|
||||
if switch:
|
||||
common.switch_db(user_connection.cursor())
|
||||
@@ -608,10 +608,10 @@ def test_merge_edge_second_node_label_granted(switch):
|
||||
@pytest.mark.parametrize("switch", [False, True])
|
||||
def test_set_label_when_label_granted(switch):
|
||||
admin_connection = common.connect(username="admin", password="test")
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
common.reset_and_prepare(admin_connection.cursor())
|
||||
common.create_multi_db(admin_connection.cursor(), switch)
|
||||
common.execute_and_fetch_all(admin_connection.cursor(), "GRANT CREATE_DELETE ON LABELS :update_label_2 TO user;")
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
|
||||
if switch:
|
||||
common.switch_db(user_connection.cursor())
|
||||
@@ -621,12 +621,12 @@ def test_set_label_when_label_granted(switch):
|
||||
@pytest.mark.parametrize("switch", [False, True])
|
||||
def test_set_label_when_label_denied(switch):
|
||||
admin_connection = common.connect(username="admin", password="test")
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
|
||||
common.reset_and_prepare(admin_connection.cursor())
|
||||
common.create_multi_db(admin_connection.cursor(), switch)
|
||||
common.execute_and_fetch_all(admin_connection.cursor(), "GRANT UPDATE ON LABELS :update_label_2 TO user;")
|
||||
common.execute_and_fetch_all(admin_connection.cursor(), "GRANT READ ON LABELS :test_delete TO user;")
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
|
||||
if switch:
|
||||
common.switch_db(user_connection.cursor())
|
||||
@@ -637,11 +637,11 @@ def test_set_label_when_label_denied(switch):
|
||||
@pytest.mark.parametrize("switch", [False, True])
|
||||
def test_remove_label_when_label_granted(switch):
|
||||
admin_connection = common.connect(username="admin", password="test")
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
|
||||
common.reset_and_prepare(admin_connection.cursor())
|
||||
common.create_multi_db(admin_connection.cursor(), switch)
|
||||
common.execute_and_fetch_all(admin_connection.cursor(), "GRANT CREATE_DELETE ON LABELS :test_delete TO user;")
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
|
||||
if switch:
|
||||
common.switch_db(user_connection.cursor())
|
||||
@@ -651,12 +651,12 @@ def test_remove_label_when_label_granted(switch):
|
||||
@pytest.mark.parametrize("switch", [False, True])
|
||||
def test_remove_label_when_label_denied(switch):
|
||||
admin_connection = common.connect(username="admin", password="test")
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
|
||||
common.reset_and_prepare(admin_connection.cursor())
|
||||
common.create_multi_db(admin_connection.cursor(), switch)
|
||||
common.execute_and_fetch_all(admin_connection.cursor(), "GRANT UPDATE ON LABELS :update_label_2 TO user;")
|
||||
common.execute_and_fetch_all(admin_connection.cursor(), "GRANT READ ON LABELS :test_delete TO user;")
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
|
||||
if switch:
|
||||
common.switch_db(user_connection.cursor())
|
||||
@@ -667,12 +667,12 @@ def test_remove_label_when_label_denied(switch):
|
||||
@pytest.mark.parametrize("switch", [False, True])
|
||||
def test_merge_nodes_pass_when_having_create_delete(switch):
|
||||
admin_connection = common.connect(username="admin", password="test")
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
|
||||
common.reset_and_prepare(admin_connection.cursor())
|
||||
common.create_multi_db(admin_connection.cursor(), switch)
|
||||
common.execute_and_fetch_all(admin_connection.cursor(), "GRANT CREATE_DELETE ON LABELS * TO user;")
|
||||
common.execute_and_fetch_all(admin_connection.cursor(), "GRANT CREATE_DELETE ON EDGE_TYPES * TO user;")
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
|
||||
if switch:
|
||||
common.switch_db(user_connection.cursor())
|
||||
|
||||
@@ -7,9 +7,9 @@ import pytest
|
||||
@pytest.mark.parametrize("switch", [False, True])
|
||||
def test_all_edge_types_all_labels_granted(switch):
|
||||
admin_connection = common.connect(username="admin", password="test")
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
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;")
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
|
||||
if switch:
|
||||
common.switch_db(user_connection.cursor())
|
||||
@@ -21,9 +21,9 @@ def test_all_edge_types_all_labels_granted(switch):
|
||||
@pytest.mark.parametrize("switch", [False, True])
|
||||
def test_deny_all_edge_types_and_all_labels(switch):
|
||||
admin_connection = common.connect(username="admin", password="test")
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
common.execute_and_fetch_all(admin_connection.cursor(), "GRANT NOTHING ON LABELS * TO user;")
|
||||
common.execute_and_fetch_all(admin_connection.cursor(), "GRANT NOTHING ON EDGE_TYPES * TO user;")
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
|
||||
if switch:
|
||||
common.switch_db(user_connection.cursor())
|
||||
@@ -35,9 +35,9 @@ def test_deny_all_edge_types_and_all_labels(switch):
|
||||
@pytest.mark.parametrize("switch", [False, True])
|
||||
def test_revoke_all_edge_types_and_all_labels(switch):
|
||||
admin_connection = common.connect(username="admin", password="test")
|
||||
user_connection = 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;")
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
|
||||
if switch:
|
||||
common.switch_db(user_connection.cursor())
|
||||
@@ -49,10 +49,10 @@ def test_revoke_all_edge_types_and_all_labels(switch):
|
||||
@pytest.mark.parametrize("switch", [False, True])
|
||||
def test_deny_edge_type(switch):
|
||||
admin_connection = common.connect(username="admin", password="test")
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
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(), "GRANT NOTHING ON EDGE_TYPES :edgeType1 TO user;")
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
|
||||
if switch:
|
||||
common.switch_db(user_connection.cursor())
|
||||
@@ -64,10 +64,10 @@ def test_deny_edge_type(switch):
|
||||
@pytest.mark.parametrize("switch", [False, True])
|
||||
def test_denied_node_label(switch):
|
||||
admin_connection = common.connect(username="admin", password="test")
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
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(), "GRANT NOTHING ON LABELS :label2 TO user;")
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
|
||||
if switch:
|
||||
common.switch_db(user_connection.cursor())
|
||||
@@ -79,10 +79,10 @@ def test_denied_node_label(switch):
|
||||
@pytest.mark.parametrize("switch", [False, True])
|
||||
def test_denied_one_of_node_label(switch):
|
||||
admin_connection = common.connect(username="admin", password="test")
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
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(), "GRANT NOTHING ON LABELS :label3 TO user;")
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
|
||||
if switch:
|
||||
common.switch_db(user_connection.cursor())
|
||||
@@ -94,8 +94,8 @@ def test_denied_one_of_node_label(switch):
|
||||
@pytest.mark.parametrize("switch", [False, True])
|
||||
def test_revoke_all_labels(switch):
|
||||
admin_connection = common.connect(username="admin", password="test")
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
common.execute_and_fetch_all(admin_connection.cursor(), "REVOKE LABELS * FROM user;")
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
if switch:
|
||||
common.switch_db(user_connection.cursor())
|
||||
results = common.execute_and_fetch_all(user_connection.cursor(), "MATCH (n)-[r]->(m) RETURN n,r,m;")
|
||||
@@ -106,8 +106,8 @@ def test_revoke_all_labels(switch):
|
||||
@pytest.mark.parametrize("switch", [False, True])
|
||||
def test_revoke_all_edge_types(switch):
|
||||
admin_connection = common.connect(username="admin", password="test")
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
common.execute_and_fetch_all(admin_connection.cursor(), "REVOKE EDGE_TYPES * FROM user;")
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
if switch:
|
||||
common.switch_db(user_connection.cursor())
|
||||
results = common.execute_and_fetch_all(user_connection.cursor(), "MATCH (n)-[r]->(m) RETURN n,r,m;")
|
||||
|
||||
@@ -7,11 +7,11 @@ import pytest
|
||||
@pytest.mark.parametrize("switch", [False, True])
|
||||
def test_weighted_shortest_path_all_edge_types_all_labels_granted(switch):
|
||||
admin_connection = common.connect(username="admin", password="test")
|
||||
user_connection = 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;")
|
||||
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;")
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
|
||||
if switch:
|
||||
common.switch_db(user_connection.cursor())
|
||||
@@ -54,11 +54,11 @@ def test_weighted_shortest_path_all_edge_types_all_labels_granted(switch):
|
||||
@pytest.mark.parametrize("switch", [False, True])
|
||||
def test_weighted_shortest_path_all_edge_types_all_labels_denied(switch):
|
||||
admin_connection = common.connect(username="admin", password="test")
|
||||
user_connection = 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;")
|
||||
common.execute_and_fetch_all(admin_connection.cursor(), "GRANT NOTHING ON LABELS * TO user;")
|
||||
common.execute_and_fetch_all(admin_connection.cursor(), "GRANT NOTHING ON EDGE_TYPES * TO user;")
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
|
||||
if switch:
|
||||
common.switch_db(user_connection.cursor())
|
||||
@@ -72,7 +72,6 @@ def test_weighted_shortest_path_all_edge_types_all_labels_denied(switch):
|
||||
@pytest.mark.parametrize("switch", [False, True])
|
||||
def test_weighted_shortest_path_denied_start(switch):
|
||||
admin_connection = common.connect(username="admin", password="test")
|
||||
user_connection = 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;")
|
||||
common.execute_and_fetch_all(
|
||||
@@ -80,6 +79,7 @@ def test_weighted_shortest_path_denied_start(switch):
|
||||
)
|
||||
common.execute_and_fetch_all(admin_connection.cursor(), "GRANT READ ON EDGE_TYPES * TO user;")
|
||||
common.execute_and_fetch_all(admin_connection.cursor(), "GRANT NOTHING ON LABELS :label0 TO user;")
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
|
||||
if switch:
|
||||
common.switch_db(user_connection.cursor())
|
||||
@@ -94,7 +94,6 @@ def test_weighted_shortest_path_denied_start(switch):
|
||||
@pytest.mark.parametrize("switch", [False, True])
|
||||
def test_weighted_shortest_path_denied_destination(switch):
|
||||
admin_connection = common.connect(username="admin", password="test")
|
||||
user_connection = 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;")
|
||||
common.execute_and_fetch_all(
|
||||
@@ -102,6 +101,7 @@ def test_weighted_shortest_path_denied_destination(switch):
|
||||
)
|
||||
common.execute_and_fetch_all(admin_connection.cursor(), "GRANT READ ON EDGE_TYPES * TO user;")
|
||||
common.execute_and_fetch_all(admin_connection.cursor(), "GRANT NOTHING ON LABELS :label4 TO user;")
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
|
||||
if switch:
|
||||
common.switch_db(user_connection.cursor())
|
||||
@@ -116,7 +116,6 @@ def test_weighted_shortest_path_denied_destination(switch):
|
||||
@pytest.mark.parametrize("switch", [False, True])
|
||||
def test_weighted_shortest_path_denied_label_1(switch):
|
||||
admin_connection = common.connect(username="admin", password="test")
|
||||
user_connection = 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;")
|
||||
common.execute_and_fetch_all(
|
||||
@@ -124,6 +123,7 @@ def test_weighted_shortest_path_denied_label_1(switch):
|
||||
)
|
||||
common.execute_and_fetch_all(admin_connection.cursor(), "GRANT NOTHING ON LABELS :label1 TO user;")
|
||||
common.execute_and_fetch_all(admin_connection.cursor(), "GRANT READ ON EDGE_TYPES * TO user;")
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
|
||||
if switch:
|
||||
common.switch_db(user_connection.cursor())
|
||||
@@ -162,7 +162,6 @@ def test_weighted_shortest_path_denied_label_1(switch):
|
||||
@pytest.mark.parametrize("switch", [False, True])
|
||||
def test_weighted_shortest_path_denied_edge_type_3(switch):
|
||||
admin_connection = common.connect(username="admin", password="test")
|
||||
user_connection = 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;")
|
||||
common.execute_and_fetch_all(admin_connection.cursor(), "GRANT READ ON LABELS * TO user;")
|
||||
@@ -170,6 +169,7 @@ def test_weighted_shortest_path_denied_edge_type_3(switch):
|
||||
admin_connection.cursor(), "GRANT READ ON EDGE_TYPES :edge_type_1, :edge_type_2, :edge_type_4 TO user;"
|
||||
)
|
||||
common.execute_and_fetch_all(admin_connection.cursor(), "GRANT NOTHING ON EDGE_TYPES :edge_type_3 TO user;")
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
|
||||
if switch:
|
||||
common.switch_db(user_connection.cursor())
|
||||
@@ -213,11 +213,11 @@ def test_weighted_shortest_path_denied_edge_type_3(switch):
|
||||
@pytest.mark.parametrize("switch", [False, True])
|
||||
def test_dfs_all_edge_types_all_labels_granted(switch):
|
||||
admin_connection = common.connect(username="admin", password="test")
|
||||
user_connection = 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;")
|
||||
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;")
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
|
||||
if switch:
|
||||
common.switch_db(user_connection.cursor())
|
||||
@@ -235,11 +235,11 @@ def test_dfs_all_edge_types_all_labels_granted(switch):
|
||||
@pytest.mark.parametrize("switch", [False, True])
|
||||
def test_dfs_all_edge_types_all_labels_denied(switch):
|
||||
admin_connection = common.connect(username="admin", password="test")
|
||||
user_connection = 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;")
|
||||
common.execute_and_fetch_all(admin_connection.cursor(), "GRANT NOTHING ON LABELS * TO user;")
|
||||
common.execute_and_fetch_all(admin_connection.cursor(), "GRANT NOTHING ON EDGE_TYPES * TO user;")
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
|
||||
if switch:
|
||||
common.switch_db(user_connection.cursor())
|
||||
@@ -251,7 +251,6 @@ def test_dfs_all_edge_types_all_labels_denied(switch):
|
||||
@pytest.mark.parametrize("switch", [False, True])
|
||||
def test_dfs_denied_start(switch):
|
||||
admin_connection = common.connect(username="admin", password="test")
|
||||
user_connection = 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;")
|
||||
common.execute_and_fetch_all(
|
||||
@@ -259,6 +258,7 @@ def test_dfs_denied_start(switch):
|
||||
)
|
||||
common.execute_and_fetch_all(admin_connection.cursor(), "GRANT READ ON EDGE_TYPES * TO user;")
|
||||
common.execute_and_fetch_all(admin_connection.cursor(), "GRANT NOTHING ON LABELS :label0 TO user;")
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
|
||||
if switch:
|
||||
common.switch_db(user_connection.cursor())
|
||||
@@ -272,7 +272,6 @@ def test_dfs_denied_start(switch):
|
||||
@pytest.mark.parametrize("switch", [False, True])
|
||||
def test_dfs_denied_destination(switch):
|
||||
admin_connection = common.connect(username="admin", password="test")
|
||||
user_connection = 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;")
|
||||
common.execute_and_fetch_all(
|
||||
@@ -280,6 +279,7 @@ def test_dfs_denied_destination(switch):
|
||||
)
|
||||
common.execute_and_fetch_all(admin_connection.cursor(), "GRANT READ ON EDGE_TYPES * TO user;")
|
||||
common.execute_and_fetch_all(admin_connection.cursor(), "GRANT NOTHING ON LABELS :label4 TO user;")
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
|
||||
if switch:
|
||||
common.switch_db(user_connection.cursor())
|
||||
@@ -293,7 +293,6 @@ def test_dfs_denied_destination(switch):
|
||||
@pytest.mark.parametrize("switch", [False, True])
|
||||
def test_dfs_denied_label_1(switch):
|
||||
admin_connection = common.connect(username="admin", password="test")
|
||||
user_connection = 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;")
|
||||
common.execute_and_fetch_all(
|
||||
@@ -301,6 +300,7 @@ def test_dfs_denied_label_1(switch):
|
||||
)
|
||||
common.execute_and_fetch_all(admin_connection.cursor(), "GRANT NOTHING ON LABELS :label1 TO user;")
|
||||
common.execute_and_fetch_all(admin_connection.cursor(), "GRANT READ ON EDGE_TYPES * TO user;")
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
|
||||
if switch:
|
||||
common.switch_db(user_connection.cursor())
|
||||
@@ -318,7 +318,6 @@ def test_dfs_denied_label_1(switch):
|
||||
@pytest.mark.parametrize("switch", [False, True])
|
||||
def test_dfs_denied_edge_type_3(switch):
|
||||
admin_connection = common.connect(username="admin", password="test")
|
||||
user_connection = 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;")
|
||||
|
||||
@@ -327,6 +326,7 @@ def test_dfs_denied_edge_type_3(switch):
|
||||
admin_connection.cursor(), "GRANT READ ON EDGE_TYPES :edge_type_1, :edge_type_2, :edge_type_4 TO user;"
|
||||
)
|
||||
common.execute_and_fetch_all(admin_connection.cursor(), "GRANT NOTHING ON EDGE_TYPES :edge_type_3 TO user;")
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
|
||||
if switch:
|
||||
common.switch_db(user_connection.cursor())
|
||||
@@ -344,11 +344,11 @@ def test_dfs_denied_edge_type_3(switch):
|
||||
@pytest.mark.parametrize("switch", [False, True])
|
||||
def test_bfs_sts_all_edge_types_all_labels_granted(switch):
|
||||
admin_connection = common.connect(username="admin", password="test")
|
||||
user_connection = 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;")
|
||||
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;")
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
|
||||
if switch:
|
||||
common.switch_db(user_connection.cursor())
|
||||
@@ -366,11 +366,11 @@ def test_bfs_sts_all_edge_types_all_labels_granted(switch):
|
||||
@pytest.mark.parametrize("switch", [False, True])
|
||||
def test_bfs_sts_all_edge_types_all_labels_denied(switch):
|
||||
admin_connection = common.connect(username="admin", password="test")
|
||||
user_connection = 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;")
|
||||
common.execute_and_fetch_all(admin_connection.cursor(), "GRANT NOTHING ON LABELS * TO user;")
|
||||
common.execute_and_fetch_all(admin_connection.cursor(), "GRANT NOTHING ON EDGE_TYPES * TO user;")
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
|
||||
if switch:
|
||||
common.switch_db(user_connection.cursor())
|
||||
@@ -384,7 +384,6 @@ def test_bfs_sts_all_edge_types_all_labels_denied(switch):
|
||||
@pytest.mark.parametrize("switch", [False, True])
|
||||
def test_bfs_sts_denied_start(switch):
|
||||
admin_connection = common.connect(username="admin", password="test")
|
||||
user_connection = 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;")
|
||||
common.execute_and_fetch_all(
|
||||
@@ -392,6 +391,7 @@ def test_bfs_sts_denied_start(switch):
|
||||
)
|
||||
common.execute_and_fetch_all(admin_connection.cursor(), "GRANT READ ON EDGE_TYPES * TO user;")
|
||||
common.execute_and_fetch_all(admin_connection.cursor(), "GRANT NOTHING ON LABELS :label0 TO user;")
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
|
||||
if switch:
|
||||
common.switch_db(user_connection.cursor())
|
||||
@@ -405,7 +405,6 @@ def test_bfs_sts_denied_start(switch):
|
||||
@pytest.mark.parametrize("switch", [False, True])
|
||||
def test_bfs_sts_denied_destination(switch):
|
||||
admin_connection = common.connect(username="admin", password="test")
|
||||
user_connection = 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;")
|
||||
common.execute_and_fetch_all(
|
||||
@@ -413,6 +412,7 @@ def test_bfs_sts_denied_destination(switch):
|
||||
)
|
||||
common.execute_and_fetch_all(admin_connection.cursor(), "GRANT READ ON EDGE_TYPES * TO user;")
|
||||
common.execute_and_fetch_all(admin_connection.cursor(), "GRANT NOTHING ON LABELS :label4 TO user;")
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
|
||||
if switch:
|
||||
common.switch_db(user_connection.cursor())
|
||||
@@ -426,7 +426,6 @@ def test_bfs_sts_denied_destination(switch):
|
||||
@pytest.mark.parametrize("switch", [False, True])
|
||||
def test_bfs_sts_denied_label_1(switch):
|
||||
admin_connection = common.connect(username="admin", password="test")
|
||||
user_connection = 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;")
|
||||
common.execute_and_fetch_all(
|
||||
@@ -434,6 +433,7 @@ def test_bfs_sts_denied_label_1(switch):
|
||||
)
|
||||
common.execute_and_fetch_all(admin_connection.cursor(), "GRANT NOTHING ON LABELS :label1 TO user;")
|
||||
common.execute_and_fetch_all(admin_connection.cursor(), "GRANT READ ON EDGE_TYPES * TO user;")
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
|
||||
if switch:
|
||||
common.switch_db(user_connection.cursor())
|
||||
@@ -450,7 +450,6 @@ def test_bfs_sts_denied_label_1(switch):
|
||||
@pytest.mark.parametrize("switch", [False, True])
|
||||
def test_bfs_sts_denied_edge_type_3(switch):
|
||||
admin_connection = common.connect(username="admin", password="test")
|
||||
user_connection = 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;")
|
||||
common.execute_and_fetch_all(admin_connection.cursor(), "GRANT READ ON LABELS * TO user;")
|
||||
@@ -458,6 +457,7 @@ def test_bfs_sts_denied_edge_type_3(switch):
|
||||
admin_connection.cursor(), "GRANT READ ON EDGE_TYPES :edge_type_1, :edge_type_2, :edge_type_4 TO user;"
|
||||
)
|
||||
common.execute_and_fetch_all(admin_connection.cursor(), "GRANT NOTHING ON EDGE_TYPES :edge_type_3 TO user;")
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
|
||||
if switch:
|
||||
common.switch_db(user_connection.cursor())
|
||||
@@ -474,11 +474,11 @@ def test_bfs_sts_denied_edge_type_3(switch):
|
||||
@pytest.mark.parametrize("switch", [False, True])
|
||||
def test_bfs_single_source_all_edge_types_all_labels_granted(switch):
|
||||
admin_connection = common.connect(username="admin", password="test")
|
||||
user_connection = 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;")
|
||||
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;")
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
|
||||
if switch:
|
||||
common.switch_db(user_connection.cursor())
|
||||
@@ -496,11 +496,11 @@ def test_bfs_single_source_all_edge_types_all_labels_granted(switch):
|
||||
@pytest.mark.parametrize("switch", [False, True])
|
||||
def test_bfs_single_source_all_edge_types_all_labels_denied(switch):
|
||||
admin_connection = common.connect(username="admin", password="test")
|
||||
user_connection = 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;")
|
||||
common.execute_and_fetch_all(admin_connection.cursor(), "GRANT NOTHING ON LABELS * TO user;")
|
||||
common.execute_and_fetch_all(admin_connection.cursor(), "GRANT NOTHING ON EDGE_TYPES * TO user;")
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
|
||||
if switch:
|
||||
common.switch_db(user_connection.cursor())
|
||||
@@ -512,7 +512,6 @@ def test_bfs_single_source_all_edge_types_all_labels_denied(switch):
|
||||
@pytest.mark.parametrize("switch", [False, True])
|
||||
def test_bfs_single_source_denied_start(switch):
|
||||
admin_connection = common.connect(username="admin", password="test")
|
||||
user_connection = 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;")
|
||||
common.execute_and_fetch_all(
|
||||
@@ -520,6 +519,7 @@ def test_bfs_single_source_denied_start(switch):
|
||||
)
|
||||
common.execute_and_fetch_all(admin_connection.cursor(), "GRANT READ ON EDGE_TYPES * TO user;")
|
||||
common.execute_and_fetch_all(admin_connection.cursor(), "GRANT NOTHING ON LABELS :label0 TO user;")
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
|
||||
if switch:
|
||||
common.switch_db(user_connection.cursor())
|
||||
@@ -533,7 +533,6 @@ def test_bfs_single_source_denied_start(switch):
|
||||
@pytest.mark.parametrize("switch", [False, True])
|
||||
def test_bfs_single_source_denied_destination(switch):
|
||||
admin_connection = common.connect(username="admin", password="test")
|
||||
user_connection = 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;")
|
||||
common.execute_and_fetch_all(
|
||||
@@ -541,6 +540,7 @@ def test_bfs_single_source_denied_destination(switch):
|
||||
)
|
||||
common.execute_and_fetch_all(admin_connection.cursor(), "GRANT READ ON EDGE_TYPES * TO user;")
|
||||
common.execute_and_fetch_all(admin_connection.cursor(), "GRANT NOTHING ON LABELS :label4 TO user;")
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
|
||||
if switch:
|
||||
common.switch_db(user_connection.cursor())
|
||||
@@ -554,7 +554,6 @@ def test_bfs_single_source_denied_destination(switch):
|
||||
@pytest.mark.parametrize("switch", [False, True])
|
||||
def test_bfs_single_source_denied_label_1(switch):
|
||||
admin_connection = common.connect(username="admin", password="test")
|
||||
user_connection = 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;")
|
||||
common.execute_and_fetch_all(
|
||||
@@ -562,6 +561,7 @@ def test_bfs_single_source_denied_label_1(switch):
|
||||
)
|
||||
common.execute_and_fetch_all(admin_connection.cursor(), "GRANT NOTHING ON LABELS :label1 TO user;")
|
||||
common.execute_and_fetch_all(admin_connection.cursor(), "GRANT READ ON EDGE_TYPES * TO user;")
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
|
||||
if switch:
|
||||
common.switch_db(user_connection.cursor())
|
||||
@@ -579,7 +579,6 @@ def test_bfs_single_source_denied_label_1(switch):
|
||||
@pytest.mark.parametrize("switch", [False, True])
|
||||
def test_bfs_single_source_denied_edge_type_3(switch):
|
||||
admin_connection = common.connect(username="admin", password="test")
|
||||
user_connection = 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;")
|
||||
common.execute_and_fetch_all(admin_connection.cursor(), "GRANT READ ON LABELS * TO user;")
|
||||
@@ -587,6 +586,7 @@ def test_bfs_single_source_denied_edge_type_3(switch):
|
||||
admin_connection.cursor(), "GRANT READ ON EDGE_TYPES :edge_type_1, :edge_type_2, :edge_type_4 TO user;"
|
||||
)
|
||||
common.execute_and_fetch_all(admin_connection.cursor(), "GRANT NOTHING ON EDGE_TYPES :edge_type_3 TO user;")
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
|
||||
if switch:
|
||||
common.switch_db(user_connection.cursor())
|
||||
@@ -604,11 +604,11 @@ def test_bfs_single_source_denied_edge_type_3(switch):
|
||||
@pytest.mark.parametrize("switch", [False, True])
|
||||
def test_all_shortest_paths_when_all_edge_types_all_labels_granted(switch):
|
||||
admin_connection = common.connect(username="admin", password="test")
|
||||
user_connection = 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;")
|
||||
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;")
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
|
||||
if switch:
|
||||
common.switch_db(user_connection.cursor())
|
||||
@@ -651,11 +651,11 @@ def test_all_shortest_paths_when_all_edge_types_all_labels_granted(switch):
|
||||
@pytest.mark.parametrize("switch", [False, True])
|
||||
def test_all_shortest_paths_when_all_edge_types_all_labels_denied(switch):
|
||||
admin_connection = common.connect(username="admin", password="test")
|
||||
user_connection = 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;")
|
||||
common.execute_and_fetch_all(admin_connection.cursor(), "GRANT NOTHING ON LABELS * TO user;")
|
||||
common.execute_and_fetch_all(admin_connection.cursor(), "GRANT NOTHING ON EDGE_TYPES * TO user;")
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
|
||||
if switch:
|
||||
common.switch_db(user_connection.cursor())
|
||||
@@ -669,7 +669,6 @@ def test_all_shortest_paths_when_all_edge_types_all_labels_denied(switch):
|
||||
@pytest.mark.parametrize("switch", [False, True])
|
||||
def test_all_shortest_paths_when_denied_start(switch):
|
||||
admin_connection = common.connect(username="admin", password="test")
|
||||
user_connection = 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;")
|
||||
common.execute_and_fetch_all(
|
||||
@@ -677,6 +676,7 @@ def test_all_shortest_paths_when_denied_start(switch):
|
||||
)
|
||||
common.execute_and_fetch_all(admin_connection.cursor(), "GRANT READ ON EDGE_TYPES * TO user;")
|
||||
common.execute_and_fetch_all(admin_connection.cursor(), "GRANT NOTHING ON LABELS :label0 TO user;")
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
|
||||
if switch:
|
||||
common.switch_db(user_connection.cursor())
|
||||
@@ -691,7 +691,6 @@ def test_all_shortest_paths_when_denied_start(switch):
|
||||
@pytest.mark.parametrize("switch", [False, True])
|
||||
def test_all_shortest_paths_when_denied_destination(switch):
|
||||
admin_connection = common.connect(username="admin", password="test")
|
||||
user_connection = 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;")
|
||||
common.execute_and_fetch_all(
|
||||
@@ -699,6 +698,7 @@ def test_all_shortest_paths_when_denied_destination(switch):
|
||||
)
|
||||
common.execute_and_fetch_all(admin_connection.cursor(), "GRANT READ ON EDGE_TYPES * TO user;")
|
||||
common.execute_and_fetch_all(admin_connection.cursor(), "GRANT NOTHING ON LABELS :label4 TO user;")
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
|
||||
if switch:
|
||||
common.switch_db(user_connection.cursor())
|
||||
@@ -713,7 +713,6 @@ def test_all_shortest_paths_when_denied_destination(switch):
|
||||
@pytest.mark.parametrize("switch", [False, True])
|
||||
def test_all_shortest_paths_when_denied_label_1(switch):
|
||||
admin_connection = common.connect(username="admin", password="test")
|
||||
user_connection = 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;")
|
||||
common.execute_and_fetch_all(
|
||||
@@ -721,6 +720,7 @@ def test_all_shortest_paths_when_denied_label_1(switch):
|
||||
)
|
||||
common.execute_and_fetch_all(admin_connection.cursor(), "GRANT NOTHING ON LABELS :label1 TO user;")
|
||||
common.execute_and_fetch_all(admin_connection.cursor(), "GRANT READ ON EDGE_TYPES * TO user;")
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
|
||||
if switch:
|
||||
common.switch_db(user_connection.cursor())
|
||||
@@ -759,7 +759,6 @@ def test_all_shortest_paths_when_denied_label_1(switch):
|
||||
@pytest.mark.parametrize("switch", [False, True])
|
||||
def test_all_shortest_paths_when_denied_edge_type_3(switch):
|
||||
admin_connection = common.connect(username="admin", password="test")
|
||||
user_connection = 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;")
|
||||
common.execute_and_fetch_all(admin_connection.cursor(), "GRANT READ ON LABELS * TO user;")
|
||||
@@ -767,6 +766,7 @@ def test_all_shortest_paths_when_denied_edge_type_3(switch):
|
||||
admin_connection.cursor(), "GRANT READ ON EDGE_TYPES :edge_type_1, :edge_type_2, :edge_type_4 TO user;"
|
||||
)
|
||||
common.execute_and_fetch_all(admin_connection.cursor(), "GRANT NOTHING ON EDGE_TYPES :edge_type_3 TO user;")
|
||||
user_connection = common.connect(username="user", password="test")
|
||||
|
||||
if switch:
|
||||
common.switch_db(user_connection.cursor())
|
||||
|
||||
@@ -84,11 +84,12 @@ show_databases_w_user_setup_queries: &show_databases_w_user_setup_queries
|
||||
- "GRANT DATABASE db1 TO user;"
|
||||
- "GRANT ALL PRIVILEGES TO user2;"
|
||||
- "GRANT DATABASE db2 TO user2;"
|
||||
- "GRANT DATABASE memgraph TO user2;"
|
||||
- "REVOKE DATABASE memgraph FROM user2;"
|
||||
- "SET MAIN DATABASE db2 FOR user2"
|
||||
- "GRANT ALL PRIVILEGES TO user3;"
|
||||
- "GRANT DATABASE * TO user3;"
|
||||
- "REVOKE DATABASE memgraph FROM user3;"
|
||||
- "DENY DATABASE memgraph FROM user3;"
|
||||
- "SET MAIN DATABASE db1 FOR user3"
|
||||
|
||||
create_delete_filtering_in_memory_cluster: &create_delete_filtering_in_memory_cluster
|
||||
|
||||
@@ -107,18 +107,21 @@ def execute_read_node_assertion(
|
||||
operation_case: List[str], queries: List[str], create_index: bool, expected_size: int, switch: bool
|
||||
) -> None:
|
||||
admin_cursor = get_admin_cursor()
|
||||
user_cursor = get_user_cursor()
|
||||
|
||||
if switch:
|
||||
create_multi_db(admin_cursor)
|
||||
switch_db(admin_cursor)
|
||||
switch_db(user_cursor)
|
||||
|
||||
reset_permissions(admin_cursor, create_index)
|
||||
|
||||
for operation in operation_case:
|
||||
execute_and_fetch_all(admin_cursor, operation)
|
||||
|
||||
# Connect after possible auth changes
|
||||
user_cursor = get_user_cursor()
|
||||
if switch:
|
||||
switch_db(user_cursor)
|
||||
|
||||
for mq in queries:
|
||||
results = execute_and_fetch_all(user_cursor, mq)
|
||||
assert len(results) == expected_size
|
||||
|
||||
@@ -121,6 +121,7 @@ def only_main_queries(cursor):
|
||||
n_exceptions += try_and_count(cursor, f"REVOKE EDGE_TYPES :e FROM user_name")
|
||||
n_exceptions += try_and_count(cursor, f"GRANT DATABASE memgraph TO user_name;")
|
||||
n_exceptions += try_and_count(cursor, f"SET MAIN DATABASE memgraph FOR user_name")
|
||||
n_exceptions += try_and_count(cursor, f"DENY DATABASE memgraph FROM user_name;")
|
||||
n_exceptions += try_and_count(cursor, f"REVOKE DATABASE memgraph FROM user_name;")
|
||||
|
||||
return n_exceptions
|
||||
@@ -198,8 +199,8 @@ def test_auth_queries_on_replica(connection):
|
||||
|
||||
# 1/
|
||||
assert only_main_queries(cursor_main) == 0
|
||||
assert only_main_queries(cursor_replica_1) == 17
|
||||
assert only_main_queries(cursor_replica_2) == 17
|
||||
assert only_main_queries(cursor_replica_1) == 18
|
||||
assert only_main_queries(cursor_replica_2) == 18
|
||||
assert main_and_repl_queries(cursor_main) == 0
|
||||
assert main_and_repl_queries(cursor_replica_1) == 0
|
||||
assert main_and_repl_queries(cursor_replica_2) == 0
|
||||
@@ -383,6 +384,7 @@ def test_manual_roles_recovery(connection):
|
||||
"--log-level=TRACE",
|
||||
"--data_directory",
|
||||
TEMP_DIR + "/replica1",
|
||||
"--also-log-to-stderr",
|
||||
],
|
||||
"log_file": "replica1.log",
|
||||
"setup_queries": [
|
||||
@@ -818,13 +820,15 @@ def test_auth_replication(connection):
|
||||
{("LABEL :l3", "UPDATE", "LABEL PERMISSION GRANTED TO ROLE")},
|
||||
)
|
||||
|
||||
# GRANT/REVOKE DATABASE
|
||||
# GRANT/DENY DATABASE
|
||||
execute_and_fetch_all(cursor_main, "CREATE DATABASE auth_test")
|
||||
execute_and_fetch_all(cursor_main, "CREATE DATABASE auth_test2")
|
||||
execute_and_fetch_all(cursor_main, "GRANT DATABASE auth_test TO user4")
|
||||
check(partial(show_database_privileges_func, user="user4"), [(["auth_test", "memgraph"], [])])
|
||||
execute_and_fetch_all(cursor_main, "REVOKE DATABASE auth_test2 FROM user4")
|
||||
execute_and_fetch_all(cursor_main, "DENY DATABASE auth_test2 FROM user4")
|
||||
check(partial(show_database_privileges_func, user="user4"), [(["auth_test", "memgraph"], ["auth_test2"])])
|
||||
execute_and_fetch_all(cursor_main, "REVOKE DATABASE memgraph FROM user4")
|
||||
check(partial(show_database_privileges_func, user="user4"), [(["auth_test"], ["auth_test2"])])
|
||||
|
||||
# SET MAIN DATABASE
|
||||
execute_and_fetch_all(cursor_main, "GRANT ALL PRIVILEGES TO user4")
|
||||
|
||||
@@ -70,21 +70,26 @@ def test_multitenant_transactions():
|
||||
# TODO Add SHOW TRANSACTIONS ON * that should return all transactions
|
||||
|
||||
|
||||
def test_admin_has_one_transaction():
|
||||
def test_admin_has_one_transaction(request):
|
||||
"""Creates admin and tests that he sees only one transaction."""
|
||||
# a_cursor is used for creating admin user, simulates main thread
|
||||
superadmin_cursor = connect().cursor()
|
||||
execute_and_fetch_all(superadmin_cursor, "CREATE USER admin")
|
||||
execute_and_fetch_all(superadmin_cursor, "GRANT TRANSACTION_MANAGEMENT TO admin")
|
||||
execute_and_fetch_all(superadmin_cursor, "GRANT DATABASE * TO admin")
|
||||
|
||||
def on_exit():
|
||||
execute_and_fetch_all(superadmin_cursor, "DROP USER admin")
|
||||
|
||||
request.addfinalizer(on_exit)
|
||||
|
||||
admin_cursor = connect(username="admin", password="").cursor()
|
||||
process = multiprocessing.Process(target=show_transactions_test, args=(admin_cursor, 1))
|
||||
process.start()
|
||||
process.join()
|
||||
execute_and_fetch_all(superadmin_cursor, "DROP USER admin")
|
||||
|
||||
|
||||
def test_user_can_see_its_transaction():
|
||||
def test_user_can_see_its_transaction(request):
|
||||
"""Tests that user without privileges can see its own transaction"""
|
||||
superadmin_cursor = connect().cursor()
|
||||
execute_and_fetch_all(superadmin_cursor, "CREATE USER admin")
|
||||
@@ -92,20 +97,31 @@ def test_user_can_see_its_transaction():
|
||||
execute_and_fetch_all(superadmin_cursor, "GRANT DATABASE * TO admin")
|
||||
execute_and_fetch_all(superadmin_cursor, "CREATE USER user")
|
||||
execute_and_fetch_all(superadmin_cursor, "REVOKE ALL PRIVILEGES FROM user")
|
||||
|
||||
def on_exit():
|
||||
execute_and_fetch_all(superadmin_cursor, "DROP USER admin")
|
||||
execute_and_fetch_all(superadmin_cursor, "DROP USER user")
|
||||
|
||||
request.addfinalizer(on_exit)
|
||||
|
||||
user_cursor = connect(username="user", password="").cursor()
|
||||
process = multiprocessing.Process(target=show_transactions_test, args=(user_cursor, 1))
|
||||
process.start()
|
||||
process.join()
|
||||
admin_cursor = connect(username="admin", password="").cursor()
|
||||
execute_and_fetch_all(admin_cursor, "DROP USER user")
|
||||
execute_and_fetch_all(admin_cursor, "DROP USER admin")
|
||||
|
||||
|
||||
def test_explicit_transaction_output():
|
||||
def test_explicit_transaction_output(request):
|
||||
superadmin_cursor = connect().cursor()
|
||||
execute_and_fetch_all(superadmin_cursor, "CREATE USER admin")
|
||||
execute_and_fetch_all(superadmin_cursor, "GRANT TRANSACTION_MANAGEMENT TO admin")
|
||||
execute_and_fetch_all(superadmin_cursor, "GRANT DATABASE * TO admin")
|
||||
|
||||
def on_exit():
|
||||
execute_and_fetch_all(superadmin_cursor, "DROP USER admin")
|
||||
|
||||
request.addfinalizer(on_exit)
|
||||
|
||||
admin_connection = connect(username="admin", password="")
|
||||
admin_cursor = admin_connection.cursor()
|
||||
# Admin starts running explicit transaction
|
||||
@@ -123,10 +139,9 @@ def test_explicit_transaction_output():
|
||||
assert show_results[1 - executing_index][2] == ["CREATE (n:Person {id_: 1})", "CREATE (n:Person {id_: 2})"]
|
||||
|
||||
execute_and_fetch_all(superadmin_cursor, "ROLLBACK")
|
||||
execute_and_fetch_all(superadmin_cursor, "DROP USER admin")
|
||||
|
||||
|
||||
def test_superadmin_cannot_see_admin_can_see_admin():
|
||||
def test_superadmin_cannot_see_admin_can_see_admin(request):
|
||||
"""Tests that superadmin cannot see the transaction created by admin but two admins can see and kill each other's transactions."""
|
||||
superadmin_cursor = connect().cursor()
|
||||
execute_and_fetch_all(superadmin_cursor, "CREATE USER admin1")
|
||||
@@ -135,6 +150,13 @@ def test_superadmin_cannot_see_admin_can_see_admin():
|
||||
execute_and_fetch_all(superadmin_cursor, "CREATE USER admin2")
|
||||
execute_and_fetch_all(superadmin_cursor, "GRANT TRANSACTION_MANAGEMENT TO admin2")
|
||||
execute_and_fetch_all(superadmin_cursor, "GRANT DATABASE * TO admin2")
|
||||
|
||||
def on_exit():
|
||||
execute_and_fetch_all(superadmin_cursor, "DROP USER admin1")
|
||||
execute_and_fetch_all(superadmin_cursor, "DROP USER admin2")
|
||||
|
||||
request.addfinalizer(on_exit)
|
||||
|
||||
# Admin starts running infinite query
|
||||
admin_connection_1 = connect(username="admin1", password="")
|
||||
admin_cursor_1 = admin_connection_1.cursor()
|
||||
@@ -160,19 +182,23 @@ def test_superadmin_cannot_see_admin_can_see_admin():
|
||||
# Kill transaction
|
||||
long_transaction_id = show_results[1 - executing_index][1]
|
||||
execute_and_fetch_all(admin_cursor_2, f"TERMINATE TRANSACTIONS '{long_transaction_id}'")
|
||||
execute_and_fetch_all(superadmin_cursor, "DROP USER admin1")
|
||||
execute_and_fetch_all(superadmin_cursor, "DROP USER admin2")
|
||||
admin_connection_1.close()
|
||||
admin_connection_2.close()
|
||||
|
||||
|
||||
def test_admin_sees_superadmin():
|
||||
def test_admin_sees_superadmin(request):
|
||||
"""Tests that admin created by superadmin can see the superadmin's transaction."""
|
||||
superadmin_connection = connect()
|
||||
superadmin_cursor = superadmin_connection.cursor()
|
||||
execute_and_fetch_all(superadmin_cursor, "CREATE USER admin")
|
||||
execute_and_fetch_all(superadmin_cursor, "GRANT TRANSACTION_MANAGEMENT TO admin")
|
||||
execute_and_fetch_all(superadmin_cursor, "GRANT DATABASE * TO admin")
|
||||
|
||||
def on_exit():
|
||||
execute_and_fetch_all(admin_cursor, "DROP USER admin")
|
||||
|
||||
request.addfinalizer(on_exit)
|
||||
|
||||
# Admin starts running infinite query
|
||||
process = multiprocessing.Process(
|
||||
target=process_function, args=(superadmin_cursor, ["CALL infinite_query.long_query() YIELD my_id RETURN my_id"])
|
||||
@@ -194,17 +220,23 @@ def test_admin_sees_superadmin():
|
||||
# Kill transaction
|
||||
long_transaction_id = show_results[1 - executing_index][1]
|
||||
execute_and_fetch_all(admin_cursor, f"TERMINATE TRANSACTIONS '{long_transaction_id}'")
|
||||
execute_and_fetch_all(admin_cursor, "DROP USER admin")
|
||||
superadmin_connection.close()
|
||||
|
||||
|
||||
def test_admin_can_see_user_transaction():
|
||||
def test_admin_can_see_user_transaction(request):
|
||||
"""Tests that admin can see user's transaction and kill it."""
|
||||
superadmin_cursor = connect().cursor()
|
||||
execute_and_fetch_all(superadmin_cursor, "CREATE USER admin")
|
||||
execute_and_fetch_all(superadmin_cursor, "GRANT TRANSACTION_MANAGEMENT TO admin")
|
||||
execute_and_fetch_all(superadmin_cursor, "GRANT DATABASE * TO admin")
|
||||
execute_and_fetch_all(superadmin_cursor, "CREATE USER user")
|
||||
|
||||
def on_exit():
|
||||
execute_and_fetch_all(superadmin_cursor, "DROP USER admin")
|
||||
execute_and_fetch_all(superadmin_cursor, "DROP USER user")
|
||||
|
||||
request.addfinalizer(on_exit)
|
||||
|
||||
# Admin starts running infinite query
|
||||
admin_connection = connect(username="admin", password="")
|
||||
admin_cursor = admin_connection.cursor()
|
||||
@@ -229,13 +261,11 @@ def test_admin_can_see_user_transaction():
|
||||
# Kill transaction
|
||||
long_transaction_id = show_results[1 - executing_index][1]
|
||||
execute_and_fetch_all(admin_cursor, f"TERMINATE TRANSACTIONS '{long_transaction_id}'")
|
||||
execute_and_fetch_all(superadmin_cursor, "DROP USER admin")
|
||||
execute_and_fetch_all(superadmin_cursor, "DROP USER user")
|
||||
admin_connection.close()
|
||||
user_connection.close()
|
||||
|
||||
|
||||
def test_user_cannot_see_admin_transaction():
|
||||
def test_user_cannot_see_admin_transaction(request):
|
||||
"""User cannot see admin's transaction but other admin can and he can kill it."""
|
||||
# Superadmin creates two admins and one user
|
||||
superadmin_cursor = connect().cursor()
|
||||
@@ -246,6 +276,14 @@ def test_user_cannot_see_admin_transaction():
|
||||
execute_and_fetch_all(superadmin_cursor, "GRANT TRANSACTION_MANAGEMENT TO admin2")
|
||||
execute_and_fetch_all(superadmin_cursor, "GRANT DATABASE * TO admin2")
|
||||
execute_and_fetch_all(superadmin_cursor, "CREATE USER user")
|
||||
|
||||
def on_exit():
|
||||
execute_and_fetch_all(superadmin_cursor, "DROP USER admin1")
|
||||
execute_and_fetch_all(superadmin_cursor, "DROP USER admin2")
|
||||
execute_and_fetch_all(superadmin_cursor, "DROP USER user")
|
||||
|
||||
request.addfinalizer(on_exit)
|
||||
|
||||
admin_connection_1 = connect(username="admin1", password="")
|
||||
admin_cursor_1 = admin_connection_1.cursor()
|
||||
admin_connection_2 = connect(username="admin2", password="")
|
||||
@@ -274,9 +312,6 @@ def test_user_cannot_see_admin_transaction():
|
||||
# Kill transaction
|
||||
long_transaction_id = show_results[1 - executing_index][1]
|
||||
execute_and_fetch_all(admin_cursor_2, f"TERMINATE TRANSACTIONS '{long_transaction_id}'")
|
||||
execute_and_fetch_all(superadmin_cursor, "DROP USER admin1")
|
||||
execute_and_fetch_all(superadmin_cursor, "DROP USER admin2")
|
||||
execute_and_fetch_all(superadmin_cursor, "DROP USER user")
|
||||
admin_connection_1.close()
|
||||
admin_connection_2.close()
|
||||
user_connection.close()
|
||||
@@ -300,12 +335,18 @@ def test_killing_multiple_non_existing_transactions():
|
||||
assert results[i][1] == False # not killed
|
||||
|
||||
|
||||
def test_admin_killing_multiple_non_existing_transactions():
|
||||
def test_admin_killing_multiple_non_existing_transactions(request):
|
||||
# Starting, superadmin admin
|
||||
superadmin_cursor = connect().cursor()
|
||||
execute_and_fetch_all(superadmin_cursor, "CREATE USER admin")
|
||||
execute_and_fetch_all(superadmin_cursor, "GRANT TRANSACTION_MANAGEMENT TO admin")
|
||||
execute_and_fetch_all(superadmin_cursor, "GRANT DATABASE * TO admin")
|
||||
|
||||
def on_exit():
|
||||
execute_and_fetch_all(admin_cursor, "DROP USER admin")
|
||||
|
||||
request.addfinalizer(on_exit)
|
||||
|
||||
# Connect with admin
|
||||
admin_cursor = connect(username="admin", password="").cursor()
|
||||
transactions_id = ["'1'", "'2'", "'3'"]
|
||||
@@ -314,7 +355,6 @@ def test_admin_killing_multiple_non_existing_transactions():
|
||||
for i in range(len(results)):
|
||||
assert results[i][0] == eval(transactions_id[i]) # transaction id
|
||||
assert results[i][1] == False # not killed
|
||||
execute_and_fetch_all(admin_cursor, "DROP USER admin")
|
||||
|
||||
|
||||
def test_user_killing_some_transactions():
|
||||
|
||||
@@ -193,12 +193,12 @@ def execute_test(memgraph_binary, tester_binary, checker_binary):
|
||||
"GRANT DATABASE db2 TO user",
|
||||
"CREATE USER useR2 IDENTIFIED BY 'user'",
|
||||
"GRANT DATABASE db2 TO user2",
|
||||
"REVOKE DATABASE memgraph FROM user2",
|
||||
"DENY DATABASE memgraph FROM user2",
|
||||
"SET MAIN DATABASE db2 FOR user2",
|
||||
"CREATE USER user3 IDENTIFIED BY 'user'",
|
||||
"GRANT ALL PRIVILEGES TO user3",
|
||||
"GRANT DATABASE * TO user3",
|
||||
"REVOKE DATABASE memgraph FROM user3",
|
||||
"DENY DATABASE memgraph FROM user3",
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
@@ -139,7 +139,7 @@ class Memgraph:
|
||||
def initialize_test(memgraph, tester_binary, **kwargs):
|
||||
memgraph.start(module_executable="")
|
||||
|
||||
execute_tester(tester_binary, ["CREATE USER root", "GRANT ALL PRIVILEGES TO root"])
|
||||
execute_tester(tester_binary, ["CREATE ROLE root_role", "GRANT ALL PRIVILEGES TO root_role"])
|
||||
check_login = kwargs.pop("check_login", True)
|
||||
memgraph.restart(**kwargs)
|
||||
if check_login:
|
||||
@@ -149,20 +149,24 @@ def initialize_test(memgraph, tester_binary, **kwargs):
|
||||
# Tests
|
||||
|
||||
|
||||
def test_basic(memgraph, tester_binary):
|
||||
def test_module_ux(memgraph, tester_binary):
|
||||
initialize_test(memgraph, tester_binary)
|
||||
execute_tester(tester_binary, [], "alice")
|
||||
execute_tester(tester_binary, ["GRANT MATCH TO alice"], "root")
|
||||
execute_tester(tester_binary, ["MATCH (n) RETURN n"], "alice")
|
||||
execute_tester(tester_binary, ["CREATE USER user1"], "root", query_should_fail=True)
|
||||
execute_tester(tester_binary, ["CREATE ROLE role1"], "root", query_should_fail=False)
|
||||
execute_tester(tester_binary, ["DROP USER user1"], "root", query_should_fail=True)
|
||||
execute_tester(tester_binary, ["DROP ROLE role1"], "root", query_should_fail=False)
|
||||
execute_tester(tester_binary, ["SET ROLE FOR user1 TO role1"], "root", query_should_fail=True)
|
||||
execute_tester(tester_binary, ["CLEAR ROLE FOR user1"], "root", query_should_fail=True)
|
||||
memgraph.stop()
|
||||
|
||||
|
||||
def test_only_existing_users(memgraph, tester_binary):
|
||||
initialize_test(memgraph, tester_binary, create_missing_user=False)
|
||||
def test_user_auth(memgraph, tester_binary):
|
||||
initialize_test(memgraph, tester_binary)
|
||||
execute_tester(tester_binary, [], "alice", auth_should_fail=True)
|
||||
execute_tester(tester_binary, ["CREATE USER alice"], "root")
|
||||
execute_tester(tester_binary, ["CREATE ROLE moderator"], "root")
|
||||
execute_tester(tester_binary, [], "alice")
|
||||
execute_tester(tester_binary, ["GRANT MATCH TO alice"], "root")
|
||||
execute_tester(tester_binary, ["MATCH (n) RETURN n"], "alice", query_should_fail=True)
|
||||
execute_tester(tester_binary, ["GRANT MATCH TO moderator"], "root")
|
||||
execute_tester(tester_binary, ["MATCH (n) RETURN n"], "alice")
|
||||
memgraph.stop()
|
||||
|
||||
@@ -170,77 +174,50 @@ def test_only_existing_users(memgraph, tester_binary):
|
||||
def test_role_mapping(memgraph, tester_binary):
|
||||
initialize_test(memgraph, tester_binary)
|
||||
|
||||
execute_tester(tester_binary, [], "alice")
|
||||
execute_tester(tester_binary, [], "alice", auth_should_fail=True)
|
||||
execute_tester(tester_binary, [], "bob", auth_should_fail=True)
|
||||
execute_tester(tester_binary, [], "carol", auth_should_fail=True)
|
||||
execute_tester(tester_binary, ["CREATE ROLE moderator"], "root")
|
||||
execute_tester(tester_binary, ["CREATE ROLE admin"], "root")
|
||||
execute_tester(tester_binary, [], "alice", auth_should_fail=False)
|
||||
execute_tester(tester_binary, [], "bob", auth_should_fail=True)
|
||||
execute_tester(tester_binary, [], "carol", auth_should_fail=False)
|
||||
|
||||
execute_tester(tester_binary, ["MATCH (n) RETURN n"], "alice", query_should_fail=True)
|
||||
execute_tester(tester_binary, ["MATCH (n) RETURN n"], "carol", query_should_fail=True)
|
||||
execute_tester(tester_binary, ["GRANT MATCH TO moderator"], "root")
|
||||
execute_tester(tester_binary, ["MATCH (n) RETURN n"], "alice")
|
||||
execute_tester(tester_binary, ["MATCH (n) RETURN n"], "alice", query_should_fail=False)
|
||||
execute_tester(tester_binary, ["MATCH (n) RETURN n"], "carol", query_should_fail=True)
|
||||
execute_tester(tester_binary, ["GRANT MATCH TO admin"], "root")
|
||||
execute_tester(tester_binary, ["MATCH (n) RETURN n"], "alice", query_should_fail=False)
|
||||
execute_tester(tester_binary, ["MATCH (n) RETURN n"], "carol", query_should_fail=False)
|
||||
|
||||
execute_tester(tester_binary, [], "bob")
|
||||
execute_tester(tester_binary, ["MATCH (n) RETURN n"], "bob", query_should_fail=True)
|
||||
|
||||
execute_tester(tester_binary, [], "carol")
|
||||
execute_tester(tester_binary, ["CREATE (n) RETURN n"], "alice", query_should_fail=True)
|
||||
execute_tester(tester_binary, ["CREATE (n) RETURN n"], "carol", query_should_fail=True)
|
||||
execute_tester(tester_binary, ["GRANT CREATE TO admin"], "root")
|
||||
execute_tester(tester_binary, ["CREATE (n) RETURN n"], "carol")
|
||||
execute_tester(tester_binary, ["CREATE (n) RETURN n"], "dave")
|
||||
execute_tester(tester_binary, ["CREATE (n) RETURN n"], "alice", query_should_fail=True)
|
||||
execute_tester(tester_binary, ["CREATE (n) RETURN n"], "carol", query_should_fail=False)
|
||||
|
||||
memgraph.stop()
|
||||
|
||||
|
||||
def test_instance_restart(memgraph, tester_binary):
|
||||
initialize_test(memgraph, tester_binary)
|
||||
execute_tester(tester_binary, ["CREATE ROLE moderator"], "root")
|
||||
execute_tester(tester_binary, ["GRANT MATCH TO moderator"], "root")
|
||||
execute_tester(tester_binary, ["MATCH (n) RETURN n"], "alice")
|
||||
memgraph.restart()
|
||||
execute_tester(tester_binary, ["MATCH (n) RETURN n"], "alice")
|
||||
memgraph.stop()
|
||||
|
||||
|
||||
def test_role_removal(memgraph, tester_binary):
|
||||
initialize_test(memgraph, tester_binary)
|
||||
execute_tester(tester_binary, [], "alice")
|
||||
execute_tester(tester_binary, ["MATCH (n) RETURN n"], "alice", query_should_fail=True)
|
||||
execute_tester(tester_binary, ["CREATE ROLE moderator"], "root")
|
||||
execute_tester(tester_binary, ["GRANT MATCH TO moderator"], "root")
|
||||
execute_tester(tester_binary, ["MATCH (n) RETURN n"], "alice")
|
||||
memgraph.restart(manage_roles=False)
|
||||
execute_tester(tester_binary, ["MATCH (n) RETURN n"], "alice")
|
||||
execute_tester(tester_binary, ["CLEAR ROLE FOR alice"], "root")
|
||||
execute_tester(tester_binary, ["MATCH (n) RETURN n"], "alice", query_should_fail=True)
|
||||
memgraph.stop()
|
||||
|
||||
|
||||
def test_only_existing_roles(memgraph, tester_binary):
|
||||
initialize_test(memgraph, tester_binary, create_missing_role=False)
|
||||
execute_tester(tester_binary, [], "bob")
|
||||
execute_tester(tester_binary, ["DROP ROLE moderator"], "root")
|
||||
execute_tester(tester_binary, [], "alice", auth_should_fail=True)
|
||||
execute_tester(tester_binary, ["CREATE ROLE moderator"], "root")
|
||||
execute_tester(tester_binary, [], "alice")
|
||||
memgraph.stop()
|
||||
|
||||
|
||||
def test_role_is_user(memgraph, tester_binary):
|
||||
initialize_test(memgraph, tester_binary)
|
||||
execute_tester(tester_binary, [], "admin")
|
||||
execute_tester(tester_binary, [], "carol", auth_should_fail=True)
|
||||
memgraph.stop()
|
||||
|
||||
|
||||
def test_user_is_role(memgraph, tester_binary):
|
||||
initialize_test(memgraph, tester_binary)
|
||||
execute_tester(tester_binary, [], "carol")
|
||||
execute_tester(tester_binary, [], "admin", auth_should_fail=True)
|
||||
memgraph.stop()
|
||||
|
||||
|
||||
def test_user_permissions_persistancy(memgraph, tester_binary):
|
||||
initialize_test(memgraph, tester_binary)
|
||||
execute_tester(tester_binary, ["CREATE USER alice", "GRANT MATCH TO alice"], "root")
|
||||
execute_tester(tester_binary, ["MATCH (n) RETURN n"], "alice")
|
||||
memgraph.stop()
|
||||
|
||||
|
||||
def test_role_permissions_persistancy(memgraph, tester_binary):
|
||||
initialize_test(memgraph, tester_binary)
|
||||
execute_tester(tester_binary, ["CREATE ROLE moderator", "GRANT MATCH TO moderator"], "root")
|
||||
execute_tester(tester_binary, ["MATCH (n) RETURN n"], "alice")
|
||||
memgraph.stop()
|
||||
|
||||
|
||||
def test_only_authentication(memgraph, tester_binary):
|
||||
initialize_test(memgraph, tester_binary, manage_roles=False)
|
||||
execute_tester(tester_binary, ["CREATE ROLE moderator", "GRANT MATCH TO moderator"], "root")
|
||||
execute_tester(tester_binary, ["MATCH (n) RETURN n"], "alice", query_should_fail=True)
|
||||
memgraph.stop()
|
||||
|
||||
|
||||
@@ -258,36 +235,36 @@ def test_wrong_suffix(memgraph, tester_binary):
|
||||
|
||||
def test_suffix_with_spaces(memgraph, tester_binary):
|
||||
initialize_test(memgraph, tester_binary, suffix=", ou= people, dc = memgraph, dc = com")
|
||||
execute_tester(tester_binary, ["CREATE USER alice", "GRANT MATCH TO alice"], "root")
|
||||
execute_tester(tester_binary, ["MATCH (n) RETURN n"], "alice")
|
||||
memgraph.stop()
|
||||
|
||||
|
||||
def test_role_mapping_wrong_root_dn(memgraph, tester_binary):
|
||||
initialize_test(memgraph, tester_binary, root_dn="ou=invalid,dc=memgraph,dc=com")
|
||||
execute_tester(tester_binary, ["CREATE ROLE moderator", "GRANT MATCH TO moderator"], "root")
|
||||
execute_tester(tester_binary, ["MATCH (n) RETURN n"], "alice", query_should_fail=True)
|
||||
memgraph.restart()
|
||||
execute_tester(tester_binary, ["MATCH (n) RETURN n"], "alice")
|
||||
memgraph.stop()
|
||||
|
||||
|
||||
def test_role_mapping_wrong_root_objectclass(memgraph, tester_binary):
|
||||
initialize_test(memgraph, tester_binary, root_objectclass="person")
|
||||
execute_tester(tester_binary, ["CREATE ROLE moderator", "GRANT MATCH TO moderator"], "root")
|
||||
execute_tester(tester_binary, ["MATCH (n) RETURN n"], "alice", query_should_fail=True)
|
||||
memgraph.restart()
|
||||
execute_tester(tester_binary, ["MATCH (n) RETURN n"], "alice")
|
||||
memgraph.stop()
|
||||
# def test_role_mapping_wrong_root_dn(memgraph, tester_binary):
|
||||
# initialize_test(memgraph, tester_binary, root_dn="ou=invalid,dc=memgraph,dc=com")
|
||||
# execute_tester(tester_binary, ["CREATE ROLE moderator", "GRANT MATCH TO moderator"], "root")
|
||||
# execute_tester(tester_binary, ["MATCH (n) RETURN n"], "alice", query_should_fail=True)
|
||||
# memgraph.restart()
|
||||
# execute_tester(tester_binary, ["MATCH (n) RETURN n"], "alice")
|
||||
# memgraph.stop()
|
||||
|
||||
|
||||
def test_role_mapping_wrong_user_attribute(memgraph, tester_binary):
|
||||
initialize_test(memgraph, tester_binary, user_attribute="cn")
|
||||
execute_tester(tester_binary, ["CREATE ROLE moderator", "GRANT MATCH TO moderator"], "root")
|
||||
execute_tester(tester_binary, ["MATCH (n) RETURN n"], "alice", query_should_fail=True)
|
||||
memgraph.restart()
|
||||
execute_tester(tester_binary, ["MATCH (n) RETURN n"], "alice")
|
||||
memgraph.stop()
|
||||
# def test_role_mapping_wrong_root_objectclass(memgraph, tester_binary):
|
||||
# initialize_test(memgraph, tester_binary, root_objectclass="person")
|
||||
# execute_tester(tester_binary, ["CREATE ROLE moderator", "GRANT MATCH TO moderator"], "root")
|
||||
# execute_tester(tester_binary, ["MATCH (n) RETURN n"], "alice", query_should_fail=True)
|
||||
# memgraph.restart()
|
||||
# execute_tester(tester_binary, ["MATCH (n) RETURN n"], "alice")
|
||||
# memgraph.stop()
|
||||
|
||||
|
||||
# def test_role_mapping_wrong_user_attribute(memgraph, tester_binary):
|
||||
# initialize_test(memgraph, tester_binary, user_attribute="cn")
|
||||
# execute_tester(tester_binary, ["CREATE ROLE moderator", "GRANT MATCH TO moderator"], "root")
|
||||
# execute_tester(tester_binary, ["MATCH (n) RETURN n"], "alice", query_should_fail=True)
|
||||
# memgraph.restart()
|
||||
# execute_tester(tester_binary, ["MATCH (n) RETURN n"], "alice")
|
||||
# memgraph.stop()
|
||||
|
||||
|
||||
def test_wrong_password(memgraph, tester_binary):
|
||||
@@ -297,31 +274,9 @@ def test_wrong_password(memgraph, tester_binary):
|
||||
memgraph.stop()
|
||||
|
||||
|
||||
def test_password_persistancy(memgraph, tester_binary):
|
||||
initialize_test(memgraph, tester_binary, check_login=False)
|
||||
memgraph.restart(module_executable="")
|
||||
execute_tester(tester_binary, ["SHOW USERS"], "root", password="sudo")
|
||||
execute_tester(tester_binary, ["SHOW USERS"], "root", password="root")
|
||||
memgraph.restart()
|
||||
execute_tester(tester_binary, [], "root", password="sudo", auth_should_fail=True)
|
||||
execute_tester(tester_binary, ["SHOW USERS"], "root", password="root")
|
||||
memgraph.restart(module_executable="")
|
||||
execute_tester(tester_binary, [], "root", password="sudo", auth_should_fail=True)
|
||||
execute_tester(tester_binary, ["SHOW USERS"], "root", password="root")
|
||||
memgraph.stop()
|
||||
|
||||
|
||||
def test_user_multiple_roles(memgraph, tester_binary):
|
||||
initialize_test(memgraph, tester_binary, check_login=False)
|
||||
memgraph.restart()
|
||||
execute_tester(tester_binary, ["MATCH (n) RETURN n"], "eve", query_should_fail=True)
|
||||
execute_tester(tester_binary, ["GRANT MATCH TO moderator"], "root", query_should_fail=True)
|
||||
memgraph.restart(manage_roles=False)
|
||||
execute_tester(tester_binary, ["MATCH (n) RETURN n"], "eve", query_should_fail=True)
|
||||
execute_tester(tester_binary, ["GRANT MATCH TO moderator"], "root", query_should_fail=True)
|
||||
memgraph.restart(manage_roles=False, root_dn="")
|
||||
execute_tester(tester_binary, ["MATCH (n) RETURN n"], "eve", query_should_fail=True)
|
||||
execute_tester(tester_binary, ["GRANT MATCH TO moderator"], "root", query_should_fail=True)
|
||||
initialize_test(memgraph, tester_binary)
|
||||
execute_tester(tester_binary, ["MATCH (n) RETURN n"], "eve", auth_should_fail=True)
|
||||
memgraph.stop()
|
||||
|
||||
|
||||
|
||||
@@ -84,6 +84,13 @@ objectclass: organizationalUnit
|
||||
objectclass: top
|
||||
ou: roles
|
||||
|
||||
# Role root
|
||||
dn: cn=root_role,ou=roles,dc=memgraph,dc=com
|
||||
cn: root_role
|
||||
member: cn=root,ou=people,dc=memgraph,dc=com
|
||||
objectclass: groupOfNames
|
||||
objectclass: top
|
||||
|
||||
# Role moderator
|
||||
dn: cn=moderator,ou=roles,dc=memgraph,dc=com
|
||||
cn: moderator
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2022 Memgraph Ltd.
|
||||
// Copyright 2024 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
|
||||
@@ -48,6 +48,7 @@ int main(int argc, char **argv) {
|
||||
}
|
||||
if (FLAGS_auth_should_fail) {
|
||||
MG_ASSERT(!what.empty(), "The authentication should have failed!");
|
||||
return 0; // Auth failed, nothing left to do
|
||||
} else {
|
||||
MG_ASSERT(what.empty(),
|
||||
"The authentication should have succeeded, but "
|
||||
|
||||
@@ -50,6 +50,8 @@ int main(int argc, char *argv[]) {
|
||||
memgraph::query::Interpreter interpreter{&interpreter_context, db_acc};
|
||||
|
||||
ResultStreamFaker stream(db_acc->storage());
|
||||
memgraph::query::AllowEverythingAuthChecker auth_checker;
|
||||
interpreter.SetUser(auth_checker.GenQueryUser(std::nullopt, std::nullopt));
|
||||
auto [header, _1, qid, _2] = interpreter.Prepare(argv[1], {}, {});
|
||||
stream.Header(header);
|
||||
auto summary = interpreter.PullAll(&stream);
|
||||
|
||||
@@ -280,6 +280,8 @@ TEST_F(AuthWithStorage, RoleManipulations) {
|
||||
}
|
||||
|
||||
{
|
||||
const auto all = auth->AllUsernames();
|
||||
for (const auto &user : all) std::cout << user << std::endl;
|
||||
auto users = auth->AllUsers();
|
||||
std::sort(users.begin(), users.end(), [](const User &a, const User &b) { return a.username() < b.username(); });
|
||||
ASSERT_EQ(users.size(), 2);
|
||||
@@ -774,14 +776,16 @@ TEST_F(AuthWithStorage, CaseInsensitivity) {
|
||||
|
||||
// Authenticate
|
||||
{
|
||||
auto user = auth->Authenticate("alice", "alice");
|
||||
ASSERT_TRUE(user);
|
||||
ASSERT_EQ(user->username(), "alice");
|
||||
auto user_or_role = auth->Authenticate("alice", "alice");
|
||||
ASSERT_TRUE(user_or_role);
|
||||
const auto &user = std::get<memgraph::auth::User>(*user_or_role);
|
||||
ASSERT_EQ(user.username(), "alice");
|
||||
}
|
||||
{
|
||||
auto user = auth->Authenticate("alICe", "alice");
|
||||
ASSERT_TRUE(user);
|
||||
ASSERT_EQ(user->username(), "alice");
|
||||
auto user_or_role = auth->Authenticate("alICe", "alice");
|
||||
ASSERT_TRUE(user_or_role);
|
||||
const auto &user = std::get<memgraph::auth::User>(*user_or_role);
|
||||
ASSERT_EQ(user.username(), "alice");
|
||||
}
|
||||
|
||||
// GetUser
|
||||
@@ -809,6 +813,8 @@ TEST_F(AuthWithStorage, CaseInsensitivity) {
|
||||
|
||||
// AllUsers
|
||||
{
|
||||
const auto all = auth->AllUsernames();
|
||||
for (const auto &user : all) std::cout << user << std::endl;
|
||||
auto users = auth->AllUsers();
|
||||
ASSERT_EQ(users.size(), 2);
|
||||
std::sort(users.begin(), users.end(), [](const auto &a, const auto &b) { return a.username() < b.username(); });
|
||||
|
||||
@@ -12,11 +12,14 @@
|
||||
#include <gmock/gmock.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "auth/exceptions.hpp"
|
||||
#include "auth/models.hpp"
|
||||
#include "disk_test_utils.hpp"
|
||||
#include "glue/auth_checker.hpp"
|
||||
|
||||
#include "license/license.hpp"
|
||||
#include "query/frontend/ast/ast.hpp"
|
||||
#include "query/query_user.hpp"
|
||||
#include "query_plan_common.hpp"
|
||||
#include "storage/v2/config.hpp"
|
||||
#include "storage/v2/disk/storage.hpp"
|
||||
@@ -225,4 +228,123 @@ TYPED_TEST(FineGrainedAuthCheckerFixture, GrantAndDenySpecificEdgeTypes) {
|
||||
ASSERT_FALSE(auth_checker.Has(this->r3, memgraph::query::AuthQuery::FineGrainedPrivilege::READ));
|
||||
ASSERT_FALSE(auth_checker.Has(this->r4, memgraph::query::AuthQuery::FineGrainedPrivilege::READ));
|
||||
}
|
||||
|
||||
TEST(AuthChecker, Generate) {
|
||||
std::filesystem::path auth_dir{std::filesystem::temp_directory_path() / "MG_auth_checker"};
|
||||
memgraph::utils::OnScopeExit clean([&]() {
|
||||
if (std::filesystem::exists(auth_dir)) {
|
||||
std::filesystem::remove_all(auth_dir);
|
||||
}
|
||||
});
|
||||
memgraph::auth::SynchedAuth auth(auth_dir, memgraph::auth::Auth::Config{/* default config */});
|
||||
memgraph::glue::AuthChecker auth_checker(&auth);
|
||||
|
||||
auto empty_user = auth_checker.GenQueryUser(std::nullopt, std::nullopt);
|
||||
ASSERT_THROW(auth_checker.GenQueryUser("does_not_exist", std::nullopt), memgraph::auth::AuthException);
|
||||
|
||||
EXPECT_FALSE(empty_user && *empty_user);
|
||||
// Still empty auth, so the above should have su permissions
|
||||
using enum memgraph::query::AuthQuery::Privilege;
|
||||
EXPECT_TRUE(empty_user->IsAuthorized({AUTH, REMOVE, REPLICATION}, "", &memgraph::query::session_long_policy));
|
||||
EXPECT_TRUE(empty_user->IsAuthorized({FREE_MEMORY, WEBSOCKET, MULTI_DATABASE_EDIT}, "memgraph",
|
||||
&memgraph::query::session_long_policy));
|
||||
EXPECT_TRUE(
|
||||
empty_user->IsAuthorized({TRIGGER, DURABILITY, STORAGE_MODE}, "some_db", &memgraph::query::session_long_policy));
|
||||
|
||||
// Add user
|
||||
auth->AddUser("new_user");
|
||||
|
||||
// ~Empty user should now fail~
|
||||
// NOTE: Cache invalidation has been disabled, so this will pass; change if it is ever turned on
|
||||
EXPECT_TRUE(empty_user->IsAuthorized({AUTH, REMOVE, REPLICATION}, "", &memgraph::query::session_long_policy));
|
||||
EXPECT_TRUE(empty_user->IsAuthorized({FREE_MEMORY, WEBSOCKET, MULTI_DATABASE_EDIT}, "memgraph",
|
||||
&memgraph::query::session_long_policy));
|
||||
EXPECT_TRUE(
|
||||
empty_user->IsAuthorized({TRIGGER, DURABILITY, STORAGE_MODE}, "some_db", &memgraph::query::session_long_policy));
|
||||
|
||||
// Add role and new user
|
||||
auto new_role = *auth->AddRole("new_role");
|
||||
auto new_user2 = *auth->AddUser("new_user2");
|
||||
auto role = auth_checker.GenQueryUser("anyuser", "new_role");
|
||||
auto user2 = auth_checker.GenQueryUser("new_user2", std::nullopt);
|
||||
|
||||
// Should be permission-less by default
|
||||
EXPECT_FALSE(role->IsAuthorized({AUTH}, "memgraph", &memgraph::query::session_long_policy));
|
||||
EXPECT_FALSE(role->IsAuthorized({FREE_MEMORY}, "memgraph", &memgraph::query::session_long_policy));
|
||||
EXPECT_FALSE(role->IsAuthorized({TRIGGER}, "memgraph", &memgraph::query::session_long_policy));
|
||||
EXPECT_FALSE(user2->IsAuthorized({AUTH}, "memgraph", &memgraph::query::session_long_policy));
|
||||
EXPECT_FALSE(user2->IsAuthorized({FREE_MEMORY}, "memgraph", &memgraph::query::session_long_policy));
|
||||
EXPECT_FALSE(user2->IsAuthorized({TRIGGER}, "memgraph", &memgraph::query::session_long_policy));
|
||||
|
||||
// Update permissions and recheck
|
||||
new_user2.permissions().Grant(memgraph::auth::Permission::AUTH);
|
||||
new_role.permissions().Grant(memgraph::auth::Permission::TRIGGER);
|
||||
auth->SaveUser(new_user2);
|
||||
auth->SaveRole(new_role);
|
||||
role = auth_checker.GenQueryUser("no check", "new_role");
|
||||
user2 = auth_checker.GenQueryUser("new_user2", std::nullopt);
|
||||
EXPECT_FALSE(role->IsAuthorized({AUTH}, "memgraph", &memgraph::query::session_long_policy));
|
||||
EXPECT_FALSE(role->IsAuthorized({FREE_MEMORY}, "memgraph", &memgraph::query::session_long_policy));
|
||||
EXPECT_TRUE(role->IsAuthorized({TRIGGER}, "memgraph", &memgraph::query::session_long_policy));
|
||||
EXPECT_TRUE(user2->IsAuthorized({AUTH}, "memgraph", &memgraph::query::session_long_policy));
|
||||
EXPECT_FALSE(user2->IsAuthorized({FREE_MEMORY}, "memgraph", &memgraph::query::session_long_policy));
|
||||
EXPECT_FALSE(user2->IsAuthorized({TRIGGER}, "memgraph", &memgraph::query::session_long_policy));
|
||||
|
||||
// Connect role and recheck
|
||||
new_user2.SetRole(new_role);
|
||||
auth->SaveUser(new_user2);
|
||||
user2 = auth_checker.GenQueryUser("new_user2", std::nullopt);
|
||||
EXPECT_TRUE(user2->IsAuthorized({AUTH}, "memgraph", &memgraph::query::session_long_policy));
|
||||
EXPECT_FALSE(user2->IsAuthorized({FREE_MEMORY}, "memgraph", &memgraph::query::session_long_policy));
|
||||
EXPECT_TRUE(user2->IsAuthorized({TRIGGER}, "memgraph", &memgraph::query::session_long_policy));
|
||||
|
||||
// Add database and recheck
|
||||
EXPECT_FALSE(user2->IsAuthorized({AUTH}, "non_default", &memgraph::query::session_long_policy));
|
||||
EXPECT_FALSE(user2->IsAuthorized({AUTH}, "another", &memgraph::query::session_long_policy));
|
||||
EXPECT_TRUE(user2->IsAuthorized({AUTH}, "memgraph", &memgraph::query::session_long_policy));
|
||||
EXPECT_FALSE(role->IsAuthorized({TRIGGER}, "non_default", &memgraph::query::session_long_policy));
|
||||
EXPECT_FALSE(role->IsAuthorized({TRIGGER}, "another", &memgraph::query::session_long_policy));
|
||||
EXPECT_TRUE(role->IsAuthorized({TRIGGER}, "memgraph", &memgraph::query::session_long_policy));
|
||||
new_user2.db_access().Grant("another");
|
||||
new_role.db_access().Grant("non_default");
|
||||
auth->SaveUser(new_user2);
|
||||
auth->SaveRole(new_role);
|
||||
// Session policy test
|
||||
// Session long policy
|
||||
EXPECT_FALSE(user2->IsAuthorized({AUTH}, "non_default", &memgraph::query::session_long_policy));
|
||||
EXPECT_FALSE(user2->IsAuthorized({AUTH}, "another", &memgraph::query::session_long_policy));
|
||||
EXPECT_TRUE(user2->IsAuthorized({AUTH}, "memgraph", &memgraph::query::session_long_policy));
|
||||
EXPECT_FALSE(role->IsAuthorized({TRIGGER}, "non_default", &memgraph::query::session_long_policy));
|
||||
EXPECT_FALSE(role->IsAuthorized({TRIGGER}, "another", &memgraph::query::session_long_policy));
|
||||
EXPECT_TRUE(role->IsAuthorized({TRIGGER}, "memgraph", &memgraph::query::session_long_policy));
|
||||
// Up to date policy
|
||||
EXPECT_TRUE(user2->IsAuthorized({AUTH}, "non_default", &memgraph::query::up_to_date_policy));
|
||||
EXPECT_TRUE(user2->IsAuthorized({AUTH}, "another", &memgraph::query::up_to_date_policy));
|
||||
EXPECT_TRUE(user2->IsAuthorized({AUTH}, "memgraph", &memgraph::query::up_to_date_policy));
|
||||
EXPECT_TRUE(role->IsAuthorized({TRIGGER}, "non_default", &memgraph::query::up_to_date_policy));
|
||||
EXPECT_FALSE(role->IsAuthorized({TRIGGER}, "another", &memgraph::query::up_to_date_policy));
|
||||
EXPECT_TRUE(role->IsAuthorized({TRIGGER}, "memgraph", &memgraph::query::up_to_date_policy));
|
||||
|
||||
new_user2.db_access().Deny("memgraph");
|
||||
new_role.db_access().Deny("non_default");
|
||||
auth->SaveUser(new_user2);
|
||||
auth->SaveRole(new_role);
|
||||
EXPECT_FALSE(user2->IsAuthorized({AUTH}, "non_default", &memgraph::query::up_to_date_policy));
|
||||
EXPECT_TRUE(user2->IsAuthorized({AUTH}, "another", &memgraph::query::up_to_date_policy));
|
||||
EXPECT_FALSE(user2->IsAuthorized({AUTH}, "memgraph", &memgraph::query::up_to_date_policy));
|
||||
EXPECT_FALSE(role->IsAuthorized({TRIGGER}, "non_default", &memgraph::query::up_to_date_policy));
|
||||
EXPECT_FALSE(role->IsAuthorized({TRIGGER}, "another", &memgraph::query::up_to_date_policy));
|
||||
EXPECT_TRUE(role->IsAuthorized({TRIGGER}, "memgraph", &memgraph::query::up_to_date_policy));
|
||||
|
||||
new_user2.db_access().Revoke("memgraph");
|
||||
new_role.db_access().Revoke("non_default");
|
||||
auth->SaveUser(new_user2);
|
||||
auth->SaveRole(new_role);
|
||||
EXPECT_FALSE(user2->IsAuthorized({AUTH}, "non_default", &memgraph::query::up_to_date_policy));
|
||||
EXPECT_TRUE(user2->IsAuthorized({AUTH}, "another", &memgraph::query::up_to_date_policy));
|
||||
EXPECT_TRUE(user2->IsAuthorized({AUTH}, "memgraph", &memgraph::query::up_to_date_policy));
|
||||
EXPECT_FALSE(role->IsAuthorized({TRIGGER}, "non_default", &memgraph::query::up_to_date_policy));
|
||||
EXPECT_FALSE(role->IsAuthorized({TRIGGER}, "another", &memgraph::query::up_to_date_policy));
|
||||
EXPECT_TRUE(role->IsAuthorized({TRIGGER}, "memgraph", &memgraph::query::up_to_date_policy));
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2023 Memgraph Ltd.
|
||||
// Copyright 2024 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
|
||||
@@ -18,6 +18,7 @@ struct InterpreterFaker {
|
||||
: interpreter_context(interpreter_context), interpreter(interpreter_context, db) {
|
||||
interpreter_context->auth_checker = &auth_checker;
|
||||
interpreter_context->interpreters.WithLock([this](auto &interpreters) { interpreters.insert(&interpreter); });
|
||||
interpreter.SetUser(auth_checker.GenQueryUser(std::nullopt, std::nullopt));
|
||||
}
|
||||
|
||||
auto Prepare(const std::string &query, const std::map<std::string, memgraph::storage::PropertyValue> ¶ms = {}) {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2022 Memgraph Ltd.
|
||||
// Copyright 2024 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
|
||||
@@ -44,11 +44,9 @@ struct MockAuth : public memgraph::communication::websocket::AuthenticationInter
|
||||
return authentication;
|
||||
}
|
||||
|
||||
bool HasUserPermission(const std::string & /*username*/, memgraph::auth::Permission /*permission*/) const override {
|
||||
return authorization;
|
||||
}
|
||||
bool HasPermission(memgraph::auth::Permission /*permission*/) const override { return authorization; }
|
||||
|
||||
bool HasAnyUsers() const override { return has_any_users; }
|
||||
bool AccessControlled() const override { return has_any_users; }
|
||||
|
||||
bool authentication{true};
|
||||
bool authorization{true};
|
||||
|
||||
@@ -21,6 +21,8 @@
|
||||
#include "communication/result_stream_faker.hpp"
|
||||
#include "dbms/database.hpp"
|
||||
#include "disk_test_utils.hpp"
|
||||
#include "glue/auth_checker.hpp"
|
||||
#include "query/auth_checker.hpp"
|
||||
#include "query/config.hpp"
|
||||
#include "query/dump.hpp"
|
||||
#include "query/interpreter.hpp"
|
||||
@@ -216,6 +218,8 @@ DatabaseState GetState(memgraph::storage::Storage *db) {
|
||||
auto Execute(memgraph::query::InterpreterContext *context, memgraph::dbms::DatabaseAccess db,
|
||||
const std::string &query) {
|
||||
memgraph::query::Interpreter interpreter(context, db);
|
||||
memgraph::query::AllowEverythingAuthChecker auth_checker;
|
||||
interpreter.SetUser(auth_checker.GenQueryUser(std::nullopt, std::nullopt));
|
||||
ResultStreamFaker stream(db->storage());
|
||||
|
||||
auto [header, _1, qid, _2] = interpreter.Prepare(query, {}, {});
|
||||
@@ -915,7 +919,10 @@ TYPED_TEST(DumpTest, ExecuteDumpDatabase) {
|
||||
class StatefulInterpreter {
|
||||
public:
|
||||
explicit StatefulInterpreter(memgraph::query::InterpreterContext *context, memgraph::dbms::DatabaseAccess db)
|
||||
: context_(context), interpreter_(context_, db) {}
|
||||
: context_(context), interpreter_(context_, db) {
|
||||
memgraph::query::AllowEverythingAuthChecker auth_checker;
|
||||
interpreter_.SetUser(auth_checker.GenQueryUser(std::nullopt, std::nullopt));
|
||||
}
|
||||
|
||||
auto Execute(const std::string &query) {
|
||||
ResultStreamFaker stream(interpreter_.current_db_.db_acc_->get()->storage());
|
||||
@@ -1138,7 +1145,7 @@ TYPED_TEST(DumpTest, DumpDatabaseWithTriggers) {
|
||||
memgraph::query::DbAccessor dba(acc.get());
|
||||
const std::map<std::string, memgraph::storage::PropertyValue> props;
|
||||
trigger_store->AddTrigger(trigger_name, trigger_statement, props, trigger_event_type, trigger_phase, &ast_cache,
|
||||
&dba, query_config, std::nullopt, &auth_checker);
|
||||
&dba, query_config, auth_checker.GenQueryUser(std::nullopt, std::nullopt));
|
||||
}
|
||||
{
|
||||
ResultStreamFaker stream(this->db->storage());
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include "communication/result_stream_faker.hpp"
|
||||
#include "query/auth_checker.hpp"
|
||||
#include "query/interpreter.hpp"
|
||||
#include "query/interpreter_context.hpp"
|
||||
#include "query/stream/streams.hpp"
|
||||
@@ -36,6 +37,7 @@ class QueryExecution : public testing::Test {
|
||||
const std::string testSuite = "query_plan_edge_cases";
|
||||
std::optional<memgraph::dbms::DatabaseAccess> db_acc_;
|
||||
std::optional<memgraph::query::InterpreterContext> interpreter_context_;
|
||||
std::optional<memgraph::query::AllowEverythingAuthChecker> auth_checker_;
|
||||
std::optional<memgraph::query::Interpreter> interpreter_;
|
||||
|
||||
std::filesystem::path data_directory{std::filesystem::temp_directory_path() / "MG_tests_unit_query_plan_edge_cases"};
|
||||
@@ -73,11 +75,14 @@ class QueryExecution : public testing::Test {
|
||||
nullptr
|
||||
#endif
|
||||
);
|
||||
auth_checker_.emplace();
|
||||
interpreter_.emplace(&*interpreter_context_, *db_acc_);
|
||||
interpreter_->SetUser(auth_checker_->GenQueryUser(std::nullopt, std::nullopt));
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
interpreter_ = std::nullopt;
|
||||
auth_checker_.reset();
|
||||
interpreter_context_ = std::nullopt;
|
||||
system_state.reset();
|
||||
db_acc_.reset();
|
||||
|
||||
@@ -20,9 +20,11 @@
|
||||
#include "integrations/constants.hpp"
|
||||
#include "integrations/kafka/exceptions.hpp"
|
||||
#include "kafka_mock.hpp"
|
||||
#include "query/auth_checker.hpp"
|
||||
#include "query/config.hpp"
|
||||
#include "query/interpreter.hpp"
|
||||
#include "query/interpreter_context.hpp"
|
||||
#include "query/query_user.hpp"
|
||||
#include "query/stream/streams.hpp"
|
||||
#include "storage/v2/config.hpp"
|
||||
#include "storage/v2/disk/storage.hpp"
|
||||
@@ -35,11 +37,23 @@ using StreamStatus = memgraph::query::stream::StreamStatus<memgraph::query::stre
|
||||
namespace {
|
||||
const static std::string kTopicName{"TrialTopic"};
|
||||
|
||||
struct FakeUser : memgraph::query::QueryUserOrRole {
|
||||
FakeUser() : memgraph::query::QueryUserOrRole{std::nullopt, std::nullopt} {}
|
||||
|
||||
bool IsAuthorized(const std::vector<memgraph::query::AuthQuery::Privilege> &privileges, const std::string &db_name,
|
||||
memgraph::query::UserPolicy *policy) const {
|
||||
return true;
|
||||
}
|
||||
#ifdef MG_ENTERPRISE
|
||||
std::string GetDefaultDB() const { return "memgraph"; }
|
||||
#endif
|
||||
};
|
||||
|
||||
struct StreamCheckData {
|
||||
std::string name;
|
||||
StreamInfo info;
|
||||
bool is_running;
|
||||
std::optional<std::string> owner;
|
||||
std::shared_ptr<memgraph::query::QueryUserOrRole> owner;
|
||||
};
|
||||
|
||||
std::string GetDefaultStreamName() {
|
||||
@@ -105,13 +119,16 @@ class StreamsTestFixture : public ::testing::Test {
|
||||
}() // iile
|
||||
};
|
||||
memgraph::system::System system_state;
|
||||
memgraph::query::InterpreterContext interpreter_context_{memgraph::query::InterpreterConfig{}, nullptr, &repl_state,
|
||||
system_state
|
||||
memgraph::query::AllowEverythingAuthChecker auth_checker;
|
||||
memgraph::query::InterpreterContext interpreter_context_{memgraph::query::InterpreterConfig{},
|
||||
nullptr,
|
||||
&repl_state,
|
||||
system_state,
|
||||
#ifdef MG_ENTERPRISE
|
||||
,
|
||||
nullptr
|
||||
nullptr,
|
||||
#endif
|
||||
};
|
||||
nullptr,
|
||||
&auth_checker};
|
||||
std::filesystem::path streams_data_directory_{data_directory_ / "separate-dir-for-test"};
|
||||
std::optional<StreamsTest> proxyStreams_;
|
||||
|
||||
@@ -173,7 +190,7 @@ class StreamsTestFixture : public ::testing::Test {
|
||||
}
|
||||
|
||||
StreamCheckData CreateDefaultStreamCheckData() {
|
||||
return {GetDefaultStreamName(), CreateDefaultStreamInfo(), false, std::nullopt};
|
||||
return {GetDefaultStreamName(), CreateDefaultStreamInfo(), false, std::make_unique<FakeUser>()};
|
||||
}
|
||||
|
||||
void Clear() {
|
||||
@@ -215,11 +232,11 @@ TYPED_TEST(StreamsTestFixture, CreateAlreadyExisting) {
|
||||
auto stream_info = this->CreateDefaultStreamInfo();
|
||||
auto stream_name = GetDefaultStreamName();
|
||||
this->proxyStreams_->streams_->template Create<memgraph::query::stream::KafkaStream>(
|
||||
stream_name, stream_info, std::nullopt, this->db_, &this->interpreter_context_);
|
||||
stream_name, stream_info, std::make_unique<FakeUser>(), this->db_, &this->interpreter_context_);
|
||||
|
||||
try {
|
||||
this->proxyStreams_->streams_->template Create<memgraph::query::stream::KafkaStream>(
|
||||
stream_name, stream_info, std::nullopt, this->db_, &this->interpreter_context_);
|
||||
stream_name, stream_info, std::make_unique<FakeUser>(), this->db_, &this->interpreter_context_);
|
||||
FAIL() << "Creating already existing stream should throw\n";
|
||||
} catch (memgraph::query::stream::StreamsException &exception) {
|
||||
EXPECT_EQ(exception.what(), fmt::format("Stream already exists with name '{}'", stream_name));
|
||||
@@ -231,7 +248,7 @@ TYPED_TEST(StreamsTestFixture, DropNotExistingStream) {
|
||||
const auto stream_name = GetDefaultStreamName();
|
||||
const std::string not_existing_stream_name{"ThisDoesn'tExists"};
|
||||
this->proxyStreams_->streams_->template Create<memgraph::query::stream::KafkaStream>(
|
||||
stream_name, stream_info, std::nullopt, this->db_, &this->interpreter_context_);
|
||||
stream_name, stream_info, std::make_unique<FakeUser>(), this->db_, &this->interpreter_context_);
|
||||
|
||||
try {
|
||||
this->proxyStreams_->streams_->Drop(not_existing_stream_name);
|
||||
@@ -262,7 +279,7 @@ TYPED_TEST(StreamsTestFixture, RestoreStreams) {
|
||||
if (i > 0) {
|
||||
stream_info.common_info.batch_interval = std::chrono::milliseconds((i + 1) * 10);
|
||||
stream_info.common_info.batch_size = 1000 + i;
|
||||
stream_check_data.owner = std::string{"owner"} + iteration_postfix;
|
||||
stream_check_data.owner = std::make_unique<FakeUser>();
|
||||
|
||||
// These are just random numbers to make the CONFIGS and CREDENTIALS map vary between consumers:
|
||||
// - 0 means no config, no credential
|
||||
@@ -280,7 +297,7 @@ TYPED_TEST(StreamsTestFixture, RestoreStreams) {
|
||||
this->mock_cluster_.CreateTopic(stream_info.topics[0]);
|
||||
}
|
||||
|
||||
stream_check_datas[3].owner = {};
|
||||
stream_check_datas[3].owner = std::make_unique<FakeUser>();
|
||||
|
||||
const auto check_restore_logic = [&stream_check_datas, this]() {
|
||||
// Reset the Streams object to trigger reloading
|
||||
@@ -336,7 +353,7 @@ TYPED_TEST(StreamsTestFixture, CheckWithTimeout) {
|
||||
const auto stream_info = this->CreateDefaultStreamInfo();
|
||||
const auto stream_name = GetDefaultStreamName();
|
||||
this->proxyStreams_->streams_->template Create<memgraph::query::stream::KafkaStream>(
|
||||
stream_name, stream_info, std::nullopt, this->db_, &this->interpreter_context_);
|
||||
stream_name, stream_info, std::make_unique<FakeUser>(), this->db_, &this->interpreter_context_);
|
||||
|
||||
std::chrono::milliseconds timeout{3000};
|
||||
|
||||
@@ -360,9 +377,10 @@ TYPED_TEST(StreamsTestFixture, CheckInvalidConfig) {
|
||||
EXPECT_TRUE(message.find(kInvalidConfigName) != std::string::npos) << message;
|
||||
EXPECT_TRUE(message.find(kConfigValue) != std::string::npos) << message;
|
||||
};
|
||||
EXPECT_THROW_WITH_MSG(this->proxyStreams_->streams_->template Create<memgraph::query::stream::KafkaStream>(
|
||||
stream_name, stream_info, std::nullopt, this->db_, &this->interpreter_context_),
|
||||
memgraph::integrations::kafka::SettingCustomConfigFailed, checker);
|
||||
EXPECT_THROW_WITH_MSG(
|
||||
this->proxyStreams_->streams_->template Create<memgraph::query::stream::KafkaStream>(
|
||||
stream_name, stream_info, std::make_unique<FakeUser>(), this->db_, &this->interpreter_context_),
|
||||
memgraph::integrations::kafka::SettingCustomConfigFailed, checker);
|
||||
}
|
||||
|
||||
TYPED_TEST(StreamsTestFixture, CheckInvalidCredentials) {
|
||||
@@ -376,7 +394,8 @@ TYPED_TEST(StreamsTestFixture, CheckInvalidCredentials) {
|
||||
EXPECT_TRUE(message.find(memgraph::integrations::kReducted) != std::string::npos) << message;
|
||||
EXPECT_TRUE(message.find(kCredentialValue) == std::string::npos) << message;
|
||||
};
|
||||
EXPECT_THROW_WITH_MSG(this->proxyStreams_->streams_->template Create<memgraph::query::stream::KafkaStream>(
|
||||
stream_name, stream_info, std::nullopt, this->db_, &this->interpreter_context_),
|
||||
memgraph::integrations::kafka::SettingCustomConfigFailed, checker);
|
||||
EXPECT_THROW_WITH_MSG(
|
||||
this->proxyStreams_->streams_->template Create<memgraph::query::stream::KafkaStream>(
|
||||
stream_name, stream_info, std::make_unique<FakeUser>(), this->db_, &this->interpreter_context_),
|
||||
memgraph::integrations::kafka::SettingCustomConfigFailed, checker);
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include "query/db_accessor.hpp"
|
||||
#include "query/frontend/ast/ast.hpp"
|
||||
#include "query/interpreter.hpp"
|
||||
#include "query/query_user.hpp"
|
||||
#include "query/trigger.hpp"
|
||||
#include "query/typed_value.hpp"
|
||||
#include "storage/v2/config.hpp"
|
||||
@@ -42,16 +43,27 @@ const std::unordered_set<memgraph::query::TriggerEventType> kAllEventTypes{
|
||||
|
||||
class MockAuthChecker : public memgraph::query::AuthChecker {
|
||||
public:
|
||||
MOCK_CONST_METHOD3(IsUserAuthorized,
|
||||
bool(const std::optional<std::string> &username,
|
||||
const std::vector<memgraph::query::AuthQuery::Privilege> &privileges, const std::string &db));
|
||||
MOCK_CONST_METHOD2(GenQueryUser,
|
||||
std::shared_ptr<memgraph::query::QueryUserOrRole>(const std::optional<std::string> &username,
|
||||
const std::optional<std::string> &rolename));
|
||||
#ifdef MG_ENTERPRISE
|
||||
MOCK_CONST_METHOD2(GetFineGrainedAuthChecker,
|
||||
std::unique_ptr<memgraph::query::FineGrainedAuthChecker>(
|
||||
const std::string &username, const memgraph::query::DbAccessor *db_accessor));
|
||||
MOCK_CONST_METHOD2(GetFineGrainedAuthChecker, std::unique_ptr<memgraph::query::FineGrainedAuthChecker>(
|
||||
std::shared_ptr<memgraph::query::QueryUserOrRole> user,
|
||||
const memgraph::query::DbAccessor *db_accessor));
|
||||
MOCK_CONST_METHOD0(ClearCache, void());
|
||||
#endif
|
||||
};
|
||||
|
||||
class MockQueryUser : public memgraph::query::QueryUserOrRole {
|
||||
public:
|
||||
MockQueryUser(std::optional<std::string> name) : memgraph::query::QueryUserOrRole(std::move(name), std::nullopt) {}
|
||||
MOCK_CONST_METHOD3(IsAuthorized, bool(const std::vector<memgraph::query::AuthQuery::Privilege> &privileges,
|
||||
const std::string &db_name, memgraph::query::UserPolicy *policy));
|
||||
|
||||
#ifdef MG_ENTERPRISE
|
||||
MOCK_CONST_METHOD0(GetDefaultDB, std::string());
|
||||
#endif
|
||||
};
|
||||
} // namespace
|
||||
|
||||
const std::string testSuite = "query_trigger";
|
||||
@@ -966,12 +978,12 @@ TYPED_TEST(TriggerStoreTest, Restore) {
|
||||
trigger_name_before, trigger_statement,
|
||||
std::map<std::string, memgraph::storage::PropertyValue>{{"parameter", memgraph::storage::PropertyValue{1}}},
|
||||
event_type, memgraph::query::TriggerPhase::BEFORE_COMMIT, &this->ast_cache, &*this->dba,
|
||||
memgraph::query::InterpreterConfig::Query{}, std::nullopt, &this->auth_checker);
|
||||
memgraph::query::InterpreterConfig::Query{}, this->auth_checker.GenQueryUser(std::nullopt, std::nullopt));
|
||||
store->AddTrigger(
|
||||
trigger_name_after, trigger_statement,
|
||||
std::map<std::string, memgraph::storage::PropertyValue>{{"parameter", memgraph::storage::PropertyValue{"value"}}},
|
||||
event_type, memgraph::query::TriggerPhase::AFTER_COMMIT, &this->ast_cache, &*this->dba,
|
||||
memgraph::query::InterpreterConfig::Query{}, {owner}, &this->auth_checker);
|
||||
memgraph::query::InterpreterConfig::Query{}, this->auth_checker.GenQueryUser(owner, std::nullopt));
|
||||
|
||||
const auto check_triggers = [&] {
|
||||
ASSERT_EQ(store->GetTriggerInfo().size(), 2);
|
||||
@@ -981,9 +993,9 @@ TYPED_TEST(TriggerStoreTest, Restore) {
|
||||
ASSERT_EQ(trigger.OriginalStatement(), trigger_statement);
|
||||
ASSERT_EQ(trigger.EventType(), event_type);
|
||||
if (owner != nullptr) {
|
||||
ASSERT_EQ(*trigger.Owner(), *owner);
|
||||
ASSERT_EQ(trigger.Owner()->username(), *owner);
|
||||
} else {
|
||||
ASSERT_FALSE(trigger.Owner().has_value());
|
||||
ASSERT_FALSE(trigger.Owner()->username());
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1022,32 +1034,38 @@ TYPED_TEST(TriggerStoreTest, AddTrigger) {
|
||||
// Invalid query in statements
|
||||
ASSERT_THROW(store.AddTrigger("trigger", "RETUR 1", {}, memgraph::query::TriggerEventType::VERTEX_CREATE,
|
||||
memgraph::query::TriggerPhase::BEFORE_COMMIT, &this->ast_cache, &*this->dba,
|
||||
memgraph::query::InterpreterConfig::Query{}, std::nullopt, &this->auth_checker),
|
||||
memgraph::query::InterpreterConfig::Query{},
|
||||
this->auth_checker.GenQueryUser(std::nullopt, std::nullopt)),
|
||||
memgraph::utils::BasicException);
|
||||
ASSERT_THROW(store.AddTrigger("trigger", "RETURN createdEdges", {}, memgraph::query::TriggerEventType::VERTEX_CREATE,
|
||||
memgraph::query::TriggerPhase::BEFORE_COMMIT, &this->ast_cache, &*this->dba,
|
||||
memgraph::query::InterpreterConfig::Query{}, std::nullopt, &this->auth_checker),
|
||||
memgraph::query::InterpreterConfig::Query{},
|
||||
this->auth_checker.GenQueryUser(std::nullopt, std::nullopt)),
|
||||
memgraph::utils::BasicException);
|
||||
|
||||
ASSERT_THROW(store.AddTrigger("trigger", "RETURN $parameter", {}, memgraph::query::TriggerEventType::VERTEX_CREATE,
|
||||
memgraph::query::TriggerPhase::BEFORE_COMMIT, &this->ast_cache, &*this->dba,
|
||||
memgraph::query::InterpreterConfig::Query{}, std::nullopt, &this->auth_checker),
|
||||
memgraph::query::InterpreterConfig::Query{},
|
||||
this->auth_checker.GenQueryUser(std::nullopt, std::nullopt)),
|
||||
memgraph::utils::BasicException);
|
||||
|
||||
ASSERT_NO_THROW(store.AddTrigger(
|
||||
"trigger", "RETURN $parameter",
|
||||
std::map<std::string, memgraph::storage::PropertyValue>{{"parameter", memgraph::storage::PropertyValue{1}}},
|
||||
memgraph::query::TriggerEventType::VERTEX_CREATE, memgraph::query::TriggerPhase::BEFORE_COMMIT, &this->ast_cache,
|
||||
&*this->dba, memgraph::query::InterpreterConfig::Query{}, std::nullopt, &this->auth_checker));
|
||||
&*this->dba, memgraph::query::InterpreterConfig::Query{},
|
||||
this->auth_checker.GenQueryUser(std::nullopt, std::nullopt)));
|
||||
|
||||
// Inserting with the same name
|
||||
ASSERT_THROW(store.AddTrigger("trigger", "RETURN 1", {}, memgraph::query::TriggerEventType::VERTEX_CREATE,
|
||||
memgraph::query::TriggerPhase::BEFORE_COMMIT, &this->ast_cache, &*this->dba,
|
||||
memgraph::query::InterpreterConfig::Query{}, std::nullopt, &this->auth_checker),
|
||||
memgraph::query::InterpreterConfig::Query{},
|
||||
this->auth_checker.GenQueryUser(std::nullopt, std::nullopt)),
|
||||
memgraph::utils::BasicException);
|
||||
ASSERT_THROW(store.AddTrigger("trigger", "RETURN 1", {}, memgraph::query::TriggerEventType::VERTEX_CREATE,
|
||||
memgraph::query::TriggerPhase::AFTER_COMMIT, &this->ast_cache, &*this->dba,
|
||||
memgraph::query::InterpreterConfig::Query{}, std::nullopt, &this->auth_checker),
|
||||
memgraph::query::InterpreterConfig::Query{},
|
||||
this->auth_checker.GenQueryUser(std::nullopt, std::nullopt)),
|
||||
memgraph::utils::BasicException);
|
||||
|
||||
ASSERT_EQ(store.GetTriggerInfo().size(), 1);
|
||||
@@ -1063,7 +1081,8 @@ TYPED_TEST(TriggerStoreTest, DropTrigger) {
|
||||
const auto *trigger_name = "trigger";
|
||||
store.AddTrigger(trigger_name, "RETURN 1", {}, memgraph::query::TriggerEventType::VERTEX_CREATE,
|
||||
memgraph::query::TriggerPhase::BEFORE_COMMIT, &this->ast_cache, &*this->dba,
|
||||
memgraph::query::InterpreterConfig::Query{}, std::nullopt, &this->auth_checker);
|
||||
memgraph::query::InterpreterConfig::Query{},
|
||||
this->auth_checker.GenQueryUser(std::nullopt, std::nullopt));
|
||||
|
||||
ASSERT_THROW(store.DropTrigger("Unknown"), memgraph::utils::BasicException);
|
||||
ASSERT_NO_THROW(store.DropTrigger(trigger_name));
|
||||
@@ -1076,7 +1095,8 @@ TYPED_TEST(TriggerStoreTest, TriggerInfo) {
|
||||
std::vector<memgraph::query::TriggerStore::TriggerInfo> expected_info;
|
||||
store.AddTrigger("trigger", "RETURN 1", {}, memgraph::query::TriggerEventType::VERTEX_CREATE,
|
||||
memgraph::query::TriggerPhase::BEFORE_COMMIT, &this->ast_cache, &*this->dba,
|
||||
memgraph::query::InterpreterConfig::Query{}, std::nullopt, &this->auth_checker);
|
||||
memgraph::query::InterpreterConfig::Query{},
|
||||
this->auth_checker.GenQueryUser(std::nullopt, std::nullopt));
|
||||
expected_info.push_back({"trigger",
|
||||
"RETURN 1",
|
||||
memgraph::query::TriggerEventType::VERTEX_CREATE,
|
||||
@@ -1099,7 +1119,8 @@ TYPED_TEST(TriggerStoreTest, TriggerInfo) {
|
||||
|
||||
store.AddTrigger("edge_update_trigger", "RETURN 1", {}, memgraph::query::TriggerEventType::EDGE_UPDATE,
|
||||
memgraph::query::TriggerPhase::AFTER_COMMIT, &this->ast_cache, &*this->dba,
|
||||
memgraph::query::InterpreterConfig::Query{}, std::nullopt, &this->auth_checker);
|
||||
memgraph::query::InterpreterConfig::Query{},
|
||||
this->auth_checker.GenQueryUser(std::nullopt, std::nullopt));
|
||||
expected_info.push_back({"edge_update_trigger",
|
||||
"RETURN 1",
|
||||
memgraph::query::TriggerEventType::EDGE_UPDATE,
|
||||
@@ -1216,7 +1237,8 @@ TYPED_TEST(TriggerStoreTest, AnyTriggerAllKeywords) {
|
||||
SCOPED_TRACE(keyword);
|
||||
EXPECT_NO_THROW(store.AddTrigger(trigger_name, fmt::format("RETURN {}", keyword), {}, event_type,
|
||||
memgraph::query::TriggerPhase::BEFORE_COMMIT, &this->ast_cache, &*this->dba,
|
||||
memgraph::query::InterpreterConfig::Query{}, std::nullopt, &this->auth_checker));
|
||||
memgraph::query::InterpreterConfig::Query{},
|
||||
this->auth_checker.GenQueryUser(std::nullopt, std::nullopt)));
|
||||
store.DropTrigger(trigger_name);
|
||||
}
|
||||
}
|
||||
@@ -1228,45 +1250,50 @@ TYPED_TEST(TriggerStoreTest, AuthCheckerUsage) {
|
||||
using ::testing::ElementsAre;
|
||||
using ::testing::Return;
|
||||
std::optional<memgraph::query::TriggerStore> store{this->testing_directory};
|
||||
const std::optional<std::string> owner{"testing_owner"};
|
||||
MockAuthChecker mock_checker;
|
||||
const std::optional<std::string> owner{"mock_user"};
|
||||
MockQueryUser mock_user(owner);
|
||||
std::shared_ptr<memgraph::query::QueryUserOrRole> mock_user_ptr(
|
||||
&mock_user, [](memgraph::query::QueryUserOrRole *) { /* do nothing */ });
|
||||
MockQueryUser mock_userless(std::nullopt);
|
||||
std::shared_ptr<memgraph::query::QueryUserOrRole> mock_userless_ptr(
|
||||
&mock_userless, [](memgraph::query::QueryUserOrRole *) { /* do nothing */ });
|
||||
|
||||
::testing::InSequence s;
|
||||
|
||||
EXPECT_CALL(mock_checker, IsUserAuthorized(std::optional<std::string>{}, ElementsAre(Privilege::CREATE), ""))
|
||||
.Times(1)
|
||||
// TODO Userless
|
||||
EXPECT_CALL(mock_user, IsAuthorized(ElementsAre(Privilege::CREATE), "", &memgraph::query::up_to_date_policy))
|
||||
.WillOnce(Return(true));
|
||||
EXPECT_CALL(mock_checker, IsUserAuthorized(owner, ElementsAre(Privilege::CREATE), ""))
|
||||
.Times(1)
|
||||
.WillOnce(Return(true));
|
||||
|
||||
ASSERT_NO_THROW(store->AddTrigger("successfull_trigger_1", "CREATE (n:VERTEX) RETURN n", {},
|
||||
memgraph::query::TriggerEventType::EDGE_UPDATE,
|
||||
memgraph::query::TriggerPhase::AFTER_COMMIT, &this->ast_cache, &*this->dba,
|
||||
memgraph::query::InterpreterConfig::Query{}, std::nullopt, &mock_checker));
|
||||
memgraph::query::InterpreterConfig::Query{}, mock_user_ptr));
|
||||
|
||||
EXPECT_CALL(mock_userless, IsAuthorized(ElementsAre(Privilege::CREATE), "", &memgraph::query::up_to_date_policy))
|
||||
.WillOnce(Return(true));
|
||||
ASSERT_NO_THROW(store->AddTrigger("successfull_trigger_2", "CREATE (n:VERTEX) RETURN n", {},
|
||||
memgraph::query::TriggerEventType::EDGE_UPDATE,
|
||||
memgraph::query::TriggerPhase::AFTER_COMMIT, &this->ast_cache, &*this->dba,
|
||||
memgraph::query::InterpreterConfig::Query{}, owner, &mock_checker));
|
||||
memgraph::query::InterpreterConfig::Query{}, mock_userless_ptr));
|
||||
|
||||
EXPECT_CALL(mock_checker, IsUserAuthorized(std::optional<std::string>{}, ElementsAre(Privilege::MATCH), ""))
|
||||
.Times(1)
|
||||
EXPECT_CALL(mock_user, IsAuthorized(ElementsAre(Privilege::MATCH), "", &memgraph::query::up_to_date_policy))
|
||||
.WillOnce(Return(false));
|
||||
ASSERT_THROW(
|
||||
store->AddTrigger("unprivileged_trigger", "MATCH (n:VERTEX) RETURN n", {},
|
||||
memgraph::query::TriggerEventType::EDGE_UPDATE, memgraph::query::TriggerPhase::AFTER_COMMIT,
|
||||
&this->ast_cache, &*this->dba, memgraph::query::InterpreterConfig::Query{}, mock_user_ptr);
|
||||
, memgraph::utils::BasicException);
|
||||
|
||||
ASSERT_THROW(store->AddTrigger("unprivileged_trigger", "MATCH (n:VERTEX) RETURN n", {},
|
||||
memgraph::query::TriggerEventType::EDGE_UPDATE,
|
||||
memgraph::query::TriggerPhase::AFTER_COMMIT, &this->ast_cache, &*this->dba,
|
||||
memgraph::query::InterpreterConfig::Query{}, std::nullopt, &mock_checker);
|
||||
, memgraph::utils::BasicException);
|
||||
|
||||
// Restore
|
||||
store.emplace(this->testing_directory);
|
||||
EXPECT_CALL(mock_checker, IsUserAuthorized(std::optional<std::string>{}, ElementsAre(Privilege::CREATE), ""))
|
||||
.Times(1)
|
||||
.WillOnce(Return(false));
|
||||
EXPECT_CALL(mock_checker, IsUserAuthorized(owner, ElementsAre(Privilege::CREATE), ""))
|
||||
.Times(1)
|
||||
|
||||
std::optional<std::string> nopt{};
|
||||
EXPECT_CALL(mock_checker, GenQueryUser(owner, nopt)).WillOnce(Return(mock_user_ptr));
|
||||
EXPECT_CALL(mock_user, IsAuthorized(ElementsAre(Privilege::CREATE), "", &memgraph::query::up_to_date_policy))
|
||||
.WillOnce(Return(true));
|
||||
EXPECT_CALL(mock_checker, GenQueryUser(nopt, nopt)).WillOnce(Return(mock_userless_ptr));
|
||||
EXPECT_CALL(mock_userless, IsAuthorized(ElementsAre(Privilege::CREATE), "", &memgraph::query::up_to_date_policy))
|
||||
.WillOnce(Return(false));
|
||||
|
||||
ASSERT_NO_THROW(store->RestoreTriggers(&this->ast_cache, &*this->dba, memgraph::query::InterpreterConfig::Query{},
|
||||
&mock_checker));
|
||||
|
||||
Reference in New Issue
Block a user