diff --git a/src/auth/models.cpp b/src/auth/models.cpp index 7dacce891..9f816304d 100644 --- a/src/auth/models.cpp +++ b/src/auth/models.cpp @@ -36,12 +36,14 @@ std::string PermissionToString(Permission permission) { return "INDEX"; case Permission::STATS: return "STATS"; + case Permission::CONSTRAINT: + return "CONSTRAINT"; + case Permission::DUMP: + return "DUMP"; case Permission::AUTH: return "AUTH"; case Permission::STREAM: return "STREAM"; - case Permission::CONSTRAINT: - return "CONSTRAINT"; } } diff --git a/src/auth/models.hpp b/src/auth/models.hpp index 9740a94c5..b8e43a69d 100644 --- a/src/auth/models.hpp +++ b/src/auth/models.hpp @@ -19,6 +19,7 @@ enum class Permission : uint64_t { INDEX = 0x00000040, STATS = 0x00000080, CONSTRAINT = 0x00000100, + DUMP = 0x00000200, AUTH = 0x00010000, STREAM = 0x00020000, }; @@ -27,8 +28,8 @@ enum class Permission : uint64_t { const std::vector<Permission> kPermissionsAll = { Permission::MATCH, Permission::CREATE, Permission::MERGE, Permission::DELETE, Permission::SET, Permission::REMOVE, - Permission::INDEX, Permission::STATS, Permission::AUTH, - Permission::STREAM}; + Permission::INDEX, Permission::STATS, Permission::CONSTRAINT, + Permission::DUMP, Permission::AUTH, Permission::STREAM}; // Function that converts a permission to its string representation. std::string PermissionToString(Permission permission); diff --git a/src/glue/auth.cpp b/src/glue/auth.cpp index 9d42ae925..8984a8c0c 100644 --- a/src/glue/auth.cpp +++ b/src/glue/auth.cpp @@ -20,13 +20,14 @@ auth::Permission PrivilegeToPermission(query::AuthQuery::Privilege privilege) { return auth::Permission::INDEX; case query::AuthQuery::Privilege::STATS: return auth::Permission::STATS; + case query::AuthQuery::Privilege::CONSTRAINT: + return auth::Permission::CONSTRAINT; + case query::AuthQuery::Privilege::DUMP: + return auth::Permission::DUMP; case query::AuthQuery::Privilege::AUTH: return auth::Permission::AUTH; case query::AuthQuery::Privilege::STREAM: return auth::Permission::STREAM; - case query::AuthQuery::Privilege::CONSTRAINT: - return auth::Permission::CONSTRAINT; } } - } diff --git a/src/query/frontend/ast/ast.lcp b/src/query/frontend/ast/ast.lcp index 621025ae9..f684cf855 100644 --- a/src/query/frontend/ast/ast.lcp +++ b/src/query/frontend/ast/ast.lcp @@ -2064,7 +2064,8 @@ cpp<# show-users-for-role) (:serialize)) (lcp:define-enum privilege - (create delete match merge set remove index stats auth stream constraint) + (create delete match merge set remove index stats auth stream constraint + dump) (:serialize)) #>cpp AuthQuery() = default; @@ -2094,12 +2095,12 @@ cpp<# #>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::STREAM, - AuthQuery::Privilege::CONSTRAINT}; + 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::STREAM, + AuthQuery::Privilege::CONSTRAINT, AuthQuery::Privilege::DUMP}; cpp<# (lcp:define-class stream-query (query) @@ -2215,4 +2216,12 @@ cpp<# (:serialize (:slk)) (:clone)) +(lcp:define-class dump-query (query) () + (:public + #>cpp + DEFVISITABLE(QueryVisitor<void>); + cpp<#) + (:serialize (:slk)) + (:clone)) + (lcp:pop-namespace) ;; namespace query diff --git a/src/query/frontend/ast/ast_visitor.hpp b/src/query/frontend/ast/ast_visitor.hpp index c63a55871..c48e0c537 100644 --- a/src/query/frontend/ast/ast_visitor.hpp +++ b/src/query/frontend/ast/ast_visitor.hpp @@ -69,6 +69,7 @@ class StreamQuery; class InfoQuery; class ConstraintQuery; class RegexMatch; +class DumpQuery; using TreeCompositeVisitor = ::utils::CompositeVisitor< SingleQuery, CypherUnion, NamedExpression, OrOperator, XorOperator, @@ -113,6 +114,6 @@ template <class TResult> class QueryVisitor : public ::utils::Visitor<TResult, CypherQuery, ExplainQuery, ProfileQuery, IndexQuery, AuthQuery, StreamQuery, InfoQuery, - ConstraintQuery> {}; + ConstraintQuery, DumpQuery> {}; } // namespace query diff --git a/src/query/frontend/ast/cypher_main_visitor.cpp b/src/query/frontend/ast/cypher_main_visitor.cpp index de409be24..ea68de1c6 100644 --- a/src/query/frontend/ast/cypher_main_visitor.cpp +++ b/src/query/frontend/ast/cypher_main_visitor.cpp @@ -187,6 +187,13 @@ antlrcpp::Any CypherMainVisitor::visitStreamQuery( return stream_query; } +antlrcpp::Any CypherMainVisitor::visitDumpQuery( + MemgraphCypher::DumpQueryContext *ctx) { + auto *dump_query = storage_->Create<DumpQuery>(); + query_ = dump_query; + return dump_query; +} + antlrcpp::Any CypherMainVisitor::visitCypherUnion( MemgraphCypher::CypherUnionContext *ctx) { bool distinct = !ctx->ALL(); diff --git a/src/query/frontend/ast/cypher_main_visitor.hpp b/src/query/frontend/ast/cypher_main_visitor.hpp index 3194f5b02..f9851bd9e 100644 --- a/src/query/frontend/ast/cypher_main_visitor.hpp +++ b/src/query/frontend/ast/cypher_main_visitor.hpp @@ -187,6 +187,11 @@ class CypherMainVisitor : public antlropencypher::MemgraphCypherBaseVisitor { antlrcpp::Any visitStreamQuery( MemgraphCypher::StreamQueryContext *ctx) override; + /** + * @return DumpQuery* + */ + antlrcpp::Any visitDumpQuery(MemgraphCypher::DumpQueryContext *ctx) override; + /** * @return CypherUnion* */ diff --git a/src/query/frontend/opencypher/grammar/MemgraphCypher.g4 b/src/query/frontend/opencypher/grammar/MemgraphCypher.g4 index dc331205f..0a8300f81 100644 --- a/src/query/frontend/opencypher/grammar/MemgraphCypher.g4 +++ b/src/query/frontend/opencypher/grammar/MemgraphCypher.g4 @@ -13,8 +13,10 @@ memgraphCypherKeyword : cypherKeyword | BATCHES | CLEAR | DATA + | DATABASE | DENY | DROP + | DUMP | FOR | FROM | GRANT @@ -54,6 +56,7 @@ query : cypherQuery | constraintQuery | authQuery | streamQuery + | dumpQuery ; authQuery : createRole @@ -101,7 +104,7 @@ denyPrivilege : DENY ( ALL PRIVILEGES | privileges=privilegeList ) TO userOrRole revokePrivilege : REVOKE ( ALL PRIVILEGES | privileges=privilegeList ) FROM userOrRole=userOrRoleName ; privilege : CREATE | DELETE | MATCH | MERGE | SET - | REMOVE | INDEX | STATS | AUTH | STREAM | CONSTRAINT ; + | REMOVE | INDEX | STATS | AUTH | STREAM | CONSTRAINT | DUMP ; privilegeList : privilege ( ',' privilege )* ; @@ -146,3 +149,5 @@ startAllStreams : START ALL STREAMS ; stopAllStreams : STOP ALL STREAMS ; testStream : K_TEST STREAM streamName ( limitBatchesOption )? ; + +dumpQuery: DUMP DATABASE ; diff --git a/src/query/frontend/opencypher/grammar/MemgraphCypherLexer.g4 b/src/query/frontend/opencypher/grammar/MemgraphCypherLexer.g4 index b87668cd3..354087030 100644 --- a/src/query/frontend/opencypher/grammar/MemgraphCypherLexer.g4 +++ b/src/query/frontend/opencypher/grammar/MemgraphCypherLexer.g4 @@ -16,8 +16,10 @@ BATCH : B A T C H ; BATCHES : B A T C H E S ; CLEAR : C L E A R ; DATA : D A T A ; +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 ; diff --git a/src/query/frontend/semantic/required_privileges.cpp b/src/query/frontend/semantic/required_privileges.cpp index 524ef6d9b..bb750c5a6 100644 --- a/src/query/frontend/semantic/required_privileges.cpp +++ b/src/query/frontend/semantic/required_privileges.cpp @@ -64,6 +64,10 @@ class PrivilegeExtractor : public QueryVisitor<void>, } } + void Visit(DumpQuery &dump_query) override { + AddPrivilege(AuthQuery::Privilege::DUMP); + } + bool PreVisit(Create &) override { AddPrivilege(AuthQuery::Privilege::CREATE); return false; diff --git a/src/query/frontend/stripped_lexer_constants.hpp b/src/query/frontend/stripped_lexer_constants.hpp index 7d2bddfd9..de477051f 100644 --- a/src/query/frontend/stripped_lexer_constants.hpp +++ b/src/query/frontend/stripped_lexer_constants.hpp @@ -92,7 +92,7 @@ const trie::Trie kKeywords = { "batch", "interval", "show", "start", "stats", "stop", "size", "topic", "test", "unique", "explain", "profile", "storage", "index", "info", "exists", "assert", "constraint", - "node", "key"}; + "node", "key", "dump", "database"}; // Unicode codepoints that are allowed at the start of the unescaped name. const std::bitset<kBitsetSize> kUnescapedNameAllowedStarts(std::string( diff --git a/src/query/interpreter.cpp b/src/query/interpreter.cpp index f066de9f0..8186fa43c 100644 --- a/src/query/interpreter.cpp +++ b/src/query/interpreter.cpp @@ -726,6 +726,10 @@ Callback HandleConstraintQuery(ConstraintQuery *constraint_query, #endif } +Callback HandleDumpQuery(database::GraphDbAccessor *db_accessor) { + throw utils::NotYetImplemented("Dump database"); +} + Interpreter::Interpreter() : is_tsc_available_(utils::CheckAvailableTSC()) {} Interpreter::Results Interpreter::operator()( @@ -988,6 +992,9 @@ Interpreter::Results Interpreter::operator()( } else if (auto *constraint_query = utils::Downcast<ConstraintQuery>(parsed_query.query)) { callback = HandleConstraintQuery(constraint_query, &db_accessor); + } else if (auto *dump_query = + utils::Downcast<DumpQuery>(parsed_query.query)) { + callback = HandleDumpQuery(&db_accessor); } else { LOG(FATAL) << "Should not get here -- unknown query type!"; } diff --git a/tests/unit/cypher_main_visitor.cpp b/tests/unit/cypher_main_visitor.cpp index c08a40c06..3156296ee 100644 --- a/tests/unit/cypher_main_visitor.cpp +++ b/tests/unit/cypher_main_visitor.cpp @@ -2911,4 +2911,12 @@ TEST_P(CypherMainVisitorTest, RegexMatch) { } } +// NOLINTNEXTLINE(hicpp-special-member-functions) +TEST_P(CypherMainVisitorTest, DumpDatabase) { + auto &ast_generator = *GetParam(); + auto *query = + dynamic_cast<DumpQuery *>(ast_generator.ParseQuery("DUMP DATABASE")); + ASSERT_TRUE(query); +} + } // namespace diff --git a/tests/unit/query_required_privileges.cpp b/tests/unit/query_required_privileges.cpp index 9be5ae9f0..414661b16 100644 --- a/tests/unit/query_required_privileges.cpp +++ b/tests/unit/query_required_privileges.cpp @@ -173,3 +173,10 @@ TEST_F(TestPrivilegeExtractor, DropConstraint) { EXPECT_THAT(GetRequiredPrivileges(query), UnorderedElementsAre(AuthQuery::Privilege::CONSTRAINT)); } + +// NOLINTNEXTLINE(hicpp-special-member-functions) +TEST_F(TestPrivilegeExtractor, DumpDatabase) { + auto *query = storage.Create<DumpQuery>(); + EXPECT_THAT(GetRequiredPrivileges(query), + UnorderedElementsAre(AuthQuery::Privilege::DUMP)); +}