diff --git a/src/Access/AccessControlManager.cpp b/src/Access/AccessControlManager.cpp index f8f15e425ed..e2589969fd8 100644 --- a/src/Access/AccessControlManager.cpp +++ b/src/Access/AccessControlManager.cpp @@ -42,7 +42,7 @@ public: std::shared_ptr getContextAccess( const UUID & user_id, - const std::vector & current_roles, + const boost::container::flat_set & current_roles, bool use_default_roles, const Settings & settings, const String & current_database, @@ -113,7 +113,7 @@ void AccessControlManager::setDefaultProfileName(const String & default_profile_ std::shared_ptr AccessControlManager::getContextAccess( const UUID & user_id, - const std::vector & current_roles, + const boost::container::flat_set & current_roles, bool use_default_roles, const Settings & settings, const String & current_database, @@ -124,21 +124,21 @@ std::shared_ptr AccessControlManager::getContextAccess( std::shared_ptr AccessControlManager::getEnabledRoles( - const std::vector & current_roles, - const std::vector & current_roles_with_admin_option) const + const boost::container::flat_set & current_roles, + const boost::container::flat_set & current_roles_with_admin_option) const { return role_cache->getEnabledRoles(current_roles, current_roles_with_admin_option); } -std::shared_ptr AccessControlManager::getEnabledRowPolicies(const UUID & user_id, const std::vector & enabled_roles) const +std::shared_ptr AccessControlManager::getEnabledRowPolicies(const UUID & user_id, const boost::container::flat_set & enabled_roles) const { return row_policy_cache->getEnabledRowPolicies(user_id, enabled_roles); } std::shared_ptr AccessControlManager::getEnabledQuota( - const UUID & user_id, const String & user_name, const std::vector & enabled_roles, const Poco::Net::IPAddress & address, const String & custom_quota_key) const + const UUID & user_id, const String & user_name, const boost::container::flat_set & enabled_roles, const Poco::Net::IPAddress & address, const String & custom_quota_key) const { return quota_cache->getEnabledQuota(user_id, user_name, enabled_roles, address, custom_quota_key); } @@ -153,7 +153,7 @@ std::vector AccessControlManager::getQuotaUsageInfo() const std::shared_ptr AccessControlManager::getEnabledSettings( const UUID & user_id, const SettingsProfileElements & settings_from_user, - const std::vector & enabled_roles, + const boost::container::flat_set & enabled_roles, const SettingsProfileElements & settings_from_enabled_roles) const { return settings_profiles_cache->getEnabledSettings(user_id, settings_from_user, enabled_roles, settings_from_enabled_roles); diff --git a/src/Access/AccessControlManager.h b/src/Access/AccessControlManager.h index 810970a8379..94bc22eb3e5 100644 --- a/src/Access/AccessControlManager.h +++ b/src/Access/AccessControlManager.h @@ -2,6 +2,7 @@ #include #include +#include #include @@ -51,24 +52,24 @@ public: std::shared_ptr getContextAccess( const UUID & user_id, - const std::vector & current_roles, + const boost::container::flat_set & current_roles, bool use_default_roles, const Settings & settings, const String & current_database, const ClientInfo & client_info) const; std::shared_ptr getEnabledRoles( - const std::vector & current_roles, - const std::vector & current_roles_with_admin_option) const; + const boost::container::flat_set & current_roles, + const boost::container::flat_set & current_roles_with_admin_option) const; std::shared_ptr getEnabledRowPolicies( const UUID & user_id, - const std::vector & enabled_roles) const; + const boost::container::flat_set & enabled_roles) const; std::shared_ptr getEnabledQuota( const UUID & user_id, const String & user_name, - const std::vector & enabled_roles, + const boost::container::flat_set & enabled_roles, const Poco::Net::IPAddress & address, const String & custom_quota_key) const; @@ -76,7 +77,7 @@ public: std::shared_ptr getEnabledSettings(const UUID & user_id, const SettingsProfileElements & settings_from_user, - const std::vector & enabled_roles, + const boost::container::flat_set & enabled_roles, const SettingsProfileElements & settings_from_enabled_roles) const; std::shared_ptr getProfileSettings(const String & profile_name) const; diff --git a/src/Access/ContextAccess.cpp b/src/Access/ContextAccess.cpp index 3a06a9aeead..475a225ba05 100644 --- a/src/Access/ContextAccess.cpp +++ b/src/Access/ContextAccess.cpp @@ -121,7 +121,6 @@ void ContextAccess::setUser(const UserPtr & user_) const subscription_for_roles_changes = {}; enabled_roles = nullptr; roles_info = nullptr; - roles_with_admin_option = nullptr; enabled_row_policies = nullptr; enabled_quota = nullptr; enabled_settings = nullptr; @@ -131,29 +130,28 @@ void ContextAccess::setUser(const UserPtr & user_) const user_name = user->getName(); trace_log = &Poco::Logger::get("ContextAccess (" + user_name + ")"); - std::vector current_roles, current_roles_with_admin_option; + boost::container::flat_set current_roles, current_roles_with_admin_option; if (params.use_default_roles) { for (const UUID & id : user->granted_roles.roles) { if (user->default_roles.match(id)) - current_roles.push_back(id); + current_roles.emplace(id); } - boost::range::set_intersection(current_roles, user->granted_roles.roles_with_admin_option, - std::back_inserter(current_roles_with_admin_option)); } else { - current_roles.reserve(params.current_roles.size()); - for (const auto & id : params.current_roles) - { - if (user->granted_roles.roles.contains(id)) - current_roles.push_back(id); - if (user->granted_roles.roles_with_admin_option.contains(id)) - current_roles_with_admin_option.push_back(id); - } + boost::range::set_intersection( + params.current_roles, + user->granted_roles.roles, + std::inserter(current_roles, current_roles.end())); } + boost::range::set_intersection( + current_roles, + user->granted_roles.roles_with_admin_option, + std::inserter(current_roles_with_admin_option, current_roles_with_admin_option.end())); + subscription_for_roles_changes = {}; enabled_roles = manager->getEnabledRoles(current_roles, current_roles_with_admin_option); subscription_for_roles_changes = enabled_roles->subscribeForChanges([this](const std::shared_ptr & roles_info_) @@ -170,7 +168,6 @@ void ContextAccess::setRolesInfo(const std::shared_ptr & { assert(roles_info_); roles_info = roles_info_; - roles_with_admin_option.store(boost::make_shared>(roles_info->enabled_roles_with_admin_option.begin(), roles_info->enabled_roles_with_admin_option.end())); boost::range::fill(result_access, nullptr /* need recalculate */); enabled_row_policies = manager->getEnabledRowPolicies(*params.user_id, roles_info->enabled_roles); enabled_quota = manager->getEnabledQuota(*params.user_id, user_name, roles_info->enabled_roles, params.address, params.quota_key); @@ -357,10 +354,13 @@ void ContextAccess::checkAdminOption(const UUID & role_id) const if (isGranted(AccessType::ROLE_ADMIN)) return; - auto roles_with_admin_option_loaded = roles_with_admin_option.load(); - if (roles_with_admin_option_loaded && roles_with_admin_option_loaded->count(role_id)) + auto info = getRolesInfo(); + if (info && info->enabled_roles_with_admin_option.count(role_id)) return; + if (!user) + throw Exception(user_name + ": User has been dropped", ErrorCodes::UNKNOWN_USER); + std::optional role_name = manager->readName(role_id); if (!role_name) role_name = "ID {" + toString(role_id) + "}"; @@ -485,30 +485,6 @@ std::shared_ptr ContextAccess::getRolesInfo() const return roles_info; } -std::vector ContextAccess::getCurrentRoles() const -{ - std::lock_guard lock{mutex}; - return roles_info ? roles_info->current_roles : std::vector{}; -} - -Strings ContextAccess::getCurrentRolesNames() const -{ - std::lock_guard lock{mutex}; - return roles_info ? roles_info->getCurrentRolesNames() : Strings{}; -} - -std::vector ContextAccess::getEnabledRoles() const -{ - std::lock_guard lock{mutex}; - return roles_info ? roles_info->enabled_roles : std::vector{}; -} - -Strings ContextAccess::getEnabledRolesNames() const -{ - std::lock_guard lock{mutex}; - return roles_info ? roles_info->getEnabledRolesNames() : Strings{}; -} - std::shared_ptr ContextAccess::getRowPolicies() const { std::lock_guard lock{mutex}; diff --git a/src/Access/ContextAccess.h b/src/Access/ContextAccess.h index e0fbf58dbe8..9a9f0e31470 100644 --- a/src/Access/ContextAccess.h +++ b/src/Access/ContextAccess.h @@ -35,7 +35,7 @@ public: struct Params { std::optional user_id; - std::vector current_roles; + boost::container::flat_set current_roles; bool use_default_roles = false; UInt64 readonly = 0; bool allow_ddl = false; @@ -56,22 +56,36 @@ public: }; const Params & getParams() const { return params; } + + /// Returns the current user. The function can return nullptr. UserPtr getUser() const; String getUserName() const; bool isCorrectPassword(const String & password) const; bool isClientHostAllowed() const; + /// Returns information about current and enabled roles. + /// The function can return nullptr. std::shared_ptr getRolesInfo() const; - std::vector getCurrentRoles() const; - Strings getCurrentRolesNames() const; - std::vector getEnabledRoles() const; - Strings getEnabledRolesNames() const; + /// Returns information about enabled row policies. + /// The function can return nullptr. std::shared_ptr getRowPolicies() const; + + /// Returns the row policy filter for a specified table. + /// The function returns nullptr if there is no filter to apply. ASTPtr getRowPolicyCondition(const String & database, const String & table_name, RowPolicy::ConditionType index, const ASTPtr & extra_condition = nullptr) const; + + /// Returns the quota to track resource consumption. + /// The function returns nullptr if no tracking or limitation is needed. std::shared_ptr getQuota() const; + + /// Returns the default settings, i.e. the settings to apply on user's login. + /// The function returns nullptr if it's no need to apply settings. std::shared_ptr getDefaultSettings() const; + + /// Returns the settings' constraints. + /// The function returns nullptr if there are no constraints. std::shared_ptr getSettingsConstraints() const; /// Checks if a specified access is granted, and throws an exception if not. @@ -118,7 +132,8 @@ public: /// Checks if a specified role is granted with admin option, and throws an exception if not. void checkAdminOption(const UUID & role_id) const; - /// Returns an instance of ContextAccess which has full access to everything. + /// Makes an instance of ContextAccess which provides full access to everything + /// without any limitations. This is used for the global context. static std::shared_ptr getFullAccess(); private: @@ -157,7 +172,6 @@ private: mutable std::shared_ptr enabled_roles; mutable ext::scope_guard subscription_for_roles_changes; mutable std::shared_ptr roles_info; - mutable boost::atomic_shared_ptr> roles_with_admin_option; mutable boost::atomic_shared_ptr result_access[7]; mutable std::shared_ptr enabled_row_policies; mutable std::shared_ptr enabled_quota; diff --git a/src/Access/EnabledQuota.h b/src/Access/EnabledQuota.h index 5a624c651af..e0a04b02206 100644 --- a/src/Access/EnabledQuota.h +++ b/src/Access/EnabledQuota.h @@ -23,7 +23,7 @@ public: { UUID user_id; String user_name; - std::vector enabled_roles; + boost::container::flat_set enabled_roles; Poco::Net::IPAddress client_address; String client_key; diff --git a/src/Access/EnabledRoles.h b/src/Access/EnabledRoles.h index 122b1a16fe3..0c5b799a30b 100644 --- a/src/Access/EnabledRoles.h +++ b/src/Access/EnabledRoles.h @@ -2,6 +2,7 @@ #include #include +#include #include #include #include @@ -16,8 +17,8 @@ class EnabledRoles public: struct Params { - std::vector current_roles; - std::vector current_roles_with_admin_option; + boost::container::flat_set current_roles; + boost::container::flat_set current_roles_with_admin_option; auto toTuple() const { return std::tie(current_roles, current_roles_with_admin_option); } friend bool operator ==(const Params & lhs, const Params & rhs) { return lhs.toTuple() == rhs.toTuple(); } diff --git a/src/Access/EnabledRolesInfo.h b/src/Access/EnabledRolesInfo.h index 837d4b74ad5..45e1bfd9057 100644 --- a/src/Access/EnabledRolesInfo.h +++ b/src/Access/EnabledRolesInfo.h @@ -3,8 +3,8 @@ #include #include #include +#include #include -#include namespace DB @@ -13,9 +13,9 @@ namespace DB /// Information about a role. struct EnabledRolesInfo { - std::vector current_roles; - std::vector enabled_roles; - std::vector enabled_roles_with_admin_option; + boost::container::flat_set current_roles; + boost::container::flat_set enabled_roles; + boost::container::flat_set enabled_roles_with_admin_option; std::unordered_map names_of_roles; AccessRights access; AccessRights access_with_grant_option; diff --git a/src/Access/EnabledRowPolicies.h b/src/Access/EnabledRowPolicies.h index 9befb65ff0b..6274850363c 100644 --- a/src/Access/EnabledRowPolicies.h +++ b/src/Access/EnabledRowPolicies.h @@ -21,7 +21,7 @@ public: struct Params { UUID user_id; - std::vector enabled_roles; + boost::container::flat_set enabled_roles; auto toTuple() const { return std::tie(user_id, enabled_roles); } friend bool operator ==(const Params & lhs, const Params & rhs) { return lhs.toTuple() == rhs.toTuple(); } diff --git a/src/Access/EnabledSettings.h b/src/Access/EnabledSettings.h index d8e969d685d..8e92298328c 100644 --- a/src/Access/EnabledSettings.h +++ b/src/Access/EnabledSettings.h @@ -5,6 +5,7 @@ #include #include #include +#include #include @@ -17,7 +18,7 @@ public: struct Params { UUID user_id; - std::vector enabled_roles; + boost::container::flat_set enabled_roles; SettingsProfileElements settings_from_enabled_roles; SettingsProfileElements settings_from_user; diff --git a/src/Access/ExtendedRoleSet.cpp b/src/Access/ExtendedRoleSet.cpp index adee5fea669..a29ee40380c 100644 --- a/src/Access/ExtendedRoleSet.cpp +++ b/src/Access/ExtendedRoleSet.cpp @@ -136,26 +136,6 @@ std::shared_ptr ExtendedRoleSet::toAST() const } -String ExtendedRoleSet::toString() const -{ - auto ast = toAST(); - return serializeAST(*ast); -} - - -Strings ExtendedRoleSet::toStrings() const -{ - if (all || !except_ids.empty()) - return {toString()}; - - Strings names; - names.reserve(ids.size()); - for (const UUID & id : ids) - names.emplace_back(::DB::toString(id)); - return names; -} - - std::shared_ptr ExtendedRoleSet::toASTWithNames(const AccessControlManager & manager) const { auto ast = std::make_shared(); @@ -189,6 +169,13 @@ std::shared_ptr ExtendedRoleSet::toASTWithNames(const Access } +String ExtendedRoleSet::toString() const +{ + auto ast = toAST(); + return serializeAST(*ast); +} + + String ExtendedRoleSet::toStringWithNames(const AccessControlManager & manager) const { auto ast = toASTWithNames(manager); @@ -198,19 +185,39 @@ String ExtendedRoleSet::toStringWithNames(const AccessControlManager & manager) Strings ExtendedRoleSet::toStringsWithNames(const AccessControlManager & manager) const { - if (all || !except_ids.empty()) - return {toStringWithNames(manager)}; + if (!all && ids.empty()) + return {}; - Strings names; - names.reserve(ids.size()); - for (const UUID & id : ids) + Strings res; + res.reserve(ids.size() + except_ids.size()); + + if (all) + res.emplace_back("ALL"); + else { - auto name = manager.tryReadName(id); - if (name) - names.emplace_back(std::move(*name)); + for (const UUID & id : ids) + { + auto name = manager.tryReadName(id); + if (name) + res.emplace_back(std::move(*name)); + } + std::sort(res.begin(), res.end()); } - boost::range::sort(names); - return names; + + if (!except_ids.empty()) + { + res.emplace_back("EXCEPT"); + size_t old_size = res.size(); + for (const UUID & id : except_ids) + { + auto name = manager.tryReadName(id); + if (name) + res.emplace_back(std::move(*name)); + } + std::sort(res.begin() + old_size, res.end()); + } + + return res; } @@ -247,25 +254,6 @@ bool ExtendedRoleSet::match(const UUID & id) const } -bool ExtendedRoleSet::match(const UUID & user_id, const std::vector & enabled_roles) const -{ - if (!all && !ids.count(user_id)) - { - bool found_enabled_role = std::any_of( - enabled_roles.begin(), enabled_roles.end(), [this](const UUID & enabled_role) { return ids.count(enabled_role); }); - if (!found_enabled_role) - return false; - } - - if (except_ids.count(user_id)) - return false; - - bool in_except_list = std::any_of( - enabled_roles.begin(), enabled_roles.end(), [this](const UUID & enabled_role) { return except_ids.count(enabled_role); }); - return !in_except_list; -} - - bool ExtendedRoleSet::match(const UUID & user_id, const boost::container::flat_set & enabled_roles) const { if (!all && !ids.count(user_id)) diff --git a/src/Access/ExtendedRoleSet.h b/src/Access/ExtendedRoleSet.h index ba84ade49f8..eeb4af84f78 100644 --- a/src/Access/ExtendedRoleSet.h +++ b/src/Access/ExtendedRoleSet.h @@ -36,10 +36,9 @@ struct ExtendedRoleSet ExtendedRoleSet(const ASTExtendedRoleSet & ast, const AccessControlManager & manager, const std::optional & current_user_id); std::shared_ptr toAST() const; - String toString() const; - Strings toStrings() const; - std::shared_ptr toASTWithNames(const AccessControlManager & manager) const; + + String toString() const; String toStringWithNames(const AccessControlManager & manager) const; Strings toStringsWithNames(const AccessControlManager & manager) const; @@ -50,7 +49,6 @@ struct ExtendedRoleSet /// Checks if a specified ID matches this ExtendedRoleSet. bool match(const UUID & id) const; - bool match(const UUID & user_id, const std::vector & enabled_roles) const; bool match(const UUID & user_id, const boost::container::flat_set & enabled_roles) const; /// Returns a list of matching IDs. The function must not be called if `all` == `true`. diff --git a/src/Access/QuotaCache.cpp b/src/Access/QuotaCache.cpp index dca844bf746..2939d2d1ef2 100644 --- a/src/Access/QuotaCache.cpp +++ b/src/Access/QuotaCache.cpp @@ -167,12 +167,7 @@ QuotaCache::QuotaCache(const AccessControlManager & access_control_manager_) QuotaCache::~QuotaCache() = default; -std::shared_ptr QuotaCache::getEnabledQuota( - const UUID & user_id, - const String & user_name, - const std::vector & enabled_roles, - const Poco::Net::IPAddress & client_address, - const String & client_key) +std::shared_ptr QuotaCache::getEnabledQuota(const UUID & user_id, const String & user_name, const boost::container::flat_set & enabled_roles, const Poco::Net::IPAddress & client_address, const String & client_key) { std::lock_guard lock{mutex}; ensureAllQuotasRead(); diff --git a/src/Access/QuotaCache.h b/src/Access/QuotaCache.h index 8399c5f73eb..b9996ed8456 100644 --- a/src/Access/QuotaCache.h +++ b/src/Access/QuotaCache.h @@ -20,13 +20,7 @@ public: QuotaCache(const AccessControlManager & access_control_manager_); ~QuotaCache(); - std::shared_ptr getEnabledQuota( - const UUID & user_id, - const String & user_name, - const std::vector & enabled_roles, - const Poco::Net::IPAddress & address, - const String & client_key); - + std::shared_ptr getEnabledQuota(const UUID & user_id, const String & user_name, const boost::container::flat_set & enabled_roles, const Poco::Net::IPAddress & address, const String & client_key); std::vector getUsageInfo() const; private: diff --git a/src/Access/RoleCache.cpp b/src/Access/RoleCache.cpp index 441e3844a07..ca8065145f3 100644 --- a/src/Access/RoleCache.cpp +++ b/src/Access/RoleCache.cpp @@ -2,68 +2,56 @@ #include #include #include -#include +#include namespace DB { namespace { - struct CollectedRoleInfo - { - RolePtr role; - bool is_current_role = false; - bool with_admin_option = false; - }; - - - void collectRoles(boost::container::flat_map & collected_roles, + void collectRoles(EnabledRolesInfo & roles_info, + boost::container::flat_set & skip_ids, const std::function & get_role_function, const UUID & role_id, bool is_current_role, bool with_admin_option) { - auto it = collected_roles.find(role_id); - if (it != collected_roles.end()) + if (roles_info.enabled_roles.count(role_id)) { - it->second.is_current_role |= is_current_role; - it->second.with_admin_option |= with_admin_option; + if (is_current_role) + roles_info.current_roles.emplace(role_id); + if (with_admin_option) + roles_info.enabled_roles_with_admin_option.emplace(role_id); return; } + if (skip_ids.count(role_id)) + return; + auto role = get_role_function(role_id); - collected_roles[role_id] = CollectedRoleInfo{role, is_current_role, with_admin_option}; if (!role) + { + skip_ids.emplace(role_id); return; + } + + roles_info.enabled_roles.emplace(role_id); + if (is_current_role) + roles_info.current_roles.emplace(role_id); + if (with_admin_option) + roles_info.enabled_roles_with_admin_option.emplace(role_id); + + roles_info.names_of_roles[role_id] = role->getName(); + roles_info.access.merge(role->access.access); + roles_info.access_with_grant_option.merge(role->access.access_with_grant_option); + roles_info.settings_from_enabled_roles.merge(role->settings); for (const auto & granted_role : role->granted_roles.roles) - collectRoles(collected_roles, get_role_function, granted_role, false, false); + collectRoles(roles_info, skip_ids, get_role_function, granted_role, false, false); for (const auto & granted_role : role->granted_roles.roles_with_admin_option) - collectRoles(collected_roles, get_role_function, granted_role, false, true); - } - - - std::shared_ptr collectInfoForRoles(const boost::container::flat_map & roles) - { - auto new_info = std::make_shared(); - for (const auto & [role_id, collect_info] : roles) - { - const auto & role = collect_info.role; - if (!role) - continue; - if (collect_info.is_current_role) - new_info->current_roles.emplace_back(role_id); - new_info->enabled_roles.emplace_back(role_id); - if (collect_info.with_admin_option) - new_info->enabled_roles_with_admin_option.emplace_back(role_id); - new_info->names_of_roles[role_id] = role->getName(); - new_info->access.merge(role->access.access); - new_info->access_with_grant_option.merge(role->access.access_with_grant_option); - new_info->settings_from_enabled_roles.merge(role->settings); - } - return new_info; + collectRoles(roles_info, skip_ids, get_role_function, granted_role, false, true); } } @@ -75,8 +63,8 @@ RoleCache::RoleCache(const AccessControlManager & manager_) RoleCache::~RoleCache() = default; -std::shared_ptr RoleCache::getEnabledRoles( - const std::vector & roles, const std::vector & roles_with_admin_option) +std::shared_ptr +RoleCache::getEnabledRoles(const boost::container::flat_set & roles, const boost::container::flat_set & roles_with_admin_option) { std::lock_guard lock{mutex}; @@ -93,13 +81,13 @@ std::shared_ptr RoleCache::getEnabledRoles( } auto res = std::shared_ptr(new EnabledRoles(params)); - collectRolesInfoFor(*res); + collectEnabledRoles(*res); enabled_roles.emplace(std::move(params), res); return res; } -void RoleCache::collectRolesInfo() +void RoleCache::collectEnabledRoles() { /// `mutex` is already locked. @@ -110,28 +98,29 @@ void RoleCache::collectRolesInfo() i = enabled_roles.erase(i); else { - collectRolesInfoFor(*elem); + collectEnabledRoles(*elem); ++i; } } } -void RoleCache::collectRolesInfoFor(EnabledRoles & enabled) +void RoleCache::collectEnabledRoles(EnabledRoles & enabled) { /// `mutex` is already locked. - /// Collect roles in use. That includes the current roles, the roles granted to the current roles, and so on. - boost::container::flat_map collected_roles; + /// Collect enabled roles. That includes the current roles, the roles granted to the current roles, and so on. + auto new_info = std::make_shared(); + boost::container::flat_set skip_ids; auto get_role_function = [this](const UUID & id) { return getRole(id); }; for (const auto & current_role : enabled.params.current_roles) - collectRoles(collected_roles, get_role_function, current_role, true, false); + collectRoles(*new_info, skip_ids, get_role_function, current_role, true, false); for (const auto & current_role : enabled.params.current_roles_with_admin_option) - collectRoles(collected_roles, get_role_function, current_role, true, true); + collectRoles(*new_info, skip_ids, get_role_function, current_role, true, true); /// Collect data from the collected roles. - enabled.setRolesInfo(collectInfoForRoles(collected_roles)); + enabled.setRolesInfo(new_info); } @@ -174,7 +163,7 @@ void RoleCache::roleChanged(const UUID & role_id, const RolePtr & changed_role) return; role_from_cache->first = changed_role; cache.update(role_id, role_from_cache); - collectRolesInfo(); + collectEnabledRoles(); } @@ -182,7 +171,7 @@ void RoleCache::roleRemoved(const UUID & role_id) { std::lock_guard lock{mutex}; cache.remove(role_id); - collectRolesInfo(); + collectEnabledRoles(); } } diff --git a/src/Access/RoleCache.h b/src/Access/RoleCache.h index 69f4cb2ebe8..f1ef783b5c4 100644 --- a/src/Access/RoleCache.h +++ b/src/Access/RoleCache.h @@ -2,6 +2,7 @@ #include #include +#include #include #include @@ -18,11 +19,12 @@ public: RoleCache(const AccessControlManager & manager_); ~RoleCache(); - std::shared_ptr getEnabledRoles(const std::vector & current_roles, const std::vector & current_roles_with_admin_option); + std::shared_ptr getEnabledRoles( + const boost::container::flat_set & current_roles, const boost::container::flat_set & current_roles_with_admin_option); private: - void collectRolesInfo(); - void collectRolesInfoFor(EnabledRoles & enabled); + void collectEnabledRoles(); + void collectEnabledRoles(EnabledRoles & enabled); RolePtr getRole(const UUID & role_id); void roleChanged(const UUID & role_id, const RolePtr & changed_role); void roleRemoved(const UUID & role_id); diff --git a/src/Access/RowPolicyCache.cpp b/src/Access/RowPolicyCache.cpp index 0c9fea69dc4..06ccf021dad 100644 --- a/src/Access/RowPolicyCache.cpp +++ b/src/Access/RowPolicyCache.cpp @@ -99,7 +99,7 @@ RowPolicyCache::RowPolicyCache(const AccessControlManager & access_control_manag RowPolicyCache::~RowPolicyCache() = default; -std::shared_ptr RowPolicyCache::getEnabledRowPolicies(const UUID & user_id, const std::vector & enabled_roles) +std::shared_ptr RowPolicyCache::getEnabledRowPolicies(const UUID & user_id, const boost::container::flat_set & enabled_roles) { std::lock_guard lock{mutex}; ensureAllRowPoliciesRead(); diff --git a/src/Access/RowPolicyCache.h b/src/Access/RowPolicyCache.h index d0ec74b9ab8..3b4ecd6e8f5 100644 --- a/src/Access/RowPolicyCache.h +++ b/src/Access/RowPolicyCache.h @@ -18,7 +18,7 @@ public: RowPolicyCache(const AccessControlManager & access_control_manager_); ~RowPolicyCache(); - std::shared_ptr getEnabledRowPolicies(const UUID & user_id, const std::vector & enabled_roles); + std::shared_ptr getEnabledRowPolicies(const UUID & user_id, const boost::container::flat_set & enabled_roles); private: using ParsedConditions = EnabledRowPolicies::ParsedConditions; diff --git a/src/Access/SettingsProfilesCache.cpp b/src/Access/SettingsProfilesCache.cpp index 516b47213fe..3f9399ca484 100644 --- a/src/Access/SettingsProfilesCache.cpp +++ b/src/Access/SettingsProfilesCache.cpp @@ -183,7 +183,7 @@ void SettingsProfilesCache::substituteProfiles(SettingsProfileElements & element std::shared_ptr SettingsProfilesCache::getEnabledSettings( const UUID & user_id, const SettingsProfileElements & settings_from_user, - const std::vector & enabled_roles, + const boost::container::flat_set & enabled_roles, const SettingsProfileElements & settings_from_enabled_roles) { std::lock_guard lock{mutex}; diff --git a/src/Access/SettingsProfilesCache.h b/src/Access/SettingsProfilesCache.h index 656ffc6fce6..42dd05df351 100644 --- a/src/Access/SettingsProfilesCache.h +++ b/src/Access/SettingsProfilesCache.h @@ -29,7 +29,7 @@ public: std::shared_ptr getEnabledSettings( const UUID & user_id, const SettingsProfileElements & settings_from_user_, - const std::vector & enabled_roles, + const boost::container::flat_set & enabled_roles, const SettingsProfileElements & settings_from_enabled_roles_); std::shared_ptr getProfileSettings(const String & profile_name); diff --git a/src/Interpreters/Context.cpp b/src/Interpreters/Context.cpp index f5651a1ab77..d6176c50ba4 100644 --- a/src/Interpreters/Context.cpp +++ b/src/Interpreters/Context.cpp @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -698,7 +699,7 @@ std::optional Context::getUserID() const } -void Context::setCurrentRoles(const std::vector & current_roles_) +void Context::setCurrentRoles(const boost::container::flat_set & current_roles_) { auto lock = getLock(); if (current_roles == current_roles_ && !use_default_roles) @@ -718,24 +719,19 @@ void Context::setCurrentRolesDefault() calculateAccessRights(); } -std::vector Context::getCurrentRoles() const +boost::container::flat_set Context::getCurrentRoles() const { - return getAccess()->getCurrentRoles(); + return getRolesInfo()->current_roles; } -Strings Context::getCurrentRolesNames() const +boost::container::flat_set Context::getEnabledRoles() const { - return getAccess()->getCurrentRolesNames(); + return getRolesInfo()->enabled_roles; } -std::vector Context::getEnabledRoles() const +std::shared_ptr Context::getRolesInfo() const { - return getAccess()->getEnabledRoles(); -} - -Strings Context::getEnabledRolesNames() const -{ - return getAccess()->getEnabledRolesNames(); + return getAccess()->getRolesInfo(); } diff --git a/src/Interpreters/Context.h b/src/Interpreters/Context.h index 0d2b3cdb5af..6cb2893af98 100644 --- a/src/Interpreters/Context.h +++ b/src/Interpreters/Context.h @@ -51,6 +51,7 @@ class Context; class ContextAccess; struct User; using UserPtr = std::shared_ptr; +struct EnabledRolesInfo; class EnabledRowPolicies; class EnabledQuota; class AccessFlags; @@ -166,7 +167,7 @@ private: InputBlocksReader input_blocks_reader; std::optional user_id; - std::vector current_roles; + boost::container::flat_set current_roles; bool use_default_roles = false; std::shared_ptr access; std::shared_ptr initial_row_policy; @@ -254,12 +255,11 @@ public: String getUserName() const; std::optional getUserID() const; - void setCurrentRoles(const std::vector & current_roles_); + void setCurrentRoles(const boost::container::flat_set & current_roles_); void setCurrentRolesDefault(); - std::vector getCurrentRoles() const; - Strings getCurrentRolesNames() const; - std::vector getEnabledRoles() const; - Strings getEnabledRolesNames() const; + boost::container::flat_set getCurrentRoles() const; + boost::container::flat_set getEnabledRoles() const; + std::shared_ptr getRolesInfo() const; /// Checks access rights. /// Empty database means the current database. diff --git a/src/Interpreters/InterpreterSetRoleQuery.cpp b/src/Interpreters/InterpreterSetRoleQuery.cpp index f56926332ec..f8e0167d748 100644 --- a/src/Interpreters/InterpreterSetRoleQuery.cpp +++ b/src/Interpreters/InterpreterSetRoleQuery.cpp @@ -39,20 +39,20 @@ void InterpreterSetRoleQuery::setRole(const ASTSetRoleQuery & query) else { ExtendedRoleSet roles_from_query{*query.roles, access_control}; - std::vector new_current_roles; + boost::container::flat_set new_current_roles; if (roles_from_query.all) { for (const auto & id : user->granted_roles.roles) if (roles_from_query.match(id)) - new_current_roles.push_back(id); + new_current_roles.emplace(id); } else { for (const auto & id : roles_from_query.getMatchingIDs()) { - if (!user->granted_roles.roles.contains(id)) + if (!user->granted_roles.roles.count(id)) throw Exception("Role should be granted to set current", ErrorCodes::SET_NON_GRANTED_ROLE); - new_current_roles.push_back(id); + new_current_roles.emplace(id); } } session_context.setCurrentRoles(new_current_roles); @@ -85,7 +85,7 @@ void InterpreterSetRoleQuery::updateUserSetDefaultRoles(User & user, const Exten { for (const auto & id : roles_from_query.getMatchingIDs()) { - if (!user.granted_roles.roles.contains(id)) + if (!user.granted_roles.roles.count(id)) throw Exception("Role should be granted to set default", ErrorCodes::SET_NON_GRANTED_ROLE); } }