Add rest of user auth queries
Reviewers: mferencevic, teon.banek Reviewed By: mferencevic, teon.banek Subscribers: pullbot Differential Revision: https://phabricator.memgraph.io/D1522
This commit is contained in:
parent
ce306a4c21
commit
2a5fce8464
@ -132,14 +132,13 @@ struct Clause {
|
||||
merge @10 :Merge;
|
||||
unwind @11 :Unwind;
|
||||
createIndex @12 :CreateIndex;
|
||||
modifyUser @13 :ModifyUser;
|
||||
dropUser @14 :DropUser;
|
||||
createStream @15 :CreateStream;
|
||||
dropStream @16 :DropStream;
|
||||
showStreams @17 :ShowStreams;
|
||||
startStopStream @18 :StartStopStream;
|
||||
startStopAllStreams @19 :StartStopAllStreams;
|
||||
testStream @20 :TestStream;
|
||||
authQuery @13 :AuthQuery;
|
||||
createStream @14 :CreateStream;
|
||||
dropStream @15 :DropStream;
|
||||
showStreams @16 :ShowStreams;
|
||||
startStopStream @17 :StartStopStream;
|
||||
startStopAllStreams @18 :StartStopAllStreams;
|
||||
testStream @19 :TestStream;
|
||||
}
|
||||
}
|
||||
|
||||
@ -398,14 +397,39 @@ struct CreateIndex {
|
||||
property @1 :Storage.Common;
|
||||
}
|
||||
|
||||
struct ModifyUser {
|
||||
username @0 :Text;
|
||||
password @1 :Tree;
|
||||
isCreate @2 :Bool;
|
||||
}
|
||||
|
||||
struct DropUser {
|
||||
usernames @0 :List(Text);
|
||||
struct AuthQuery {
|
||||
enum Action {
|
||||
createRole @0;
|
||||
dropRole @1;
|
||||
showRoles @2;
|
||||
createUser @3;
|
||||
setPassword @4;
|
||||
dropUser @5;
|
||||
showUsers @6;
|
||||
grantRole @7;
|
||||
revokeRole @8;
|
||||
grantPrivilege @9;
|
||||
denyPrivilege @10;
|
||||
revokePrivilege @11;
|
||||
showGrants @12;
|
||||
showRoleForUser @13;
|
||||
showUsersForRole @14;
|
||||
}
|
||||
enum Privilege {
|
||||
create @0;
|
||||
delete @1;
|
||||
match @2;
|
||||
merge @3;
|
||||
set @4;
|
||||
auth @5;
|
||||
stream @6;
|
||||
}
|
||||
action @0 :Action;
|
||||
user @1 :Text;
|
||||
role @2 :Text;
|
||||
userOrRole @3 :Text;
|
||||
password @4 :Tree;
|
||||
privileges @5 :List(Privilege);
|
||||
}
|
||||
|
||||
struct CreateStream {
|
||||
|
@ -1268,13 +1268,9 @@ Clause *Clause::Construct(const capnp::Clause::Reader &reader,
|
||||
auto with_reader = reader.getWith();
|
||||
return With::Construct(with_reader, storage);
|
||||
}
|
||||
case capnp::Clause::MODIFY_USER: {
|
||||
auto mu_reader = reader.getModifyUser();
|
||||
return ModifyUser::Construct(mu_reader, storage);
|
||||
}
|
||||
case capnp::Clause::DROP_USER: {
|
||||
auto du_reader = reader.getDropUser();
|
||||
return DropUser::Construct(du_reader, storage);
|
||||
case capnp::Clause::AUTH_QUERY: {
|
||||
auto aq_reader = reader.getAuthQuery();
|
||||
return AuthQuery::Construct(aq_reader, storage);
|
||||
}
|
||||
case capnp::Clause::CREATE_STREAM: {
|
||||
auto cs_reader = reader.getCreateStream();
|
||||
@ -2067,69 +2063,188 @@ With *With::Construct(const capnp::With::Reader &reader, AstStorage *storage) {
|
||||
return storage->Create<With>();
|
||||
}
|
||||
|
||||
// ModifyUser.
|
||||
void ModifyUser::Save(capnp::Clause::Builder *clause_builder,
|
||||
std::vector<int> *saved_uids) {
|
||||
// AuthQuery.
|
||||
void AuthQuery::Save(capnp::Clause::Builder *clause_builder,
|
||||
std::vector<int> *saved_uids) {
|
||||
Clause::Save(clause_builder, saved_uids);
|
||||
auto builder = clause_builder->initModifyUser();
|
||||
ModifyUser::Save(&builder, saved_uids);
|
||||
auto builder = clause_builder->initAuthQuery();
|
||||
AuthQuery::Save(&builder, saved_uids);
|
||||
}
|
||||
|
||||
void ModifyUser::Save(capnp::ModifyUser::Builder *builder,
|
||||
std::vector<int> *saved_uids) {
|
||||
builder->setUsername(username_);
|
||||
void AuthQuery::Save(capnp::AuthQuery::Builder *builder,
|
||||
std::vector<int> *saved_uids) {
|
||||
switch (action_) {
|
||||
case Action::CREATE_ROLE:
|
||||
builder->setAction(capnp::AuthQuery::Action::CREATE_ROLE);
|
||||
break;
|
||||
case Action::DROP_ROLE:
|
||||
builder->setAction(capnp::AuthQuery::Action::DROP_ROLE);
|
||||
break;
|
||||
case Action::SHOW_ROLES:
|
||||
builder->setAction(capnp::AuthQuery::Action::SHOW_ROLES);
|
||||
break;
|
||||
case Action::CREATE_USER:
|
||||
builder->setAction(capnp::AuthQuery::Action::CREATE_USER);
|
||||
break;
|
||||
case Action::SET_PASSWORD:
|
||||
builder->setAction(capnp::AuthQuery::Action::SET_PASSWORD);
|
||||
break;
|
||||
case Action::DROP_USER:
|
||||
builder->setAction(capnp::AuthQuery::Action::DROP_USER);
|
||||
break;
|
||||
case Action::SHOW_USERS:
|
||||
builder->setAction(capnp::AuthQuery::Action::SHOW_USERS);
|
||||
break;
|
||||
case Action::GRANT_ROLE:
|
||||
builder->setAction(capnp::AuthQuery::Action::GRANT_ROLE);
|
||||
break;
|
||||
case Action::REVOKE_ROLE:
|
||||
builder->setAction(capnp::AuthQuery::Action::REVOKE_ROLE);
|
||||
break;
|
||||
case Action::GRANT_PRIVILEGE:
|
||||
builder->setAction(capnp::AuthQuery::Action::GRANT_PRIVILEGE);
|
||||
break;
|
||||
case Action::DENY_PRIVILEGE:
|
||||
builder->setAction(capnp::AuthQuery::Action::DENY_PRIVILEGE);
|
||||
break;
|
||||
case Action::REVOKE_PRIVILEGE:
|
||||
builder->setAction(capnp::AuthQuery::Action::REVOKE_PRIVILEGE);
|
||||
break;
|
||||
case Action::SHOW_GRANTS:
|
||||
builder->setAction(capnp::AuthQuery::Action::SHOW_GRANTS);
|
||||
break;
|
||||
case Action::SHOW_ROLE_FOR_USER:
|
||||
builder->setAction(capnp::AuthQuery::Action::SHOW_ROLE_FOR_USER);
|
||||
break;
|
||||
case Action::SHOW_USERS_FOR_ROLE:
|
||||
builder->setAction(capnp::AuthQuery::Action::SHOW_USERS_FOR_ROLE);
|
||||
break;
|
||||
}
|
||||
builder->setUser(user_);
|
||||
builder->setRole(role_);
|
||||
builder->setUserOrRole(user_or_role_);
|
||||
if (password_) {
|
||||
auto password_builder = builder->getPassword();
|
||||
auto password_builder = builder->initPassword();
|
||||
password_->Save(&password_builder, saved_uids);
|
||||
}
|
||||
builder->setIsCreate(is_create_);
|
||||
::capnp::List<capnp::AuthQuery::Privilege>::Builder privileges_builder =
|
||||
builder->initPrivileges(privileges_.size());
|
||||
for (size_t i = 0; i < privileges_.size(); ++i) {
|
||||
switch (privileges_[i]) {
|
||||
case Privilege::CREATE:
|
||||
privileges_builder.set(i, capnp::AuthQuery::Privilege::CREATE);
|
||||
break;
|
||||
case Privilege::DELETE:
|
||||
privileges_builder.set(i, capnp::AuthQuery::Privilege::DELETE);
|
||||
break;
|
||||
case Privilege::MATCH:
|
||||
privileges_builder.set(i, capnp::AuthQuery::Privilege::MATCH);
|
||||
break;
|
||||
case Privilege::MERGE:
|
||||
privileges_builder.set(i, capnp::AuthQuery::Privilege::MERGE);
|
||||
break;
|
||||
case Privilege::SET:
|
||||
privileges_builder.set(i, capnp::AuthQuery::Privilege::SET);
|
||||
break;
|
||||
case Privilege::AUTH:
|
||||
privileges_builder.set(i, capnp::AuthQuery::Privilege::AUTH);
|
||||
break;
|
||||
case Privilege::STREAM:
|
||||
privileges_builder.set(i, capnp::AuthQuery::Privilege::STREAM);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ModifyUser::Load(const capnp::Tree::Reader &base_reader,
|
||||
AstStorage *storage, std::vector<int> *loaded_uids) {
|
||||
void AuthQuery::Load(const capnp::Tree::Reader &base_reader,
|
||||
AstStorage *storage, std::vector<int> *loaded_uids) {
|
||||
Clause::Load(base_reader, storage, loaded_uids);
|
||||
auto reader = base_reader.getClause().getModifyUser();
|
||||
username_ = reader.getUsername();
|
||||
if (reader.hasPassword()) {
|
||||
const auto password_reader = reader.getPassword();
|
||||
auto auth_reader = base_reader.getClause().getAuthQuery();
|
||||
switch (auth_reader.getAction()) {
|
||||
case capnp::AuthQuery::Action::CREATE_ROLE:
|
||||
action_ = Action::CREATE_ROLE;
|
||||
break;
|
||||
case capnp::AuthQuery::Action::DROP_ROLE:
|
||||
action_ = Action::DROP_ROLE;
|
||||
break;
|
||||
case capnp::AuthQuery::Action::SHOW_ROLES:
|
||||
action_ = Action::SHOW_ROLES;
|
||||
break;
|
||||
case capnp::AuthQuery::Action::CREATE_USER:
|
||||
action_ = Action::CREATE_USER;
|
||||
break;
|
||||
case capnp::AuthQuery::Action::SET_PASSWORD:
|
||||
action_ = Action::SET_PASSWORD;
|
||||
break;
|
||||
case capnp::AuthQuery::Action::DROP_USER:
|
||||
action_ = Action::DROP_USER;
|
||||
break;
|
||||
case capnp::AuthQuery::Action::SHOW_USERS:
|
||||
action_ = Action::SHOW_USERS;
|
||||
break;
|
||||
case capnp::AuthQuery::Action::GRANT_ROLE:
|
||||
action_ = Action::GRANT_ROLE;
|
||||
break;
|
||||
case capnp::AuthQuery::Action::REVOKE_ROLE:
|
||||
action_ = Action::REVOKE_ROLE;
|
||||
break;
|
||||
case capnp::AuthQuery::Action::GRANT_PRIVILEGE:
|
||||
action_ = Action::GRANT_PRIVILEGE;
|
||||
break;
|
||||
case capnp::AuthQuery::Action::DENY_PRIVILEGE:
|
||||
action_ = Action::DENY_PRIVILEGE;
|
||||
break;
|
||||
case capnp::AuthQuery::Action::REVOKE_PRIVILEGE:
|
||||
action_ = Action::REVOKE_PRIVILEGE;
|
||||
break;
|
||||
case capnp::AuthQuery::Action::SHOW_GRANTS:
|
||||
action_ = Action::SHOW_GRANTS;
|
||||
break;
|
||||
case capnp::AuthQuery::Action::SHOW_ROLE_FOR_USER:
|
||||
action_ = Action::SHOW_ROLE_FOR_USER;
|
||||
break;
|
||||
case capnp::AuthQuery::Action::SHOW_USERS_FOR_ROLE:
|
||||
action_ = Action::SHOW_USERS_FOR_ROLE;
|
||||
break;
|
||||
}
|
||||
user_ = auth_reader.getUser();
|
||||
role_ = auth_reader.getRole();
|
||||
user_or_role_ = auth_reader.getUserOrRole();
|
||||
if (auth_reader.hasPassword()) {
|
||||
const auto password_reader = auth_reader.getPassword();
|
||||
password_ =
|
||||
dynamic_cast<Expression *>(storage->Load(password_reader, loaded_uids));
|
||||
} else {
|
||||
password_ = nullptr;
|
||||
}
|
||||
is_create_ = reader.getIsCreate();
|
||||
for (const auto &privilege : auth_reader.getPrivileges()) {
|
||||
switch (privilege) {
|
||||
case capnp::AuthQuery::Privilege::CREATE:
|
||||
privileges_.push_back(Privilege::CREATE);
|
||||
break;
|
||||
case capnp::AuthQuery::Privilege::DELETE:
|
||||
privileges_.push_back(Privilege::DELETE);
|
||||
break;
|
||||
case capnp::AuthQuery::Privilege::MATCH:
|
||||
privileges_.push_back(Privilege::MATCH);
|
||||
break;
|
||||
case capnp::AuthQuery::Privilege::MERGE:
|
||||
privileges_.push_back(Privilege::MERGE);
|
||||
break;
|
||||
case capnp::AuthQuery::Privilege::SET:
|
||||
privileges_.push_back(Privilege::SET);
|
||||
break;
|
||||
case capnp::AuthQuery::Privilege::AUTH:
|
||||
privileges_.push_back(Privilege::AUTH);
|
||||
break;
|
||||
case capnp::AuthQuery::Privilege::STREAM:
|
||||
privileges_.push_back(Privilege::STREAM);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ModifyUser *ModifyUser::Construct(const capnp::ModifyUser::Reader &reader,
|
||||
AstStorage *storage) {
|
||||
return storage->Create<ModifyUser>();
|
||||
}
|
||||
|
||||
// DropUser.
|
||||
void DropUser::Save(capnp::Clause::Builder *clause_builder,
|
||||
std::vector<int> *saved_uids) {
|
||||
Clause::Save(clause_builder, saved_uids);
|
||||
auto builder = clause_builder->initDropUser();
|
||||
DropUser::Save(&builder, saved_uids);
|
||||
}
|
||||
|
||||
void DropUser::Save(capnp::DropUser::Builder *builder,
|
||||
std::vector<int> *saved_uids) {
|
||||
auto usernames_builder = builder->initUsernames(usernames_.size());
|
||||
utils::SaveVector(usernames_, &usernames_builder);
|
||||
}
|
||||
|
||||
void DropUser::Load(const capnp::Tree::Reader &base_reader, AstStorage *storage,
|
||||
std::vector<int> *loaded_uids) {
|
||||
Clause::Load(base_reader, storage, loaded_uids);
|
||||
auto reader = base_reader.getClause().getDropUser();
|
||||
usernames_.clear();
|
||||
utils::LoadVector(&usernames_, reader.getUsernames());
|
||||
}
|
||||
|
||||
DropUser *DropUser::Construct(const capnp::DropUser::Reader &reader,
|
||||
AstStorage *storage) {
|
||||
return storage->Create<DropUser>();
|
||||
AuthQuery *AuthQuery::Construct(const capnp::AuthQuery::Reader &reader,
|
||||
AstStorage *storage) {
|
||||
return storage->Create<AuthQuery>();
|
||||
}
|
||||
|
||||
// CypherUnion
|
||||
|
@ -2339,68 +2339,67 @@ class CreateIndex : public Clause {
|
||||
std::vector<int> *saved_uids);
|
||||
};
|
||||
|
||||
class ModifyUser : public Clause {
|
||||
class AuthQuery : public Clause {
|
||||
friend class AstStorage;
|
||||
|
||||
public:
|
||||
enum class Action {
|
||||
CREATE_ROLE,
|
||||
DROP_ROLE,
|
||||
SHOW_ROLES,
|
||||
CREATE_USER,
|
||||
SET_PASSWORD,
|
||||
DROP_USER,
|
||||
SHOW_USERS,
|
||||
GRANT_ROLE,
|
||||
REVOKE_ROLE,
|
||||
GRANT_PRIVILEGE,
|
||||
DENY_PRIVILEGE,
|
||||
REVOKE_PRIVILEGE,
|
||||
SHOW_GRANTS,
|
||||
SHOW_ROLE_FOR_USER,
|
||||
SHOW_USERS_FOR_ROLE
|
||||
};
|
||||
|
||||
enum class Privilege { CREATE, DELETE, MATCH, MERGE, SET, AUTH, STREAM };
|
||||
|
||||
Action action_;
|
||||
std::string user_;
|
||||
std::string role_;
|
||||
std::string user_or_role_;
|
||||
Expression *password_{nullptr};
|
||||
std::vector<Privilege> privileges_;
|
||||
|
||||
DEFVISITABLE(TreeVisitor<TypedValue>);
|
||||
DEFVISITABLE(HierarchicalTreeVisitor);
|
||||
|
||||
ModifyUser *Clone(AstStorage &storage) const override {
|
||||
return storage.Create<ModifyUser>(
|
||||
username_, password_ ? password_->Clone(storage) : nullptr, is_create_);
|
||||
AuthQuery *Clone(AstStorage &storage) const override {
|
||||
return storage.Create<AuthQuery>(
|
||||
action_, user_, role_, user_or_role_,
|
||||
password_ ? password_->Clone(storage) : nullptr, privileges_);
|
||||
}
|
||||
|
||||
static ModifyUser *Construct(const capnp::ModifyUser::Reader &reader,
|
||||
AstStorage *storage);
|
||||
static AuthQuery *Construct(const capnp::AuthQuery::Reader &reader,
|
||||
AstStorage *storage);
|
||||
using Clause::Save;
|
||||
|
||||
std::string username_;
|
||||
Expression *password_;
|
||||
bool is_create_;
|
||||
|
||||
protected:
|
||||
explicit ModifyUser(int uid) : Clause(uid) {}
|
||||
ModifyUser(int uid, std::string username, Expression *password,
|
||||
bool is_create)
|
||||
explicit AuthQuery(int uid) : Clause(uid) {}
|
||||
|
||||
explicit AuthQuery(int uid, Action action, std::string user, std::string role,
|
||||
std::string user_or_role, Expression *password,
|
||||
std::vector<Privilege> privileges)
|
||||
: Clause(uid),
|
||||
username_(std::move(username)),
|
||||
action_(action),
|
||||
user_(user),
|
||||
role_(role),
|
||||
user_or_role_(user_or_role),
|
||||
password_(password),
|
||||
is_create_(is_create) {}
|
||||
privileges_(privileges) {}
|
||||
|
||||
void Save(capnp::Clause::Builder *builder,
|
||||
std::vector<int> *saved_uids) override;
|
||||
virtual void Save(capnp::ModifyUser::Builder *builder,
|
||||
std::vector<int> *saved_uids);
|
||||
void Load(const capnp::Tree::Reader &base_reader, AstStorage *storage,
|
||||
std::vector<int> *loaded_uids) override;
|
||||
};
|
||||
|
||||
class DropUser : public Clause {
|
||||
friend class AstStorage;
|
||||
|
||||
public:
|
||||
DEFVISITABLE(TreeVisitor<TypedValue>);
|
||||
DEFVISITABLE(HierarchicalTreeVisitor);
|
||||
|
||||
DropUser *Clone(AstStorage &storage) const override {
|
||||
return storage.Create<DropUser>(usernames_);
|
||||
}
|
||||
|
||||
static DropUser *Construct(const capnp::DropUser::Reader &reader,
|
||||
AstStorage *storage);
|
||||
using Clause::Save;
|
||||
|
||||
std::vector<std::string> usernames_;
|
||||
|
||||
protected:
|
||||
explicit DropUser(int uid) : Clause(uid) {}
|
||||
DropUser(int uid, std::vector<std::string> usernames)
|
||||
: Clause(uid), usernames_(usernames) {}
|
||||
|
||||
void Save(capnp::Clause::Builder *builder,
|
||||
std::vector<int> *saved_uids) override;
|
||||
virtual void Save(capnp::DropUser::Builder *builder,
|
||||
virtual void Save(capnp::AuthQuery::Builder *builder,
|
||||
std::vector<int> *saved_uids);
|
||||
void Load(const capnp::Tree::Reader &base_reader, AstStorage *storage,
|
||||
std::vector<int> *loaded_uids) override;
|
||||
|
@ -61,8 +61,7 @@ class RemoveLabels;
|
||||
class Merge;
|
||||
class Unwind;
|
||||
class CreateIndex;
|
||||
class ModifyUser;
|
||||
class DropUser;
|
||||
class AuthQuery;
|
||||
class CreateStream;
|
||||
class DropStream;
|
||||
class ShowStreams;
|
||||
@ -84,9 +83,9 @@ using TreeCompositeVisitor = ::utils::CompositeVisitor<
|
||||
|
||||
using TreeLeafVisitor =
|
||||
::utils::LeafVisitor<Identifier, PrimitiveLiteral, ParameterLookup,
|
||||
CreateIndex, ModifyUser, DropUser, CreateStream,
|
||||
DropStream, ShowStreams, StartStopStream,
|
||||
StartStopAllStreams, TestStream>;
|
||||
CreateIndex, AuthQuery, CreateStream, DropStream,
|
||||
ShowStreams, StartStopStream, StartStopAllStreams,
|
||||
TestStream>;
|
||||
|
||||
class HierarchicalTreeVisitor : public TreeCompositeVisitor,
|
||||
public TreeLeafVisitor {
|
||||
@ -109,8 +108,7 @@ using TreeVisitor = ::utils::Visitor<
|
||||
Aggregation, Function, Reduce, Extract, All, Single, ParameterLookup,
|
||||
Create, Match, Return, With, Pattern, NodeAtom, EdgeAtom, Delete, Where,
|
||||
SetProperty, SetProperties, SetLabels, RemoveProperty, RemoveLabels, Merge,
|
||||
Unwind, Identifier, PrimitiveLiteral, CreateIndex, ModifyUser, DropUser,
|
||||
CreateStream, DropStream, ShowStreams, StartStopStream, StartStopAllStreams,
|
||||
TestStream>;
|
||||
Unwind, Identifier, PrimitiveLiteral, CreateIndex, AuthQuery, CreateStream,
|
||||
DropStream, ShowStreams, StartStopStream, StartStopAllStreams, TestStream>;
|
||||
|
||||
} // namespace query
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include <codecvt>
|
||||
#include <cstring>
|
||||
#include <limits>
|
||||
#include <regex>
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
#include <unordered_map>
|
||||
@ -28,13 +29,10 @@ antlrcpp::Any CypherMainVisitor::visitAuthQuery(
|
||||
MemgraphCypher::AuthQueryContext *ctx) {
|
||||
query_ = storage_.query();
|
||||
query_->single_query_ = storage_.Create<SingleQuery>();
|
||||
Clause *clause = nullptr;
|
||||
if (ctx->modifyUser()) {
|
||||
clause = ctx->modifyUser()->accept(this).as<ModifyUser *>();
|
||||
} else if (ctx->dropUser()) {
|
||||
clause = ctx->dropUser()->accept(this).as<DropUser *>();
|
||||
}
|
||||
query_->single_query_->clauses_ = {clause};
|
||||
CHECK(ctx->children.size() == 1)
|
||||
<< "AuthQuery should have exactly one child!";
|
||||
query_->single_query_->clauses_.push_back(
|
||||
ctx->children[0]->accept(this).as<AuthQuery *>());
|
||||
return query_;
|
||||
}
|
||||
|
||||
@ -259,46 +257,224 @@ antlrcpp::Any CypherMainVisitor::visitCreateIndex(
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ModifyUser*
|
||||
* @return std::string
|
||||
*/
|
||||
antlrcpp::Any CypherMainVisitor::visitModifyUser(
|
||||
MemgraphCypher::ModifyUserContext *ctx) {
|
||||
std::string username(ctx->userName->getText());
|
||||
Expression *password = nullptr;
|
||||
bool is_create = static_cast<bool>(ctx->CREATE());
|
||||
for (auto option : ctx->modifyUserOption()) {
|
||||
if (option->passwordOption()) {
|
||||
if (password) {
|
||||
throw QueryException("password should be set at most once");
|
||||
}
|
||||
password = option->passwordOption()->accept(this);
|
||||
continue;
|
||||
}
|
||||
LOG(FATAL) << "Expected to handle all cases above.";
|
||||
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 storage_.Create<ModifyUser>(username, password, is_create);
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Expression*
|
||||
* @return AuthQuery*
|
||||
*/
|
||||
antlrcpp::Any CypherMainVisitor::visitPasswordOption(
|
||||
MemgraphCypher::PasswordOptionContext *ctx) {
|
||||
if (!ctx->literal()->StringLiteral() && !ctx->literal()->CYPHERNULL()) {
|
||||
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");
|
||||
}
|
||||
return ctx->literal()->accept(this);
|
||||
auth->password_ = ctx->password->accept(this);
|
||||
return auth;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return DropUser*
|
||||
* @return AuthQuery*
|
||||
*/
|
||||
antlrcpp::Any CypherMainVisitor::visitDropUser(
|
||||
MemgraphCypher::DropUserContext *ctx) {
|
||||
std::vector<std::string> usernames;
|
||||
for (auto username_ptr : ctx->userName)
|
||||
usernames.emplace_back(username_ptr->getText());
|
||||
return storage_.Create<DropUser>(usernames);
|
||||
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::visitGrantRole(
|
||||
MemgraphCypher::GrantRoleContext *ctx) {
|
||||
AuthQuery *auth = storage_.Create<AuthQuery>();
|
||||
auth->action_ = AuthQuery::Action::GRANT_ROLE;
|
||||
auth->role_ = ctx->role->accept(this).as<std::string>();
|
||||
auth->user_ = ctx->user->accept(this).as<std::string>();
|
||||
return auth;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return AuthQuery*
|
||||
*/
|
||||
antlrcpp::Any CypherMainVisitor::visitRevokeRole(
|
||||
MemgraphCypher::RevokeRoleContext *ctx) {
|
||||
AuthQuery *auth = storage_.Create<AuthQuery>();
|
||||
auth->action_ = AuthQuery::Action::REVOKE_ROLE;
|
||||
auth->role_ = ctx->role->accept(this).as<std::string>();
|
||||
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>();
|
||||
for (auto *privilege : ctx->privilegeList()->privilege()) {
|
||||
auth->privileges_.push_back(privilege->accept(this));
|
||||
}
|
||||
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>();
|
||||
for (auto *privilege : ctx->privilegeList()->privilege()) {
|
||||
auth->privileges_.push_back(privilege->accept(this));
|
||||
}
|
||||
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_ = {
|
||||
AuthQuery::Privilege::CREATE, AuthQuery::Privilege::DELETE,
|
||||
AuthQuery::Privilege::MATCH, AuthQuery::Privilege::MERGE,
|
||||
AuthQuery::Privilege::SET, AuthQuery::Privilege::AUTH,
|
||||
AuthQuery::Privilege::STREAM};
|
||||
}
|
||||
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->AUTH()) return AuthQuery::Privilege::AUTH;
|
||||
if (ctx->STREAM()) return AuthQuery::Privilege::STREAM;
|
||||
LOG(FATAL) << "Should not get here - unknown privilege!";
|
||||
}
|
||||
|
||||
/**
|
||||
* @return AuthQuery*
|
||||
*/
|
||||
antlrcpp::Any CypherMainVisitor::visitShowGrants(
|
||||
MemgraphCypher::ShowGrantsContext *ctx) {
|
||||
AuthQuery *auth = storage_.Create<AuthQuery>();
|
||||
auth->action_ = AuthQuery::Action::SHOW_GRANTS;
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -177,6 +177,28 @@ class CypherMainVisitor : public antlropencypher::MemgraphCypherBaseVisitor {
|
||||
*/
|
||||
antlrcpp::Any visitCreate(MemgraphCypher::CreateContext *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 CreateIndex*
|
||||
*/
|
||||
@ -184,19 +206,79 @@ class CypherMainVisitor : public antlropencypher::MemgraphCypherBaseVisitor {
|
||||
MemgraphCypher::CreateIndexContext *ctx) override;
|
||||
|
||||
/**
|
||||
* @return ModifyUser*
|
||||
* @return AuthQuery*
|
||||
*/
|
||||
antlrcpp::Any visitModifyUser(
|
||||
MemgraphCypher::ModifyUserContext *ctx) override;
|
||||
|
||||
antlrcpp::Any visitPasswordOption(
|
||||
MemgraphCypher::PasswordOptionContext *ctx) override;
|
||||
antlrcpp::Any visitCreateUser(
|
||||
MemgraphCypher::CreateUserContext *ctx) override;
|
||||
|
||||
/**
|
||||
* @return DropUser*
|
||||
* @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 visitGrantRole(MemgraphCypher::GrantRoleContext *ctx) override;
|
||||
|
||||
/**
|
||||
* @return AuthQuery*
|
||||
*/
|
||||
antlrcpp::Any visitRevokeRole(
|
||||
MemgraphCypher::RevokeRoleContext *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 visitShowGrants(
|
||||
MemgraphCypher::ShowGrantsContext *ctx) override;
|
||||
|
||||
/**
|
||||
* @return AuthQuery*
|
||||
*/
|
||||
antlrcpp::Any visitShowRoleForUser(
|
||||
MemgraphCypher::ShowRoleForUserContext *ctx) override;
|
||||
|
||||
/**
|
||||
* @return AuthQuery*
|
||||
*/
|
||||
antlrcpp::Any visitShowUsersForRole(
|
||||
MemgraphCypher::ShowUsersForRoleContext *ctx) override;
|
||||
|
||||
/**
|
||||
* @return CreateStream*
|
||||
*/
|
||||
|
@ -8,23 +8,36 @@ import Cypher ;
|
||||
|
||||
memgraphCypherKeyword : cypherKeyword
|
||||
| ALTER
|
||||
| AUTH
|
||||
| BATCH
|
||||
| BATCHES
|
||||
| DATA
|
||||
| DENY
|
||||
| DROP
|
||||
| FOR
|
||||
| FROM
|
||||
| GRANT
|
||||
| GRANTS
|
||||
| IDENTIFIED
|
||||
| INTERVAL
|
||||
| K_TEST
|
||||
| KAFKA
|
||||
| LOAD
|
||||
| PASSWORD
|
||||
| PRIVILEGES
|
||||
| REVOKE
|
||||
| ROLE
|
||||
| ROLES
|
||||
| SIZE
|
||||
| START
|
||||
| STOP
|
||||
| STREAM
|
||||
| STREAMS
|
||||
| TO
|
||||
| TOPIC
|
||||
| TRANSFORM
|
||||
| USER
|
||||
| USERS
|
||||
;
|
||||
|
||||
symbolicName : UnescapedSymbolicName
|
||||
@ -37,19 +50,60 @@ query : regularQuery
|
||||
| streamQuery
|
||||
;
|
||||
|
||||
authQuery : modifyUser
|
||||
authQuery : createRole
|
||||
| dropRole
|
||||
| showRoles
|
||||
| createUser
|
||||
| setPassword
|
||||
| dropUser
|
||||
| showUsers
|
||||
| grantRole
|
||||
| revokeRole
|
||||
| grantPrivilege
|
||||
| denyPrivilege
|
||||
| revokePrivilege
|
||||
| showGrants
|
||||
| showRoleForUser
|
||||
| showUsersForRole
|
||||
;
|
||||
|
||||
modifyUser : ( CREATE | ALTER ) USER userName=UnescapedSymbolicName
|
||||
( WITH ( modifyUserOption )+ )? ;
|
||||
userOrRoleName : symbolicName ;
|
||||
|
||||
modifyUserOption : passwordOption ;
|
||||
createRole : CREATE ROLE role=userOrRoleName ;
|
||||
|
||||
passwordOption : PASSWORD literal;
|
||||
dropRole : DROP ROLE role=userOrRoleName ;
|
||||
|
||||
dropUser : DROP USER userName+=UnescapedSymbolicName
|
||||
( ',' userName+=UnescapedSymbolicName )* ;
|
||||
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 ;
|
||||
|
||||
grantRole : GRANT ROLE role=userOrRoleName TO user=userOrRoleName ;
|
||||
|
||||
revokeRole : REVOKE ROLE role=userOrRoleName FROM user=userOrRoleName ;
|
||||
|
||||
grantPrivilege : GRANT privilegeList TO userOrRole=userOrRoleName ;
|
||||
|
||||
denyPrivilege : DENY privilegeList TO userOrRole=userOrRoleName ;
|
||||
|
||||
revokePrivilege : REVOKE ( ALL PRIVILEGES | privileges=privilegeList ) FROM userOrRole=userOrRoleName ;
|
||||
|
||||
privilege : CREATE | DELETE | MATCH | MERGE | SET
|
||||
| AUTH | STREAM ;
|
||||
|
||||
privilegeList : privilege ( ',' privilege )* ;
|
||||
|
||||
showGrants : SHOW GRANTS FOR userOrRole=userOrRoleName ;
|
||||
|
||||
showRoleForUser : SHOW ROLE FOR USER user=userOrRoleName ;
|
||||
|
||||
showUsersForRole : SHOW USERS FOR ROLE role=userOrRoleName ;
|
||||
|
||||
streamQuery : createStream
|
||||
| dropStream
|
||||
|
@ -11,20 +11,33 @@ lexer grammar MemgraphCypherLexer ;
|
||||
import CypherLexer ;
|
||||
|
||||
ALTER : A L T E R ;
|
||||
AUTH : A U T H ;
|
||||
BATCH : B A T C H ;
|
||||
BATCHES : B A T C H E S ;
|
||||
DATA : D A T A ;
|
||||
DENY : D E N Y ;
|
||||
DROP : D R O 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 ;
|
||||
INTERVAL : I N T E R V A L ;
|
||||
K_TEST : T E S T ;
|
||||
KAFKA : K A F K A ;
|
||||
LOAD : L O A 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 ;
|
||||
SIZE : S I Z E ;
|
||||
START : S T A R T ;
|
||||
STOP : S T O P ;
|
||||
STREAM : S T R E A M ;
|
||||
STREAMS : S T R E A M S ;
|
||||
TO : T O ;
|
||||
TOPIC : T O P I C ;
|
||||
TRANSFORM : T R A N S F O R M ;
|
||||
USER : U S E R ;
|
||||
USERS : U S E R S ;
|
||||
|
@ -220,9 +220,7 @@ bool SymbolGenerator::PostVisit(Match &) {
|
||||
|
||||
bool SymbolGenerator::Visit(CreateIndex &) { return true; }
|
||||
|
||||
bool SymbolGenerator::Visit(ModifyUser &) { return true; }
|
||||
|
||||
bool SymbolGenerator::Visit(DropUser &) { return true; }
|
||||
bool SymbolGenerator::Visit(AuthQuery &) { return true; }
|
||||
|
||||
bool SymbolGenerator::Visit(CreateStream &) { return true; }
|
||||
|
||||
|
@ -47,8 +47,7 @@ class SymbolGenerator : public HierarchicalTreeVisitor {
|
||||
bool PreVisit(Match &) override;
|
||||
bool PostVisit(Match &) override;
|
||||
bool Visit(CreateIndex &) override;
|
||||
bool Visit(ModifyUser &) override;
|
||||
bool Visit(DropUser &) override;
|
||||
bool Visit(AuthQuery &) override;
|
||||
bool Visit(CreateStream &) override;
|
||||
bool Visit(DropStream &) override;
|
||||
bool Visit(ShowStreams &) override;
|
||||
|
@ -49,8 +49,7 @@ class ExpressionEvaluator : public TreeVisitor<TypedValue> {
|
||||
BLOCK_VISIT(Merge);
|
||||
BLOCK_VISIT(Unwind);
|
||||
BLOCK_VISIT(CreateIndex);
|
||||
BLOCK_VISIT(ModifyUser);
|
||||
BLOCK_VISIT(DropUser);
|
||||
BLOCK_VISIT(AuthQuery);
|
||||
BLOCK_VISIT(CreateStream);
|
||||
BLOCK_VISIT(DropStream);
|
||||
BLOCK_VISIT(ShowStreams);
|
||||
|
@ -185,8 +185,7 @@ class CostEstimator : public HierarchicalLogicalOperatorVisitor {
|
||||
|
||||
bool Visit(Once &) override { return true; }
|
||||
bool Visit(CreateIndex &) override { return true; }
|
||||
bool Visit(ModifyUser &) override { return true; }
|
||||
bool Visit(DropUser &) override { return true; }
|
||||
bool Visit(AuthHandler &) override { return true; }
|
||||
bool Visit(CreateStream &) override { return true; }
|
||||
bool Visit(DropStream &) override { return true; }
|
||||
bool Visit(ShowStreams &) override { return true; }
|
||||
|
@ -87,8 +87,7 @@ class IndependentSubtreeFinder : public HierarchicalLogicalOperatorVisitor {
|
||||
// These don't use any symbols
|
||||
bool Visit(Once &) override { return true; }
|
||||
bool Visit(CreateIndex &) override { return true; }
|
||||
bool Visit(ModifyUser &) override { return true; }
|
||||
bool Visit(DropUser &) override { return true; }
|
||||
bool Visit(AuthHandler &) override { return true; }
|
||||
bool Visit(CreateStream &) override { return true; }
|
||||
bool Visit(DropStream &) override { return true; }
|
||||
bool Visit(ShowStreams &) override { return true; }
|
||||
@ -1344,9 +1343,7 @@ class DistributedPlanner : public HierarchicalLogicalOperatorVisitor {
|
||||
|
||||
bool Visit(CreateIndex &) override { return true; }
|
||||
|
||||
bool Visit(ModifyUser &) override { return true; }
|
||||
|
||||
bool Visit(DropUser &) override { return true; }
|
||||
bool Visit(AuthHandler &) override { return true; }
|
||||
|
||||
bool Visit(CreateStream &) override { return true; }
|
||||
|
||||
|
@ -159,7 +159,7 @@ VertexAccessor &CreateVertexOnWorker(int worker_id, NodeAtom *node_atom,
|
||||
int current_worker_id = 0;
|
||||
// TODO: Figure out a better solution.
|
||||
if (auto *distributed_db =
|
||||
dynamic_cast<database::DistributedGraphDb *>(&dba.db())) {
|
||||
dynamic_cast<database::DistributedGraphDb *>(&dba.db())) {
|
||||
current_worker_id = distributed_db->WorkerId();
|
||||
} else {
|
||||
CHECK(dynamic_cast<database::SingleNode *>(&dba.db()));
|
||||
@ -1392,7 +1392,8 @@ class ExpandWeightedShortestPathCursor : public query::plan::Cursor {
|
||||
// For the given (edge, vertex, weight, depth) tuple checks if they
|
||||
// satisfy the "where" condition. if so, places them in the priority queue.
|
||||
auto expand_pair = [this, &evaluator, &frame, &create_state](
|
||||
EdgeAccessor edge, VertexAccessor vertex, double weight, int depth) {
|
||||
EdgeAccessor edge, VertexAccessor vertex,
|
||||
double weight, int depth) {
|
||||
SwitchAccessor(edge, self_.graph_view_);
|
||||
SwitchAccessor(vertex, self_.graph_view_);
|
||||
|
||||
@ -3889,130 +3890,120 @@ std::unique_ptr<Cursor> PullRemoteOrderBy::MakeCursor(
|
||||
return std::make_unique<PullRemoteOrderByCursor>(*this, db);
|
||||
}
|
||||
|
||||
ModifyUser::ModifyUser(std::string username, Expression *password,
|
||||
bool is_create)
|
||||
: username_(std::move(username)),
|
||||
AuthHandler::AuthHandler(AuthQuery::Action action, std::string user,
|
||||
std::string role, std::string user_or_role,
|
||||
Expression *password,
|
||||
std::vector<AuthQuery::Privilege> privileges)
|
||||
: action_(action),
|
||||
user_(user),
|
||||
role_(role),
|
||||
user_or_role_(user_or_role),
|
||||
password_(password),
|
||||
is_create_(is_create) {}
|
||||
privileges_(privileges) {}
|
||||
|
||||
bool ModifyUser::Accept(HierarchicalLogicalOperatorVisitor &visitor) {
|
||||
bool AuthHandler::Accept(HierarchicalLogicalOperatorVisitor &visitor) {
|
||||
return visitor.Visit(*this);
|
||||
}
|
||||
|
||||
WITHOUT_SINGLE_INPUT(ModifyUser)
|
||||
|
||||
class ModifyUserCursor : public Cursor {
|
||||
class AuthHandlerCursor : public Cursor {
|
||||
public:
|
||||
ModifyUserCursor(const ModifyUser &self) : self_(self) {}
|
||||
AuthHandlerCursor(const AuthHandler &self) : self_(self) {}
|
||||
|
||||
bool Pull(Frame &frame, Context &ctx) override {
|
||||
if (ctx.in_explicit_transaction_) {
|
||||
throw UserModificationInMulticommandTxException();
|
||||
}
|
||||
|
||||
ExpressionEvaluator evaluator(frame, &ctx, GraphView::OLD);
|
||||
|
||||
TypedValue password_tv = self_.password()->Accept(evaluator);
|
||||
if (password_tv.type() != TypedValue::Type::String) {
|
||||
throw QueryRuntimeException(fmt::format(
|
||||
"Password must be a string, not '{}'", password_tv.type()));
|
||||
}
|
||||
|
||||
// All of the following operations are done with a lock.
|
||||
std::lock_guard<std::mutex> guard(ctx.auth_->WithLock());
|
||||
|
||||
std::experimental::optional<auth::User> user;
|
||||
if (self_.is_create()) {
|
||||
// Create a new user.
|
||||
user = ctx.auth_->AddUser(self_.username());
|
||||
if (!user) {
|
||||
throw QueryRuntimeException(
|
||||
fmt::format("User '{}' already exists!", self_.username()));
|
||||
std::experimental::optional<std::string> password;
|
||||
/* TODO(mferencevic): handle null passwords properly */
|
||||
if (self_.password()) {
|
||||
auto password_tv = self_.password()->Accept(evaluator);
|
||||
if (!password_tv.IsString()) {
|
||||
throw QueryRuntimeException("Password must be a string, not '{}'!",
|
||||
password_tv.type());
|
||||
}
|
||||
} else {
|
||||
// Update an existing user.
|
||||
user = ctx.auth_->GetUser(self_.username());
|
||||
if (!user) {
|
||||
throw QueryRuntimeException(
|
||||
fmt::format("User '{}' doesn't exist!", self_.username()));
|
||||
password = password_tv.ValueString();
|
||||
}
|
||||
|
||||
auto &auth = *ctx.auth_;
|
||||
std::lock_guard<std::mutex> lock(auth.WithLock());
|
||||
|
||||
switch (self_.action()) {
|
||||
case AuthQuery::Action::CREATE_USER: {
|
||||
if (!password) {
|
||||
throw QueryRuntimeException(
|
||||
"Password must be provided when creating a user!");
|
||||
}
|
||||
auto user = auth.AddUser(self_.user());
|
||||
if (!user) {
|
||||
throw QueryRuntimeException("User '{}' already exists!",
|
||||
self_.user());
|
||||
}
|
||||
user->UpdatePassword(*password);
|
||||
if (!auth.SaveUser(*user)) {
|
||||
throw QueryRuntimeException("Couldn't save user '{}'!", self_.user());
|
||||
}
|
||||
break;
|
||||
}
|
||||
case AuthQuery::Action::DROP_USER: {
|
||||
auto user = auth.GetUser(self_.user());
|
||||
if (!user) {
|
||||
throw QueryRuntimeException("User '{}' doesn't exist!", self_.user());
|
||||
}
|
||||
if (!auth.RemoveUser(self_.user())) {
|
||||
throw QueryRuntimeException("Couldn't remove user '{}'!",
|
||||
self_.user());
|
||||
}
|
||||
break;
|
||||
}
|
||||
case AuthQuery::Action::SET_PASSWORD: {
|
||||
if (!password) {
|
||||
throw QueryRuntimeException("Password must be provided!");
|
||||
}
|
||||
auto user = auth.GetUser(self_.user());
|
||||
if (!user) {
|
||||
throw QueryRuntimeException("User '{}' doesn't exist!", self_.user());
|
||||
}
|
||||
user->UpdatePassword(*password);
|
||||
if (!auth.SaveUser(*user)) {
|
||||
throw QueryRuntimeException("Couldn't set password for user '{}'!",
|
||||
self_.user());
|
||||
}
|
||||
break;
|
||||
}
|
||||
case AuthQuery::Action::CREATE_ROLE:
|
||||
case AuthQuery::Action::DROP_ROLE:
|
||||
case AuthQuery::Action::SHOW_ROLES:
|
||||
case AuthQuery::Action::SHOW_USERS:
|
||||
case AuthQuery::Action::GRANT_ROLE:
|
||||
case AuthQuery::Action::REVOKE_ROLE:
|
||||
case AuthQuery::Action::GRANT_PRIVILEGE:
|
||||
case AuthQuery::Action::DENY_PRIVILEGE:
|
||||
case AuthQuery::Action::REVOKE_PRIVILEGE:
|
||||
case AuthQuery::Action::SHOW_GRANTS:
|
||||
case AuthQuery::Action::SHOW_ROLE_FOR_USER:
|
||||
case AuthQuery::Action::SHOW_USERS_FOR_ROLE:
|
||||
throw utils::NotYetImplemented("user auth");
|
||||
}
|
||||
|
||||
// Set the password and save the user.
|
||||
user->UpdatePassword(password_tv.Value<std::string>());
|
||||
if (!ctx.auth_->SaveUser(*user)) {
|
||||
throw QueryRuntimeException(
|
||||
fmt::format("Couldn't save user '{}'!", self_.username()));
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void Reset() override {}
|
||||
|
||||
private:
|
||||
const ModifyUser &self_;
|
||||
};
|
||||
|
||||
std::unique_ptr<Cursor> ModifyUser::MakeCursor(
|
||||
database::GraphDbAccessor &) const {
|
||||
return std::make_unique<ModifyUserCursor>(*this);
|
||||
}
|
||||
|
||||
bool DropUser::Accept(HierarchicalLogicalOperatorVisitor &visitor) {
|
||||
return visitor.Visit(*this);
|
||||
}
|
||||
|
||||
WITHOUT_SINGLE_INPUT(DropUser)
|
||||
|
||||
class DropUserCursor : public Cursor {
|
||||
public:
|
||||
DropUserCursor(const DropUser &self) : self_(self) {}
|
||||
|
||||
bool Pull(Frame &, Context &ctx) override {
|
||||
if (ctx.in_explicit_transaction_) {
|
||||
throw UserModificationInMulticommandTxException();
|
||||
}
|
||||
|
||||
// All of the following operations are done with a lock.
|
||||
std::lock_guard<std::mutex> guard(ctx.auth_->WithLock());
|
||||
|
||||
// Check if all users exist.
|
||||
for (const auto &username : self_.usernames()) {
|
||||
auto user = ctx.auth_->GetUser(username);
|
||||
if (!user) {
|
||||
throw QueryRuntimeException(
|
||||
fmt::format("User '{}' doesn't exist!", username));
|
||||
}
|
||||
}
|
||||
|
||||
// Delete all users.
|
||||
std::vector<std::string> failed;
|
||||
for (const auto &username : self_.usernames()) {
|
||||
if (!ctx.auth_->RemoveUser(username)) {
|
||||
failed.push_back(username);
|
||||
}
|
||||
}
|
||||
|
||||
// Check for failures.
|
||||
if (failed.size() > 0) {
|
||||
throw QueryRuntimeException(fmt::format("Couldn't remove users: '{}'!",
|
||||
utils::Join(failed, "', '")));
|
||||
}
|
||||
|
||||
return false;
|
||||
void Reset() override {
|
||||
LOG(FATAL) << "AuthHandler cursor should never be reset";
|
||||
}
|
||||
|
||||
void Reset() override {}
|
||||
|
||||
private:
|
||||
const DropUser &self_;
|
||||
const AuthHandler &self_;
|
||||
};
|
||||
|
||||
std::unique_ptr<Cursor> DropUser::MakeCursor(
|
||||
database::GraphDbAccessor &) const {
|
||||
return std::make_unique<DropUserCursor>(*this);
|
||||
std::unique_ptr<Cursor> AuthHandler::MakeCursor(
|
||||
database::GraphDbAccessor &db) const {
|
||||
return std::make_unique<AuthHandlerCursor>(*this);
|
||||
}
|
||||
|
||||
WITHOUT_SINGLE_INPUT(AuthHandler)
|
||||
|
||||
CreateStream::CreateStream(std::string stream_name, Expression *stream_uri,
|
||||
Expression *stream_topic, Expression *transform_uri,
|
||||
Expression *batch_interval_in_ms,
|
||||
|
@ -102,8 +102,7 @@ class PullRemote;
|
||||
class Synchronize;
|
||||
class Cartesian;
|
||||
class PullRemoteOrderBy;
|
||||
class ModifyUser;
|
||||
class DropUser;
|
||||
class AuthHandler;
|
||||
class CreateStream;
|
||||
class DropStream;
|
||||
class ShowStreams;
|
||||
@ -122,9 +121,9 @@ using LogicalOperatorCompositeVisitor = ::utils::CompositeVisitor<
|
||||
Cartesian, PullRemoteOrderBy>;
|
||||
|
||||
using LogicalOperatorLeafVisitor =
|
||||
::utils::LeafVisitor<Once, CreateIndex, ModifyUser, DropUser,
|
||||
CreateStream, DropStream, ShowStreams,
|
||||
StartStopStream, StartStopAllStreams, TestStream>;
|
||||
::utils::LeafVisitor<Once, CreateIndex, AuthHandler, CreateStream,
|
||||
DropStream, ShowStreams, StartStopStream,
|
||||
StartStopAllStreams, TestStream>;
|
||||
|
||||
/**
|
||||
* @brief Base class for hierarhical visitors of @c LogicalOperator class
|
||||
@ -1969,6 +1968,114 @@ and returns true, once.")
|
||||
cpp<#)
|
||||
(:serialize :capnp))
|
||||
|
||||
(lcp:define-class auth-handler (logical-operator)
|
||||
((action "AuthQuery::Action" :reader t
|
||||
:capnp-init nil
|
||||
:capnp-type "Ast.AuthQuery.Action"
|
||||
:capnp-save (lcp:capnp-save-enum "::query::capnp::AuthQuery::Action"
|
||||
"AuthQuery::Action"
|
||||
'(create-role drop-role show-roles
|
||||
create-user set-password
|
||||
drop-user show-users grant-role
|
||||
revoke-role grant-privilege
|
||||
deny-privilege revoke-privilege
|
||||
show-grants show-role-for-user
|
||||
show-users-for-role))
|
||||
:capnp-load (lcp:capnp-load-enum "::query::capnp::AuthQuery::Action"
|
||||
"AuthQuery::Action"
|
||||
'(create-role drop-role show-roles
|
||||
create-user set-password
|
||||
drop-user show-users grant-role
|
||||
revoke-role grant-privilege
|
||||
deny-privilege revoke-privilege
|
||||
show-grants show-role-for-user
|
||||
show-users-for-role)))
|
||||
(user "std::string" :reader t)
|
||||
(role "std::string" :reader t)
|
||||
(user-or-role "std::string" :reader t)
|
||||
(password "Expression *" :reader t
|
||||
:capnp-type "Ast.Tree" :capnp-init nil
|
||||
:capnp-save #'save-ast-pointer
|
||||
:capnp-load (load-ast-pointer "Expression *"))
|
||||
(privileges "std::vector<AuthQuery::Privilege>" :reader t
|
||||
:capnp-type "List(Ast.AuthQuery.Privilege)"
|
||||
:capnp-save
|
||||
(lambda (builder member-name)
|
||||
#>cpp
|
||||
for (size_t i = 0; i < ${member-name}.size(); ++i) {
|
||||
switch (privileges_[i]) {
|
||||
case AuthQuery::Privilege::CREATE:
|
||||
${builder}.set(i, query::capnp::AuthQuery::Privilege::CREATE);
|
||||
break;
|
||||
case AuthQuery::Privilege::DELETE:
|
||||
${builder}.set(i, query::capnp::AuthQuery::Privilege::DELETE);
|
||||
break;
|
||||
case AuthQuery::Privilege::MATCH:
|
||||
${builder}.set(i, query::capnp::AuthQuery::Privilege::MATCH);
|
||||
break;
|
||||
case AuthQuery::Privilege::MERGE:
|
||||
${builder}.set(i, query::capnp::AuthQuery::Privilege::MERGE);
|
||||
break;
|
||||
case AuthQuery::Privilege::SET:
|
||||
${builder}.set(i, query::capnp::AuthQuery::Privilege::SET);
|
||||
break;
|
||||
case AuthQuery::Privilege::AUTH:
|
||||
${builder}.set(i, query::capnp::AuthQuery::Privilege::AUTH);
|
||||
break;
|
||||
case AuthQuery::Privilege::STREAM:
|
||||
${builder}.set(i, query::capnp::AuthQuery::Privilege::STREAM);
|
||||
break;
|
||||
}
|
||||
}
|
||||
cpp<#)
|
||||
:capnp-load
|
||||
(lambda (reader member-name)
|
||||
#>cpp
|
||||
for (auto privilege : ${reader}) {
|
||||
switch (privilege) {
|
||||
case query::capnp::AuthQuery::Privilege::CREATE:
|
||||
${member-name}.push_back(AuthQuery::Privilege::CREATE);
|
||||
break;
|
||||
case query::capnp::AuthQuery::Privilege::DELETE:
|
||||
${member-name}.push_back(AuthQuery::Privilege::DELETE);
|
||||
break;
|
||||
case query::capnp::AuthQuery::Privilege::MATCH:
|
||||
${member-name}.push_back(AuthQuery::Privilege::MATCH);
|
||||
break;
|
||||
case query::capnp::AuthQuery::Privilege::MERGE:
|
||||
${member-name}.push_back(AuthQuery::Privilege::MERGE);
|
||||
break;
|
||||
case query::capnp::AuthQuery::Privilege::SET:
|
||||
${member-name}.push_back(AuthQuery::Privilege::SET);
|
||||
break;
|
||||
case query::capnp::AuthQuery::Privilege::AUTH:
|
||||
${member-name}.push_back(AuthQuery::Privilege::AUTH);
|
||||
break;
|
||||
case query::capnp::AuthQuery::Privilege::STREAM:
|
||||
${member-name}.push_back(AuthQuery::Privilege::STREAM);
|
||||
break;
|
||||
}
|
||||
}
|
||||
cpp<#)))
|
||||
(:public
|
||||
#>cpp
|
||||
AuthHandler(AuthQuery::Action action, std::string user, std::string role,
|
||||
std::string user_or_role, Expression * password,
|
||||
std::vector<AuthQuery::Privilege> privileges);
|
||||
|
||||
bool Accept(HierarchicalLogicalOperatorVisitor &visitor) override;
|
||||
std::unique_ptr<Cursor> MakeCursor(database::GraphDbAccessor & db)
|
||||
const override;
|
||||
virtual std::vector<Symbol> ModifiedSymbols(const SymbolTable &)
|
||||
const override { return {}; }
|
||||
|
||||
bool HasSingleInput() const override;
|
||||
std::shared_ptr<LogicalOperator> input() const override;
|
||||
void set_input(std::shared_ptr<LogicalOperator>) override;
|
||||
cpp<#)
|
||||
(:protected #>cpp AuthHandler() {} cpp<#)
|
||||
(:serialize :capnp))
|
||||
|
||||
(lcp:define-class unwind (logical-operator)
|
||||
((input "std::shared_ptr<LogicalOperator>"
|
||||
:capnp-save #'save-operator-pointer
|
||||
@ -1991,8 +2098,10 @@ Input is optional (unwind can be the first clause in a query).")
|
||||
database::GraphDbAccessor &db) const override;
|
||||
std::vector<Symbol> ModifiedSymbols(const SymbolTable &) const override;
|
||||
|
||||
bool HasSingleInput() const override { return true; }
|
||||
std::shared_ptr<LogicalOperator> input() const override { return input_; }
|
||||
bool HasSingleInput() const override {
|
||||
return true; }
|
||||
std::shared_ptr<LogicalOperator> input() const override {
|
||||
return input_; }
|
||||
void set_input(std::shared_ptr<LogicalOperator> input) override {
|
||||
input_ = input;
|
||||
}
|
||||
@ -2338,70 +2447,6 @@ by having only one result from each worker.")
|
||||
(:private #>cpp PullRemoteOrderBy() {} cpp<#)
|
||||
(:serialize :capnp))
|
||||
|
||||
(lcp:define-class modify-user (logical-operator)
|
||||
((input "std::shared_ptr<LogicalOperator>"
|
||||
:capnp-save #'save-operator-pointer
|
||||
:capnp-load #'load-operator-pointer)
|
||||
(username "std::string" :reader t)
|
||||
(password "Expression *" :reader t
|
||||
:capnp-type "Ast.Tree"
|
||||
:capnp-init nil
|
||||
:capnp-save #'save-ast-pointer
|
||||
:capnp-load (load-ast-pointer "Expression *"))
|
||||
(is-create :bool :reader t))
|
||||
(:documentation
|
||||
"Operator that creates a new database user or modifies an existing one.")
|
||||
(:public
|
||||
#>cpp
|
||||
ModifyUser(std::string username, Expression *password, bool is_create);
|
||||
|
||||
bool Accept(HierarchicalLogicalOperatorVisitor &visitor) override;
|
||||
std::unique_ptr<Cursor> MakeCursor(
|
||||
database::GraphDbAccessor &db) const override;
|
||||
|
||||
std::vector<Symbol> ModifiedSymbols(const SymbolTable &) const override {
|
||||
return std::vector<Symbol>();
|
||||
}
|
||||
|
||||
bool HasSingleInput() const override;
|
||||
std::shared_ptr<LogicalOperator> input() const override;
|
||||
void set_input(std::shared_ptr<LogicalOperator> input) override;
|
||||
cpp<#)
|
||||
(:private
|
||||
#>cpp
|
||||
ModifyUser() {}
|
||||
cpp<#)
|
||||
(:serialize :capnp))
|
||||
|
||||
(lcp:define-class drop-user (logical-operator)
|
||||
((input "std::shared_ptr<LogicalOperator>"
|
||||
:capnp-save #'save-operator-pointer
|
||||
:capnp-load #'load-operator-pointer)
|
||||
(usernames "std::vector<std::string>" :reader t))
|
||||
(:documentation
|
||||
"Operator that deletes one or more existing database users.")
|
||||
(:public
|
||||
#>cpp
|
||||
DropUser(std::vector<std::string> usernames): usernames_(usernames) {}
|
||||
|
||||
bool Accept(HierarchicalLogicalOperatorVisitor &visitor) override;
|
||||
std::unique_ptr<Cursor> MakeCursor(
|
||||
database::GraphDbAccessor &db) const override;
|
||||
|
||||
std::vector<Symbol> ModifiedSymbols(const SymbolTable &) const override {
|
||||
return std::vector<Symbol>();
|
||||
}
|
||||
|
||||
bool HasSingleInput() const override;
|
||||
std::shared_ptr<LogicalOperator> input() const override;
|
||||
void set_input(std::shared_ptr<LogicalOperator> input) override;
|
||||
cpp<#)
|
||||
(:private
|
||||
#>cpp
|
||||
DropUser() {}
|
||||
cpp<#)
|
||||
(:serialize :capnp))
|
||||
|
||||
(lcp:define-class create-stream (logical-operator)
|
||||
((stream-name "std::string" :reader t)
|
||||
(stream-uri "Expression *"
|
||||
|
@ -53,8 +53,7 @@ class UsedSymbolsCollector : public HierarchicalTreeVisitor {
|
||||
bool Visit(PrimitiveLiteral &) override { return true; }
|
||||
bool Visit(ParameterLookup &) override { return true; }
|
||||
bool Visit(query::CreateIndex &) override { return true; }
|
||||
bool Visit(query::ModifyUser &) override { return true; }
|
||||
bool Visit(query::DropUser &) override { return true; }
|
||||
bool Visit(query::AuthQuery &) override { return true; }
|
||||
bool Visit(query::CreateStream &) override { return true; }
|
||||
bool Visit(query::DropStream &) override { return true; }
|
||||
bool Visit(query::ShowStreams &) override { return true; }
|
||||
|
@ -402,12 +402,7 @@ class ReturnBodyContext : public HierarchicalTreeVisitor {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Visit(query::ModifyUser &) override {
|
||||
has_aggregation_.emplace_back(false);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Visit(query::DropUser &) override {
|
||||
bool Visit(query::AuthQuery &) override {
|
||||
has_aggregation_.emplace_back(false);
|
||||
return true;
|
||||
}
|
||||
|
@ -182,15 +182,13 @@ class RuleBasedPlanner {
|
||||
DCHECK(!input_op) << "Unexpected operator before CreateIndex";
|
||||
input_op = std::make_unique<plan::CreateIndex>(
|
||||
create_index->label_, create_index->property_);
|
||||
} else if (auto *modify_user =
|
||||
dynamic_cast<query::ModifyUser *>(clause)) {
|
||||
DCHECK(!input_op) << "Unexpected operator before ModifyUser";
|
||||
input_op = std::make_unique<plan::ModifyUser>(
|
||||
modify_user->username_, modify_user->password_,
|
||||
modify_user->is_create_);
|
||||
} else if (auto *drop_user = dynamic_cast<query::DropUser *>(clause)) {
|
||||
DCHECK(!input_op) << "Unexpected operator before DropUser";
|
||||
input_op = std::make_unique<plan::DropUser>(drop_user->usernames_);
|
||||
} else if (auto *auth_query =
|
||||
dynamic_cast<query::AuthQuery *>(clause)) {
|
||||
DCHECK(!input_op) << "Unexpected operator before AuthQuery";
|
||||
input_op = std::make_unique<plan::AuthHandler>(
|
||||
auth_query->action_, auth_query->user_, auth_query->role_,
|
||||
auth_query->user_or_role_, auth_query->password_,
|
||||
auth_query->privileges_);
|
||||
} else if (auto *create_stream =
|
||||
dynamic_cast<query::CreateStream *>(clause)) {
|
||||
DCHECK(!input_op) << "Unexpected operator before CreateStream";
|
||||
|
@ -514,13 +514,8 @@ class PlanPrinter : public query::plan::HierarchicalLogicalOperatorVisitor {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Visit(query::plan::ModifyUser &op) override {
|
||||
WithPrintLn([](auto &out) { out << "* ModifyUser "; });
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Visit(query::plan::DropUser &op) override {
|
||||
WithPrintLn([](auto &out) { out << "* DropUser"; });
|
||||
bool Visit(query::plan::AuthHandler &op) override {
|
||||
WithPrintLn([](auto &out) { out << "* AuthHandler"; });
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1866,72 +1866,203 @@ TYPED_TEST(CypherMainVisitorTest, UnionAll) {
|
||||
ASSERT_FALSE(return_clause->body_.distinct);
|
||||
}
|
||||
|
||||
TYPED_TEST(CypherMainVisitorTest, ModifyUser) {
|
||||
auto check_modify_user = [](std::string input, std::string username,
|
||||
std::experimental::optional<TypedValue> password,
|
||||
bool is_create) {
|
||||
TypeParam ast_generator(input);
|
||||
auto *query = ast_generator.query_;
|
||||
ASSERT_TRUE(query->single_query_);
|
||||
auto *single_query = query->single_query_;
|
||||
ASSERT_EQ(single_query->clauses_.size(), 1U);
|
||||
auto *create_user = dynamic_cast<ModifyUser *>(single_query->clauses_[0]);
|
||||
ASSERT_TRUE(create_user);
|
||||
EXPECT_EQ(create_user->username_, username);
|
||||
if (password) {
|
||||
ASSERT_NE(create_user->password_, nullptr);
|
||||
CheckLiteral(ast_generator.context_, create_user->password_, *password);
|
||||
} else {
|
||||
EXPECT_EQ(create_user->password_, nullptr);
|
||||
}
|
||||
EXPECT_EQ(create_user->is_create_, is_create);
|
||||
};
|
||||
template <typename AstGeneratorT>
|
||||
void check_auth_query(std::string input, AuthQuery::Action action,
|
||||
std::string user, std::string role,
|
||||
std::string user_or_role,
|
||||
std::experimental::optional<TypedValue> password,
|
||||
std::vector<AuthQuery::Privilege> privileges) {
|
||||
AstGeneratorT ast_generator(input);
|
||||
auto *query = ast_generator.query_;
|
||||
ASSERT_TRUE(query->single_query_ &&
|
||||
query->single_query_->clauses_.size() == 1U);
|
||||
auto auth_query =
|
||||
dynamic_cast<AuthQuery *>(query->single_query_->clauses_[0]);
|
||||
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) {
|
||||
CheckLiteral(ast_generator.context_, auth_query->password_, *password);
|
||||
}
|
||||
EXPECT_EQ(auth_query->privileges_, privileges);
|
||||
}
|
||||
|
||||
check_modify_user("CreaTE UsEr dominik", "dominik",
|
||||
std::experimental::nullopt, true);
|
||||
check_modify_user("CreaTE UsEr dominik WIth PaSSWORD 'spomenik'", "dominik",
|
||||
"spomenik", true);
|
||||
check_modify_user("CreaTE UsEr dominik WIth PaSSWORD NULL", "dominik",
|
||||
TypedValue::Null, true);
|
||||
check_modify_user("AlTeR UsEr dominik", "dominik", std::experimental::nullopt,
|
||||
false);
|
||||
check_modify_user("ALtEr UsEr dominik", "dominik", std::experimental::nullopt,
|
||||
false);
|
||||
check_modify_user("ALtEr UsEr dominik WIth PaSSWORD 'spomenik'", "dominik",
|
||||
"spomenik", false);
|
||||
check_modify_user("ALtEr UsEr dominik WIth PaSSWORD NULL", "dominik",
|
||||
TypedValue::Null, false);
|
||||
EXPECT_THROW(
|
||||
check_modify_user(
|
||||
"CreaTE UsEr dominik WIth PaSSWORD 'spomenik' PaSSwoRD 'u muzeju'",
|
||||
"dominik", "spomenik", true),
|
||||
QueryException);
|
||||
EXPECT_THROW(check_modify_user("CreaTE UsEr dominik WIth PaSSWORD 12345",
|
||||
"dominik", "spomenik", true),
|
||||
TYPED_TEST(CypherMainVisitorTest, UserOrRoleName) {
|
||||
ASSERT_THROW(TypeParam("CREATE ROLE `us|er`"), SyntaxException);
|
||||
ASSERT_THROW(TypeParam("CREATE ROLE `us er`"), SyntaxException);
|
||||
check_auth_query<TypeParam>("CREATE ROLE `user`",
|
||||
AuthQuery::Action::CREATE_ROLE, "", "user", "",
|
||||
{}, {});
|
||||
check_auth_query<TypeParam>("CREATE ROLE us___er",
|
||||
AuthQuery::Action::CREATE_ROLE, "", "us___er", "",
|
||||
{}, {});
|
||||
check_auth_query<TypeParam>("CREATE ROLE `us+er`",
|
||||
AuthQuery::Action::CREATE_ROLE, "", "us+er", "",
|
||||
{}, {});
|
||||
}
|
||||
|
||||
TYPED_TEST(CypherMainVisitorTest, CreateRole) {
|
||||
ASSERT_THROW(TypeParam("CREATE ROLE"), SyntaxException);
|
||||
check_auth_query<TypeParam>("CREATE ROLE rola",
|
||||
AuthQuery::Action::CREATE_ROLE, "", "rola", "",
|
||||
{}, {});
|
||||
ASSERT_THROW(TypeParam("CREATE ROLE lagano rolamo"), SyntaxException);
|
||||
}
|
||||
|
||||
TYPED_TEST(CypherMainVisitorTest, DropRole) {
|
||||
ASSERT_THROW(TypeParam("DROP ROLE"), SyntaxException);
|
||||
check_auth_query<TypeParam>("DROP ROLE rola", AuthQuery::Action::DROP_ROLE,
|
||||
"", "rola", "", {}, {});
|
||||
ASSERT_THROW(TypeParam("DROP ROLE lagano rolamo"), SyntaxException);
|
||||
}
|
||||
|
||||
TYPED_TEST(CypherMainVisitorTest, ShowRoles) {
|
||||
ASSERT_THROW(TypeParam("SHOW ROLES ROLES"), SyntaxException);
|
||||
check_auth_query<TypeParam>("SHOW ROLES", AuthQuery::Action::SHOW_ROLES, "",
|
||||
"", "", {}, {});
|
||||
}
|
||||
|
||||
TYPED_TEST(CypherMainVisitorTest, CreateUser) {
|
||||
ASSERT_THROW(TypeParam("CREATE USER"), SyntaxException);
|
||||
ASSERT_THROW(TypeParam("CREATE USER 123"), SyntaxException);
|
||||
check_auth_query<TypeParam>("CREATE USER user",
|
||||
AuthQuery::Action::CREATE_USER, "user", "", "",
|
||||
{}, {});
|
||||
check_auth_query<TypeParam>("CREATE USER user IDENTIFIED BY 'password'",
|
||||
AuthQuery::Action::CREATE_USER, "user", "", "",
|
||||
"password", {});
|
||||
check_auth_query<TypeParam>("CREATE USER user IDENTIFIED BY ''",
|
||||
AuthQuery::Action::CREATE_USER, "user", "", "",
|
||||
"", {});
|
||||
check_auth_query<TypeParam>("CREATE USER user IDENTIFIED BY null",
|
||||
AuthQuery::Action::CREATE_USER, "user", "", "",
|
||||
TypedValue::Null, {});
|
||||
ASSERT_THROW(TypeParam("CRATE USER user IDENTIFIED BY password"),
|
||||
SyntaxException);
|
||||
ASSERT_THROW(TypeParam("CREATE USER user IDENTIFIED BY 5"), SyntaxException);
|
||||
ASSERT_THROW(TypeParam("CREATE USER user IDENTIFIED BY "), SyntaxException);
|
||||
}
|
||||
|
||||
TYPED_TEST(CypherMainVisitorTest, SetPassword) {
|
||||
ASSERT_THROW(TypeParam("SET PASSWORD FOR"), SyntaxException);
|
||||
ASSERT_THROW(TypeParam("SET PASSWORD FOR user "), SyntaxException);
|
||||
check_auth_query<TypeParam>("SET PASSWORD FOR user TO null",
|
||||
AuthQuery::Action::SET_PASSWORD, "user", "", "",
|
||||
TypedValue::Null, {});
|
||||
check_auth_query<TypeParam>("SET PASSWORD FOR user TO 'password'",
|
||||
AuthQuery::Action::SET_PASSWORD, "user", "", "",
|
||||
"password", {});
|
||||
ASSERT_THROW(TypeParam("SET PASSWORD FOR user To 5"), SyntaxException);
|
||||
}
|
||||
|
||||
TYPED_TEST(CypherMainVisitorTest, DropUser) {
|
||||
auto check_drop_user = [](std::string input,
|
||||
const std::vector<std::string> &usernames) {
|
||||
TypeParam ast_generator(input);
|
||||
auto *query = ast_generator.query_;
|
||||
ASSERT_TRUE(query->single_query_);
|
||||
auto *single_query = query->single_query_;
|
||||
ASSERT_EQ(single_query->clauses_.size(), 1U);
|
||||
auto *drop_user = dynamic_cast<DropUser *>(single_query->clauses_[0]);
|
||||
ASSERT_TRUE(drop_user);
|
||||
EXPECT_EQ(drop_user->usernames_, usernames);
|
||||
};
|
||||
ASSERT_THROW(TypeParam("DROP USER"), SyntaxException);
|
||||
check_auth_query<TypeParam>("DROP USER user", AuthQuery::Action::DROP_USER,
|
||||
"user", "", "", {}, {});
|
||||
ASSERT_THROW(TypeParam("DROP USER lagano rolamo"), SyntaxException);
|
||||
}
|
||||
|
||||
EXPECT_THROW(check_drop_user("DrOp USER", {}), SyntaxException);
|
||||
check_drop_user("DrOP UsEr dominik", {"dominik"});
|
||||
check_drop_user("DrOP USER dominik , spomenik", {"dominik", "spomenik"});
|
||||
EXPECT_THROW(
|
||||
check_drop_user("DrOP USER dominik, , spomenik", {"dominik", "spomenik"}),
|
||||
SyntaxException);
|
||||
check_drop_user("DrOP USER dominik , spomenik , jackie, jackie , johnny",
|
||||
{"dominik", "spomenik", "jackie", "jackie", "johnny"});
|
||||
TYPED_TEST(CypherMainVisitorTest, ShowUsers) {
|
||||
ASSERT_THROW(TypeParam("SHOW USERS ROLES"), SyntaxException);
|
||||
check_auth_query<TypeParam>("SHOW USERS", AuthQuery::Action::SHOW_USERS, "",
|
||||
"", "", {}, {});
|
||||
}
|
||||
|
||||
TYPED_TEST(CypherMainVisitorTest, GrantRole) {
|
||||
ASSERT_THROW(TypeParam("GRANT ROLE"), SyntaxException);
|
||||
ASSERT_THROW(TypeParam("GRANT ROLE role"), SyntaxException);
|
||||
ASSERT_THROW(TypeParam("GRANT ROLE role TO"), SyntaxException);
|
||||
ASSERT_THROW(TypeParam("GRANT ROLE TO user"), SyntaxException);
|
||||
check_auth_query<TypeParam>("GRANT ROLE role TO user",
|
||||
AuthQuery::Action::GRANT_ROLE, "user", "role", "",
|
||||
{}, {});
|
||||
}
|
||||
|
||||
TYPED_TEST(CypherMainVisitorTest, RevokeRole) {
|
||||
ASSERT_THROW(TypeParam("REVOKE ROLE"), SyntaxException);
|
||||
ASSERT_THROW(TypeParam("REVOKE ROLE role"), SyntaxException);
|
||||
ASSERT_THROW(TypeParam("REVOKE ROLE role FROM"), SyntaxException);
|
||||
ASSERT_THROW(TypeParam("REVOKE ROLE FROM user"), SyntaxException);
|
||||
check_auth_query<TypeParam>("REVOKE ROLE role FROM user",
|
||||
AuthQuery::Action::REVOKE_ROLE, "user", "role",
|
||||
"", {}, {});
|
||||
}
|
||||
|
||||
TYPED_TEST(CypherMainVisitorTest, GrantPrivilege) {
|
||||
ASSERT_THROW(TypeParam("GRANT"), SyntaxException);
|
||||
ASSERT_THROW(TypeParam("GRANT TO user"), SyntaxException);
|
||||
ASSERT_THROW(TypeParam("GRANT BLABLA TO user"), SyntaxException);
|
||||
ASSERT_THROW(TypeParam("GRANT MATCH, TO user"), SyntaxException);
|
||||
ASSERT_THROW(TypeParam("GRANT MATCH, BLABLA TO user"), SyntaxException);
|
||||
check_auth_query<TypeParam>("GRANT MATCH TO user",
|
||||
AuthQuery::Action::GRANT_PRIVILEGE, "", "",
|
||||
"user", {}, {AuthQuery::Privilege::MATCH});
|
||||
check_auth_query<TypeParam>(
|
||||
"GRANT MATCH, AUTH TO user", AuthQuery::Action::GRANT_PRIVILEGE, "", "",
|
||||
"user", {}, {AuthQuery::Privilege::MATCH, AuthQuery::Privilege::AUTH});
|
||||
}
|
||||
|
||||
TYPED_TEST(CypherMainVisitorTest, DenyPrivilege) {
|
||||
ASSERT_THROW(TypeParam("DENY"), SyntaxException);
|
||||
ASSERT_THROW(TypeParam("DENY TO user"), SyntaxException);
|
||||
ASSERT_THROW(TypeParam("DENY BLABLA TO user"), SyntaxException);
|
||||
ASSERT_THROW(TypeParam("DENY MATCH, TO user"), SyntaxException);
|
||||
ASSERT_THROW(TypeParam("DENY MATCH, BLABLA TO user"), SyntaxException);
|
||||
check_auth_query<TypeParam>("DENY MATCH TO user",
|
||||
AuthQuery::Action::DENY_PRIVILEGE, "", "",
|
||||
"user", {}, {AuthQuery::Privilege::MATCH});
|
||||
check_auth_query<TypeParam>(
|
||||
"DENY MATCH, AUTH TO user", AuthQuery::Action::DENY_PRIVILEGE, "", "",
|
||||
"user", {}, {AuthQuery::Privilege::MATCH, AuthQuery::Privilege::AUTH});
|
||||
}
|
||||
|
||||
TYPED_TEST(CypherMainVisitorTest, RevokePrivilege) {
|
||||
ASSERT_THROW(TypeParam("REVOKE"), SyntaxException);
|
||||
ASSERT_THROW(TypeParam("REVOKE FROM user"), SyntaxException);
|
||||
ASSERT_THROW(TypeParam("REVOKE BLABLA FROM user"), SyntaxException);
|
||||
ASSERT_THROW(TypeParam("REVOKE MATCH, FROM user"), SyntaxException);
|
||||
ASSERT_THROW(TypeParam("REVOKE MATCH, BLABLA FROM user"), SyntaxException);
|
||||
check_auth_query<TypeParam>("REVOKE MATCH FROM user",
|
||||
AuthQuery::Action::REVOKE_PRIVILEGE, "", "",
|
||||
"user", {}, {AuthQuery::Privilege::MATCH});
|
||||
check_auth_query<TypeParam>(
|
||||
"REVOKE MATCH, AUTH FROM user", AuthQuery::Action::REVOKE_PRIVILEGE, "",
|
||||
"", "user", {},
|
||||
{AuthQuery::Privilege::MATCH, AuthQuery::Privilege::AUTH});
|
||||
check_auth_query<TypeParam>(
|
||||
"REVOKE ALL PRIVILEGES FROM user", AuthQuery::Action::REVOKE_PRIVILEGE,
|
||||
"", "", "user", {},
|
||||
{AuthQuery::Privilege::CREATE, AuthQuery::Privilege::DELETE,
|
||||
AuthQuery::Privilege::MATCH, AuthQuery::Privilege::MERGE,
|
||||
AuthQuery::Privilege::SET, AuthQuery::Privilege::AUTH,
|
||||
AuthQuery::Privilege::STREAM});
|
||||
}
|
||||
|
||||
TYPED_TEST(CypherMainVisitorTest, ShowGrants) {
|
||||
ASSERT_THROW(TypeParam("SHOW GRANTS FOR"), SyntaxException);
|
||||
check_auth_query<TypeParam>("SHOW GRANTS FOR user",
|
||||
AuthQuery::Action::SHOW_GRANTS, "", "", "user",
|
||||
{}, {});
|
||||
ASSERT_THROW(TypeParam("SHOW GRANTS FOR user1, user2"), SyntaxException);
|
||||
}
|
||||
|
||||
TYPED_TEST(CypherMainVisitorTest, ShowRoleForUser) {
|
||||
ASSERT_THROW(TypeParam("SHOW ROLE FOR USER"), SyntaxException);
|
||||
check_auth_query<TypeParam>("SHOW ROLE FOR USER user",
|
||||
AuthQuery::Action::SHOW_ROLE_FOR_USER, "user", "",
|
||||
"", {}, {});
|
||||
ASSERT_THROW(TypeParam("SHOW ROLE FOR USER user1, user2"), SyntaxException);
|
||||
}
|
||||
|
||||
TYPED_TEST(CypherMainVisitorTest, ShowUsersForRole) {
|
||||
ASSERT_THROW(TypeParam("SHOW USERS FOR ROLE"), SyntaxException);
|
||||
check_auth_query<TypeParam>("SHOW USERS FOR ROLE role",
|
||||
AuthQuery::Action::SHOW_USERS_FOR_ROLE, "",
|
||||
"role", "", {}, {});
|
||||
ASSERT_THROW(TypeParam("SHOW USERS FOR ROLE role1, role2"), SyntaxException);
|
||||
}
|
||||
|
||||
TYPED_TEST(CypherMainVisitorTest, CreateStream) {
|
||||
|
@ -574,10 +574,9 @@ auto GetMerge(AstStorage &storage, Pattern *pattern, OnMatch on_match,
|
||||
#define EXTRACT(variable, list, expr) \
|
||||
storage.Create<query::Extract>(storage.Create<query::Identifier>(variable), \
|
||||
list, expr)
|
||||
#define CREATE_USER(username, password) \
|
||||
storage.Create<query::ModifyUser>((username), LITERAL(password), true)
|
||||
#define ALTER_USER(username, password) \
|
||||
storage.Create<query::ModifyUser>((username), LITERAL(password), false)
|
||||
#define AUTH_QUERY(action, user, role, user_or_role, password, privileges) \
|
||||
storage.Create<query::AuthQuery>((action), (user), (role), (user_or_role), \
|
||||
LITERAL(password), (privileges))
|
||||
#define DROP_USER(usernames) storage.Create<query::DropUser>((usernames))
|
||||
#define CREATE_STREAM(stream_name, stream_uri, stream_topic, transform_uri, \
|
||||
batch_interval, batch_size) \
|
||||
|
@ -132,8 +132,7 @@ class PlanChecker : public HierarchicalLogicalOperatorVisitor {
|
||||
|
||||
PRE_VISIT(PullRemoteOrderBy);
|
||||
|
||||
VISIT(ModifyUser);
|
||||
VISIT(DropUser);
|
||||
VISIT(AuthHandler);
|
||||
|
||||
VISIT(CreateStream);
|
||||
VISIT(DropStream);
|
||||
@ -377,6 +376,37 @@ class ExpectScanAllByLabelPropertyRange
|
||||
std::experimental::optional<Bound> upper_bound_;
|
||||
};
|
||||
|
||||
class ExpectAuthHandler : public OpChecker<AuthHandler> {
|
||||
public:
|
||||
ExpectAuthHandler(query::AuthQuery::Action action, std::string user,
|
||||
std::string role, std::string user_or_role,
|
||||
query::Expression *password,
|
||||
std::vector<query::AuthQuery::Privilege> privileges)
|
||||
: action_(action),
|
||||
user_(user),
|
||||
role_(role),
|
||||
user_or_role_(user_or_role),
|
||||
password_(password),
|
||||
privileges_(privileges) {}
|
||||
|
||||
void ExpectOp(AuthHandler &auth_handler, const SymbolTable &) override {
|
||||
EXPECT_EQ(auth_handler.action(), action_);
|
||||
EXPECT_EQ(auth_handler.user(), user_);
|
||||
EXPECT_EQ(auth_handler.role(), role_);
|
||||
EXPECT_EQ(auth_handler.user_or_role(), user_or_role_);
|
||||
EXPECT_TRUE(auth_handler.password());
|
||||
EXPECT_EQ(auth_handler.privileges(), privileges_);
|
||||
}
|
||||
|
||||
private:
|
||||
query::AuthQuery::Action action_;
|
||||
std::string user_;
|
||||
std::string role_;
|
||||
std::string user_or_role_;
|
||||
query::Expression *password_{nullptr};
|
||||
std::vector<query::AuthQuery::Privilege> privileges_;
|
||||
};
|
||||
|
||||
class ExpectCreateIndex : public OpChecker<CreateIndex> {
|
||||
public:
|
||||
ExpectCreateIndex(storage::Label label, storage::Property property)
|
||||
@ -623,36 +653,6 @@ class Planner {
|
||||
std::unique_ptr<LogicalOperator> plan_;
|
||||
};
|
||||
|
||||
class ExpectModifyUser : public OpChecker<ModifyUser> {
|
||||
public:
|
||||
ExpectModifyUser(std::string username, bool is_create)
|
||||
: username_(username), is_create_(is_create) {}
|
||||
|
||||
void ExpectOp(ModifyUser &modify_user, const SymbolTable &) override {
|
||||
EXPECT_EQ(username_, modify_user.username());
|
||||
// TODO(mtomic): proper password verification
|
||||
EXPECT_NE(dynamic_cast<query::Expression *>(modify_user.password()),
|
||||
nullptr);
|
||||
EXPECT_EQ(is_create_, modify_user.is_create());
|
||||
}
|
||||
|
||||
private:
|
||||
std::string username_;
|
||||
bool is_create_;
|
||||
};
|
||||
|
||||
class ExpectDropUser : public OpChecker<DropUser> {
|
||||
public:
|
||||
ExpectDropUser(std::vector<std::string> usernames) : usernames_(usernames) {}
|
||||
|
||||
void ExpectOp(DropUser &drop_user, const SymbolTable &) override {
|
||||
EXPECT_EQ(usernames_, drop_user.usernames());
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<std::string> usernames_;
|
||||
};
|
||||
|
||||
void SavePlan(const LogicalOperator &plan, ::capnp::MessageBuilder *message) {
|
||||
auto builder = message->initRoot<query::plan::capnp::LogicalOperator>();
|
||||
LogicalOperator::SaveHelper helper;
|
||||
@ -2076,8 +2076,9 @@ TYPED_TEST(TestPlanner, WhereIndexedLabelPropertyRange) {
|
||||
AstStorage storage;
|
||||
auto lit_42 = LITERAL(42);
|
||||
auto n_prop = PROPERTY_LOOKUP("n", property);
|
||||
auto check_planned_range = [&label, &property, &dba](
|
||||
const auto &rel_expr, auto lower_bound, auto upper_bound) {
|
||||
auto check_planned_range = [&label, &property, &dba](const auto &rel_expr,
|
||||
auto lower_bound,
|
||||
auto upper_bound) {
|
||||
// Shadow the first storage, so that the query is created in this one.
|
||||
AstStorage storage;
|
||||
QUERY(SINGLE_QUERY(MATCH(PATTERN(NODE("n", label))), WHERE(rel_expr),
|
||||
@ -2318,36 +2319,25 @@ TYPED_TEST(TestPlanner, ReturnAsteriskOmitsLambdaSymbols) {
|
||||
}
|
||||
}
|
||||
|
||||
TYPED_TEST(TestPlanner, ModifyUser) {
|
||||
{
|
||||
// Test CREATE USER user WITH PASSWORD 'password'
|
||||
FakeDbAccessor dba;
|
||||
AstStorage storage;
|
||||
QUERY(SINGLE_QUERY(CREATE_USER("user", "password")));
|
||||
CheckPlan<TypeParam>(storage, ExpectModifyUser("user", true));
|
||||
auto expected =
|
||||
ExpectDistributed(MakeCheckers(ExpectModifyUser("user", true)));
|
||||
CheckDistributedPlan<TypeParam>(storage, expected);
|
||||
}
|
||||
{
|
||||
// Test ALTER USER user WITH PASSWORD 'password'
|
||||
FakeDbAccessor dba;
|
||||
AstStorage storage;
|
||||
QUERY(SINGLE_QUERY(ALTER_USER("user", "password")));
|
||||
CheckPlan<TypeParam>(storage, ExpectModifyUser("user", false));
|
||||
auto expected =
|
||||
ExpectDistributed(MakeCheckers(ExpectModifyUser("user", false)));
|
||||
CheckDistributedPlan<TypeParam>(storage, expected);
|
||||
}
|
||||
}
|
||||
|
||||
TYPED_TEST(TestPlanner, DropUser) {
|
||||
// Test DROP USER user1, user2, user3
|
||||
TYPED_TEST(TestPlanner, AuthQuery) {
|
||||
// Check if everything is properly forwarded from ast node to the operator
|
||||
FakeDbAccessor dba;
|
||||
AstStorage storage;
|
||||
std::vector<std::string> usernames({"user1", "user2", "user3"});
|
||||
QUERY(SINGLE_QUERY(DROP_USER(usernames)));
|
||||
CheckPlan<TypeParam>(storage, ExpectDropUser(usernames));
|
||||
auto expected = ExpectDistributed(MakeCheckers(ExpectDropUser(usernames)));
|
||||
QUERY(SINGLE_QUERY(AUTH_QUERY(query::AuthQuery::Action::DROP_ROLE, "user",
|
||||
"role", "user_or_role", LITERAL("password"),
|
||||
std::vector<query::AuthQuery::Privilege>(
|
||||
{query::AuthQuery::Privilege::MATCH,
|
||||
query::AuthQuery::Privilege::AUTH}))));
|
||||
CheckPlan<TypeParam>(
|
||||
storage, ExpectAuthHandler(query::AuthQuery::Action::DROP_ROLE, "user",
|
||||
"role", "user_or_role", LITERAL("password"),
|
||||
{query::AuthQuery::Privilege::MATCH,
|
||||
query::AuthQuery::Privilege::AUTH}));
|
||||
auto expected = ExpectDistributed(MakeCheckers(
|
||||
ExpectAuthHandler(query::AuthQuery::Action::DROP_ROLE, "user", "role",
|
||||
"user_or_role", LITERAL("password"),
|
||||
{query::AuthQuery::Privilege::MATCH,
|
||||
query::AuthQuery::Privilege::AUTH})));
|
||||
CheckDistributedPlan<TypeParam>(storage, expected);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user