GRANT, REVOKE, DENY and access_checker DONE

This commit is contained in:
niko4299
2022-07-20 14:22:26 +02:00
parent ff2f8031a9
commit 761f536b75
11 changed files with 331 additions and 41 deletions

View File

@@ -8,7 +8,10 @@
#include "auth/models.hpp"
#include <algorithm>
#include <iterator>
#include <regex>
#include <unordered_set>
#include <gflags/gflags.h>
@@ -84,6 +87,8 @@ std::string PermissionToString(Permission permission) {
return "MODULE_WRITE";
case Permission::WEBSOCKET:
return "WEBSOCKET";
case Permission::EDGE_TYPES:
return "EDGE_TYPES";
}
}
@@ -98,12 +103,9 @@ std::string PermissionLevelToString(PermissionLevel level) {
}
}
Permissions::Permissions(uint64_t grants, uint64_t denies) {
// The deny bitmask has higher priority than the grant bitmask.
denies_ = denies;
// Mask out the grant bitmask to make sure that it is correct.
grants_ = grants & (~denies);
}
const std::string ASTERISK = "*";
Permissions::Permissions(uint64_t grants, uint64_t denies) : grants_(grants & (~denies)), denies_(denies) {}
PermissionLevel Permissions::Has(Permission permission) const {
// Check for the deny first because it has greater priority than a grant.
@@ -183,19 +185,133 @@ bool operator==(const Permissions &first, const Permissions &second) {
bool operator!=(const Permissions &first, const Permissions &second) { return !(first == second); }
AccessPermissions::AccessPermissions(const std::unordered_set<std::string> &grants,
const std::unordered_set<std::string> &denies)
: grants_(grants), denies_(denies) {}
PermissionLevel AccessPermissions::Has(const std::string &permission) const {
if ((denies_.size() == 1 && denies_.find(ASTERISK) != denies_.end()) || denies_.find(permission) != denies_.end()) {
return PermissionLevel::DENY;
}
if ((grants_.size() == 1 && grants_.find(ASTERISK) != grants_.end()) || grants_.find(permission) != denies_.end()) {
return PermissionLevel::GRANT;
}
return PermissionLevel::NEUTRAL;
}
void AccessPermissions::Grant(const std::string &permission) {
if (permission == ASTERISK) {
grants_.clear();
grants_.insert(permission);
return;
}
auto deniedPermissionIter = denies_.find(permission);
if (deniedPermissionIter != denies_.end()) {
denies_.erase(deniedPermissionIter);
}
if (grants_.size() == 1 && grants_.find(ASTERISK) != grants_.end()) {
grants_.erase(ASTERISK);
}
if (grants_.find(permission) == grants_.end()) {
grants_.insert(permission);
}
}
void AccessPermissions::Revoke(const std::string &permission) {
if (permission == ASTERISK) {
grants_.clear();
denies_.clear();
return;
}
auto deniedPermissionIter = denies_.find(permission);
auto grantedPermissionIter = grants_.find(permission);
if (deniedPermissionIter != denies_.end()) {
denies_.erase(deniedPermissionIter);
}
if (grantedPermissionIter != grants_.end()) {
grants_.erase(grantedPermissionIter);
}
}
void AccessPermissions::Deny(const std::string &permission) {
if (permission == ASTERISK) {
denies_.clear();
denies_.insert(permission);
return;
}
auto grantedPermissionIter = grants_.find(permission);
if (grantedPermissionIter != grants_.end()) {
grants_.erase(grantedPermissionIter);
}
if (denies_.size() == 1 && denies_.find(ASTERISK) != denies_.end()) {
denies_.erase(ASTERISK);
}
if (denies_.find(permission) == denies_.end()) {
denies_.insert(permission);
}
}
std::unordered_set<std::string> AccessPermissions::GetGrants() const { return grants_; }
std::unordered_set<std::string> AccessPermissions::GetDenies() const { return denies_; }
nlohmann::json AccessPermissions::Serialize() const {
nlohmann::json data = nlohmann::json::object();
data["grants"] = grants_;
data["denies"] = denies_;
return data;
}
AccessPermissions AccessPermissions::Deserialize(const nlohmann::json &data) {
if (!data.is_object()) {
throw AuthException("Couldn't load permissions data!");
}
return {data["grants"], data["denies"]};
}
std::unordered_set<std::string> AccessPermissions::grants() const { return grants_; }
std::unordered_set<std::string> AccessPermissions::denies() const { return denies_; }
bool operator==(const AccessPermissions &first, const AccessPermissions &second) {
return first.grants() == second.grants() && first.denies() == second.denies();
}
bool operator!=(const AccessPermissions &first, const AccessPermissions &second) { return !(first == second); }
Role::Role(const std::string &rolename) : rolename_(utils::ToLowerCase(rolename)) {}
Role::Role(const std::string &rolename, const Permissions &permissions)
: rolename_(utils::ToLowerCase(rolename)), permissions_(permissions) {}
Role::Role(const std::string &rolename, const Permissions &permissions, const AccessPermissions &edgeTypePermissions)
: rolename_(utils::ToLowerCase(rolename)), permissions_(permissions), edgeTypePermissions_(edgeTypePermissions) {}
const std::string &Role::rolename() const { return rolename_; }
const Permissions &Role::permissions() const { return permissions_; }
Permissions &Role::permissions() { return permissions_; }
const AccessPermissions &Role::edgeTypePermissions() const { return edgeTypePermissions_; }
AccessPermissions &Role::edgeTypePermissions() { return edgeTypePermissions_; }
nlohmann::json Role::Serialize() const {
nlohmann::json data = nlohmann::json::object();
data["rolename"] = rolename_;
data["permissions"] = permissions_.Serialize();
data["edgeTypePermissions"] = edgeTypePermissions_.Serialize();
return data;
}
@@ -207,17 +323,23 @@ Role Role::Deserialize(const nlohmann::json &data) {
throw AuthException("Couldn't load role data!");
}
auto permissions = Permissions::Deserialize(data["permissions"]);
return {data["rolename"], permissions};
auto edgeTypePermissions = AccessPermissions::Deserialize(data["edgeTypePermissions"]);
return {data["rolename"], permissions, edgeTypePermissions};
}
bool operator==(const Role &first, const Role &second) {
return first.rolename_ == second.rolename_ && first.permissions_ == second.permissions_;
return first.rolename_ == second.rolename_ && first.permissions_ == second.permissions_ &&
first.edgeTypePermissions_ == second.edgeTypePermissions_;
}
User::User(const std::string &username) : username_(utils::ToLowerCase(username)) {}
User::User(const std::string &username, const std::string &password_hash, const Permissions &permissions)
: username_(utils::ToLowerCase(username)), password_hash_(password_hash), permissions_(permissions) {}
User::User(const std::string &username, const std::string &password_hash, const Permissions &permissions,
const AccessPermissions &edgeTypePermissions)
: username_(utils::ToLowerCase(username)),
password_hash_(password_hash),
permissions_(permissions),
edgeTypePermissions_(edgeTypePermissions) {}
bool User::CheckPassword(const std::string &password) {
if (password_hash_.empty()) return true;
@@ -260,17 +382,39 @@ void User::ClearRole() { role_ = std::nullopt; }
Permissions User::GetPermissions() const {
if (role_) {
return Permissions(permissions_.grants() | role_->permissions().grants(),
permissions_.denies() | role_->permissions().denies());
return {permissions_.grants() | role_->permissions().grants(),
permissions_.denies() | role_->permissions().denies()};
}
return permissions_;
}
AccessPermissions User::GetEdgeTypePermissions() const {
if (role_) {
std::unordered_set<std::string> resultGrants;
std::set_union(edgeTypePermissions_.grants().begin(), edgeTypePermissions_.grants().end(),
role_->edgeTypePermissions().grants().begin(), role_->edgeTypePermissions().grants().end(),
std::inserter(resultGrants, resultGrants.begin()));
std::unordered_set<std::string> resultDenies;
std::set_union(edgeTypePermissions_.denies().begin(), edgeTypePermissions_.denies().end(),
role_->edgeTypePermissions().denies().begin(), role_->edgeTypePermissions().denies().end(),
std::inserter(resultDenies, resultDenies.begin()));
return {resultGrants, resultDenies};
}
return edgeTypePermissions_;
}
const std::string &User::username() const { return username_; }
const Permissions &User::permissions() const { return permissions_; }
Permissions &User::permissions() { return permissions_; }
const AccessPermissions &User::edgeTypePermissions() const { return edgeTypePermissions_; }
AccessPermissions &User::edgeTypePermissions() { return edgeTypePermissions_; }
const Role *User::role() const {
if (role_.has_value()) {
return &role_.value();
@@ -283,6 +427,7 @@ nlohmann::json User::Serialize() const {
data["username"] = username_;
data["password_hash"] = password_hash_;
data["permissions"] = permissions_.Serialize();
data["edgeTypePermissions"] = edgeTypePermissions_.Serialize();
// The role shouldn't be serialized here, it is stored as a foreign key.
return data;
}
@@ -295,11 +440,14 @@ User User::Deserialize(const nlohmann::json &data) {
throw AuthException("Couldn't load user data!");
}
auto permissions = Permissions::Deserialize(data["permissions"]);
return {data["username"], data["password_hash"], permissions};
auto edgeTypePermissions = AccessPermissions::Deserialize(data["edgeTypePermissions"]);
return {data["username"], data["password_hash"], permissions, edgeTypePermissions};
}
bool operator==(const User &first, const User &second) {
return first.username_ == second.username_ && first.password_hash_ == second.password_hash_ &&
first.permissions_ == second.permissions_ && first.role_ == second.role_;
first.permissions_ == second.permissions_ && first.edgeTypePermissions_ == second.edgeTypePermissions_ &&
first.role_ == second.role_;
}
} // namespace memgraph::auth

View File

@@ -12,6 +12,7 @@
#include <string>
#include <json/json.hpp>
#include <unordered_set>
namespace memgraph::auth {
// These permissions must have values that are applicable for usage in a
@@ -38,7 +39,8 @@ enum class Permission : uint64_t {
STREAM = 1U << 17U,
MODULE_READ = 1U << 18U,
MODULE_WRITE = 1U << 19U,
WEBSOCKET = 1U << 20U
WEBSOCKET = 1U << 20U,
EDGE_TYPES = 1U << 22U
};
// clang-format on
@@ -88,16 +90,52 @@ bool operator==(const Permissions &first, const Permissions &second);
bool operator!=(const Permissions &first, const Permissions &second);
class AccessPermissions final {
public:
AccessPermissions(const std::unordered_set<std::string> &grants = {},
const std::unordered_set<std::string> &denies = {});
PermissionLevel Has(const std::string &permission) const;
void Grant(const std::string &permission);
void Revoke(const std::string &permission);
void Deny(const std::string &permission);
std::unordered_set<std::string> GetGrants() const;
std::unordered_set<std::string> GetDenies() const;
nlohmann::json Serialize() const;
/// @throw AuthException if unable to deserialize.
static AccessPermissions Deserialize(const nlohmann::json &data);
std::unordered_set<std::string> grants() const;
std::unordered_set<std::string> denies() const;
private:
std::unordered_set<std::string> grants_{};
std::unordered_set<std::string> denies_{};
};
bool operator==(const AccessPermissions &first, const AccessPermissions &second);
bool operator!=(const AccessPermissions &first, const AccessPermissions &second);
class Role final {
public:
Role(const std::string &rolename);
Role(const std::string &rolename, const Permissions &permissions);
Role(const std::string &rolename, const Permissions &permissions, const AccessPermissions &edgeTypePermissions_);
const std::string &rolename() const;
const Permissions &permissions() const;
Permissions &permissions();
const AccessPermissions &edgeTypePermissions() const;
AccessPermissions &edgeTypePermissions();
nlohmann::json Serialize() const;
/// @throw AuthException if unable to deserialize.
@@ -108,6 +146,7 @@ class Role final {
private:
std::string rolename_;
Permissions permissions_;
AccessPermissions edgeTypePermissions_;
};
bool operator==(const Role &first, const Role &second);
@@ -117,7 +156,8 @@ class User final {
public:
User(const std::string &username);
User(const std::string &username, const std::string &password_hash, const Permissions &permissions);
User(const std::string &username, const std::string &password_hash, const Permissions &permissions,
const AccessPermissions &edgeTypePermissions_);
/// @throw AuthException if unable to verify the password.
bool CheckPassword(const std::string &password);
@@ -130,12 +170,16 @@ class User final {
void ClearRole();
Permissions GetPermissions() const;
AccessPermissions GetEdgeTypePermissions() const;
const std::string &username() const;
const Permissions &permissions() const;
Permissions &permissions();
const AccessPermissions &edgeTypePermissions() const;
AccessPermissions &edgeTypePermissions();
const Role *role() const;
nlohmann::json Serialize() const;
@@ -149,6 +193,7 @@ class User final {
std::string username_;
std::string password_hash_;
Permissions permissions_;
AccessPermissions edgeTypePermissions_;
std::optional<Role> role_;
};

View File

@@ -57,6 +57,8 @@ auth::Permission PrivilegeToPermission(query::AuthQuery::Privilege privilege) {
return auth::Permission::MODULE_WRITE;
case query::AuthQuery::Privilege::WEBSOCKET:
return auth::Permission::WEBSOCKET;
case query::AuthQuery::Privilege::EDGE_TYPES:
return auth::Permission::EDGE_TYPES;
}
}
} // namespace memgraph::glue

View File

@@ -506,7 +506,7 @@ class AuthQueryHandler final : public memgraph::query::AuthQueryHandler {
if (first_user) {
spdlog::info("{} is first created user. Granting all privileges.", username);
GrantPrivilege(username, memgraph::query::kPrivilegesAll);
GrantPrivilege(username, memgraph::query::kPrivilegesAll, {"*"});
}
return user_added;
@@ -752,8 +752,9 @@ class AuthQueryHandler final : public memgraph::query::AuthQueryHandler {
}
void GrantPrivilege(const std::string &user_or_role,
const std::vector<memgraph::query::AuthQuery::Privilege> &privileges) override {
EditPermissions(user_or_role, privileges, [](auto *permissions, const auto &permission) {
const std::vector<memgraph::query::AuthQuery::Privilege> &privileges,
const std::vector<std::string> &edgeTypes) override {
EditPermissions(user_or_role, privileges, edgeTypes, [](auto *permissions, const auto &permission) {
// TODO (mferencevic): should we first check that the
// privilege is granted/denied/revoked before
// unconditionally granting/denying/revoking it?
@@ -762,8 +763,9 @@ class AuthQueryHandler final : public memgraph::query::AuthQueryHandler {
}
void DenyPrivilege(const std::string &user_or_role,
const std::vector<memgraph::query::AuthQuery::Privilege> &privileges) override {
EditPermissions(user_or_role, privileges, [](auto *permissions, const auto &permission) {
const std::vector<memgraph::query::AuthQuery::Privilege> &privileges,
const std::vector<std::string> &edgeTypes) override {
EditPermissions(user_or_role, privileges, edgeTypes, [](auto *permissions, const auto &permission) {
// TODO (mferencevic): should we first check that the
// privilege is granted/denied/revoked before
// unconditionally granting/denying/revoking it?
@@ -772,8 +774,9 @@ class AuthQueryHandler final : public memgraph::query::AuthQueryHandler {
}
void RevokePrivilege(const std::string &user_or_role,
const std::vector<memgraph::query::AuthQuery::Privilege> &privileges) override {
EditPermissions(user_or_role, privileges, [](auto *permissions, const auto &permission) {
const std::vector<memgraph::query::AuthQuery::Privilege> &privileges,
const std::vector<std::string> &edgeTypes) override {
EditPermissions(user_or_role, privileges, edgeTypes, [](auto *permissions, const auto &permission) {
// TODO (mferencevic): should we first check that the
// privilege is granted/denied/revoked before
// unconditionally granting/denying/revoking it?
@@ -784,7 +787,8 @@ class AuthQueryHandler final : public memgraph::query::AuthQueryHandler {
private:
template <class TEditFun>
void EditPermissions(const std::string &user_or_role,
const std::vector<memgraph::query::AuthQuery::Privilege> &privileges, const TEditFun &edit_fun) {
const std::vector<memgraph::query::AuthQuery::Privilege> &privileges,
const std::vector<std::string> &edgeTypes, const TEditFun &edit_fun) {
if (!std::regex_match(user_or_role, name_regex_)) {
throw memgraph::query::QueryRuntimeException("Invalid user or role name.");
}
@@ -804,11 +808,18 @@ class AuthQueryHandler final : public memgraph::query::AuthQueryHandler {
for (const auto &permission : permissions) {
edit_fun(&user->permissions(), permission);
}
for (const auto &edgeType : edgeTypes) {
edit_fun(&user->edgeTypePermissions(), edgeType);
}
locked_auth->SaveUser(*user);
} else {
for (const auto &permission : permissions) {
edit_fun(&role->permissions(), permission);
}
for (const auto &edgeType : edgeTypes) {
edit_fun(&role->edgeTypePermissions(), edgeType);
}
locked_auth->SaveRole(*role);
}
} catch (const memgraph::auth::AuthException &e) {

View File

@@ -0,0 +1,24 @@
// 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 "auth/models.hpp"
#include "query/frontend/ast/ast.hpp"
#include "storage/v2/id_types.hpp"
namespace memgraph::query {
class AccessChecker {
public:
virtual bool IsUserAuthorizedEdgeTypes(const std::vector<memgraph::storage::EdgeTypeId> &edgeTypes,
memgraph::query::DbAccessor *dba) const = 0;
};
} // namespace memgraph::query

View File

@@ -2242,6 +2242,7 @@ cpp<#
(password "Expression *" :initval "nullptr" :scope :public
:slk-save #'slk-save-ast-pointer
:slk-load (slk-load-ast-pointer "Expression"))
(edgeTypes "std::vector<std::string>" :scope :public)
(privileges "std::vector<Privilege>" :scope :public))
(:public
(lcp:define-enum action
@@ -2253,7 +2254,7 @@ cpp<#
(lcp:define-enum privilege
(create delete match merge set remove index stats auth constraint
dump replication durability read_file free_memory trigger config stream module_read module_write
websocket)
websocket edge_types)
(:serialize))
#>cpp
AuthQuery() = default;
@@ -2264,12 +2265,14 @@ cpp<#
#>cpp
AuthQuery(Action action, std::string user, std::string role,
std::string user_or_role, Expression *password,
std::vector<std::string> edgeTypes,
std::vector<Privilege> privileges)
: action_(action),
user_(user),
role_(role),
user_or_role_(user_or_role),
password_(password),
edgetypes_(edgeTypes),
privileges_(privileges) {}
cpp<#)
(:private
@@ -2295,7 +2298,7 @@ const std::vector<AuthQuery::Privilege> kPrivilegesAll = {
AuthQuery::Privilege::FREE_MEMORY, AuthQuery::Privilege::TRIGGER,
AuthQuery::Privilege::CONFIG, AuthQuery::Privilege::STREAM,
AuthQuery::Privilege::MODULE_READ, AuthQuery::Privilege::MODULE_WRITE,
AuthQuery::Privilege::WEBSOCKET};
AuthQuery::Privilege::WEBSOCKET, };
cpp<#
(lcp:define-class info-query (query)

View File

@@ -1274,7 +1274,11 @@ antlrcpp::Any CypherMainVisitor::visitGrantPrivilege(MemgraphCypher::GrantPrivil
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));
if (privilege->EDGE_TYPES()) {
auth->edgetypes_ = privilege->edgeTypeList()->accept(this).as<std::vector<std::string>>();
} else {
auth->privileges_.push_back(privilege->accept(this));
}
}
} else {
/* grant all privileges */
@@ -1319,6 +1323,22 @@ antlrcpp::Any CypherMainVisitor::visitRevokePrivilege(MemgraphCypher::RevokePriv
return auth;
}
/**
* @return AuthQuery*
*/
antlrcpp::Any CypherMainVisitor::visitEdgeTypeList(MemgraphCypher::EdgeTypeListContext *ctx) {
std::vector<std::string> edgeTypes;
if (ctx->listOfEdgeTypes()) {
for (auto *edgeType : ctx->listOfEdgeTypes()->edgeType()) {
edgeTypes.push_back(edgeType->symbolicName()->accept(this).as<std::string>());
}
} else {
edgeTypes.emplace_back("*");
}
return edgeTypes;
}
/**
* @return AuthQuery::Privilege
*/
@@ -1344,6 +1364,7 @@ antlrcpp::Any CypherMainVisitor::visitPrivilege(MemgraphCypher::PrivilegeContext
if (ctx->MODULE_READ()) return AuthQuery::Privilege::MODULE_READ;
if (ctx->MODULE_WRITE()) return AuthQuery::Privilege::MODULE_WRITE;
if (ctx->WEBSOCKET()) return AuthQuery::Privilege::WEBSOCKET;
if (ctx->EDGE_TYPES()) return AuthQuery::Privilege::EDGE_TYPES;
LOG_FATAL("Should not get here - unknown privilege!");
}

View File

@@ -468,6 +468,11 @@ class CypherMainVisitor : public antlropencypher::MemgraphCypherBaseVisitor {
*/
antlrcpp::Any visitRevokePrivilege(MemgraphCypher::RevokePrivilegeContext *ctx) override;
/**
* @return AuthQuery*
*/
antlrcpp::Any visitEdgeTypeList(MemgraphCypher::EdgeTypeListContext *ctx) override;
/**
* @return AuthQuery::Privilege
*/

View File

@@ -254,10 +254,18 @@ privilege : CREATE
| MODULE_READ
| MODULE_WRITE
| WEBSOCKET
| EDGE_TYPES edgeTypes = edgeTypeList
;
privilegeList : privilege ( ',' privilege )* ;
edgeTypeList : '*' | listOfEdgeTypes ;
listOfEdgeTypes : edgeType ( ',' edgeType )* ;
edgeType : COLON symbolicName ;
showPrivileges : SHOW PRIVILEGES FOR userOrRole=userOrRoleName ;
showRoleForUser : SHOW ROLE FOR user=userOrRoleName ;

View File

@@ -23,6 +23,7 @@
#include "glue/communication.hpp"
#include "memory/memory_control.hpp"
#include "query/access_checker.hpp"
#include "query/constants.hpp"
#include "query/context.hpp"
#include "query/cypher_query_interpreter.hpp"
@@ -43,6 +44,7 @@
#include "query/stream/common.hpp"
#include "query/trigger.hpp"
#include "query/typed_value.hpp"
#include "storage/v2/id_types.hpp"
#include "storage/v2/property_value.hpp"
#include "storage/v2/replication/enums.hpp"
#include "utils/algorithm.hpp"
@@ -259,6 +261,24 @@ class ReplQueryHandler final : public query::ReplicationQueryHandler {
private:
storage::Storage *db_;
};
class AccessChecker final : public memgraph::query::AccessChecker {
public:
explicit AccessChecker(memgraph::auth::User *user) : user_{user} {}
bool IsUserAuthorizedEdgeTypes(const std::vector<memgraph::storage::EdgeTypeId> &edgeTypes,
memgraph::query::DbAccessor *dba) const final {
auto edgeTypePermissions = user_->GetEdgeTypePermissions();
return std::any_of(edgeTypes.begin(), edgeTypes.end(), [edgeTypePermissions, dba](const auto edgeType) {
return edgeTypePermissions.Has(dba->EdgeTypeToName(edgeType)) == memgraph::auth::PermissionLevel::GRANT;
});
}
private:
memgraph::auth::User *user_;
};
/// returns false if the replication role can't be set
/// @throw QueryRuntimeException if an error ocurred.
@@ -280,6 +300,7 @@ Callback HandleAuthQuery(AuthQuery *auth_query, AuthQueryHandler *auth, const Pa
std::string rolename = auth_query->role_;
std::string user_or_role = auth_query->user_or_role_;
std::vector<AuthQuery::Privilege> privileges = auth_query->privileges_;
std::vector<std::string> edgeTypes = auth_query->edgetypes_;
auto password = EvaluateOptionalExpression(auth_query->password_, &evaluator);
Callback callback;
@@ -309,7 +330,7 @@ Callback HandleAuthQuery(AuthQuery *auth_query, AuthQueryHandler *auth, const Pa
// If the license is not valid we create users with admin access
if (!valid_enterprise_license) {
spdlog::warn("Granting all the privileges to {}.", username);
auth->GrantPrivilege(username, kPrivilegesAll);
auth->GrantPrivilege(username, kPrivilegesAll, {"*"});
}
return std::vector<std::vector<TypedValue>>();
@@ -384,20 +405,20 @@ Callback HandleAuthQuery(AuthQuery *auth_query, AuthQueryHandler *auth, const Pa
};
return callback;
case AuthQuery::Action::GRANT_PRIVILEGE:
callback.fn = [auth, user_or_role, privileges] {
auth->GrantPrivilege(user_or_role, privileges);
callback.fn = [auth, user_or_role, privileges, edgeTypes] {
auth->GrantPrivilege(user_or_role, privileges, edgeTypes);
return std::vector<std::vector<TypedValue>>();
};
return callback;
case AuthQuery::Action::DENY_PRIVILEGE:
callback.fn = [auth, user_or_role, privileges] {
auth->DenyPrivilege(user_or_role, privileges);
callback.fn = [auth, user_or_role, privileges, edgeTypes] {
auth->DenyPrivilege(user_or_role, privileges, edgeTypes);
return std::vector<std::vector<TypedValue>>();
};
return callback;
case AuthQuery::Action::REVOKE_PRIVILEGE: {
callback.fn = [auth, user_or_role, privileges] {
auth->RevokePrivilege(user_or_role, privileges);
callback.fn = [auth, user_or_role, privileges, edgeTypes] {
auth->RevokePrivilege(user_or_role, privileges, edgeTypes);
return std::vector<std::vector<TypedValue>>();
};
return callback;

View File

@@ -99,14 +99,16 @@ class AuthQueryHandler {
virtual std::vector<std::vector<TypedValue>> GetPrivileges(const std::string &user_or_role) = 0;
/// @throw QueryRuntimeException if an error ocurred.
virtual void GrantPrivilege(const std::string &user_or_role, const std::vector<AuthQuery::Privilege> &privileges) = 0;
virtual void GrantPrivilege(const std::string &user_or_role, const std::vector<AuthQuery::Privilege> &privileges,
const std::vector<std::string> &edgeTypes) = 0;
/// @throw QueryRuntimeException if an error ocurred.
virtual void DenyPrivilege(const std::string &user_or_role, const std::vector<AuthQuery::Privilege> &privileges) = 0;
virtual void DenyPrivilege(const std::string &user_or_role, const std::vector<AuthQuery::Privilege> &privileges,
const std::vector<std::string> &edgeTypes) = 0;
/// @throw QueryRuntimeException if an error ocurred.
virtual void RevokePrivilege(const std::string &user_or_role,
const std::vector<AuthQuery::Privilege> &privileges) = 0;
virtual void RevokePrivilege(const std::string &user_or_role, const std::vector<AuthQuery::Privilege> &privileges,
const std::vector<std::string> &edgeTypes) = 0;
};
enum class QueryHandlerResult { COMMIT, ABORT, NOTHING };