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

taosdata / TDengine / #4935

22 Jan 2026 06:38AM UTC coverage: 66.708% (+0.02%) from 66.691%
#4935

push

travis-ci

web-flow
merge: from main to 3.0 #34371

121 of 271 new or added lines in 17 files covered. (44.65%)

9066 existing lines in 149 files now uncovered.

203884 of 305637 relevant lines covered (66.71%)

125811266.68 hits per line

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

63.83
/source/dnode/mnode/impl/src/mndRole.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
// clang-format off
18
#ifndef TD_ASTRA
19
#include <uv.h>
20
#endif
21
#include "crypt.h"
22
#include "mndRole.h"
23
#include "mndUser.h"
24
#include "audit.h"
25
#include "mndDb.h"
26
#include "mndPrivilege.h"
27
#include "mndShow.h"
28
#include "mndStb.h"
29
#include "mndTopic.h"
30
#include "mndTrans.h"
31
#include "tbase64.h"
32

33
// clang-format on
34

35
#define MND_ROLE_VER_NUMBER  1
36
#define MND_ROLE_SYSROLE_VER PRIV_INFO_TABLE_VERSION
37

38
static SRoleMgmt roleMgmt = {0};
39
static bool      isDeploy = false;
40

41
static int32_t  mndCreateDefaultRoles(SMnode *pMnode);
42
static SSdbRow *mndRoleActionDecode(SSdbRaw *pRaw);
43
static int32_t  mndRoleActionInsert(SSdb *pSdb, SRoleObj *pRole);
44
static int32_t  mndRoleActionDelete(SSdb *pSdb, SRoleObj *pRole);
45
static int32_t  mndRoleActionUpdate(SSdb *pSdb, SRoleObj *pOld, SRoleObj *pNew);
46
static int32_t  mndCreateRole(SMnode *pMnode, char *acct, SCreateRoleReq *pCreate, SRpcMsg *pReq);
47
static int32_t  mndProcessCreateRoleReq(SRpcMsg *pReq);
48
static int32_t  mndProcessAlterRoleReq(SRpcMsg *pReq);
49
static int32_t  mndProcessDropRoleReq(SRpcMsg *pReq);
50
static int32_t  mndProcessGetRoleAuthReq(SRpcMsg *pReq);
51
static int32_t  mndRetrieveRoles(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pBlock, int32_t rows);
52
static void     mndCancelGetNextRole(SMnode *pMnode, void *pIter);
53
static int32_t  mndRetrievePrivileges(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pBlock, int32_t rows);
54
static void     mndCancelGetNextPrivileges(SMnode *pMnode, void *pIter);
55
static int32_t  mndRetrieveColPrivileges(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pBlock, int32_t rows);
56
static void     mndCancelGetNextColPrivileges(SMnode *pMnode, void *pIter);
57

58
int32_t mndInitRole(SMnode *pMnode) {
396,445✔
59
  // role management init
60
  roleMgmt.lastUpd = taosGetTimestampMs();
396,445✔
61
  TAOS_CHECK_RETURN(taosThreadRwlockInit(&roleMgmt.rw, NULL));
396,445✔
62

63
  SSdbTable table = {
396,445✔
64
      .sdbType = SDB_ROLE,
65
      .keyType = SDB_KEY_BINARY,
66
      .deployFp = (SdbDeployFp)mndCreateDefaultRoles,
67
      // .redeployFp = (SdbDeployFp)mndCreateDefaultRoles, // TODO: upgrade role table
68
      .encodeFp = (SdbEncodeFp)mndRoleActionEncode,
69
      .decodeFp = (SdbDecodeFp)mndRoleActionDecode,
70
      .insertFp = (SdbInsertFp)mndRoleActionInsert,
71
      .updateFp = (SdbUpdateFp)mndRoleActionUpdate,
72
      .deleteFp = (SdbDeleteFp)mndRoleActionDelete,
73
  };
74

75
  mndSetMsgHandle(pMnode, TDMT_MND_CREATE_ROLE, mndProcessCreateRoleReq);
396,445✔
76
  mndSetMsgHandle(pMnode, TDMT_MND_DROP_ROLE, mndProcessDropRoleReq);
396,445✔
77
  mndSetMsgHandle(pMnode, TDMT_MND_ALTER_ROLE, mndProcessAlterRoleReq);
396,445✔
78

79
  mndAddShowRetrieveHandle(pMnode, TSDB_MGMT_TABLE_ROLE, mndRetrieveRoles);
396,445✔
80
  mndAddShowFreeIterHandle(pMnode, TSDB_MGMT_TABLE_ROLE, mndCancelGetNextRole);
396,445✔
81
  mndAddShowRetrieveHandle(pMnode, TSDB_MGMT_TABLE_ROLE_PRIVILEGES, mndRetrievePrivileges);
396,445✔
82
  mndAddShowFreeIterHandle(pMnode, TSDB_MGMT_TABLE_ROLE_PRIVILEGES, mndCancelGetNextPrivileges);
396,445✔
83
  mndAddShowRetrieveHandle(pMnode, TSDB_MGMT_TABLE_ROLE_COL_PRIVILEGES, mndRetrieveColPrivileges);
396,445✔
84
  mndAddShowFreeIterHandle(pMnode, TSDB_MGMT_TABLE_ROLE_COL_PRIVILEGES, mndCancelGetNextColPrivileges);
396,445✔
85
  return sdbSetTable(pMnode->pSdb, table);
396,445✔
86
}
87

88
void mndCleanupRole(SMnode *pMnode) { (void)taosThreadRwlockDestroy(&roleMgmt.rw); }
396,387✔
89

90
int64_t mndGetRoleLastUpd() {
×
91
  int64_t lastUpd;
92
  (void)taosThreadRwlockRdlock(&roleMgmt.rw);
×
93
  lastUpd = roleMgmt.lastUpd;
×
94
  (void)taosThreadRwlockUnlock(&roleMgmt.rw);
×
95
  return lastUpd;
×
96
}
97

98
void mndSetRoleLastUpd(int64_t updateTime) {
604✔
99
  (void)taosThreadRwlockWrlock(&roleMgmt.rw);
604✔
100
  roleMgmt.lastUpd = updateTime;
604✔
101
  (void)taosThreadRwlockUnlock(&roleMgmt.rw);
604✔
102
}
604✔
103

UNCOV
104
bool mndNeedRetrieveRole(SUserObj *pUser) {
×
UNCOV
105
  bool result = false;
×
UNCOV
106
  if (taosHashGetSize(pUser->roles) > 0) {
×
UNCOV
107
    (void)taosThreadRwlockRdlock(&roleMgmt.rw);
×
UNCOV
108
    if (pUser->lastRoleRetrieve <= roleMgmt.lastUpd) result = true;
×
UNCOV
109
    (void)taosThreadRwlockUnlock(&roleMgmt.rw);
×
110
  }
UNCOV
111
  return result;
×
112
}
113

114
static int32_t mndFillSystemRoleTblPrivileges(SHashObj **ppHash) {
×
115
  int32_t code = 0, lino = 0;
×
116
  char    objKey[TSDB_PRIV_MAX_KEY_LEN] = {0};
×
117
  int32_t keyLen = privTblKey("1.*", "*", objKey, sizeof(objKey));
×
118

119
  if (!(*ppHash) &&
×
120
      !((*ppHash) = taosHashInit(1, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_ENTRY_LOCK))) {
×
121
    TAOS_CHECK_EXIT(terrno);
×
122
  }
123

124
  TAOS_CHECK_EXIT(taosHashPut(*ppHash, objKey, keyLen + 1, NULL, 0));
×
125

126
_exit:
×
127
  TAOS_RETURN(code);
×
128
}
129

130
static int32_t mndFillSystemRolePrivileges(SMnode *pMnode, SRoleObj *pObj, uint32_t roleType) {
1,695,306✔
131
  int32_t       code = 0, lino = 0;
1,695,306✔
132
  SPrivInfoIter iter = {0};
1,695,306✔
133
  privInfoIterInit(&iter);
1,695,306✔
134

135
  char objKey[TSDB_PRIV_MAX_KEY_LEN] = {0};
1,695,306✔
136

137
  SPrivInfo *pPrivInfo = NULL;
1,695,306✔
138
  while (privInfoIterNext(&iter, &pPrivInfo)) {
232,256,922✔
139
    if ((pPrivInfo->sysType & roleType) == 0) continue;
230,561,616✔
140
    if (pPrivInfo->category == PRIV_CATEGORY_SYSTEM) {  // system privileges
76,006,219✔
141
      privAddType(&pObj->sysPrivs, pPrivInfo->privType);
34,753,773✔
142
    } else if (pPrivInfo->category == PRIV_CATEGORY_OBJECT) {  // object privileges
41,252,446✔
143
      switch (pPrivInfo->privType) {
41,252,446✔
144
        case PRIV_TBL_SELECT: {  // SELECT TABLE
×
145
          TAOS_CHECK_EXIT(mndFillSystemRoleTblPrivileges(&pObj->selectTbs));
×
146
          break;
×
147
        }
148
        case PRIV_TBL_INSERT: {  // INSERT TABLE
×
149
          TAOS_CHECK_EXIT(mndFillSystemRoleTblPrivileges(&pObj->insertTbs));
×
150
          break;
×
151
        }
152
        case PRIV_TBL_UPDATE: {  // UPDATE TABLE(reserved)
×
153
          TAOS_CHECK_EXIT(mndFillSystemRoleTblPrivileges(&pObj->updateTbs));
×
154
          break;
×
155
        }
156
        case PRIV_TBL_DELETE: {  // DELETE TABLE:
×
157
          TAOS_CHECK_EXIT(mndFillSystemRoleTblPrivileges(&pObj->deleteTbs));
×
158
          break;
×
159
        }
160
        default: {
41,252,446✔
161
          int32_t keyLen = privObjKeyF(pPrivInfo, "1.*", "*", objKey, sizeof(objKey));
41,252,446✔
162
          if (!pObj->objPrivs && !(pObj->objPrivs = taosHashInit(1, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY),
41,252,446✔
163
                                                                 true, HASH_ENTRY_LOCK))) {
164
            TAOS_CHECK_EXIT(terrno);
×
165
          }
166
          SPrivObjPolicies *objPolicy = taosHashGet(pObj->objPrivs, objKey, keyLen + 1);
41,252,446✔
167
          if (objPolicy) {
41,252,446✔
168
            privAddType(&objPolicy->policy, pPrivInfo->privType);
29,385,304✔
169
          } else {
170
            SPrivObjPolicies policies = {0};
11,867,142✔
171
            privAddType(&policies.policy, pPrivInfo->privType);
11,867,142✔
172
            TAOS_CHECK_EXIT(taosHashPut(pObj->objPrivs, objKey, keyLen + 1, &policies, sizeof(policies)));
11,867,142✔
173
          }
174
          break;
41,252,446✔
175
        }
176
      }
177
    }
178
  }
179
_exit:
1,695,306✔
180
  if (code != 0) {
1,695,306✔
181
    mError("role, %s failed at line %d for %s since %s", __func__, lino, pObj->name, tstrerror(code));
×
182
  }
183
  TAOS_RETURN(code);
1,695,306✔
184
}
185

186
/**
187
 * system roles: SYSDBA/SYSSEC/SYSAUDIT/SYSINFO_0/SYSINFO_1
188
 */
189
static int32_t mndCreateDefaultRole(SMnode *pMnode, char *role, uint32_t roleType) {
1,695,306✔
190
  int32_t   code = 0, lino = 0;
1,695,306✔
191
  SRoleObj *pRole = NULL, *pNew = NULL;
1,695,306✔
192
  if (mndAcquireRole(pMnode, role, &pRole) == 0) {
1,695,306✔
193
    if (pRole->version < MND_ROLE_SYSROLE_VER) {
×
194
      mInfo("role:%s version:%" PRId64 " upgrade to version:%d", role, pRole->version, MND_ROLE_SYSROLE_VER);
×
195
      pNew = taosMemoryCalloc(1, sizeof(SRoleObj));
×
196
      if (pNew == NULL) {
×
197
        mndReleaseRole(pMnode, pRole);
×
198
        TAOS_RETURN(TSDB_CODE_OUT_OF_MEMORY);
×
199
      }
200
      snprintf(pNew->name, TSDB_ROLE_LEN, "%s", pRole->name);
×
201
      pNew->createdTime = pRole->createdTime;
×
202
      pNew->uid = pRole->uid;
×
203
      pNew->flag = pRole->flag;
×
204
      pNew->updateTime = taosGetTimestampMs();
×
205
      pNew->version = MND_ROLE_SYSROLE_VER;
×
206
      mndReleaseRole(pMnode, pRole);
×
207
    } else {
208
      mndReleaseRole(pMnode, pRole);
×
209
      return 0;
×
210
    }
211
  } else {
212
    pNew = taosMemoryCalloc(1, sizeof(SRoleObj));
1,695,306✔
213
    if (pNew == NULL) {
1,695,306✔
214
      TAOS_RETURN(TSDB_CODE_OUT_OF_MEMORY);
×
215
    }
216
    tstrncpy(pNew->name, role, TSDB_ROLE_LEN);
1,695,306✔
217
    pNew->uid = mndGenerateUid(pNew->name, strlen(pNew->name));
1,695,306✔
218
    pNew->createdTime = taosGetTimestampMs();
1,695,306✔
219
    pNew->updateTime = pNew->createdTime;
1,695,306✔
220
    pNew->enable = 1;
1,695,306✔
221
    pNew->sys = 1;
1,695,306✔
222
    pNew->version = MND_ROLE_SYSROLE_VER;
1,695,306✔
223
  }
224

225
  TAOS_CHECK_EXIT(mndFillSystemRolePrivileges(pMnode, pNew, roleType));
1,695,306✔
226

227
  SSdbRaw *pRaw = mndRoleActionEncode(pNew);
1,695,306✔
228
  if (pRaw == NULL) goto _exit;
1,695,306✔
229
  TAOS_CHECK_EXIT(sdbSetRawStatus(pRaw, SDB_STATUS_READY));
1,695,306✔
230

231
  mInfo("role:%s, will be created when deploying, raw:%p", pNew->name, pRaw);
1,695,306✔
232

233
  STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_RETRY, TRN_CONFLICT_NOTHING, NULL, "create-role");
1,695,306✔
234
  if (pTrans == NULL) {
1,695,306✔
235
    sdbFreeRaw(pRaw);
×
236
    mError("role:%s, failed to create since %s", pNew->name, terrstr());
×
237
    TAOS_CHECK_EXIT(terrno);
×
238
  }
239
  mInfo("trans:%d, used to create role:%s", pTrans->id, pNew->name);
1,695,306✔
240

241
  if (mndTransAppendCommitlog(pTrans, pRaw) != 0) {
1,695,306✔
242
    mError("trans:%d, failed to commit redo log since %s", pTrans->id, terrstr());
×
243
    TAOS_CHECK_EXIT(terrno);
×
244
  }
245
  TAOS_CHECK_EXIT(sdbSetRawStatus(pRaw, SDB_STATUS_READY));
1,695,306✔
246

247
  if (mndTransPrepare(pMnode, pTrans) != 0) {
1,695,306✔
248
    mError("trans:%d, failed to prepare since %s", pTrans->id, terrstr());
×
249
    TAOS_CHECK_EXIT(terrno);
×
250
  }
251

252
_exit:
1,695,306✔
253
  if (pNew) {
1,695,306✔
254
    mndRoleFreeObj(pNew);
1,695,306✔
255
    taosMemoryFree(pNew);
1,695,306✔
256
  }
257
  mndTransDrop(pTrans);
1,695,306✔
258
  TAOS_RETURN(code);
1,695,306✔
259
}
260

261
static int32_t mndCreateDefaultRoles(SMnode *pMnode) {
282,551✔
262
  int32_t code = 0, lino = 0;
282,551✔
263
  TAOS_CHECK_EXIT(mndCreateDefaultRole(pMnode, TSDB_ROLE_SYSDBA, T_ROLE_SYSDBA));
282,551✔
264
  TAOS_CHECK_EXIT(mndCreateDefaultRole(pMnode, TSDB_ROLE_SYSSEC, T_ROLE_SYSSEC));
282,551✔
265
  TAOS_CHECK_EXIT(mndCreateDefaultRole(pMnode, TSDB_ROLE_SYSAUDIT, T_ROLE_SYSAUDIT));
282,551✔
266
  TAOS_CHECK_EXIT(mndCreateDefaultRole(pMnode, TSDB_ROLE_SYSAUDIT_LOG, T_ROLE_SYSAUDIT_LOG));
282,551✔
267
  TAOS_CHECK_EXIT(mndCreateDefaultRole(pMnode, TSDB_ROLE_SYSINFO_0, T_ROLE_SYSINFO_0));
282,551✔
268
  TAOS_CHECK_EXIT(mndCreateDefaultRole(pMnode, TSDB_ROLE_SYSINFO_1, T_ROLE_SYSINFO_1));
282,551✔
269
_exit:
282,551✔
270
  TAOS_RETURN(code);
282,551✔
271
}
272

273
static int32_t tSerializeSRoleObj(void *buf, int32_t bufLen, SRoleObj *pObj) {
12,505,080✔
274
  int32_t  code = 0, lino = 0;
12,505,080✔
275
  int32_t  tlen = 0;
12,505,080✔
276
  SEncoder encoder = {0};
12,505,080✔
277
  tEncoderInit(&encoder, buf, bufLen);
12,505,080✔
278

279
  TAOS_CHECK_EXIT(tStartEncode(&encoder));
12,505,080✔
280
  TAOS_CHECK_EXIT(tEncodeCStr(&encoder, pObj->name));
25,010,160✔
281
  TAOS_CHECK_EXIT(tEncodeI64v(&encoder, pObj->createdTime));
25,010,160✔
282
  TAOS_CHECK_EXIT(tEncodeI64v(&encoder, pObj->updateTime));
25,010,160✔
283
  TAOS_CHECK_EXIT(tEncodeI64v(&encoder, pObj->uid));
25,010,160✔
284
  TAOS_CHECK_EXIT(tEncodeI64v(&encoder, pObj->version));
25,010,160✔
285
  TAOS_CHECK_EXIT(tEncodeU8(&encoder, pObj->flag));
25,010,160✔
286

287
  TAOS_CHECK_EXIT(tSerializePrivSysObjPolicies(&encoder, &pObj->sysPrivs, pObj->objPrivs));
12,505,080✔
288

289
  TAOS_CHECK_EXIT(tSerializePrivTblPolicies(&encoder, pObj->selectTbs));
12,505,080✔
290
  TAOS_CHECK_EXIT(tSerializePrivTblPolicies(&encoder, pObj->insertTbs));
12,505,080✔
291
  TAOS_CHECK_EXIT(tSerializePrivTblPolicies(&encoder, pObj->updateTbs));
12,505,080✔
292
  TAOS_CHECK_EXIT(tSerializePrivTblPolicies(&encoder, pObj->deleteTbs));
12,505,080✔
293

294
  int32_t nParentRoles = taosHashGetSize(pObj->parentRoles);
12,505,080✔
295
  TAOS_CHECK_EXIT(tEncodeI32v(&encoder, nParentRoles));
12,505,080✔
296
  if (nParentRoles > 0) {
12,505,080✔
297
    void *pIter = NULL;
×
298
    while ((pIter = taosHashIterate(pObj->parentRoles, pIter))) {
×
299
      char *roleName = taosHashGetKey(pIter, NULL);
×
300
      TAOS_CHECK_EXIT(tEncodeCStr(&encoder, roleName));
×
301
    }
302
  }
303
  int32_t nSubRoles = taosHashGetSize(pObj->subRoles);
12,505,080✔
304
  TAOS_CHECK_EXIT(tEncodeI32v(&encoder, nSubRoles));
12,505,080✔
305
  if (nSubRoles > 0) {
12,505,080✔
306
    void *pIter = NULL;
×
307
    while ((pIter = taosHashIterate(pObj->subRoles, pIter))) {
×
308
      char *roleName = taosHashGetKey(pIter, NULL);
×
309
      TAOS_CHECK_EXIT(tEncodeCStr(&encoder, roleName));
×
310
    }
311
  }
312

313
  tEndEncode(&encoder);
12,505,080✔
314
  tlen = encoder.pos;
12,505,080✔
315
_exit:
12,505,080✔
316
  tEncoderClear(&encoder);
12,505,080✔
317
  if (code < 0) {
12,505,080✔
318
    mError("role:%s, %s failed at line %d since %s", pObj->name, __func__, lino, tstrerror(code));
×
319
    TAOS_RETURN(code);
×
320
  }
321

322
  return tlen;
12,505,080✔
323
}
324

325
void tFreePrivTblPolicies(SHashObj **ppHash) {
×
326
  if (*ppHash) {
×
327
    void *pIter = NULL;
×
328
    while ((pIter = taosHashIterate(*ppHash, pIter))) {
×
329
      int32_t vlen = taosHashGetValueSize(pIter);  // value is NULL for key 1.db.* or 1.*.*
×
330
      if (vlen == 0) continue;
×
331
      privTblPoliciesFree((SPrivTblPolicies *)pIter);
332
    }
333
    taosHashCleanup(*ppHash);
×
334
    *ppHash = NULL;
×
335
  }
336
}
×
337

338
static int32_t tDeserializeSRoleObj(void *buf, int32_t bufLen, SRoleObj *pObj) {
2,379,335✔
339
  int32_t  code = 0, lino = 0;
2,379,335✔
340
  SDecoder decoder = {0};
2,379,335✔
341
  tDecoderInit(&decoder, buf, bufLen);
2,379,335✔
342

343
  TAOS_CHECK_EXIT(tStartDecode(&decoder));
2,379,335✔
344

345
  TAOS_CHECK_EXIT(tDecodeCStrTo(&decoder, pObj->name));
2,379,335✔
346
  TAOS_CHECK_EXIT(tDecodeI64v(&decoder, &pObj->createdTime));
4,758,670✔
347
  TAOS_CHECK_EXIT(tDecodeI64v(&decoder, &pObj->updateTime));
4,758,670✔
348
  TAOS_CHECK_EXIT(tDecodeI64v(&decoder, &pObj->uid));
4,758,670✔
349
  TAOS_CHECK_EXIT(tDecodeI64v(&decoder, &pObj->version));
4,758,670✔
350
  TAOS_CHECK_EXIT(tDecodeU8(&decoder, &pObj->flag));
4,758,670✔
351

352
  TAOS_CHECK_EXIT(tDeserializePrivSysObjPolicies(&decoder, &pObj->sysPrivs, &pObj->objPrivs));
2,379,335✔
353

354
  TAOS_CHECK_EXIT(tDeserializePrivTblPolicies(&decoder, &pObj->selectTbs));
2,379,335✔
355
  TAOS_CHECK_EXIT(tDeserializePrivTblPolicies(&decoder, &pObj->insertTbs));
2,379,335✔
356
  TAOS_CHECK_EXIT(tDeserializePrivTblPolicies(&decoder, &pObj->updateTbs));
2,379,335✔
357
  TAOS_CHECK_EXIT(tDeserializePrivTblPolicies(&decoder, &pObj->deleteTbs));
2,379,335✔
358

359
  char    roleName[TSDB_ROLE_LEN] = {0};
2,379,335✔
360
  int32_t nParentRoles = 0;
2,379,335✔
361
  TAOS_CHECK_EXIT(tDecodeI32v(&decoder, &nParentRoles));
2,379,335✔
362
  if (nParentRoles > 0) {
2,379,335✔
363
    if (!(pObj->parentRoles =
×
364
              taosHashInit(nParentRoles, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_ENTRY_LOCK))) {
×
365
      TAOS_CHECK_EXIT(terrno);
×
366
    }
367
    for (int32_t i = 0; i < nParentRoles; ++i) {
×
368
      TAOS_CHECK_EXIT(tDecodeCStrTo(&decoder, roleName));
×
369
      TAOS_CHECK_EXIT(taosHashPut(pObj->parentRoles, roleName, strlen(roleName) + 1, NULL, 0));
×
370
    }
371
  }
372
  int32_t nSubRoles = 0;
2,379,335✔
373
  TAOS_CHECK_EXIT(tDecodeI32v(&decoder, &nSubRoles));
2,379,335✔
374
  if (nSubRoles > 0) {
2,379,335✔
375
    if (!(pObj->subRoles =
×
376
              taosHashInit(nSubRoles, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_ENTRY_LOCK))) {
×
377
      TAOS_CHECK_EXIT(terrno);
×
378
    }
379
    for (int32_t i = 0; i < nSubRoles; ++i) {
×
380
      TAOS_CHECK_EXIT(tDecodeCStrTo(&decoder, roleName));
×
381
      TAOS_CHECK_EXIT(taosHashPut(pObj->subRoles, roleName, strlen(roleName) + 1, NULL, 0));
×
382
    }
383
  }
384

385
_exit:
2,379,335✔
386
  tEndDecode(&decoder);
2,379,335✔
387
  tDecoderClear(&decoder);
2,379,335✔
388
  if (code < 0) {
2,379,335✔
389
    mError("role, %s failed at line %d since %s, row:%p", __func__, lino, tstrerror(code), pObj);
×
390
  }
391
  TAOS_RETURN(code);
2,379,335✔
392
}
393

394
SSdbRaw *mndRoleActionEncode(SRoleObj *pObj) {
6,252,540✔
395
  int32_t  code = 0, lino = 0;
6,252,540✔
396
  void    *buf = NULL;
6,252,540✔
397
  SSdbRaw *pRaw = NULL;
6,252,540✔
398
  int32_t  tlen = tSerializeSRoleObj(NULL, 0, pObj);
6,252,540✔
399
  if (tlen < 0) {
6,252,540✔
400
    TAOS_CHECK_EXIT(tlen);
×
401
  }
402
  int32_t size = sizeof(int32_t) + tlen;
6,252,540✔
403
  if (!(pRaw = sdbAllocRaw(SDB_ROLE, MND_ROLE_VER_NUMBER, size))) {
6,252,540✔
404
    TAOS_CHECK_EXIT(terrno);
×
405
  }
406
  if (!(buf = taosMemoryMalloc(tlen))) {
6,252,540✔
407
    TAOS_CHECK_EXIT(terrno);
×
408
  }
409
  if ((tlen = tSerializeSRoleObj(buf, tlen, pObj)) < 0) {
6,252,540✔
410
    TAOS_CHECK_EXIT(tlen);
×
411
  }
412

413
  int32_t dataPos = 0;
6,252,540✔
414
  SDB_SET_INT32(pRaw, dataPos, tlen, _exit);
6,252,540✔
415
  SDB_SET_BINARY(pRaw, dataPos, buf, tlen, _exit);
6,252,540✔
416
  SDB_SET_DATALEN(pRaw, dataPos, _exit);
6,252,540✔
417
_exit:
6,252,540✔
418
  taosMemoryFreeClear(buf);
6,252,540✔
419
  if (code != TSDB_CODE_SUCCESS) {
6,252,540✔
420
    terrno = code;
×
421
    mError("role, failed at line %d to encode to raw:%p since %s", lino, pRaw, tstrerror(code));
×
422
    sdbFreeRaw(pRaw);
×
423
    return NULL;
×
424
  }
425
  mTrace("role, encode to raw:%p, row:%p", pRaw, pObj);
6,252,540✔
426
  return pRaw;
6,252,540✔
427
}
428

429
static SSdbRow *mndRoleActionDecode(SSdbRaw *pRaw) {
2,379,335✔
430
  int32_t   code = 0, lino = 0;
2,379,335✔
431
  SSdbRow  *pRow = NULL;
2,379,335✔
432
  SRoleObj *pObj = NULL;
2,379,335✔
433
  void     *buf = NULL;
2,379,335✔
434

435
  int8_t sver = 0;
2,379,335✔
436
  TAOS_CHECK_EXIT(sdbGetRawSoftVer(pRaw, &sver));
2,379,335✔
437

438
  if (sver != MND_ROLE_VER_NUMBER) {
2,379,335✔
439
    mError("role, read invalid ver, data ver: %d, curr ver: %d", sver, MND_ROLE_VER_NUMBER);
×
440
    TAOS_CHECK_EXIT(TSDB_CODE_SDB_INVALID_DATA_VER);
×
441
  }
442

443
  if (!(pRow = sdbAllocRow(sizeof(SRoleObj)))) {
2,379,335✔
444
    TAOS_CHECK_EXIT(terrno);
×
445
  }
446

447
  if (!(pObj = sdbGetRowObj(pRow))) {
2,379,335✔
448
    TAOS_CHECK_EXIT(terrno);
×
449
  }
450

451
  int32_t tlen;
2,370,857✔
452
  int32_t dataPos = 0;
2,379,335✔
453
  SDB_GET_INT32(pRaw, dataPos, &tlen, _exit);
2,379,335✔
454
  if (!(buf = taosMemoryMalloc(tlen + 1))) {
2,379,335✔
455
    TAOS_CHECK_EXIT(terrno);
×
456
  }
457
  SDB_GET_BINARY(pRaw, dataPos, buf, tlen, _exit);
2,379,335✔
458
  TAOS_CHECK_EXIT(tDeserializeSRoleObj(buf, tlen, pObj));
2,379,335✔
459
  if (pObj->version < MND_ROLE_SYSROLE_VER) {
2,379,335✔
460
  }
461
  taosInitRWLatch(&pObj->lock);
2,379,335✔
462
_exit:
2,379,335✔
463
  taosMemoryFreeClear(buf);
2,379,335✔
464
  if (code != TSDB_CODE_SUCCESS) {
2,379,335✔
465
    terrno = code;
×
466
    mError("role, failed at line %d to decode from raw:%p since %s", lino, pRaw, tstrerror(code));
×
467
    mndRoleFreeObj(pObj);
×
468
    taosMemoryFreeClear(pRow);
×
469
    return NULL;
×
470
  }
471
  mTrace("role, decode from raw:%p, row:%p", pRaw, pObj);
2,379,335✔
472
  return pRow;
2,379,335✔
473
}
474

475
void mndRoleFreeObj(SRoleObj *pObj) {
5,023,100✔
476
  if (pObj) {
5,023,100✔
477
    taosHashCleanup(pObj->objPrivs);
5,023,100✔
478
    taosHashCleanup(pObj->selectTbs);
5,023,100✔
479
    taosHashCleanup(pObj->insertTbs);
5,023,100✔
480
    taosHashCleanup(pObj->updateTbs);
5,023,100✔
481
    taosHashCleanup(pObj->deleteTbs);
5,023,100✔
482
    taosHashCleanup(pObj->parentRoles);
5,023,100✔
483
    taosHashCleanup(pObj->subRoles);
5,023,100✔
484
    pObj->objPrivs = NULL;
5,023,100✔
485
    pObj->selectTbs = NULL;
5,023,100✔
486
    pObj->insertTbs = NULL;
5,023,100✔
487
    pObj->updateTbs = NULL;
5,023,100✔
488
    pObj->deleteTbs = NULL;
5,023,100✔
489
    pObj->parentRoles = NULL;
5,023,100✔
490
    pObj->subRoles = NULL;
5,023,100✔
491
  }
492
}
5,023,100✔
493

494
static int32_t mndRoleActionInsert(SSdb *pSdb, SRoleObj *pObj) {
2,378,731✔
495
  mTrace("role:%s, perform insert action, row:%p", pObj->name, pObj);
2,378,731✔
496
  return 0;
2,378,731✔
497
}
498

499
static int32_t mndRoleActionDelete(SSdb *pSdb, SRoleObj *pObj) {
2,379,077✔
500
  mTrace("role:%s, perform delete action, row:%p", pObj->name, pObj);
2,379,077✔
501
  mndRoleFreeObj(pObj);
2,379,077✔
502
  return 0;
2,379,077✔
503
}
504

505
static int32_t mndRoleActionUpdate(SSdb *pSdb, SRoleObj *pOld, SRoleObj *pNew) {
604✔
506
  mTrace("role:%s, perform update action, old row:%p new row:%p", pOld->name, pOld, pNew);
604✔
507
  taosWLockLatch(&pOld->lock);
604✔
508
  pOld->updateTime = pNew->updateTime;
604✔
509
  pOld->sysPrivs = pNew->sysPrivs;
604✔
510
  pOld->version = pNew->version;
604✔
511
  pOld->flag = pNew->flag;
604✔
512
  TSWAP(pOld->objPrivs, pNew->objPrivs);
604✔
513
  TSWAP(pOld->selectTbs, pNew->selectTbs);
604✔
514
  TSWAP(pOld->insertTbs, pNew->insertTbs);
604✔
515
  TSWAP(pOld->updateTbs, pNew->updateTbs);
604✔
516
  TSWAP(pOld->deleteTbs, pNew->deleteTbs);
604✔
517
  TSWAP(pOld->parentRoles, pNew->parentRoles);
604✔
518
  TSWAP(pOld->subRoles, pNew->subRoles);
604✔
519
  taosWUnLockLatch(&pOld->lock);
604✔
520
  return 0;
604✔
521
}
522

523
int32_t mndAcquireRole(SMnode *pMnode, const char *roleName, SRoleObj **ppRole) {
80,343,302✔
524
  int32_t code = 0;
80,343,302✔
525
  SSdb   *pSdb = pMnode->pSdb;
80,343,302✔
526

527
  *ppRole = sdbAcquire(pSdb, SDB_ROLE, roleName);
80,343,302✔
528
  if (*ppRole == NULL) {
80,343,302✔
529
    if (terrno == TSDB_CODE_SDB_OBJ_NOT_THERE) {
2,698,918✔
530
      code = TSDB_CODE_MND_ROLE_NOT_EXIST;
2,698,918✔
531
    } else {
532
      code = TSDB_CODE_MND_ROLE_NOT_AVAILABLE;
×
533
    }
534
  }
535
  TAOS_RETURN(code);
80,343,302✔
536
}
537

538
void mndReleaseRole(SMnode *pMnode, SRoleObj *pRole) {
78,648,619✔
539
  SSdb *pSdb = pMnode->pSdb;
78,648,619✔
540
  sdbRelease(pSdb, pRole);
78,648,619✔
541
}
78,649,225✔
542

543
static int32_t mndCreateRole(SMnode *pMnode, char *acct, SCreateRoleReq *pCreate, SRpcMsg *pReq) {
151✔
544
  int32_t  code = 0, lino = 0;
151✔
545
  SRoleObj obj = {0};
151✔
546

547
  tstrncpy(obj.name, pCreate->name, TSDB_ROLE_LEN);
151✔
548
  obj.createdTime = taosGetTimestampMs();
151✔
549
  obj.updateTime = obj.createdTime;
151✔
550
  obj.uid = mndGenerateUid(obj.name, strlen(obj.name));
151✔
551
  obj.version = 1;
151✔
552
  obj.enable = 1;
151✔
553
  obj.sys = 0;
151✔
554
  // TODO: assign default privileges
555

556
  STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_ROLLBACK, TRN_CONFLICT_ROLE, pReq, "create-role");
151✔
557
  if (pTrans == NULL) {
151✔
558
    TAOS_CHECK_EXIT(terrno);
×
559
  }
560
  mInfo("trans:%d, used to create role:%s", pTrans->id, pCreate->name);
151✔
561

562
  SSdbRaw *pCommitRaw = mndRoleActionEncode(&obj);
151✔
563
  if (pCommitRaw == NULL || mndTransAppendCommitlog(pTrans, pCommitRaw) != 0) {
151✔
564
    mError("trans:%d, failed to commit redo log since %s", pTrans->id, terrstr());
×
565
    TAOS_CHECK_EXIT(terrno);
×
566
  }
567
  TAOS_CHECK_EXIT(sdbSetRawStatus(pCommitRaw, SDB_STATUS_READY));
151✔
568
  TAOS_CHECK_EXIT(mndTransPrepare(pMnode, pTrans));
151✔
569
_exit:
151✔
570
  if (code != 0 && code != TSDB_CODE_ACTION_IN_PROGRESS) {
151✔
571
    mError("role:%s, failed at line %d to create role, since %s", obj.name, lino, tstrerror(code));
×
572
  }
573
  mndRoleFreeObj(&obj);
151✔
574
  mndTransDrop(pTrans);
151✔
575
  TAOS_RETURN(code);
151✔
576
}
577

578
static int32_t mndProcessCreateRoleReq(SRpcMsg *pReq) {
151✔
579
  SMnode        *pMnode = pReq->info.node;
151✔
580
  int32_t        code = 0, lino = 0;
151✔
581
  SRoleObj      *pRole = NULL;
151✔
582
  SUserObj      *pOperUser = NULL;
151✔
583
  SUserObj      *pUser = NULL;
151✔
584
  SCreateRoleReq createReq = {0};
151✔
585
  int64_t        tss = taosGetTimestampMs();
151✔
586

587
  if (tDeserializeSCreateRoleReq(pReq->pCont, pReq->contLen, &createReq) != 0) {
151✔
588
    TAOS_CHECK_EXIT(TSDB_CODE_INVALID_MSG);
×
589
  }
590
  if ((code = mndAcquireRole(pMnode, createReq.name, &pRole)) == 0) {
151✔
591
    if (createReq.ignoreExists) {
×
592
      mInfo("role:%s, already exist, ignore exist is set", createReq.name);
×
593
      goto _exit;
×
594
    } else {
595
      TAOS_CHECK_EXIT(TSDB_CODE_MND_ROLE_ALREADY_EXIST);
×
596
    }
597
  } else {
598
    if ((code = terrno) == TSDB_CODE_MND_ROLE_NOT_EXIST) {
151✔
599
      // continue
600
    } else {
601
      goto _exit;
×
602
    }
603
  }
604
  code = mndAcquireUser(pMnode, RPC_MSG_USER(pReq), &pOperUser);
151✔
605
  if (pOperUser == NULL) {
151✔
606
    TAOS_CHECK_EXIT(TSDB_CODE_MND_NO_USER_FROM_CONN);
×
607
  }
608

609
  mInfo("role:%s, start to create by %s", createReq.name, pOperUser->user);
151✔
610

611
  // TAOS_CHECK_EXIT(mndCheckOperPrivilege(pMnode, RPC_MSG_USER(pReq), MND_OPER_CREATE_ROLE));
612
  TAOS_CHECK_EXIT(mndCheckSysObjPrivilege(pMnode, pOperUser, PRIV_ROLE_CREATE, 0, 0, NULL, NULL));
151✔
613

614
  if (createReq.name[0] == 0) {
151✔
615
    TAOS_CHECK_EXIT(TSDB_CODE_MND_ROLE_INVALID_FORMAT);
×
616
  }
617
  code = mndAcquireUser(pMnode, createReq.name, &pUser);
151✔
618
  if (pUser != NULL) {
151✔
619
    TAOS_CHECK_EXIT(TSDB_CODE_MND_USER_ALREADY_EXIST);
×
620
  }
621
  TAOS_CHECK_EXIT(mndCreateRole(pMnode, pOperUser->acct, &createReq, pReq));
151✔
622
  if (code == 0) code = TSDB_CODE_ACTION_IN_PROGRESS;
151✔
623

624
  if (tsAuditLevel >= AUDIT_LEVEL_CLUSTER) {
151✔
625
    char    detail[128] = {0};
151✔
626
    int32_t len = snprintf(detail, sizeof(detail), "operUser:%s", pOperUser->user);
151✔
627

628
    int64_t tse = taosGetTimestampMs();
151✔
629
    double  duration = (double)(tse - tss);
151✔
630
    duration = duration / 1000;
151✔
631
    auditRecord(pReq, pMnode->clusterId, "createRole", "", createReq.name, detail, strlen(detail), duration, 0);
151✔
632
  }
633
_exit:
151✔
634
  if (code < 0 && code != TSDB_CODE_ACTION_IN_PROGRESS) {
151✔
635
    mError("role:%s, failed to create at line %d since %s", createReq.name, lino, tstrerror(code));
×
636
  }
637
  mndReleaseUser(pMnode, pUser);
151✔
638
  mndReleaseUser(pMnode, pOperUser);
151✔
639
  mndReleaseRole(pMnode, pRole);
151✔
640
  tFreeSCreateRoleReq(&createReq);
151✔
641
  TAOS_RETURN(code);
151✔
642
}
643

644
static int32_t mndDropParentRole(SMnode *pMnode, STrans *pTrans, SRoleObj *pObj) {  // TODO
×
645
  return 0;
×
646
}
647

648
static int32_t mndDropRole(SMnode *pMnode, SRpcMsg *pReq, SRoleObj *pObj) {
×
649
  int32_t code = 0, lino = 0;
×
650
  STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_ROLLBACK, TRN_CONFLICT_ROLE, pReq, "drop-role");
×
651
  if (pTrans == NULL) {
×
652
    mError("role:%s, failed to drop since %s", pObj->name, terrstr());
×
653
    TAOS_CHECK_EXIT(terrno);
×
654
  }
655
  mInfo("trans:%d, used to drop role:%s", pTrans->id, pObj->name);
×
656

657
  SSdbRaw *pCommitRaw = mndRoleActionEncode(pObj);
×
658
  if (pCommitRaw == NULL || mndTransAppendCommitlog(pTrans, pCommitRaw) != 0) {
×
659
    mError("trans:%d, failed to append commit log since %s", pTrans->id, terrstr());
×
660
    TAOS_CHECK_EXIT(terrno);
×
661
  }
662
  TAOS_CHECK_EXIT(sdbSetRawStatus(pCommitRaw, SDB_STATUS_DROPPED));
×
663
  TAOS_CHECK_EXIT(mndDropParentRole(pMnode, pTrans, pObj));
×
664
  TAOS_CHECK_EXIT(mndUserDropRole(pMnode, pTrans, pObj));
×
665
  TAOS_CHECK_EXIT(mndTransPrepare(pMnode, pTrans));
×
666
  mndSetRoleLastUpd(taosGetTimestampMs());
×
667
_exit:
×
668
  if (code != 0 && code != TSDB_CODE_ACTION_IN_PROGRESS) {
×
669
    mError("role:%s, failed to drop at line:%d since %s", pObj->name, lino, tstrerror(code));
×
670
  }
671
  mndTransDrop(pTrans);
×
672
  TAOS_RETURN(0);
×
673
}
674

675
static int32_t mndProcessDropRoleReq(SRpcMsg *pReq) {
×
676
  SMnode      *pMnode = pReq->info.node;
×
677
  int32_t      code = 0, lino = 0;
×
678
  SRoleObj    *pObj = NULL;
×
679
  SUserObj    *pOperUser = NULL;
×
680
  SDropRoleReq dropReq = {0};
×
681
  int64_t      tss = taosGetTimestampMs();
×
682

683
  TAOS_CHECK_EXIT(tDeserializeSDropRoleReq(pReq->pCont, pReq->contLen, &dropReq));
×
684
  code = mndAcquireUser(pMnode, RPC_MSG_USER(pReq), &pOperUser);
×
685
  if (pOperUser == NULL) {
×
686
    TAOS_CHECK_EXIT(TSDB_CODE_MND_NO_USER_FROM_CONN);
×
687
  }
688
  mInfo("role:%s, start to drop", dropReq.name);
×
689
  // TAOS_CHECK_EXIT(mndCheckOperPrivilege(pMnode, RPC_MSG_USER(pReq), MND_OPER_DROP_ROLE));
690
  TAOS_CHECK_EXIT(mndCheckSysObjPrivilege(pMnode, pOperUser, PRIV_ROLE_CREATE, 0, 0, NULL, NULL));
×
691

692
  if (dropReq.name[0] == 0) {
×
693
    TAOS_CHECK_EXIT(TSDB_CODE_MND_ROLE_INVALID_FORMAT);
×
694
  }
695

696
  TAOS_CHECK_EXIT(mndAcquireRole(pMnode, dropReq.name, &pObj));
×
697

698
  TAOS_CHECK_EXIT(mndDropRole(pMnode, pReq, pObj));
×
699
  if (code == 0) code = TSDB_CODE_ACTION_IN_PROGRESS;
×
700

701
  if (tsAuditLevel >= AUDIT_LEVEL_CLUSTER) {
×
702
    int64_t tse = taosGetTimestampMs();
×
703
    double  duration = (double)(tse - tss);
×
704
    duration = duration / 1000;
×
705
    auditRecord(pReq, pMnode->clusterId, "dropRole", "", dropReq.name, dropReq.sql, dropReq.sqlLen, duration, 0);
×
706
  }
707
_exit:
×
708
  if (code < 0 && code != TSDB_CODE_ACTION_IN_PROGRESS) {
×
709
    mError("role:%s, failed to drop at line %d since %s", dropReq.name, lino, tstrerror(code));
×
710
  }
711
  mndReleaseRole(pMnode, pObj);
×
712
  mndReleaseUser(pMnode, pOperUser);
×
713
  tFreeSDropRoleReq(&dropReq);
×
714
  TAOS_RETURN(code);
×
715
}
716

717
static int32_t mndAlterRole(SMnode *pMnode, SRpcMsg *pReq, SRoleObj *pObj) {
604✔
718
  int32_t code = 0, lino = 0;
604✔
719
  STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_ROLLBACK, TRN_CONFLICT_ROLE, pReq, "alter-role");
604✔
720
  if (pTrans == NULL) {
604✔
721
    mError("role:%s, failed to alter since %s", pObj->name, terrstr());
×
722
    TAOS_CHECK_EXIT(terrno);
×
723
  }
724
  mInfo("trans:%d, used to alter role:%s", pTrans->id, pObj->name);
604✔
725

726
  SSdbRaw *pCommitRaw = mndRoleActionEncode(pObj);
604✔
727
  if (pCommitRaw == NULL || mndTransAppendCommitlog(pTrans, pCommitRaw) != 0) {
604✔
728
    mError("trans:%d, failed to append commit log since %s", pTrans->id, terrstr());
×
729
    TAOS_CHECK_EXIT(terrno);
×
730
  }
731
  TAOS_CHECK_EXIT(sdbSetRawStatus(pCommitRaw, SDB_STATUS_READY));
604✔
732
  TAOS_CHECK_EXIT(mndTransPrepare(pMnode, pTrans));
604✔
733
_exit:
604✔
734
  if (code != 0 && code != TSDB_CODE_ACTION_IN_PROGRESS) {
604✔
735
    mError("role:%s, failed to alter at line:%d since %s", pObj->name, lino, tstrerror(code));
×
736
  }
737
  mndTransDrop(pTrans);
604✔
738
  TAOS_RETURN(0);
604✔
739
}
740

741
int32_t mndRoleDupObj(SRoleObj *pOld, SRoleObj *pNew) {
604✔
742
  int32_t code = 0, lino = 0;
604✔
743
  snprintf(pNew->name, TSDB_ROLE_LEN, "%s", pOld->name);
604✔
744
  pNew->createdTime = pOld->createdTime;
604✔
745
  pNew->uid = pOld->uid;
604✔
746
  pNew->version = pOld->version + 1;
604✔
747
  pNew->flag = pOld->flag;
604✔
748
  pNew->updateTime = taosGetTimestampMs();
604✔
749
  pNew->sysPrivs = pOld->sysPrivs;
604✔
750

751
  taosRLockLatch(&pOld->lock);
604✔
752
  TAOS_CHECK_EXIT(mndDupPrivObjHash(pOld->objPrivs, &pNew->objPrivs));
604✔
753
  TAOS_CHECK_EXIT(mndDupPrivTblHash(pOld->selectTbs, &pNew->selectTbs, false));
604✔
754
  TAOS_CHECK_EXIT(mndDupPrivTblHash(pOld->insertTbs, &pNew->insertTbs, false));
604✔
755
  TAOS_CHECK_EXIT(mndDupPrivTblHash(pOld->updateTbs, &pNew->updateTbs, false));
604✔
756
  TAOS_CHECK_EXIT(mndDupPrivTblHash(pOld->deleteTbs, &pNew->deleteTbs, false));
604✔
757
  // TODO: alterTbs?
758
  TAOS_CHECK_EXIT(mndDupRoleHash(pOld->parentRoles, &pNew->parentRoles));
604✔
759
  TAOS_CHECK_EXIT(mndDupRoleHash(pOld->subRoles, &pNew->subRoles));
604✔
760
_exit:
604✔
761
  taosRUnLockLatch(&pOld->lock);
604✔
762
  if (code < 0) {
604✔
763
    mError("role:%s, failed at line %d to dup obj since %s", pOld->name, lino, tstrerror(code));
×
764
  }
765
  TAOS_RETURN(code);
604✔
766
}
767

768
static bool mndIsRoleChanged(SRoleObj *pOld, SAlterRoleReq *pAlterReq) {
604✔
769
  switch (pAlterReq->alterType) {
604✔
770
    case TSDB_ALTER_ROLE_LOCK: {
×
771
      if ((pAlterReq->lock && !pOld->enable) || (!pAlterReq->lock && pOld->enable)) {
×
772
        return false;
×
773
      }
774
      break;
×
775
    }
776
    default:
604✔
777
      break;
604✔
778
  }
779
  return true;
604✔
780
}
781

782
#ifdef TD_ENTERPRISE
783
extern int32_t mndAlterRoleInfo(SMnode *pMnode, SUserObj *pOperUser, SRoleObj *pOld, SRoleObj *pNew,
784
                                SAlterRoleReq *pAlterReq);
785
#endif
786

787
static int32_t mndProcessAlterRoleReq(SRpcMsg *pReq) {
948,566✔
788
  int32_t       code = 0, lino = 0;
948,566✔
789
  SMnode       *pMnode = pReq->info.node;
948,566✔
790
  SRoleObj     *pObj = NULL;
948,566✔
791
  SRoleObj      newObj = {0};
948,566✔
792
  SUserObj     *pOperUser = NULL;
948,566✔
793
  SAlterRoleReq alterReq = {0};
948,566✔
794
  bool          alterUser = false;
948,566✔
795
  int64_t       tss = taosGetTimestampMs();
948,566✔
796

797
  TAOS_CHECK_EXIT(tDeserializeSAlterRoleReq(pReq->pCont, pReq->contLen, &alterReq));
948,566✔
798

799
  mInfo("role:%s, start to alter, flag:%u", alterReq.principal, alterReq.flag);
948,566✔
800
  TAOS_CHECK_EXIT(mndCheckOperPrivilege(pMnode, RPC_MSG_USER(pReq), RPC_MSG_TOKEN(pReq), MND_OPER_ALTER_ROLE));
948,566✔
801

802
  TAOS_CHECK_EXIT(mndAcquireUser(pMnode, RPC_MSG_USER(pReq), &pOperUser));
948,566✔
803

804
  if (alterReq.principal[0] == 0) {
948,566✔
805
    TAOS_CHECK_EXIT(TSDB_CODE_MND_ROLE_INVALID_FORMAT);
×
806
  }
807

808
  if (mndAcquireRole(pMnode, alterReq.principal, &pObj) == 0) {
948,566✔
809
    if (alterReq.alterType == TSDB_ALTER_ROLE_ROLE) {
604✔
810
      TAOS_CHECK_EXIT(TSDB_CODE_OPS_NOT_SUPPORT);  // not support grant role to role yet
×
811
    }
812
  } else {
813
    if (alterReq.alterType == TSDB_ALTER_ROLE_LOCK) {
947,962✔
814
      TAOS_CHECK_EXIT(terrno);
×
815
    }
816
    alterUser = true;
947,962✔
817
  }
818

819
  if (alterUser) {
948,566✔
820
    mInfo("role:%s, not exist, will alter user instead", alterReq.principal);
947,962✔
821
    TAOS_CHECK_EXIT(mndAlterUserFromRole(pReq, pOperUser, &alterReq));
947,962✔
822
  } else if (mndIsRoleChanged(pObj, &alterReq)) {
604✔
823
    TAOS_CHECK_EXIT(mndRoleDupObj(pObj, &newObj));
604✔
824
#ifdef TD_ENTERPRISE
825
    TAOS_CHECK_EXIT(mndAlterRoleInfo(pMnode, pOperUser, pObj, &newObj, &alterReq));
604✔
826
#endif
827
    TAOS_CHECK_EXIT(mndAlterRole(pMnode, pReq, &newObj));
604✔
828
    if (code == 0) code = TSDB_CODE_ACTION_IN_PROGRESS;
604✔
829
    mndSetRoleLastUpd(taosGetTimestampMs());
604✔
830
  }
831

832
  if (tsAuditLevel >= AUDIT_LEVEL_CLUSTER) {
755✔
833
    int64_t tse = taosGetTimestampMs();
755✔
834
    double  duration = (double)(tse - tss);
755✔
835
    duration = duration / 1000;
755✔
836
    auditRecord(pReq, pMnode->clusterId, "alterRole", "", alterReq.principal, alterReq.sql, alterReq.sqlLen, duration,
755✔
837
                0);
838
  }
839
_exit:
948,566✔
840
  if (code < 0 && code != TSDB_CODE_ACTION_IN_PROGRESS) {
948,566✔
841
    mError("role:%s, failed to alter at line %d since %s", alterReq.principal, lino, tstrerror(code));
1,397✔
842
  }
843
  mndReleaseUser(pMnode, pOperUser);
948,566✔
844
  mndReleaseRole(pMnode, pObj);
948,566✔
845
  mndRoleFreeObj(&newObj);
948,566✔
846
  tFreeSAlterRoleReq(&alterReq);
948,566✔
847
  TAOS_RETURN(code);
948,566✔
848
}
849

850
static int32_t mndProcessGetRoleAuthReq(SRpcMsg *pReq) { TAOS_RETURN(0); }
×
851

852
static int32_t mndRetrieveRoles(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pBlock, int32_t rows) {
151✔
853
  SMnode   *pMnode = pReq->info.node;
151✔
854
  SSdb     *pSdb = pMnode->pSdb;
151✔
855
  int32_t   code = 0, lino = 0;
151✔
856
  int32_t   numOfRows = 0;
151✔
857
  SRoleObj *pObj = NULL;
151✔
858
  int32_t   cols = 0;
151✔
859
  int32_t   bufSize = TSDB_MAX_SUBROLE * TSDB_ROLE_LEN + VARSTR_HEADER_SIZE;
151✔
860
  char      tBuf[TSDB_MAX_SUBROLE * TSDB_ROLE_LEN + VARSTR_HEADER_SIZE] = {0};
151✔
861

862
  while (numOfRows < rows) {
1,208✔
863
    pShow->pIter = sdbFetch(pSdb, SDB_ROLE, pShow->pIter, (void **)&pObj);
1,208✔
864
    if (pShow->pIter == NULL) break;
1,208✔
865

866
    cols = 0;
1,057✔
867
    SColumnInfoData *pColInfo = taosArrayGet(pBlock->pDataBlock, cols);
1,057✔
868
    char             name[TSDB_ROLE_LEN + VARSTR_HEADER_SIZE] = {0};
1,057✔
869
    STR_WITH_MAXSIZE_TO_VARSTR(name, pObj->name, pShow->pMeta->pSchemas[cols].bytes);
1,057✔
870
    COL_DATA_SET_VAL_GOTO((const char *)name, false, pObj, pShow->pIter, _exit);
1,057✔
871

872
    if ((pColInfo = taosArrayGet(pBlock->pDataBlock, ++cols))) {
1,057✔
873
      int8_t enable = pObj->enable ? 1 : 0;
1,057✔
874
      COL_DATA_SET_VAL_GOTO((const char *)&enable, false, pObj, pShow->pIter, _exit);
1,057✔
875
    }
876

877
    if ((pColInfo = taosArrayGet(pBlock->pDataBlock, ++cols))) {
1,057✔
878
      COL_DATA_SET_VAL_GOTO((const char *)&pObj->createdTime, false, pObj, pShow->pIter, _exit);
1,057✔
879
    }
880
    if ((pColInfo = taosArrayGet(pBlock->pDataBlock, ++cols))) {
1,057✔
881
      COL_DATA_SET_VAL_GOTO((const char *)&pObj->updateTime, false, pObj, pShow->pIter, _exit);
1,057✔
882
    }
883
    if ((pColInfo = taosArrayGet(pBlock->pDataBlock, ++cols))) {
1,057✔
884
      char *roleType = pObj->sys ? "SYSTEM" : "USER";
1,057✔
885
      STR_WITH_MAXSIZE_TO_VARSTR(tBuf, roleType, pShow->pMeta->pSchemas[cols].bytes);
1,057✔
886
      COL_DATA_SET_VAL_GOTO((const char *)tBuf, false, pObj, pShow->pIter, _exit);
1,057✔
887
    }
888

889
    if ((pColInfo = taosArrayGet(pBlock->pDataBlock, ++cols))) {
1,057✔
890
      void  *pIter = NULL;
1,057✔
891
      size_t klen = 0, tlen = 0;
1,057✔
892
      char  *pBuf = POINTER_SHIFT(tBuf, VARSTR_HEADER_SIZE);
1,057✔
893
      while ((pIter = taosHashIterate(pObj->subRoles, pIter))) {
1,057✔
894
        char *roleName = taosHashGetKey(pIter, &klen);
×
895
        tlen += snprintf(pBuf + tlen, bufSize - tlen, "%s,", roleName);
×
896
      }
897
      if (tlen > 0) {
1,057✔
898
        pBuf[tlen - 1] = 0;  // remove last ','
×
899
      } else {
900
        pBuf[0] = 0;
1,057✔
901
      }
902
      varDataSetLen(tBuf, tlen);
1,057✔
903
      COL_DATA_SET_VAL_GOTO((const char *)tBuf, false, pObj, pShow->pIter, _exit);
1,057✔
904
    }
905
    numOfRows++;
1,057✔
906
    sdbRelease(pSdb, pObj);
1,057✔
907
  }
908
  pShow->numOfRows += numOfRows;
151✔
909
_exit:
151✔
910
  if (code < 0) {
151✔
911
    uError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
912
    TAOS_RETURN(code);
×
913
  }
914
  return numOfRows;
151✔
915
}
916

917
static void mndCancelGetNextRole(SMnode *pMnode, void *pIter) {
×
918
  SSdb *pSdb = pMnode->pSdb;
×
919
  sdbCancelFetchByType(pSdb, pIter, SDB_ROLE);
×
920
}
×
921

922
static int32_t mndRetrievePrivileges(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pBlock, int32_t rows) {
755✔
923
  int32_t   code = 0, lino = 0;
755✔
924
  SMnode   *pMnode = pReq->info.node;
755✔
925
  SSdb     *pSdb = pMnode->pSdb;
755✔
926
  int32_t   numOfRows = 0;
755✔
927
  int32_t   cols = 0;
755✔
928
  SRoleObj *pObj = NULL;
755✔
929
  char     *pBuf = NULL, *qBuf = NULL;
755✔
930
  char     *sql = NULL;
755✔
931
  char      roleName[TSDB_ROLE_LEN + VARSTR_HEADER_SIZE] = {0};
755✔
932
  int32_t   bufSize = TSDB_PRIVILEDGE_CONDITION_LEN + VARSTR_HEADER_SIZE;
755✔
933

934
  bool fetchNextInstance = pShow->restore ? false : true;
755✔
935
  pShow->restore = false;
755✔
936

937
  while (numOfRows < rows) {
6,040✔
938
    if (fetchNextInstance) {
6,040✔
939
      pShow->pIter = sdbFetch(pSdb, SDB_ROLE, pShow->pIter, (void **)&pObj);
6,040✔
940
      if (pShow->pIter == NULL) break;
6,040✔
941
    } else {
942
      fetchNextInstance = true;
×
943
      void *pKey = taosHashGetKey(pShow->pIter, NULL);
×
944
      if (!(pObj = sdbAcquire(pSdb, SDB_ROLE, pKey))) {
×
945
        continue;
×
946
      }
947
    }
948

949
    int32_t nSysPrivileges = 0, nObjPrivileges = 0;
5,285✔
950
    if (nSysPrivileges + nObjPrivileges >= rows) {
5,285✔
951
      pShow->restore = true;
×
952
      sdbRelease(pSdb, pObj);
×
953
      break;
×
954
    }
955

956
    if (!pBuf && !(pBuf = taosMemoryMalloc(bufSize))) {
5,285✔
957
      sdbCancelFetch(pSdb, pShow->pIter);
×
958
      sdbRelease(pSdb, pObj);
×
959
      TAOS_CHECK_EXIT(terrno);
×
960
    }
961

962
    cols = 0;
5,285✔
963
    STR_WITH_MAXSIZE_TO_VARSTR(roleName, pObj->name, pShow->pMeta->pSchemas[cols].bytes);
5,285✔
964

965
    // system privileges
966
    SPrivIter privIter = {0};
5,285✔
967
    privIterInit(&privIter, &pObj->sysPrivs);
5,285✔
968
    SPrivInfo *pPrivInfo = NULL;
5,285✔
969
    while (privIterNext(&privIter, &pPrivInfo)) {
98,150✔
970
      cols = 0;
92,865✔
971
      SColumnInfoData *pColInfo = taosArrayGet(pBlock->pDataBlock, cols);
92,865✔
972
      COL_DATA_SET_VAL_GOTO((const char *)roleName, false, pObj, pShow->pIter, _exit);
92,865✔
973

974
      if ((pColInfo = taosArrayGet(pBlock->pDataBlock, ++cols))) {
92,865✔
975
        STR_WITH_MAXSIZE_TO_VARSTR(pBuf, pPrivInfo->name, pShow->pMeta->pSchemas[cols].bytes);
92,865✔
976
        COL_DATA_SET_VAL_GOTO((const char *)pBuf, false, pObj, pShow->pIter, _exit);
92,865✔
977
      }
978
      if ((pColInfo = taosArrayGet(pBlock->pDataBlock, ++cols))) {
92,865✔
979
        STR_WITH_MAXSIZE_TO_VARSTR(pBuf, privObjGetName(PRIV_OBJ_CLUSTER), pShow->pMeta->pSchemas[cols].bytes);
92,865✔
980
        COL_DATA_SET_VAL_GOTO((const char *)pBuf, false, pObj, pShow->pIter, _exit);
92,865✔
981
      }
982
      // skip db, table, condition, notes, columns, update_time
983
      COL_DATA_SET_EMPTY_VARCHAR(pBuf, 6);
650,055✔
984

985
      numOfRows++;
92,865✔
986
    }
987

988
    // object privileges
989
    void *pIter = NULL;
5,285✔
990
    while ((pIter = taosHashIterate(pObj->objPrivs, pIter))) {
37,448✔
991
      SPrivObjPolicies *pPolices = (SPrivObjPolicies *)pIter;
32,163✔
992

993
      char   *key = taosHashGetKey(pPolices, NULL);
32,163✔
994
      int32_t objType = PRIV_OBJ_UNKNOWN;
32,163✔
995
      char    dbName[TSDB_DB_NAME_LEN + VARSTR_HEADER_SIZE] = {0};
32,163✔
996
      char    tblName[TSDB_TABLE_NAME_LEN + VARSTR_HEADER_SIZE] = {0};
32,163✔
997

998
      if ((code = privObjKeyParse(key, &objType, dbName, sizeof(dbName), tblName, sizeof(tblName), false))) {
32,163✔
999
        sdbRelease(pSdb, pObj);
×
1000
        sdbCancelFetch(pSdb, pShow->pIter);
×
1001
        TAOS_CHECK_EXIT(code);
×
1002
      }
1003

1004
      SPrivIter privIter = {0};
32,163✔
1005
      privIterInit(&privIter, &pPolices->policy);
32,163✔
1006
      SPrivInfo *pPrivInfo = NULL;
32,163✔
1007
      while (privIterNext(&privIter, &pPrivInfo)) {
142,997✔
1008
        cols = 0;
110,834✔
1009
        SColumnInfoData *pColInfo = taosArrayGet(pBlock->pDataBlock, cols);
110,834✔
1010
        COL_DATA_SET_VAL_GOTO((const char *)roleName, false, pObj, pShow->pIter, _exit);
110,834✔
1011

1012
        if ((pColInfo = taosArrayGet(pBlock->pDataBlock, ++cols))) {
110,834✔
1013
          STR_WITH_MAXSIZE_TO_VARSTR(pBuf, pPrivInfo->name, pShow->pMeta->pSchemas[cols].bytes);
110,834✔
1014
          COL_DATA_SET_VAL_GOTO((const char *)pBuf, false, pObj, pShow->pIter, _exit);
110,834✔
1015
        }
1016

1017
        if ((pColInfo = taosArrayGet(pBlock->pDataBlock, ++cols))) {
110,834✔
1018
          STR_WITH_MAXSIZE_TO_VARSTR(pBuf, privObjGetName(objType), pShow->pMeta->pSchemas[cols].bytes);
110,834✔
1019
          COL_DATA_SET_VAL_GOTO((const char *)pBuf, false, pObj, pShow->pIter, _exit);
110,834✔
1020
        }
1021

1022
        if ((pColInfo = taosArrayGet(pBlock->pDataBlock, ++cols))) {
110,834✔
1023
          STR_WITH_MAXSIZE_TO_VARSTR(pBuf, dbName, pShow->pMeta->pSchemas[cols].bytes);
110,834✔
1024
          COL_DATA_SET_VAL_GOTO((const char *)pBuf, false, pObj, pShow->pIter, _exit);
110,834✔
1025
        }
1026

1027
        if ((pColInfo = taosArrayGet(pBlock->pDataBlock, ++cols))) {
110,834✔
1028
          STR_WITH_MAXSIZE_TO_VARSTR(pBuf, tblName, pShow->pMeta->pSchemas[cols].bytes);
110,834✔
1029
          COL_DATA_SET_VAL_GOTO((const char *)pBuf, false, pObj, pShow->pIter, _exit);
110,834✔
1030
        }
1031

1032
        // skip condition, notes, columns, update_time
1033
        COL_DATA_SET_EMPTY_VARCHAR(pBuf, 4);
554,170✔
1034

1035
        numOfRows++;
110,834✔
1036
      }
1037
    }
1038
    // row level privileges
1039

1040
    // table level privileges
1041
    sdbRelease(pSdb, pObj);
5,285✔
1042
  }
1043

1044
  pShow->numOfRows += numOfRows;
755✔
1045
_exit:
755✔
1046
  taosMemoryFreeClear(pBuf);
755✔
1047
  taosMemoryFreeClear(sql);
755✔
1048
  if (code < 0) {
755✔
1049
    uError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
1050
    TAOS_RETURN(code);
×
1051
  }
1052
  return numOfRows;
755✔
1053
}
1054

1055
static void mndCancelGetNextPrivileges(SMnode *pMnode, void *pIter) {
×
1056
  SSdb *pSdb = pMnode->pSdb;
×
1057
  sdbCancelFetchByType(pSdb, pIter, SDB_ROLE);
×
1058
}
×
1059

1060
static int32_t mndRetrieveColPrivileges(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pBlock, int32_t rows) {
×
1061
  int32_t   code = 0, lino = 0;
×
1062
  SMnode   *pMnode = pReq->info.node;
×
1063
  SSdb     *pSdb = pMnode->pSdb;
×
1064
  int32_t   numOfRows = 0;
×
1065
  int32_t   cols = 0;
×
1066
  SRoleObj *pObj = NULL;
×
1067
  char     *pBuf = NULL, *qBuf = NULL;
×
1068
  char     *sql = NULL;
×
1069
  char      roleName[TSDB_ROLE_LEN + VARSTR_HEADER_SIZE] = {0};
×
1070
  int32_t   bufSize = TSDB_PRIVILEDGE_CONDITION_LEN + VARSTR_HEADER_SIZE;
×
1071

1072
  bool fetchNextInstance = pShow->restore ? false : true;
×
1073
  pShow->restore = false;
×
1074

1075
  while (numOfRows < rows) {
×
1076
    if (fetchNextInstance) {
×
1077
      pShow->pIter = sdbFetch(pSdb, SDB_ROLE, pShow->pIter, (void **)&pObj);
×
1078
      if (pShow->pIter == NULL) break;
×
1079
    } else {
1080
      fetchNextInstance = true;
×
1081
      void *pKey = taosHashGetKey(pShow->pIter, NULL);
×
1082
      if (!(pObj = sdbAcquire(pSdb, SDB_ROLE, pKey))) {
×
1083
        continue;
×
1084
      }
1085
    }
1086

1087
    int32_t nSysPrivileges = 0, nObjPrivileges = 0;
×
1088
    if (nSysPrivileges + nObjPrivileges >= rows) {
×
1089
      pShow->restore = true;
×
1090
      sdbRelease(pSdb, pObj);
×
1091
      break;
×
1092
    }
1093

1094
    if (!pBuf && !(pBuf = taosMemoryMalloc(bufSize))) {
×
1095
      sdbCancelFetch(pSdb, pShow->pIter);
×
1096
      sdbRelease(pSdb, pObj);
×
1097
      TAOS_CHECK_EXIT(terrno);
×
1098
    }
1099

1100
    cols = 0;
×
1101
    STR_WITH_MAXSIZE_TO_VARSTR(roleName, pObj->name, pShow->pMeta->pSchemas[cols].bytes);
×
1102

1103
    SPrivIter privIter = {0};
×
1104
    privIterInit(&privIter, &pObj->sysPrivs);
×
1105
    SPrivInfo *pPrivInfo = NULL;
×
1106
    while (privIterNext(&privIter, &pPrivInfo)) {
×
1107
      cols = 0;
×
1108
      SColumnInfoData *pColInfo = taosArrayGet(pBlock->pDataBlock, cols);
×
1109
      COL_DATA_SET_VAL_GOTO((const char *)roleName, false, pObj, pShow->pIter, _exit);
×
1110

1111
      if ((pColInfo = taosArrayGet(pBlock->pDataBlock, ++cols))) {
×
1112
        STR_WITH_MAXSIZE_TO_VARSTR(pBuf, pPrivInfo->name, pShow->pMeta->pSchemas[cols].bytes);
×
1113
        COL_DATA_SET_VAL_GOTO((const char *)pBuf, false, pObj, pShow->pIter, _exit);
×
1114
      }
1115

1116
      // for (int32_t i = 0; i < 6; i++) {
1117
      //   if ((pColInfo = taosArrayGet(pBlock->pDataBlock, ++cols))) {
1118
      //     STR_WITH_MAXSIZE_TO_VARSTR(pBuf, "", 2);
1119
      //     COL_DATA_SET_VAL_GOTO((const char *)pBuf, false, pObj, pShow->pIter, _exit);
1120
      //   }
1121
      // }
1122
      // skip db, table, condition, notes, columns, update_time
1123
      COL_DATA_SET_EMPTY_VARCHAR(pBuf, 6);
×
1124
      numOfRows++;
×
1125
    }
1126

1127
    sdbRelease(pSdb, pObj);
×
1128
  }
1129

1130
  pShow->numOfRows += numOfRows;
×
1131
_exit:
×
1132
  taosMemoryFreeClear(pBuf);
×
1133
  taosMemoryFreeClear(sql);
×
1134
  if (code < 0) {
×
1135
    uError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
1136
    TAOS_RETURN(code);
×
1137
  }
1138
  return numOfRows;
×
1139
}
1140

1141
static void mndCancelGetNextColPrivileges(SMnode *pMnode, void *pIter) {
×
1142
  SSdb *pSdb = pMnode->pSdb;
×
1143
  sdbCancelFetchByType(pSdb, pIter, SDB_ROLE);
×
1144
}
×
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