Remove creation of a unnecessary temporary ContextAccess on login.

This commit is contained in:
Vitaly Baranov 2023-07-16 13:40:47 +02:00
parent 7684e68008
commit 16dfb028b6
4 changed files with 46 additions and 38 deletions

View File

@ -6,6 +6,7 @@
#include <Access/DiskAccessStorage.h> #include <Access/DiskAccessStorage.h>
#include <Access/LDAPAccessStorage.h> #include <Access/LDAPAccessStorage.h>
#include <Access/ContextAccess.h> #include <Access/ContextAccess.h>
#include <Access/EnabledSettings.h>
#include <Access/EnabledRolesInfo.h> #include <Access/EnabledRolesInfo.h>
#include <Access/RoleCache.h> #include <Access/RoleCache.h>
#include <Access/RowPolicyCache.h> #include <Access/RowPolicyCache.h>
@ -729,6 +730,14 @@ std::shared_ptr<const EnabledRoles> AccessControl::getEnabledRoles(
} }
std::shared_ptr<const EnabledRolesInfo> AccessControl::getEnabledRolesInfo(
const std::vector<UUID> & current_roles,
const std::vector<UUID> & current_roles_with_admin_option) const
{
return getEnabledRoles(current_roles, current_roles_with_admin_option)->getRolesInfo();
}
std::shared_ptr<const EnabledRowPolicies> AccessControl::getEnabledRowPolicies(const UUID & user_id, const boost::container::flat_set<UUID> & enabled_roles) const std::shared_ptr<const EnabledRowPolicies> AccessControl::getEnabledRowPolicies(const UUID & user_id, const boost::container::flat_set<UUID> & enabled_roles) const
{ {
return row_policy_cache->getEnabledRowPolicies(user_id, enabled_roles); return row_policy_cache->getEnabledRowPolicies(user_id, enabled_roles);
@ -772,6 +781,15 @@ std::shared_ptr<const EnabledSettings> AccessControl::getEnabledSettings(
return settings_profiles_cache->getEnabledSettings(user_id, settings_from_user, enabled_roles, settings_from_enabled_roles); return settings_profiles_cache->getEnabledSettings(user_id, settings_from_user, enabled_roles, settings_from_enabled_roles);
} }
std::shared_ptr<const SettingsProfilesInfo> AccessControl::getEnabledSettingsInfo(
const UUID & user_id,
const SettingsProfileElements & settings_from_user,
const boost::container::flat_set<UUID> & enabled_roles,
const SettingsProfileElements & settings_from_enabled_roles) const
{
return getEnabledSettings(user_id, settings_from_user, enabled_roles, settings_from_enabled_roles)->getInfo();
}
std::shared_ptr<const SettingsProfilesInfo> AccessControl::getSettingsProfileInfo(const UUID & profile_id) std::shared_ptr<const SettingsProfilesInfo> AccessControl::getSettingsProfileInfo(const UUID & profile_id)
{ {
return settings_profiles_cache->getSettingsProfileInfo(profile_id); return settings_profiles_cache->getSettingsProfileInfo(profile_id);

View File

@ -29,6 +29,7 @@ class ContextAccessParams;
struct User; struct User;
using UserPtr = std::shared_ptr<const User>; using UserPtr = std::shared_ptr<const User>;
class EnabledRoles; class EnabledRoles;
struct EnabledRolesInfo;
class RoleCache; class RoleCache;
class EnabledRowPolicies; class EnabledRowPolicies;
class RowPolicyCache; class RowPolicyCache;
@ -187,6 +188,10 @@ public:
const std::vector<UUID> & current_roles, const std::vector<UUID> & current_roles,
const std::vector<UUID> & current_roles_with_admin_option) const; const std::vector<UUID> & current_roles_with_admin_option) const;
std::shared_ptr<const EnabledRolesInfo> getEnabledRolesInfo(
const std::vector<UUID> & current_roles,
const std::vector<UUID> & current_roles_with_admin_option) const;
std::shared_ptr<const EnabledRowPolicies> getEnabledRowPolicies( std::shared_ptr<const EnabledRowPolicies> getEnabledRowPolicies(
const UUID & user_id, const UUID & user_id,
const boost::container::flat_set<UUID> & enabled_roles) const; const boost::container::flat_set<UUID> & enabled_roles) const;
@ -209,6 +214,12 @@ public:
const boost::container::flat_set<UUID> & enabled_roles, const boost::container::flat_set<UUID> & enabled_roles,
const SettingsProfileElements & settings_from_enabled_roles) const; const SettingsProfileElements & settings_from_enabled_roles) const;
std::shared_ptr<const SettingsProfilesInfo> getEnabledSettingsInfo(
const UUID & user_id,
const SettingsProfileElements & settings_from_user,
const boost::container::flat_set<UUID> & enabled_roles,
const SettingsProfileElements & settings_from_enabled_roles) const;
std::shared_ptr<const SettingsProfilesInfo> getSettingsProfileInfo(const UUID & profile_id); std::shared_ptr<const SettingsProfilesInfo> getSettingsProfileInfo(const UUID & profile_id);
const ExternalAuthenticators & getExternalAuthenticators() const; const ExternalAuthenticators & getExternalAuthenticators() const;

View File

@ -1089,52 +1089,31 @@ ConfigurationPtr Context::getUsersConfig()
return shared->users_config; return shared->users_config;
} }
void Context::setUser(const UUID & user_id_, bool set_current_profiles_, bool set_current_roles_, bool set_current_database_) void Context::setUser(const UUID & user_id_)
{ {
/// Prepare lists of user's profiles, constraints, settings, roles. /// Prepare lists of user's profiles, constraints, settings, roles.
/// NOTE: AccessControl::read<User>() and other AccessControl's functions may require some IO work,
/// so Context::getLock() must be unlocked while we're doing this.
std::shared_ptr<const User> user; auto user = getAccessControl().read<User>(user_id_);
std::shared_ptr<const ContextAccess> temp_access; auto default_roles = user->granted_roles.findGranted(user->default_roles);
if (set_current_profiles_ || set_current_roles_ || set_current_database_) auto enabled_roles = getAccessControl().getEnabledRolesInfo(default_roles, {});
{ auto enabled_profiles = getAccessControl().getEnabledSettingsInfo(user_id_, user->settings, enabled_roles->enabled_roles, enabled_roles->settings_from_enabled_roles);
std::optional<ContextAccessParams> params; const auto & database = user->default_database;
{
auto lock = getLock();
params.emplace(ContextAccessParams{user_id_, /* full_access= */ false, /* use_default_roles = */ true, {}, settings, current_database, client_info });
}
/// `temp_access` is used here only to extract information about the user, not to actually check access.
/// NOTE: AccessControl::getContextAccess() may require some IO work, so Context::getLock() must be unlocked while we're doing this.
temp_access = getAccessControl().getContextAccess(*params);
user = temp_access->getUser();
}
std::shared_ptr<const SettingsProfilesInfo> profiles;
if (set_current_profiles_)
profiles = temp_access->getDefaultProfileInfo();
std::optional<std::vector<UUID>> roles;
if (set_current_roles_)
roles = user->granted_roles.findGranted(user->default_roles);
String database;
if (set_current_database_)
database = user->default_database;
/// Apply user's profiles, constraints, settings, roles. /// Apply user's profiles, constraints, settings, roles.
auto lock = getLock(); auto lock = getLock();
setUserID(user_id_); setUserID(user_id_);
if (profiles) /// A profile can specify a value and a readonly constraint for same setting at the same time,
{ /// so we shouldn't check constraints here.
/// A profile can specify a value and a readonly constraint for same setting at the same time, setCurrentProfiles(*enabled_profiles, /* check_constraints= */ false);
/// so we shouldn't check constraints here.
setCurrentProfiles(*profiles, /* check_constraints= */ false);
}
if (roles) setCurrentRoles(default_roles);
setCurrentRoles(*roles);
/// It's optional to specify the DEFAULT DATABASE in the user's definition.
if (!database.empty()) if (!database.empty())
setCurrentDatabase(database); setCurrentDatabase(database);
} }

View File

@ -534,12 +534,10 @@ public:
/// Sets the current user assuming that he/she is already authenticated. /// Sets the current user assuming that he/she is already authenticated.
/// WARNING: This function doesn't check password! /// WARNING: This function doesn't check password!
void setUser(const UUID & user_id_, bool set_current_profiles_ = true, bool set_current_roles_ = true, bool set_current_database_ = true); void setUser(const UUID & user_id_);
UserPtr getUser() const; UserPtr getUser() const;
void setUserID(const UUID & user_id_);
std::optional<UUID> getUserID() const; std::optional<UUID> getUserID() const;
String getUserName() const; String getUserName() const;
void setCurrentRoles(const std::vector<UUID> & current_roles_); void setCurrentRoles(const std::vector<UUID> & current_roles_);
@ -1195,6 +1193,8 @@ private:
void initGlobal(); void initGlobal();
void setUserID(const UUID & user_id_);
template <typename... Args> template <typename... Args>
void checkAccessImpl(const Args &... args) const; void checkAccessImpl(const Args &... args) const;