mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-24 16:42:05 +00:00
Use boost::flat_set instead of vector to store current and enabled roles.
This commit is contained in:
parent
b93a15ef36
commit
c7213ab607
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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};
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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(); }
|
||||
|
@ -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;
|
||||
|
@ -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(); }
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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());
|
||||
Strings res;
|
||||
res.reserve(ids.size() + except_ids.size());
|
||||
|
||||
if (all)
|
||||
res.emplace_back("ALL");
|
||||
else
|
||||
{
|
||||
for (const UUID & id : ids)
|
||||
{
|
||||
auto name = manager.tryReadName(id);
|
||||
if (name)
|
||||
names.emplace_back(std::move(*name));
|
||||
res.emplace_back(std::move(*name));
|
||||
}
|
||||
boost::range::sort(names);
|
||||
return names;
|
||||
std::sort(res.begin(), res.end());
|
||||
}
|
||||
|
||||
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))
|
||||
|
@ -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`.
|
||||
|
@ -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();
|
||||
|
@ -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:
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
|
@ -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};
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user