• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

taosdata / TDengine / #5034

24 Apr 2026 11:25AM UTC coverage: 73.058%. Remained the same
#5034

push

travis-ci

web-flow
merge: from main to 3.0 branch #35224

merge: from main to 3.0 branch[manual-only]

1336 of 1975 new or added lines in 48 files covered. (67.65%)

14149 existing lines in 164 files now uncovered.

275896 of 377640 relevant lines covered (73.06%)

132944440.29 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

71.86
/source/common/src/tpriv.c
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
static void initPrivLookup(void) {
371,731✔
268
  for (size_t i = 0; i < sizeof(privInfoTable) / sizeof(privInfoTable[0]); ++i) {
58,361,767✔
269
    EPrivType privType = privInfoTable[i].privType;
57,990,036✔
270
    if (privType <= MAX_PRIV_TYPE &&
57,990,036✔
271
        !privLookup[privType]) {  // duplicated items for other purpose, e.g. createDefaultRoles.
57,990,036✔
272
      privLookup[privType] = &privInfoTable[i];
43,864,258✔
273
    }
274
  }
275
}
371,731✔
276

277
int32_t privExpandAll(SPrivSet* privSet, EPrivObjType pObjType, uint8_t pObjLevel) {
1,492,678✔
278
  if (!privSet) return TSDB_CODE_APP_ERROR;
1,492,678✔
279
  if (!PRIV_HAS(privSet, PRIV_CM_ALL)) return TSDB_CODE_SUCCESS;
1,492,678✔
280

281
  SPrivInfoIter iter = {0};
404,830✔
282
  privInfoIterInit(&iter);
404,830✔
283

284
  SPrivInfo* pPrivInfo = NULL;
404,830✔
285
  while (privInfoIterNext(&iter, &pPrivInfo)) {
63,558,310✔
286
    if (pPrivInfo->objType != pObjType) continue;
63,153,480✔
287
    if (pPrivInfo->objLevel != pObjLevel) {
3,621,952✔
UNCOV
288
      uWarn("privExpandAll: skip privType %d due to level mismatch, expected %d vs %d", pPrivInfo->privType, pObjLevel,
×
289
            pPrivInfo->objLevel);
UNCOV
290
      continue;
×
291
    }
292
    if (pPrivInfo->category != PRIV_CATEGORY_OBJECT) {
3,621,952✔
UNCOV
293
      uWarn("privExpandAll: skip privType %d due to category mismatch, expected OBJECT vs %d", pPrivInfo->privType,
×
294
            pPrivInfo->category);
295
      continue;
×
296
    }
297
    privAddType(privSet, pPrivInfo->privType);
3,621,952✔
298
  }
299

300
  return TSDB_CODE_SUCCESS;
404,830✔
301
}
302

303
int32_t privExpandRw(SPrivSet* privSet, EPrivObjType pObjType, uint8_t pObjLevel) {
1,242,843✔
304
  if (!privSet) return TSDB_CODE_APP_ERROR;
1,242,843✔
305

306
  bool hasRead = PRIV_HAS(privSet, PRIV_CM_READ);
1,242,843✔
307
  bool hasWrite = PRIV_HAS(privSet, PRIV_CM_WRITE);
1,242,843✔
308

309
  if (!hasRead && !hasWrite) return TSDB_CODE_SUCCESS;
1,242,843✔
310

311
  // Remove the legacy types
312
  if (hasRead) privRemoveType(privSet, PRIV_CM_READ);
7,740✔
313
  if (hasWrite) privRemoveType(privSet, PRIV_CM_WRITE);
7,740✔
314

315
  SPrivInfoIter iter = {0};
7,740✔
316
  privInfoIterInit(&iter);
7,740✔
317

318
  SPrivInfo* pPrivInfo = NULL;
7,740✔
319
  while (privInfoIterNext(&iter, &pPrivInfo)) {
1,215,180✔
320
    if (pPrivInfo->objType != pObjType) continue;
1,207,440✔
321
    if (pPrivInfo->objLevel != pObjLevel) continue;
58,680✔
322
    if (pPrivInfo->category != PRIV_CATEGORY_OBJECT) continue;
58,680✔
323

324
    // Check rwAttr and add corresponding privileges
325
    // rwAttr: 1 = read, 2 = write, 3 = read/write
326
    if (hasRead && (pPrivInfo->rwAttr & PRIV_RW_ATTR_READ)) {
58,680✔
327
      privAddType(privSet, pPrivInfo->privType);
28,440✔
328
    }
329
    if (hasWrite && (pPrivInfo->rwAttr & PRIV_RW_ATTR_WRITE)) {
58,680✔
330
      privAddType(privSet, pPrivInfo->privType);
23,580✔
331
    }
332
  }
333

334
  return TSDB_CODE_SUCCESS;
7,740✔
335
}
336

UNCOV
337
int32_t privUpgradeRwDb(SHashObj* objPrivs, const char* dbFName, const char* tbName, uint8_t rwAttr) {
×
UNCOV
338
  if (!objPrivs) return TSDB_CODE_APP_ERROR;
×
339

UNCOV
340
  int32_t       code = 0, lino = 0;
×
UNCOV
341
  char          key[TSDB_PRIV_MAX_KEY_LEN] = {0};
×
UNCOV
342
  SPrivInfoIter iter = {0};
×
UNCOV
343
  privInfoIterInit(&iter);
×
344

345
  SPrivInfo* pPrivInfo = NULL;
×
UNCOV
346
  while (privInfoIterNext(&iter, &pPrivInfo)) {
×
347
    if ((pPrivInfo->rwAttr & rwAttr) == 0) continue;
×
348
    SPrivInfo privInfo = {.objType = pPrivInfo->objType, .objLevel = pPrivInfo->objLevel};
×
349
    int32_t   keyLen = privObjKeyF(&privInfo, dbFName, tbName, key, sizeof(key));
×
350

UNCOV
351
    SPrivObjPolicies* policies = taosHashGet(objPrivs, key, keyLen + 1);
×
352
    if (policies == NULL) {
×
353
      SPrivObjPolicies policy = {0};
×
354
      privAddType(&policy.policy, pPrivInfo->privType);
×
355
      TAOS_CHECK_EXIT(taosHashPut(objPrivs, key, keyLen + 1, &policy, sizeof(SPrivObjPolicies)));
×
356
    } else {
UNCOV
357
      privAddType(&policies->policy, pPrivInfo->privType);
×
358
    }
359
  }
360
_exit:
×
361
  return code;
×
362
}
363

364
int32_t privCheckConflicts(const SPrivSet* privSet, EPrivCategory* pCategory, EPrivObjType* pObjType,
1,478,192✔
365
                           uint8_t* pObjLevel, EPrivType* conflict0, EPrivType* conflict1) {
366
  (void)taosThreadOnce(&privInit, initPrivLookup);
1,478,192✔
367

368
  if (!privSet) return TSDB_CODE_APP_ERROR;
1,478,192✔
369

370
  int32_t          code = 0;
1,478,192✔
371
  const SPrivInfo* privInfo = NULL;
1,478,192✔
372

373
  bool hasSystemPriv = false;
1,478,192✔
374
  bool hasObjectPriv = false;
1,478,192✔
375
  bool hasCommonPriv = false;
1,478,192✔
376

377
  EPrivType lastPriv = PRIV_TYPE_UNKNOWN;
1,478,192✔
378

379
  for (int32_t i = 0; i < PRIV_GROUP_CNT; ++i) {
7,389,442✔
380
    uint64_t chunk = privSet->set[i];
5,911,816✔
381
    if (chunk == 0) continue;
5,911,816✔
382

383
    while (chunk != 0) {
2,445,267✔
384
      int32_t   bitPos = BUILDIN_CTZL(chunk);
1,231,078✔
385
      EPrivType privType = (i << 6) + bitPos;
1,231,078✔
386
      chunk &= ~(1ULL << bitPos);
1,231,078✔
387

388
      privInfo = privLookup[privType];
1,231,078✔
389
      if (privInfo == NULL) continue;
1,231,078✔
390

391
      switch (privInfo->category) {
1,222,742✔
392
        case PRIV_CATEGORY_SYSTEM: {
20,806✔
393
          if (hasObjectPriv || hasCommonPriv) {
20,806✔
394
            code = 1;
180✔
395
            goto _exit;
180✔
396
          }
397
          hasSystemPriv = true;
20,626✔
398
          lastPriv = privInfo->privType;
20,626✔
399
          break;
20,626✔
400
        }
401
        case PRIV_CATEGORY_OBJECT: {
986,527✔
402
          if (hasSystemPriv) {
986,527✔
UNCOV
403
            code = 1;
×
UNCOV
404
            goto _exit;
×
405
          }
406
          if ((*pObjType != privInfo->objType) && (*pObjType != PRIV_OBJ_NONE)) {
986,527✔
407
            code = 2;
386✔
408
            goto _exit;
386✔
409
          }
410
          if (*pObjLevel != privInfo->objLevel) {
986,141✔
411
            code = 3;
×
UNCOV
412
            goto _exit;
×
413
          }
414
          hasObjectPriv = true;
986,141✔
415
          lastPriv = privInfo->privType;
986,141✔
416
          break;
986,141✔
417
        }
418
        case PRIV_CATEGORY_COMMON: {
215,409✔
419
          if (hasSystemPriv) {
215,409✔
UNCOV
420
            code = 1;
×
UNCOV
421
            goto _exit;
×
422
          }
423
          hasCommonPriv = true;
215,409✔
424
          lastPriv = privInfo->privType;
215,409✔
425
          break;
215,409✔
426
        }
427
        default:
×
428
          break;
×
429
      }
430
    }
431
  }
432

433
_exit:
1,477,626✔
434
  if (code != 0) {
1,478,192✔
435
    if (conflict0) *conflict0 = lastPriv;
566✔
436
    if (conflict1 && privInfo) *conflict1 = privInfo->privType;
566✔
437
    return code;
566✔
438
  }
439

440
  if (pCategory) {
1,477,626✔
441
    *pCategory = hasSystemPriv   ? PRIV_CATEGORY_SYSTEM
1,477,626✔
442
                 : hasObjectPriv ? PRIV_CATEGORY_OBJECT
1,477,626✔
443
                 : hasCommonPriv ? PRIV_CATEGORY_COMMON
444
                                 : PRIV_CATEGORY_UNKNOWN;
445
  }
446

447
  return 0;
1,477,626✔
448
}
449

450
void privIterInit(SPrivIter* pIter, SPrivSet* privSet) {
2,314,359✔
451
  (void)taosThreadOnce(&privInit, initPrivLookup);
2,314,359✔
452
  pIter->privSet = privSet;
2,314,359✔
453
  pIter->groupIndex = 0;
2,314,359✔
454
  pIter->curPriv = privSet->set[0];
2,314,359✔
455
}
2,314,359✔
456

457
bool privIterNext(SPrivIter* iter, SPrivInfo** ppPrivInfo) {
6,154,283✔
458
_loop:
6,154,283✔
459
  while (iter->curPriv == 0) {
13,097,000✔
460
    if (++iter->groupIndex >= PRIV_GROUP_CNT) {
9,256,716✔
461
      return false;
2,313,999✔
462
    }
463
    iter->curPriv = iter->privSet->set[iter->groupIndex];
6,942,717✔
464
  }
465
  int32_t   bitPos = BUILDIN_CTZL(iter->curPriv);
3,840,284✔
466
  EPrivType privType = (iter->groupIndex << 6) + bitPos;
3,840,284✔
467
  iter->curPriv &= (iter->curPriv -1);
3,840,284✔
468
  if (ppPrivInfo) {
3,840,284✔
469
    *ppPrivInfo = privLookup[privType];
3,840,284✔
470
    if (!(*ppPrivInfo)) goto _loop;
3,840,284✔
471
  }
472
  return true;
3,816,828✔
473
}
474

475
void privInfoIterInit(SPrivInfoIter* pIter) {
2,569,516✔
476
  (void)taosThreadOnce(&privInit, initPrivLookup);
2,569,516✔
477
  pIter->privInfo = privInfoTable;
2,569,516✔
478
  pIter->privInfoCnt = sizeof(privInfoTable) / sizeof(privInfoTable[0]);
2,569,516✔
479
  pIter->index = 0;
2,569,516✔
480
}
2,569,516✔
481

482
bool privInfoIterNext(SPrivInfoIter* iter, SPrivInfo** ppPrivInfo) {
403,414,012✔
483
  if (iter->index < iter->privInfoCnt) {
403,414,012✔
484
    if (ppPrivInfo) {
400,844,496✔
485
      *ppPrivInfo = &iter->privInfo[iter->index++];
400,844,496✔
486
    } else {
UNCOV
487
      iter->index++;
×
488
    }
489
    return true;
400,844,496✔
490
  }
491

492
  return false;
2,569,516✔
493
}
494
// objType.1.db.tb or objType.1.db
495
int32_t privObjKeyF(const SPrivInfo* pPrivInfo, const char* fname, const char* tb, char* buf, int32_t bufLen) {
58,878,025✔
496
  return (pPrivInfo->objLevel == 0)
58,878,025✔
497
             ? snprintf(buf, bufLen, "%d.%s", pPrivInfo->objType, fname ? fname : "")
22,679,454✔
498
             : snprintf(buf, bufLen, "%d.%s.%s", pPrivInfo->objType, fname ? fname : "", tb ? tb : "");
81,557,479✔
499
}
500

501
int32_t privObjKey(const SPrivInfo* pPrivInfo, int32_t acctId, const char* name, const char* tb, char* buf,
3,910,587✔
502
                   int32_t bufLen) {
503
  return (pPrivInfo->objLevel == 0)
3,910,587✔
504
             ? snprintf(buf, bufLen, "%d.%d.%s", pPrivInfo->objType, acctId, name ? name : "")
1,593,375✔
505
             : snprintf(buf, bufLen, "%d.%d.%s.%s", pPrivInfo->objType, acctId, name ? name : "", tb ? tb : "");
5,503,962✔
506
}
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,
1,367,275✔
510
                        bool fullDb) {
511
  char* p = strchr(str, '.');
1,367,275✔
512
  if (!p) {
1,367,275✔
UNCOV
513
    return TSDB_CODE_INVALID_DATA_FMT;
×
514
  }
515
  *pObjType = taosStr2Int32(str, NULL, 10);
1,367,275✔
516
  if (errno == ERANGE || *pObjType < PRIV_OBJ_CLUSTER || *pObjType >= PRIV_OBJ_MAX) {
1,367,275✔
UNCOV
517
    return TSDB_CODE_INVALID_DATA_FMT;
×
518
  }
519
  char* pNext = strchr(p + 1, '.');
1,367,275✔
520
  if (!pNext) {
1,367,275✔
UNCOV
521
    return TSDB_CODE_INVALID_DATA_FMT;
×
522
  }
523
  char* qNext = strchr(pNext + 1, '.');
1,367,275✔
524
  if (qNext) {
1,367,275✔
525
    size_t dbLength = qNext - (fullDb ? (p + 1) : (pNext + 1));
1,310,905✔
526
    if (dbLength >= (size_t)dbLen) {
1,310,905✔
UNCOV
527
      return TSDB_CODE_INVALID_DATA_FMT;
×
528
    }
529
    tstrncpy(db, fullDb ? (p + 1) : (pNext + 1), dbLength + 1);
1,310,905✔
530
    tstrncpy(tb, qNext + 1, tbLen);
1,310,905✔
531
  } else {
532
    tstrncpy(db, fullDb ? (p + 1) : (pNext + 1), dbLen);
56,370✔
533
    tb[0] = '\0';
56,370✔
534
  }
535
  return TSDB_CODE_SUCCESS;
1,367,275✔
536
}
537

538
const char* privObjGetName(EPrivObjType objType) {
3,058,173✔
539
  if (objType < PRIV_OBJ_CLUSTER || objType >= PRIV_OBJ_MAX) {
3,058,173✔
UNCOV
540
    return "UNKNOWN";
×
541
  }
542
  return __privObjInfo[objType].name;
3,058,173✔
543
}
544

545
int32_t privObjGetLevel(EPrivObjType objType) {
3,073,936✔
546
  if (objType < PRIV_OBJ_CLUSTER || objType >= PRIV_OBJ_MAX) {
3,073,936✔
547
    return -1;
×
548
  }
549
  return __privObjInfo[objType].level;
3,073,936✔
550
}
551

UNCOV
552
int32_t getSysRoleType(const char* roleName) {
×
UNCOV
553
  if (strcmp(roleName, TSDB_ROLE_SYSDBA) == 0) {
×
554
    return T_ROLE_SYSDBA;
×
UNCOV
555
  } else if (strcmp(roleName, TSDB_ROLE_SYSSEC) == 0) {
×
UNCOV
556
    return T_ROLE_SYSSEC;
×
UNCOV
557
  } else if (strcmp(roleName, TSDB_ROLE_SYSAUDIT) == 0) {
×
UNCOV
558
    return T_ROLE_SYSAUDIT;
×
559
  } else if (strcmp(roleName, TSDB_ROLE_SYSAUDIT_LOG) == 0) {
×
560
    return T_ROLE_SYSAUDIT_LOG;
×
561
  } else if (strcmp(roleName, TSDB_ROLE_SYSINFO_0) == 0) {
×
562
    return T_ROLE_SYSINFO_0;
×
563
  } else if (strcmp(roleName, TSDB_ROLE_SYSINFO_1) == 0) {
×
564
    return T_ROLE_SYSINFO_1;
×
565
  }
566
  return 0;
×
567
}
568

569
bool isPrivInheritName(const char* name) {
1,616,062✔
570
  if (name && (name[0] == 'S' || name[0] == 's')) {
1,616,062✔
571
    if (taosStrncasecmp(name, TSDB_ROLE_SYSDBA, 7) == 0 || taosStrncasecmp(name, TSDB_ROLE_SYSSEC, 7) == 0 ||
4,703✔
572
        taosStrncasecmp(name, TSDB_ROLE_SYSAUDIT, 9) == 0 || taosStrncasecmp(name, TSDB_ROLE_SYSAUDIT_LOG, 13) == 0 ||
4,703✔
573
        taosStrncasecmp(name, TSDB_ROLE_SYSINFO_0, 10) == 0 || taosStrncasecmp(name, TSDB_ROLE_SYSINFO_1, 10) == 0) {
4,703✔
UNCOV
574
      return true;
×
575
    }
576
  }
577
  return false;
1,616,062✔
578
}
579

580
int32_t privTblPolicyCopy(SPrivTblPolicy* dest, SPrivTblPolicy* src) {
540,510✔
581
  dest->updateUs = src->updateUs;
540,510✔
582
  dest->condLen = src->condLen;
540,510✔
583
  if (src->cond) {
540,510✔
584
    if (!(dest->cond = taosStrdup(src->cond))) {
534,257✔
UNCOV
585
      return terrno;
×
586
    }
587
  } else {
588
    dest->cond = NULL;
6,253✔
589
  }
590

591
  if (taosArrayGetSize(src->cols) > 0) {
540,510✔
592
    dest->cols = taosArrayDup(src->cols, NULL);
15,738✔
593
    if (!dest->cols) return terrno;
15,738✔
594
  } else {
595
    dest->cols = NULL;
524,772✔
596
  }
597
  return 0;
540,510✔
598
}
599

600
int32_t privTblPoliciesAdd(SPrivTblPolicies* dest, SPrivTblPolicies* src, bool deepCopy, bool setUpdateTimeMax) {
540,510✔
601
  int32_t code = 0, lino = 0;
540,510✔
602
  if (deepCopy) {
540,510✔
603
    if (taosArrayGetSize(src->policy) == 0) {
540,510✔
UNCOV
604
      dest->policy = NULL;
×
UNCOV
605
      goto _exit;
×
606
    }
607
    if (!dest->policy) {
540,510✔
608
      dest->policy = taosArrayInit(TARRAY_SIZE(src->policy), sizeof(SPrivTblPolicy));
540,510✔
609
      if (!dest->policy) {
540,510✔
UNCOV
610
        TAOS_CHECK_EXIT(terrno);
×
611
      }
612
    }
613
    for (int32_t j = 0; j < TARRAY_SIZE(src->policy); ++j) {
1,081,020✔
614
      SPrivTblPolicy* pSrcPolicy = (SPrivTblPolicy*)TARRAY_GET_ELEM(src->policy, j);
540,510✔
615
      SPrivTblPolicy  destPolicy = {0};
540,510✔
616
      if ((code = privTblPolicyCopy(&destPolicy, pSrcPolicy))) {
540,510✔
617
        privTblPolicyFree(&destPolicy);
UNCOV
618
        TAOS_CHECK_EXIT(code);
×
619
      }
620
      if (setUpdateTimeMax) destPolicy.updateUs = INT64_MAX;
540,510✔
621
      if (!taosArrayPush(dest->policy, &destPolicy)) {
1,081,020✔
622
        privTblPolicyFree(&destPolicy);
UNCOV
623
        TAOS_CHECK_EXIT(terrno);
×
624
      }
625
    }
626
  } else {
UNCOV
627
    dest->policy = src->policy;
×
628
  }
629
_exit:
540,510✔
630
  return code;
540,510✔
631
}
632

633
int32_t privTblPoliciesMerge(SPrivTblPolicies* dest, SPrivTblPolicies* src, bool updateWithLatest) {
1,014✔
634
  int32_t code = 0, lino = 0;
1,014✔
635
  if (taosArrayGetSize(src->policy) == 0) {
1,014✔
UNCOV
636
    dest->policy = NULL;
×
UNCOV
637
    goto _exit;
×
638
  }
639
  if (!dest->policy) {
1,014✔
UNCOV
640
    dest->policy = taosArrayInit(TARRAY_SIZE(src->policy), sizeof(SPrivTblPolicy));
×
UNCOV
641
    if (!dest->policy) {
×
UNCOV
642
      TAOS_CHECK_EXIT(terrno);
×
643
    }
644
  }
645
  // only 1 element exist in the table policy array currently
646
  for (int32_t j = 0; j < TARRAY_SIZE(src->policy); ++j) {
1,014✔
647
    SPrivTblPolicy* pSrcPolicy = (SPrivTblPolicy*)TARRAY_GET_ELEM(src->policy, j);
1,014✔
648
    SPrivTblPolicy* pDestPolicy = taosArrayGet(dest->policy, 0);
1,014✔
649

650
    bool needAdd = false;
1,014✔
651
    if (!pDestPolicy) {
1,014✔
UNCOV
652
      needAdd = true;
×
653
    } else if (updateWithLatest && (pSrcPolicy->updateUs > pDestPolicy->updateUs)) {
1,014✔
UNCOV
654
      taosArrayClearEx(dest->policy, privTblPolicyFree);
×
UNCOV
655
      needAdd = true;
×
656
    }
657
    if (!needAdd) {
1,014✔
658
      break;
1,014✔
659
    }
660

661
    SPrivTblPolicy destPolicy = {0};
×
662
    if ((code = privTblPolicyCopy(&destPolicy, pSrcPolicy))) {
×
663
      privTblPolicyFree(&destPolicy);
UNCOV
664
      TAOS_CHECK_EXIT(code);
×
665
    }
UNCOV
666
    if (!taosArrayPush(dest->policy, &destPolicy)) {
×
667
      privTblPolicyFree(&destPolicy);
668
      TAOS_CHECK_EXIT(terrno);
×
669
    }
670
  }
671
_exit:
×
672
  return code;
1,014✔
673
}
674

675
bool privHasObjPrivilege(SHashObj* privs, int32_t acctId, const char* objName, const char* tbName,
2,774,519✔
676
                         const SPrivInfo* privInfo, bool recursive) {
677
  if (tbName != NULL) {
2,774,519✔
678
    if (privInfo->objLevel == 0 || privInfo->objType <= PRIV_OBJ_DB) {
1,245,236✔
UNCOV
679
      uError("invalid privilege info for table level check, privType:%d, objType:%d, objLevel:%d\n", privInfo->privType,
×
680
             privInfo->objType, privInfo->objLevel);
681
    }
682
  }
683

684
  if (taosHashGetSize(privs) == 0) return false;
2,774,519✔
685

686
  const char* pObjName = objName;
2,758,590✔
687
  const char* pTbName = tbName;
2,758,590✔
688
  char        key[TSDB_PRIV_MAX_KEY_LEN] = {0};
2,758,590✔
689
  int32_t     klen = 0;
2,758,590✔
690

691
_retry:
3,845,859✔
692
  klen = privObjKey(privInfo, acctId, pObjName, pTbName, key, sizeof(key));
3,845,859✔
693

694
  SPrivObjPolicies* policies = taosHashGet(privs, key, klen + 1);
3,845,859✔
695
  if (policies && PRIV_HAS(&policies->policy, privInfo->privType)) {
3,845,859✔
696
    return true;
2,088,104✔
697
  }
698

699
  if (!recursive) goto _exit;
1,757,755✔
700

701
  if (pTbName && !(pTbName[0] == '*' && pTbName[1] == 0)) {
1,557,705✔
702
    pTbName = "*";
601,746✔
703
    goto _retry;
601,746✔
704
  }
705
  if (pObjName && !(pObjName[0] == '*' && pObjName[1] == 0)) {
955,959✔
706
    pObjName = "*";
485,523✔
707
    goto _retry;
485,523✔
708
  }
709
_exit:
670,486✔
710
  return false;
670,486✔
711
}
712

713
SPrivTblPolicy* privGetConstraintTblPrivileges(SHashObj* privs, int32_t acctId, const char* objName, const char* tbName,
64,728✔
714
                                               const SPrivInfo* privInfo) {
715
  if (taosHashGetSize(privs) == 0) return NULL;
64,728✔
716

717
  const char* pObjName = objName;
64,728✔
718
  const char* pTbName = tbName;
64,728✔
719
  char        key[TSDB_PRIV_MAX_KEY_LEN] = {0};
64,728✔
720
  int32_t     klen = 0;
64,728✔
721

722
  klen = privObjKey(privInfo, acctId, pObjName, pTbName, key, sizeof(key));
64,728✔
723

724
  SPrivTblPolicies* policies = taosHashGet(privs, key, klen + 1);
64,728✔
725
  if (policies) {
64,728✔
726
    return (SPrivTblPolicy*)taosArrayGet(policies->policy, 0);
36,612✔
727
  }
728

729
  return NULL;
28,116✔
730
}
731

732
const SPrivInfo* privInfoGet(EPrivType privType) {
6,886,431✔
733
  (void)taosThreadOnce(&privInit, initPrivLookup);
6,886,431✔
734
  SPrivInfo* result = (privType >= 0 && privType <= MAX_PRIV_TYPE) ? privLookup[privType] : NULL;
6,886,431✔
735
  if (!result) terrno = TSDB_CODE_APP_ERROR;
6,886,431✔
736
  return result;
6,886,431✔
737
}
738

739
const char* privInfoGetName(EPrivType privType) {
448,526✔
740
  const SPrivInfo* privInfo = privInfoGet(privType);
448,526✔
741
  return privInfo ? privInfo->name : "privUnkown";
448,526✔
742
}
743

744
void privAddSetByObjType(SPrivSet* fromSet, SPrivSet* toSet, uint8_t objType) {
236,800✔
745
  SPrivIter privIter = {0};
236,800✔
746
  privIterInit(&privIter, fromSet);
236,800✔
747
  SPrivInfo* pPrivInfo = NULL;
236,800✔
748
  while (privIterNext(&privIter, &pPrivInfo)) {
466,400✔
749
    if (pPrivInfo->objType == objType) {
229,600✔
UNCOV
750
      privAddType(toSet, pPrivInfo->privType);
×
751
    }
752
  }
753
}
236,800✔
754

755
EPrivObjType privDeduceObjType(SPrivSet* privSet) {
433,185✔
756
  uint32_t objTypeMask = 0;  // extend to uint64_t if needed
433,185✔
757

758
  if (PRIV_OBJ_MAX >= 32) {
759
    return PRIV_OBJ_NONE;
760
  }
761

762
  SPrivIter privIter = {0};
433,185✔
763
  privIterInit(&privIter, privSet);
433,185✔
764
  SPrivInfo* pPrivInfo = NULL;
433,185✔
765

766
  while (privIterNext(&privIter, &pPrivInfo)) {
740,443✔
767
    if (pPrivInfo->category == PRIV_CATEGORY_SYSTEM) {
307,618✔
768
      return PRIV_OBJ_NONE;
360✔
769
    }
770
    if (pPrivInfo->category == PRIV_CATEGORY_OBJECT) {
307,258✔
771
      switch (pPrivInfo->objType) {
190,838✔
UNCOV
772
        case PRIV_OBJ_DB:
×
UNCOV
773
          objTypeMask |= (1 << PRIV_OBJ_DB);
×
UNCOV
774
          break;
×
775
        case PRIV_OBJ_TBL:
190,838✔
776
          objTypeMask |= (1 << PRIV_OBJ_TBL);
190,838✔
777
          break;
190,838✔
UNCOV
778
        case PRIV_OBJ_VIEW:
×
779
          objTypeMask |= (1 << PRIV_OBJ_VIEW);
×
780
          break;
×
781
        case PRIV_OBJ_TOPIC:
×
UNCOV
782
          objTypeMask |= (1 << PRIV_OBJ_TOPIC);
×
UNCOV
783
          break;
×
UNCOV
784
        case PRIV_OBJ_IDX:
×
785
          objTypeMask |= (1 << PRIV_OBJ_IDX);
×
786
          break;
×
787
        case PRIV_OBJ_RSMA:
×
788
          objTypeMask |= (1 << PRIV_OBJ_RSMA);
×
789
          break;
×
790
        case PRIV_OBJ_TSMA:
×
791
          objTypeMask |= (1 << PRIV_OBJ_TSMA);
×
792
          break;
×
793
        case PRIV_OBJ_STREAM:
×
794
          objTypeMask |= (1 << PRIV_OBJ_STREAM);
×
795
          break;
×
796
        case PRIV_OBJ_XTASK:
×
797
          objTypeMask |= (1 << PRIV_OBJ_XTASK);
×
798
          break;
×
799
        default:
×
800
          return PRIV_OBJ_NONE;
×
801
      }
802
    } else if (pPrivInfo->privType == PRIV_CM_SUBSCRIBE) {
116,420✔
803
      objTypeMask |= (1 << PRIV_OBJ_TOPIC);
540✔
804
    }
805
    if (objTypeMask > 0) {
307,258✔
806
      uint32_t mask = objTypeMask & (objTypeMask - 1);
191,378✔
807
      if (mask > 0) return PRIV_OBJ_NONE;
191,378✔
808
    }
809
  }
810
  if (objTypeMask == 0) return PRIV_OBJ_NONE;
432,825✔
811

812
  int32_t bitPos = BUILDIN_CTZL(objTypeMask);
189,101✔
813
  if (bitPos < 0 || bitPos >= PRIV_OBJ_MAX) {
189,101✔
UNCOV
814
    return PRIV_OBJ_NONE;
×
815
  }
816
  return bitPos;
189,101✔
817
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc