| 663 | |
| 664 | template <bool throw_if_denied, bool grant_option, bool wildcard, typename... Args> |
| 665 | bool ContextAccess::checkAccessImplHelper(const ContextPtr & context, AccessFlags flags, const Args &... args) const |
| 666 | { |
| 667 | if (user_was_dropped) |
| 668 | { |
| 669 | /// If the current user has been dropped we always throw an exception (even if `throw_if_denied` is false) |
| 670 | /// because dropping of the current user is considered as a situation which is exceptional enough to stop |
| 671 | /// query execution. |
| 672 | throw Exception(ErrorCodes::UNKNOWN_USER, "{}: User has been dropped", getUserName()); |
| 673 | } |
| 674 | |
| 675 | if (params.full_access) |
| 676 | return true; |
| 677 | |
| 678 | auto access_granted = [&] |
| 679 | { |
| 680 | /// Record every granted access, regardless of whether the caller is the throwing entry point |
| 681 | /// (`checkAccess` / `checkGrantOption`) or the non-throwing one (`isGranted`, used internally by |
| 682 | /// `checkAccessWithFilter`). Without this, an `isGranted`-driven success leaves no trace in |
| 683 | /// system.query_log.used_privileges even though the privilege was effectively required by the query. |
| 684 | context->addQueryPrivilegesInfo(AccessRightsElement{flags, args...}.toStringWithoutOptions(), true); |
| 685 | return true; |
| 686 | }; |
| 687 | |
| 688 | auto access_denied = [&]<typename... FmtArgs>(int error_code [[maybe_unused]], |
| 689 | FormatStringHelper<String, FmtArgs...> fmt_string [[maybe_unused]], |
| 690 | FmtArgs && ...fmt_args [[maybe_unused]]) |
| 691 | { |
| 692 | if constexpr (throw_if_denied) |
| 693 | { |
| 694 | context->addQueryPrivilegesInfo(AccessRightsElement{flags, args...}.toStringWithoutOptions(), false); |
| 695 | throw Exception(error_code, std::move(fmt_string), getUserName(), std::forward<FmtArgs>(fmt_args)...); |
| 696 | } |
| 697 | return false; |
| 698 | }; |
| 699 | |
| 700 | if (flags & AccessType::CLUSTER && !access_control->doesOnClusterQueriesRequireClusterGrant()) |
| 701 | flags &= ~AccessType::CLUSTER; |
| 702 | |
| 703 | if (!flags) |
| 704 | return true; |
| 705 | |
| 706 | const auto parameter_type = flags.getParameterType(); |
| 707 | if (parameter_type == AccessFlags::NONE) |
| 708 | { |
| 709 | /// Access to temporary tables is controlled in an unusual way, not like normal tables. |
| 710 | /// Creating of temporary tables is controlled by AccessType::CREATE_TEMPORARY_TABLES grant, |
| 711 | /// and other grants are considered as always given. |
| 712 | /// The DatabaseCatalog class won't resolve StorageID for temporary tables |
| 713 | /// which shouldn't be accessed. |
| 714 | if (getDatabase(args...) == DatabaseCatalog::TEMPORARY_DATABASE) |
| 715 | return access_granted(); |
| 716 | } |
| 717 | |
| 718 | auto acs = getAccessRightsWithImplicit(); |
| 719 | bool granted = false; |
| 720 | if constexpr (wildcard) |
| 721 | { |
| 722 | if constexpr (grant_option) |
nothing calls this directly
no test coverage detected