#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace DB { namespace ErrorCodes { extern const int INCORRECT_ACCESS_ENTITY_DEFINITION; } String serializeAccessEntity(const IAccessEntity & entity) { /// Build list of ATTACH queries. ASTs queries; queries.push_back(InterpreterShowCreateAccessEntityQuery::getAttachQuery(entity)); if ((entity.getType() == AccessEntityType::USER) || (entity.getType() == AccessEntityType::ROLE)) boost::range::push_back(queries, InterpreterShowGrantsQuery::getAttachGrantQueries(entity)); /// Serialize the list of ATTACH queries to a string. WriteBufferFromOwnString buf; for (const ASTPtr & query : queries) { formatAST(*query, buf, false, true); buf.write(";\n", 2); } return buf.str(); } AccessEntityPtr deserializeAccessEntityImpl(const String & definition) { ASTs queries; ParserAttachAccessEntity parser; const char * begin = definition.data(); /// begin of current query const char * pos = begin; /// parser moves pos from begin to the end of current query const char * end = begin + definition.size(); while (pos < end) { queries.emplace_back(parseQueryAndMovePosition(parser, pos, end, "", true, 0, DBMS_DEFAULT_MAX_PARSER_DEPTH)); while (isWhitespaceASCII(*pos) || *pos == ';') ++pos; } /// Interpret the AST to build an access entity. std::shared_ptr user; std::shared_ptr role; std::shared_ptr policy; std::shared_ptr quota; std::shared_ptr profile; AccessEntityPtr res; for (const auto & query : queries) { if (auto * create_user_query = query->as()) { if (res) throw Exception("Two access entities attached in the same file", ErrorCodes::INCORRECT_ACCESS_ENTITY_DEFINITION); res = user = std::make_unique(); InterpreterCreateUserQuery::updateUserFromQuery(*user, *create_user_query, /* allow_no_password = */ true, /* allow_plaintext_password = */ true); } else if (auto * create_role_query = query->as()) { if (res) throw Exception("Two access entities attached in the same file", ErrorCodes::INCORRECT_ACCESS_ENTITY_DEFINITION); res = role = std::make_unique(); InterpreterCreateRoleQuery::updateRoleFromQuery(*role, *create_role_query); } else if (auto * create_policy_query = query->as()) { if (res) throw Exception("Two access entities attached in the same file", ErrorCodes::INCORRECT_ACCESS_ENTITY_DEFINITION); res = policy = std::make_unique(); InterpreterCreateRowPolicyQuery::updateRowPolicyFromQuery(*policy, *create_policy_query); } else if (auto * create_quota_query = query->as()) { if (res) throw Exception("Two access entities attached in the same file", ErrorCodes::INCORRECT_ACCESS_ENTITY_DEFINITION); res = quota = std::make_unique(); InterpreterCreateQuotaQuery::updateQuotaFromQuery(*quota, *create_quota_query); } else if (auto * create_profile_query = query->as()) { if (res) throw Exception("Two access entities attached in the same file", ErrorCodes::INCORRECT_ACCESS_ENTITY_DEFINITION); res = profile = std::make_unique(); InterpreterCreateSettingsProfileQuery::updateSettingsProfileFromQuery(*profile, *create_profile_query); } else if (auto * grant_query = query->as()) { if (!user && !role) throw Exception("A user or role should be attached before grant", ErrorCodes::INCORRECT_ACCESS_ENTITY_DEFINITION); if (user) InterpreterGrantQuery::updateUserFromQuery(*user, *grant_query); else InterpreterGrantQuery::updateRoleFromQuery(*role, *grant_query); } else throw Exception("No interpreter found for query " + query->getID(), ErrorCodes::INCORRECT_ACCESS_ENTITY_DEFINITION); } if (!res) throw Exception("No access entities attached", ErrorCodes::INCORRECT_ACCESS_ENTITY_DEFINITION); return res; } AccessEntityPtr deserializeAccessEntity(const String & definition, const String & file_path) { if (file_path.empty()) return deserializeAccessEntityImpl(definition); try { return deserializeAccessEntityImpl(definition); } catch (Exception & e) { e.addMessage("Could not parse " + file_path); e.rethrow(); __builtin_unreachable(); } } }