Use boost::flat_set instead of vector to store current and enabled roles.

This commit is contained in:
Vitaly Baranov 2020-04-29 22:35:56 +03:00
parent b93a15ef36
commit c7213ab607
22 changed files with 172 additions and 217 deletions

View File

@ -42,7 +42,7 @@ public:
std::shared_ptr<const ContextAccess> getContextAccess(
const UUID & user_id,
const std::vector<UUID> & current_roles,
const boost::container::flat_set<UUID> & 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<const ContextAccess> AccessControlManager::getContextAccess(
const UUID & user_id,
const std::vector<UUID> & current_roles,
const boost::container::flat_set<UUID> & current_roles,
bool use_default_roles,
const Settings & settings,
const String & current_database,
@ -124,21 +124,21 @@ std::shared_ptr<const ContextAccess> AccessControlManager::getContextAccess(
std::shared_ptr<const EnabledRoles> AccessControlManager::getEnabledRoles(
const std::vector<UUID> & current_roles,
const std::vector<UUID> & current_roles_with_admin_option) const
const boost::container::flat_set<UUID> & current_roles,
const boost::container::flat_set<UUID> & current_roles_with_admin_option) const
{
return role_cache->getEnabledRoles(current_roles, current_roles_with_admin_option);
}
std::shared_ptr<const EnabledRowPolicies> AccessControlManager::getEnabledRowPolicies(const UUID & user_id, const std::vector<UUID> & enabled_roles) const
std::shared_ptr<const EnabledRowPolicies> AccessControlManager::getEnabledRowPolicies(const UUID & user_id, const boost::container::flat_set<UUID> & enabled_roles) const
{
return row_policy_cache->getEnabledRowPolicies(user_id, enabled_roles);
}
std::shared_ptr<const EnabledQuota> AccessControlManager::getEnabledQuota(
const UUID & user_id, const String & user_name, const std::vector<UUID> & 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<UUID> & 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<QuotaUsageInfo> AccessControlManager::getQuotaUsageInfo() const
std::shared_ptr<const EnabledSettings> AccessControlManager::getEnabledSettings(
const UUID & user_id,
const SettingsProfileElements & settings_from_user,
const std::vector<UUID> & enabled_roles,
const boost::container::flat_set<UUID> & 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);

View File

@ -2,6 +2,7 @@
#include <Access/MultipleAccessStorage.h>
#include <Poco/AutoPtr.h>
#include <boost/container/flat_set.hpp>
#include <memory>
@ -51,24 +52,24 @@ public:
std::shared_ptr<const ContextAccess> getContextAccess(
const UUID & user_id,
const std::vector<UUID> & current_roles,
const boost::container::flat_set<UUID> & current_roles,
bool use_default_roles,
const Settings & settings,
const String & current_database,
const ClientInfo & client_info) const;
std::shared_ptr<const EnabledRoles> getEnabledRoles(
const std::vector<UUID> & current_roles,
const std::vector<UUID> & current_roles_with_admin_option) const;
const boost::container::flat_set<UUID> & current_roles,
const boost::container::flat_set<UUID> & current_roles_with_admin_option) const;
std::shared_ptr<const EnabledRowPolicies> getEnabledRowPolicies(
const UUID & user_id,
const std::vector<UUID> & enabled_roles) const;
const boost::container::flat_set<UUID> & enabled_roles) const;
std::shared_ptr<const EnabledQuota> getEnabledQuota(
const UUID & user_id,
const String & user_name,
const std::vector<UUID> & enabled_roles,
const boost::container::flat_set<UUID> & enabled_roles,
const Poco::Net::IPAddress & address,
const String & custom_quota_key) const;
@ -76,7 +77,7 @@ public:
std::shared_ptr<const EnabledSettings> getEnabledSettings(const UUID & user_id,
const SettingsProfileElements & settings_from_user,
const std::vector<UUID> & enabled_roles,
const boost::container::flat_set<UUID> & enabled_roles,
const SettingsProfileElements & settings_from_enabled_roles) const;
std::shared_ptr<const SettingsChanges> getProfileSettings(const String & profile_name) const;

View File

@ -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<UUID> current_roles, current_roles_with_admin_option;
boost::container::flat_set<UUID> 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<const EnabledRolesInfo> & roles_info_)
@ -170,7 +168,6 @@ void ContextAccess::setRolesInfo(const std::shared_ptr<const EnabledRolesInfo> &
{
assert(roles_info_);
roles_info = roles_info_;
roles_with_admin_option.store(boost::make_shared<boost::container::flat_set<UUID>>(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<String> role_name = manager->readName(role_id);
if (!role_name)
role_name = "ID {" + toString(role_id) + "}";
@ -485,30 +485,6 @@ std::shared_ptr<const EnabledRolesInfo> ContextAccess::getRolesInfo() const
return roles_info;
}
std::vector<UUID> ContextAccess::getCurrentRoles() const
{
std::lock_guard lock{mutex};
return roles_info ? roles_info->current_roles : std::vector<UUID>{};
}
Strings ContextAccess::getCurrentRolesNames() const
{
std::lock_guard lock{mutex};
return roles_info ? roles_info->getCurrentRolesNames() : Strings{};
}
std::vector<UUID> ContextAccess::getEnabledRoles() const
{
std::lock_guard lock{mutex};
return roles_info ? roles_info->enabled_roles : std::vector<UUID>{};
}
Strings ContextAccess::getEnabledRolesNames() const
{
std::lock_guard lock{mutex};
return roles_info ? roles_info->getEnabledRolesNames() : Strings{};
}
std::shared_ptr<const EnabledRowPolicies> ContextAccess::getRowPolicies() const
{
std::lock_guard lock{mutex};

View File

@ -35,7 +35,7 @@ public:
struct Params
{
std::optional<UUID> user_id;
std::vector<UUID> current_roles;
boost::container::flat_set<UUID> 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<const EnabledRolesInfo> getRolesInfo() const;
std::vector<UUID> getCurrentRoles() const;
Strings getCurrentRolesNames() const;
std::vector<UUID> getEnabledRoles() const;
Strings getEnabledRolesNames() const;
/// Returns information about enabled row policies.
/// The function can return nullptr.
std::shared_ptr<const EnabledRowPolicies> 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<const EnabledQuota> 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<const Settings> getDefaultSettings() const;
/// Returns the settings' constraints.
/// The function returns nullptr if there are no constraints.
std::shared_ptr<const SettingsConstraints> 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<const ContextAccess> getFullAccess();
private:
@ -157,7 +172,6 @@ private:
mutable std::shared_ptr<const EnabledRoles> enabled_roles;
mutable ext::scope_guard subscription_for_roles_changes;
mutable std::shared_ptr<const EnabledRolesInfo> roles_info;
mutable boost::atomic_shared_ptr<const boost::container::flat_set<UUID>> roles_with_admin_option;
mutable boost::atomic_shared_ptr<const AccessRights> result_access[7];
mutable std::shared_ptr<const EnabledRowPolicies> enabled_row_policies;
mutable std::shared_ptr<const EnabledQuota> enabled_quota;

View File

@ -23,7 +23,7 @@ public:
{
UUID user_id;
String user_name;
std::vector<UUID> enabled_roles;
boost::container::flat_set<UUID> enabled_roles;
Poco::Net::IPAddress client_address;
String client_key;

View File

@ -2,6 +2,7 @@
#include <Core/UUID.h>
#include <ext/scope_guard.h>
#include <boost/container/flat_set.hpp>
#include <list>
#include <mutex>
#include <vector>
@ -16,8 +17,8 @@ class EnabledRoles
public:
struct Params
{
std::vector<UUID> current_roles;
std::vector<UUID> current_roles_with_admin_option;
boost::container::flat_set<UUID> current_roles;
boost::container::flat_set<UUID> 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(); }

View File

@ -3,8 +3,8 @@
#include <Access/AccessRights.h>
#include <Access/SettingsProfileElement.h>
#include <Core/UUID.h>
#include <boost/container/flat_set.hpp>
#include <unordered_map>
#include <vector>
namespace DB
@ -13,9 +13,9 @@ namespace DB
/// Information about a role.
struct EnabledRolesInfo
{
std::vector<UUID> current_roles;
std::vector<UUID> enabled_roles;
std::vector<UUID> enabled_roles_with_admin_option;
boost::container::flat_set<UUID> current_roles;
boost::container::flat_set<UUID> enabled_roles;
boost::container::flat_set<UUID> enabled_roles_with_admin_option;
std::unordered_map<UUID, String> names_of_roles;
AccessRights access;
AccessRights access_with_grant_option;

View File

@ -21,7 +21,7 @@ public:
struct Params
{
UUID user_id;
std::vector<UUID> enabled_roles;
boost::container::flat_set<UUID> 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(); }

View File

@ -5,6 +5,7 @@
#include <Common/SettingsChanges.h>
#include <Access/SettingsConstraints.h>
#include <Access/SettingsProfileElement.h>
#include <boost/container/flat_set.hpp>
#include <mutex>
@ -17,7 +18,7 @@ public:
struct Params
{
UUID user_id;
std::vector<UUID> enabled_roles;
boost::container::flat_set<UUID> enabled_roles;
SettingsProfileElements settings_from_enabled_roles;
SettingsProfileElements settings_from_user;

View File

@ -136,26 +136,6 @@ std::shared_ptr<ASTExtendedRoleSet> 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<ASTExtendedRoleSet> ExtendedRoleSet::toASTWithNames(const AccessControlManager & manager) const
{
auto ast = std::make_shared<ASTExtendedRoleSet>();
@ -189,6 +169,13 @@ std::shared_ptr<ASTExtendedRoleSet> 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<UUID> & 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<UUID> & enabled_roles) const
{
if (!all && !ids.count(user_id))

View File

@ -36,10 +36,9 @@ struct ExtendedRoleSet
ExtendedRoleSet(const ASTExtendedRoleSet & ast, const AccessControlManager & manager, const std::optional<UUID> & current_user_id);
std::shared_ptr<ASTExtendedRoleSet> toAST() const;
String toString() const;
Strings toStrings() const;
std::shared_ptr<ASTExtendedRoleSet> 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<UUID> & enabled_roles) const;
bool match(const UUID & user_id, const boost::container::flat_set<UUID> & enabled_roles) const;
/// Returns a list of matching IDs. The function must not be called if `all` == `true`.

View File

@ -167,12 +167,7 @@ QuotaCache::QuotaCache(const AccessControlManager & access_control_manager_)
QuotaCache::~QuotaCache() = default;
std::shared_ptr<const EnabledQuota> QuotaCache::getEnabledQuota(
const UUID & user_id,
const String & user_name,
const std::vector<UUID> & enabled_roles,
const Poco::Net::IPAddress & client_address,
const String & client_key)
std::shared_ptr<const EnabledQuota> QuotaCache::getEnabledQuota(const UUID & user_id, const String & user_name, const boost::container::flat_set<UUID> & enabled_roles, const Poco::Net::IPAddress & client_address, const String & client_key)
{
std::lock_guard lock{mutex};
ensureAllQuotasRead();

View File

@ -20,13 +20,7 @@ public:
QuotaCache(const AccessControlManager & access_control_manager_);
~QuotaCache();
std::shared_ptr<const EnabledQuota> getEnabledQuota(
const UUID & user_id,
const String & user_name,
const std::vector<UUID> & enabled_roles,
const Poco::Net::IPAddress & address,
const String & client_key);
std::shared_ptr<const EnabledQuota> getEnabledQuota(const UUID & user_id, const String & user_name, const boost::container::flat_set<UUID> & enabled_roles, const Poco::Net::IPAddress & address, const String & client_key);
std::vector<QuotaUsageInfo> getUsageInfo() const;
private:

View File

@ -2,68 +2,56 @@
#include <Access/Role.h>
#include <Access/EnabledRolesInfo.h>
#include <Access/AccessControlManager.h>
#include <boost/container/flat_map.hpp>
#include <boost/container/flat_set.hpp>
namespace DB
{
namespace
{
struct CollectedRoleInfo
{
RolePtr role;
bool is_current_role = false;
bool with_admin_option = false;
};
void collectRoles(boost::container::flat_map<UUID, CollectedRoleInfo> & collected_roles,
void collectRoles(EnabledRolesInfo & roles_info,
boost::container::flat_set<UUID> & skip_ids,
const std::function<RolePtr(const UUID &)> & 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<EnabledRolesInfo> collectInfoForRoles(const boost::container::flat_map<UUID, CollectedRoleInfo> & roles)
{
auto new_info = std::make_shared<EnabledRolesInfo>();
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<const EnabledRoles> RoleCache::getEnabledRoles(
const std::vector<UUID> & roles, const std::vector<UUID> & roles_with_admin_option)
std::shared_ptr<const EnabledRoles>
RoleCache::getEnabledRoles(const boost::container::flat_set<UUID> & roles, const boost::container::flat_set<UUID> & roles_with_admin_option)
{
std::lock_guard lock{mutex};
@ -93,13 +81,13 @@ std::shared_ptr<const EnabledRoles> RoleCache::getEnabledRoles(
}
auto res = std::shared_ptr<EnabledRoles>(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<UUID, CollectedRoleInfo> 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<EnabledRolesInfo>();
boost::container::flat_set<UUID> 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();
}
}

View File

@ -2,6 +2,7 @@
#include <Access/EnabledRoles.h>
#include <Poco/ExpireCache.h>
#include <boost/container/flat_set.hpp>
#include <map>
#include <mutex>
@ -18,11 +19,12 @@ public:
RoleCache(const AccessControlManager & manager_);
~RoleCache();
std::shared_ptr<const EnabledRoles> getEnabledRoles(const std::vector<UUID> & current_roles, const std::vector<UUID> & current_roles_with_admin_option);
std::shared_ptr<const EnabledRoles> getEnabledRoles(
const boost::container::flat_set<UUID> & current_roles, const boost::container::flat_set<UUID> & 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);

View File

@ -99,7 +99,7 @@ RowPolicyCache::RowPolicyCache(const AccessControlManager & access_control_manag
RowPolicyCache::~RowPolicyCache() = default;
std::shared_ptr<const EnabledRowPolicies> RowPolicyCache::getEnabledRowPolicies(const UUID & user_id, const std::vector<UUID> & enabled_roles)
std::shared_ptr<const EnabledRowPolicies> RowPolicyCache::getEnabledRowPolicies(const UUID & user_id, const boost::container::flat_set<UUID> & enabled_roles)
{
std::lock_guard lock{mutex};
ensureAllRowPoliciesRead();

View File

@ -18,7 +18,7 @@ public:
RowPolicyCache(const AccessControlManager & access_control_manager_);
~RowPolicyCache();
std::shared_ptr<const EnabledRowPolicies> getEnabledRowPolicies(const UUID & user_id, const std::vector<UUID> & enabled_roles);
std::shared_ptr<const EnabledRowPolicies> getEnabledRowPolicies(const UUID & user_id, const boost::container::flat_set<UUID> & enabled_roles);
private:
using ParsedConditions = EnabledRowPolicies::ParsedConditions;

View File

@ -183,7 +183,7 @@ void SettingsProfilesCache::substituteProfiles(SettingsProfileElements & element
std::shared_ptr<const EnabledSettings> SettingsProfilesCache::getEnabledSettings(
const UUID & user_id,
const SettingsProfileElements & settings_from_user,
const std::vector<UUID> & enabled_roles,
const boost::container::flat_set<UUID> & enabled_roles,
const SettingsProfileElements & settings_from_enabled_roles)
{
std::lock_guard lock{mutex};

View File

@ -29,7 +29,7 @@ public:
std::shared_ptr<const EnabledSettings> getEnabledSettings(
const UUID & user_id,
const SettingsProfileElements & settings_from_user_,
const std::vector<UUID> & enabled_roles,
const boost::container::flat_set<UUID> & enabled_roles,
const SettingsProfileElements & settings_from_enabled_roles_);
std::shared_ptr<const SettingsChanges> getProfileSettings(const String & profile_name);

View File

@ -28,6 +28,7 @@
#include <Core/Settings.h>
#include <Access/AccessControlManager.h>
#include <Access/ContextAccess.h>
#include <Access/EnabledRolesInfo.h>
#include <Access/EnabledRowPolicies.h>
#include <Access/User.h>
#include <Access/SettingsProfile.h>
@ -698,7 +699,7 @@ std::optional<UUID> Context::getUserID() const
}
void Context::setCurrentRoles(const std::vector<UUID> & current_roles_)
void Context::setCurrentRoles(const boost::container::flat_set<UUID> & current_roles_)
{
auto lock = getLock();
if (current_roles == current_roles_ && !use_default_roles)
@ -718,24 +719,19 @@ void Context::setCurrentRolesDefault()
calculateAccessRights();
}
std::vector<UUID> Context::getCurrentRoles() const
boost::container::flat_set<UUID> Context::getCurrentRoles() const
{
return getAccess()->getCurrentRoles();
return getRolesInfo()->current_roles;
}
Strings Context::getCurrentRolesNames() const
boost::container::flat_set<UUID> Context::getEnabledRoles() const
{
return getAccess()->getCurrentRolesNames();
return getRolesInfo()->enabled_roles;
}
std::vector<UUID> Context::getEnabledRoles() const
std::shared_ptr<const EnabledRolesInfo> Context::getRolesInfo() const
{
return getAccess()->getEnabledRoles();
}
Strings Context::getEnabledRolesNames() const
{
return getAccess()->getEnabledRolesNames();
return getAccess()->getRolesInfo();
}

View File

@ -51,6 +51,7 @@ class Context;
class ContextAccess;
struct User;
using UserPtr = std::shared_ptr<const User>;
struct EnabledRolesInfo;
class EnabledRowPolicies;
class EnabledQuota;
class AccessFlags;
@ -166,7 +167,7 @@ private:
InputBlocksReader input_blocks_reader;
std::optional<UUID> user_id;
std::vector<UUID> current_roles;
boost::container::flat_set<UUID> current_roles;
bool use_default_roles = false;
std::shared_ptr<const ContextAccess> access;
std::shared_ptr<const EnabledRowPolicies> initial_row_policy;
@ -254,12 +255,11 @@ public:
String getUserName() const;
std::optional<UUID> getUserID() const;
void setCurrentRoles(const std::vector<UUID> & current_roles_);
void setCurrentRoles(const boost::container::flat_set<UUID> & current_roles_);
void setCurrentRolesDefault();
std::vector<UUID> getCurrentRoles() const;
Strings getCurrentRolesNames() const;
std::vector<UUID> getEnabledRoles() const;
Strings getEnabledRolesNames() const;
boost::container::flat_set<UUID> getCurrentRoles() const;
boost::container::flat_set<UUID> getEnabledRoles() const;
std::shared_ptr<const EnabledRolesInfo> getRolesInfo() const;
/// Checks access rights.
/// Empty database means the current database.

View File

@ -39,20 +39,20 @@ void InterpreterSetRoleQuery::setRole(const ASTSetRoleQuery & query)
else
{
ExtendedRoleSet roles_from_query{*query.roles, access_control};
std::vector<UUID> new_current_roles;
boost::container::flat_set<UUID> 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);
}
}