aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/clickhouse/src/Storages/System/StorageSystemRoleGrants.cpp
blob: 8fcd0fd7cf5ae24079a7a20165b403bdcc1ab31f (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
#include <Storages/System/StorageSystemRoleGrants.h>
#include <DataTypes/DataTypeEnum.h>
#include <DataTypes/DataTypeNullable.h>
#include <DataTypes/DataTypeString.h>
#include <DataTypes/DataTypesNumber.h>
#include <DataTypes/DataTypeUUID.h>
#include <Columns/ColumnString.h>
#include <Columns/ColumnNullable.h>
#include <Columns/ColumnsNumber.h>
#include <Access/AccessControl.h>
#include <Access/Role.h>
#include <Access/User.h>
#include <Interpreters/Context.h>
#include <boost/range/algorithm_ext/push_back.hpp>


namespace DB
{

NamesAndTypesList StorageSystemRoleGrants::getNamesAndTypes()
{
    NamesAndTypesList names_and_types{
        {"user_name", std::make_shared<DataTypeNullable>(std::make_shared<DataTypeString>())},
        {"role_name", std::make_shared<DataTypeNullable>(std::make_shared<DataTypeString>())},
        {"granted_role_name", std::make_shared<DataTypeString>()},
        {"granted_role_id", std::make_shared<DataTypeUUID>()},
        {"granted_role_is_default", std::make_shared<DataTypeUInt8>()},
        {"with_admin_option", std::make_shared<DataTypeUInt8>()},
    };
    return names_and_types;
}


void StorageSystemRoleGrants::fillData(MutableColumns & res_columns, ContextPtr context, const SelectQueryInfo &) const
{
    /// If "select_from_system_db_requires_grant" is enabled the access rights were already checked in InterpreterSelectQuery.
    const auto & access_control = context->getAccessControl();
    if (!access_control.doesSelectFromSystemDatabaseRequireGrant())
        context->checkAccess(AccessType::SHOW_USERS | AccessType::SHOW_ROLES);

    std::vector<UUID> ids = access_control.findAll<User>();
    boost::range::push_back(ids, access_control.findAll<Role>());

    size_t column_index = 0;
    auto & column_user_name = assert_cast<ColumnString &>(assert_cast<ColumnNullable &>(*res_columns[column_index]).getNestedColumn());
    auto & column_user_name_null_map = assert_cast<ColumnNullable &>(*res_columns[column_index++]).getNullMapData();
    auto & column_role_name = assert_cast<ColumnString &>(assert_cast<ColumnNullable &>(*res_columns[column_index]).getNestedColumn());
    auto & column_role_name_null_map = assert_cast<ColumnNullable &>(*res_columns[column_index++]).getNullMapData();
    auto & column_granted_role_name = assert_cast<ColumnString &>(*res_columns[column_index++]);
    auto & column_granted_role_id = assert_cast<ColumnUUID &>(*res_columns[column_index++]).getData();
    auto & column_is_default = assert_cast<ColumnUInt8 &>(*res_columns[column_index++]).getData();
    auto & column_admin_option = assert_cast<ColumnUInt8 &>(*res_columns[column_index++]).getData();

    auto add_row = [&](const String & grantee_name,
                       AccessEntityType grantee_type,
                       const String & granted_role_name,
                       const UUID & granted_role_id,
                       bool is_default,
                       bool with_admin_option)
    {
        if (grantee_type == AccessEntityType::USER)
        {
            column_user_name.insertData(grantee_name.data(), grantee_name.length());
            column_user_name_null_map.push_back(false);
            column_role_name.insertDefault();
            column_role_name_null_map.push_back(true);
        }
        else if (grantee_type == AccessEntityType::ROLE)
        {
            column_user_name.insertDefault();
            column_user_name_null_map.push_back(true);
            column_role_name.insertData(grantee_name.data(), grantee_name.length());
            column_role_name_null_map.push_back(false);
        }
        else
            assert(false);

        column_granted_role_name.insertData(granted_role_name.data(), granted_role_name.length());
        column_granted_role_id.push_back(granted_role_id.toUnderType());
        column_is_default.push_back(is_default);
        column_admin_option.push_back(with_admin_option);
    };

    auto add_rows = [&](const String & grantee_name,
                        AccessEntityType grantee_type,
                        const GrantedRoles & granted_roles,
                        const RolesOrUsersSet * default_roles)
    {
        for (const auto & element : granted_roles.getElements())
        {
            for (const auto & role_id : element.ids)
            {
                auto role_name = access_control.tryReadName(role_id);
                if (!role_name)
                    continue;

                bool is_default = !default_roles || default_roles->match(role_id);
                add_row(grantee_name, grantee_type, *role_name, role_id, is_default, element.admin_option);
            }
        }
    };

    for (const auto & id : ids)
    {
        auto entity = access_control.tryRead(id);
        if (!entity)
            continue;

        const GrantedRoles * granted_roles = nullptr;
        const RolesOrUsersSet * default_roles = nullptr;
        if (auto role = typeid_cast<RolePtr>(entity))
            granted_roles = &role->granted_roles;
        else if (auto user = typeid_cast<UserPtr>(entity))
        {
            granted_roles = &user->granted_roles;
            default_roles = &user->default_roles;
        }
        else
            continue;

        add_rows(entity->getName(), entity->getType(), *granted_roles, default_roles);
    }
}

}