diff --git a/src/memgraph.cpp b/src/memgraph.cpp index 6bee0e2fd..fb6990a34 100644 --- a/src/memgraph.cpp +++ b/src/memgraph.cpp @@ -885,6 +885,20 @@ class AuthChecker final : public memgraph::query::AuthChecker { return maybe_user.has_value() && IsUserAuthorized(*maybe_user, privileges); } + bool IsUserAuthorizedLabels(const memgraph::auth::User *user, const memgraph::query::DbAccessor *dba, + const std::vector &labels) const final { + return std::any_of(labels.begin(), labels.end(), [dba, user](const auto label) { + return user->GetFineGrainedAccessLabelPermissions().Has(dba->LabelToName(label)) == + memgraph::auth::PermissionLevel::GRANT; + }); + } + + bool IsUserAuthorizedEdgeType(const memgraph::auth::User *user, const memgraph::query::DbAccessor *dba, + const memgraph::storage::EdgeTypeId &edgeType) const final { + return user->GetFineGrainedAccessEdgeTypePermissions().Has(dba->EdgeTypeToName(edgeType)) == + memgraph::auth::PermissionLevel::GRANT; + } + private: memgraph::utils::Synchronized *auth_; }; diff --git a/src/query/auth_checker.hpp b/src/query/auth_checker.hpp index a0ff8a2a8..4d8c9a2b3 100644 --- a/src/query/auth_checker.hpp +++ b/src/query/auth_checker.hpp @@ -11,13 +11,19 @@ #pragma once +#include "auth/models.hpp" #include "query/frontend/ast/ast.hpp" - namespace memgraph::query { class AuthChecker { public: virtual bool IsUserAuthorized(const std::optional &username, const std::vector &privileges) const = 0; + + virtual bool IsUserAuthorizedLabels(const memgraph::auth::User *user, const memgraph::query::DbAccessor *dba, + const std::vector &labels) const = 0; + + virtual bool IsUserAuthorizedEdgeType(const memgraph::auth::User *user, const memgraph::query::DbAccessor *dba, + const memgraph::storage::EdgeTypeId &edgeType) const = 0; }; class AllowEverythingAuthChecker final : public query::AuthChecker { @@ -25,5 +31,14 @@ class AllowEverythingAuthChecker final : public query::AuthChecker { const std::vector &privileges) const override { return true; } + bool IsUserAuthorizedLabels(const memgraph::auth::User *user, const memgraph::query::DbAccessor *dba, + const std::vector &labels) const override { + return true; + }; + + bool IsUserAuthorizedEdgeType(const memgraph::auth::User *user, const memgraph::query::DbAccessor *dba, + const memgraph::storage::EdgeTypeId &edgeType) const override { + return true; + }; }; -} // namespace memgraph::query \ No newline at end of file +} // namespace memgraph::query diff --git a/src/query/context.hpp b/src/query/context.hpp index 0be220dfb..92465c227 100644 --- a/src/query/context.hpp +++ b/src/query/context.hpp @@ -14,7 +14,6 @@ #include #include "query/common.hpp" -#include "query/fine_grained_access_checker.hpp" #include "query/frontend/semantic/symbol_table.hpp" #include "query/metadata.hpp" #include "query/parameters.hpp" @@ -73,7 +72,8 @@ struct ExecutionContext { ExecutionStats execution_stats; TriggerContextCollector *trigger_context_collector{nullptr}; utils::AsyncTimer timer; - FineGrainedAccessChecker *fine_grained_access_checker{nullptr}; + AuthChecker *auth_checker{nullptr}; + memgraph::auth::User *user{nullptr}; }; static_assert(std::is_move_assignable_v, "ExecutionContext must be move assignable!"); diff --git a/src/query/fine_grained_access_checker.hpp b/src/query/fine_grained_access_checker.hpp deleted file mode 100644 index f428846d2..000000000 --- a/src/query/fine_grained_access_checker.hpp +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2022 Memgraph Ltd. -// -// Use of this software is governed by the Business Source License -// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source -// License, and you may not use this file except in compliance with the Business Source License. -// -// As of the Change Date specified in that file, in accordance with -// the Business Source License, use of this software will be governed -// by the Apache License, Version 2.0, included in the file -// licenses/APL.txt. - -#pragma once - -#include "query/db_accessor.hpp" -#include "storage/v2/id_types.hpp" - -namespace memgraph::query { -class FineGrainedAccessChecker { - public: - virtual bool Accept(const VertexAccessor &vertex) = 0; - - virtual bool Accept(const EdgeAccessor &edge) = 0; - - private: - virtual bool IsUserAuthorizedLabels(const std::vector &labels) const = 0; - - virtual bool IsUserAuthorizedEdgeType(const memgraph::storage::EdgeTypeId &edgeType) const = 0; -}; -} // namespace memgraph::query diff --git a/src/query/interpreter.cpp b/src/query/interpreter.cpp index 3afe6489f..2a5561d31 100644 --- a/src/query/interpreter.cpp +++ b/src/query/interpreter.cpp @@ -29,7 +29,6 @@ #include "query/db_accessor.hpp" #include "query/dump.hpp" #include "query/exceptions.hpp" -#include "query/fine_grained_access_checker.hpp" #include "query/frontend/ast/ast.hpp" #include "query/frontend/ast/ast_visitor.hpp" #include "query/frontend/ast/cypher_main_visitor.hpp" @@ -262,33 +261,6 @@ class ReplQueryHandler final : public query::ReplicationQueryHandler { storage::Storage *db_; }; -class FineGrainedAccessChecker final : public memgraph::query::FineGrainedAccessChecker { - public: - explicit FineGrainedAccessChecker(memgraph::auth::User *user, DbAccessor *dba) : user_{user}, dba_{dba} {} - - bool Accept(const VertexAccessor &vertex) { - return IsUserAuthorizedLabels(vertex.Labels(memgraph::storage::View::NEW).GetValue()); - } - - bool Accept(const EdgeAccessor &edge) { return IsUserAuthorizedEdgeType(edge.EdgeType()); } - - private: - bool IsUserAuthorizedLabels(const std::vector &labels) const final { - return std::any_of(labels.begin(), labels.end(), [this](const auto label) { - return user_->GetFineGrainedAccessLabelPermissions().Has(dba_->LabelToName(label)) == - memgraph::auth::PermissionLevel::GRANT; - }); - } - - bool IsUserAuthorizedEdgeType(const memgraph::storage::EdgeTypeId &edgeType) const final { - return user_->GetFineGrainedAccessEdgeTypePermissions().Has(dba_->EdgeTypeToName(edgeType)) == - memgraph::auth::PermissionLevel::GRANT; - } - - memgraph::auth::User *user_; - DbAccessor *dba_; -}; - /// returns false if the replication role can't be set /// @throw QueryRuntimeException if an error ocurred. @@ -974,8 +946,8 @@ PullPlan::PullPlan(const std::shared_ptr plan, const Parameters &par ctx_.evaluation_context.labels = NamesToLabels(plan->ast_storage().labels_, dba); #ifdef MG_ENTERPRISE if (username.has_value()) { - memgraph::auth::User *user = interpreter_context->auth->GetUser(*username); - ctx_.fine_grained_access_checker = new FineGrainedAccessChecker{user, dba}; + ctx_.user = interpreter_context->auth->GetUser(*username); + ctx_.auth_checker = interpreter_context->auth_checker; } #endif if (interpreter_context->config.execution_timeout_sec > 0) { diff --git a/src/query/plan/operator.cpp b/src/query/plan/operator.cpp index 3a5a6412f..c6d9ae334 100644 --- a/src/query/plan/operator.cpp +++ b/src/query/plan/operator.cpp @@ -683,7 +683,9 @@ bool Expand::ExpandCursor::Pull(Frame &frame, ExecutionContext &context) { // attempt to get a value from the incoming edges if (in_edges_ && *in_edges_it_ != in_edges_->end()) { auto edge = *(*in_edges_it_)++; - if (context.fine_grained_access_checker && !context.fine_grained_access_checker->Accept(edge)) continue; + if (context.auth_checker && + !context.auth_checker->IsUserAuthorizedEdgeType(context.user, context.db_accessor, edge.EdgeType())) + continue; frame[self_.common_.edge_symbol] = edge; pull_node(edge, EdgeAtom::Direction::IN); return true; @@ -696,7 +698,9 @@ bool Expand::ExpandCursor::Pull(Frame &frame, ExecutionContext &context) { // we should do only one expansion for cycles, and it was // already done in the block above if (self_.common_.direction == EdgeAtom::Direction::BOTH && edge.IsCycle()) continue; - if (context.fine_grained_access_checker && !context.fine_grained_access_checker->Accept(edge)) continue; + if (context.auth_checker && + !context.auth_checker->IsUserAuthorizedEdgeType(context.user, context.db_accessor, edge.EdgeType())) + continue; frame[self_.common_.edge_symbol] = edge; pull_node(edge, EdgeAtom::Direction::OUT); return true; @@ -831,10 +835,9 @@ auto ExpandFromVertex(const VertexAccessor &vertex, EdgeAtom::Direction directio if (direction != EdgeAtom::Direction::OUT) { auto edges = UnwrapEdgesResult(vertex.InEdges(view, edge_types)); - if (context.fine_grained_access_checker) { - auto *fine_grained_access_checker = context.fine_grained_access_checker; - (void)std::remove_if(edges.begin(), edges.end(), [&fine_grained_access_checker](const auto &edge) { - return !fine_grained_access_checker->Accept(edge); + if (context.auth_checker) { + (void)std::remove_if(edges.begin(), edges.end(), [&context](const auto &edge) { + return context.auth_checker->IsUserAuthorizedEdgeType(context.user, context.db_accessor, edge.EdgeType()); }); } @@ -845,10 +848,9 @@ auto ExpandFromVertex(const VertexAccessor &vertex, EdgeAtom::Direction directio if (direction != EdgeAtom::Direction::IN) { auto edges = UnwrapEdgesResult(vertex.OutEdges(view, edge_types)); - if (context.fine_grained_access_checker) { - auto *fine_grained_access_checker = context.fine_grained_access_checker; - (void)std::remove_if(edges.begin(), edges.end(), [&fine_grained_access_checker](const auto &edge) { - return !fine_grained_access_checker->Accept(edge); + if (context.auth_checker) { + (void)std::remove_if(edges.begin(), edges.end(), [&context](const auto &edge) { + return context.auth_checker->IsUserAuthorizedEdgeType(context.user, context.db_accessor, edge.EdgeType()); }); } @@ -1041,9 +1043,10 @@ class ExpandVariableCursor : public Cursor { if (found_existing) continue; VertexAccessor current_vertex = current_edge.second == EdgeAtom::Direction::IN ? current_edge.first.From() : current_edge.first.To(); - - if (!context.fine_grained_access_checker->Accept(current_edge.first) || - !context.fine_grained_access_checker->Accept(current_vertex)) + if (context.auth_checker->IsUserAuthorizedEdgeType(context.user, context.db_accessor, + current_edge.first.EdgeType()) || + context.auth_checker->IsUserAuthorizedLabels(context.user, context.db_accessor, + current_vertex.Labels(storage::View::NEW).GetValue())) continue; AppendEdge(current_edge.first, &edges_on_frame);