summaryrefslogtreecommitdiffstats
path: root/contrib/clickhouse/src/Interpreters/Access/InterpreterCreateUserQuery.cpp
diff options
context:
space:
mode:
authorvitalyisaev <[email protected]>2023-11-14 09:58:56 +0300
committervitalyisaev <[email protected]>2023-11-14 10:20:20 +0300
commitc2b2dfd9827a400a8495e172a56343462e3ceb82 (patch)
treecd4e4f597d01bede4c82dffeb2d780d0a9046bd0 /contrib/clickhouse/src/Interpreters/Access/InterpreterCreateUserQuery.cpp
parentd4ae8f119e67808cb0cf776ba6e0cf95296f2df7 (diff)
YQ Connector: move tests from yql to ydb (OSS)
Перенос папки с тестами на Коннектор из папки yql в папку ydb (синхронизируется с github).
Diffstat (limited to 'contrib/clickhouse/src/Interpreters/Access/InterpreterCreateUserQuery.cpp')
-rw-r--r--contrib/clickhouse/src/Interpreters/Access/InterpreterCreateUserQuery.cpp232
1 files changed, 232 insertions, 0 deletions
diff --git a/contrib/clickhouse/src/Interpreters/Access/InterpreterCreateUserQuery.cpp b/contrib/clickhouse/src/Interpreters/Access/InterpreterCreateUserQuery.cpp
new file mode 100644
index 00000000000..cd4565293ac
--- /dev/null
+++ b/contrib/clickhouse/src/Interpreters/Access/InterpreterCreateUserQuery.cpp
@@ -0,0 +1,232 @@
+#include <Interpreters/Access/InterpreterCreateUserQuery.h>
+
+#include <Access/AccessControl.h>
+#include <Access/ContextAccess.h>
+#include <Access/ReplicatedAccessStorage.h>
+#include <Access/User.h>
+#include <Common/logger_useful.h>
+#include <Interpreters/Access/InterpreterSetRoleQuery.h>
+#include <Interpreters/Context.h>
+#include <Interpreters/executeDDLQueryOnCluster.h>
+#include <Interpreters/removeOnClusterClauseIfNeeded.h>
+#include <Parsers/ASTDatabaseOrNone.h>
+#include <Parsers/Access/ASTCreateUserQuery.h>
+#include <Parsers/Access/ASTRolesOrUsersSet.h>
+#include <Parsers/Access/ASTUserNameWithHost.h>
+#include <boost/range/algorithm/copy.hpp>
+
+
+namespace DB
+{
+namespace ErrorCodes
+{
+ extern const int BAD_ARGUMENTS;
+ extern const int ACCESS_ENTITY_ALREADY_EXISTS;
+}
+namespace
+{
+ void updateUserFromQueryImpl(
+ User & user,
+ const ASTCreateUserQuery & query,
+ const std::optional<AuthenticationData> auth_data,
+ const std::shared_ptr<ASTUserNameWithHost> & override_name,
+ const std::optional<RolesOrUsersSet> & override_default_roles,
+ const std::optional<SettingsProfileElements> & override_settings,
+ const std::optional<RolesOrUsersSet> & override_grantees,
+ bool allow_implicit_no_password,
+ bool allow_no_password,
+ bool allow_plaintext_password)
+ {
+ if (override_name)
+ user.setName(override_name->toString());
+ else if (query.new_name)
+ user.setName(*query.new_name);
+ else if (query.names->size() == 1)
+ user.setName(query.names->front()->toString());
+
+ if (!query.attach && !query.alter && !auth_data && !allow_implicit_no_password)
+ throw Exception(ErrorCodes::BAD_ARGUMENTS,
+ "Authentication type NO_PASSWORD must "
+ "be explicitly specified, check the setting allow_implicit_no_password "
+ "in the server configuration");
+
+ if (auth_data)
+ user.auth_data = *auth_data;
+
+ if (auth_data || !query.alter)
+ {
+ auto auth_type = user.auth_data.getType();
+ if (((auth_type == AuthenticationType::NO_PASSWORD) && !allow_no_password) ||
+ ((auth_type == AuthenticationType::PLAINTEXT_PASSWORD) && !allow_plaintext_password))
+ {
+ throw Exception(ErrorCodes::BAD_ARGUMENTS,
+ "Authentication type {} is not allowed, check the setting allow_{} in the server configuration",
+ toString(auth_type),
+ AuthenticationTypeInfo::get(auth_type).name);
+ }
+ }
+
+ if (override_name && !override_name->host_pattern.empty())
+ {
+ user.allowed_client_hosts = AllowedClientHosts{};
+ user.allowed_client_hosts.addLikePattern(override_name->host_pattern);
+ }
+ else if (query.hosts)
+ user.allowed_client_hosts = *query.hosts;
+
+ if (query.remove_hosts)
+ user.allowed_client_hosts.remove(*query.remove_hosts);
+ if (query.add_hosts)
+ user.allowed_client_hosts.add(*query.add_hosts);
+
+ auto set_default_roles = [&](const RolesOrUsersSet & default_roles_)
+ {
+ if (!query.alter && !default_roles_.all)
+ user.granted_roles.grant(default_roles_.getMatchingIDs());
+
+ InterpreterSetRoleQuery::updateUserSetDefaultRoles(user, default_roles_);
+ };
+
+ if (override_default_roles)
+ set_default_roles(*override_default_roles);
+ else if (query.default_roles)
+ set_default_roles(*query.default_roles);
+
+ if (query.default_database)
+ user.default_database = query.default_database->database_name;
+
+ if (override_settings)
+ user.settings = *override_settings;
+ else if (query.settings)
+ user.settings = *query.settings;
+
+ if (override_grantees)
+ user.grantees = *override_grantees;
+ else if (query.grantees)
+ user.grantees = *query.grantees;
+ }
+}
+
+BlockIO InterpreterCreateUserQuery::execute()
+{
+ const auto updated_query_ptr = removeOnClusterClauseIfNeeded(query_ptr, getContext());
+ const auto & query = updated_query_ptr->as<const ASTCreateUserQuery &>();
+
+ auto & access_control = getContext()->getAccessControl();
+ auto access = getContext()->getAccess();
+ access->checkAccess(query.alter ? AccessType::ALTER_USER : AccessType::CREATE_USER);
+ bool implicit_no_password_allowed = access_control.isImplicitNoPasswordAllowed();
+ bool no_password_allowed = access_control.isNoPasswordAllowed();
+ bool plaintext_password_allowed = access_control.isPlaintextPasswordAllowed();
+
+ std::optional<AuthenticationData> auth_data;
+ if (query.auth_data)
+ auth_data = AuthenticationData::fromAST(*query.auth_data, getContext(), !query.attach);
+
+ std::optional<RolesOrUsersSet> default_roles_from_query;
+ if (query.default_roles)
+ {
+ default_roles_from_query = RolesOrUsersSet{*query.default_roles, access_control};
+ if (!query.alter && !default_roles_from_query->all)
+ {
+ for (const UUID & role : default_roles_from_query->getMatchingIDs())
+ access->checkAdminOption(role);
+ }
+ }
+
+ std::optional<SettingsProfileElements> settings_from_query;
+ if (query.settings)
+ {
+ settings_from_query = SettingsProfileElements{*query.settings, access_control};
+
+ if (!query.attach)
+ getContext()->checkSettingsConstraints(*settings_from_query, SettingSource::USER);
+ }
+
+ if (!query.cluster.empty())
+ return executeDDLQueryOnCluster(updated_query_ptr, getContext());
+
+ IAccessStorage * storage = &access_control;
+ MultipleAccessStorage::StoragePtr storage_ptr;
+
+ if (!query.storage_name.empty())
+ {
+ storage_ptr = access_control.getStorageByName(query.storage_name);
+ storage = storage_ptr.get();
+ }
+
+ Strings names = query.names->toStrings();
+ if (query.alter)
+ {
+ std::optional<RolesOrUsersSet> grantees_from_query;
+ if (query.grantees)
+ grantees_from_query = RolesOrUsersSet{*query.grantees, access_control};
+
+ auto update_func = [&](const AccessEntityPtr & entity) -> AccessEntityPtr
+ {
+ auto updated_user = typeid_cast<std::shared_ptr<User>>(entity->clone());
+ updateUserFromQueryImpl(*updated_user, query, auth_data, {}, default_roles_from_query, settings_from_query, grantees_from_query, implicit_no_password_allowed, no_password_allowed, plaintext_password_allowed);
+ return updated_user;
+ };
+
+ if (query.if_exists)
+ {
+ auto ids = storage->find<User>(names);
+ storage->tryUpdate(ids, update_func);
+ }
+ else
+ storage->update(storage->getIDs<User>(names), update_func);
+ }
+ else
+ {
+ std::vector<AccessEntityPtr> new_users;
+ for (const auto & name : *query.names)
+ {
+ auto new_user = std::make_shared<User>();
+ updateUserFromQueryImpl(*new_user, query, auth_data, name, default_roles_from_query, settings_from_query, RolesOrUsersSet::AllTag{}, implicit_no_password_allowed, no_password_allowed, plaintext_password_allowed);
+ new_users.emplace_back(std::move(new_user));
+ }
+
+ if (!query.storage_name.empty())
+ {
+ for (const auto & name : names)
+ {
+ if (auto another_storage_ptr = access_control.findExcludingStorage(AccessEntityType::USER, name, storage_ptr))
+ throw Exception(ErrorCodes::ACCESS_ENTITY_ALREADY_EXISTS, "User {} already exists in storage {}", name, another_storage_ptr->getStorageName());
+ }
+ }
+
+ std::vector<UUID> ids;
+ if (query.if_not_exists)
+ ids = storage->tryInsert(new_users);
+ else if (query.or_replace)
+ ids = storage->insertOrReplace(new_users);
+ else
+ ids = storage->insert(new_users);
+
+ if (query.grantees)
+ {
+ RolesOrUsersSet grantees_from_query = RolesOrUsersSet{*query.grantees, access_control};
+ access_control.update(ids, [&](const AccessEntityPtr & entity) -> AccessEntityPtr
+ {
+ auto updated_user = typeid_cast<std::shared_ptr<User>>(entity->clone());
+ updated_user->grantees = grantees_from_query;
+ return updated_user;
+ });
+ }
+ }
+
+ return {};
+}
+
+
+void InterpreterCreateUserQuery::updateUserFromQuery(User & user, const ASTCreateUserQuery & query, bool allow_no_password, bool allow_plaintext_password)
+{
+ std::optional<AuthenticationData> auth_data;
+ if (query.auth_data)
+ auth_data = AuthenticationData::fromAST(*query.auth_data, {}, !query.attach);
+
+ updateUserFromQueryImpl(user, query, auth_data, {}, {}, {}, {}, allow_no_password, allow_plaintext_password, true);
+}
+
+}