diff --git a/programs/server/config.xml b/programs/server/config.xml
index e0d527f9538..f55ab02d903 100644
--- a/programs/server/config.xml
+++ b/programs/server/config.xml
@@ -128,6 +128,9 @@
/var/lib/clickhouse/user_files/
+
+ /var/lib/clickhouse/access/
+
users.xml
diff --git a/programs/server/users.xml b/programs/server/users.xml
index d631fbb0f8a..3d95269190b 100644
--- a/programs/server/users.xml
+++ b/programs/server/users.xml
@@ -83,6 +83,9 @@
default
+
+
+
diff --git a/src/Access/AccessControlManager.cpp b/src/Access/AccessControlManager.cpp
index b5e06549c28..f8f15e425ed 100644
--- a/src/Access/AccessControlManager.cpp
+++ b/src/Access/AccessControlManager.cpp
@@ -23,7 +23,10 @@ namespace
std::vector> list;
list.emplace_back(std::make_unique());
list.emplace_back(std::make_unique());
+
+#if 0 /// Memory access storage is disabled.
list.emplace_back(std::make_unique());
+#endif
return list;
}
diff --git a/src/Access/AccessFlags.h b/src/Access/AccessFlags.h
index 2c5307bbd1a..c8f57fcd419 100644
--- a/src/Access/AccessFlags.h
+++ b/src/Access/AccessFlags.h
@@ -5,12 +5,19 @@
#include
#include
#include
+#include
+#include
#include
#include
namespace DB
{
+namespace ErrorCodes
+{
+ extern const int LOGICAL_ERROR;
+}
+
/// Represents a combination of access types which can be granted globally, on databases, tables, columns, etc.
/// For example "SELECT, CREATE USER" is an access type.
class AccessFlags
@@ -175,9 +182,10 @@ public:
const Flags & getDictionaryFlags() const { return all_flags_for_target[DICTIONARY]; }
private:
- enum Target
+ enum NodeType
{
- UNKNOWN_TARGET,
+ UNKNOWN = -2,
+ GROUP = -1,
GLOBAL,
DATABASE,
TABLE,
@@ -186,46 +194,190 @@ private:
DICTIONARY,
};
- static constexpr size_t NUM_TARGETS = static_cast(DICTIONARY) + 1;
-
struct Node;
using NodePtr = std::unique_ptr;
- using Nodes = std::vector;
-
- template
- static Nodes nodes(Args&& ... args)
- {
- Nodes res;
- ext::push_back(res, std::move(args)...);
- return res;
- }
struct Node
{
- std::string_view keyword;
- std::vector aliases;
+ const String keyword;
+ NodeType node_type;
+ AccessType type = AccessType::NONE;
+ Strings aliases;
Flags flags;
- Target target = UNKNOWN_TARGET;
- Nodes children;
+ std::vector children;
- Node(std::string_view keyword_, size_t flag_, Target target_)
- : keyword(keyword_), target(target_)
+ Node(String keyword_, NodeType node_type_ = UNKNOWN) : keyword(std::move(keyword_)), node_type(node_type_) {}
+
+ void setFlag(size_t flag) { flags.set(flag); }
+
+ void addChild(NodePtr child)
{
- flags.set(flag_);
+ flags |= child->flags;
+ children.push_back(std::move(child));
}
-
- Node(std::string_view keyword_, Nodes children_)
- : keyword(keyword_), children(std::move(children_))
- {
- for (const auto & child : children)
- flags |= child->flags;
- }
-
- template
- Node(std::string_view keyword_, NodePtr first_child, Args &&... other_children)
- : Node(keyword_, nodes(std::move(first_child), std::move(other_children)...)) {}
};
+ static String replaceUnderscoreWithSpace(const std::string_view & str)
+ {
+ String res{str};
+ boost::replace_all(res, "_", " ");
+ return res;
+ }
+
+ static Strings splitAliases(const std::string_view & str)
+ {
+ Strings aliases;
+ boost::split(aliases, str, boost::is_any_of(","));
+ for (auto & alias : aliases)
+ boost::trim(alias);
+ return aliases;
+ }
+
+ static void makeFlagsToKeywordTreeNode(
+ AccessType type,
+ const std::string_view & name,
+ const std::string_view & aliases,
+ NodeType node_type,
+ const std::string_view & parent_group_name,
+ std::unordered_map & nodes,
+ std::unordered_map & owned_nodes,
+ size_t & next_flag)
+ {
+ NodePtr node;
+ auto keyword = replaceUnderscoreWithSpace(name);
+ auto it = owned_nodes.find(keyword);
+ if (it != owned_nodes.end())
+ {
+ node = std::move(it->second);
+ owned_nodes.erase(it);
+ }
+ else
+ {
+ if (nodes.contains(keyword))
+ throw Exception(keyword + " declared twice", ErrorCodes::LOGICAL_ERROR);
+ node = std::make_unique(keyword, node_type);
+ nodes[node->keyword] = node.get();
+ }
+
+ node->type = type;
+ node->node_type = node_type;
+ node->aliases = splitAliases(aliases);
+ if (node_type != GROUP)
+ node->setFlag(next_flag++);
+
+ bool has_parent_group = (parent_group_name != "NONE");
+ if (!has_parent_group)
+ {
+ std::string_view keyword_as_string_view = node->keyword;
+ owned_nodes[keyword_as_string_view] = std::move(node);
+ return;
+ }
+
+ auto parent_keyword = replaceUnderscoreWithSpace(parent_group_name);
+ auto it_parent = nodes.find(parent_keyword);
+ if (it_parent == nodes.end())
+ {
+ auto parent_node = std::make_unique(parent_keyword);
+ it_parent = nodes.emplace(parent_node->keyword, parent_node.get()).first;
+ assert(!owned_nodes.contains(parent_node->keyword));
+ std::string_view parent_keyword_as_string_view = parent_node->keyword;
+ owned_nodes[parent_keyword_as_string_view] = std::move(parent_node);
+ }
+ it_parent->second->addChild(std::move(node));
+ }
+
+ void makeFlagsToKeywordTree()
+ {
+ std::unordered_map owned_nodes;
+ std::unordered_map nodes;
+ size_t next_flag = 0;
+
+#define MAKE_ACCESS_FLAGS_TO_KEYWORD_TREE_NODE(name, aliases, node_type, parent_group_name) \
+ makeFlagsToKeywordTreeNode(AccessType::name, #name, aliases, node_type, #parent_group_name, nodes, owned_nodes, next_flag);
+
+ APPLY_FOR_ACCESS_TYPES(MAKE_ACCESS_FLAGS_TO_KEYWORD_TREE_NODE)
+
+#undef MAKE_ACCESS_FLAGS_TO_KEYWORD_TREE_NODE
+
+ if (!owned_nodes.contains("NONE"))
+ throw Exception("'NONE' not declared", ErrorCodes::LOGICAL_ERROR);
+ if (!owned_nodes.contains("ALL"))
+ throw Exception("'ALL' not declared", ErrorCodes::LOGICAL_ERROR);
+
+ flags_to_keyword_tree = std::move(owned_nodes["ALL"]);
+ none_node = std::move(owned_nodes["NONE"]);
+ owned_nodes.erase("ALL");
+ owned_nodes.erase("NONE");
+
+ if (!owned_nodes.empty())
+ {
+ const auto & unused_node = *(owned_nodes.begin()->second);
+ if (unused_node.node_type == UNKNOWN)
+ throw Exception("Parent group '" + unused_node.keyword + "' not found", ErrorCodes::LOGICAL_ERROR);
+ else
+ throw Exception("Access type '" + unused_node.keyword + "' should have parent group", ErrorCodes::LOGICAL_ERROR);
+ }
+ }
+
+ void makeKeywordToFlagsMap(Node * start_node = nullptr)
+ {
+ if (!start_node)
+ {
+ makeKeywordToFlagsMap(none_node.get());
+ start_node = flags_to_keyword_tree.get();
+ }
+
+ start_node->aliases.emplace_back(start_node->keyword);
+ for (auto & alias : start_node->aliases)
+ {
+ boost::to_upper(alias);
+ keyword_to_flags_map[alias] = start_node->flags;
+ }
+
+ for (auto & child : start_node->children)
+ makeKeywordToFlagsMap(child.get());
+ }
+
+ void makeAccessTypeToFlagsMapping(Node * start_node = nullptr)
+ {
+ if (!start_node)
+ {
+ makeAccessTypeToFlagsMapping(none_node.get());
+ start_node = flags_to_keyword_tree.get();
+ }
+
+ size_t index = static_cast(start_node->type);
+ access_type_to_flags_mapping.resize(std::max(index + 1, access_type_to_flags_mapping.size()));
+ access_type_to_flags_mapping[index] = start_node->flags;
+
+ for (auto & child : start_node->children)
+ makeAccessTypeToFlagsMapping(child.get());
+ }
+
+ void collectAllFlags(const Node * start_node = nullptr)
+ {
+ if (!start_node)
+ {
+ start_node = flags_to_keyword_tree.get();
+ all_flags = start_node->flags;
+ }
+ if (start_node->node_type != GROUP)
+ {
+ assert(static_cast(start_node->node_type) < std::size(all_flags_for_target));
+ all_flags_for_target[start_node->node_type] |= start_node->flags;
+ }
+ for (const auto & child : start_node->children)
+ collectAllFlags(child.get());
+ }
+
+ Impl()
+ {
+ makeFlagsToKeywordTree();
+ makeKeywordToFlagsMap();
+ makeAccessTypeToFlagsMapping();
+ collectAllFlags();
+ }
+
static void flagsToKeywordsRec(const Flags & flags_, std::vector & keywords, const Node & start_node)
{
Flags matching_flags = (flags_ & start_node.flags);
@@ -243,275 +395,12 @@ private:
}
}
- static NodePtr makeFlagsToKeywordTree()
- {
- size_t next_flag = 0;
- Nodes all;
-
- auto show_databases = std::make_unique("SHOW DATABASES", next_flag++, DATABASE);
- auto show_tables = std::make_unique("SHOW TABLES", next_flag++, TABLE);
- auto show_columns = std::make_unique("SHOW COLUMNS", next_flag++, COLUMN);
- auto show_dictionaries = std::make_unique("SHOW DICTIONARIES", next_flag++, DICTIONARY);
- auto show = std::make_unique("SHOW", std::move(show_databases), std::move(show_tables), std::move(show_columns), std::move(show_dictionaries));
- ext::push_back(all, std::move(show));
-
- auto select = std::make_unique("SELECT", next_flag++, COLUMN);
- auto insert = std::make_unique("INSERT", next_flag++, COLUMN);
- ext::push_back(all, std::move(select), std::move(insert));
-
- auto update = std::make_unique("UPDATE", next_flag++, COLUMN);
- ext::push_back(update->aliases, "ALTER UPDATE");
- auto delet = std::make_unique("DELETE", next_flag++, TABLE);
- ext::push_back(delet->aliases, "ALTER DELETE");
-
- auto add_column = std::make_unique("ADD COLUMN", next_flag++, COLUMN);
- add_column->aliases.push_back("ALTER ADD COLUMN");
- auto modify_column = std::make_unique("MODIFY COLUMN", next_flag++, COLUMN);
- modify_column->aliases.push_back("ALTER MODIFY COLUMN");
- auto drop_column = std::make_unique("DROP COLUMN", next_flag++, COLUMN);
- drop_column->aliases.push_back("ALTER DROP COLUMN");
- auto comment_column = std::make_unique("COMMENT COLUMN", next_flag++, COLUMN);
- comment_column->aliases.push_back("ALTER COMMENT COLUMN");
- auto clear_column = std::make_unique("CLEAR COLUMN", next_flag++, COLUMN);
- clear_column->aliases.push_back("ALTER CLEAR COLUMN");
- auto rename_column = std::make_unique("RENAME COLUMN", next_flag++, COLUMN);
- rename_column->aliases.push_back("ALTER RENAME COLUMN");
-
- auto alter_column = std::make_unique(
- "ALTER COLUMN",
- std::move(add_column),
- std::move(modify_column),
- std::move(drop_column),
- std::move(comment_column),
- std::move(clear_column),
- std::move(rename_column));
-
- auto alter_order_by = std::make_unique("ALTER ORDER BY", next_flag++, TABLE);
- alter_order_by->aliases.push_back("MODIFY ORDER BY");
- alter_order_by->aliases.push_back("ALTER MODIFY ORDER BY");
- auto add_index = std::make_unique("ADD INDEX", next_flag++, TABLE);
- add_index->aliases.push_back("ALTER ADD INDEX");
- auto drop_index = std::make_unique("DROP INDEX", next_flag++, TABLE);
- drop_index->aliases.push_back("ALTER DROP INDEX");
- auto materialize_index = std::make_unique("MATERIALIZE INDEX", next_flag++, TABLE);
- materialize_index->aliases.push_back("ALTER MATERIALIZE INDEX");
- auto clear_index = std::make_unique("CLEAR INDEX", next_flag++, TABLE);
- clear_index->aliases.push_back("ALTER CLEAR INDEX");
- auto index = std::make_unique("INDEX", std::move(alter_order_by), std::move(add_index), std::move(drop_index), std::move(materialize_index), std::move(clear_index));
- index->aliases.push_back("ALTER INDEX");
-
- auto add_constraint = std::make_unique("ADD CONSTRAINT", next_flag++, TABLE);
- add_constraint->aliases.push_back("ALTER ADD CONSTRAINT");
- auto drop_constraint = std::make_unique("DROP CONSTRAINT", next_flag++, TABLE);
- drop_constraint->aliases.push_back("ALTER DROP CONSTRAINT");
- auto alter_constraint = std::make_unique("CONSTRAINT", std::move(add_constraint), std::move(drop_constraint));
- alter_constraint->aliases.push_back("ALTER CONSTRAINT");
-
- auto modify_ttl = std::make_unique("MODIFY TTL", next_flag++, TABLE);
- modify_ttl->aliases.push_back("ALTER MODIFY TTL");
- auto materialize_ttl = std::make_unique("MATERIALIZE TTL", next_flag++, TABLE);
- materialize_ttl->aliases.push_back("ALTER MATERIALIZE TTL");
-
- auto modify_setting = std::make_unique("MODIFY SETTING", next_flag++, TABLE);
- modify_setting->aliases.push_back("ALTER MODIFY SETTING");
-
- auto move_partition = std::make_unique("MOVE PARTITION", next_flag++, TABLE);
- ext::push_back(move_partition->aliases, "ALTER MOVE PARTITION", "MOVE PART", "ALTER MOVE PART");
- auto fetch_partition = std::make_unique("FETCH PARTITION", next_flag++, TABLE);
- ext::push_back(fetch_partition->aliases, "ALTER FETCH PARTITION");
- auto freeze_partition = std::make_unique("FREEZE PARTITION", next_flag++, TABLE);
- ext::push_back(freeze_partition->aliases, "ALTER FREEZE PARTITION");
-
- auto alter_table = std::make_unique("ALTER TABLE", std::move(update), std::move(delet), std::move(alter_column), std::move(index), std::move(alter_constraint), std::move(modify_ttl), std::move(materialize_ttl), std::move(modify_setting), std::move(move_partition), std::move(fetch_partition), std::move(freeze_partition));
-
- auto refresh_view = std::make_unique("REFRESH VIEW", next_flag++, VIEW);
- ext::push_back(refresh_view->aliases, "ALTER LIVE VIEW REFRESH");
- auto modify_view_query = std::make_unique("MODIFY VIEW QUERY", next_flag++, VIEW);
- auto alter_view = std::make_unique("ALTER VIEW", std::move(refresh_view), std::move(modify_view_query));
-
- auto alter = std::make_unique("ALTER", std::move(alter_table), std::move(alter_view));
- ext::push_back(all, std::move(alter));
-
- auto create_database = std::make_unique("CREATE DATABASE", next_flag++, DATABASE);
- auto create_table = std::make_unique("CREATE TABLE", next_flag++, TABLE);
- auto create_view = std::make_unique("CREATE VIEW", next_flag++, VIEW);
- auto create_dictionary = std::make_unique("CREATE DICTIONARY", next_flag++, DICTIONARY);
- auto create = std::make_unique("CREATE", std::move(create_database), std::move(create_table), std::move(create_view), std::move(create_dictionary));
- ext::push_back(all, std::move(create));
-
- auto create_temporary_table = std::make_unique("CREATE TEMPORARY TABLE", next_flag++, GLOBAL);
- ext::push_back(all, std::move(create_temporary_table));
-
- auto drop_database = std::make_unique("DROP DATABASE", next_flag++, DATABASE);
- auto drop_table = std::make_unique("DROP TABLE", next_flag++, TABLE);
- auto drop_view = std::make_unique("DROP VIEW", next_flag++, VIEW);
- auto drop_dictionary = std::make_unique("DROP DICTIONARY", next_flag++, DICTIONARY);
- auto drop = std::make_unique("DROP", std::move(drop_database), std::move(drop_table), std::move(drop_view), std::move(drop_dictionary));
- ext::push_back(all, std::move(drop));
-
- auto truncate_table = std::make_unique("TRUNCATE TABLE", next_flag++, TABLE);
- auto truncate_view = std::make_unique("TRUNCATE VIEW", next_flag++, VIEW);
- auto truncate = std::make_unique("TRUNCATE", std::move(truncate_table), std::move(truncate_view));
- ext::push_back(all, std::move(truncate));
-
- auto optimize = std::make_unique("OPTIMIZE", next_flag++, TABLE);
- optimize->aliases.push_back("OPTIMIZE TABLE");
- ext::push_back(all, std::move(optimize));
-
- auto kill_query = std::make_unique("KILL QUERY", next_flag++, GLOBAL);
- ext::push_back(all, std::move(kill_query));
-
- auto create_user = std::make_unique("CREATE USER", next_flag++, GLOBAL);
- auto alter_user = std::make_unique("ALTER USER", next_flag++, GLOBAL);
- auto drop_user = std::make_unique("DROP USER", next_flag++, GLOBAL);
- auto create_role = std::make_unique("CREATE ROLE", next_flag++, GLOBAL);
- auto alter_role = std::make_unique("ALTER ROLE", next_flag++, GLOBAL);
- auto drop_role = std::make_unique("DROP ROLE", next_flag++, GLOBAL);
- auto create_policy = std::make_unique("CREATE POLICY", next_flag++, GLOBAL);
- auto alter_policy = std::make_unique("ALTER POLICY", next_flag++, GLOBAL);
- auto drop_policy = std::make_unique("DROP POLICY", next_flag++, GLOBAL);
- auto create_quota = std::make_unique("CREATE QUOTA", next_flag++, GLOBAL);
- auto alter_quota = std::make_unique("ALTER QUOTA", next_flag++, GLOBAL);
- auto drop_quota = std::make_unique("DROP QUOTA", next_flag++, GLOBAL);
- auto create_profile = std::make_unique("CREATE SETTINGS PROFILE", next_flag++, GLOBAL);
- ext::push_back(create_profile->aliases, "CREATE PROFILE");
- auto alter_profile = std::make_unique("ALTER SETTINGS PROFILE", next_flag++, GLOBAL);
- ext::push_back(alter_profile->aliases, "ALTER PROFILE");
- auto drop_profile = std::make_unique("DROP SETTINGS PROFILE", next_flag++, GLOBAL);
- ext::push_back(drop_profile->aliases, "DROP PROFILE");
- auto role_admin = std::make_unique("ROLE ADMIN", next_flag++, GLOBAL);
- ext::push_back(all, std::move(create_user), std::move(alter_user), std::move(drop_user), std::move(create_role), std::move(alter_role), std::move(drop_role), std::move(create_policy), std::move(alter_policy), std::move(drop_policy), std::move(create_quota), std::move(alter_quota), std::move(drop_quota), std::move(create_profile), std::move(alter_profile), std::move(drop_profile), std::move(role_admin));
-
- auto shutdown = std::make_unique("SHUTDOWN", next_flag++, GLOBAL);
- ext::push_back(shutdown->aliases, "SYSTEM SHUTDOWN", "SYSTEM KILL");
- auto drop_cache = std::make_unique("DROP CACHE", next_flag++, GLOBAL);
- ext::push_back(drop_cache->aliases, "SYSTEM DROP CACHE", "DROP DNS CACHE", "SYSTEM DROP DNS CACHE", "DROP MARK CACHE", "SYSTEM DROP MARK CACHE", "DROP UNCOMPRESSED CACHE", "SYSTEM DROP UNCOMPRESSED CACHE", "DROP COMPILED EXPRESSION CACHE", "SYSTEM DROP COMPILED EXPRESSION CACHE");
- auto reload_config = std::make_unique("RELOAD CONFIG", next_flag++, GLOBAL);
- ext::push_back(reload_config->aliases, "SYSTEM RELOAD CONFIG");
- auto reload_dictionary = std::make_unique("RELOAD DICTIONARY", next_flag++, GLOBAL);
- ext::push_back(reload_dictionary->aliases, "SYSTEM RELOAD DICTIONARY", "RELOAD DICTIONARIES", "SYSTEM RELOAD DICTIONARIES", "RELOAD EMBEDDED DICTIONARIES", "SYSTEM RELOAD EMBEDDED DICTIONARIES");
- auto stop_merges = std::make_unique("STOP MERGES", next_flag++, TABLE);
- ext::push_back(stop_merges->aliases, "SYSTEM STOP MERGES", "START MERGES", "SYSTEM START MERGES");
- auto stop_ttl_merges = std::make_unique("STOP TTL MERGES", next_flag++, TABLE);
- ext::push_back(stop_ttl_merges->aliases, "SYSTEM STOP TTL MERGES", "START TTL MERGES", "SYSTEM START TTL MERGES");
- auto stop_fetches = std::make_unique("STOP FETCHES", next_flag++, TABLE);
- ext::push_back(stop_fetches->aliases, "SYSTEM STOP FETCHES", "START FETCHES", "SYSTEM START FETCHES");
- auto stop_moves = std::make_unique("STOP MOVES", next_flag++, TABLE);
- ext::push_back(stop_moves->aliases, "SYSTEM STOP MOVES", "START MOVES", "SYSTEM START MOVES");
- auto stop_distributed_sends = std::make_unique("STOP DISTRIBUTED SENDS", next_flag++, TABLE);
- ext::push_back(stop_distributed_sends->aliases, "SYSTEM STOP DISTRIBUTED SENDS", "START DISTRIBUTED SENDS", "SYSTEM START DISTRIBUTED SENDS");
- auto stop_replicated_sends = std::make_unique("STOP REPLICATED SENDS", next_flag++, TABLE);
- ext::push_back(stop_replicated_sends->aliases, "SYSTEM STOP REPLICATED SENDS", "START REPLICATED SENDS", "SYSTEM START REPLICATED SENDS");
- auto stop_replication_queues = std::make_unique("STOP REPLICATION QUEUES", next_flag++, TABLE);
- ext::push_back(stop_replication_queues->aliases, "SYSTEM STOP REPLICATION QUEUES", "START REPLICATION QUEUES", "SYSTEM START REPLICATION QUEUES");
- auto sync_replica = std::make_unique("SYNC REPLICA", next_flag++, TABLE);
- ext::push_back(sync_replica->aliases, "SYSTEM SYNC REPLICA");
- auto restart_replica = std::make_unique("RESTART REPLICA", next_flag++, TABLE);
- ext::push_back(restart_replica->aliases, "SYSTEM RESTART REPLICA");
- auto flush_distributed = std::make_unique("FLUSH DISTRIBUTED", next_flag++, TABLE);
- ext::push_back(flush_distributed->aliases, "SYSTEM FLUSH DISTRIBUTED");
- auto flush_logs = std::make_unique("FLUSH LOGS", next_flag++, GLOBAL);
- ext::push_back(flush_logs->aliases, "SYSTEM FLUSH LOGS");
- auto system = std::make_unique("SYSTEM", std::move(shutdown), std::move(drop_cache), std::move(reload_config), std::move(reload_dictionary), std::move(stop_merges), std::move(stop_ttl_merges), std::move(stop_fetches), std::move(stop_moves), std::move(stop_distributed_sends), std::move(stop_replicated_sends), std::move(stop_replication_queues), std::move(sync_replica), std::move(restart_replica), std::move(flush_distributed), std::move(flush_logs));
- ext::push_back(all, std::move(system));
-
- auto dict_get = std::make_unique("dictGet()", next_flag++, DICTIONARY);
- dict_get->aliases.push_back("dictHas()");
- dict_get->aliases.push_back("dictGetHierarchy()");
- dict_get->aliases.push_back("dictIsIn()");
- ext::push_back(all, std::move(dict_get));
-
- auto address_to_line = std::make_unique("addressToLine()", next_flag++, GLOBAL);
- auto address_to_symbol = std::make_unique("addressToSymbol()", next_flag++, GLOBAL);
- auto demangle = std::make_unique("demangle()", next_flag++, GLOBAL);
- auto introspection = std::make_unique("INTROSPECTION", std::move(address_to_line), std::move(address_to_symbol), std::move(demangle));
- ext::push_back(introspection->aliases, "INTROSPECTION FUNCTIONS");
- ext::push_back(all, std::move(introspection));
-
- auto file = std::make_unique("file()", next_flag++, GLOBAL);
- auto url = std::make_unique("url()", next_flag++, GLOBAL);
- auto input = std::make_unique("input()", next_flag++, GLOBAL);
- auto values = std::make_unique("values()", next_flag++, GLOBAL);
- auto numbers = std::make_unique("numbers()", next_flag++, GLOBAL);
- auto zeros = std::make_unique("zeros()", next_flag++, GLOBAL);
- auto merge = std::make_unique("merge()", next_flag++, DATABASE);
- auto remote = std::make_unique("remote()", next_flag++, GLOBAL);
- ext::push_back(remote->aliases, "remoteSecure()", "cluster()");
- auto mysql = std::make_unique("mysql()", next_flag++, GLOBAL);
- auto odbc = std::make_unique("odbc()", next_flag++, GLOBAL);
- auto jdbc = std::make_unique("jdbc()", next_flag++, GLOBAL);
- auto hdfs = std::make_unique("hdfs()", next_flag++, GLOBAL);
- auto s3 = std::make_unique("s3()", next_flag++, GLOBAL);
- auto table_functions = std::make_unique("TABLE FUNCTIONS", std::move(file), std::move(url), std::move(input), std::move(values), std::move(numbers), std::move(zeros), std::move(merge), std::move(remote), std::move(mysql), std::move(odbc), std::move(jdbc), std::move(hdfs), std::move(s3));
- ext::push_back(all, std::move(table_functions));
-
- auto node_all = std::make_unique("ALL", std::move(all));
- node_all->aliases.push_back("ALL PRIVILEGES");
- return node_all;
- }
-
- void makeKeywordToFlagsMap(Node * start_node = nullptr)
- {
- if (!start_node)
- {
- start_node = flags_to_keyword_tree.get();
- keyword_to_flags_map["USAGE"] = {};
- keyword_to_flags_map["NONE"] = {};
- keyword_to_flags_map["NO PRIVILEGES"] = {};
- }
- start_node->aliases.emplace_back(start_node->keyword);
- for (auto & alias : start_node->aliases)
- {
- boost::to_upper(alias);
- keyword_to_flags_map[alias] = start_node->flags;
- }
- for (auto & child : start_node->children)
- makeKeywordToFlagsMap(child.get());
- }
-
- void makeAccessTypeToFlagsMapping()
- {
- access_type_to_flags_mapping.resize(MAX_ACCESS_TYPE);
- for (auto access_type : ext::range_with_static_cast(0, MAX_ACCESS_TYPE))
- {
- auto str = toKeyword(access_type);
- auto it = keyword_to_flags_map.find(str);
- if (it == keyword_to_flags_map.end())
- {
- String uppercased{str};
- boost::to_upper(uppercased);
- it = keyword_to_flags_map.find(uppercased);
- }
- access_type_to_flags_mapping[static_cast(access_type)] = it->second;
- }
- }
-
- void collectAllFlags(const Node * start_node = nullptr)
- {
- if (!start_node)
- {
- start_node = flags_to_keyword_tree.get();
- all_flags = start_node->flags;
- }
- if (start_node->target != UNKNOWN_TARGET)
- all_flags_for_target[start_node->target] |= start_node->flags;
- for (const auto & child : start_node->children)
- collectAllFlags(child.get());
- }
-
- Impl()
- {
- flags_to_keyword_tree = makeFlagsToKeywordTree();
- makeKeywordToFlagsMap();
- makeAccessTypeToFlagsMapping();
- collectAllFlags();
- }
-
- std::unique_ptr flags_to_keyword_tree;
+ NodePtr flags_to_keyword_tree;
+ NodePtr none_node;
std::unordered_map keyword_to_flags_map;
std::vector access_type_to_flags_mapping;
Flags all_flags;
- Flags all_flags_for_target[NUM_TARGETS];
+ Flags all_flags_for_target[static_cast(DICTIONARY) + 1];
};
diff --git a/src/Access/AccessRights.cpp b/src/Access/AccessRights.cpp
index 6f94cfac286..9c3b5e36ec8 100644
--- a/src/Access/AccessRights.cpp
+++ b/src/Access/AccessRights.cpp
@@ -49,10 +49,13 @@ namespace
const AccessFlags create_temporary_table_flag = AccessType::CREATE_TEMPORARY_TABLE;
const AccessFlags alter_table_flag = AccessType::ALTER_TABLE;
const AccessFlags alter_view_flag = AccessType::ALTER_VIEW;
- const AccessFlags truncate_table_flag = AccessType::TRUNCATE_TABLE;
- const AccessFlags truncate_view_flag = AccessType::TRUNCATE_VIEW;
+ const AccessFlags truncate_flag = AccessType::TRUNCATE;
const AccessFlags drop_table_flag = AccessType::DROP_TABLE;
const AccessFlags drop_view_flag = AccessType::DROP_VIEW;
+ const AccessFlags alter_ttl_flag = AccessType::ALTER_TTL;
+ const AccessFlags alter_materialize_ttl_flag = AccessType::ALTER_MATERIALIZE_TTL;
+ const AccessFlags system_reload_dictionary = AccessType::SYSTEM_RELOAD_DICTIONARY;
+ const AccessFlags system_reload_embedded_dictionaries = AccessType::SYSTEM_RELOAD_EMBEDDED_DICTIONARIES;
};
std::string_view checkCurrentDatabase(const std::string_view & current_database)
@@ -413,8 +416,14 @@ private:
implicit_access |= helper.show_tables_flag;
}
- if ((level == GLOBAL_LEVEL) && ((access | max_access_among_children) & helper.create_table_flag))
- implicit_access |= helper.create_temporary_table_flag;
+ if (level == GLOBAL_LEVEL)
+ {
+ if ((access | max_access_among_children) & helper.create_table_flag)
+ implicit_access |= helper.create_temporary_table_flag;
+
+ if (access & helper.system_reload_dictionary)
+ implicit_access |= helper.system_reload_embedded_dictionaries;
+ }
if (level <= TABLE_LEVEL)
{
@@ -427,8 +436,8 @@ private:
if (access & helper.alter_table_flag)
implicit_access |= helper.alter_view_flag;
- if (access & helper.truncate_table_flag)
- implicit_access |= helper.truncate_view_flag;
+ if (access & helper.alter_ttl_flag)
+ implicit_access |= helper.alter_materialize_ttl_flag;
}
final_access = access | implicit_access;
diff --git a/src/Access/AccessType.h b/src/Access/AccessType.h
index df8839f64ce..d0665a6e55f 100644
--- a/src/Access/AccessType.h
+++ b/src/Access/AccessType.h
@@ -11,139 +11,162 @@ namespace DB
/// Represents an access type which can be granted on databases, tables, columns, etc.
enum class AccessType
{
- NONE, /// no access
- ALL, /// full access
+/// Macro M should be defined as M(name, aliases, node_type, parent_group_name)
+/// where name is identifier with underscores (instead of spaces);
+/// aliases is a string containing comma-separated list;
+/// node_type either specifies access type's level (GLOBAL/DATABASE/TABLE/DICTIONARY/VIEW/COLUMNS),
+/// or specifies that the access type is a GROUP of other access types;
+/// parent_group_name is the name of the group containing this access type (or NONE if there is no such group).
+#define APPLY_FOR_ACCESS_TYPES(M) \
+ M(SHOW_DATABASES, "", DATABASE, SHOW) /* allows to execute SHOW DATABASES, SHOW CREATE DATABASE, USE ;
+ implicitly enabled by any grant on the database */\
+ M(SHOW_TABLES, "", TABLE, SHOW) /* allows to execute SHOW TABLES, EXISTS , CHECK ;
+ implicitly enabled by any grant on the table */\
+ M(SHOW_COLUMNS, "", COLUMN, SHOW) /* allows to execute SHOW CREATE TABLE, DESCRIBE;
+ implicitly enabled with any grant on the column */\
+ M(SHOW_DICTIONARIES, "", DICTIONARY, SHOW) /* allows to execute SHOW DICTIONARIES, SHOW CREATE DICTIONARY, EXISTS ;
+ implicitly enabled by any grant on the dictionary */\
+ M(SHOW, "", GROUP, ALL) /* allows to execute SHOW, USE, EXISTS, CHECK, DESCRIBE */\
+ \
+ M(SELECT, "", COLUMN, ALL) \
+ M(INSERT, "", COLUMN, ALL) \
+ M(ALTER_UPDATE, "UPDATE", COLUMN, ALTER_TABLE) /* allows to execute ALTER UPDATE */\
+ M(ALTER_DELETE, "DELETE", COLUMN, ALTER_TABLE) /* allows to execute ALTER DELETE */\
+ \
+ M(ALTER_ADD_COLUMN, "ADD COLUMN", COLUMN, ALTER_COLUMN) \
+ M(ALTER_MODIFY_COLUMN, "MODIFY COLUMN", COLUMN, ALTER_COLUMN) \
+ M(ALTER_DROP_COLUMN, "DROP COLUMN", COLUMN, ALTER_COLUMN) \
+ M(ALTER_COMMENT_COLUMN, "COMMENT COLUMN", COLUMN, ALTER_COLUMN) \
+ M(ALTER_CLEAR_COLUMN, "CLEAR COLUMN", COLUMN, ALTER_COLUMN) \
+ M(ALTER_RENAME_COLUMN, "RENAME COLUMN", COLUMN, ALTER_COLUMN) \
+ M(ALTER_COLUMN, "", GROUP, ALTER_TABLE) /* allow to execute ALTER {ADD|DROP|MODIFY...} COLUMN */\
+ \
+ M(ALTER_ORDER_BY, "ALTER MODIFY ORDER BY, MODIFY ORDER BY", TABLE, ALTER_INDEX) \
+ M(ALTER_ADD_INDEX, "ADD INDEX", TABLE, ALTER_INDEX) \
+ M(ALTER_DROP_INDEX, "DROP INDEX", TABLE, ALTER_INDEX) \
+ M(ALTER_MATERIALIZE_INDEX, "MATERIALIZE INDEX", TABLE, ALTER_INDEX) \
+ M(ALTER_CLEAR_INDEX, "CLEAR INDEX", TABLE, ALTER_INDEX) \
+ M(ALTER_INDEX, "INDEX", GROUP, ALTER_TABLE) /* allows to execute ALTER ORDER BY or ALTER {ADD|DROP...} INDEX */\
+ \
+ M(ALTER_ADD_CONSTRAINT, "ADD CONSTRAINT", TABLE, ALTER_CONSTRAINT) \
+ M(ALTER_DROP_CONSTRAINT, "DROP CONSTRAINT", TABLE, ALTER_CONSTRAINT) \
+ M(ALTER_CONSTRAINT, "CONSTRAINT", GROUP, ALTER_TABLE) /* allows to execute ALTER {ADD|DROP} CONSTRAINT */\
+ \
+ M(ALTER_TTL, "ALTER MODIFY TTL, MODIFY TTL", TABLE, ALTER_TABLE) /* allows to execute ALTER MODIFY TTL */\
+ M(ALTER_MATERIALIZE_TTL, "MATERIALIZE TTL", TABLE, ALTER_TABLE) /* allows to execute ALTER MATERIALIZE TTL;
+ enabled implicitly by the grant ALTER_TABLE */\
+ M(ALTER_SETTINGS, "ALTER SETTING, ALTER MODIFY SETTING, MODIFY SETTING", TABLE, ALTER_TABLE) /* allows to execute ALTER MODIFY SETTING */\
+ M(ALTER_MOVE_PARTITION, "ALTER MOVE PART, MOVE PARTITION, MOVE PART", TABLE, ALTER_TABLE) \
+ M(ALTER_FETCH_PARTITION, "FETCH PARTITION", TABLE, ALTER_TABLE) \
+ M(ALTER_FREEZE_PARTITION, "FREEZE PARTITION", TABLE, ALTER_TABLE) \
+ \
+ M(ALTER_TABLE, "", GROUP, ALTER) \
+ \
+ M(ALTER_VIEW_REFRESH, "ALTER LIVE VIEW REFRESH, REFRESH VIEW", VIEW, ALTER_VIEW) \
+ M(ALTER_VIEW_MODIFY_QUERY, "ALTER TABLE MODIFY QUERY", VIEW, ALTER_VIEW) \
+ M(ALTER_VIEW, "", GROUP, ALTER) /* allows to execute ALTER VIEW REFRESH, ALTER VIEW MODIFY QUERY;
+ implicitly enabled by the grant ALTER_TABLE */\
+ \
+ M(ALTER, "", GROUP, ALL) /* allows to execute ALTER {TABLE|LIVE VIEW} */\
+ \
+ M(CREATE_DATABASE, "", DATABASE, CREATE) /* allows to execute {CREATE|ATTACH} DATABASE */\
+ M(CREATE_TABLE, "", TABLE, CREATE) /* allows to execute {CREATE|ATTACH} {TABLE|VIEW} */\
+ M(CREATE_VIEW, "", VIEW, CREATE) /* allows to execute {CREATE|ATTACH} VIEW;
+ implicitly enabled by the grant CREATE_TABLE */\
+ M(CREATE_DICTIONARY, "", DICTIONARY, CREATE) /* allows to execute {CREATE|ATTACH} DICTIONARY */\
+ M(CREATE_TEMPORARY_TABLE, "", GLOBAL, CREATE) /* allows to create and manipulate temporary tables;
+ implicitly enabled by the grant CREATE_TABLE on any table */ \
+ M(CREATE, "", GROUP, ALL) /* allows to execute {CREATE|ATTACH} */ \
+ \
+ M(DROP_DATABASE, "", DATABASE, DROP) /* allows to execute {DROP|DETACH} DATABASE */\
+ M(DROP_TABLE, "", TABLE, DROP) /* allows to execute {DROP|DETACH} TABLE */\
+ M(DROP_VIEW, "", VIEW, DROP) /* allows to execute {DROP|DETACH} TABLE for views;
+ implicitly enabled by the grant DROP_TABLE */\
+ M(DROP_DICTIONARY, "", DICTIONARY, DROP) /* allows to execute {DROP|DETACH} DICTIONARY */\
+ M(DROP, "", GROUP, ALL) /* allows to execute {DROP|DETACH} */\
+ \
+ M(TRUNCATE, "TRUNCATE TABLE", TABLE, ALL) \
+ M(OPTIMIZE, "OPTIMIZE TABLE", TABLE, ALL) \
+ \
+ M(KILL_QUERY, "", GLOBAL, ALL) /* allows to kill a query started by another user
+ (anyone can kill his own queries) */\
+ \
+ M(CREATE_USER, "", GLOBAL, ACCESS_MANAGEMENT) \
+ M(ALTER_USER, "", GLOBAL, ACCESS_MANAGEMENT) \
+ M(DROP_USER, "", GLOBAL, ACCESS_MANAGEMENT) \
+ M(CREATE_ROLE, "", GLOBAL, ACCESS_MANAGEMENT) \
+ M(ALTER_ROLE, "", GLOBAL, ACCESS_MANAGEMENT) \
+ M(DROP_ROLE, "", GLOBAL, ACCESS_MANAGEMENT) \
+ M(ROLE_ADMIN, "", GLOBAL, ACCESS_MANAGEMENT) /* allows to grant and revoke the roles which are not granted to the current user with admin option */\
+ M(CREATE_ROW_POLICY, "CREATE POLICY", GLOBAL, ACCESS_MANAGEMENT) \
+ M(ALTER_ROW_POLICY, "ALTER POLICY", GLOBAL, ACCESS_MANAGEMENT) \
+ M(DROP_ROW_POLICY, "DROP POLICY", GLOBAL, ACCESS_MANAGEMENT) \
+ M(CREATE_QUOTA, "", GLOBAL, ACCESS_MANAGEMENT) \
+ M(ALTER_QUOTA, "", GLOBAL, ACCESS_MANAGEMENT) \
+ M(DROP_QUOTA, "", GLOBAL, ACCESS_MANAGEMENT) \
+ M(CREATE_SETTINGS_PROFILE, "CREATE PROFILE", GLOBAL, ACCESS_MANAGEMENT) \
+ M(ALTER_SETTINGS_PROFILE, "ALTER PROFILE", GLOBAL, ACCESS_MANAGEMENT) \
+ M(DROP_SETTINGS_PROFILE, "DROP PROFILE", GLOBAL, ACCESS_MANAGEMENT) \
+ M(SHOW_USERS, "SHOW CREATE USER", GLOBAL, SHOW_ACCESS) \
+ M(SHOW_ROLES, "SHOW CREATE ROLE", GLOBAL, SHOW_ACCESS) \
+ M(SHOW_ROW_POLICIES, "SHOW POLICIES, SHOW CREATE ROW POLICY, SHOW CREATE POLICY", GLOBAL, SHOW_ACCESS) \
+ M(SHOW_QUOTAS, "SHOW CREATE QUOTA", GLOBAL, SHOW_ACCESS) \
+ M(SHOW_SETTINGS_PROFILES, "SHOW PROFILES, SHOW CREATE SETTINGS PROFILE, SHOW CREATE PROFILE", GLOBAL, SHOW_ACCESS) \
+ M(SHOW_ACCESS, "", GROUP, ACCESS_MANAGEMENT) \
+ M(ACCESS_MANAGEMENT, "", GROUP, ALL) \
+ \
+ M(SYSTEM_SHUTDOWN, "SYSTEM KILL, SHUTDOWN", GLOBAL, SYSTEM) \
+ M(SYSTEM_DROP_DNS_CACHE, "SYSTEM DROP DNS, DROP DNS CACHE, DROP DNS", GLOBAL, SYSTEM_DROP_CACHE) \
+ M(SYSTEM_DROP_MARK_CACHE, "SYSTEM DROP MARK, DROP MARK CACHE, DROP MARKS", GLOBAL, SYSTEM_DROP_CACHE) \
+ M(SYSTEM_DROP_UNCOMPRESSED_CACHE, "SYSTEM DROP UNCOMPRESSED, DROP UNCOMPRESSED CACHE, DROP UNCOMPRESSED", GLOBAL, SYSTEM_DROP_CACHE) \
+ M(SYSTEM_DROP_COMPILED_EXPRESSION_CACHE, "SYSTEM DROP COMPILED EXPRESSION, DROP COMPILED EXPRESSION CACHE, DROP COMPILED EXPRESSIONS", GLOBAL, SYSTEM_DROP_CACHE) \
+ M(SYSTEM_DROP_CACHE, "DROP CACHE", GROUP, SYSTEM) \
+ M(SYSTEM_RELOAD_CONFIG, "RELOAD CONFIG", GLOBAL, SYSTEM_RELOAD) \
+ M(SYSTEM_RELOAD_DICTIONARY, "SYSTEM RELOAD DICTIONARIES, RELOAD DICTIONARY, RELOAD DICTIONARIES", GLOBAL, SYSTEM_RELOAD) \
+ M(SYSTEM_RELOAD_EMBEDDED_DICTIONARIES, "RELOAD EMBEDDED DICTIONARIES", GLOBAL, SYSTEM_RELOAD) /* implicitly enabled by the grant SYSTEM_RELOAD_DICTIONARY ON *.* */\
+ M(SYSTEM_RELOAD, "", GROUP, SYSTEM) \
+ M(SYSTEM_MERGES, "SYSTEM STOP MERGES, SYSTEM START MERGES, STOP_MERGES, START MERGES", TABLE, SYSTEM) \
+ M(SYSTEM_TTL_MERGES, "SYSTEM STOP TTL MERGES, SYSTEM START TTL MERGES, STOP TTL MERGES, START TTL MERGES", TABLE, SYSTEM) \
+ M(SYSTEM_FETCHES, "SYSTEM STOP FETCHES, SYSTEM START FETCHES, STOP FETCHES, START FETCHES", TABLE, SYSTEM) \
+ M(SYSTEM_MOVES, "SYSTEM STOP MOVES, SYSTEM START MOVES, STOP MOVES, START MOVES", TABLE, SYSTEM) \
+ M(SYSTEM_DISTRIBUTED_SENDS, "SYSTEM STOP DISTRIBUTED SENDS, SYSTEM START DISTRIBUTED SENDS, STOP DISTRIBUTED SENDS, START DISTRIBUTED SENDS", TABLE, SYSTEM_SENDS) \
+ M(SYSTEM_REPLICATED_SENDS, "SYSTEM STOP REPLICATED SENDS, SYSTEM START REPLICATED SENDS, STOP_REPLICATED_SENDS, START REPLICATED SENDS", TABLE, SYSTEM_SENDS) \
+ M(SYSTEM_SENDS, "SYSTEM STOP SENDS, SYSTEM START SENDS, STOP SENDS, START SENDS", GROUP, SYSTEM) \
+ M(SYSTEM_REPLICATION_QUEUES, "SYSTEM STOP REPLICATION QUEUES, SYSTEM START REPLICATION QUEUES, STOP_REPLICATION_QUEUES, START REPLICATION QUEUES", TABLE, SYSTEM) \
+ M(SYSTEM_SYNC_REPLICA, "SYNC REPLICA", TABLE, SYSTEM) \
+ M(SYSTEM_RESTART_REPLICA, "RESTART REPLICA", TABLE, SYSTEM) \
+ M(SYSTEM_FLUSH_DISTRIBUTED, "FLUSH DISTRIBUTED", TABLE, SYSTEM_FLUSH) \
+ M(SYSTEM_FLUSH_LOGS, "FLUSH LOGS", GLOBAL, SYSTEM_FLUSH) \
+ M(SYSTEM_FLUSH, "", GROUP, SYSTEM) \
+ M(SYSTEM, "", GROUP, ALL) /* allows to execute SYSTEM {SHUTDOWN|RELOAD CONFIG|...} */ \
+ \
+ M(dictGet, "dictHas, dictGetHierarchy, dictIsIn", DICTIONARY, ALL) /* allows to execute functions dictGet(), dictHas(), dictGetHierarchy(), dictIsIn() */\
+ \
+ M(addressToLine, "", GLOBAL, INTROSPECTION) /* allows to execute function addressToLine() */\
+ M(addressToSymbol, "", GLOBAL, INTROSPECTION) /* allows to execute function addressToSymbol() */\
+ M(demangle, "", GLOBAL, INTROSPECTION) /* allows to execute function demangle() */\
+ M(INTROSPECTION, "INTROSPECTION FUNCTIONS", GROUP, ALL) /* allows to execute functions addressToLine(), addressToSymbol(), demangle()*/\
+ \
+ M(FILE, "", GLOBAL, SOURCES) \
+ M(URL, "", GLOBAL, SOURCES) \
+ M(REMOTE, "", GLOBAL, SOURCES) \
+ M(MYSQL, "", GLOBAL, SOURCES) \
+ M(ODBC, "", GLOBAL, SOURCES) \
+ M(JDBC, "", GLOBAL, SOURCES) \
+ M(HDFS, "", GLOBAL, SOURCES) \
+ M(S3, "", GLOBAL, SOURCES) \
+ M(SOURCES, "", GROUP, ALL) \
+ \
+ M(ALL, "ALL PRIVILEGES", GROUP, NONE) /* full access */ \
+ M(NONE, "USAGE, NO PRIVILEGES", GROUP, NONE) /* no access */
- SHOW_DATABASES, /// allows to execute SHOW DATABASES, SHOW CREATE DATABASE, USE
- SHOW_TABLES, /// allows to execute SHOW TABLES, EXISTS , CHECK
- SHOW_COLUMNS, /// allows to execute SHOW CREATE TABLE, DESCRIBE
- SHOW_DICTIONARIES, /// allows to execute SHOW DICTIONARIES, SHOW CREATE DICTIONARY, EXISTS
- SHOW, /// allows to execute SHOW, USE, EXISTS, CHECK, DESCRIBE
+#define DECLARE_ACCESS_TYPE_ENUM_CONST(name, aliases, node_type, parent_group_name) \
+ name,
- SELECT,
- INSERT,
- UPDATE, /// allows to execute ALTER UPDATE
- DELETE, /// allows to execute ALTER DELETE
-
- ADD_COLUMN,
- DROP_COLUMN,
- MODIFY_COLUMN,
- COMMENT_COLUMN,
- CLEAR_COLUMN,
- RENAME_COLUMN,
- ALTER_COLUMN, /// allow to execute ALTER {ADD|DROP|MODIFY...} COLUMN
-
- ALTER_ORDER_BY,
- ADD_INDEX,
- DROP_INDEX,
- MATERIALIZE_INDEX,
- CLEAR_INDEX,
- INDEX, /// allows to execute ALTER ORDER BY or ALTER {ADD|DROP...} INDEX
-
- ADD_CONSTRAINT,
- DROP_CONSTRAINT,
- ALTER_CONSTRAINT, /// allows to execute ALTER {ADD|DROP} CONSTRAINT
-
- MODIFY_TTL, /// allows to execute ALTER MODIFY TTL
- MATERIALIZE_TTL, /// allows to execute ALTER MATERIALIZE TTL
- MODIFY_SETTING, /// allows to execute ALTER MODIFY SETTING
-
- MOVE_PARTITION,
- FETCH_PARTITION,
- FREEZE_PARTITION,
-
- ALTER_TABLE, /// allows to execute ALTER TABLE ...
-
- REFRESH_VIEW, /// allows to execute ALTER LIVE VIEW REFRESH
- MODIFY_VIEW_QUERY, /// allows to execute ALTER TABLE MODIFY QUERY
- ALTER_VIEW, /// allows to execute ALTER LIVE VIEW REFRESH, ALTER TABLE MODIFY QUERY
-
- ALTER, /// allows to execute ALTER {TABLE|LIVE VIEW} ...
-
- CREATE_DATABASE, /// allows to execute {CREATE|ATTACH} DATABASE
- CREATE_TABLE, /// allows to execute {CREATE|ATTACH} TABLE
- CREATE_VIEW, /// allows to execute {CREATE|ATTACH} VIEW
- CREATE_DICTIONARY, /// allows to execute {CREATE|ATTACH} DICTIONARY
- CREATE_TEMPORARY_TABLE, /// allows to create and manipulate temporary tables and views.
- CREATE, /// allows to execute {CREATE|ATTACH} [TEMPORARY] {DATABASE|TABLE|VIEW|DICTIONARY}
-
- DROP_DATABASE,
- DROP_TABLE,
- DROP_VIEW,
- DROP_DICTIONARY,
- DROP, /// allows to execute DROP {DATABASE|TABLE|VIEW|DICTIONARY}
-
- TRUNCATE_TABLE,
- TRUNCATE_VIEW,
- TRUNCATE, /// allows to execute TRUNCATE {TABLE|VIEW}
-
- OPTIMIZE, /// allows to execute OPTIMIZE TABLE
-
- KILL_QUERY, /// allows to kill a query started by another user (anyone can kill his own queries)
-
- CREATE_USER,
- ALTER_USER,
- DROP_USER,
- CREATE_ROLE,
- ALTER_ROLE,
- DROP_ROLE,
- CREATE_POLICY,
- ALTER_POLICY,
- DROP_POLICY,
- CREATE_QUOTA,
- ALTER_QUOTA,
- DROP_QUOTA,
- CREATE_SETTINGS_PROFILE,
- ALTER_SETTINGS_PROFILE,
- DROP_SETTINGS_PROFILE,
-
- ROLE_ADMIN, /// allows to grant and revoke any roles.
-
- SHUTDOWN,
- DROP_CACHE,
- RELOAD_CONFIG,
- RELOAD_DICTIONARY,
- STOP_MERGES,
- STOP_TTL_MERGES,
- STOP_FETCHES,
- STOP_MOVES,
- STOP_DISTRIBUTED_SENDS,
- STOP_REPLICATED_SENDS,
- STOP_REPLICATION_QUEUES,
- SYNC_REPLICA,
- RESTART_REPLICA,
- FLUSH_DISTRIBUTED,
- FLUSH_LOGS,
- SYSTEM, /// allows to execute SYSTEM {SHUTDOWN|RELOAD CONFIG|...}
-
- dictGet, /// allows to execute functions dictGet, dictHas, dictGetHierarchy, dictIsIn
- dictHas, /// allows to execute functions dictGet, dictHas, dictGetHierarchy, dictIsIn
- dictGetHierarchy, /// allows to execute functions dictGet, dictHas, dictGetHierarchy, dictIsIn
- dictIsIn, /// allows to execute functions dictGet, dictHas, dictGetHierarchy, dictIsIn
-
- addressToLine, /// allows to execute function addressToLine
- addressToSymbol, /// allows to execute function addressToSymbol
- demangle, /// allows to execute function demangle
- INTROSPECTION, /// allows to execute functions addressToLine, addressToSymbol, demangle
-
- file,
- url,
- input,
- values,
- numbers,
- zeros,
- merge,
- remote,
- mysql,
- odbc,
- jdbc,
- hdfs,
- s3,
- TABLE_FUNCTIONS, /// allows to execute any table function
+ APPLY_FOR_ACCESS_TYPES(DECLARE_ACCESS_TYPE_ENUM_CONST)
+#undef DECLARE_ACCESS_TYPE_ENUM_CONST
};
-constexpr size_t MAX_ACCESS_TYPE = static_cast(AccessType::TABLE_FUNCTIONS) + 1;
-
std::string_view toString(AccessType type);
@@ -165,153 +188,26 @@ namespace impl
}
private:
- void addToMapping(AccessType type, const std::string_view & str)
+ AccessTypeToKeywordConverter()
+ {
+#define INSERT_ACCESS_TYPE_KEYWORD_PAIR_TO_MAPPING(name, aliases, node_type, parent_group_name) \
+ insertToMapping(AccessType::name, #name);
+
+ APPLY_FOR_ACCESS_TYPES(INSERT_ACCESS_TYPE_KEYWORD_PAIR_TO_MAPPING)
+
+#undef INSERT_ACCESS_TYPE_KEYWORD_PAIR_TO_MAPPING
+ }
+
+ void insertToMapping(AccessType type, const std::string_view & str)
{
String str2{str};
boost::replace_all(str2, "_", " ");
- if (islower(str2[0]))
- str2 += "()";
- access_type_to_keyword_mapping[static_cast(type)] = str2;
+ size_t index = static_cast(type);
+ access_type_to_keyword_mapping.resize(std::max(index + 1, access_type_to_keyword_mapping.size()));
+ access_type_to_keyword_mapping[index] = str2;
}
- AccessTypeToKeywordConverter()
- {
-#define ACCESS_TYPE_TO_KEYWORD_CASE(type) \
- addToMapping(AccessType::type, #type)
-
- ACCESS_TYPE_TO_KEYWORD_CASE(NONE);
- ACCESS_TYPE_TO_KEYWORD_CASE(ALL);
-
- ACCESS_TYPE_TO_KEYWORD_CASE(SHOW_DATABASES);
- ACCESS_TYPE_TO_KEYWORD_CASE(SHOW_TABLES);
- ACCESS_TYPE_TO_KEYWORD_CASE(SHOW_COLUMNS);
- ACCESS_TYPE_TO_KEYWORD_CASE(SHOW_DICTIONARIES);
- ACCESS_TYPE_TO_KEYWORD_CASE(SHOW);
-
- ACCESS_TYPE_TO_KEYWORD_CASE(SELECT);
- ACCESS_TYPE_TO_KEYWORD_CASE(INSERT);
- ACCESS_TYPE_TO_KEYWORD_CASE(UPDATE);
- ACCESS_TYPE_TO_KEYWORD_CASE(DELETE);
-
- ACCESS_TYPE_TO_KEYWORD_CASE(ADD_COLUMN);
- ACCESS_TYPE_TO_KEYWORD_CASE(DROP_COLUMN);
- ACCESS_TYPE_TO_KEYWORD_CASE(MODIFY_COLUMN);
- ACCESS_TYPE_TO_KEYWORD_CASE(COMMENT_COLUMN);
- ACCESS_TYPE_TO_KEYWORD_CASE(CLEAR_COLUMN);
- ACCESS_TYPE_TO_KEYWORD_CASE(RENAME_COLUMN);
- ACCESS_TYPE_TO_KEYWORD_CASE(ALTER_COLUMN);
-
- ACCESS_TYPE_TO_KEYWORD_CASE(ALTER_ORDER_BY);
- ACCESS_TYPE_TO_KEYWORD_CASE(ADD_INDEX);
- ACCESS_TYPE_TO_KEYWORD_CASE(DROP_INDEX);
- ACCESS_TYPE_TO_KEYWORD_CASE(MATERIALIZE_INDEX);
- ACCESS_TYPE_TO_KEYWORD_CASE(CLEAR_INDEX);
- ACCESS_TYPE_TO_KEYWORD_CASE(INDEX);
-
- ACCESS_TYPE_TO_KEYWORD_CASE(ADD_CONSTRAINT);
- ACCESS_TYPE_TO_KEYWORD_CASE(DROP_CONSTRAINT);
- ACCESS_TYPE_TO_KEYWORD_CASE(ALTER_CONSTRAINT);
-
- ACCESS_TYPE_TO_KEYWORD_CASE(MODIFY_TTL);
- ACCESS_TYPE_TO_KEYWORD_CASE(MATERIALIZE_TTL);
- ACCESS_TYPE_TO_KEYWORD_CASE(MODIFY_SETTING);
-
- ACCESS_TYPE_TO_KEYWORD_CASE(MOVE_PARTITION);
- ACCESS_TYPE_TO_KEYWORD_CASE(FETCH_PARTITION);
- ACCESS_TYPE_TO_KEYWORD_CASE(FREEZE_PARTITION);
-
- ACCESS_TYPE_TO_KEYWORD_CASE(ALTER_TABLE);
-
- ACCESS_TYPE_TO_KEYWORD_CASE(REFRESH_VIEW);
- ACCESS_TYPE_TO_KEYWORD_CASE(MODIFY_VIEW_QUERY);
- ACCESS_TYPE_TO_KEYWORD_CASE(ALTER_VIEW);
-
- ACCESS_TYPE_TO_KEYWORD_CASE(ALTER);
-
- ACCESS_TYPE_TO_KEYWORD_CASE(CREATE_DATABASE);
- ACCESS_TYPE_TO_KEYWORD_CASE(CREATE_TABLE);
- ACCESS_TYPE_TO_KEYWORD_CASE(CREATE_VIEW);
- ACCESS_TYPE_TO_KEYWORD_CASE(CREATE_DICTIONARY);
- ACCESS_TYPE_TO_KEYWORD_CASE(CREATE_TEMPORARY_TABLE);
- ACCESS_TYPE_TO_KEYWORD_CASE(CREATE);
-
- ACCESS_TYPE_TO_KEYWORD_CASE(DROP_DATABASE);
- ACCESS_TYPE_TO_KEYWORD_CASE(DROP_TABLE);
- ACCESS_TYPE_TO_KEYWORD_CASE(DROP_VIEW);
- ACCESS_TYPE_TO_KEYWORD_CASE(DROP_DICTIONARY);
- ACCESS_TYPE_TO_KEYWORD_CASE(DROP);
-
- ACCESS_TYPE_TO_KEYWORD_CASE(TRUNCATE_TABLE);
- ACCESS_TYPE_TO_KEYWORD_CASE(TRUNCATE_VIEW);
- ACCESS_TYPE_TO_KEYWORD_CASE(TRUNCATE);
-
- ACCESS_TYPE_TO_KEYWORD_CASE(OPTIMIZE);
-
- ACCESS_TYPE_TO_KEYWORD_CASE(KILL_QUERY);
-
- ACCESS_TYPE_TO_KEYWORD_CASE(CREATE_USER);
- ACCESS_TYPE_TO_KEYWORD_CASE(ALTER_USER);
- ACCESS_TYPE_TO_KEYWORD_CASE(DROP_USER);
- ACCESS_TYPE_TO_KEYWORD_CASE(CREATE_ROLE);
- ACCESS_TYPE_TO_KEYWORD_CASE(ALTER_ROLE);
- ACCESS_TYPE_TO_KEYWORD_CASE(DROP_ROLE);
- ACCESS_TYPE_TO_KEYWORD_CASE(CREATE_POLICY);
- ACCESS_TYPE_TO_KEYWORD_CASE(ALTER_POLICY);
- ACCESS_TYPE_TO_KEYWORD_CASE(DROP_POLICY);
- ACCESS_TYPE_TO_KEYWORD_CASE(CREATE_QUOTA);
- ACCESS_TYPE_TO_KEYWORD_CASE(ALTER_QUOTA);
- ACCESS_TYPE_TO_KEYWORD_CASE(DROP_QUOTA);
- ACCESS_TYPE_TO_KEYWORD_CASE(CREATE_SETTINGS_PROFILE);
- ACCESS_TYPE_TO_KEYWORD_CASE(ALTER_SETTINGS_PROFILE);
- ACCESS_TYPE_TO_KEYWORD_CASE(DROP_SETTINGS_PROFILE);
- ACCESS_TYPE_TO_KEYWORD_CASE(ROLE_ADMIN);
-
- ACCESS_TYPE_TO_KEYWORD_CASE(SHUTDOWN);
- ACCESS_TYPE_TO_KEYWORD_CASE(DROP_CACHE);
- ACCESS_TYPE_TO_KEYWORD_CASE(RELOAD_CONFIG);
- ACCESS_TYPE_TO_KEYWORD_CASE(RELOAD_DICTIONARY);
- ACCESS_TYPE_TO_KEYWORD_CASE(STOP_MERGES);
- ACCESS_TYPE_TO_KEYWORD_CASE(STOP_TTL_MERGES);
- ACCESS_TYPE_TO_KEYWORD_CASE(STOP_FETCHES);
- ACCESS_TYPE_TO_KEYWORD_CASE(STOP_MOVES);
- ACCESS_TYPE_TO_KEYWORD_CASE(STOP_DISTRIBUTED_SENDS);
- ACCESS_TYPE_TO_KEYWORD_CASE(STOP_REPLICATED_SENDS);
- ACCESS_TYPE_TO_KEYWORD_CASE(STOP_REPLICATION_QUEUES);
- ACCESS_TYPE_TO_KEYWORD_CASE(SYNC_REPLICA);
- ACCESS_TYPE_TO_KEYWORD_CASE(RESTART_REPLICA);
- ACCESS_TYPE_TO_KEYWORD_CASE(FLUSH_DISTRIBUTED);
- ACCESS_TYPE_TO_KEYWORD_CASE(FLUSH_LOGS);
- ACCESS_TYPE_TO_KEYWORD_CASE(SYSTEM);
-
- ACCESS_TYPE_TO_KEYWORD_CASE(dictGet);
- ACCESS_TYPE_TO_KEYWORD_CASE(dictHas);
- ACCESS_TYPE_TO_KEYWORD_CASE(dictGetHierarchy);
- ACCESS_TYPE_TO_KEYWORD_CASE(dictIsIn);
-
- ACCESS_TYPE_TO_KEYWORD_CASE(addressToLine);
- ACCESS_TYPE_TO_KEYWORD_CASE(addressToSymbol);
- ACCESS_TYPE_TO_KEYWORD_CASE(demangle);
- ACCESS_TYPE_TO_KEYWORD_CASE(INTROSPECTION);
-
- ACCESS_TYPE_TO_KEYWORD_CASE(file);
- ACCESS_TYPE_TO_KEYWORD_CASE(url);
- ACCESS_TYPE_TO_KEYWORD_CASE(input);
- ACCESS_TYPE_TO_KEYWORD_CASE(values);
- ACCESS_TYPE_TO_KEYWORD_CASE(numbers);
- ACCESS_TYPE_TO_KEYWORD_CASE(zeros);
- ACCESS_TYPE_TO_KEYWORD_CASE(merge);
- ACCESS_TYPE_TO_KEYWORD_CASE(remote);
- ACCESS_TYPE_TO_KEYWORD_CASE(mysql);
- ACCESS_TYPE_TO_KEYWORD_CASE(odbc);
- ACCESS_TYPE_TO_KEYWORD_CASE(jdbc);
- ACCESS_TYPE_TO_KEYWORD_CASE(hdfs);
- ACCESS_TYPE_TO_KEYWORD_CASE(s3);
- ACCESS_TYPE_TO_KEYWORD_CASE(TABLE_FUNCTIONS);
-
-#undef ACCESS_TYPE_TO_KEYWORD_CASE
- }
-
- std::array access_type_to_keyword_mapping;
+ Strings access_type_to_keyword_mapping;
};
}
diff --git a/src/Access/AllowedClientHosts.h b/src/Access/AllowedClientHosts.h
index 9e89c2b92a1..2baafb2e04a 100644
--- a/src/Access/AllowedClientHosts.h
+++ b/src/Access/AllowedClientHosts.h
@@ -91,7 +91,7 @@ public:
/// Allows IP addresses or host names using LIKE pattern.
/// This pattern can contain % and _ wildcard characters.
- /// For example, addLikePattern("@") will allow all addresses.
+ /// For example, addLikePattern("%") will allow all addresses.
void addLikePattern(const String & pattern);
void removeLikePattern(const String & like_pattern);
const std::vector & getLikePatterns() const { return like_patterns; }
@@ -298,7 +298,7 @@ inline void AllowedClientHosts::addLikePattern(const String & pattern)
{
if (boost::iequals(pattern, "localhost") || (pattern == "127.0.0.1") || (pattern == "::1"))
local_host = true;
- else if ((pattern == "@") || (pattern == "0.0.0.0/0") || (pattern == "::/0"))
+ else if ((pattern == "%") || (pattern == "0.0.0.0/0") || (pattern == "::/0"))
any_host = true;
else if (boost::range::find(like_patterns, pattern) == name_regexps.end())
like_patterns.push_back(pattern);
@@ -308,7 +308,7 @@ inline void AllowedClientHosts::removeLikePattern(const String & pattern)
{
if (boost::iequals(pattern, "localhost") || (pattern == "127.0.0.1") || (pattern == "::1"))
local_host = false;
- else if ((pattern == "@") || (pattern == "0.0.0.0/0") || (pattern == "::/0"))
+ else if ((pattern == "%") || (pattern == "0.0.0.0/0") || (pattern == "::/0"))
any_host = false;
else
boost::range::remove_erase(like_patterns, pattern);
diff --git a/src/Access/ContextAccess.cpp b/src/Access/ContextAccess.cpp
index 4c690956358..14775f7a4de 100644
--- a/src/Access/ContextAccess.cpp
+++ b/src/Access/ContextAccess.cpp
@@ -404,23 +404,19 @@ boost::shared_ptr ContextAccess::calculateResultAccess(bool
static const AccessFlags table_ddl = AccessType::CREATE_DATABASE | AccessType::CREATE_TABLE | AccessType::CREATE_VIEW
| AccessType::ALTER_TABLE | AccessType::ALTER_VIEW | AccessType::DROP_DATABASE | AccessType::DROP_TABLE | AccessType::DROP_VIEW
| AccessType::TRUNCATE;
+
static const AccessFlags dictionary_ddl = AccessType::CREATE_DICTIONARY | AccessType::DROP_DICTIONARY;
static const AccessFlags table_and_dictionary_ddl = table_ddl | dictionary_ddl;
static const AccessFlags write_table_access = AccessType::INSERT | AccessType::OPTIMIZE;
- static const AccessFlags all_dcl = AccessType::CREATE_USER | AccessType::CREATE_ROLE | AccessType::CREATE_POLICY
- | AccessType::CREATE_QUOTA | AccessType::CREATE_SETTINGS_PROFILE | AccessType::ALTER_USER | AccessType::ALTER_ROLE
- | AccessType::ALTER_POLICY | AccessType::ALTER_QUOTA | AccessType::ALTER_SETTINGS_PROFILE | AccessType::DROP_USER
- | AccessType::DROP_ROLE | AccessType::DROP_POLICY | AccessType::DROP_QUOTA | AccessType::DROP_SETTINGS_PROFILE
- | AccessType::ROLE_ADMIN;
if (readonly_)
- merged_access->revoke(write_table_access | all_dcl | table_and_dictionary_ddl | AccessType::SYSTEM | AccessType::KILL_QUERY);
+ merged_access->revoke(write_table_access | table_and_dictionary_ddl | AccessType::SYSTEM | AccessType::KILL_QUERY | AccessType::ACCESS_MANAGEMENT);
if (readonly_ == 1)
{
/// Table functions are forbidden in readonly mode.
/// For example, for readonly = 2 - allowed.
- merged_access->revoke(AccessType::CREATE_TEMPORARY_TABLE | AccessType::TABLE_FUNCTIONS);
+ merged_access->revoke(AccessType::CREATE_TEMPORARY_TABLE);
}
if (!allow_ddl_ && !grant_option)
diff --git a/src/Access/ExtendedRoleSet.cpp b/src/Access/ExtendedRoleSet.cpp
index b59dc7ac232..eed475bc3cc 100644
--- a/src/Access/ExtendedRoleSet.cpp
+++ b/src/Access/ExtendedRoleSet.cpp
@@ -51,25 +51,25 @@ ExtendedRoleSet::ExtendedRoleSet(const boost::container::flat_set & ids_)
ExtendedRoleSet::ExtendedRoleSet(const ASTExtendedRoleSet & ast)
{
- init(ast, nullptr, nullptr);
+ init(ast, nullptr);
}
-ExtendedRoleSet::ExtendedRoleSet(const ASTExtendedRoleSet & ast, const UUID & current_user_id)
+ExtendedRoleSet::ExtendedRoleSet(const ASTExtendedRoleSet & ast, const std::optional & current_user_id)
{
- init(ast, nullptr, ¤t_user_id);
+ init(ast, nullptr, current_user_id);
}
ExtendedRoleSet::ExtendedRoleSet(const ASTExtendedRoleSet & ast, const AccessControlManager & manager)
{
- init(ast, &manager, nullptr);
+ init(ast, &manager);
}
-ExtendedRoleSet::ExtendedRoleSet(const ASTExtendedRoleSet & ast, const AccessControlManager & manager, const UUID & current_user_id)
+ExtendedRoleSet::ExtendedRoleSet(const ASTExtendedRoleSet & ast, const AccessControlManager & manager, const std::optional & current_user_id)
{
- init(ast, &manager, ¤t_user_id);
+ init(ast, &manager, current_user_id);
}
-void ExtendedRoleSet::init(const ASTExtendedRoleSet & ast, const AccessControlManager * manager, const UUID * current_user_id)
+void ExtendedRoleSet::init(const ASTExtendedRoleSet & ast, const AccessControlManager * manager, const std::optional & current_user_id)
{
all = ast.all;
diff --git a/src/Access/ExtendedRoleSet.h b/src/Access/ExtendedRoleSet.h
index 61a4db6e0ae..486b4277337 100644
--- a/src/Access/ExtendedRoleSet.h
+++ b/src/Access/ExtendedRoleSet.h
@@ -32,9 +32,9 @@ struct ExtendedRoleSet
/// The constructor from AST requires the AccessControlManager if `ast.id_mode == false`.
ExtendedRoleSet(const ASTExtendedRoleSet & ast);
- ExtendedRoleSet(const ASTExtendedRoleSet & ast, const UUID & current_user_id);
+ ExtendedRoleSet(const ASTExtendedRoleSet & ast, const std::optional & current_user_id);
ExtendedRoleSet(const ASTExtendedRoleSet & ast, const AccessControlManager & manager);
- ExtendedRoleSet(const ASTExtendedRoleSet & ast, const AccessControlManager & manager, const UUID & current_user_id);
+ ExtendedRoleSet(const ASTExtendedRoleSet & ast, const AccessControlManager & manager, const std::optional & current_user_id);
std::shared_ptr toAST() const;
String toString() const;
@@ -69,7 +69,7 @@ struct ExtendedRoleSet
boost::container::flat_set except_ids;
private:
- void init(const ASTExtendedRoleSet & ast, const AccessControlManager * manager = nullptr, const UUID * current_user_id = nullptr);
+ void init(const ASTExtendedRoleSet & ast, const AccessControlManager * manager = nullptr, const std::optional & current_user_id = {});
};
}
diff --git a/src/Access/UsersConfigAccessStorage.cpp b/src/Access/UsersConfigAccessStorage.cpp
index 13102528108..0842839dec8 100644
--- a/src/Access/UsersConfigAccessStorage.cpp
+++ b/src/Access/UsersConfigAccessStorage.cpp
@@ -168,7 +168,14 @@ namespace
user->access.grant(AccessFlags::allDictionaryFlags(), IDictionary::NO_DATABASE_TAG, dictionary);
}
- user->access_with_grant_option = user->access;
+ user->access_with_grant_option = user->access; /// By default the user can grant everything he has.
+
+ bool access_management = config.getBool(user_config + ".access_management", false);
+ if (!access_management)
+ {
+ user->access.revoke(AccessType::ACCESS_MANAGEMENT);
+ user->access_with_grant_option.clear();
+ }
return user;
}
diff --git a/src/Common/XDBCBridgeHelper.h b/src/Common/XDBCBridgeHelper.h
index 613d1bed8d7..b9d1f2cdcdf 100644
--- a/src/Common/XDBCBridgeHelper.h
+++ b/src/Common/XDBCBridgeHelper.h
@@ -4,6 +4,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -230,6 +231,10 @@ struct JDBCBridgeMixin
{
return "JDBC";
}
+ static AccessType getSourceAccessType()
+ {
+ return AccessType::JDBC;
+ }
static std::unique_ptr startBridge(const Poco::Util::AbstractConfiguration &, const Poco::Logger *, const Poco::Timespan &)
{
@@ -253,6 +258,10 @@ struct ODBCBridgeMixin
{
return "ODBC";
}
+ static AccessType getSourceAccessType()
+ {
+ return AccessType::ODBC;
+ }
static std::unique_ptr startBridge(const Poco::Util::AbstractConfiguration & config, Poco::Logger * log, const Poco::Timespan & http_timeout)
{
diff --git a/src/Functions/FunctionsExternalDictionaries.h b/src/Functions/FunctionsExternalDictionaries.h
index e1c89dd7d53..fc3c2c583a9 100644
--- a/src/Functions/FunctionsExternalDictionaries.h
+++ b/src/Functions/FunctionsExternalDictionaries.h
@@ -128,7 +128,7 @@ private:
auto dict = dictionaries_loader.getDictionary(dict_name_col->getValue());
const auto dict_ptr = dict.get();
- context.checkAccess(AccessType::dictHas, dict_ptr->getDatabaseOrNoDatabaseTag(), dict_ptr->getName());
+ context.checkAccess(AccessType::dictGet, dict_ptr->getDatabaseOrNoDatabaseTag(), dict_ptr->getName());
if (!executeDispatchSimple(block, arguments, result, dict_ptr) &&
!executeDispatchSimple(block, arguments, result, dict_ptr) &&
@@ -1652,7 +1652,7 @@ private:
auto dict = dictionaries_loader.getDictionary(dict_name_col->getValue());
const auto dict_ptr = dict.get();
- context.checkAccess(AccessType::dictGetHierarchy, dict_ptr->getDatabaseOrNoDatabaseTag(), dict_ptr->getName());
+ context.checkAccess(AccessType::dictGet, dict_ptr->getDatabaseOrNoDatabaseTag(), dict_ptr->getName());
if (!executeDispatch(block, arguments, result, dict_ptr) &&
!executeDispatch(block, arguments, result, dict_ptr) &&
@@ -1816,7 +1816,7 @@ private:
auto dict = dictionaries_loader.getDictionary(dict_name_col->getValue());
const auto dict_ptr = dict.get();
- context.checkAccess(AccessType::dictIsIn, dict_ptr->getDatabaseOrNoDatabaseTag(), dict_ptr->getName());
+ context.checkAccess(AccessType::dictGet, dict_ptr->getDatabaseOrNoDatabaseTag(), dict_ptr->getName());
if (!executeDispatch(block, arguments, result, dict_ptr)
&& !executeDispatch(block, arguments, result, dict_ptr)
diff --git a/src/Interpreters/Context.cpp b/src/Interpreters/Context.cpp
index 4dc72948f8a..5e98a0267ca 100644
--- a/src/Interpreters/Context.cpp
+++ b/src/Interpreters/Context.cpp
@@ -665,12 +665,10 @@ String Context::getUserName() const
return access->getUserName();
}
-UUID Context::getUserID() const
+std::optional Context::getUserID() const
{
auto lock = getLock();
- if (!user_id)
- throw Exception("No current user", ErrorCodes::LOGICAL_ERROR);
- return *user_id;
+ return user_id;
}
diff --git a/src/Interpreters/Context.h b/src/Interpreters/Context.h
index e5b33e43614..b34a0e0c542 100644
--- a/src/Interpreters/Context.h
+++ b/src/Interpreters/Context.h
@@ -233,7 +233,7 @@ public:
UserPtr getUser() const;
String getUserName() const;
- UUID getUserID() const;
+ std::optional getUserID() const;
void setCurrentRoles(const std::vector & current_roles_);
void setCurrentRolesDefault();
diff --git a/src/Interpreters/DDLWorker.cpp b/src/Interpreters/DDLWorker.cpp
index eaee356264d..4a39cc6b8a1 100644
--- a/src/Interpreters/DDLWorker.cpp
+++ b/src/Interpreters/DDLWorker.cpp
@@ -1377,4 +1377,9 @@ BlockIO executeDDLQueryOnCluster(const ASTPtr & query_ptr_, const Context & cont
}
+BlockIO executeDDLQueryOnCluster(const ASTPtr & query_ptr_, const Context & context)
+{
+ return executeDDLQueryOnCluster(query_ptr_, context, {});
+}
+
}
diff --git a/src/Interpreters/DDLWorker.h b/src/Interpreters/DDLWorker.h
index 32b7cd5f172..62eba97032e 100644
--- a/src/Interpreters/DDLWorker.h
+++ b/src/Interpreters/DDLWorker.h
@@ -24,6 +24,7 @@ struct DDLTask;
/// Pushes distributed DDL query to the queue
BlockIO executeDDLQueryOnCluster(const ASTPtr & query_ptr, const Context & context, AccessRightsElements && query_required_access);
+BlockIO executeDDLQueryOnCluster(const ASTPtr & query_ptr, const Context & context);
class DDLWorker
diff --git a/src/Interpreters/InterpreterAlterQuery.cpp b/src/Interpreters/InterpreterAlterQuery.cpp
index 7411537601f..7c6b9678325 100644
--- a/src/Interpreters/InterpreterAlterQuery.cpp
+++ b/src/Interpreters/InterpreterAlterQuery.cpp
@@ -149,35 +149,35 @@ AccessRightsElements InterpreterAlterQuery::getRequiredAccessForCommand(const AS
{
case ASTAlterCommand::UPDATE:
{
- required_access.emplace_back(AccessType::UPDATE, database, table, column_names_from_update_assignments());
+ required_access.emplace_back(AccessType::ALTER_UPDATE, database, table, column_names_from_update_assignments());
break;
}
case ASTAlterCommand::DELETE:
{
- required_access.emplace_back(AccessType::DELETE, database, table);
+ required_access.emplace_back(AccessType::ALTER_DELETE, database, table);
break;
}
case ASTAlterCommand::ADD_COLUMN:
{
- required_access.emplace_back(AccessType::ADD_COLUMN, database, table, column_name_from_col_decl());
+ required_access.emplace_back(AccessType::ALTER_ADD_COLUMN, database, table, column_name_from_col_decl());
break;
}
case ASTAlterCommand::DROP_COLUMN:
{
if (command.clear_column)
- required_access.emplace_back(AccessType::CLEAR_COLUMN, database, table, column_name());
+ required_access.emplace_back(AccessType::ALTER_CLEAR_COLUMN, database, table, column_name());
else
- required_access.emplace_back(AccessType::DROP_COLUMN, database, table, column_name());
+ required_access.emplace_back(AccessType::ALTER_DROP_COLUMN, database, table, column_name());
break;
}
case ASTAlterCommand::MODIFY_COLUMN:
{
- required_access.emplace_back(AccessType::MODIFY_COLUMN, database, table, column_name_from_col_decl());
+ required_access.emplace_back(AccessType::ALTER_MODIFY_COLUMN, database, table, column_name_from_col_decl());
break;
}
case ASTAlterCommand::COMMENT_COLUMN:
{
- required_access.emplace_back(AccessType::COMMENT_COLUMN, database, table, column_name());
+ required_access.emplace_back(AccessType::ALTER_COMMENT_COLUMN, database, table, column_name());
break;
}
case ASTAlterCommand::MODIFY_ORDER_BY:
@@ -187,45 +187,45 @@ AccessRightsElements InterpreterAlterQuery::getRequiredAccessForCommand(const AS
}
case ASTAlterCommand::ADD_INDEX:
{
- required_access.emplace_back(AccessType::ADD_INDEX, database, table);
+ required_access.emplace_back(AccessType::ALTER_ADD_INDEX, database, table);
break;
}
case ASTAlterCommand::DROP_INDEX:
{
if (command.clear_index)
- required_access.emplace_back(AccessType::CLEAR_INDEX, database, table);
+ required_access.emplace_back(AccessType::ALTER_CLEAR_INDEX, database, table);
else
- required_access.emplace_back(AccessType::DROP_INDEX, database, table);
+ required_access.emplace_back(AccessType::ALTER_DROP_INDEX, database, table);
break;
}
case ASTAlterCommand::MATERIALIZE_INDEX:
{
- required_access.emplace_back(AccessType::MATERIALIZE_INDEX, database, table);
+ required_access.emplace_back(AccessType::ALTER_MATERIALIZE_INDEX, database, table);
break;
}
case ASTAlterCommand::ADD_CONSTRAINT:
{
- required_access.emplace_back(AccessType::ADD_CONSTRAINT, database, table);
+ required_access.emplace_back(AccessType::ALTER_ADD_CONSTRAINT, database, table);
break;
}
case ASTAlterCommand::DROP_CONSTRAINT:
{
- required_access.emplace_back(AccessType::DROP_CONSTRAINT, database, table);
+ required_access.emplace_back(AccessType::ALTER_DROP_CONSTRAINT, database, table);
break;
}
case ASTAlterCommand::MODIFY_TTL:
{
- required_access.emplace_back(AccessType::MODIFY_TTL, database, table);
+ required_access.emplace_back(AccessType::ALTER_TTL, database, table);
break;
}
case ASTAlterCommand::MATERIALIZE_TTL:
{
- required_access.emplace_back(AccessType::MATERIALIZE_TTL, database, table);
+ required_access.emplace_back(AccessType::ALTER_MATERIALIZE_TTL, database, table);
break;
}
case ASTAlterCommand::MODIFY_SETTING:
{
- required_access.emplace_back(AccessType::MODIFY_SETTING, database, table);
+ required_access.emplace_back(AccessType::ALTER_SETTINGS, database, table);
break;
}
case ASTAlterCommand::ATTACH_PARTITION:
@@ -236,7 +236,7 @@ AccessRightsElements InterpreterAlterQuery::getRequiredAccessForCommand(const AS
case ASTAlterCommand::DROP_PARTITION: [[fallthrough]];
case ASTAlterCommand::DROP_DETACHED_PARTITION:
{
- required_access.emplace_back(AccessType::DELETE, database, table);
+ required_access.emplace_back(AccessType::ALTER_DELETE, database, table);
break;
}
case ASTAlterCommand::MOVE_PARTITION:
@@ -244,11 +244,11 @@ AccessRightsElements InterpreterAlterQuery::getRequiredAccessForCommand(const AS
if ((command.move_destination_type == PartDestinationType::DISK)
|| (command.move_destination_type == PartDestinationType::VOLUME))
{
- required_access.emplace_back(AccessType::MOVE_PARTITION, database, table);
+ required_access.emplace_back(AccessType::ALTER_MOVE_PARTITION, database, table);
}
else if (command.move_destination_type == PartDestinationType::TABLE)
{
- required_access.emplace_back(AccessType::SELECT | AccessType::DELETE, database, table);
+ required_access.emplace_back(AccessType::SELECT | AccessType::ALTER_DELETE, database, table);
required_access.emplace_back(AccessType::INSERT, command.to_database, command.to_table);
}
break;
@@ -256,33 +256,33 @@ AccessRightsElements InterpreterAlterQuery::getRequiredAccessForCommand(const AS
case ASTAlterCommand::REPLACE_PARTITION:
{
required_access.emplace_back(AccessType::SELECT, command.from_database, command.from_table);
- required_access.emplace_back(AccessType::DELETE | AccessType::INSERT, database, table);
+ required_access.emplace_back(AccessType::ALTER_DELETE | AccessType::INSERT, database, table);
break;
}
case ASTAlterCommand::FETCH_PARTITION:
{
- required_access.emplace_back(AccessType::FETCH_PARTITION, database, table);
+ required_access.emplace_back(AccessType::ALTER_FETCH_PARTITION, database, table);
break;
}
case ASTAlterCommand::FREEZE_PARTITION: [[fallthrough]];
case ASTAlterCommand::FREEZE_ALL:
{
- required_access.emplace_back(AccessType::FREEZE_PARTITION, database, table);
+ required_access.emplace_back(AccessType::ALTER_FREEZE_PARTITION, database, table);
break;
}
case ASTAlterCommand::MODIFY_QUERY:
{
- required_access.emplace_back(AccessType::MODIFY_VIEW_QUERY, database, table);
+ required_access.emplace_back(AccessType::ALTER_VIEW_MODIFY_QUERY, database, table);
break;
}
case ASTAlterCommand::LIVE_VIEW_REFRESH:
{
- required_access.emplace_back(AccessType::REFRESH_VIEW, database, table);
+ required_access.emplace_back(AccessType::ALTER_VIEW_REFRESH, database, table);
break;
}
case ASTAlterCommand::RENAME_COLUMN:
{
- required_access.emplace_back(AccessType::RENAME_COLUMN, database, table, column_name());
+ required_access.emplace_back(AccessType::ALTER_RENAME_COLUMN, database, table, column_name());
break;
}
case ASTAlterCommand::NO_TYPE: break;
diff --git a/src/Interpreters/InterpreterCreateQuery.cpp b/src/Interpreters/InterpreterCreateQuery.cpp
index f15796688e1..b605ce85bc2 100644
--- a/src/Interpreters/InterpreterCreateQuery.cpp
+++ b/src/Interpreters/InterpreterCreateQuery.cpp
@@ -765,7 +765,14 @@ AccessRightsElements InterpreterCreateQuery::getRequiredAccess() const
}
if (!create.to_table.empty())
- required_access.emplace_back(AccessType::INSERT, create.to_database, create.to_table);
+ required_access.emplace_back(AccessType::SELECT | AccessType::INSERT, create.to_database, create.to_table);
+
+ if (create.storage && create.storage->engine)
+ {
+ auto source_access_type = StorageFactory::instance().getSourceAccessType(create.storage->engine->name);
+ if (source_access_type != AccessType::NONE)
+ required_access.emplace_back(source_access_type);
+ }
return required_access;
}
diff --git a/src/Interpreters/InterpreterCreateQuotaQuery.cpp b/src/Interpreters/InterpreterCreateQuotaQuery.cpp
index 4b64615dd36..13e772965ff 100644
--- a/src/Interpreters/InterpreterCreateQuotaQuery.cpp
+++ b/src/Interpreters/InterpreterCreateQuotaQuery.cpp
@@ -2,6 +2,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -76,10 +77,16 @@ void updateQuotaFromQueryImpl(Quota & quota, const ASTCreateQuotaQuery & query,
BlockIO InterpreterCreateQuotaQuery::execute()
{
- const auto & query = query_ptr->as();
+ auto & query = query_ptr->as();
auto & access_control = context.getAccessControlManager();
context.checkAccess(query.alter ? AccessType::ALTER_QUOTA : AccessType::CREATE_QUOTA);
+ if (!query.cluster.empty())
+ {
+ query.replaceCurrentUserTagWithName(context.getUserName());
+ return executeDDLQueryOnCluster(query_ptr, context);
+ }
+
std::optional roles_from_query;
if (query.roles)
roles_from_query = ExtendedRoleSet{*query.roles, access_control, context.getUserID()};
diff --git a/src/Interpreters/InterpreterCreateRoleQuery.cpp b/src/Interpreters/InterpreterCreateRoleQuery.cpp
index f64462d443b..ed9135b2bb6 100644
--- a/src/Interpreters/InterpreterCreateRoleQuery.cpp
+++ b/src/Interpreters/InterpreterCreateRoleQuery.cpp
@@ -1,6 +1,7 @@
#include
#include
#include
+#include
#include
#include
@@ -44,6 +45,9 @@ BlockIO InterpreterCreateRoleQuery::execute()
else
context.checkAccess(AccessType::CREATE_ROLE);
+ if (!query.cluster.empty())
+ return executeDDLQueryOnCluster(query_ptr, context);
+
std::optional settings_from_query;
if (query.settings)
settings_from_query = SettingsProfileElements{*query.settings, access_control};
diff --git a/src/Interpreters/InterpreterCreateRowPolicyQuery.cpp b/src/Interpreters/InterpreterCreateRowPolicyQuery.cpp
index 9ea47aba7bb..c3de3876c46 100644
--- a/src/Interpreters/InterpreterCreateRowPolicyQuery.cpp
+++ b/src/Interpreters/InterpreterCreateRowPolicyQuery.cpp
@@ -3,6 +3,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -63,9 +64,15 @@ namespace
BlockIO InterpreterCreateRowPolicyQuery::execute()
{
- const auto & query = query_ptr->as();
+ auto & query = query_ptr->as();
auto & access_control = context.getAccessControlManager();
- context.checkAccess(query.alter ? AccessType::ALTER_POLICY : AccessType::CREATE_POLICY);
+ context.checkAccess(query.alter ? AccessType::ALTER_ROW_POLICY : AccessType::CREATE_ROW_POLICY);
+
+ if (!query.cluster.empty())
+ {
+ query.replaceCurrentUserTagWithName(context.getUserName());
+ return executeDDLQueryOnCluster(query_ptr, context);
+ }
std::optional roles_from_query;
if (query.roles)
diff --git a/src/Interpreters/InterpreterCreateSettingsProfileQuery.cpp b/src/Interpreters/InterpreterCreateSettingsProfileQuery.cpp
index 9d110a69516..cb0b5587bdc 100644
--- a/src/Interpreters/InterpreterCreateSettingsProfileQuery.cpp
+++ b/src/Interpreters/InterpreterCreateSettingsProfileQuery.cpp
@@ -1,6 +1,8 @@
#include
#include
+#include
#include
+#include
#include
#include
#include
@@ -49,13 +51,19 @@ namespace
BlockIO InterpreterCreateSettingsProfileQuery::execute()
{
- const auto & query = query_ptr->as();
+ auto & query = query_ptr->as();
auto & access_control = context.getAccessControlManager();
if (query.alter)
context.checkAccess(AccessType::ALTER_SETTINGS_PROFILE);
else
context.checkAccess(AccessType::CREATE_SETTINGS_PROFILE);
+ if (!query.cluster.empty())
+ {
+ query.replaceCurrentUserTagWithName(context.getUserName());
+ return executeDDLQueryOnCluster(query_ptr, context);
+ }
+
std::optional settings_from_query;
if (query.settings)
settings_from_query = SettingsProfileElements{*query.settings, access_control};
diff --git a/src/Interpreters/InterpreterCreateUserQuery.cpp b/src/Interpreters/InterpreterCreateUserQuery.cpp
index 5dba1fefc9c..78c7cc222ae 100644
--- a/src/Interpreters/InterpreterCreateUserQuery.cpp
+++ b/src/Interpreters/InterpreterCreateUserQuery.cpp
@@ -1,10 +1,11 @@
#include
#include
#include
+#include
#include
+#include
#include
#include
-#include
#include
#include
@@ -67,7 +68,7 @@ namespace
BlockIO InterpreterCreateUserQuery::execute()
{
- const auto & query = query_ptr->as();
+ auto & query = query_ptr->as();
auto & access_control = context.getAccessControlManager();
auto access = context.getAccess();
access->checkAccess(query.alter ? AccessType::ALTER_USER : AccessType::CREATE_USER);
@@ -83,6 +84,9 @@ BlockIO InterpreterCreateUserQuery::execute()
}
}
+ if (!query.cluster.empty())
+ return executeDDLQueryOnCluster(query_ptr, context);
+
std::optional settings_from_query;
if (query.settings)
settings_from_query = SettingsProfileElements{*query.settings, access_control};
diff --git a/src/Interpreters/InterpreterDropAccessEntityQuery.cpp b/src/Interpreters/InterpreterDropAccessEntityQuery.cpp
index 12f33250188..e67e0659796 100644
--- a/src/Interpreters/InterpreterDropAccessEntityQuery.cpp
+++ b/src/Interpreters/InterpreterDropAccessEntityQuery.cpp
@@ -1,6 +1,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -37,7 +38,7 @@ namespace
case Kind::USER: return AccessType::DROP_USER;
case Kind::ROLE: return AccessType::DROP_ROLE;
case Kind::QUOTA: return AccessType::DROP_QUOTA;
- case Kind::ROW_POLICY: return AccessType::DROP_POLICY;
+ case Kind::ROW_POLICY: return AccessType::DROP_ROW_POLICY;
case Kind::SETTINGS_PROFILE: return AccessType::DROP_SETTINGS_PROFILE;
}
__builtin_unreachable();
@@ -52,6 +53,9 @@ BlockIO InterpreterDropAccessEntityQuery::execute()
std::type_index type = getType(query.kind);
context.checkAccess(getRequiredAccessType(query.kind));
+ if (!query.cluster.empty())
+ return executeDDLQueryOnCluster(query_ptr, context);
+
if (query.kind == Kind::ROW_POLICY)
{
Strings full_names;
diff --git a/src/Interpreters/InterpreterDropQuery.cpp b/src/Interpreters/InterpreterDropQuery.cpp
index 42d9528abd5..e3f5d467f38 100644
--- a/src/Interpreters/InterpreterDropQuery.cpp
+++ b/src/Interpreters/InterpreterDropQuery.cpp
@@ -99,7 +99,7 @@ BlockIO InterpreterDropQuery::executeToTable(
}
else if (kind == ASTDropQuery::Kind::Truncate)
{
- context.checkAccess(table->isView() ? AccessType::TRUNCATE_VIEW : AccessType::TRUNCATE_TABLE, table_id);
+ context.checkAccess(AccessType::TRUNCATE, table_id);
table->checkTableCanBeDropped();
/// If table was already dropped by anyone, an exception will be thrown
@@ -316,7 +316,7 @@ AccessRightsElements InterpreterDropQuery::getRequiredAccessForDDLOnCluster() co
if (drop.kind == ASTDropQuery::Kind::Drop)
required_access.emplace_back(AccessType::DROP_TABLE | AccessType::DROP_VIEW, drop.database, drop.table);
else if (drop.kind == ASTDropQuery::Kind::Truncate)
- required_access.emplace_back(AccessType::TRUNCATE_TABLE | AccessType::TRUNCATE_VIEW, drop.database, drop.table);
+ required_access.emplace_back(AccessType::TRUNCATE, drop.database, drop.table);
else if (drop.kind == ASTDropQuery::Kind::Detach)
required_access.emplace_back(AccessType::DROP_TABLE | AccessType::DROP_VIEW, drop.database, drop.table);
}
diff --git a/src/Interpreters/InterpreterGrantQuery.cpp b/src/Interpreters/InterpreterGrantQuery.cpp
index 5d215ff3a93..a5f13dbbbfe 100644
--- a/src/Interpreters/InterpreterGrantQuery.cpp
+++ b/src/Interpreters/InterpreterGrantQuery.cpp
@@ -1,6 +1,8 @@
#include
#include
+#include
#include
+#include
#include
#include
#include
@@ -59,7 +61,7 @@ namespace
BlockIO InterpreterGrantQuery::execute()
{
- const auto & query = query_ptr->as();
+ auto & query = query_ptr->as();
auto & access_control = context.getAccessControlManager();
auto access = context.getAccess();
access->checkGrantOption(query.access_rights_elements);
@@ -72,6 +74,12 @@ BlockIO InterpreterGrantQuery::execute()
access->checkAdminOption(role_from_query);
}
+ if (!query.cluster.empty())
+ {
+ query.replaceCurrentUserTagWithName(context.getUserName());
+ return executeDDLQueryOnCluster(query_ptr, context);
+ }
+
std::vector to_roles = ExtendedRoleSet{*query.to_roles, access_control, context.getUserID()}.getMatchingIDs(access_control);
String current_database = context.getCurrentDatabase();
diff --git a/src/Interpreters/InterpreterKillQueryQuery.cpp b/src/Interpreters/InterpreterKillQueryQuery.cpp
index 196b2b4eef1..b23d88524e1 100644
--- a/src/Interpreters/InterpreterKillQueryQuery.cpp
+++ b/src/Interpreters/InterpreterKillQueryQuery.cpp
@@ -319,7 +319,7 @@ AccessRightsElements InterpreterKillQueryQuery::getRequiredAccessForDDLOnCluster
if (query.type == ASTKillQueryQuery::Type::Query)
required_access.emplace_back(AccessType::KILL_QUERY);
else if (query.type == ASTKillQueryQuery::Type::Mutation)
- required_access.emplace_back(AccessType::UPDATE | AccessType::DELETE | AccessType::MATERIALIZE_INDEX | AccessType::MATERIALIZE_TTL);
+ required_access.emplace_back(AccessType::ALTER_UPDATE | AccessType::ALTER_DELETE | AccessType::ALTER_MATERIALIZE_INDEX | AccessType::ALTER_MATERIALIZE_TTL);
return required_access;
}
diff --git a/src/Interpreters/InterpreterShowCreateAccessEntityQuery.cpp b/src/Interpreters/InterpreterShowCreateAccessEntityQuery.cpp
index 52126b0507e..d2f435106a8 100644
--- a/src/Interpreters/InterpreterShowCreateAccessEntityQuery.cpp
+++ b/src/Interpreters/InterpreterShowCreateAccessEntityQuery.cpp
@@ -256,6 +256,7 @@ BlockInputStreamPtr InterpreterShowCreateAccessEntityQuery::executeImpl()
ASTPtr InterpreterShowCreateAccessEntityQuery::getCreateQuery(const ASTShowCreateAccessEntityQuery & show_query) const
{
const auto & access_control = context.getAccessControlManager();
+ context.checkAccess(getRequiredAccess());
if (show_query.current_user)
{
@@ -281,6 +282,22 @@ ASTPtr InterpreterShowCreateAccessEntityQuery::getCreateQuery(const ASTShowCreat
}
+AccessRightsElements InterpreterShowCreateAccessEntityQuery::getRequiredAccess() const
+{
+ const auto & show_query = query_ptr->as();
+ AccessRightsElements res;
+ switch (show_query.kind)
+ {
+ case Kind::USER: res.emplace_back(AccessType::SHOW_USERS); break;
+ case Kind::ROLE: res.emplace_back(AccessType::SHOW_ROLES); break;
+ case Kind::ROW_POLICY: res.emplace_back(AccessType::SHOW_ROW_POLICIES); break;
+ case Kind::SETTINGS_PROFILE: res.emplace_back(AccessType::SHOW_SETTINGS_PROFILES); break;
+ case Kind::QUOTA: res.emplace_back(AccessType::SHOW_QUOTAS); break;
+ }
+ return res;
+}
+
+
ASTPtr InterpreterShowCreateAccessEntityQuery::getAttachQuery(const IAccessEntity & entity)
{
return getCreateQueryImpl(entity, nullptr, true);
diff --git a/src/Interpreters/InterpreterShowCreateAccessEntityQuery.h b/src/Interpreters/InterpreterShowCreateAccessEntityQuery.h
index 92025bedb6c..0183c59766f 100644
--- a/src/Interpreters/InterpreterShowCreateAccessEntityQuery.h
+++ b/src/Interpreters/InterpreterShowCreateAccessEntityQuery.h
@@ -9,6 +9,7 @@ namespace DB
{
class Context;
class ASTShowCreateAccessEntityQuery;
+class AccessRightsElements;
struct IAccessEntity;
@@ -30,6 +31,7 @@ public:
private:
BlockInputStreamPtr executeImpl();
ASTPtr getCreateQuery(const ASTShowCreateAccessEntityQuery & show_query) const;
+ AccessRightsElements getRequiredAccess() const;
ASTPtr query_ptr;
const Context & context;
diff --git a/src/Interpreters/InterpreterSystemQuery.cpp b/src/Interpreters/InterpreterSystemQuery.cpp
index 9a7d6ae7c5a..056959d372c 100644
--- a/src/Interpreters/InterpreterSystemQuery.cpp
+++ b/src/Interpreters/InterpreterSystemQuery.cpp
@@ -102,19 +102,19 @@ void executeCommandsAndThrowIfError(Callables && ... commands)
AccessType getRequiredAccessType(StorageActionBlockType action_type)
{
if (action_type == ActionLocks::PartsMerge)
- return AccessType::STOP_MERGES;
+ return AccessType::SYSTEM_MERGES;
else if (action_type == ActionLocks::PartsFetch)
- return AccessType::STOP_FETCHES;
+ return AccessType::SYSTEM_FETCHES;
else if (action_type == ActionLocks::PartsSend)
- return AccessType::STOP_REPLICATED_SENDS;
+ return AccessType::SYSTEM_REPLICATED_SENDS;
else if (action_type == ActionLocks::ReplicationQueue)
- return AccessType::STOP_REPLICATION_QUEUES;
+ return AccessType::SYSTEM_REPLICATION_QUEUES;
else if (action_type == ActionLocks::DistributedSend)
- return AccessType::STOP_DISTRIBUTED_SENDS;
+ return AccessType::SYSTEM_DISTRIBUTED_SENDS;
else if (action_type == ActionLocks::PartsTTLMerge)
- return AccessType::STOP_TTL_MERGES;
+ return AccessType::SYSTEM_TTL_MERGES;
else if (action_type == ActionLocks::PartsMove)
- return AccessType::STOP_MOVES;
+ return AccessType::SYSTEM_MOVES;
else
throw Exception("Unknown action type: " + std::to_string(action_type), ErrorCodes::LOGICAL_ERROR);
}
@@ -183,42 +183,42 @@ BlockIO InterpreterSystemQuery::execute()
switch (query.type)
{
case Type::SHUTDOWN:
- context.checkAccess(AccessType::SHUTDOWN);
+ context.checkAccess(AccessType::SYSTEM_SHUTDOWN);
if (kill(0, SIGTERM))
throwFromErrno("System call kill(0, SIGTERM) failed", ErrorCodes::CANNOT_KILL);
break;
case Type::KILL:
- context.checkAccess(AccessType::SHUTDOWN);
+ context.checkAccess(AccessType::SYSTEM_SHUTDOWN);
if (kill(0, SIGKILL))
throwFromErrno("System call kill(0, SIGKILL) failed", ErrorCodes::CANNOT_KILL);
break;
case Type::DROP_DNS_CACHE:
- context.checkAccess(AccessType::DROP_CACHE);
+ context.checkAccess(AccessType::SYSTEM_DROP_DNS_CACHE);
DNSResolver::instance().dropCache();
/// Reinitialize clusters to update their resolved_addresses
system_context.reloadClusterConfig();
break;
case Type::DROP_MARK_CACHE:
- context.checkAccess(AccessType::DROP_CACHE);
+ context.checkAccess(AccessType::SYSTEM_DROP_MARK_CACHE);
system_context.dropMarkCache();
break;
case Type::DROP_UNCOMPRESSED_CACHE:
- context.checkAccess(AccessType::DROP_CACHE);
+ context.checkAccess(AccessType::SYSTEM_DROP_UNCOMPRESSED_CACHE);
system_context.dropUncompressedCache();
break;
#if USE_EMBEDDED_COMPILER
case Type::DROP_COMPILED_EXPRESSION_CACHE:
- context.checkAccess(AccessType::DROP_CACHE);
+ context.checkAccess(AccessType::SYSTEM_DROP_COMPILED_EXPRESSION_CACHE);
system_context.dropCompiledExpressionCache();
break;
#endif
case Type::RELOAD_DICTIONARY:
- context.checkAccess(AccessType::RELOAD_DICTIONARY);
+ context.checkAccess(AccessType::SYSTEM_RELOAD_DICTIONARY);
system_context.getExternalDictionariesLoader().loadOrReload(query.target_dictionary);
ExternalDictionariesLoader::resetAll();
break;
case Type::RELOAD_DICTIONARIES:
- context.checkAccess(AccessType::RELOAD_DICTIONARY);
+ context.checkAccess(AccessType::SYSTEM_RELOAD_DICTIONARY);
executeCommandsAndThrowIfError(
[&] () { system_context.getExternalDictionariesLoader().reloadAllTriedToLoad(); },
[&] () { system_context.getEmbeddedDictionaries().reload(); }
@@ -226,11 +226,11 @@ BlockIO InterpreterSystemQuery::execute()
ExternalDictionariesLoader::resetAll();
break;
case Type::RELOAD_EMBEDDED_DICTIONARIES:
- context.checkAccess(AccessType::RELOAD_DICTIONARY);
+ context.checkAccess(AccessType::SYSTEM_RELOAD_EMBEDDED_DICTIONARIES);
system_context.getEmbeddedDictionaries().reload();
break;
case Type::RELOAD_CONFIG:
- context.checkAccess(AccessType::RELOAD_CONFIG);
+ context.checkAccess(AccessType::SYSTEM_RELOAD_CONFIG);
system_context.reloadConfig();
break;
case Type::STOP_MERGES:
@@ -290,7 +290,7 @@ BlockIO InterpreterSystemQuery::execute()
ErrorCodes::BAD_ARGUMENTS);
break;
case Type::FLUSH_LOGS:
- context.checkAccess(AccessType::FLUSH_LOGS);
+ context.checkAccess(AccessType::SYSTEM_FLUSH_LOGS);
executeCommandsAndThrowIfError(
[&] () { if (auto query_log = context.getQueryLog()) query_log->flush(); },
[&] () { if (auto part_log = context.getPartLog("")) part_log->flush(); },
@@ -313,7 +313,7 @@ BlockIO InterpreterSystemQuery::execute()
StoragePtr InterpreterSystemQuery::tryRestartReplica(const StorageID & replica, Context & system_context, bool need_ddl_guard)
{
- context.checkAccess(AccessType::RESTART_REPLICA, replica);
+ context.checkAccess(AccessType::SYSTEM_RESTART_REPLICA, replica);
auto table_ddl_guard = need_ddl_guard ? DatabaseCatalog::instance().getDDLGuard(replica.getDatabaseName(), replica.getTableName()) : nullptr;
auto [database, table] = DatabaseCatalog::instance().tryGetDatabaseAndTable(replica);
@@ -387,7 +387,7 @@ void InterpreterSystemQuery::restartReplicas(Context & system_context)
void InterpreterSystemQuery::syncReplica(ASTSystemQuery &)
{
- context.checkAccess(AccessType::SYNC_REPLICA, table_id);
+ context.checkAccess(AccessType::SYSTEM_SYNC_REPLICA, table_id);
StoragePtr table = DatabaseCatalog::instance().getTable(table_id);
if (auto storage_replicated = dynamic_cast(table.get()))
@@ -408,7 +408,7 @@ void InterpreterSystemQuery::syncReplica(ASTSystemQuery &)
void InterpreterSystemQuery::flushDistributed(ASTSystemQuery &)
{
- context.checkAccess(AccessType::FLUSH_DISTRIBUTED, table_id);
+ context.checkAccess(AccessType::SYSTEM_FLUSH_DISTRIBUTED, table_id);
if (auto storage_distributed = dynamic_cast(DatabaseCatalog::instance().getTable(table_id).get()))
storage_distributed->flushClusterNodesAllData();
@@ -427,7 +427,7 @@ AccessRightsElements InterpreterSystemQuery::getRequiredAccessForDDLOnCluster()
case Type::SHUTDOWN: [[fallthrough]];
case Type::KILL:
{
- required_access.emplace_back(AccessType::SHUTDOWN);
+ required_access.emplace_back(AccessType::SYSTEM_SHUTDOWN);
break;
}
case Type::DROP_DNS_CACHE: [[fallthrough]];
@@ -437,107 +437,107 @@ AccessRightsElements InterpreterSystemQuery::getRequiredAccessForDDLOnCluster()
#endif
case Type::DROP_UNCOMPRESSED_CACHE:
{
- required_access.emplace_back(AccessType::DROP_CACHE);
+ required_access.emplace_back(AccessType::SYSTEM_DROP_CACHE);
break;
}
case Type::RELOAD_DICTIONARY: [[fallthrough]];
case Type::RELOAD_DICTIONARIES: [[fallthrough]];
case Type::RELOAD_EMBEDDED_DICTIONARIES:
{
- required_access.emplace_back(AccessType::RELOAD_DICTIONARY);
+ required_access.emplace_back(AccessType::SYSTEM_RELOAD_DICTIONARY);
break;
}
case Type::RELOAD_CONFIG:
{
- required_access.emplace_back(AccessType::RELOAD_CONFIG);
+ required_access.emplace_back(AccessType::SYSTEM_RELOAD_CONFIG);
break;
}
case Type::STOP_MERGES: [[fallthrough]];
case Type::START_MERGES:
{
if (query.table.empty())
- required_access.emplace_back(AccessType::STOP_MERGES);
+ required_access.emplace_back(AccessType::SYSTEM_MERGES);
else
- required_access.emplace_back(AccessType::STOP_MERGES, query.database, query.table);
+ required_access.emplace_back(AccessType::SYSTEM_MERGES, query.database, query.table);
break;
}
case Type::STOP_TTL_MERGES: [[fallthrough]];
case Type::START_TTL_MERGES:
{
if (query.table.empty())
- required_access.emplace_back(AccessType::STOP_TTL_MERGES);
+ required_access.emplace_back(AccessType::SYSTEM_TTL_MERGES);
else
- required_access.emplace_back(AccessType::STOP_TTL_MERGES, query.database, query.table);
+ required_access.emplace_back(AccessType::SYSTEM_TTL_MERGES, query.database, query.table);
break;
}
case Type::STOP_MOVES: [[fallthrough]];
case Type::START_MOVES:
{
if (query.table.empty())
- required_access.emplace_back(AccessType::STOP_MOVES);
+ required_access.emplace_back(AccessType::SYSTEM_MOVES);
else
- required_access.emplace_back(AccessType::STOP_MOVES, query.database, query.table);
+ required_access.emplace_back(AccessType::SYSTEM_MOVES, query.database, query.table);
break;
}
case Type::STOP_FETCHES: [[fallthrough]];
case Type::START_FETCHES:
{
if (query.table.empty())
- required_access.emplace_back(AccessType::STOP_FETCHES);
+ required_access.emplace_back(AccessType::SYSTEM_FETCHES);
else
- required_access.emplace_back(AccessType::STOP_FETCHES, query.database, query.table);
+ required_access.emplace_back(AccessType::SYSTEM_FETCHES, query.database, query.table);
break;
}
case Type::STOP_DISTRIBUTED_SENDS: [[fallthrough]];
case Type::START_DISTRIBUTED_SENDS:
{
if (query.table.empty())
- required_access.emplace_back(AccessType::STOP_DISTRIBUTED_SENDS);
+ required_access.emplace_back(AccessType::SYSTEM_DISTRIBUTED_SENDS);
else
- required_access.emplace_back(AccessType::STOP_DISTRIBUTED_SENDS, query.database, query.table);
+ required_access.emplace_back(AccessType::SYSTEM_DISTRIBUTED_SENDS, query.database, query.table);
break;
}
case Type::STOP_REPLICATED_SENDS: [[fallthrough]];
case Type::START_REPLICATED_SENDS:
{
if (query.table.empty())
- required_access.emplace_back(AccessType::STOP_REPLICATED_SENDS);
+ required_access.emplace_back(AccessType::SYSTEM_REPLICATED_SENDS);
else
- required_access.emplace_back(AccessType::STOP_REPLICATED_SENDS, query.database, query.table);
+ required_access.emplace_back(AccessType::SYSTEM_REPLICATED_SENDS, query.database, query.table);
break;
}
case Type::STOP_REPLICATION_QUEUES: [[fallthrough]];
case Type::START_REPLICATION_QUEUES:
{
if (query.table.empty())
- required_access.emplace_back(AccessType::STOP_REPLICATION_QUEUES);
+ required_access.emplace_back(AccessType::SYSTEM_REPLICATION_QUEUES);
else
- required_access.emplace_back(AccessType::STOP_REPLICATION_QUEUES, query.database, query.table);
+ required_access.emplace_back(AccessType::SYSTEM_REPLICATION_QUEUES, query.database, query.table);
break;
}
case Type::SYNC_REPLICA:
{
- required_access.emplace_back(AccessType::SYNC_REPLICA, query.database, query.table);
+ required_access.emplace_back(AccessType::SYSTEM_SYNC_REPLICA, query.database, query.table);
break;
}
case Type::RESTART_REPLICA:
{
- required_access.emplace_back(AccessType::RESTART_REPLICA, query.database, query.table);
+ required_access.emplace_back(AccessType::SYSTEM_RESTART_REPLICA, query.database, query.table);
break;
}
case Type::RESTART_REPLICAS:
{
- required_access.emplace_back(AccessType::RESTART_REPLICA);
+ required_access.emplace_back(AccessType::SYSTEM_RESTART_REPLICA);
break;
}
case Type::FLUSH_DISTRIBUTED:
{
- required_access.emplace_back(AccessType::FLUSH_DISTRIBUTED, query.database, query.table);
+ required_access.emplace_back(AccessType::SYSTEM_FLUSH_DISTRIBUTED, query.database, query.table);
break;
}
case Type::FLUSH_LOGS:
{
- required_access.emplace_back(AccessType::FLUSH_LOGS);
+ required_access.emplace_back(AccessType::SYSTEM_FLUSH_LOGS);
break;
}
case Type::STOP_LISTEN_QUERIES: break;
diff --git a/src/Parsers/ASTCreateQuotaQuery.cpp b/src/Parsers/ASTCreateQuotaQuery.cpp
index 7613fce6167..8fa0dbb0d31 100644
--- a/src/Parsers/ASTCreateQuotaQuery.cpp
+++ b/src/Parsers/ASTCreateQuotaQuery.cpp
@@ -135,6 +135,8 @@ void ASTCreateQuotaQuery::formatImpl(const FormatSettings & settings, FormatStat
settings.ostr << " " << backQuoteIfNeed(name);
+ formatOnCluster(settings);
+
if (!new_name.empty())
formatRenameTo(new_name, settings);
@@ -146,4 +148,12 @@ void ASTCreateQuotaQuery::formatImpl(const FormatSettings & settings, FormatStat
if (roles && (!roles->empty() || alter))
formatToRoles(*roles, settings);
}
+
+
+void ASTCreateQuotaQuery::replaceCurrentUserTagWithName(const String & current_user_name)
+{
+ if (roles)
+ roles->replaceCurrentUserTagWithName(current_user_name);
+}
+
}
diff --git a/src/Parsers/ASTCreateQuotaQuery.h b/src/Parsers/ASTCreateQuotaQuery.h
index 2968c2cc607..09ceaea9825 100644
--- a/src/Parsers/ASTCreateQuotaQuery.h
+++ b/src/Parsers/ASTCreateQuotaQuery.h
@@ -1,6 +1,7 @@
#pragma once
#include