Compare commits
1 Commits
master
...
release/0.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8ad84e8629 |
@@ -1,9 +1,7 @@
|
||||
- name: Binaries
|
||||
archive:
|
||||
- build_debug/memgraph
|
||||
- build_debug/memgraph_ha
|
||||
- build_release/memgraph
|
||||
- build_release/memgraph_ha
|
||||
- build_release/tools/src/mg_client
|
||||
- build_release/tools/src/mg_import_csv
|
||||
- config
|
||||
|
||||
@@ -204,21 +204,3 @@ import_external_library(rocksdb STATIC
|
||||
-DCMAKE_INSTALL_LIBDIR=lib
|
||||
-DCMAKE_SKIP_INSTALL_ALL_DEPENDENCY=true
|
||||
BUILD_COMMAND $(MAKE) rocksdb)
|
||||
|
||||
# Setup libbcrypt
|
||||
import_external_library(libbcrypt STATIC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/libbcrypt/bcrypt.a
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/libbcrypt
|
||||
CONFIGURE_COMMAND sed s/-Wcast-align// -i ${CMAKE_CURRENT_SOURCE_DIR}/libbcrypt/crypt_blowfish/Makefile
|
||||
BUILD_COMMAND make -C ${CMAKE_CURRENT_SOURCE_DIR}/libbcrypt
|
||||
CC=${CMAKE_C_COMPILER}
|
||||
CXX=${CMAKE_CXX_COMPILER}
|
||||
INSTALL_COMMAND true)
|
||||
|
||||
# Setup mgclient
|
||||
import_external_library(mgclient STATIC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/mgclient/lib/libmgclient.a
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/mgclient/include
|
||||
CMAKE_ARGS -DBUILD_TESTING=OFF)
|
||||
find_package(OpenSSL REQUIRED)
|
||||
target_link_libraries(mgclient INTERFACE ${OPENSSL_LIBRARIES})
|
||||
|
||||
@@ -135,8 +135,3 @@ clone git://deps.memgraph.io/rocksdb.git rocksdb $rocksdb_tag
|
||||
sed -i 's/-Wshadow/-Wno-defaulted-function-deleted/' rocksdb/CMakeLists.txt
|
||||
# remove shared library from install dependencies
|
||||
sed -i 's/TARGETS ${ROCKSDB_SHARED_LIB}/TARGETS ${ROCKSDB_SHARED_LIB} OPTIONAL/' rocksdb/CMakeLists.txt
|
||||
|
||||
# mgclient
|
||||
mgclient_tag="fe94b3631385ef5dbe40a3d8458860dbcc33e6ea" # May 27, 2019
|
||||
# git clone https://github.com/memgraph/mgclient.git
|
||||
clone git://deps.memgraph.io/mgclient.git mgclient $mgclient_tag
|
||||
|
||||
@@ -26,6 +26,3 @@ install(PROGRAMS $<TARGET_FILE:example>
|
||||
RENAME example.so)
|
||||
# Also install the source of the example, so user can read it.
|
||||
install(FILES example.c DESTINATION lib/memgraph/query_modules)
|
||||
|
||||
add_subdirectory(louvain)
|
||||
add_subdirectory(connectivity)
|
||||
|
||||
@@ -1,3 +1,2 @@
|
||||
/etc/memgraph/memgraph.conf
|
||||
/etc/logrotate.d/memgraph
|
||||
/etc/logrotate.d/memgraph_audit
|
||||
|
||||
@@ -7,8 +7,6 @@ add_subdirectory(requests)
|
||||
add_subdirectory(io)
|
||||
add_subdirectory(telemetry)
|
||||
add_subdirectory(communication)
|
||||
add_subdirectory(auth)
|
||||
add_subdirectory(slk)
|
||||
add_subdirectory(storage/v2)
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
@@ -32,7 +30,6 @@ add_custom_target(generate_lcp_common DEPENDS ${generated_lcp_common_files})
|
||||
# ----------------------------------------------------------------------------
|
||||
set(mg_single_node_sources
|
||||
${lcp_common_cpp_files}
|
||||
audit/log.cpp
|
||||
data_structures/concurrent/skiplist_gc.cpp
|
||||
database/single_node/config.cpp
|
||||
database/single_node/graph_db.cpp
|
||||
@@ -42,14 +39,12 @@ set(mg_single_node_sources
|
||||
durability/single_node/recovery.cpp
|
||||
durability/single_node/snapshooter.cpp
|
||||
durability/single_node/wal.cpp
|
||||
glue/auth.cpp
|
||||
glue/communication.cpp
|
||||
query/common.cpp
|
||||
query/dump.cpp
|
||||
query/frontend/ast/cypher_main_visitor.cpp
|
||||
query/frontend/ast/pretty_print.cpp
|
||||
query/frontend/parsing.cpp
|
||||
query/frontend/semantic/required_privileges.cpp
|
||||
query/frontend/semantic/symbol_generator.cpp
|
||||
query/frontend/stripped.cpp
|
||||
query/interpret/awesome_memgraph_functions.cpp
|
||||
@@ -84,8 +79,6 @@ add_custom_target(generate_lcp_single_node DEPENDS generate_lcp_common ${generat
|
||||
set(MG_SINGLE_NODE_LIBS stdc++fs Threads::Threads fmt cppitertools
|
||||
antlr_opencypher_parser_lib dl glog gflags
|
||||
mg-utils mg-io mg-requests mg-communication)
|
||||
# These are enterprise subsystems
|
||||
set(MG_SINGLE_NODE_LIBS ${MG_SINGLE_NODE_LIBS} mg-auth)
|
||||
|
||||
if (USE_LTALLOC)
|
||||
list(APPEND MG_SINGLE_NODE_LIBS ltalloc)
|
||||
@@ -113,15 +106,12 @@ target_link_libraries(mg-single-node "-Wl,--dynamic-list=${CMAKE_SOURCE_DIR}/inc
|
||||
# ----------------------------------------------------------------------------
|
||||
set(mg_single_node_v2_sources
|
||||
${lcp_common_cpp_files}
|
||||
audit/log.cpp
|
||||
glue/auth.cpp
|
||||
glue/communication.cpp
|
||||
query/common.cpp
|
||||
query/dump.cpp
|
||||
query/frontend/ast/cypher_main_visitor.cpp
|
||||
query/frontend/ast/pretty_print.cpp
|
||||
query/frontend/parsing.cpp
|
||||
query/frontend/semantic/required_privileges.cpp
|
||||
query/frontend/semantic/symbol_generator.cpp
|
||||
query/frontend/stripped.cpp
|
||||
query/interpret/awesome_memgraph_functions.cpp
|
||||
@@ -142,8 +132,6 @@ set(mg_single_node_v2_sources
|
||||
set(MG_SINGLE_NODE_V2_LIBS stdc++fs Threads::Threads fmt cppitertools
|
||||
antlr_opencypher_parser_lib dl glog gflags mg-storage-v2
|
||||
mg-utils mg-io mg-requests mg-communication)
|
||||
# These are enterprise subsystems
|
||||
set(MG_SINGLE_NODE_V2_LIBS ${MG_SINGLE_NODE_V2_LIBS} mg-auth)
|
||||
|
||||
if (USE_LTALLOC)
|
||||
list(APPEND MG_SINGLE_NODE_V2_LIBS ltalloc)
|
||||
@@ -166,98 +154,8 @@ target_link_libraries(mg-single-node-v2 "-Wl,--dynamic-list=${CMAKE_SOURCE_DIR}/
|
||||
# END Memgraph Single Node v2
|
||||
# ----------------------------------------------------------------------------
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
# Memgraph Single Node High Availability
|
||||
# ----------------------------------------------------------------------------
|
||||
set(mg_single_node_ha_sources
|
||||
${lcp_common_cpp_files}
|
||||
audit/log.cpp
|
||||
data_structures/concurrent/skiplist_gc.cpp
|
||||
database/single_node_ha/config.cpp
|
||||
database/single_node_ha/graph_db.cpp
|
||||
database/single_node_ha/graph_db_accessor.cpp
|
||||
durability/single_node_ha/state_delta.cpp
|
||||
durability/single_node_ha/paths.cpp
|
||||
durability/single_node_ha/snapshooter.cpp
|
||||
durability/single_node_ha/recovery.cpp
|
||||
glue/auth.cpp
|
||||
glue/communication.cpp
|
||||
raft/coordination.cpp
|
||||
raft/raft_server.cpp
|
||||
raft/storage_info.cpp
|
||||
query/common.cpp
|
||||
query/frontend/ast/cypher_main_visitor.cpp
|
||||
query/frontend/ast/pretty_print.cpp
|
||||
query/frontend/parsing.cpp
|
||||
query/frontend/semantic/required_privileges.cpp
|
||||
query/frontend/semantic/symbol_generator.cpp
|
||||
query/frontend/stripped.cpp
|
||||
query/interpret/awesome_memgraph_functions.cpp
|
||||
query/interpreter.cpp
|
||||
query/plan/operator.cpp
|
||||
query/plan/preprocess.cpp
|
||||
query/plan/pretty_print.cpp
|
||||
query/plan/profile.cpp
|
||||
query/plan/rewrite/index_lookup.cpp
|
||||
query/plan/rule_based_planner.cpp
|
||||
query/plan/variable_start_planner.cpp
|
||||
query/procedure/mg_procedure_impl.cpp
|
||||
query/procedure/module.cpp
|
||||
query/typed_value.cpp
|
||||
storage/common/constraints/record.cpp
|
||||
storage/common/constraints/unique_constraints.cpp
|
||||
storage/common/types/slk.cpp
|
||||
storage/common/types/property_value_store.cpp
|
||||
storage/common/locking/record_lock.cpp
|
||||
storage/single_node_ha/edge_accessor.cpp
|
||||
storage/single_node_ha/record_accessor.cpp
|
||||
storage/single_node_ha/vertex_accessor.cpp
|
||||
transactions/single_node_ha/engine.cpp
|
||||
memgraph_init.cpp
|
||||
)
|
||||
|
||||
define_add_lcp(add_lcp_single_node_ha mg_single_node_ha_sources generated_lcp_single_node_ha_files)
|
||||
|
||||
add_lcp_single_node_ha(durability/single_node_ha/state_delta.lcp)
|
||||
add_lcp_single_node_ha(database/single_node_ha/serialization.lcp SLK_SERIALIZE
|
||||
DEPENDS durability/single_node_ha/state_delta.lcp)
|
||||
add_lcp_single_node_ha(raft/raft_rpc_messages.lcp SLK_SERIALIZE)
|
||||
add_lcp_single_node_ha(raft/log_entry.lcp SLK_SERIALIZE)
|
||||
add_lcp_single_node_ha(raft/snapshot_metadata.lcp SLK_SERIALIZE)
|
||||
add_lcp_single_node_ha(raft/storage_info_rpc_messages.lcp SLK_SERIALIZE)
|
||||
|
||||
add_custom_target(generate_lcp_single_node_ha DEPENDS generate_lcp_common ${generated_lcp_single_node_ha_files})
|
||||
|
||||
set(MG_SINGLE_NODE_HA_LIBS stdc++fs Threads::Threads fmt cppitertools
|
||||
antlr_opencypher_parser_lib dl glog gflags
|
||||
mg-utils mg-io mg-requests mg-communication mg-comm-rpc
|
||||
mg-auth)
|
||||
|
||||
if (USE_LTALLOC)
|
||||
list(APPEND MG_SINGLE_NODE_HA_LIBS ltalloc)
|
||||
# TODO(mferencevic): Enable this when clang is updated on apollo.
|
||||
# set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -flto")
|
||||
endif()
|
||||
|
||||
add_library(mg-single-node-ha STATIC ${mg_single_node_ha_sources})
|
||||
target_include_directories(mg-single-node-ha PUBLIC ${CMAKE_SOURCE_DIR}/include)
|
||||
target_link_libraries(mg-single-node-ha ${MG_SINGLE_NODE_HA_LIBS})
|
||||
add_dependencies(mg-single-node-ha generate_opencypher_parser)
|
||||
add_dependencies(mg-single-node-ha generate_lcp_single_node_ha)
|
||||
target_compile_definitions(mg-single-node-ha PUBLIC MG_SINGLE_NODE_HA)
|
||||
# TODO: Make these symbols visible once we add support for custom procedure
|
||||
# modules in HA.
|
||||
# NOTE: `include/mg_procedure.syms` describes a pattern match for symbols which
|
||||
# should be dynamically exported, so that `dlopen` can correctly link the
|
||||
# symbols in custom procedure module libraries.
|
||||
# target_link_libraries(mg-single-node-ha "-Wl,--dynamic-list=${CMAKE_SOURCE_DIR}/include/mg_procedure.syms")
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
# END Memgraph Single Node High Availability
|
||||
# ----------------------------------------------------------------------------
|
||||
|
||||
add_custom_target(generate_lcp)
|
||||
add_dependencies(generate_lcp generate_lcp_single_node generate_lcp_single_node_ha)
|
||||
add_dependencies(generate_lcp generate_lcp_single_node)
|
||||
|
||||
string(TOLOWER ${CMAKE_BUILD_TYPE} lower_build_type)
|
||||
|
||||
@@ -330,8 +228,6 @@ install(FILES ${CMAKE_BINARY_DIR}/config/memgraph.conf
|
||||
# Install logrotate configuration (must use absolute path).
|
||||
install(FILES ${CMAKE_SOURCE_DIR}/release/logrotate.conf
|
||||
DESTINATION /etc/logrotate.d RENAME memgraph)
|
||||
install(FILES ${CMAKE_SOURCE_DIR}/release/logrotate_audit.conf
|
||||
DESTINATION /etc/logrotate.d RENAME memgraph_audit)
|
||||
# Create empty directories for default location of lib and log.
|
||||
install(CODE "file(MAKE_DIRECTORY \$ENV{DESTDIR}/var/log/memgraph
|
||||
\$ENV{DESTDIR}/var/lib/memgraph)")
|
||||
@@ -351,18 +247,3 @@ install(
|
||||
${CMAKE_BINARY_DIR}/tools/src/mg_client
|
||||
WORKING_DIRECTORY ${examples})")
|
||||
install(DIRECTORY ${examples}/build/ DESTINATION share/memgraph/examples)
|
||||
|
||||
|
||||
# memgraph single node high availability executable
|
||||
add_executable(memgraph_ha memgraph_ha.cpp)
|
||||
target_link_libraries(memgraph_ha mg-single-node-ha kvstore_lib telemetry_lib)
|
||||
set_target_properties(memgraph_ha PROPERTIES
|
||||
# Set the executable output name to include version information.
|
||||
OUTPUT_NAME "memgraph_ha-${memgraph_VERSION}-${COMMIT_HASH}_${CMAKE_BUILD_TYPE}"
|
||||
# Output the executable in main binary dir.
|
||||
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
|
||||
# Create symlink to the built executable.
|
||||
add_custom_command(TARGET memgraph_ha POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E create_symlink $<TARGET_FILE:memgraph_ha> ${CMAKE_BINARY_DIR}/memgraph_ha
|
||||
BYPRODUCTS ${CMAKE_BINARY_DIR}/memgraph_ha
|
||||
COMMENT "Creating symlink to memgraph single node high availability executable")
|
||||
|
||||
@@ -10,12 +10,3 @@ add_library(mg-communication STATIC ${communication_src_files})
|
||||
target_link_libraries(mg-communication Threads::Threads mg-utils mg-io fmt glog gflags)
|
||||
target_link_libraries(mg-communication ${OPENSSL_LIBRARIES})
|
||||
target_include_directories(mg-communication SYSTEM PUBLIC ${OPENSSL_INCLUDE_DIR})
|
||||
|
||||
set(communication_rpc_src_files
|
||||
rpc/client.cpp
|
||||
rpc/protocol.cpp
|
||||
rpc/server.cpp)
|
||||
|
||||
add_library(mg-comm-rpc STATIC ${communication_rpc_src_files})
|
||||
target_link_libraries(mg-comm-rpc Threads::Threads mg-communication mg-utils mg-io fmt glog gflags)
|
||||
target_link_libraries(mg-comm-rpc mg-slk)
|
||||
|
||||
@@ -60,10 +60,6 @@ class Session {
|
||||
/** Aborts currently running query. */
|
||||
virtual void Abort() = 0;
|
||||
|
||||
/** Return `true` if the user was successfully authenticated. */
|
||||
virtual bool Authenticate(const std::string &username,
|
||||
const std::string &password) = 0;
|
||||
|
||||
/**
|
||||
* Executes the session after data has been read into the buffer.
|
||||
* Goes through the bolt states in order to execute commands from the client.
|
||||
|
||||
@@ -60,38 +60,6 @@ State StateInitRun(Session &session) {
|
||||
LOG(INFO) << fmt::format("Client connected '{}'", client_name.ValueString())
|
||||
<< std::endl;
|
||||
|
||||
// Get authentication data.
|
||||
std::string username, password;
|
||||
auto &data = metadata.ValueMap();
|
||||
if (!data.count("scheme")) {
|
||||
LOG(WARNING) << "The client didn't supply authentication information!";
|
||||
return State::Close;
|
||||
}
|
||||
if (data["scheme"].ValueString() == "basic") {
|
||||
if (!data.count("principal") || !data.count("credentials")) {
|
||||
LOG(WARNING) << "The client didn't supply authentication information!";
|
||||
return State::Close;
|
||||
}
|
||||
username = data["principal"].ValueString();
|
||||
password = data["credentials"].ValueString();
|
||||
} else if (data["scheme"].ValueString() != "none") {
|
||||
LOG(WARNING) << "Unsupported authentication scheme: "
|
||||
<< data["scheme"].ValueString();
|
||||
return State::Close;
|
||||
}
|
||||
|
||||
// Authenticate the user.
|
||||
if (!session.Authenticate(username, password)) {
|
||||
if (!session.encoder_.MessageFailure(
|
||||
{{"code", "Memgraph.ClientError.Security.Unauthenticated"},
|
||||
{"message", "Authentication failure"}})) {
|
||||
DLOG(WARNING) << "Couldn't send failure message to the client!";
|
||||
}
|
||||
// Throw an exception to indicate to the network stack that the session
|
||||
// should be closed and cleaned up.
|
||||
throw SessionClosedException("The client is not authenticated!");
|
||||
}
|
||||
|
||||
// Return success.
|
||||
if (!session.encoder_.MessageSuccess()) {
|
||||
DLOG(WARNING) << "Couldn't send success message to the client!";
|
||||
|
||||
@@ -87,16 +87,6 @@ DEFINE_bool(telemetry_enabled, false,
|
||||
"the database runtime (vertex and edge counts and resource usage) "
|
||||
"to allow for easier improvement of the product.");
|
||||
|
||||
// Audit logging flags.
|
||||
DEFINE_bool(audit_enabled, false, "Set to true to enable audit logging.");
|
||||
DEFINE_VALIDATED_int32(audit_buffer_size, audit::kBufferSizeDefault,
|
||||
"Maximum number of items in the audit log buffer.",
|
||||
FLAG_IN_RANGE(1, INT32_MAX));
|
||||
DEFINE_VALIDATED_int32(
|
||||
audit_buffer_flush_interval_ms, audit::kBufferFlushIntervalMillisDefault,
|
||||
"Interval (in milliseconds) used for flushing the audit log buffer.",
|
||||
FLAG_IN_RANGE(10, INT32_MAX));
|
||||
|
||||
// Query flags.
|
||||
DEFINE_uint64(query_execution_timeout_sec, 180,
|
||||
"Maximum allowed query execution time. Queries exceeding this "
|
||||
@@ -116,41 +106,12 @@ using ServerT = communication::Server<BoltSession, SessionData>;
|
||||
using communication::ServerContext;
|
||||
|
||||
void SingleNodeMain() {
|
||||
// All enterprise features should be constructed before the main database
|
||||
// storage. This will cause them to be destructed *after* the main database
|
||||
// storage. That way any errors that happen during enterprise features
|
||||
// destruction won't have an impact on the storage engine.
|
||||
// Example: When the main storage is destructed it makes a snapshot. When
|
||||
// audit logging is destructed it syncs all pending data to disk and that can
|
||||
// fail. That is why it must be destructed *after* the main database storage
|
||||
// to minimise the impact of their failure on the main storage.
|
||||
|
||||
// Begin enterprise features initialization
|
||||
|
||||
#ifdef MG_SINGLE_NODE_V2
|
||||
auto data_directory = std::filesystem::path(FLAGS_data_directory);
|
||||
#else
|
||||
auto data_directory = std::filesystem::path(FLAGS_durability_directory);
|
||||
#endif
|
||||
|
||||
// Auth
|
||||
auth::Auth auth{data_directory / "auth"};
|
||||
|
||||
// Audit log
|
||||
audit::Log audit_log{data_directory / "audit", FLAGS_audit_buffer_size,
|
||||
FLAGS_audit_buffer_flush_interval_ms};
|
||||
// Start the log if enabled.
|
||||
if (FLAGS_audit_enabled) {
|
||||
audit_log.Start();
|
||||
}
|
||||
// Setup SIGUSR2 to be used for reopening audit log files, when e.g. logrotate
|
||||
// rotates our audit logs.
|
||||
CHECK(utils::SignalHandler::RegisterHandler(
|
||||
utils::Signal::User2, [&audit_log]() { audit_log.ReopenLog(); }))
|
||||
<< "Unable to register SIGUSR2 handler!";
|
||||
|
||||
// End enterprise features initialization
|
||||
|
||||
// Main storage and execution engines initialization
|
||||
|
||||
#ifdef MG_SINGLE_NODE_V2
|
||||
@@ -190,7 +151,7 @@ void SingleNodeMain() {
|
||||
query::InterpreterContext interpreter_context{&db};
|
||||
query::SetExecutionTimeout(&interpreter_context,
|
||||
FLAGS_query_execution_timeout_sec);
|
||||
SessionData session_data{&db, &interpreter_context, &auth, &audit_log};
|
||||
SessionData session_data{&db, &interpreter_context};
|
||||
|
||||
// Register modules
|
||||
if (!FLAGS_query_modules_directory.empty()) {
|
||||
@@ -202,8 +163,6 @@ void SingleNodeMain() {
|
||||
}
|
||||
// Register modules END
|
||||
|
||||
interpreter_context.auth = &auth;
|
||||
|
||||
ServerContext context;
|
||||
std::string service_name = "Bolt";
|
||||
if (!FLAGS_bolt_key_file.empty() && !FLAGS_bolt_cert_file.empty()) {
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
#include <glog/logging.h>
|
||||
|
||||
#include "config.hpp"
|
||||
#include "glue/auth.hpp"
|
||||
#include "glue/communication.hpp"
|
||||
#include "query/exceptions.hpp"
|
||||
#include "requests/requests.hpp"
|
||||
@@ -33,10 +32,6 @@ BoltSession::BoltSession(SessionData *data,
|
||||
db_(data->db),
|
||||
#endif
|
||||
interpreter_(data->interpreter_context),
|
||||
#ifndef MG_SINGLE_NODE_HA
|
||||
auth_(data->auth),
|
||||
audit_log_(data->audit_log),
|
||||
#endif
|
||||
endpoint_(endpoint) {
|
||||
}
|
||||
|
||||
@@ -50,28 +45,8 @@ std::vector<std::string> BoltSession::Interpret(
|
||||
std::map<std::string, PropertyValue> params_pv;
|
||||
for (const auto &kv : params)
|
||||
params_pv.emplace(kv.first, glue::ToPropertyValue(kv.second));
|
||||
#ifndef MG_SINGLE_NODE_HA
|
||||
audit_log_->Record(endpoint_.address(), user_ ? user_->username() : "", query,
|
||||
PropertyValue(params_pv));
|
||||
#endif
|
||||
try {
|
||||
auto result = interpreter_.Prepare(query, params_pv);
|
||||
#ifndef MG_SINGLE_NODE_HA
|
||||
if (user_) {
|
||||
const auto &permissions = user_->GetPermissions();
|
||||
for (const auto &privilege : result.second) {
|
||||
if (permissions.Has(glue::PrivilegeToPermission(privilege)) !=
|
||||
auth::PermissionLevel::GRANT) {
|
||||
interpreter_.Abort();
|
||||
throw communication::bolt::ClientError(
|
||||
"You are not authorized to execute this query! Please contact "
|
||||
"your database administrator.");
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return result.first;
|
||||
|
||||
return interpreter_.Prepare(query, params_pv);
|
||||
} catch (const query::QueryException &e) {
|
||||
// Wrap QueryException into ClientError, because we want to allow the
|
||||
// client to fix their query.
|
||||
@@ -119,17 +94,6 @@ std::map<std::string, communication::bolt::Value> BoltSession::PullAll(
|
||||
|
||||
void BoltSession::Abort() { interpreter_.Abort(); }
|
||||
|
||||
bool BoltSession::Authenticate(const std::string &username,
|
||||
const std::string &password) {
|
||||
#ifdef MG_SINGLE_NODE_HA
|
||||
return true;
|
||||
#else
|
||||
if (!auth_->HasUsers()) return true;
|
||||
user_ = auth_->Authenticate(username, password);
|
||||
return !!user_;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef MG_SINGLE_NODE_V2
|
||||
BoltSession::TypedValueResultStream::TypedValueResultStream(
|
||||
TEncoder *encoder, const storage::Storage *db)
|
||||
|
||||
@@ -31,16 +31,11 @@ struct SessionData {
|
||||
// Explicit constructor here to ensure that pointers to all objects are
|
||||
// supplied.
|
||||
SessionData(database::GraphDb *_db,
|
||||
query::InterpreterContext *_interpreter_context,
|
||||
auth::Auth *_auth, audit::Log *_audit_log)
|
||||
query::InterpreterContext *_interpreter_context)
|
||||
: db(_db),
|
||||
interpreter_context(_interpreter_context),
|
||||
auth(_auth),
|
||||
audit_log(_audit_log) {}
|
||||
interpreter_context(_interpreter_context) {}
|
||||
database::GraphDb *db;
|
||||
query::InterpreterContext *interpreter_context;
|
||||
auth::Auth *auth;
|
||||
audit::Log *audit_log;
|
||||
};
|
||||
|
||||
class BoltSession final
|
||||
@@ -63,9 +58,6 @@ class BoltSession final
|
||||
|
||||
void Abort() override;
|
||||
|
||||
bool Authenticate(const std::string &username,
|
||||
const std::string &password) override;
|
||||
|
||||
private:
|
||||
/// Wrapper around TEncoder which converts TypedValue to Value
|
||||
/// before forwarding the calls to original TEncoder.
|
||||
@@ -92,11 +84,6 @@ class BoltSession final
|
||||
const storage::Storage *db_;
|
||||
#endif
|
||||
query::Interpreter interpreter_;
|
||||
#ifndef MG_SINGLE_NODE_HA
|
||||
auth::Auth *auth_;
|
||||
std::optional<auth::User> user_;
|
||||
audit::Log *audit_log_;
|
||||
#endif
|
||||
io::network::Endpoint endpoint_;
|
||||
};
|
||||
|
||||
|
||||
@@ -127,19 +127,4 @@ class RemoveAttachedVertexException : public QueryRuntimeException {
|
||||
"connections. Consider using DETACH DELETE.") {}
|
||||
};
|
||||
|
||||
class UserModificationInMulticommandTxException : public QueryException {
|
||||
public:
|
||||
UserModificationInMulticommandTxException()
|
||||
: QueryException(
|
||||
"Authentication clause not allowed in multicommand transactions.") {
|
||||
}
|
||||
};
|
||||
|
||||
class StreamClauseInMulticommandTxException : public QueryException {
|
||||
public:
|
||||
StreamClauseInMulticommandTxException()
|
||||
: QueryException(
|
||||
"Stream clause not allowed in multicommand transactions.") {}
|
||||
};
|
||||
|
||||
} // namespace query
|
||||
|
||||
@@ -2087,67 +2087,11 @@ cpp<#
|
||||
(:serialize (:slk))
|
||||
(:clone))
|
||||
|
||||
(lcp:define-class auth-query (query)
|
||||
((action "Action" :scope :public)
|
||||
(user "std::string" :scope :public)
|
||||
(role "std::string" :scope :public)
|
||||
(user-or-role "std::string" :scope :public)
|
||||
(password "Expression *" :initval "nullptr" :scope :public
|
||||
:slk-save #'slk-save-ast-pointer
|
||||
:slk-load (slk-load-ast-pointer "Expression"))
|
||||
(privileges "std::vector<Privilege>" :scope :public))
|
||||
(:public
|
||||
(lcp:define-enum action
|
||||
(create-role drop-role show-roles create-user set-password drop-user
|
||||
show-users set-role clear-role grant-privilege deny-privilege
|
||||
revoke-privilege show-privileges show-role-for-user
|
||||
show-users-for-role)
|
||||
(:serialize))
|
||||
(lcp:define-enum privilege
|
||||
(create delete match merge set remove index stats auth constraint
|
||||
dump)
|
||||
(:serialize))
|
||||
#>cpp
|
||||
AuthQuery() = default;
|
||||
|
||||
DEFVISITABLE(QueryVisitor<void>);
|
||||
cpp<#)
|
||||
(:protected
|
||||
#>cpp
|
||||
AuthQuery(Action action, std::string user, std::string role,
|
||||
std::string user_or_role, Expression *password,
|
||||
std::vector<Privilege> privileges)
|
||||
: action_(action),
|
||||
user_(user),
|
||||
role_(role),
|
||||
user_or_role_(user_or_role),
|
||||
password_(password),
|
||||
privileges_(privileges) {}
|
||||
cpp<#)
|
||||
(:private
|
||||
#>cpp
|
||||
friend class AstStorage;
|
||||
cpp<#)
|
||||
(:serialize (:slk))
|
||||
(:clone))
|
||||
|
||||
;; TODO: Generate this via LCP
|
||||
#>cpp
|
||||
/// Constant that holds all available privileges.
|
||||
const std::vector<AuthQuery::Privilege> kPrivilegesAll = {
|
||||
AuthQuery::Privilege::CREATE, AuthQuery::Privilege::DELETE,
|
||||
AuthQuery::Privilege::MATCH, AuthQuery::Privilege::MERGE,
|
||||
AuthQuery::Privilege::SET, AuthQuery::Privilege::REMOVE,
|
||||
AuthQuery::Privilege::INDEX, AuthQuery::Privilege::STATS,
|
||||
AuthQuery::Privilege::AUTH,
|
||||
AuthQuery::Privilege::CONSTRAINT, AuthQuery::Privilege::DUMP};
|
||||
cpp<#
|
||||
|
||||
(lcp:define-class info-query (query)
|
||||
((info-type "InfoType" :scope :public))
|
||||
(:public
|
||||
(lcp:define-enum info-type
|
||||
(storage index constraint raft)
|
||||
(storage index constraint)
|
||||
(:serialize))
|
||||
|
||||
#>cpp
|
||||
|
||||
@@ -62,7 +62,6 @@ class RemoveProperty;
|
||||
class RemoveLabels;
|
||||
class Merge;
|
||||
class Unwind;
|
||||
class AuthQuery;
|
||||
class ExplainQuery;
|
||||
class ProfileQuery;
|
||||
class IndexQuery;
|
||||
@@ -113,7 +112,7 @@ class ExpressionVisitor
|
||||
template <class TResult>
|
||||
class QueryVisitor
|
||||
: public ::utils::Visitor<TResult, CypherQuery, ExplainQuery, ProfileQuery,
|
||||
IndexQuery, AuthQuery, InfoQuery,
|
||||
IndexQuery, InfoQuery,
|
||||
ConstraintQuery, DumpQuery> {};
|
||||
|
||||
} // namespace query
|
||||
|
||||
@@ -62,9 +62,6 @@ antlrcpp::Any CypherMainVisitor::visitInfoQuery(
|
||||
} else if (ctx->constraintInfo()) {
|
||||
info_query->info_type_ = InfoQuery::InfoType::CONSTRAINT;
|
||||
return info_query;
|
||||
} else if (ctx->raftInfo()) {
|
||||
info_query->info_type_ = InfoQuery::InfoType::RAFT;
|
||||
return info_query;
|
||||
} else {
|
||||
throw utils::NotYetImplemented("Info query: '{}'", ctx->getText());
|
||||
}
|
||||
@@ -174,15 +171,6 @@ antlrcpp::Any CypherMainVisitor::visitDropIndex(
|
||||
return index_query;
|
||||
}
|
||||
|
||||
antlrcpp::Any CypherMainVisitor::visitAuthQuery(
|
||||
MemgraphCypher::AuthQueryContext *ctx) {
|
||||
CHECK(ctx->children.size() == 1)
|
||||
<< "AuthQuery should have exactly one child!";
|
||||
auto *auth_query = ctx->children[0]->accept(this).as<AuthQuery *>();
|
||||
query_ = auth_query;
|
||||
return auth_query;
|
||||
}
|
||||
|
||||
antlrcpp::Any CypherMainVisitor::visitDumpQuery(
|
||||
MemgraphCypher::DumpQueryContext *ctx) {
|
||||
auto *dump_query = storage_->Create<DumpQuery>();
|
||||
@@ -434,235 +422,6 @@ antlrcpp::Any CypherMainVisitor::visitCallProcedure(
|
||||
return call_proc;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return std::string
|
||||
*/
|
||||
antlrcpp::Any CypherMainVisitor::visitUserOrRoleName(
|
||||
MemgraphCypher::UserOrRoleNameContext *ctx) {
|
||||
std::string value = ctx->symbolicName()->accept(this).as<std::string>();
|
||||
const std::regex NAME_REGEX("[a-zA-Z0-9_.+-]+");
|
||||
if (!std::regex_match(value, NAME_REGEX)) {
|
||||
throw SyntaxException("Invalid user or role name.");
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return AuthQuery*
|
||||
*/
|
||||
antlrcpp::Any CypherMainVisitor::visitCreateRole(
|
||||
MemgraphCypher::CreateRoleContext *ctx) {
|
||||
AuthQuery *auth = storage_->Create<AuthQuery>();
|
||||
auth->action_ = AuthQuery::Action::CREATE_ROLE;
|
||||
auth->role_ = ctx->role->accept(this).as<std::string>();
|
||||
return auth;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return AuthQuery*
|
||||
*/
|
||||
antlrcpp::Any CypherMainVisitor::visitDropRole(
|
||||
MemgraphCypher::DropRoleContext *ctx) {
|
||||
AuthQuery *auth = storage_->Create<AuthQuery>();
|
||||
auth->action_ = AuthQuery::Action::DROP_ROLE;
|
||||
auth->role_ = ctx->role->accept(this).as<std::string>();
|
||||
return auth;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return AuthQuery*
|
||||
*/
|
||||
antlrcpp::Any CypherMainVisitor::visitShowRoles(
|
||||
MemgraphCypher::ShowRolesContext *ctx) {
|
||||
AuthQuery *auth = storage_->Create<AuthQuery>();
|
||||
auth->action_ = AuthQuery::Action::SHOW_ROLES;
|
||||
return auth;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return AuthQuery*
|
||||
*/
|
||||
antlrcpp::Any CypherMainVisitor::visitCreateUser(
|
||||
MemgraphCypher::CreateUserContext *ctx) {
|
||||
AuthQuery *auth = storage_->Create<AuthQuery>();
|
||||
auth->action_ = AuthQuery::Action::CREATE_USER;
|
||||
auth->user_ = ctx->user->accept(this).as<std::string>();
|
||||
if (ctx->password) {
|
||||
if (!ctx->password->StringLiteral() && !ctx->literal()->CYPHERNULL()) {
|
||||
throw SyntaxException("Password should be a string literal or null.");
|
||||
}
|
||||
auth->password_ = ctx->password->accept(this);
|
||||
}
|
||||
return auth;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return AuthQuery*
|
||||
*/
|
||||
antlrcpp::Any CypherMainVisitor::visitSetPassword(
|
||||
MemgraphCypher::SetPasswordContext *ctx) {
|
||||
AuthQuery *auth = storage_->Create<AuthQuery>();
|
||||
auth->action_ = AuthQuery::Action::SET_PASSWORD;
|
||||
auth->user_ = ctx->user->accept(this).as<std::string>();
|
||||
if (!ctx->password->StringLiteral() && !ctx->literal()->CYPHERNULL()) {
|
||||
throw SyntaxException("Password should be a string literal or null.");
|
||||
}
|
||||
auth->password_ = ctx->password->accept(this);
|
||||
return auth;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return AuthQuery*
|
||||
*/
|
||||
antlrcpp::Any CypherMainVisitor::visitDropUser(
|
||||
MemgraphCypher::DropUserContext *ctx) {
|
||||
AuthQuery *auth = storage_->Create<AuthQuery>();
|
||||
auth->action_ = AuthQuery::Action::DROP_USER;
|
||||
auth->user_ = ctx->user->accept(this).as<std::string>();
|
||||
return auth;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return AuthQuery*
|
||||
*/
|
||||
antlrcpp::Any CypherMainVisitor::visitShowUsers(
|
||||
MemgraphCypher::ShowUsersContext *ctx) {
|
||||
AuthQuery *auth = storage_->Create<AuthQuery>();
|
||||
auth->action_ = AuthQuery::Action::SHOW_USERS;
|
||||
return auth;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return AuthQuery*
|
||||
*/
|
||||
antlrcpp::Any CypherMainVisitor::visitSetRole(
|
||||
MemgraphCypher::SetRoleContext *ctx) {
|
||||
AuthQuery *auth = storage_->Create<AuthQuery>();
|
||||
auth->action_ = AuthQuery::Action::SET_ROLE;
|
||||
auth->user_ = ctx->user->accept(this).as<std::string>();
|
||||
auth->role_ = ctx->role->accept(this).as<std::string>();
|
||||
return auth;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return AuthQuery*
|
||||
*/
|
||||
antlrcpp::Any CypherMainVisitor::visitClearRole(
|
||||
MemgraphCypher::ClearRoleContext *ctx) {
|
||||
AuthQuery *auth = storage_->Create<AuthQuery>();
|
||||
auth->action_ = AuthQuery::Action::CLEAR_ROLE;
|
||||
auth->user_ = ctx->user->accept(this).as<std::string>();
|
||||
return auth;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return AuthQuery*
|
||||
*/
|
||||
antlrcpp::Any CypherMainVisitor::visitGrantPrivilege(
|
||||
MemgraphCypher::GrantPrivilegeContext *ctx) {
|
||||
AuthQuery *auth = storage_->Create<AuthQuery>();
|
||||
auth->action_ = AuthQuery::Action::GRANT_PRIVILEGE;
|
||||
auth->user_or_role_ = ctx->userOrRole->accept(this).as<std::string>();
|
||||
if (ctx->privilegeList()) {
|
||||
for (auto *privilege : ctx->privilegeList()->privilege()) {
|
||||
auth->privileges_.push_back(privilege->accept(this));
|
||||
}
|
||||
} else {
|
||||
/* grant all privileges */
|
||||
auth->privileges_ = kPrivilegesAll;
|
||||
}
|
||||
return auth;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return AuthQuery*
|
||||
*/
|
||||
antlrcpp::Any CypherMainVisitor::visitDenyPrivilege(
|
||||
MemgraphCypher::DenyPrivilegeContext *ctx) {
|
||||
AuthQuery *auth = storage_->Create<AuthQuery>();
|
||||
auth->action_ = AuthQuery::Action::DENY_PRIVILEGE;
|
||||
auth->user_or_role_ = ctx->userOrRole->accept(this).as<std::string>();
|
||||
if (ctx->privilegeList()) {
|
||||
for (auto *privilege : ctx->privilegeList()->privilege()) {
|
||||
auth->privileges_.push_back(privilege->accept(this));
|
||||
}
|
||||
} else {
|
||||
/* deny all privileges */
|
||||
auth->privileges_ = kPrivilegesAll;
|
||||
}
|
||||
return auth;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return AuthQuery*
|
||||
*/
|
||||
antlrcpp::Any CypherMainVisitor::visitRevokePrivilege(
|
||||
MemgraphCypher::RevokePrivilegeContext *ctx) {
|
||||
AuthQuery *auth = storage_->Create<AuthQuery>();
|
||||
auth->action_ = AuthQuery::Action::REVOKE_PRIVILEGE;
|
||||
auth->user_or_role_ = ctx->userOrRole->accept(this).as<std::string>();
|
||||
if (ctx->privilegeList()) {
|
||||
for (auto *privilege : ctx->privilegeList()->privilege()) {
|
||||
auth->privileges_.push_back(privilege->accept(this));
|
||||
}
|
||||
} else {
|
||||
/* revoke all privileges */
|
||||
auth->privileges_ = kPrivilegesAll;
|
||||
}
|
||||
return auth;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return AuthQuery::Privilege
|
||||
*/
|
||||
antlrcpp::Any CypherMainVisitor::visitPrivilege(
|
||||
MemgraphCypher::PrivilegeContext *ctx) {
|
||||
if (ctx->CREATE()) return AuthQuery::Privilege::CREATE;
|
||||
if (ctx->DELETE()) return AuthQuery::Privilege::DELETE;
|
||||
if (ctx->MATCH()) return AuthQuery::Privilege::MATCH;
|
||||
if (ctx->MERGE()) return AuthQuery::Privilege::MERGE;
|
||||
if (ctx->SET()) return AuthQuery::Privilege::SET;
|
||||
if (ctx->REMOVE()) return AuthQuery::Privilege::REMOVE;
|
||||
if (ctx->INDEX()) return AuthQuery::Privilege::INDEX;
|
||||
if (ctx->STATS()) return AuthQuery::Privilege::STATS;
|
||||
if (ctx->AUTH()) return AuthQuery::Privilege::AUTH;
|
||||
if (ctx->CONSTRAINT()) return AuthQuery::Privilege::CONSTRAINT;
|
||||
LOG(FATAL) << "Should not get here - unknown privilege!";
|
||||
}
|
||||
|
||||
/**
|
||||
* @return AuthQuery*
|
||||
*/
|
||||
antlrcpp::Any CypherMainVisitor::visitShowPrivileges(
|
||||
MemgraphCypher::ShowPrivilegesContext *ctx) {
|
||||
AuthQuery *auth = storage_->Create<AuthQuery>();
|
||||
auth->action_ = AuthQuery::Action::SHOW_PRIVILEGES;
|
||||
auth->user_or_role_ = ctx->userOrRole->accept(this).as<std::string>();
|
||||
return auth;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return AuthQuery*
|
||||
*/
|
||||
antlrcpp::Any CypherMainVisitor::visitShowRoleForUser(
|
||||
MemgraphCypher::ShowRoleForUserContext *ctx) {
|
||||
AuthQuery *auth = storage_->Create<AuthQuery>();
|
||||
auth->action_ = AuthQuery::Action::SHOW_ROLE_FOR_USER;
|
||||
auth->user_ = ctx->user->accept(this).as<std::string>();
|
||||
return auth;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return AuthQuery*
|
||||
*/
|
||||
antlrcpp::Any CypherMainVisitor::visitShowUsersForRole(
|
||||
MemgraphCypher::ShowUsersForRoleContext *ctx) {
|
||||
AuthQuery *auth = storage_->Create<AuthQuery>();
|
||||
auth->action_ = AuthQuery::Action::SHOW_USERS_FOR_ROLE;
|
||||
auth->role_ = ctx->role->accept(this).as<std::string>();
|
||||
return auth;
|
||||
}
|
||||
|
||||
antlrcpp::Any CypherMainVisitor::visitCypherReturn(
|
||||
MemgraphCypher::CypherReturnContext *ctx) {
|
||||
auto *return_clause = storage_->Create<Return>();
|
||||
|
||||
@@ -176,11 +176,6 @@ class CypherMainVisitor : public antlropencypher::MemgraphCypherBaseVisitor {
|
||||
antlrcpp::Any visitConstraintQuery(
|
||||
MemgraphCypher::ConstraintQueryContext *ctx) override;
|
||||
|
||||
/**
|
||||
* @return AuthQuery*
|
||||
*/
|
||||
antlrcpp::Any visitAuthQuery(MemgraphCypher::AuthQueryContext *ctx) override;
|
||||
|
||||
/**
|
||||
* @return DumpQuery*
|
||||
*/
|
||||
@@ -219,28 +214,6 @@ class CypherMainVisitor : public antlropencypher::MemgraphCypherBaseVisitor {
|
||||
*/
|
||||
antlrcpp::Any visitCallProcedure(MemgraphCypher::CallProcedureContext *ctx) override;
|
||||
|
||||
/**
|
||||
* @return std::string
|
||||
*/
|
||||
antlrcpp::Any visitUserOrRoleName(
|
||||
MemgraphCypher::UserOrRoleNameContext *ctx) override;
|
||||
|
||||
/**
|
||||
* @return AuthQuery*
|
||||
*/
|
||||
antlrcpp::Any visitCreateRole(
|
||||
MemgraphCypher::CreateRoleContext *ctx) override;
|
||||
|
||||
/**
|
||||
* @return AuthQuery*
|
||||
*/
|
||||
antlrcpp::Any visitDropRole(MemgraphCypher::DropRoleContext *ctx) override;
|
||||
|
||||
/**
|
||||
* @return AuthQuery*
|
||||
*/
|
||||
antlrcpp::Any visitShowRoles(MemgraphCypher::ShowRolesContext *ctx) override;
|
||||
|
||||
/**
|
||||
* @return IndexQuery*
|
||||
*/
|
||||
@@ -252,79 +225,6 @@ class CypherMainVisitor : public antlropencypher::MemgraphCypherBaseVisitor {
|
||||
*/
|
||||
antlrcpp::Any visitDropIndex(MemgraphCypher::DropIndexContext *ctx) override;
|
||||
|
||||
/**
|
||||
* @return AuthQuery*
|
||||
*/
|
||||
antlrcpp::Any visitCreateUser(
|
||||
MemgraphCypher::CreateUserContext *ctx) override;
|
||||
|
||||
/**
|
||||
* @return AuthQuery*
|
||||
*/
|
||||
antlrcpp::Any visitSetPassword(
|
||||
MemgraphCypher::SetPasswordContext *ctx) override;
|
||||
|
||||
/**
|
||||
* @return AuthQuery*
|
||||
*/
|
||||
antlrcpp::Any visitDropUser(MemgraphCypher::DropUserContext *ctx) override;
|
||||
|
||||
/**
|
||||
* @return AuthQuery*
|
||||
*/
|
||||
antlrcpp::Any visitShowUsers(MemgraphCypher::ShowUsersContext *ctx) override;
|
||||
|
||||
/**
|
||||
* @return AuthQuery*
|
||||
*/
|
||||
antlrcpp::Any visitSetRole(MemgraphCypher::SetRoleContext *ctx) override;
|
||||
|
||||
/**
|
||||
* @return AuthQuery*
|
||||
*/
|
||||
antlrcpp::Any visitClearRole(MemgraphCypher::ClearRoleContext *ctx) override;
|
||||
|
||||
/**
|
||||
* @return AuthQuery*
|
||||
*/
|
||||
antlrcpp::Any visitGrantPrivilege(
|
||||
MemgraphCypher::GrantPrivilegeContext *ctx) override;
|
||||
|
||||
/**
|
||||
* @return AuthQuery*
|
||||
*/
|
||||
antlrcpp::Any visitDenyPrivilege(
|
||||
MemgraphCypher::DenyPrivilegeContext *ctx) override;
|
||||
|
||||
/**
|
||||
* @return AuthQuery*
|
||||
*/
|
||||
antlrcpp::Any visitRevokePrivilege(
|
||||
MemgraphCypher::RevokePrivilegeContext *ctx) override;
|
||||
|
||||
/**
|
||||
* @return AuthQuery::Privilege
|
||||
*/
|
||||
antlrcpp::Any visitPrivilege(MemgraphCypher::PrivilegeContext *ctx) override;
|
||||
|
||||
/**
|
||||
* @return AuthQuery*
|
||||
*/
|
||||
antlrcpp::Any visitShowPrivileges(
|
||||
MemgraphCypher::ShowPrivilegesContext *ctx) override;
|
||||
|
||||
/**
|
||||
* @return AuthQuery*
|
||||
*/
|
||||
antlrcpp::Any visitShowRoleForUser(
|
||||
MemgraphCypher::ShowRoleForUserContext *ctx) override;
|
||||
|
||||
/**
|
||||
* @return AuthQuery*
|
||||
*/
|
||||
antlrcpp::Any visitShowUsersForRole(
|
||||
MemgraphCypher::ShowUsersForRoleContext *ctx) override;
|
||||
|
||||
/**
|
||||
* @return Return*
|
||||
*/
|
||||
|
||||
@@ -46,9 +46,7 @@ indexInfo : INDEX INFO ;
|
||||
|
||||
constraintInfo : CONSTRAINT INFO ;
|
||||
|
||||
raftInfo : RAFT INFO ;
|
||||
|
||||
infoQuery : SHOW ( storageInfo | indexInfo | constraintInfo | raftInfo ) ;
|
||||
infoQuery : SHOW ( storageInfo | indexInfo | constraintInfo ) ;
|
||||
|
||||
explainQuery : EXPLAIN cypherQuery ;
|
||||
|
||||
|
||||
@@ -116,7 +116,6 @@ OPTIONAL : O P T I O N A L ;
|
||||
OR : O R ;
|
||||
ORDER : O R D E R ;
|
||||
PROFILE : P R O F I L E ;
|
||||
RAFT : R A F T ;
|
||||
REDUCE : R E D U C E ;
|
||||
REMOVE : R E M O V E ;
|
||||
RETURN : R E T U R N ;
|
||||
|
||||
@@ -7,26 +7,8 @@ options { tokenVocab=MemgraphCypherLexer; }
|
||||
import Cypher ;
|
||||
|
||||
memgraphCypherKeyword : cypherKeyword
|
||||
| ALTER
|
||||
| AUTH
|
||||
| CLEAR
|
||||
| DATABASE
|
||||
| DENY
|
||||
| DROP
|
||||
| DUMP
|
||||
| FOR
|
||||
| FROM
|
||||
| GRANT
|
||||
| IDENTIFIED
|
||||
| PASSWORD
|
||||
| PRIVILEGES
|
||||
| REVOKE
|
||||
| ROLE
|
||||
| ROLES
|
||||
| STATS
|
||||
| TO
|
||||
| USER
|
||||
| USERS
|
||||
;
|
||||
|
||||
symbolicName : UnescapedSymbolicName
|
||||
@@ -40,63 +22,7 @@ query : cypherQuery
|
||||
| profileQuery
|
||||
| infoQuery
|
||||
| constraintQuery
|
||||
| authQuery
|
||||
| dumpQuery
|
||||
;
|
||||
|
||||
authQuery : createRole
|
||||
| dropRole
|
||||
| showRoles
|
||||
| createUser
|
||||
| setPassword
|
||||
| dropUser
|
||||
| showUsers
|
||||
| setRole
|
||||
| clearRole
|
||||
| grantPrivilege
|
||||
| denyPrivilege
|
||||
| revokePrivilege
|
||||
| showPrivileges
|
||||
| showRoleForUser
|
||||
| showUsersForRole
|
||||
;
|
||||
|
||||
userOrRoleName : symbolicName ;
|
||||
|
||||
createRole : CREATE ROLE role=userOrRoleName ;
|
||||
|
||||
dropRole : DROP ROLE role=userOrRoleName ;
|
||||
|
||||
showRoles : SHOW ROLES ;
|
||||
|
||||
createUser : CREATE USER user=userOrRoleName
|
||||
( IDENTIFIED BY password=literal )? ;
|
||||
|
||||
setPassword : SET PASSWORD FOR user=userOrRoleName TO password=literal;
|
||||
|
||||
dropUser : DROP USER user=userOrRoleName ;
|
||||
|
||||
showUsers : SHOW USERS ;
|
||||
|
||||
setRole : SET ROLE FOR user=userOrRoleName TO role=userOrRoleName;
|
||||
|
||||
clearRole : CLEAR ROLE FOR user=userOrRoleName ;
|
||||
|
||||
grantPrivilege : GRANT ( ALL PRIVILEGES | privileges=privilegeList ) TO userOrRole=userOrRoleName ;
|
||||
|
||||
denyPrivilege : DENY ( ALL PRIVILEGES | privileges=privilegeList ) TO userOrRole=userOrRoleName ;
|
||||
|
||||
revokePrivilege : REVOKE ( ALL PRIVILEGES | privileges=privilegeList ) FROM userOrRole=userOrRoleName ;
|
||||
|
||||
privilege : CREATE | DELETE | MATCH | MERGE | SET
|
||||
| REMOVE | INDEX | STATS | AUTH | CONSTRAINT | DUMP ;
|
||||
|
||||
privilegeList : privilege ( ',' privilege )* ;
|
||||
|
||||
showPrivileges : SHOW PRIVILEGES FOR userOrRole=userOrRoleName ;
|
||||
|
||||
showRoleForUser : SHOW ROLE FOR user=userOrRoleName ;
|
||||
|
||||
showUsersForRole : SHOW USERS FOR role=userOrRoleName ;
|
||||
|
||||
dumpQuery: DUMP DATABASE ;
|
||||
|
||||
@@ -10,24 +10,5 @@ lexer grammar MemgraphCypherLexer ;
|
||||
|
||||
import CypherLexer ;
|
||||
|
||||
ALTER : A L T E R ;
|
||||
AUTH : A U T H ;
|
||||
CLEAR : C L E A R ;
|
||||
DATABASE : D A T A B A S E ;
|
||||
DENY : D E N Y ;
|
||||
DROP : D R O P ;
|
||||
DUMP : D U M P ;
|
||||
FOR : F O R ;
|
||||
FROM : F R O M ;
|
||||
GRANT : G R A N T ;
|
||||
GRANTS : G R A N T S ;
|
||||
IDENTIFIED : I D E N T I F I E D ;
|
||||
PASSWORD : P A S S W O R D ;
|
||||
PRIVILEGES : P R I V I L E G E S ;
|
||||
REVOKE : R E V O K E ;
|
||||
ROLE : R O L E ;
|
||||
ROLES : R O L E S ;
|
||||
STATS : S T A T S ;
|
||||
TO : T O ;
|
||||
USER : U S E R ;
|
||||
USERS : U S E R S ;
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
|
||||
#include <glog/logging.h>
|
||||
|
||||
#include "auth/auth.hpp"
|
||||
#include "glue/auth.hpp"
|
||||
#include "glue/communication.hpp"
|
||||
#ifndef MG_SINGLE_NODE_HA
|
||||
#include "query/dump.hpp"
|
||||
@@ -13,15 +11,11 @@
|
||||
#include "query/exceptions.hpp"
|
||||
#include "query/frontend/ast/cypher_main_visitor.hpp"
|
||||
#include "query/frontend/opencypher/parser.hpp"
|
||||
#include "query/frontend/semantic/required_privileges.hpp"
|
||||
#include "query/frontend/semantic/symbol_generator.hpp"
|
||||
#include "query/interpret/eval.hpp"
|
||||
#include "query/plan/planner.hpp"
|
||||
#include "query/plan/profile.hpp"
|
||||
#include "query/plan/vertex_count_cache.hpp"
|
||||
#ifdef MG_SINGLE_NODE_HA
|
||||
#include "raft/exceptions.hpp"
|
||||
#endif
|
||||
#include "utils/exceptions.hpp"
|
||||
#include "utils/flag_validation.hpp"
|
||||
#include "utils/string.hpp"
|
||||
@@ -45,7 +39,6 @@ struct ParsedQuery {
|
||||
frontend::StrippedQuery stripped_query;
|
||||
AstStorage ast_storage;
|
||||
Query *query;
|
||||
std::vector<AuthQuery::Privilege> required_privileges;
|
||||
};
|
||||
|
||||
ParsedQuery ParseQuery(const std::string &query_string,
|
||||
@@ -105,8 +98,7 @@ ParsedQuery ParseQuery(const std::string &query_string,
|
||||
|
||||
visitor.visit(parser->tree());
|
||||
|
||||
CachedQuery cached_query{std::move(ast_storage), visitor.query(),
|
||||
query::GetRequiredPrivileges(visitor.query())};
|
||||
CachedQuery cached_query{std::move(ast_storage), visitor.query()};
|
||||
|
||||
it = accessor.insert({hash, std::move(cached_query)}).first;
|
||||
}
|
||||
@@ -124,8 +116,7 @@ ParsedQuery ParseQuery(const std::string &query_string,
|
||||
std::move(parameters),
|
||||
std::move(stripped_query),
|
||||
std::move(ast_storage),
|
||||
query,
|
||||
it->second.required_privileges};
|
||||
query};
|
||||
}
|
||||
|
||||
class SingleNodeLogicalPlan final : public LogicalPlan {
|
||||
@@ -164,302 +155,6 @@ TypedValue EvaluateOptionalExpression(Expression *expression,
|
||||
return expression ? expression->Accept(*eval) : TypedValue();
|
||||
}
|
||||
|
||||
Callback HandleAuthQuery(AuthQuery *auth_query, auth::Auth *auth,
|
||||
const Parameters ¶meters,
|
||||
DbAccessor *db_accessor) {
|
||||
// Empty frame for evaluation of password expression. This is OK since
|
||||
// password should be either null or string literal and it's evaluation
|
||||
// should not depend on frame.
|
||||
Frame frame(0);
|
||||
SymbolTable symbol_table;
|
||||
EvaluationContext evaluation_context;
|
||||
// TODO: MemoryResource for EvaluationContext, it should probably be passed as
|
||||
// the argument to Callback.
|
||||
evaluation_context.timestamp =
|
||||
std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||
std::chrono::system_clock::now().time_since_epoch())
|
||||
.count();
|
||||
evaluation_context.parameters = parameters;
|
||||
ExpressionEvaluator evaluator(&frame, symbol_table, evaluation_context,
|
||||
db_accessor, storage::View::OLD);
|
||||
|
||||
AuthQuery::Action action = auth_query->action_;
|
||||
std::string username = auth_query->user_;
|
||||
std::string rolename = auth_query->role_;
|
||||
std::string user_or_role = auth_query->user_or_role_;
|
||||
std::vector<AuthQuery::Privilege> privileges = auth_query->privileges_;
|
||||
auto password = EvaluateOptionalExpression(auth_query->password_, &evaluator);
|
||||
|
||||
Callback callback;
|
||||
|
||||
switch (auth_query->action_) {
|
||||
case AuthQuery::Action::CREATE_USER:
|
||||
callback.fn = [auth, username, password] {
|
||||
CHECK(password.IsString() || password.IsNull());
|
||||
|
||||
std::lock_guard<std::mutex> lock(auth->WithLock());
|
||||
auto user = auth->AddUser(
|
||||
username,
|
||||
password.IsString()
|
||||
? std::make_optional(std::string(password.ValueString()))
|
||||
: std::nullopt);
|
||||
if (!user) {
|
||||
throw QueryRuntimeException("User or role '{}' already exists.",
|
||||
username);
|
||||
}
|
||||
return std::vector<std::vector<TypedValue>>();
|
||||
};
|
||||
return callback;
|
||||
case AuthQuery::Action::DROP_USER:
|
||||
callback.fn = [auth, username] {
|
||||
std::lock_guard<std::mutex> lock(auth->WithLock());
|
||||
auto user = auth->GetUser(username);
|
||||
if (!user) {
|
||||
throw QueryRuntimeException("User '{}' doesn't exist.", username);
|
||||
}
|
||||
if (!auth->RemoveUser(username)) {
|
||||
throw QueryRuntimeException("Couldn't remove user '{}'.", username);
|
||||
}
|
||||
return std::vector<std::vector<TypedValue>>();
|
||||
};
|
||||
return callback;
|
||||
case AuthQuery::Action::SET_PASSWORD:
|
||||
callback.fn = [auth, username, password] {
|
||||
CHECK(password.IsString() || password.IsNull());
|
||||
|
||||
std::lock_guard<std::mutex> lock(auth->WithLock());
|
||||
auto user = auth->GetUser(username);
|
||||
if (!user) {
|
||||
throw QueryRuntimeException("User '{}' doesn't exist.", username);
|
||||
}
|
||||
user->UpdatePassword(
|
||||
password.IsString()
|
||||
? std::make_optional(std::string(password.ValueString()))
|
||||
: std::nullopt);
|
||||
auth->SaveUser(*user);
|
||||
return std::vector<std::vector<TypedValue>>();
|
||||
};
|
||||
return callback;
|
||||
case AuthQuery::Action::CREATE_ROLE:
|
||||
callback.fn = [auth, rolename] {
|
||||
std::lock_guard<std::mutex> lock(auth->WithLock());
|
||||
auto role = auth->AddRole(rolename);
|
||||
if (!role) {
|
||||
throw QueryRuntimeException("User or role '{}' already exists.",
|
||||
rolename);
|
||||
}
|
||||
return std::vector<std::vector<TypedValue>>();
|
||||
};
|
||||
return callback;
|
||||
case AuthQuery::Action::DROP_ROLE:
|
||||
callback.fn = [auth, rolename] {
|
||||
std::lock_guard<std::mutex> lock(auth->WithLock());
|
||||
auto role = auth->GetRole(rolename);
|
||||
if (!role) {
|
||||
throw QueryRuntimeException("Role '{}' doesn't exist.", rolename);
|
||||
}
|
||||
if (!auth->RemoveRole(rolename)) {
|
||||
throw QueryRuntimeException("Couldn't remove role '{}'.", rolename);
|
||||
}
|
||||
return std::vector<std::vector<TypedValue>>();
|
||||
};
|
||||
return callback;
|
||||
case AuthQuery::Action::SHOW_USERS:
|
||||
callback.header = {"user"};
|
||||
callback.fn = [auth] {
|
||||
std::lock_guard<std::mutex> lock(auth->WithLock());
|
||||
std::vector<std::vector<TypedValue>> users;
|
||||
for (const auto &user : auth->AllUsers()) {
|
||||
users.push_back({TypedValue(user.username())});
|
||||
}
|
||||
return users;
|
||||
};
|
||||
return callback;
|
||||
case AuthQuery::Action::SHOW_ROLES:
|
||||
callback.header = {"role"};
|
||||
callback.fn = [auth] {
|
||||
std::lock_guard<std::mutex> lock(auth->WithLock());
|
||||
std::vector<std::vector<TypedValue>> roles;
|
||||
for (const auto &role : auth->AllRoles()) {
|
||||
roles.push_back({TypedValue(role.rolename())});
|
||||
}
|
||||
return roles;
|
||||
};
|
||||
return callback;
|
||||
case AuthQuery::Action::SET_ROLE:
|
||||
callback.fn = [auth, username, rolename] {
|
||||
std::lock_guard<std::mutex> lock(auth->WithLock());
|
||||
auto user = auth->GetUser(username);
|
||||
if (!user) {
|
||||
throw QueryRuntimeException("User '{}' doesn't exist .", username);
|
||||
}
|
||||
auto role = auth->GetRole(rolename);
|
||||
if (!role) {
|
||||
throw QueryRuntimeException("Role '{}' doesn't exist .", rolename);
|
||||
}
|
||||
if (user->role()) {
|
||||
throw QueryRuntimeException(
|
||||
"User '{}' is already a member of role '{}'.", username,
|
||||
user->role()->rolename());
|
||||
}
|
||||
user->SetRole(*role);
|
||||
auth->SaveUser(*user);
|
||||
return std::vector<std::vector<TypedValue>>();
|
||||
};
|
||||
return callback;
|
||||
case AuthQuery::Action::CLEAR_ROLE:
|
||||
callback.fn = [auth, username] {
|
||||
std::lock_guard<std::mutex> lock(auth->WithLock());
|
||||
auto user = auth->GetUser(username);
|
||||
if (!user) {
|
||||
throw QueryRuntimeException("User '{}' doesn't exist .", username);
|
||||
}
|
||||
user->ClearRole();
|
||||
auth->SaveUser(*user);
|
||||
return std::vector<std::vector<TypedValue>>();
|
||||
};
|
||||
return callback;
|
||||
case AuthQuery::Action::GRANT_PRIVILEGE:
|
||||
case AuthQuery::Action::DENY_PRIVILEGE:
|
||||
case AuthQuery::Action::REVOKE_PRIVILEGE: {
|
||||
callback.fn = [auth, user_or_role, action, privileges] {
|
||||
std::lock_guard<std::mutex> lock(auth->WithLock());
|
||||
std::vector<auth::Permission> permissions;
|
||||
for (const auto &privilege : privileges) {
|
||||
permissions.push_back(glue::PrivilegeToPermission(privilege));
|
||||
}
|
||||
auto user = auth->GetUser(user_or_role);
|
||||
auto role = auth->GetRole(user_or_role);
|
||||
if (!user && !role) {
|
||||
throw QueryRuntimeException("User or role '{}' doesn't exist.",
|
||||
user_or_role);
|
||||
}
|
||||
if (user) {
|
||||
for (const auto &permission : permissions) {
|
||||
// TODO (mferencevic): should we first check that the privilege
|
||||
// is granted/denied/revoked before unconditionally
|
||||
// granting/denying/revoking it?
|
||||
if (action == AuthQuery::Action::GRANT_PRIVILEGE) {
|
||||
user->permissions().Grant(permission);
|
||||
} else if (action == AuthQuery::Action::DENY_PRIVILEGE) {
|
||||
user->permissions().Deny(permission);
|
||||
} else {
|
||||
user->permissions().Revoke(permission);
|
||||
}
|
||||
}
|
||||
auth->SaveUser(*user);
|
||||
} else {
|
||||
for (const auto &permission : permissions) {
|
||||
// TODO (mferencevic): should we first check that the privilege
|
||||
// is granted/denied/revoked before unconditionally
|
||||
// granting/denying/revoking it?
|
||||
if (action == AuthQuery::Action::GRANT_PRIVILEGE) {
|
||||
role->permissions().Grant(permission);
|
||||
} else if (action == AuthQuery::Action::DENY_PRIVILEGE) {
|
||||
role->permissions().Deny(permission);
|
||||
} else {
|
||||
role->permissions().Revoke(permission);
|
||||
}
|
||||
}
|
||||
auth->SaveRole(*role);
|
||||
}
|
||||
return std::vector<std::vector<TypedValue>>();
|
||||
};
|
||||
return callback;
|
||||
}
|
||||
case AuthQuery::Action::SHOW_PRIVILEGES:
|
||||
callback.header = {"privilege", "effective", "description"};
|
||||
callback.fn = [auth, user_or_role] {
|
||||
std::lock_guard<std::mutex> lock(auth->WithLock());
|
||||
std::vector<std::vector<TypedValue>> grants;
|
||||
auto user = auth->GetUser(user_or_role);
|
||||
auto role = auth->GetRole(user_or_role);
|
||||
if (!user && !role) {
|
||||
throw QueryRuntimeException("User or role '{}' doesn't exist.",
|
||||
user_or_role);
|
||||
}
|
||||
if (user) {
|
||||
const auto &permissions = user->GetPermissions();
|
||||
for (const auto &privilege : kPrivilegesAll) {
|
||||
auto permission = glue::PrivilegeToPermission(privilege);
|
||||
auto effective = permissions.Has(permission);
|
||||
if (permissions.Has(permission) != auth::PermissionLevel::NEUTRAL) {
|
||||
std::vector<std::string> description;
|
||||
auto user_level = user->permissions().Has(permission);
|
||||
if (user_level == auth::PermissionLevel::GRANT) {
|
||||
description.push_back("GRANTED TO USER");
|
||||
} else if (user_level == auth::PermissionLevel::DENY) {
|
||||
description.push_back("DENIED TO USER");
|
||||
}
|
||||
if (user->role()) {
|
||||
auto role_level = user->role()->permissions().Has(permission);
|
||||
if (role_level == auth::PermissionLevel::GRANT) {
|
||||
description.push_back("GRANTED TO ROLE");
|
||||
} else if (role_level == auth::PermissionLevel::DENY) {
|
||||
description.push_back("DENIED TO ROLE");
|
||||
}
|
||||
}
|
||||
grants.push_back(
|
||||
{TypedValue(auth::PermissionToString(permission)),
|
||||
TypedValue(auth::PermissionLevelToString(effective)),
|
||||
TypedValue(utils::Join(description, ", "))});
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const auto &permissions = role->permissions();
|
||||
for (const auto &privilege : kPrivilegesAll) {
|
||||
auto permission = glue::PrivilegeToPermission(privilege);
|
||||
auto effective = permissions.Has(permission);
|
||||
if (effective != auth::PermissionLevel::NEUTRAL) {
|
||||
std::string description;
|
||||
if (effective == auth::PermissionLevel::GRANT) {
|
||||
description = "GRANTED TO ROLE";
|
||||
} else if (effective == auth::PermissionLevel::DENY) {
|
||||
description = "DENIED TO ROLE";
|
||||
}
|
||||
grants.push_back(
|
||||
{TypedValue(auth::PermissionToString(permission)),
|
||||
TypedValue(auth::PermissionLevelToString(effective)),
|
||||
TypedValue(description)});
|
||||
}
|
||||
}
|
||||
}
|
||||
return grants;
|
||||
};
|
||||
return callback;
|
||||
case AuthQuery::Action::SHOW_ROLE_FOR_USER:
|
||||
callback.header = {"role"};
|
||||
callback.fn = [auth, username] {
|
||||
std::lock_guard<std::mutex> lock(auth->WithLock());
|
||||
auto user = auth->GetUser(username);
|
||||
if (!user) {
|
||||
throw QueryRuntimeException("User '{}' doesn't exist .", username);
|
||||
}
|
||||
return std::vector<std::vector<TypedValue>>{std::vector<TypedValue>{
|
||||
TypedValue(user->role() ? user->role()->rolename() : "null")}};
|
||||
};
|
||||
return callback;
|
||||
case AuthQuery::Action::SHOW_USERS_FOR_ROLE:
|
||||
callback.header = {"users"};
|
||||
callback.fn = [auth, rolename] {
|
||||
std::lock_guard<std::mutex> lock(auth->WithLock());
|
||||
auto role = auth->GetRole(rolename);
|
||||
if (!role) {
|
||||
throw QueryRuntimeException("Role '{}' doesn't exist.", rolename);
|
||||
}
|
||||
std::vector<std::vector<TypedValue>> users;
|
||||
for (const auto &user : auth->AllUsersForRole(rolename)) {
|
||||
users.emplace_back(
|
||||
std::vector<TypedValue>{TypedValue(user.username())});
|
||||
}
|
||||
return users;
|
||||
};
|
||||
return callback;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Interpreter::Interpreter(InterpreterContext *interpreter_context)
|
||||
: interpreter_context_(interpreter_context) {
|
||||
CHECK(interpreter_context_) << "Interpreter context must not be NULL";
|
||||
@@ -630,7 +325,7 @@ PreparedQuery Interpreter::PrepareTransactionQuery(
|
||||
LOG(FATAL) << "Should not get here -- unknown transaction query!";
|
||||
}
|
||||
|
||||
return {{}, {}, [handler = std::move(handler)](AnyStream *) {
|
||||
return {{}, [handler = std::move(handler)](AnyStream *) {
|
||||
handler();
|
||||
return QueryHandlerResult::NOTHING;
|
||||
}};
|
||||
@@ -663,7 +358,7 @@ PreparedQuery PrepareCypherQuery(
|
||||
}
|
||||
|
||||
return PreparedQuery{
|
||||
std::move(header), std::move(parsed_query.required_privileges),
|
||||
std::move(header),
|
||||
[plan = std::move(plan), parameters = std::move(parsed_query.parameters),
|
||||
output_symbols = std::move(output_symbols), summary, dba,
|
||||
interpreter_context, execution_memory](AnyStream *stream) {
|
||||
@@ -717,7 +412,6 @@ PreparedQuery PrepareExplainQuery(
|
||||
|
||||
return PreparedQuery{
|
||||
{"QUERY PLAN"},
|
||||
std::move(parsed_query.required_privileges),
|
||||
[rows = std::move(printed_plan_rows)](AnyStream *stream) {
|
||||
for (const auto &row : rows) {
|
||||
stream->Result(row);
|
||||
@@ -769,7 +463,6 @@ PreparedQuery PrepareProfileQuery(
|
||||
|
||||
return PreparedQuery{
|
||||
{"OPERATOR", "ACTUAL HITS", "RELATIVE TIME", "ABSOLUTE TIME"},
|
||||
std::move(parsed_query.required_privileges),
|
||||
[plan = std::move(cypher_query_plan),
|
||||
parameters = std::move(parsed_inner_query.parameters), summary, dba,
|
||||
interpreter_context, execution_memory](AnyStream *stream) {
|
||||
@@ -797,7 +490,6 @@ PreparedQuery PrepareDumpQuery(
|
||||
#ifndef MG_SINGLE_NODE_HA
|
||||
return PreparedQuery{
|
||||
{"QUERY"},
|
||||
std::move(parsed_query.required_privileges),
|
||||
[interpreter_context](AnyStream *stream) {
|
||||
auto dba = interpreter_context->db->Access();
|
||||
query::DbAccessor query_dba{&dba};
|
||||
@@ -913,7 +605,6 @@ PreparedQuery PrepareIndexQuery(
|
||||
}
|
||||
|
||||
return PreparedQuery{{},
|
||||
std::move(parsed_query.required_privileges),
|
||||
[handler = std::move(handler)](AnyStream *stream) {
|
||||
handler();
|
||||
#ifdef MG_SINGLE_NODE_V2
|
||||
@@ -924,52 +615,6 @@ PreparedQuery PrepareIndexQuery(
|
||||
}};
|
||||
}
|
||||
|
||||
PreparedQuery PrepareAuthQuery(
|
||||
ParsedQuery parsed_query, bool in_explicit_transaction,
|
||||
std::map<std::string, TypedValue> *summary,
|
||||
InterpreterContext *interpreter_context, DbAccessor *dba,
|
||||
utils::MonotonicBufferResource *execution_memory) {
|
||||
#ifdef MG_SINGLE_NODE_HA
|
||||
throw utils::NotYetImplemented(
|
||||
"Managing user privileges is not yet supported in Memgraph HA "
|
||||
"instance.");
|
||||
#else
|
||||
if (in_explicit_transaction) {
|
||||
throw UserModificationInMulticommandTxException();
|
||||
}
|
||||
|
||||
auto *auth_query = utils::Downcast<AuthQuery>(parsed_query.query);
|
||||
|
||||
auto callback = HandleAuthQuery(auth_query, interpreter_context->auth,
|
||||
parsed_query.parameters, dba);
|
||||
|
||||
SymbolTable symbol_table;
|
||||
std::vector<Symbol> output_symbols;
|
||||
for (const auto &column : callback.header) {
|
||||
output_symbols.emplace_back(symbol_table.CreateSymbol(column, "false"));
|
||||
}
|
||||
|
||||
auto plan =
|
||||
std::make_shared<CachedPlan>(std::make_unique<SingleNodeLogicalPlan>(
|
||||
std::make_unique<plan::OutputTable>(
|
||||
output_symbols,
|
||||
[fn = callback.fn](Frame *, ExecutionContext *) { return fn(); }),
|
||||
0.0, AstStorage{}, symbol_table));
|
||||
|
||||
return PreparedQuery{
|
||||
callback.header, std::move(parsed_query.required_privileges),
|
||||
[callback = std::move(callback), plan = std::move(plan),
|
||||
parameters = std::move(parsed_query.parameters),
|
||||
output_symbols = std::move(output_symbols), summary, dba,
|
||||
interpreter_context, execution_memory](AnyStream *stream) {
|
||||
PullAllPlan(stream, *plan, parameters, output_symbols, false, summary,
|
||||
dba, interpreter_context, execution_memory);
|
||||
return callback.should_abort_query ? QueryHandlerResult::ABORT
|
||||
: QueryHandlerResult::COMMIT;
|
||||
}};
|
||||
#endif
|
||||
}
|
||||
|
||||
PreparedQuery PrepareInfoQuery(
|
||||
ParsedQuery parsed_query, std::map<std::string, TypedValue> *summary,
|
||||
InterpreterContext *interpreter_context,
|
||||
@@ -1102,26 +747,9 @@ PreparedQuery PrepareInfoQuery(
|
||||
};
|
||||
break;
|
||||
#endif
|
||||
case InfoQuery::InfoType::RAFT:
|
||||
#if defined(MG_SINGLE_NODE_HA)
|
||||
header = {"info", "value"};
|
||||
handler = [dba] {
|
||||
std::vector<std::vector<TypedValue>> results(
|
||||
{{TypedValue("is_leader"), TypedValue(dba->raft()->IsLeader())},
|
||||
{TypedValue("term_id"),
|
||||
TypedValue(static_cast<int64_t>(dba->raft()->TermId()))}});
|
||||
// It is critical to abort this query because it can be executed on
|
||||
// machines that aren't the leader.
|
||||
return std::pair{results, QueryHandlerResult::ABORT};
|
||||
};
|
||||
#else
|
||||
throw utils::NotYetImplemented("raft info");
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
return PreparedQuery{std::move(header),
|
||||
std::move(parsed_query.required_privileges),
|
||||
[handler = std::move(handler)](AnyStream *stream) {
|
||||
auto [results, action] = handler();
|
||||
|
||||
@@ -1246,14 +874,13 @@ PreparedQuery PrepareConstraintQuery(
|
||||
}
|
||||
|
||||
return PreparedQuery{{},
|
||||
std::move(parsed_query.required_privileges),
|
||||
[handler = std::move(handler)](AnyStream *stream) {
|
||||
handler();
|
||||
return QueryHandlerResult::COMMIT;
|
||||
}};
|
||||
}
|
||||
|
||||
std::pair<std::vector<std::string>, std::vector<query::AuthQuery::Privilege>>
|
||||
std::vector<std::string>
|
||||
Interpreter::Prepare(const std::string &query_string,
|
||||
const std::map<std::string, PropertyValue> ¶ms) {
|
||||
// Clear the last prepared query.
|
||||
@@ -1266,7 +893,7 @@ Interpreter::Prepare(const std::string &query_string,
|
||||
if (query_upper == "BEGIN" || query_upper == "COMMIT" ||
|
||||
query_upper == "ROLLBACK") {
|
||||
prepared_query_ = PrepareTransactionQuery(query_upper);
|
||||
return {prepared_query_->header, prepared_query_->privileges};
|
||||
return prepared_query_->header;
|
||||
}
|
||||
|
||||
// All queries other than transaction control queries advance the command in
|
||||
@@ -1318,17 +945,6 @@ Interpreter::Prepare(const std::string &query_string,
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef MG_SINGLE_NODE_HA
|
||||
{
|
||||
InfoQuery *info_query = nullptr;
|
||||
if (!execution_db_accessor_->raft()->IsLeader() &&
|
||||
(!(info_query = utils::Downcast<InfoQuery>(parsed_query.query)) ||
|
||||
info_query->info_type_ != InfoQuery::InfoType::RAFT)) {
|
||||
throw raft::CantExecuteQueries();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
utils::Timer planning_timer;
|
||||
PreparedQuery prepared_query;
|
||||
|
||||
@@ -1357,10 +973,6 @@ Interpreter::Prepare(const std::string &query_string,
|
||||
prepared_query = PrepareIndexQuery(
|
||||
std::move(parsed_query), in_explicit_transaction_, &summary_,
|
||||
interpreter_context_, dba, &execution_memory_);
|
||||
} else if (utils::Downcast<AuthQuery>(parsed_query.query)) {
|
||||
prepared_query = PrepareAuthQuery(
|
||||
std::move(parsed_query), in_explicit_transaction_, &summary_,
|
||||
interpreter_context_, &*execution_db_accessor_, &execution_memory_);
|
||||
} else if (utils::Downcast<InfoQuery>(parsed_query.query)) {
|
||||
#ifdef MG_SINGLE_NODE_V2
|
||||
prepared_query = PrepareInfoQuery(
|
||||
@@ -1388,7 +1000,7 @@ Interpreter::Prepare(const std::string &query_string,
|
||||
summary_["planning_time"] = planning_timer.Elapsed().count();
|
||||
prepared_query_ = std::move(prepared_query);
|
||||
|
||||
return {prepared_query_->header, prepared_query_->privileges};
|
||||
return prepared_query_->header;
|
||||
} catch (const utils::BasicException &) {
|
||||
AbortCommand();
|
||||
throw;
|
||||
|
||||
@@ -21,10 +21,6 @@
|
||||
DECLARE_bool(query_cost_planner);
|
||||
DECLARE_int32(query_plan_cache_ttl);
|
||||
|
||||
namespace auth {
|
||||
class Auth;
|
||||
} // namespace auth
|
||||
|
||||
namespace query {
|
||||
|
||||
static constexpr size_t kExecutionMemoryBlockSize = 1U * 1024U * 1024U;
|
||||
@@ -36,7 +32,6 @@ enum class QueryHandlerResult { COMMIT, ABORT, NOTHING };
|
||||
*/
|
||||
struct PreparedQuery {
|
||||
std::vector<std::string> header;
|
||||
std::vector<AuthQuery::Privilege> privileges;
|
||||
std::function<QueryHandlerResult(AnyStream *stream)> query_handler;
|
||||
};
|
||||
|
||||
@@ -74,7 +69,6 @@ class CachedPlan {
|
||||
struct CachedQuery {
|
||||
AstStorage ast_storage;
|
||||
Query *query;
|
||||
std::vector<AuthQuery::Privilege> required_privileges;
|
||||
};
|
||||
|
||||
struct QueryCacheEntry {
|
||||
@@ -144,8 +138,6 @@ struct InterpreterContext {
|
||||
// The default execution timeout is 3 minutes.
|
||||
double execution_timeout_sec{180.0};
|
||||
|
||||
auth::Auth *auth{nullptr};
|
||||
|
||||
utils::SkipList<QueryCacheEntry> ast_cache;
|
||||
utils::SkipList<PlanCacheEntry> plan_cache;
|
||||
};
|
||||
@@ -181,7 +173,7 @@ class Interpreter final {
|
||||
* leader and a query other than an Info Raft query was given
|
||||
* @throw query::QueryException
|
||||
*/
|
||||
std::pair<std::vector<std::string>, std::vector<query::AuthQuery::Privilege>>
|
||||
std::vector<std::string>
|
||||
Prepare(const std::string &query,
|
||||
const std::map<std::string, PropertyValue> ¶ms);
|
||||
|
||||
|
||||
@@ -23,6 +23,3 @@ add_subdirectory(property_based)
|
||||
|
||||
# integration test binaries
|
||||
add_subdirectory(integration)
|
||||
|
||||
# feature benchmark test binaries
|
||||
add_subdirectory(feature_benchmark)
|
||||
|
||||
@@ -31,22 +31,22 @@ add_benchmark(data_structures/concurrent/map_concurrent.cpp)
|
||||
target_link_libraries(${test_prefix}map_concurrent mg-single-node kvstore_dummy_lib)
|
||||
|
||||
add_benchmark(data_structures/ring_buffer.cpp)
|
||||
target_link_libraries(${test_prefix}ring_buffer mg-single-node-v2 mg-auth kvstore_dummy_lib)
|
||||
target_link_libraries(${test_prefix}ring_buffer mg-single-node-v2 kvstore_dummy_lib)
|
||||
|
||||
add_benchmark(query/eval.cpp)
|
||||
target_link_libraries(${test_prefix}eval mg-single-node-v2 mg-auth kvstore_dummy_lib)
|
||||
target_link_libraries(${test_prefix}eval mg-single-node-v2 kvstore_dummy_lib)
|
||||
|
||||
add_benchmark(query/execution.cpp)
|
||||
target_link_libraries(${test_prefix}execution mg-single-node-v2 mg-auth kvstore_dummy_lib)
|
||||
target_link_libraries(${test_prefix}execution mg-single-node-v2 kvstore_dummy_lib)
|
||||
|
||||
add_benchmark(query/planner.cpp)
|
||||
target_link_libraries(${test_prefix}planner mg-single-node-v2 mg-auth kvstore_dummy_lib)
|
||||
target_link_libraries(${test_prefix}planner mg-single-node-v2 kvstore_dummy_lib)
|
||||
|
||||
add_benchmark(query/profile.cpp)
|
||||
target_link_libraries(${test_prefix}profile mg-single-node-v2 mg-auth kvstore_dummy_lib)
|
||||
target_link_libraries(${test_prefix}profile mg-single-node-v2 kvstore_dummy_lib)
|
||||
|
||||
add_benchmark(query/stripped.cpp)
|
||||
target_link_libraries(${test_prefix}stripped mg-single-node-v2 mg-auth kvstore_dummy_lib)
|
||||
target_link_libraries(${test_prefix}stripped mg-single-node-v2 kvstore_dummy_lib)
|
||||
|
||||
add_benchmark(edge_storage.cpp)
|
||||
target_link_libraries(${test_prefix}edge_storage mg-single-node kvstore_dummy_lib)
|
||||
@@ -54,9 +54,6 @@ target_link_libraries(${test_prefix}edge_storage mg-single-node kvstore_dummy_li
|
||||
add_benchmark(mvcc.cpp)
|
||||
target_link_libraries(${test_prefix}mvcc mg-single-node kvstore_dummy_lib)
|
||||
|
||||
add_benchmark(rpc.cpp)
|
||||
target_link_libraries(${test_prefix}rpc mg-comm-rpc)
|
||||
|
||||
add_benchmark(skip_list_random.cpp)
|
||||
target_link_libraries(${test_prefix}skip_list_random mg-utils)
|
||||
|
||||
@@ -73,7 +70,7 @@ add_benchmark(tx_engine.cpp)
|
||||
target_link_libraries(${test_prefix}tx_engine mg-single-node kvstore_dummy_lib)
|
||||
|
||||
add_benchmark(expansion.cpp)
|
||||
target_link_libraries(${test_prefix}expansion mg-single-node-v2 mg-auth kvstore_dummy_lib)
|
||||
target_link_libraries(${test_prefix}expansion mg-single-node-v2 kvstore_dummy_lib)
|
||||
|
||||
add_benchmark(storage_v2_gc.cpp)
|
||||
target_link_libraries(${test_prefix}storage_v2_gc mg-storage-v2)
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
|
||||
#include "communication/result_stream_faker.hpp"
|
||||
#include "query/frontend/opencypher/parser.hpp"
|
||||
#include "query/frontend/semantic/required_privileges.hpp"
|
||||
#include "query/frontend/semantic/symbol_generator.hpp"
|
||||
#include "query/interpreter.hpp"
|
||||
#include "query/plan/planner.hpp"
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
- name: feature_benchmark__ha__read
|
||||
cd: ha/read
|
||||
commands: ./runner.sh
|
||||
infiles:
|
||||
- runner.sh # runner script
|
||||
- raft.json # raft configuration file
|
||||
- coordination.json # coordination configuration file
|
||||
- ../../../../build_release/tests/feature_benchmark/ha/read/benchmark # benchmark binary
|
||||
- ../../../../build_release/memgraph_ha # memgraph binary
|
||||
enable_network: true
|
||||
|
||||
- name: feature_benchmark__ha__write
|
||||
cd: ha/write
|
||||
commands: ./runner.sh
|
||||
infiles:
|
||||
- runner.sh # runner script
|
||||
- raft.json # raft configuration file
|
||||
- coordination.json # coordination configuration file
|
||||
- ../../../../build_release/tests/feature_benchmark/ha/write/benchmark # benchmark binary
|
||||
- ../../../../build_release/memgraph_ha # memgraph binary
|
||||
enable_network: true
|
||||
@@ -6,30 +6,3 @@ add_subdirectory(ssl)
|
||||
|
||||
# transactions test binaries
|
||||
add_subdirectory(transactions)
|
||||
|
||||
# auth test binaries
|
||||
add_subdirectory(auth)
|
||||
|
||||
# distributed ha/basic binaries
|
||||
add_subdirectory(ha/basic)
|
||||
|
||||
# distributed ha/constraints binaries
|
||||
add_subdirectory(ha/constraints)
|
||||
|
||||
# distributed ha/index binaries
|
||||
add_subdirectory(ha/index)
|
||||
|
||||
# distributed ha/large_log_entries binaries
|
||||
add_subdirectory(ha/large_log_entries)
|
||||
|
||||
# distributed ha/leader_election binaries
|
||||
add_subdirectory(ha/leader_election)
|
||||
|
||||
# distributed ha/term_updates binaries
|
||||
add_subdirectory(ha/term_updates)
|
||||
|
||||
# audit test binaries
|
||||
add_subdirectory(audit)
|
||||
|
||||
# ldap test binaries
|
||||
add_subdirectory(ldap)
|
||||
|
||||
@@ -22,105 +22,3 @@
|
||||
- runner.sh # runner script
|
||||
- ../../../build_debug/memgraph # memgraph binary
|
||||
- ../../../build_debug/tests/integration/transactions/tester # tester binary
|
||||
|
||||
- name: integration__auth
|
||||
cd: auth
|
||||
commands: TIMEOUT=820 ./runner.py
|
||||
infiles:
|
||||
- runner.py # runner script
|
||||
- ../../../build_debug/memgraph # memgraph binary
|
||||
- ../../../build_debug/tests/integration/auth/checker # checker binary
|
||||
- ../../../build_debug/tests/integration/auth/tester # tester binary
|
||||
|
||||
- name: integration__audit
|
||||
cd: audit
|
||||
commands: ./runner.py
|
||||
infiles:
|
||||
- runner.py # runner script
|
||||
- ../../../build_debug/memgraph # memgraph binary
|
||||
- ../../../build_debug/tests/integration/audit/tester # tester binary
|
||||
|
||||
- name: integration__ldap
|
||||
cd: ldap
|
||||
commands: |
|
||||
./prepare.sh
|
||||
./runner.py
|
||||
infiles:
|
||||
- prepare.sh # preparation script
|
||||
- runner.py # runner script
|
||||
- schema.ldif # schema file
|
||||
- ve3 # Python virtual environment
|
||||
- ../../../src/auth/reference_modules/ldap.py # LDAP auth module
|
||||
- ../../../build_debug/memgraph # memgraph binary
|
||||
- ../../../build_debug/tests/integration/ldap/tester # tester binary
|
||||
enable_network: true
|
||||
|
||||
- name: integration__ha_basic
|
||||
cd: ha/basic
|
||||
commands: TIMEOUT=480 ./runner.py
|
||||
infiles:
|
||||
- runner.py # runner script
|
||||
- raft.json # raft configuration
|
||||
- ../ha_test.py # raft test base module
|
||||
- ../../../../build_debug/memgraph_ha # memgraph ha binary
|
||||
- ../../../../build_debug/tests/integration/ha/basic/tester # tester binary
|
||||
|
||||
- name: integration__ha_constraints
|
||||
cd: ha/constraints
|
||||
commands: ./runner.py
|
||||
infiles:
|
||||
- runner.py # runner script
|
||||
- raft.json # raft configuration
|
||||
- ../ha_test.py # raft test base module
|
||||
- ../../../../build_debug/memgraph_ha # memgraph ha binary
|
||||
- ../../../../build_debug/tests/integration/ha/constraints/tester # tester binary
|
||||
|
||||
- name: integration__ha_index
|
||||
cd: ha/index
|
||||
commands: ./runner.py
|
||||
infiles:
|
||||
- runner.py # runner script
|
||||
- raft.json # raft configuration
|
||||
- ../ha_test.py # raft test base module
|
||||
- ../../../../build_debug/memgraph_ha # memgraph ha binary
|
||||
- ../../../../build_debug/tests/integration/ha/index/tester # tester binary
|
||||
|
||||
- name: integration__ha_large_log_entries
|
||||
cd: ha/large_log_entries
|
||||
commands: TIMEOUT=600 ./runner.py
|
||||
infiles:
|
||||
- runner.py # runner script
|
||||
- raft.json # raft configuration
|
||||
- ../ha_test.py # raft test base module
|
||||
- ../../../../build_debug/memgraph_ha # memgraph ha binary
|
||||
- ../../../../build_debug/tests/integration/ha/large_log_entries/tester # tester binary
|
||||
|
||||
- name: integration__ha_leader_election
|
||||
cd: ha/leader_election
|
||||
commands: TIMEOUT=300 ./runner.py
|
||||
infiles:
|
||||
- runner.py # runner script
|
||||
- raft.json # raft configuration
|
||||
- ../ha_test.py # raft test base module
|
||||
- ../../../../build_debug/memgraph_ha # memgraph ha binary
|
||||
- ../../../../build_debug/tests/integration/ha/leader_election/tester # tester binary
|
||||
|
||||
- name: integration__ha_log_compaction
|
||||
cd: ha/log_compaction
|
||||
commands: ./runner.py
|
||||
infiles:
|
||||
- runner.py # runner script
|
||||
- raft.json # raft configuration
|
||||
- ../ha_test.py # raft test base module
|
||||
- ../../../../build_debug/memgraph_ha # memgraph ha binary
|
||||
- ../../../../build_debug/tests/manual/ha_client # tester binary
|
||||
|
||||
- name: integration__ha_term_updates
|
||||
cd: ha/term_updates
|
||||
commands: ./runner.py
|
||||
infiles:
|
||||
- runner.py # runner script
|
||||
- raft.json # raft configuration
|
||||
- ../ha_test.py # raft test base module
|
||||
- ../../../../build_debug/memgraph_ha # memgraph ha binary
|
||||
- ../../../../build_debug/tests/integration/ha/term_updates/tester # tester binary
|
||||
|
||||
@@ -30,30 +30,23 @@ target_link_libraries(${test_prefix}binomial mg-utils)
|
||||
add_manual_test(bolt_client.cpp)
|
||||
target_link_libraries(${test_prefix}bolt_client mg-communication)
|
||||
|
||||
add_manual_test(ha_client.cpp)
|
||||
target_link_libraries(${test_prefix}ha_client mg-utils mg-communication)
|
||||
|
||||
add_manual_test(ha_proxy.cpp)
|
||||
target_include_directories(${test_prefix}ha_proxy PRIVATE ${CMAKE_BINARY_DIR}/src)
|
||||
target_link_libraries(${test_prefix}ha_proxy mg-utils mg-communication)
|
||||
|
||||
add_manual_test(kvstore_console.cpp)
|
||||
target_link_libraries(${test_prefix}kvstore_console kvstore_lib gflags glog)
|
||||
|
||||
add_manual_test(query_hash.cpp)
|
||||
target_link_libraries(${test_prefix}query_hash mg-single-node-v2 mg-auth kvstore_dummy_lib)
|
||||
target_link_libraries(${test_prefix}query_hash mg-single-node-v2 kvstore_dummy_lib)
|
||||
|
||||
add_manual_test(query_planner.cpp interactive_planning.cpp)
|
||||
target_link_libraries(${test_prefix}query_planner mg-single-node-v2 mg-auth kvstore_dummy_lib)
|
||||
target_link_libraries(${test_prefix}query_planner mg-single-node-v2 kvstore_dummy_lib)
|
||||
if (READLINE_FOUND)
|
||||
target_link_libraries(${test_prefix}query_planner readline)
|
||||
endif()
|
||||
|
||||
add_manual_test(expression_pretty_printer.cpp)
|
||||
target_link_libraries(${test_prefix}expression_pretty_printer mg-single-node-v2 mg-auth kvstore_dummy_lib)
|
||||
target_link_libraries(${test_prefix}expression_pretty_printer mg-single-node-v2 kvstore_dummy_lib)
|
||||
|
||||
add_manual_test(single_query.cpp)
|
||||
target_link_libraries(${test_prefix}single_query mg-single-node-v2 mg-auth kvstore_dummy_lib)
|
||||
target_link_libraries(${test_prefix}single_query mg-single-node-v2 kvstore_dummy_lib)
|
||||
|
||||
add_manual_test(sl_position_and_count.cpp)
|
||||
target_link_libraries(${test_prefix}sl_position_and_count mg-single-node kvstore_dummy_lib)
|
||||
@@ -62,7 +55,7 @@ add_manual_test(snapshot_explorer.cpp)
|
||||
target_link_libraries(${test_prefix}snapshot_explorer mg-single-node kvstore_dummy_lib)
|
||||
|
||||
add_manual_test(stripped_timing.cpp)
|
||||
target_link_libraries(${test_prefix}stripped_timing mg-single-node-v2 mg-auth kvstore_dummy_lib)
|
||||
target_link_libraries(${test_prefix}stripped_timing mg-single-node-v2 kvstore_dummy_lib)
|
||||
|
||||
add_manual_test(ssl_client.cpp)
|
||||
target_link_libraries(${test_prefix}ssl_client mg-communication)
|
||||
|
||||
@@ -16,7 +16,7 @@ int main(int argc, char *argv[]) {
|
||||
query::Interpreter interpreter{&interpreter_context};
|
||||
|
||||
ResultStreamFaker stream(&db);
|
||||
auto [header, _] = interpreter.Prepare(argv[1], {});
|
||||
auto header = interpreter.Prepare(argv[1], {});
|
||||
stream.Header(header);
|
||||
auto summary = interpreter.PullAll(&stream);
|
||||
stream.Summary(summary);
|
||||
|
||||
@@ -15,18 +15,6 @@
|
||||
commands: TIMEOUT=43200 ./continuous_integration --large-dataset
|
||||
infiles: *STRESS_INFILES
|
||||
|
||||
- name: stress_ha_normal_operation
|
||||
commands: TIMEOUT=200 ./continuous_integration_ha
|
||||
infiles: &STRESS_HA_INFILES
|
||||
- . # current directory
|
||||
- ../../build_release/memgraph_ha # memgraph release binary
|
||||
- ../../build_release/tests/stress/ # stress client binaries
|
||||
|
||||
- name: stress_ha_normal_opration_large
|
||||
project: release
|
||||
commands: TIMEOUT=7500 ./continuous_integration_ha --large-dataset
|
||||
infiles: *STRESS_HA_INFILES
|
||||
|
||||
- name: durability
|
||||
commands: TIMEOUT=300 ./ve3/bin/python3 durability --num-steps 5
|
||||
infiles: &DURABILITY_INFILES
|
||||
|
||||
@@ -19,7 +19,7 @@ function(add_unit_test test_cpp)
|
||||
endfunction(add_unit_test)
|
||||
|
||||
add_unit_test(bolt_encoder.cpp)
|
||||
target_link_libraries(${test_prefix}bolt_encoder mg-single-node-v2 mg-auth kvstore_dummy_lib)
|
||||
target_link_libraries(${test_prefix}bolt_encoder mg-single-node-v2 kvstore_dummy_lib)
|
||||
|
||||
add_unit_test(commit_log_v2.cpp)
|
||||
target_link_libraries(${test_prefix}commit_log_v2 glog gflags)
|
||||
@@ -34,7 +34,7 @@ add_unit_test(concurrent_map.cpp)
|
||||
target_link_libraries(${test_prefix}concurrent_map mg-single-node kvstore_dummy_lib)
|
||||
|
||||
add_unit_test(cypher_main_visitor.cpp)
|
||||
target_link_libraries(${test_prefix}cypher_main_visitor mg-single-node-v2 mg-auth kvstore_dummy_lib)
|
||||
target_link_libraries(${test_prefix}cypher_main_visitor mg-single-node-v2 kvstore_dummy_lib)
|
||||
|
||||
add_unit_test(database_key_index.cpp)
|
||||
target_link_libraries(${test_prefix}database_key_index mg-single-node kvstore_dummy_lib)
|
||||
@@ -52,7 +52,7 @@ add_unit_test(deferred_deleter.cpp)
|
||||
target_link_libraries(${test_prefix}deferred_deleter mg-single-node kvstore_dummy_lib)
|
||||
|
||||
add_unit_test(bfs_single_node.cpp)
|
||||
target_link_libraries(${test_prefix}bfs_single_node mg-single-node-v2 mg-auth kvstore_dummy_lib)
|
||||
target_link_libraries(${test_prefix}bfs_single_node mg-single-node-v2 kvstore_dummy_lib)
|
||||
|
||||
add_unit_test(durability.cpp)
|
||||
target_link_libraries(${test_prefix}durability mg-single-node kvstore_dummy_lib)
|
||||
@@ -73,7 +73,7 @@ add_unit_test(graph_db.cpp)
|
||||
target_link_libraries(${test_prefix}graph_db mg-single-node kvstore_dummy_lib)
|
||||
|
||||
add_unit_test(interpreter.cpp)
|
||||
target_link_libraries(${test_prefix}interpreter mg-single-node-v2 mg-auth kvstore_dummy_lib)
|
||||
target_link_libraries(${test_prefix}interpreter mg-single-node-v2 kvstore_dummy_lib)
|
||||
|
||||
add_unit_test(kvstore.cpp)
|
||||
target_link_libraries(${test_prefix}kvstore kvstore_lib glog)
|
||||
@@ -99,68 +99,62 @@ target_link_libraries(${test_prefix}pod_buffer mg-single-node kvstore_dummy_lib)
|
||||
add_unit_test(property_value_store.cpp)
|
||||
target_link_libraries(${test_prefix}property_value_store kvstore_lib mg-single-node)
|
||||
|
||||
add_unit_test(replication_log.cpp)
|
||||
target_link_libraries(${test_prefix}replication_log mg-single-node-ha kvstore_lib glog)
|
||||
|
||||
add_unit_test(query_cost_estimator.cpp)
|
||||
target_link_libraries(${test_prefix}query_cost_estimator mg-single-node-v2 mg-auth kvstore_dummy_lib)
|
||||
target_link_libraries(${test_prefix}query_cost_estimator mg-single-node-v2 kvstore_dummy_lib)
|
||||
|
||||
add_unit_test(query_expression_evaluator.cpp)
|
||||
target_link_libraries(${test_prefix}query_expression_evaluator mg-single-node-v2 mg-auth kvstore_dummy_lib)
|
||||
target_link_libraries(${test_prefix}query_expression_evaluator mg-single-node-v2 kvstore_dummy_lib)
|
||||
|
||||
add_unit_test(plan_pretty_print.cpp)
|
||||
target_link_libraries(${test_prefix}plan_pretty_print mg-single-node-v2 mg-auth kvstore_dummy_lib)
|
||||
target_link_libraries(${test_prefix}plan_pretty_print mg-single-node-v2 kvstore_dummy_lib)
|
||||
|
||||
add_unit_test(query_dump.cpp)
|
||||
target_link_libraries(${test_prefix}query_dump mg-single-node-v2 mg-auth kvstore_dummy_lib)
|
||||
target_link_libraries(${test_prefix}query_dump mg-single-node-v2 kvstore_dummy_lib)
|
||||
|
||||
add_unit_test(query_pretty_print.cpp)
|
||||
target_link_libraries(${test_prefix}query_pretty_print mg-single-node-v2 mg-auth kvstore_dummy_lib)
|
||||
target_link_libraries(${test_prefix}query_pretty_print mg-single-node-v2 kvstore_dummy_lib)
|
||||
|
||||
add_unit_test(query_profile.cpp)
|
||||
target_link_libraries(${test_prefix}query_profile mg-single-node-v2 mg-auth kvstore_dummy_lib)
|
||||
target_link_libraries(${test_prefix}query_profile mg-single-node-v2 kvstore_dummy_lib)
|
||||
|
||||
add_unit_test(query_plan_accumulate_aggregate.cpp)
|
||||
target_link_libraries(${test_prefix}query_plan_accumulate_aggregate mg-single-node-v2 mg-auth kvstore_dummy_lib)
|
||||
target_link_libraries(${test_prefix}query_plan_accumulate_aggregate mg-single-node-v2 kvstore_dummy_lib)
|
||||
|
||||
add_unit_test(query_plan_bag_semantics.cpp)
|
||||
target_link_libraries(${test_prefix}query_plan_bag_semantics mg-single-node-v2 mg-auth kvstore_dummy_lib)
|
||||
target_link_libraries(${test_prefix}query_plan_bag_semantics mg-single-node-v2 kvstore_dummy_lib)
|
||||
|
||||
add_unit_test(query_plan_create_set_remove_delete.cpp)
|
||||
target_link_libraries(${test_prefix}query_plan_create_set_remove_delete mg-single-node-v2 mg-auth kvstore_dummy_lib)
|
||||
target_link_libraries(${test_prefix}query_plan_create_set_remove_delete mg-single-node-v2 kvstore_dummy_lib)
|
||||
|
||||
# Storage V2 in query execution
|
||||
add_unit_test(query_plan_v2_create_set_remove_delete.cpp)
|
||||
target_link_libraries(${test_prefix}query_plan_v2_create_set_remove_delete mg-single-node-v2 mg-auth kvstore_dummy_lib)
|
||||
target_link_libraries(${test_prefix}query_plan_v2_create_set_remove_delete mg-single-node-v2 kvstore_dummy_lib)
|
||||
# END Storage V2 in query execution
|
||||
|
||||
add_unit_test(query_plan_edge_cases.cpp)
|
||||
target_link_libraries(${test_prefix}query_plan_edge_cases mg-single-node-v2 mg-auth kvstore_dummy_lib)
|
||||
target_link_libraries(${test_prefix}query_plan_edge_cases mg-single-node-v2 kvstore_dummy_lib)
|
||||
|
||||
add_unit_test(query_plan_match_filter_return.cpp)
|
||||
target_link_libraries(${test_prefix}query_plan_match_filter_return mg-single-node-v2 mg-auth kvstore_dummy_lib)
|
||||
target_link_libraries(${test_prefix}query_plan_match_filter_return mg-single-node-v2 kvstore_dummy_lib)
|
||||
|
||||
add_unit_test(query_plan.cpp)
|
||||
target_link_libraries(${test_prefix}query_plan mg-single-node-v2 mg-auth kvstore_dummy_lib)
|
||||
target_link_libraries(${test_prefix}query_plan mg-single-node-v2 kvstore_dummy_lib)
|
||||
|
||||
# Test query/procedure
|
||||
add_unit_test(query_procedure_mgp_type.cpp)
|
||||
target_link_libraries(${test_prefix}query_procedure_mgp_type mg-single-node-v2 mg-auth kvstore_dummy_lib)
|
||||
target_link_libraries(${test_prefix}query_procedure_mgp_type mg-single-node-v2 kvstore_dummy_lib)
|
||||
target_include_directories(${test_prefix}query_procedure_mgp_type PRIVATE ${CMAKE_SOURCE_DIR}/include)
|
||||
|
||||
add_unit_test(query_procedure_mgp_module.cpp)
|
||||
target_link_libraries(${test_prefix}query_procedure_mgp_module mg-single-node-v2 mg-auth kvstore_dummy_lib)
|
||||
target_link_libraries(${test_prefix}query_procedure_mgp_module mg-single-node-v2 kvstore_dummy_lib)
|
||||
target_include_directories(${test_prefix}query_procedure_mgp_module PRIVATE ${CMAKE_SOURCE_DIR}/include)
|
||||
# END query/procedure
|
||||
|
||||
add_unit_test(query_required_privileges.cpp)
|
||||
target_link_libraries(${test_prefix}query_required_privileges mg-single-node-v2 mg-auth kvstore_dummy_lib)
|
||||
|
||||
add_unit_test(query_semantic.cpp)
|
||||
target_link_libraries(${test_prefix}query_semantic mg-single-node-v2 mg-auth kvstore_dummy_lib)
|
||||
target_link_libraries(${test_prefix}query_semantic mg-single-node-v2 kvstore_dummy_lib)
|
||||
|
||||
add_unit_test(query_variable_start_planner.cpp)
|
||||
target_link_libraries(${test_prefix}query_variable_start_planner mg-single-node-v2 mg-auth kvstore_dummy_lib)
|
||||
target_link_libraries(${test_prefix}query_variable_start_planner mg-single-node-v2 kvstore_dummy_lib)
|
||||
|
||||
add_unit_test(queue.cpp)
|
||||
target_link_libraries(${test_prefix}queue mg-single-node kvstore_dummy_lib)
|
||||
@@ -186,16 +180,6 @@ target_link_libraries(${test_prefix}skiplist_reverse_iteration mg-single-node kv
|
||||
add_unit_test(skiplist_suffix.cpp)
|
||||
target_link_libraries(${test_prefix}skiplist_suffix mg-single-node kvstore_dummy_lib)
|
||||
|
||||
# TODO: REPLACE single-node-ha
|
||||
add_unit_test(slk_advanced.cpp)
|
||||
target_link_libraries(${test_prefix}slk_advanced mg-single-node-ha kvstore_dummy_lib)
|
||||
|
||||
add_unit_test(slk_core.cpp)
|
||||
target_link_libraries(${test_prefix}slk_core mg-slk glog gflags fmt)
|
||||
|
||||
add_unit_test(slk_streams.cpp)
|
||||
target_link_libraries(${test_prefix}slk_streams mg-slk glog gflags fmt)
|
||||
|
||||
add_unit_test(small_vector.cpp)
|
||||
target_link_libraries(${test_prefix}small_vector mg-utils)
|
||||
|
||||
@@ -209,13 +193,13 @@ add_unit_test(storage_stat.cpp)
|
||||
target_link_libraries(${test_prefix}storage_stat mg-single-node kvstore_dummy_lib)
|
||||
|
||||
add_unit_test(stripped.cpp)
|
||||
target_link_libraries(${test_prefix}stripped mg-single-node-v2 mg-auth kvstore_dummy_lib)
|
||||
target_link_libraries(${test_prefix}stripped mg-single-node-v2 kvstore_dummy_lib)
|
||||
|
||||
add_unit_test(transaction_engine_single_node.cpp)
|
||||
target_link_libraries(${test_prefix}transaction_engine_single_node mg-single-node kvstore_dummy_lib)
|
||||
|
||||
add_unit_test(typed_value.cpp)
|
||||
target_link_libraries(${test_prefix}typed_value mg-single-node-v2 mg-auth kvstore_dummy_lib)
|
||||
target_link_libraries(${test_prefix}typed_value mg-single-node-v2 kvstore_dummy_lib)
|
||||
|
||||
add_unit_test(unique_constraints.cpp)
|
||||
target_link_libraries(${test_prefix}unique_constraints mg-single-node kvstore_dummy_lib)
|
||||
@@ -240,9 +224,6 @@ target_link_libraries(${test_prefix}communication_buffer mg-communication)
|
||||
add_unit_test(network_timeouts.cpp)
|
||||
target_link_libraries(${test_prefix}network_timeouts mg-communication)
|
||||
|
||||
add_unit_test(rpc.cpp)
|
||||
target_link_libraries(${test_prefix}rpc mg-comm-rpc)
|
||||
|
||||
# Test data structures
|
||||
|
||||
add_unit_test(ring_buffer.cpp)
|
||||
@@ -309,11 +290,6 @@ target_link_libraries(${test_prefix}utils_timestamp mg-utils)
|
||||
add_unit_test(utils_watchdog.cpp)
|
||||
target_link_libraries(${test_prefix}utils_watchdog mg-utils)
|
||||
|
||||
# Test mg-auth
|
||||
|
||||
add_unit_test(auth.cpp)
|
||||
target_link_libraries(${test_prefix}auth mg-auth kvstore_lib)
|
||||
|
||||
# Test storage v2
|
||||
|
||||
add_unit_test(property_value_v2.cpp)
|
||||
|
||||
@@ -50,11 +50,6 @@ class TestSession : public Session<TestInputStream, TestOutputStream> {
|
||||
|
||||
void Abort() override {}
|
||||
|
||||
bool Authenticate(const std::string &username,
|
||||
const std::string &password) override {
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string query_;
|
||||
};
|
||||
|
||||
@@ -2119,230 +2119,6 @@ TEST_P(CypherMainVisitorTest, UnionAll) {
|
||||
ASSERT_FALSE(return_clause->body_.distinct);
|
||||
}
|
||||
|
||||
void check_auth_query(Base *ast_generator, std::string input,
|
||||
AuthQuery::Action action, std::string user,
|
||||
std::string role, std::string user_or_role,
|
||||
std::optional<TypedValue> password,
|
||||
std::vector<AuthQuery::Privilege> privileges) {
|
||||
auto *auth_query =
|
||||
dynamic_cast<AuthQuery *>(ast_generator->ParseQuery(input));
|
||||
ASSERT_TRUE(auth_query);
|
||||
EXPECT_EQ(auth_query->action_, action);
|
||||
EXPECT_EQ(auth_query->user_, user);
|
||||
EXPECT_EQ(auth_query->role_, role);
|
||||
EXPECT_EQ(auth_query->user_or_role_, user_or_role);
|
||||
ASSERT_EQ(static_cast<bool>(auth_query->password_),
|
||||
static_cast<bool>(password));
|
||||
if (password) {
|
||||
ast_generator->CheckLiteral(auth_query->password_, *password);
|
||||
}
|
||||
EXPECT_EQ(auth_query->privileges_, privileges);
|
||||
}
|
||||
|
||||
TEST_P(CypherMainVisitorTest, UserOrRoleName) {
|
||||
auto &ast_generator = *GetParam();
|
||||
ASSERT_THROW(ast_generator.ParseQuery("CREATE ROLE `us|er`"),
|
||||
SyntaxException);
|
||||
ASSERT_THROW(ast_generator.ParseQuery("CREATE ROLE `us er`"),
|
||||
SyntaxException);
|
||||
check_auth_query(&ast_generator, "CREATE ROLE `user`",
|
||||
AuthQuery::Action::CREATE_ROLE, "", "user", "", {}, {});
|
||||
check_auth_query(&ast_generator, "CREATE ROLE us___er",
|
||||
AuthQuery::Action::CREATE_ROLE, "", "us___er", "", {}, {});
|
||||
check_auth_query(&ast_generator, "CREATE ROLE `us+er`",
|
||||
AuthQuery::Action::CREATE_ROLE, "", "us+er", "", {}, {});
|
||||
}
|
||||
|
||||
TEST_P(CypherMainVisitorTest, CreateRole) {
|
||||
auto &ast_generator = *GetParam();
|
||||
ASSERT_THROW(ast_generator.ParseQuery("CREATE ROLE"), SyntaxException);
|
||||
check_auth_query(&ast_generator, "CREATE ROLE rola",
|
||||
AuthQuery::Action::CREATE_ROLE, "", "rola", "", {}, {});
|
||||
ASSERT_THROW(ast_generator.ParseQuery("CREATE ROLE lagano rolamo"),
|
||||
SyntaxException);
|
||||
}
|
||||
|
||||
TEST_P(CypherMainVisitorTest, DropRole) {
|
||||
auto &ast_generator = *GetParam();
|
||||
ASSERT_THROW(ast_generator.ParseQuery("DROP ROLE"), SyntaxException);
|
||||
check_auth_query(&ast_generator, "DROP ROLE rola",
|
||||
AuthQuery::Action::DROP_ROLE, "", "rola", "", {}, {});
|
||||
ASSERT_THROW(ast_generator.ParseQuery("DROP ROLE lagano rolamo"),
|
||||
SyntaxException);
|
||||
}
|
||||
|
||||
TEST_P(CypherMainVisitorTest, ShowRoles) {
|
||||
auto &ast_generator = *GetParam();
|
||||
ASSERT_THROW(ast_generator.ParseQuery("SHOW ROLES ROLES"), SyntaxException);
|
||||
check_auth_query(&ast_generator, "SHOW ROLES", AuthQuery::Action::SHOW_ROLES,
|
||||
"", "", "", {}, {});
|
||||
}
|
||||
|
||||
TEST_P(CypherMainVisitorTest, CreateUser) {
|
||||
auto &ast_generator = *GetParam();
|
||||
ASSERT_THROW(ast_generator.ParseQuery("CREATE USER"), SyntaxException);
|
||||
ASSERT_THROW(ast_generator.ParseQuery("CREATE USER 123"), SyntaxException);
|
||||
check_auth_query(&ast_generator, "CREATE USER user",
|
||||
AuthQuery::Action::CREATE_USER, "user", "", "", {}, {});
|
||||
check_auth_query(&ast_generator, "CREATE USER user IDENTIFIED BY 'password'",
|
||||
AuthQuery::Action::CREATE_USER, "user", "", "",
|
||||
TypedValue("password"), {});
|
||||
check_auth_query(&ast_generator, "CREATE USER user IDENTIFIED BY ''",
|
||||
AuthQuery::Action::CREATE_USER, "user", "", "",
|
||||
TypedValue(""), {});
|
||||
check_auth_query(&ast_generator, "CREATE USER user IDENTIFIED BY null",
|
||||
AuthQuery::Action::CREATE_USER, "user", "", "", TypedValue(),
|
||||
{});
|
||||
ASSERT_THROW(
|
||||
ast_generator.ParseQuery("CRATE USER user IDENTIFIED BY password"),
|
||||
SyntaxException);
|
||||
ASSERT_THROW(ast_generator.ParseQuery("CREATE USER user IDENTIFIED BY 5"),
|
||||
SyntaxException);
|
||||
ASSERT_THROW(ast_generator.ParseQuery("CREATE USER user IDENTIFIED BY "),
|
||||
SyntaxException);
|
||||
}
|
||||
|
||||
TEST_P(CypherMainVisitorTest, SetPassword) {
|
||||
auto &ast_generator = *GetParam();
|
||||
ASSERT_THROW(ast_generator.ParseQuery("SET PASSWORD FOR"), SyntaxException);
|
||||
ASSERT_THROW(ast_generator.ParseQuery("SET PASSWORD FOR user "),
|
||||
SyntaxException);
|
||||
check_auth_query(&ast_generator, "SET PASSWORD FOR user TO null",
|
||||
AuthQuery::Action::SET_PASSWORD, "user", "", "",
|
||||
TypedValue(), {});
|
||||
check_auth_query(&ast_generator, "SET PASSWORD FOR user TO 'password'",
|
||||
AuthQuery::Action::SET_PASSWORD, "user", "", "",
|
||||
TypedValue("password"), {});
|
||||
ASSERT_THROW(ast_generator.ParseQuery("SET PASSWORD FOR user To 5"),
|
||||
SyntaxException);
|
||||
}
|
||||
|
||||
TEST_P(CypherMainVisitorTest, DropUser) {
|
||||
auto &ast_generator = *GetParam();
|
||||
ASSERT_THROW(ast_generator.ParseQuery("DROP USER"), SyntaxException);
|
||||
check_auth_query(&ast_generator, "DROP USER user",
|
||||
AuthQuery::Action::DROP_USER, "user", "", "", {}, {});
|
||||
ASSERT_THROW(ast_generator.ParseQuery("DROP USER lagano rolamo"),
|
||||
SyntaxException);
|
||||
}
|
||||
|
||||
TEST_P(CypherMainVisitorTest, ShowUsers) {
|
||||
auto &ast_generator = *GetParam();
|
||||
ASSERT_THROW(ast_generator.ParseQuery("SHOW USERS ROLES"), SyntaxException);
|
||||
check_auth_query(&ast_generator, "SHOW USERS", AuthQuery::Action::SHOW_USERS,
|
||||
"", "", "", {}, {});
|
||||
}
|
||||
|
||||
TEST_P(CypherMainVisitorTest, SetRole) {
|
||||
auto &ast_generator = *GetParam();
|
||||
ASSERT_THROW(ast_generator.ParseQuery("SET ROLE"), SyntaxException);
|
||||
ASSERT_THROW(ast_generator.ParseQuery("SET ROLE user"), SyntaxException);
|
||||
ASSERT_THROW(ast_generator.ParseQuery("SET ROLE FOR user"), SyntaxException);
|
||||
ASSERT_THROW(ast_generator.ParseQuery("SET ROLE FOR user TO"),
|
||||
SyntaxException);
|
||||
check_auth_query(&ast_generator, "SET ROLE FOR user TO role",
|
||||
AuthQuery::Action::SET_ROLE, "user", "role", "", {}, {});
|
||||
check_auth_query(&ast_generator, "SET ROLE FOR user TO null",
|
||||
AuthQuery::Action::SET_ROLE, "user", "null", "", {}, {});
|
||||
}
|
||||
|
||||
TEST_P(CypherMainVisitorTest, ClearRole) {
|
||||
auto &ast_generator = *GetParam();
|
||||
ASSERT_THROW(ast_generator.ParseQuery("CLEAR ROLE"), SyntaxException);
|
||||
ASSERT_THROW(ast_generator.ParseQuery("CLEAR ROLE user"), SyntaxException);
|
||||
ASSERT_THROW(ast_generator.ParseQuery("CLEAR ROLE FOR user TO"),
|
||||
SyntaxException);
|
||||
check_auth_query(&ast_generator, "CLEAR ROLE FOR user",
|
||||
AuthQuery::Action::CLEAR_ROLE, "user", "", "", {}, {});
|
||||
}
|
||||
|
||||
TEST_P(CypherMainVisitorTest, GrantPrivilege) {
|
||||
auto &ast_generator = *GetParam();
|
||||
ASSERT_THROW(ast_generator.ParseQuery("GRANT"), SyntaxException);
|
||||
ASSERT_THROW(ast_generator.ParseQuery("GRANT TO user"), SyntaxException);
|
||||
ASSERT_THROW(ast_generator.ParseQuery("GRANT BLABLA TO user"),
|
||||
SyntaxException);
|
||||
ASSERT_THROW(ast_generator.ParseQuery("GRANT MATCH, TO user"),
|
||||
SyntaxException);
|
||||
ASSERT_THROW(ast_generator.ParseQuery("GRANT MATCH, BLABLA TO user"),
|
||||
SyntaxException);
|
||||
check_auth_query(&ast_generator, "GRANT MATCH TO user",
|
||||
AuthQuery::Action::GRANT_PRIVILEGE, "", "", "user", {},
|
||||
{AuthQuery::Privilege::MATCH});
|
||||
check_auth_query(&ast_generator, "GRANT MATCH, AUTH TO user",
|
||||
AuthQuery::Action::GRANT_PRIVILEGE, "", "", "user", {},
|
||||
{AuthQuery::Privilege::MATCH, AuthQuery::Privilege::AUTH});
|
||||
}
|
||||
|
||||
TEST_P(CypherMainVisitorTest, DenyPrivilege) {
|
||||
auto &ast_generator = *GetParam();
|
||||
ASSERT_THROW(ast_generator.ParseQuery("DENY"), SyntaxException);
|
||||
ASSERT_THROW(ast_generator.ParseQuery("DENY TO user"), SyntaxException);
|
||||
ASSERT_THROW(ast_generator.ParseQuery("DENY BLABLA TO user"),
|
||||
SyntaxException);
|
||||
ASSERT_THROW(ast_generator.ParseQuery("DENY MATCH, TO user"),
|
||||
SyntaxException);
|
||||
ASSERT_THROW(ast_generator.ParseQuery("DENY MATCH, BLABLA TO user"),
|
||||
SyntaxException);
|
||||
check_auth_query(&ast_generator, "DENY MATCH TO user",
|
||||
AuthQuery::Action::DENY_PRIVILEGE, "", "", "user", {},
|
||||
{AuthQuery::Privilege::MATCH});
|
||||
check_auth_query(&ast_generator, "DENY MATCH, AUTH TO user",
|
||||
AuthQuery::Action::DENY_PRIVILEGE, "", "", "user", {},
|
||||
{AuthQuery::Privilege::MATCH, AuthQuery::Privilege::AUTH});
|
||||
}
|
||||
|
||||
TEST_P(CypherMainVisitorTest, RevokePrivilege) {
|
||||
auto &ast_generator = *GetParam();
|
||||
ASSERT_THROW(ast_generator.ParseQuery("REVOKE"), SyntaxException);
|
||||
ASSERT_THROW(ast_generator.ParseQuery("REVOKE FROM user"), SyntaxException);
|
||||
ASSERT_THROW(ast_generator.ParseQuery("REVOKE BLABLA FROM user"),
|
||||
SyntaxException);
|
||||
ASSERT_THROW(ast_generator.ParseQuery("REVOKE MATCH, FROM user"),
|
||||
SyntaxException);
|
||||
ASSERT_THROW(ast_generator.ParseQuery("REVOKE MATCH, BLABLA FROM user"),
|
||||
SyntaxException);
|
||||
check_auth_query(&ast_generator, "REVOKE MATCH FROM user",
|
||||
AuthQuery::Action::REVOKE_PRIVILEGE, "", "", "user", {},
|
||||
{AuthQuery::Privilege::MATCH});
|
||||
check_auth_query(&ast_generator, "REVOKE MATCH, AUTH FROM user",
|
||||
AuthQuery::Action::REVOKE_PRIVILEGE, "", "", "user", {},
|
||||
{AuthQuery::Privilege::MATCH, AuthQuery::Privilege::AUTH});
|
||||
check_auth_query(&ast_generator, "REVOKE ALL PRIVILEGES FROM user",
|
||||
AuthQuery::Action::REVOKE_PRIVILEGE, "", "", "user", {},
|
||||
kPrivilegesAll);
|
||||
}
|
||||
|
||||
TEST_P(CypherMainVisitorTest, ShowPrivileges) {
|
||||
auto &ast_generator = *GetParam();
|
||||
ASSERT_THROW(ast_generator.ParseQuery("SHOW PRIVILEGES FOR"),
|
||||
SyntaxException);
|
||||
check_auth_query(&ast_generator, "SHOW PRIVILEGES FOR user",
|
||||
AuthQuery::Action::SHOW_PRIVILEGES, "", "", "user", {}, {});
|
||||
ASSERT_THROW(ast_generator.ParseQuery("SHOW PRIVILEGES FOR user1, user2"),
|
||||
SyntaxException);
|
||||
}
|
||||
|
||||
TEST_P(CypherMainVisitorTest, ShowRoleForUser) {
|
||||
auto &ast_generator = *GetParam();
|
||||
ASSERT_THROW(ast_generator.ParseQuery("SHOW ROLE FOR "), SyntaxException);
|
||||
check_auth_query(&ast_generator, "SHOW ROLE FOR user",
|
||||
AuthQuery::Action::SHOW_ROLE_FOR_USER, "user", "", "", {},
|
||||
{});
|
||||
ASSERT_THROW(ast_generator.ParseQuery("SHOW ROLE FOR user1, user2"),
|
||||
SyntaxException);
|
||||
}
|
||||
|
||||
TEST_P(CypherMainVisitorTest, ShowUsersForRole) {
|
||||
auto &ast_generator = *GetParam();
|
||||
ASSERT_THROW(ast_generator.ParseQuery("SHOW USERS FOR "), SyntaxException);
|
||||
check_auth_query(&ast_generator, "SHOW USERS FOR role",
|
||||
AuthQuery::Action::SHOW_USERS_FOR_ROLE, "", "role", "", {},
|
||||
{});
|
||||
ASSERT_THROW(ast_generator.ParseQuery("SHOW USERS FOR role1, role2"),
|
||||
SyntaxException);
|
||||
}
|
||||
|
||||
TEST_P(CypherMainVisitorTest, TestExplainRegularQuery) {
|
||||
auto &ast_generator = *GetParam();
|
||||
EXPECT_TRUE(dynamic_cast<ExplainQuery *>(
|
||||
|
||||
@@ -40,7 +40,7 @@ class InterpreterTest : public ::testing::Test {
|
||||
const std::map<std::string, PropertyValue> ¶ms = {}) {
|
||||
ResultStreamFaker stream(&db_);
|
||||
|
||||
auto [header, _] = interpreter_.Prepare(query, params);
|
||||
auto header = interpreter_.Prepare(query, params);
|
||||
stream.Header(header);
|
||||
auto summary = interpreter_.PullAll(&stream);
|
||||
stream.Summary(summary);
|
||||
|
||||
@@ -184,7 +184,7 @@ auto Execute(storage::Storage *db, const std::string &query) {
|
||||
query::Interpreter interpreter(&context);
|
||||
ResultStreamFaker stream(db);
|
||||
|
||||
auto [header, _] = interpreter.Prepare(query, {});
|
||||
auto header = interpreter.Prepare(query, {});
|
||||
stream.Header(header);
|
||||
auto summary = interpreter.PullAll(&stream);
|
||||
stream.Summary(summary);
|
||||
|
||||
@@ -39,7 +39,7 @@ class QueryExecution : public testing::Test {
|
||||
auto Execute(const std::string &query) {
|
||||
ResultStreamFaker stream(&*db_);
|
||||
|
||||
auto [header, _] = interpreter_->Prepare(query, {});
|
||||
auto header = interpreter_->Prepare(query, {});
|
||||
stream.Header(header);
|
||||
auto summary = interpreter_->PullAll(&stream);
|
||||
stream.Summary(summary);
|
||||
|
||||
@@ -15,11 +15,6 @@ if (READLINE_FOUND)
|
||||
endif()
|
||||
target_link_libraries(mg_client ${CLIENT_LIBS})
|
||||
|
||||
# Memgraph Dump Target
|
||||
add_executable(mg_dump mg_dump/main.cpp)
|
||||
target_include_directories(mg_dump PRIVATE ${MGCLIENT_INCLUDE_DIR})
|
||||
target_link_libraries(mg_dump fmt gflags glog mgclient pthread)
|
||||
|
||||
# Strip the executable in release build.
|
||||
string(TOLOWER ${CMAKE_BUILD_TYPE} lower_build_type)
|
||||
if (lower_build_type STREQUAL "release")
|
||||
@@ -37,4 +32,4 @@ endif()
|
||||
install(TARGETS mg_client RUNTIME DESTINATION bin)
|
||||
|
||||
# Target for building all the tool executables.
|
||||
add_custom_target(tools DEPENDS mg_import_csv mg_client mg_dump)
|
||||
add_custom_target(tools DEPENDS mg_import_csv mg_client)
|
||||
|
||||
Reference in New Issue
Block a user