Coverage Report

Created: 2026-07-03 06:22

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/tdengine/source/common/src/tpriv.c
Line
Count
Source
1
/*
2
 * Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
3
 *
4
 * This program is free software: you can use, redistribute, and/or modify
5
 * it under the terms of the GNU Affero General Public License, version 3
6
 * or later ("AGPL"), as published by the Free Software Foundation.
7
 *
8
 * This program is distributed in the hope that it will be useful, but WITHOUT
9
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10
 * FITNESS FOR A PARTICULAR PURPOSE.
11
 *
12
 * You should have received a copy of the GNU Affero General Public License
13
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
14
 */
15
16
#define _DEFAULT_SOURCE
17
#include "systable.h"
18
#include "tpriv.h"
19
#include "tmsg.h"
20
#include "tutil.h"
21
22
static TdThreadOnce privInit = PTHREAD_ONCE_INIT;
23
24
typedef struct {
25
  const char* name;
26
  int32_t     level;
27
} SPrivObjInfo;
28
29
static const SPrivObjInfo __privObjInfo[] = {
30
    {"CLUSTER", 0}, {"NODE", 0},  {"DATABASE", 0}, {"TABLE", 1}, {"FUNCTION", 0}, {"INDEX", 1},
31
    {"VIEW", 1},    {"USER", 0},  {"ROLE", 0},     {"RSMA", 1},  {"TSMA", 1},     {"TOPIC", 1},
32
    {"STREAM", 1},  {"MOUNT", 0}, {"AUDIT", 0},    {"TOKEN", 0}, {"NONE", 1},     {"XTASK", 0},
33
};
34
35
/**
36
 * N.B. increase the macro PRIV_INFO_TABLE_VERSION for any update of privInfoTable
37
 */
38
39
#define SYS_ADMIN_BASIC_ROLES (T_ROLE_SYSDBA | T_ROLE_SYSSEC | T_ROLE_SYSAUDIT)
40
#define SYS_ADMIN_CORE_ROLES  (T_ROLE_SYSDBA | T_ROLE_SYSSEC)
41
#define SYS_ADMIN_INFO1_ROLES (SYS_ADMIN_BASIC_ROLES | T_ROLE_SYSINFO_1)
42
#define SYS_ADMIN_INFO_ROLES  (SYS_ADMIN_BASIC_ROLES | T_ROLE_SYSINFO_0 | T_ROLE_SYSINFO_1)
43
#define SYS_ADMIN_EXT_ROLES   (T_ROLE_SYSINFO_0 | T_ROLE_SYSINFO_1 | T_ROLE_SYSAUDIT_LOG)
44
#define SYS_ADMIN_ALL_ROLES   (SYS_ADMIN_BASIC_ROLES | T_ROLE_SYSAUDIT_LOG | T_ROLE_SYSINFO_0 | T_ROLE_SYSINFO_1)
45
46
static SPrivInfo privInfoTable[] = {
47
    // ==================== common privileges ====================
48
    {PRIV_CM_ALL, PRIV_CATEGORY_COMMON, 0, 0, 0, 0, "", "ALL"},
49
    {PRIV_CM_ALTER, PRIV_CATEGORY_COMMON, 0, 0, 0, 0, "", "ALTER"},
50
    {PRIV_CM_DROP, PRIV_CATEGORY_COMMON, 0, 0, 0, 0, "", "DROP"},
51
    {PRIV_CM_SHOW, PRIV_CATEGORY_COMMON, 0, 0, 0, 0, "", "SHOW"},
52
    {PRIV_CM_SHOW_CREATE, PRIV_CATEGORY_COMMON, 0, 0, 0, 0, "", "SHOW CREATE"},
53
    {PRIV_CM_START, PRIV_CATEGORY_COMMON, 0, 0, 0, 0, "", "START"},
54
    {PRIV_CM_STOP, PRIV_CATEGORY_COMMON, 0, 0, 0, 0, "", "STOP"},
55
    {PRIV_CM_RECALC, PRIV_CATEGORY_COMMON, 0, 0, 0, 0, "", "RECALCULATE"},
56
    {PRIV_CM_KILL, PRIV_CATEGORY_COMMON, 0, 0, 0, 0, "", "KILL"},
57
    {PRIV_CM_SUBSCRIBE, PRIV_CATEGORY_COMMON, 0, 0, 0, 0, "", "SUBSCRIBE"},
58
59
    // ==================== system privileges ====================
60
    // Database Management
61
    {PRIV_DB_CREATE, PRIV_CATEGORY_SYSTEM, 0, 0, T_ROLE_SYSDBA, 0, "", "CREATE DATABASE"},
62
    {PRIV_VG_BALANCE, PRIV_CATEGORY_SYSTEM, 0, 0, T_ROLE_SYSDBA, 0, "", "BALANCE VGROUP"},
63
    {PRIV_VG_BALANCE_LEADER, PRIV_CATEGORY_SYSTEM, 0, 0, T_ROLE_SYSDBA, 0, "", "BALANCE VGROUP LEADER"},
64
    {PRIV_VG_MERGE, PRIV_CATEGORY_SYSTEM, 0, 0, T_ROLE_SYSDBA, 0, "", "MERGE VGROUP"},
65
    {PRIV_VG_REDISTRIBUTE, PRIV_CATEGORY_SYSTEM, 0, 0, T_ROLE_SYSDBA, 0, "", "REDISTRIBUTE VGROUP"},
66
    {PRIV_VG_SPLIT, PRIV_CATEGORY_SYSTEM, 0, 0, T_ROLE_SYSDBA, 0, "", "SPLIT VGROUP"},
67
68
    // Function Privileges
69
    {PRIV_FUNC_CREATE, PRIV_CATEGORY_SYSTEM, 0, 0, T_ROLE_SYSDBA, 0, "", "CREATE FUNCTION"},
70
    {PRIV_FUNC_DROP, PRIV_CATEGORY_SYSTEM, 0, 0, T_ROLE_SYSDBA, 0, "", "DROP FUNCTION"},
71
    {PRIV_FUNC_SHOW, PRIV_CATEGORY_SYSTEM, 0, 0, SYS_ADMIN_INFO_ROLES, 0, "", "SHOW FUNCTIONS"},
72
73
    // Mount Privileges
74
    {PRIV_MOUNT_CREATE, PRIV_CATEGORY_SYSTEM, 0, 0, T_ROLE_SYSDBA, 0, "", "CREATE MOUNT"},
75
    {PRIV_MOUNT_DROP, PRIV_CATEGORY_SYSTEM, 0, 0, T_ROLE_SYSDBA, 0, "", "DROP MOUNT"},
76
    {PRIV_MOUNT_SHOW, PRIV_CATEGORY_SYSTEM, 0, 0, SYS_ADMIN_INFO1_ROLES, 0, "", "SHOW MOUNTS"},
77
78
    // User Management
79
    {PRIV_USER_CREATE, PRIV_CATEGORY_SYSTEM, 0, 0, T_ROLE_SYSDBA, 0, "", "CREATE USER"},
80
    {PRIV_USER_DROP, PRIV_CATEGORY_SYSTEM, 0, 0, T_ROLE_SYSDBA, 0, "", "DROP USER"},
81
    {PRIV_USER_SET_SECURITY, PRIV_CATEGORY_SYSTEM, 0, 0, T_ROLE_SYSDBA | T_ROLE_SYSSEC, 0, "",
82
     "SET USER SECURITY INFORMATION"},
83
    {PRIV_USER_SET_AUDIT, PRIV_CATEGORY_SYSTEM, 0, 0, T_ROLE_SYSDBA | T_ROLE_SYSAUDIT, 0, "",
84
     "SET USER AUDIT INFORMATION"},
85
    {PRIV_USER_SET_BASIC, PRIV_CATEGORY_SYSTEM, 0, 0, T_ROLE_SYSDBA, 0, "", "SET USER BASIC INFORMATION"},
86
    {PRIV_USER_UNLOCK, PRIV_CATEGORY_SYSTEM, 0, 0, SYS_ADMIN_CORE_ROLES, 0, "", "UNLOCK USER"},
87
    {PRIV_USER_LOCK, PRIV_CATEGORY_SYSTEM, 0, 0, SYS_ADMIN_CORE_ROLES, 0, "", "LOCK USER"},
88
    {PRIV_USER_SHOW, PRIV_CATEGORY_SYSTEM, 0, 0, SYS_ADMIN_INFO1_ROLES, 0, "", "SHOW USERS"},
89
    {PRIV_USER_ALTER, PRIV_CATEGORY_SYSTEM, 0, 0, SYS_ADMIN_INFO_ROLES, 0, "", "ALTER USER"},
90
    {PRIV_USER_SHOW_SECURITY, PRIV_CATEGORY_SYSTEM, 0, 0, SYS_ADMIN_BASIC_ROLES, 0, "",
91
     "SHOW USERS SECURITY INFORMATION"},
92
93
    // Role Management
94
    {PRIV_ROLE_CREATE, PRIV_CATEGORY_SYSTEM, 0, 0, T_ROLE_SYSDBA, 0, "", "CREATE ROLE"},
95
    {PRIV_ROLE_DROP, PRIV_CATEGORY_SYSTEM, 0, 0, T_ROLE_SYSDBA, 0, "", "DROP ROLE"},
96
    {PRIV_ROLE_UNLOCK, PRIV_CATEGORY_SYSTEM, 0, 0, SYS_ADMIN_CORE_ROLES, 0, "", "UNLOCK ROLE"},
97
    {PRIV_ROLE_LOCK, PRIV_CATEGORY_SYSTEM, 0, 0, SYS_ADMIN_CORE_ROLES, 0, "", "LOCK ROLE"},
98
    {PRIV_ROLE_SHOW, PRIV_CATEGORY_SYSTEM, 0, 0, SYS_ADMIN_INFO1_ROLES, 0, "", "SHOW ROLES"},
99
100
    // Token Privileges
101
    {PRIV_TOKEN_CREATE, PRIV_CATEGORY_SYSTEM, 0, 0, T_ROLE_SYSSEC, 0, "", "CREATE TOKEN"},
102
    {PRIV_TOKEN_DROP, PRIV_CATEGORY_SYSTEM, 0, 0, T_ROLE_SYSSEC, 0, "", "DROP TOKEN"},
103
    {PRIV_TOKEN_ALTER, PRIV_CATEGORY_SYSTEM, 0, 0, T_ROLE_SYSSEC, 0, "", "ALTER TOKEN"},
104
    {PRIV_TOKEN_SHOW, PRIV_CATEGORY_SYSTEM, 0, 0, SYS_ADMIN_BASIC_ROLES, 0, "", "SHOW TOKENS"},
105
106
    // Node Management
107
    {PRIV_NODE_CREATE, PRIV_CATEGORY_SYSTEM, 0, 0, T_ROLE_SYSDBA, 0, "", "CREATE NODE"},
108
    {PRIV_NODE_ALTER, PRIV_CATEGORY_SYSTEM, 0, 0, T_ROLE_SYSDBA, 0, "", "ALTER NODE"},
109
    {PRIV_NODE_DROP, PRIV_CATEGORY_SYSTEM, 0, 0, T_ROLE_SYSDBA, 0, "", "DROP NODE"},
110
    {PRIV_NODES_SHOW, PRIV_CATEGORY_SYSTEM, 0, 0, SYS_ADMIN_INFO1_ROLES, 0, "", "SHOW NODES"},
111
112
    // System Variables
113
    {PRIV_VAR_SECURITY_ALTER, PRIV_CATEGORY_SYSTEM, 0, 0, T_ROLE_SYSSEC, 0, "", "ALTER SECURITY VARIABLE"},
114
    {PRIV_VAR_AUDIT_ALTER, PRIV_CATEGORY_SYSTEM, 0, 0, T_ROLE_SYSAUDIT, 0, "", "ALTER AUDIT VARIABLE"},
115
    {PRIV_VAR_SYSTEM_ALTER, PRIV_CATEGORY_SYSTEM, 0, 0, T_ROLE_SYSDBA, 0, "", "ALTER SYSTEM VARIABLE"},
116
    {PRIV_VAR_DEBUG_ALTER, PRIV_CATEGORY_SYSTEM, 0, 0, T_ROLE_SYSDBA, 0, "", "ALTER DEBUG VARIABLE"},
117
    {PRIV_VAR_SECURITY_SHOW, PRIV_CATEGORY_SYSTEM, 0, 0, SYS_ADMIN_INFO1_ROLES, 0, "", "SHOW SECURITY VARIABLE"},
118
    {PRIV_VAR_AUDIT_SHOW, PRIV_CATEGORY_SYSTEM, 0, 0, SYS_ADMIN_INFO1_ROLES, 0, "", "SHOW AUDIT VARIABLE"},
119
    {PRIV_VAR_SYSTEM_SHOW, PRIV_CATEGORY_SYSTEM, 0, 0, SYS_ADMIN_INFO_ROLES, 0, "", "SHOW SYSTEM VARIABLE"},
120
    {PRIV_VAR_DEBUG_SHOW, PRIV_CATEGORY_SYSTEM, 0, 0, SYS_ADMIN_INFO_ROLES, 0, "", "SHOW DEBUG VARIABLE"},
121
122
    // Key/Password Management
123
    {PRIV_KEY_UPDATE, PRIV_CATEGORY_SYSTEM, 0, 0, T_ROLE_SYSDBA, 0, "", "UPDATE KEY"},
124
    {PRIV_TOTP_CREATE, PRIV_CATEGORY_SYSTEM, 0, 0, T_ROLE_SYSSEC, 0, "", "CREATE TOTP_SECRET"},
125
    {PRIV_TOTP_DROP, PRIV_CATEGORY_SYSTEM, 0, 0, T_ROLE_SYSSEC, 0, "", "DROP TOTP_SECRET"},
126
    {PRIV_PASS_ALTER, PRIV_CATEGORY_SYSTEM, 0, 0, T_ROLE_SYSDBA, 0, "", "ALTER PASS"},
127
    {PRIV_PASS_ALTER_SELF, PRIV_CATEGORY_SYSTEM, 0, 0, SYS_ADMIN_INFO_ROLES, 0, "", "ALTER SELF PASS"},
128
129
    // Grant/Revoke Privileges
130
    {PRIV_GRANT_PRIVILEGE, PRIV_CATEGORY_SYSTEM, 0, 0, T_ROLE_SYSSEC, 0, "", "GRANT PRIVILEGE"},
131
    {PRIV_REVOKE_PRIVILEGE, PRIV_CATEGORY_SYSTEM, 0, 0, T_ROLE_SYSSEC, 0, "", "REVOKE PRIVILEGE"},
132
    {PRIV_SHOW_PRIVILEGES, PRIV_CATEGORY_SYSTEM, 0, 0, SYS_ADMIN_INFO1_ROLES, 0, "", "SHOW PRIVILEGES"},
133
    {PRIV_GRANT_SYSDBA, PRIV_CATEGORY_SYSTEM, 0, 0, T_ROLE_SYSDBA, 0, "", "GRANT SYSDBA PRIVILEGE"},
134
    {PRIV_REVOKE_SYSDBA, PRIV_CATEGORY_SYSTEM, 0, 0, T_ROLE_SYSDBA, 0, "", "REVOKE SYSDBA PRIVILEGE"},
135
    {PRIV_GRANT_SYSSEC, PRIV_CATEGORY_SYSTEM, 0, 0, T_ROLE_SYSSEC, 0, "", "GRANT SYSSEC PRIVILEGE"},
136
    {PRIV_REVOKE_SYSSEC, PRIV_CATEGORY_SYSTEM, 0, 0, T_ROLE_SYSSEC, 0, "", "REVOKE SYSSEC PRIVILEGE"},
137
    {PRIV_GRANT_SYSAUDIT, PRIV_CATEGORY_SYSTEM, 0, 0, T_ROLE_SYSAUDIT, 0, "", "GRANT SYSAUDIT PRIVILEGE"},
138
    {PRIV_REVOKE_SYSAUDIT, PRIV_CATEGORY_SYSTEM, 0, 0, T_ROLE_SYSAUDIT, 0, "", "REVOKE SYSAUDIT PRIVILEGE"},
139
140
    // Audit Management
141
    {PRIV_AUDIT_DB_DROP, PRIV_CATEGORY_SYSTEM, 0, 0, T_ROLE_SYSAUDIT, 0, "", "DROP AUDIT DATABASE"},
142
    {PRIV_AUDIT_DB_ALTER, PRIV_CATEGORY_SYSTEM, 0, 0, T_ROLE_SYSAUDIT, 0, "", "ALTER AUDIT DATABASE"},
143
    {PRIV_AUDIT_DB_USE, PRIV_CATEGORY_SYSTEM, 0, 0, T_ROLE_SYSAUDIT | T_ROLE_SYSAUDIT_LOG, 0, "", "USE AUDIT DATABASE"},
144
    {PRIV_AUDIT_TBL_CREATE, PRIV_CATEGORY_SYSTEM, 0, 0, T_ROLE_SYSAUDIT_LOG, 0, "", "CREATE AUDIT TABLE"},
145
    {PRIV_AUDIT_TBL_SELECT, PRIV_CATEGORY_SYSTEM, 0, 0, T_ROLE_SYSAUDIT, 0, "", "SELECT AUDIT TABLE"},
146
    {PRIV_AUDIT_TBL_INSERT, PRIV_CATEGORY_SYSTEM, 0, 0, T_ROLE_SYSAUDIT_LOG, 0, "", "INSERT AUDIT TABLE"},
147
148
    // System Administration
149
    {PRIV_TRANS_SHOW, PRIV_CATEGORY_SYSTEM, 0, 0, SYS_ADMIN_INFO_ROLES, 0, "", "SHOW TRANS"},
150
    {PRIV_TRANS_KILL, PRIV_CATEGORY_SYSTEM, 0, 0, T_ROLE_SYSDBA, 0, "", "KILL TRANS"},
151
    {PRIV_CONN_SHOW, PRIV_CATEGORY_SYSTEM, 0, 0, SYS_ADMIN_INFO_ROLES, 0, "", "SHOW CONNECTIONS"},
152
    {PRIV_CONN_KILL, PRIV_CATEGORY_SYSTEM, 0, 0, T_ROLE_SYSDBA, 0, "", "KILL CONNECTION"},
153
    {PRIV_QUERY_SHOW, PRIV_CATEGORY_SYSTEM, 0, 0, SYS_ADMIN_INFO_ROLES, 0, "", "SHOW QUERIES"},
154
    {PRIV_QUERY_KILL, PRIV_CATEGORY_SYSTEM, 0, 0, T_ROLE_SYSDBA, 0, "", "KILL QUERY"},
155
    {PRIV_INFO_SCHEMA_READ_BASIC, PRIV_CATEGORY_SYSTEM, 0, 0, SYS_ADMIN_INFO_ROLES, 0, "",
156
     "READ INFORMATION SCHEMA BASIC"},
157
    {PRIV_INFO_SCHEMA_READ_SEC, PRIV_CATEGORY_SYSTEM, 0, 0, SYS_ADMIN_INFO1_ROLES, 0, "",
158
     "READ INFORMATION SCHEMA SECURITY"},
159
    {PRIV_INFO_SCHEMA_READ_AUDIT, PRIV_CATEGORY_SYSTEM, 0, 0, SYS_ADMIN_INFO1_ROLES, 0, "",
160
     "READ INFORMATION SCHEMA AUDIT"},
161
    {PRIV_INFO_SCHEMA_READ_PRIVILEGED, PRIV_CATEGORY_SYSTEM, 0, 0, SYS_ADMIN_INFO1_ROLES, 0, "",
162
     "READ INFORMATION SCHEMA PRIVILEGED"},
163
    {PRIV_PERF_SCHEMA_READ_BASIC, PRIV_CATEGORY_SYSTEM, 0, 0, SYS_ADMIN_INFO_ROLES, 0, "",
164
     "READ PERFORMANCE SCHEMA BASIC"},
165
    {PRIV_PERF_SCHEMA_READ_PRIVILEGED, PRIV_CATEGORY_SYSTEM, 0, 0, SYS_ADMIN_INFO1_ROLES, 0, "",
166
     "READ PERFORMANCE SCHEMA PRIVILEGED"},
167
    {PRIV_GRANTS_SHOW, PRIV_CATEGORY_SYSTEM, 0, 0, SYS_ADMIN_INFO1_ROLES, 0, "", "SHOW GRANTS"},
168
    {PRIV_CLUSTER_SHOW, PRIV_CATEGORY_SYSTEM, 0, 0, SYS_ADMIN_INFO1_ROLES, 0, "", "SHOW CLUSTER"},
169
    {PRIV_APPS_SHOW, PRIV_CATEGORY_SYSTEM, 0, 0, SYS_ADMIN_INFO_ROLES, 0, "", "SHOW APPS"},
170
    // Xnode Task Management
171
    {PRIV_XNODE_TASK_CREATE, PRIV_CATEGORY_SYSTEM, 0, 0, T_ROLE_SYSDBA, 0, "", "CREATE XNODE TASK"},
172
  
173
    // Security Policy Management
174
    {PRIV_SECURITY_POLICY_ALTER, PRIV_CATEGORY_SYSTEM, 0, 0, T_ROLE_SYSSEC, 0, "", "ALTER SECURITY POLICY"},
175
    {PRIV_SECURITY_POLICIES_SHOW, PRIV_CATEGORY_SYSTEM, 0, 0, SYS_ADMIN_INFO1_ROLES, 0, "", "SHOW SECURITY POLICIES"},
176
177
    // ==================== object privileges ====================
178
    // Cluster Privileges
179
    {PRIV_CM_ALTER, PRIV_CATEGORY_OBJECT, PRIV_OBJ_CLUSTER, 0, SYS_ADMIN_INFO1_ROLES, 2, "", "ALTER CLUSTER"},
180
181
    // Database Privileges
182
    {PRIV_CM_ALTER, PRIV_CATEGORY_OBJECT, PRIV_OBJ_DB, 0, T_ROLE_SYSDBA, 2, "", "ALTER DATABASE"},
183
    {PRIV_CM_DROP, PRIV_CATEGORY_OBJECT, PRIV_OBJ_DB, 0, T_ROLE_SYSDBA, 2, "", "DROP DATABASE"},
184
    {PRIV_DB_USE, PRIV_CATEGORY_OBJECT, PRIV_OBJ_DB, 0, SYS_ADMIN_BASIC_ROLES, 3, "", "USE DATABASE"},
185
    {PRIV_DB_USE, PRIV_CATEGORY_OBJECT, PRIV_OBJ_DB, 0, SYS_ADMIN_EXT_ROLES, 3, TSDB_INFORMATION_SCHEMA_DB,
186
     "USE DATABASE"},
187
    {PRIV_DB_USE, PRIV_CATEGORY_OBJECT, PRIV_OBJ_DB, 0, SYS_ADMIN_EXT_ROLES, 3, TSDB_PERFORMANCE_SCHEMA_DB,
188
     "USE DATABASE"},
189
    {PRIV_DB_FLUSH, PRIV_CATEGORY_OBJECT, PRIV_OBJ_DB, 0, T_ROLE_SYSDBA, 2, "", "FLUSH DATABASE"},
190
    {PRIV_DB_COMPACT, PRIV_CATEGORY_OBJECT, PRIV_OBJ_DB, 0, T_ROLE_SYSDBA, 2, "", "COMPACT DATABASE"},
191
    {PRIV_DB_TRIM, PRIV_CATEGORY_OBJECT, PRIV_OBJ_DB, 0, T_ROLE_SYSDBA, 2, "", "TRIM DATABASE"},
192
    {PRIV_DB_ROLLUP, PRIV_CATEGORY_OBJECT, PRIV_OBJ_DB, 0, T_ROLE_SYSDBA, 2, "", "ROLLUP DATABASE"},
193
    {PRIV_DB_SCAN, PRIV_CATEGORY_OBJECT, PRIV_OBJ_DB, 0, T_ROLE_SYSDBA, 1, "", "SCAN DATABASE"},
194
    {PRIV_DB_SSMIGRATE, PRIV_CATEGORY_OBJECT, PRIV_OBJ_DB, 0, T_ROLE_SYSDBA, 2, "", "SSMIGRATE DATABASE"},
195
    {PRIV_CM_SHOW, PRIV_CATEGORY_OBJECT, PRIV_OBJ_DB, 0, SYS_ADMIN_INFO_ROLES, 1, "", "SHOW DATABASES"},
196
    {PRIV_CM_SHOW_CREATE, PRIV_CATEGORY_OBJECT, PRIV_OBJ_DB, 0, SYS_ADMIN_INFO_ROLES, 1, "", "SHOW CREATE DATABASE"},
197
    {PRIV_SHOW_VNODES, PRIV_CATEGORY_OBJECT, PRIV_OBJ_DB, 0, SYS_ADMIN_INFO1_ROLES, 1, "", "SHOW VNODES"},
198
    {PRIV_SHOW_VGROUPS, PRIV_CATEGORY_OBJECT, PRIV_OBJ_DB, 0, SYS_ADMIN_INFO1_ROLES, 1, "", "SHOW VGROUPS"},
199
    {PRIV_SHOW_COMPACTS, PRIV_CATEGORY_OBJECT, PRIV_OBJ_DB, 0, SYS_ADMIN_INFO1_ROLES, 1, "", "SHOW COMPACTS"},
200
    {PRIV_SHOW_RETENTIONS, PRIV_CATEGORY_OBJECT, PRIV_OBJ_DB, 0, SYS_ADMIN_INFO1_ROLES, 1, "", "SHOW RETENTIONS"},
201
    {PRIV_SHOW_SCANS, PRIV_CATEGORY_OBJECT, PRIV_OBJ_DB, 0, SYS_ADMIN_INFO1_ROLES, 1, "", "SHOW SCANS"},
202
    {PRIV_SHOW_SSMIGRATES, PRIV_CATEGORY_OBJECT, PRIV_OBJ_DB, 0, SYS_ADMIN_INFO1_ROLES, 1, "", "SHOW SSMIGRATES"},
203
204
    // Table Privileges
205
    {PRIV_TBL_CREATE, PRIV_CATEGORY_OBJECT, PRIV_OBJ_DB, 0, T_ROLE_SYSDBA, 2, "", "CREATE TABLE"},
206
    {PRIV_CM_DROP, PRIV_CATEGORY_OBJECT, PRIV_OBJ_TBL, 1, T_ROLE_SYSDBA, 2, "", "DROP TABLE"},
207
    {PRIV_CM_ALTER, PRIV_CATEGORY_OBJECT, PRIV_OBJ_TBL, 1, T_ROLE_SYSDBA, 2, "", "ALTER TABLE"},
208
    {PRIV_CM_SHOW, PRIV_CATEGORY_OBJECT, PRIV_OBJ_TBL, 1, SYS_ADMIN_INFO_ROLES, 1, "", "SHOW TABLES"},
209
    {PRIV_CM_SHOW_CREATE, PRIV_CATEGORY_OBJECT, PRIV_OBJ_TBL, 1, SYS_ADMIN_INFO_ROLES, 1, "", "SHOW CREATE TABLE"},
210
    {PRIV_TBL_SELECT, PRIV_CATEGORY_OBJECT, PRIV_OBJ_TBL, 1, 0, 1, "", "SELECT"},
211
    {PRIV_TBL_INSERT, PRIV_CATEGORY_OBJECT, PRIV_OBJ_TBL, 1, 0, 2, "", "INSERT"},
212
    {PRIV_TBL_UPDATE, PRIV_CATEGORY_OBJECT, PRIV_OBJ_TBL, 1, 0, 2, "", "UPDATE"},
213
    {PRIV_TBL_DELETE, PRIV_CATEGORY_OBJECT, PRIV_OBJ_TBL, 1, 0, 2, "", "DELETE"},
214
215
    // Index Privileges
216
    {PRIV_IDX_CREATE, PRIV_CATEGORY_OBJECT, PRIV_OBJ_TBL, 1, T_ROLE_SYSDBA, 2, "", "CREATE INDEX"},
217
    {PRIV_CM_DROP, PRIV_CATEGORY_OBJECT, PRIV_OBJ_IDX, 1, T_ROLE_SYSDBA, 2, "", "DROP INDEX"},
218
    {PRIV_CM_SHOW, PRIV_CATEGORY_OBJECT, PRIV_OBJ_IDX, 1, SYS_ADMIN_INFO_ROLES, 1, "", "SHOW INDEXES"},
219
    {PRIV_CM_SHOW_CREATE, PRIV_CATEGORY_OBJECT, PRIV_OBJ_IDX, 1, SYS_ADMIN_INFO_ROLES, 1, "", "SHOW CREATE INDEX"},
220
221
    // RSMA Privileges
222
    {PRIV_RSMA_CREATE, PRIV_CATEGORY_OBJECT, PRIV_OBJ_TBL, 1, T_ROLE_SYSDBA, 2, "", "CREATE RSMA"},
223
    {PRIV_CM_DROP, PRIV_CATEGORY_OBJECT, PRIV_OBJ_RSMA, 1, T_ROLE_SYSDBA, 2, "", "DROP RSMA"},
224
    {PRIV_CM_ALTER, PRIV_CATEGORY_OBJECT, PRIV_OBJ_RSMA, 1, T_ROLE_SYSDBA, 2, "", "ALTER RSMA"},
225
    {PRIV_CM_SHOW, PRIV_CATEGORY_OBJECT, PRIV_OBJ_RSMA, 1, SYS_ADMIN_INFO_ROLES, 1, "", "SHOW RSMAS"},
226
    {PRIV_CM_SHOW_CREATE, PRIV_CATEGORY_OBJECT, PRIV_OBJ_RSMA, 1, SYS_ADMIN_INFO_ROLES, 1, "", "SHOW CREATE RSMA"},
227
228
    // TSMA Privileges
229
    {PRIV_TSMA_CREATE, PRIV_CATEGORY_OBJECT, PRIV_OBJ_TBL, 1, T_ROLE_SYSDBA, 2, "", "CREATE TSMA"},
230
    {PRIV_CM_DROP, PRIV_CATEGORY_OBJECT, PRIV_OBJ_TSMA, 1, T_ROLE_SYSDBA, 2, "", "DROP TSMA"},
231
    {PRIV_CM_SHOW, PRIV_CATEGORY_OBJECT, PRIV_OBJ_TSMA, 1, SYS_ADMIN_INFO_ROLES, 1, "", "SHOW TSMAS"},
232
    {PRIV_CM_SHOW_CREATE, PRIV_CATEGORY_OBJECT, PRIV_OBJ_TSMA, 1, SYS_ADMIN_INFO_ROLES, 1, "", "SHOW CREATE TSMA"},
233
234
    // View Privileges
235
    {PRIV_VIEW_CREATE, PRIV_CATEGORY_OBJECT, PRIV_OBJ_DB, 0, T_ROLE_SYSDBA, 2, "", "CREATE VIEW"},
236
    {PRIV_CM_DROP, PRIV_CATEGORY_OBJECT, PRIV_OBJ_VIEW, 1, T_ROLE_SYSDBA, 2, "", "DROP VIEW"},
237
    {PRIV_CM_ALTER, PRIV_CATEGORY_OBJECT, PRIV_OBJ_VIEW, 1, T_ROLE_SYSDBA, 2, "", "ALTER VIEW"},
238
    {PRIV_CM_SHOW, PRIV_CATEGORY_OBJECT, PRIV_OBJ_VIEW, 1, SYS_ADMIN_INFO_ROLES, 1, "", "SHOW VIEWS"},
239
    {PRIV_CM_SHOW_CREATE, PRIV_CATEGORY_OBJECT, PRIV_OBJ_VIEW, 1, SYS_ADMIN_INFO_ROLES, 1, "", "SHOW CREATE VIEW"},
240
    {PRIV_VIEW_SELECT, PRIV_CATEGORY_OBJECT, PRIV_OBJ_VIEW, 1, 0, 1, "", "SELECT VIEW"},
241
242
    // Topic Privileges
243
    {PRIV_TOPIC_CREATE, PRIV_CATEGORY_OBJECT, PRIV_OBJ_DB, 0, T_ROLE_SYSDBA, 2, "", "CREATE TOPIC"},
244
    {PRIV_CM_DROP, PRIV_CATEGORY_OBJECT, PRIV_OBJ_TOPIC, 1, T_ROLE_SYSDBA, 2, "", "DROP TOPIC"},
245
    {PRIV_CM_SHOW, PRIV_CATEGORY_OBJECT, PRIV_OBJ_TOPIC, 1, SYS_ADMIN_INFO_ROLES, 1, "", "SHOW TOPICS"},
246
    {PRIV_CM_SHOW_CREATE, PRIV_CATEGORY_OBJECT, PRIV_OBJ_TOPIC, 1, SYS_ADMIN_INFO_ROLES, 1, "", "SHOW CREATE TOPIC"},
247
    {PRIV_CM_SUBSCRIBE, PRIV_CATEGORY_OBJECT, PRIV_OBJ_TOPIC, 1, 0, 1, "", "SUBSCRIBE TOPIC"},
248
    {PRIV_CONSUMER_SHOW, PRIV_CATEGORY_OBJECT, PRIV_OBJ_TOPIC, 1, SYS_ADMIN_INFO_ROLES, 1, "", "SHOW CONSUMERS"},
249
    {PRIV_SUBSCRIPTION_SHOW, PRIV_CATEGORY_OBJECT, PRIV_OBJ_TOPIC, 1, SYS_ADMIN_INFO_ROLES, 1, "",
250
     "SHOW SUBSCRIPTIONS"},
251
    // Stream Privileges
252
    {PRIV_STREAM_CREATE, PRIV_CATEGORY_OBJECT, PRIV_OBJ_DB, 0, T_ROLE_SYSDBA, 2, "", "CREATE STREAM"},
253
    {PRIV_CM_DROP, PRIV_CATEGORY_OBJECT, PRIV_OBJ_STREAM, 1, T_ROLE_SYSDBA, 2, "", "DROP STREAM"},
254
    {PRIV_CM_SHOW, PRIV_CATEGORY_OBJECT, PRIV_OBJ_STREAM, 1, SYS_ADMIN_INFO_ROLES, 1, "", "SHOW STREAMS"},
255
    {PRIV_CM_SHOW_CREATE, PRIV_CATEGORY_OBJECT, PRIV_OBJ_STREAM, 1, SYS_ADMIN_INFO_ROLES, 1, "", "SHOW CREATE STREAM"},
256
    {PRIV_CM_START, PRIV_CATEGORY_OBJECT, PRIV_OBJ_STREAM, 1, T_ROLE_SYSDBA, 2, "", "START STREAM"},
257
    {PRIV_CM_STOP, PRIV_CATEGORY_OBJECT, PRIV_OBJ_STREAM, 1, T_ROLE_SYSDBA, 2, "", "STOP STREAM"},
258
    {PRIV_CM_RECALC, PRIV_CATEGORY_OBJECT, PRIV_OBJ_STREAM, 1, T_ROLE_SYSDBA, 2, "", "RECALCULATE STREAM"},
259
    // Xnode/Xnode Task Privileges
260
    {PRIV_CM_SHOW, PRIV_CATEGORY_OBJECT, PRIV_OBJ_XTASK, 0, T_ROLE_SYSDBA, 1, "", "SHOW XNODE TASKS"},
261
    {PRIV_CM_ALTER, PRIV_CATEGORY_OBJECT, PRIV_OBJ_XTASK, 0, T_ROLE_SYSDBA, 2, "", "ALTER XNODE TASK"},
262
    {PRIV_CM_DROP, PRIV_CATEGORY_OBJECT, PRIV_OBJ_XTASK, 0, T_ROLE_SYSDBA, 2, "", "DROP XNODE TASK"},
263
};
264
265
static SPrivInfo* privLookup[MAX_PRIV_TYPE + 1] = {0};
266
267
0
static void initPrivLookup(void) {
268
0
  for (size_t i = 0; i < sizeof(privInfoTable) / sizeof(privInfoTable[0]); ++i) {
269
0
    EPrivType privType = privInfoTable[i].privType;
270
0
    if (privType <= MAX_PRIV_TYPE &&
271
0
        !privLookup[privType]) {  // duplicated items for other purpose, e.g. createDefaultRoles.
272
0
      privLookup[privType] = &privInfoTable[i];
273
0
    }
274
0
  }
275
0
}
276
277
0
int32_t privExpandAll(SPrivSet* privSet, EPrivObjType pObjType, uint8_t pObjLevel) {
278
0
  if (!privSet) return TSDB_CODE_APP_ERROR;
279
0
  if (!PRIV_HAS(privSet, PRIV_CM_ALL)) return TSDB_CODE_SUCCESS;
280
281
0
  SPrivInfoIter iter = {0};
282
0
  privInfoIterInit(&iter);
283
284
0
  SPrivInfo* pPrivInfo = NULL;
285
0
  while (privInfoIterNext(&iter, &pPrivInfo)) {
286
0
    if (pPrivInfo->objType != pObjType) continue;
287
0
    if (pPrivInfo->objLevel != pObjLevel) {
288
0
      uWarn("privExpandAll: skip privType %d due to level mismatch, expected %d vs %d", pPrivInfo->privType, pObjLevel,
289
0
            pPrivInfo->objLevel);
290
0
      continue;
291
0
    }
292
0
    if (pPrivInfo->category != PRIV_CATEGORY_OBJECT) {
293
0
      uWarn("privExpandAll: skip privType %d due to category mismatch, expected OBJECT vs %d", pPrivInfo->privType,
294
0
            pPrivInfo->category);
295
0
      continue;
296
0
    }
297
0
    privAddType(privSet, pPrivInfo->privType);
298
0
  }
299
300
0
  return TSDB_CODE_SUCCESS;
301
0
}
302
303
0
int32_t privExpandRw(SPrivSet* privSet, EPrivObjType pObjType, uint8_t pObjLevel) {
304
0
  if (!privSet) return TSDB_CODE_APP_ERROR;
305
306
0
  bool hasRead = PRIV_HAS(privSet, PRIV_CM_READ);
307
0
  bool hasWrite = PRIV_HAS(privSet, PRIV_CM_WRITE);
308
309
0
  if (!hasRead && !hasWrite) return TSDB_CODE_SUCCESS;
310
311
  // Remove the legacy types
312
0
  if (hasRead) privRemoveType(privSet, PRIV_CM_READ);
313
0
  if (hasWrite) privRemoveType(privSet, PRIV_CM_WRITE);
314
315
0
  SPrivInfoIter iter = {0};
316
0
  privInfoIterInit(&iter);
317
318
0
  SPrivInfo* pPrivInfo = NULL;
319
0
  while (privInfoIterNext(&iter, &pPrivInfo)) {
320
0
    if (pPrivInfo->objType != pObjType) continue;
321
0
    if (pPrivInfo->objLevel != pObjLevel) continue;
322
0
    if (pPrivInfo->category != PRIV_CATEGORY_OBJECT) continue;
323
324
    // Check rwAttr and add corresponding privileges
325
    // rwAttr: 1 = read, 2 = write, 3 = read/write
326
0
    if (hasRead && (pPrivInfo->rwAttr & PRIV_RW_ATTR_READ)) {
327
0
      privAddType(privSet, pPrivInfo->privType);
328
0
    }
329
0
    if (hasWrite && (pPrivInfo->rwAttr & PRIV_RW_ATTR_WRITE)) {
330
0
      privAddType(privSet, pPrivInfo->privType);
331
0
    }
332
0
  }
333
334
0
  return TSDB_CODE_SUCCESS;
335
0
}
336
337
0
int32_t privUpgradeRwDb(SHashObj* objPrivs, const char* dbFName, const char* tbName, uint8_t rwAttr) {
338
0
  if (!objPrivs) return TSDB_CODE_APP_ERROR;
339
340
0
  int32_t       code = 0, lino = 0;
341
0
  char          key[TSDB_PRIV_MAX_KEY_LEN] = {0};
342
0
  SPrivInfoIter iter = {0};
343
0
  privInfoIterInit(&iter);
344
345
0
  SPrivInfo* pPrivInfo = NULL;
346
0
  while (privInfoIterNext(&iter, &pPrivInfo)) {
347
0
    if ((pPrivInfo->rwAttr & rwAttr) == 0) continue;
348
0
    SPrivInfo privInfo = {.objType = pPrivInfo->objType, .objLevel = pPrivInfo->objLevel};
349
0
    int32_t   keyLen = privObjKeyF(&privInfo, dbFName, tbName, key, sizeof(key));
350
351
0
    SPrivObjPolicies* policies = taosHashGet(objPrivs, key, keyLen + 1);
352
0
    if (policies == NULL) {
353
0
      SPrivObjPolicies policy = {0};
354
0
      privAddType(&policy.policy, pPrivInfo->privType);
355
0
      TAOS_CHECK_EXIT(taosHashPut(objPrivs, key, keyLen + 1, &policy, sizeof(SPrivObjPolicies)));
356
0
    } else {
357
0
      privAddType(&policies->policy, pPrivInfo->privType);
358
0
    }
359
0
  }
360
0
_exit:
361
0
  return code;
362
0
}
363
364
int32_t privCheckConflicts(const SPrivSet* privSet, EPrivCategory* pCategory, EPrivObjType* pObjType,
365
0
                           uint8_t* pObjLevel, EPrivType* conflict0, EPrivType* conflict1) {
366
0
  (void)taosThreadOnce(&privInit, initPrivLookup);
367
368
0
  if (!privSet) return TSDB_CODE_APP_ERROR;
369
370
0
  int32_t          code = 0;
371
0
  const SPrivInfo* privInfo = NULL;
372
373
0
  bool hasSystemPriv = false;
374
0
  bool hasObjectPriv = false;
375
0
  bool hasCommonPriv = false;
376
377
0
  EPrivType lastPriv = PRIV_TYPE_UNKNOWN;
378
379
0
  for (int32_t i = 0; i < PRIV_GROUP_CNT; ++i) {
380
0
    uint64_t chunk = privSet->set[i];
381
0
    if (chunk == 0) continue;
382
383
0
    while (chunk != 0) {
384
0
      int32_t   bitPos = BUILDIN_CTZL(chunk);
385
0
      EPrivType privType = (i << 6) + bitPos;
386
0
      chunk &= ~(1ULL << bitPos);
387
388
0
      privInfo = privLookup[privType];
389
0
      if (privInfo == NULL) continue;
390
391
0
      switch (privInfo->category) {
392
0
        case PRIV_CATEGORY_SYSTEM: {
393
0
          if (hasObjectPriv || hasCommonPriv) {
394
0
            code = 1;
395
0
            goto _exit;
396
0
          }
397
0
          hasSystemPriv = true;
398
0
          lastPriv = privInfo->privType;
399
0
          break;
400
0
        }
401
0
        case PRIV_CATEGORY_OBJECT: {
402
0
          if (hasSystemPriv) {
403
0
            code = 1;
404
0
            goto _exit;
405
0
          }
406
0
          if ((*pObjType != privInfo->objType) && (*pObjType != PRIV_OBJ_NONE)) {
407
0
            code = 2;
408
0
            goto _exit;
409
0
          }
410
0
          if (*pObjLevel != privInfo->objLevel) {
411
0
            code = 3;
412
0
            goto _exit;
413
0
          }
414
0
          hasObjectPriv = true;
415
0
          lastPriv = privInfo->privType;
416
0
          break;
417
0
        }
418
0
        case PRIV_CATEGORY_COMMON: {
419
0
          if (hasSystemPriv) {
420
0
            code = 1;
421
0
            goto _exit;
422
0
          }
423
0
          hasCommonPriv = true;
424
0
          lastPriv = privInfo->privType;
425
0
          break;
426
0
        }
427
0
        default:
428
0
          break;
429
0
      }
430
0
    }
431
0
  }
432
433
0
_exit:
434
0
  if (code != 0) {
435
0
    if (conflict0) *conflict0 = lastPriv;
436
0
    if (conflict1 && privInfo) *conflict1 = privInfo->privType;
437
0
    return code;
438
0
  }
439
440
0
  if (pCategory) {
441
0
    *pCategory = hasSystemPriv   ? PRIV_CATEGORY_SYSTEM
442
0
                 : hasObjectPriv ? PRIV_CATEGORY_OBJECT
443
0
                 : hasCommonPriv ? PRIV_CATEGORY_COMMON
444
0
                                 : PRIV_CATEGORY_UNKNOWN;
445
0
  }
446
447
0
  return 0;
448
0
}
449
450
0
void privIterInit(SPrivIter* pIter, SPrivSet* privSet) {
451
0
  (void)taosThreadOnce(&privInit, initPrivLookup);
452
0
  pIter->privSet = privSet;
453
0
  pIter->groupIndex = 0;
454
0
  pIter->curPriv = privSet->set[0];
455
0
}
456
457
0
bool privIterNext(SPrivIter* iter, SPrivInfo** ppPrivInfo) {
458
0
_loop:
459
0
  while (iter->curPriv == 0) {
460
0
    if (++iter->groupIndex >= PRIV_GROUP_CNT) {
461
0
      return false;
462
0
    }
463
0
    iter->curPriv = iter->privSet->set[iter->groupIndex];
464
0
  }
465
0
  int32_t   bitPos = BUILDIN_CTZL(iter->curPriv);
466
0
  EPrivType privType = (iter->groupIndex << 6) + bitPos;
467
0
  iter->curPriv &= (iter->curPriv -1);
468
0
  if (ppPrivInfo) {
469
0
    *ppPrivInfo = privLookup[privType];
470
0
    if (!(*ppPrivInfo)) goto _loop;
471
0
  }
472
0
  return true;
473
0
}
474
475
0
void privInfoIterInit(SPrivInfoIter* pIter) {
476
0
  (void)taosThreadOnce(&privInit, initPrivLookup);
477
0
  pIter->privInfo = privInfoTable;
478
0
  pIter->privInfoCnt = sizeof(privInfoTable) / sizeof(privInfoTable[0]);
479
0
  pIter->index = 0;
480
0
}
481
482
0
bool privInfoIterNext(SPrivInfoIter* iter, SPrivInfo** ppPrivInfo) {
483
0
  if (iter->index < iter->privInfoCnt) {
484
0
    if (ppPrivInfo) {
485
0
      *ppPrivInfo = &iter->privInfo[iter->index++];
486
0
    } else {
487
0
      iter->index++;
488
0
    }
489
0
    return true;
490
0
  }
491
492
0
  return false;
493
0
}
494
// objType.1.db.tb or objType.1.db
495
0
int32_t privObjKeyF(const SPrivInfo* pPrivInfo, const char* fname, const char* tb, char* buf, int32_t bufLen) {
496
0
  return (pPrivInfo->objLevel == 0)
497
0
             ? snprintf(buf, bufLen, "%d.%s", pPrivInfo->objType, fname ? fname : "")
498
0
             : snprintf(buf, bufLen, "%d.%s.%s", pPrivInfo->objType, fname ? fname : "", tb ? tb : "");
499
0
}
500
501
int32_t privObjKey(const SPrivInfo* pPrivInfo, int32_t acctId, const char* name, const char* tb, char* buf,
502
0
                   int32_t bufLen) {
503
0
  return (pPrivInfo->objLevel == 0)
504
0
             ? snprintf(buf, bufLen, "%d.%d.%s", pPrivInfo->objType, acctId, name ? name : "")
505
0
             : snprintf(buf, bufLen, "%d.%d.%s.%s", pPrivInfo->objType, acctId, name ? name : "", tb ? tb : "");
506
0
}
507
508
// objType.1.db or objType.1.db.tb
509
int32_t privObjKeyParse(const char* str, EPrivObjType* pObjType, char* db, int32_t dbLen, char* tb, int32_t tbLen,
510
0
                        bool fullDb) {
511
0
  char* p = strchr(str, '.');
512
0
  if (!p) {
513
0
    return TSDB_CODE_INVALID_DATA_FMT;
514
0
  }
515
0
  *pObjType = taosStr2Int32(str, NULL, 10);
516
0
  if (errno == ERANGE || *pObjType < PRIV_OBJ_CLUSTER || *pObjType >= PRIV_OBJ_MAX) {
517
0
    return TSDB_CODE_INVALID_DATA_FMT;
518
0
  }
519
0
  char* pNext = strchr(p + 1, '.');
520
0
  if (!pNext) {
521
0
    return TSDB_CODE_INVALID_DATA_FMT;
522
0
  }
523
0
  char* qNext = strchr(pNext + 1, '.');
524
0
  if (qNext) {
525
0
    size_t dbLength = qNext - (fullDb ? (p + 1) : (pNext + 1));
526
0
    if (dbLength >= (size_t)dbLen) {
527
0
      return TSDB_CODE_INVALID_DATA_FMT;
528
0
    }
529
0
    tstrncpy(db, fullDb ? (p + 1) : (pNext + 1), dbLength + 1);
530
0
    tstrncpy(tb, qNext + 1, tbLen);
531
0
  } else {
532
0
    tstrncpy(db, fullDb ? (p + 1) : (pNext + 1), dbLen);
533
0
    tb[0] = '\0';
534
0
  }
535
0
  return TSDB_CODE_SUCCESS;
536
0
}
537
538
0
const char* privObjGetName(EPrivObjType objType) {
539
0
  if (objType < PRIV_OBJ_CLUSTER || objType >= PRIV_OBJ_MAX) {
540
0
    return "UNKNOWN";
541
0
  }
542
0
  return __privObjInfo[objType].name;
543
0
}
544
545
0
int32_t privObjGetLevel(EPrivObjType objType) {
546
0
  if (objType < PRIV_OBJ_CLUSTER || objType >= PRIV_OBJ_MAX) {
547
0
    return -1;
548
0
  }
549
0
  return __privObjInfo[objType].level;
550
0
}
551
552
0
int32_t getSysRoleType(const char* roleName) {
553
0
  if (strcmp(roleName, TSDB_ROLE_SYSDBA) == 0) {
554
0
    return T_ROLE_SYSDBA;
555
0
  } else if (strcmp(roleName, TSDB_ROLE_SYSSEC) == 0) {
556
0
    return T_ROLE_SYSSEC;
557
0
  } else if (strcmp(roleName, TSDB_ROLE_SYSAUDIT) == 0) {
558
0
    return T_ROLE_SYSAUDIT;
559
0
  } else if (strcmp(roleName, TSDB_ROLE_SYSAUDIT_LOG) == 0) {
560
0
    return T_ROLE_SYSAUDIT_LOG;
561
0
  } else if (strcmp(roleName, TSDB_ROLE_SYSINFO_0) == 0) {
562
0
    return T_ROLE_SYSINFO_0;
563
0
  } else if (strcmp(roleName, TSDB_ROLE_SYSINFO_1) == 0) {
564
0
    return T_ROLE_SYSINFO_1;
565
0
  }
566
0
  return 0;
567
0
}
568
569
0
bool isPrivInheritName(const char* name) {
570
0
  if (name && (name[0] == 'S' || name[0] == 's')) {
571
0
    if (taosStrncasecmp(name, TSDB_ROLE_SYSDBA, 7) == 0 || taosStrncasecmp(name, TSDB_ROLE_SYSSEC, 7) == 0 ||
572
0
        taosStrncasecmp(name, TSDB_ROLE_SYSAUDIT, 9) == 0 || taosStrncasecmp(name, TSDB_ROLE_SYSAUDIT_LOG, 13) == 0 ||
573
0
        taosStrncasecmp(name, TSDB_ROLE_SYSINFO_0, 10) == 0 || taosStrncasecmp(name, TSDB_ROLE_SYSINFO_1, 10) == 0) {
574
0
      return true;
575
0
    }
576
0
  }
577
0
  return false;
578
0
}
579
580
0
int32_t privTblPolicyCopy(SPrivTblPolicy* dest, SPrivTblPolicy* src) {
581
0
  dest->updateUs = src->updateUs;
582
0
  dest->condLen = src->condLen;
583
0
  if (src->cond) {
584
0
    if (!(dest->cond = taosStrdup(src->cond))) {
585
0
      return terrno;
586
0
    }
587
0
  } else {
588
0
    dest->cond = NULL;
589
0
  }
590
591
0
  if (taosArrayGetSize(src->cols) > 0) {
592
0
    dest->cols = taosArrayDup(src->cols, NULL);
593
0
    if (!dest->cols) return terrno;
594
0
  } else {
595
0
    dest->cols = NULL;
596
0
  }
597
0
  return 0;
598
0
}
599
600
0
int32_t privTblPoliciesAdd(SPrivTblPolicies* dest, SPrivTblPolicies* src, bool deepCopy, bool setUpdateTimeMax) {
601
0
  int32_t code = 0, lino = 0;
602
0
  if (deepCopy) {
603
0
    if (taosArrayGetSize(src->policy) == 0) {
604
0
      dest->policy = NULL;
605
0
      goto _exit;
606
0
    }
607
0
    if (!dest->policy) {
608
0
      dest->policy = taosArrayInit(TARRAY_SIZE(src->policy), sizeof(SPrivTblPolicy));
609
0
      if (!dest->policy) {
610
0
        TAOS_CHECK_EXIT(terrno);
611
0
      }
612
0
    }
613
0
    for (int32_t j = 0; j < TARRAY_SIZE(src->policy); ++j) {
614
0
      SPrivTblPolicy* pSrcPolicy = (SPrivTblPolicy*)TARRAY_GET_ELEM(src->policy, j);
615
0
      SPrivTblPolicy  destPolicy = {0};
616
0
      if ((code = privTblPolicyCopy(&destPolicy, pSrcPolicy))) {
617
0
        privTblPolicyFree(&destPolicy);
618
0
        TAOS_CHECK_EXIT(code);
619
0
      }
620
0
      if (setUpdateTimeMax) destPolicy.updateUs = INT64_MAX;
621
0
      if (!taosArrayPush(dest->policy, &destPolicy)) {
622
0
        privTblPolicyFree(&destPolicy);
623
0
        TAOS_CHECK_EXIT(terrno);
624
0
      }
625
0
    }
626
0
  } else {
627
0
    dest->policy = src->policy;
628
0
  }
629
0
_exit:
630
0
  return code;
631
0
}
632
633
0
int32_t privTblPoliciesMerge(SPrivTblPolicies* dest, SPrivTblPolicies* src, bool updateWithLatest) {
634
0
  int32_t code = 0, lino = 0;
635
0
  if (taosArrayGetSize(src->policy) == 0) {
636
0
    dest->policy = NULL;
637
0
    goto _exit;
638
0
  }
639
0
  if (!dest->policy) {
640
0
    dest->policy = taosArrayInit(TARRAY_SIZE(src->policy), sizeof(SPrivTblPolicy));
641
0
    if (!dest->policy) {
642
0
      TAOS_CHECK_EXIT(terrno);
643
0
    }
644
0
  }
645
  // only 1 element exist in the table policy array currently
646
0
  for (int32_t j = 0; j < TARRAY_SIZE(src->policy); ++j) {
647
0
    SPrivTblPolicy* pSrcPolicy = (SPrivTblPolicy*)TARRAY_GET_ELEM(src->policy, j);
648
0
    SPrivTblPolicy* pDestPolicy = taosArrayGet(dest->policy, 0);
649
650
0
    bool needAdd = false;
651
0
    if (!pDestPolicy) {
652
0
      needAdd = true;
653
0
    } else if (updateWithLatest && (pSrcPolicy->updateUs > pDestPolicy->updateUs)) {
654
0
      taosArrayClearEx(dest->policy, privTblPolicyFree);
655
0
      needAdd = true;
656
0
    }
657
0
    if (!needAdd) {
658
0
      break;
659
0
    }
660
661
0
    SPrivTblPolicy destPolicy = {0};
662
0
    if ((code = privTblPolicyCopy(&destPolicy, pSrcPolicy))) {
663
0
      privTblPolicyFree(&destPolicy);
664
0
      TAOS_CHECK_EXIT(code);
665
0
    }
666
0
    if (!taosArrayPush(dest->policy, &destPolicy)) {
667
0
      privTblPolicyFree(&destPolicy);
668
0
      TAOS_CHECK_EXIT(terrno);
669
0
    }
670
0
  }
671
0
_exit:
672
0
  return code;
673
0
}
674
675
bool privHasObjPrivilege(SHashObj* privs, int32_t acctId, const char* objName, const char* tbName,
676
0
                         const SPrivInfo* privInfo, bool recursive) {
677
0
  if (tbName != NULL) {
678
0
    if (privInfo->objLevel == 0 || privInfo->objType <= PRIV_OBJ_DB) {
679
0
      uError("invalid privilege info for table level check, privType:%d, objType:%d, objLevel:%d\n", privInfo->privType,
680
0
             privInfo->objType, privInfo->objLevel);
681
0
    }
682
0
  }
683
684
0
  if (taosHashGetSize(privs) == 0) return false;
685
686
0
  const char* pObjName = objName;
687
0
  const char* pTbName = tbName;
688
0
  char        key[TSDB_PRIV_MAX_KEY_LEN] = {0};
689
0
  int32_t     klen = 0;
690
691
0
_retry:
692
0
  klen = privObjKey(privInfo, acctId, pObjName, pTbName, key, sizeof(key));
693
694
0
  SPrivObjPolicies* policies = taosHashGet(privs, key, klen + 1);
695
0
  if (policies && PRIV_HAS(&policies->policy, privInfo->privType)) {
696
0
    return true;
697
0
  }
698
699
0
  if (!recursive) goto _exit;
700
701
0
  if (pTbName && !(pTbName[0] == '*' && pTbName[1] == 0)) {
702
0
    pTbName = "*";
703
0
    goto _retry;
704
0
  }
705
0
  if (pObjName && !(pObjName[0] == '*' && pObjName[1] == 0)) {
706
0
    pObjName = "*";
707
0
    goto _retry;
708
0
  }
709
0
_exit:
710
0
  return false;
711
0
}
712
713
SPrivTblPolicy* privGetConstraintTblPrivileges(SHashObj* privs, int32_t acctId, const char* objName, const char* tbName,
714
0
                                               const SPrivInfo* privInfo) {
715
0
  if (taosHashGetSize(privs) == 0) return NULL;
716
717
0
  const char* pObjName = objName;
718
0
  const char* pTbName = tbName;
719
0
  char        key[TSDB_PRIV_MAX_KEY_LEN] = {0};
720
0
  int32_t     klen = 0;
721
722
0
  klen = privObjKey(privInfo, acctId, pObjName, pTbName, key, sizeof(key));
723
724
0
  SPrivTblPolicies* policies = taosHashGet(privs, key, klen + 1);
725
0
  if (policies) {
726
0
    return (SPrivTblPolicy*)taosArrayGet(policies->policy, 0);
727
0
  }
728
729
0
  return NULL;
730
0
}
731
732
0
const SPrivInfo* privInfoGet(EPrivType privType) {
733
0
  (void)taosThreadOnce(&privInit, initPrivLookup);
734
0
  SPrivInfo* result = (privType >= 0 && privType <= MAX_PRIV_TYPE) ? privLookup[privType] : NULL;
735
0
  if (!result) terrno = TSDB_CODE_APP_ERROR;
736
0
  return result;
737
0
}
738
739
0
const char* privInfoGetName(EPrivType privType) {
740
0
  const SPrivInfo* privInfo = privInfoGet(privType);
741
0
  return privInfo ? privInfo->name : "privUnkown";
742
0
}
743
744
0
void privAddSetByObjType(SPrivSet* fromSet, SPrivSet* toSet, uint8_t objType) {
745
0
  SPrivIter privIter = {0};
746
0
  privIterInit(&privIter, fromSet);
747
0
  SPrivInfo* pPrivInfo = NULL;
748
0
  while (privIterNext(&privIter, &pPrivInfo)) {
749
0
    if (pPrivInfo->objType == objType) {
750
0
      privAddType(toSet, pPrivInfo->privType);
751
0
    }
752
0
  }
753
0
}
754
755
0
EPrivObjType privDeduceObjType(SPrivSet* privSet) {
756
0
  uint32_t objTypeMask = 0;  // extend to uint64_t if needed
757
758
0
  if (PRIV_OBJ_MAX >= 32) {
759
0
    return PRIV_OBJ_NONE;
760
0
  }
761
762
0
  SPrivIter privIter = {0};
763
0
  privIterInit(&privIter, privSet);
764
0
  SPrivInfo* pPrivInfo = NULL;
765
766
0
  while (privIterNext(&privIter, &pPrivInfo)) {
767
0
    if (pPrivInfo->category == PRIV_CATEGORY_SYSTEM) {
768
0
      return PRIV_OBJ_NONE;
769
0
    }
770
0
    if (pPrivInfo->category == PRIV_CATEGORY_OBJECT) {
771
0
      switch (pPrivInfo->objType) {
772
0
        case PRIV_OBJ_DB:
773
0
          objTypeMask |= (1 << PRIV_OBJ_DB);
774
0
          break;
775
0
        case PRIV_OBJ_TBL:
776
0
          objTypeMask |= (1 << PRIV_OBJ_TBL);
777
0
          break;
778
0
        case PRIV_OBJ_VIEW:
779
0
          objTypeMask |= (1 << PRIV_OBJ_VIEW);
780
0
          break;
781
0
        case PRIV_OBJ_TOPIC:
782
0
          objTypeMask |= (1 << PRIV_OBJ_TOPIC);
783
0
          break;
784
0
        case PRIV_OBJ_IDX:
785
0
          objTypeMask |= (1 << PRIV_OBJ_IDX);
786
0
          break;
787
0
        case PRIV_OBJ_RSMA:
788
0
          objTypeMask |= (1 << PRIV_OBJ_RSMA);
789
0
          break;
790
0
        case PRIV_OBJ_TSMA:
791
0
          objTypeMask |= (1 << PRIV_OBJ_TSMA);
792
0
          break;
793
0
        case PRIV_OBJ_STREAM:
794
0
          objTypeMask |= (1 << PRIV_OBJ_STREAM);
795
0
          break;
796
0
        case PRIV_OBJ_XTASK:
797
0
          objTypeMask |= (1 << PRIV_OBJ_XTASK);
798
0
          break;
799
0
        default:
800
0
          return PRIV_OBJ_NONE;
801
0
      }
802
0
    } else if (pPrivInfo->privType == PRIV_CM_SUBSCRIBE) {
803
0
      objTypeMask |= (1 << PRIV_OBJ_TOPIC);
804
0
    }
805
0
    if (objTypeMask > 0) {
806
0
      uint32_t mask = objTypeMask & (objTypeMask - 1);
807
0
      if (mask > 0) return PRIV_OBJ_NONE;
808
0
    }
809
0
  }
810
0
  if (objTypeMask == 0) return PRIV_OBJ_NONE;
811
812
0
  int32_t bitPos = BUILDIN_CTZL(objTypeMask);
813
0
  if (bitPos < 0 || bitPos >= PRIV_OBJ_MAX) {
814
0
    return PRIV_OBJ_NONE;
815
0
  }
816
0
  return bitPos;
817
0
}