mndUser.c 23.4 KB
Newer Older
H
refact  
Hongze Cheng 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
/*
 * Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
 *
 * This program is free software: you can use, redistribute, and/or modify
 * it under the terms of the GNU Affero General Public License, version 3
 * or later ("AGPL"), as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */

S
Shengliang Guan 已提交
16
#define _DEFAULT_SOURCE
S
Shengliang Guan 已提交
17
#include "mndUser.h"
S
Shengliang Guan 已提交
18
#include "mndAuth.h"
S
Shengliang Guan 已提交
19
#include "mndDb.h"
S
Shengliang Guan 已提交
20
#include "mndShow.h"
S
Shengliang Guan 已提交
21
#include "mndTrans.h"
S
tbase64  
Shengliang Guan 已提交
22
#include "tbase64.h"
S
Shengliang Guan 已提交
23

24 25
#define USER_VER_NUMBER   1
#define USER_RESERVE_SIZE 64
S
Shengliang Guan 已提交
26

S
Shengliang Guan 已提交
27 28 29 30
static int32_t  mndCreateDefaultUsers(SMnode *pMnode);
static SSdbRow *mndUserActionDecode(SSdbRaw *pRaw);
static int32_t  mndUserActionInsert(SSdb *pSdb, SUserObj *pUser);
static int32_t  mndUserActionDelete(SSdb *pSdb, SUserObj *pUser);
S
Shengliang Guan 已提交
31
static int32_t  mndUserActionUpdate(SSdb *pSdb, SUserObj *pOld, SUserObj *pNew);
S
Shengliang Guan 已提交
32 33 34 35 36
static int32_t  mndCreateUser(SMnode *pMnode, char *acct, SCreateUserReq *pCreate, SNodeMsg *pReq);
static int32_t  mndProcessCreateUserReq(SNodeMsg *pReq);
static int32_t  mndProcessAlterUserReq(SNodeMsg *pReq);
static int32_t  mndProcessDropUserReq(SNodeMsg *pReq);
static int32_t  mndProcessGetUserAuthReq(SNodeMsg *pReq);
37
static int32_t  mndRetrieveUsers(SNodeMsg *pReq, SShowObj *pShow, SSDataBlock *pBlock, int32_t rows);
S
Shengliang Guan 已提交
38
static void     mndCancelGetNextUser(SMnode *pMnode, void *pIter);
S
Shengliang Guan 已提交
39 40

int32_t mndInitUser(SMnode *pMnode) {
S
Shengliang Guan 已提交
41 42 43 44 45 46 47 48 49 50
  SSdbTable table = {
      .sdbType = SDB_USER,
      .keyType = SDB_KEY_BINARY,
      .deployFp = (SdbDeployFp)mndCreateDefaultUsers,
      .encodeFp = (SdbEncodeFp)mndUserActionEncode,
      .decodeFp = (SdbDecodeFp)mndUserActionDecode,
      .insertFp = (SdbInsertFp)mndUserActionInsert,
      .updateFp = (SdbUpdateFp)mndUserActionUpdate,
      .deleteFp = (SdbDeleteFp)mndUserActionDelete,
  };
S
Shengliang Guan 已提交
51

S
Shengliang Guan 已提交
52 53 54
  mndSetMsgHandle(pMnode, TDMT_MND_CREATE_USER, mndProcessCreateUserReq);
  mndSetMsgHandle(pMnode, TDMT_MND_ALTER_USER, mndProcessAlterUserReq);
  mndSetMsgHandle(pMnode, TDMT_MND_DROP_USER, mndProcessDropUserReq);
S
Shengliang Guan 已提交
55
  mndSetMsgHandle(pMnode, TDMT_MND_GET_USER_AUTH, mndProcessGetUserAuthReq);
S
Shengliang Guan 已提交
56

S
Shengliang Guan 已提交
57 58
  mndAddShowRetrieveHandle(pMnode, TSDB_MGMT_TABLE_USER, mndRetrieveUsers);
  mndAddShowFreeIterHandle(pMnode, TSDB_MGMT_TABLE_USER, mndCancelGetNextUser);
S
Shengliang Guan 已提交
59 60 61 62 63 64 65
  return sdbSetTable(pMnode->pSdb, table);
}

void mndCleanupUser(SMnode *pMnode) {}

static int32_t mndCreateDefaultUser(SMnode *pMnode, char *acct, char *user, char *pass) {
  SUserObj userObj = {0};
S
Shengliang Guan 已提交
66
  taosEncryptPass_c((uint8_t *)pass, strlen(pass), userObj.pass);
S
Shengliang Guan 已提交
67 68 69 70 71 72
  tstrncpy(userObj.user, user, TSDB_USER_LEN);
  tstrncpy(userObj.acct, acct, TSDB_USER_LEN);
  userObj.createdTime = taosGetTimestampMs();
  userObj.updateTime = userObj.createdTime;

  if (strcmp(user, TSDB_DEFAULT_USER) == 0) {
73
    userObj.superUser = 1;
S
Shengliang Guan 已提交
74 75 76 77 78 79
  }

  SSdbRaw *pRaw = mndUserActionEncode(&userObj);
  if (pRaw == NULL) return -1;
  sdbSetRawStatus(pRaw, SDB_STATUS_READY);

S
Shengliang Guan 已提交
80
  mDebug("user:%s, will be created while deploy sdb, raw:%p", userObj.user, pRaw);
S
Shengliang Guan 已提交
81 82 83 84 85 86 87 88 89 90 91
  return sdbWrite(pMnode->pSdb, pRaw);
}

static int32_t mndCreateDefaultUsers(SMnode *pMnode) {
  if (mndCreateDefaultUser(pMnode, TSDB_DEFAULT_USER, TSDB_DEFAULT_USER, TSDB_DEFAULT_PASS) != 0) {
    return -1;
  }

  return 0;
}

92
SSdbRaw *mndUserActionEncode(SUserObj *pUser) {
93 94
  terrno = TSDB_CODE_OUT_OF_MEMORY;

S
Shengliang Guan 已提交
95 96
  int32_t numOfReadDbs = taosHashGetSize(pUser->readDbs);
  int32_t numOfWriteDbs = taosHashGetSize(pUser->writeDbs);
97
  int32_t size = sizeof(SUserObj) + USER_RESERVE_SIZE + (numOfReadDbs + numOfWriteDbs) * TSDB_DB_FNAME_LEN;
S
Shengliang Guan 已提交
98

99
  SSdbRaw *pRaw = sdbAllocRaw(SDB_USER, USER_VER_NUMBER, size);
100
  if (pRaw == NULL) goto _OVER;
S
Shengliang Guan 已提交
101 102

  int32_t dataPos = 0;
103 104 105 106 107 108 109 110
  SDB_SET_BINARY(pRaw, dataPos, pUser->user, TSDB_USER_LEN, _OVER)
  SDB_SET_BINARY(pRaw, dataPos, pUser->pass, TSDB_PASSWORD_LEN, _OVER)
  SDB_SET_BINARY(pRaw, dataPos, pUser->acct, TSDB_USER_LEN, _OVER)
  SDB_SET_INT64(pRaw, dataPos, pUser->createdTime, _OVER)
  SDB_SET_INT64(pRaw, dataPos, pUser->updateTime, _OVER)
  SDB_SET_INT8(pRaw, dataPos, pUser->superUser, _OVER)
  SDB_SET_INT32(pRaw, dataPos, numOfReadDbs, _OVER)
  SDB_SET_INT32(pRaw, dataPos, numOfWriteDbs, _OVER)
111 112 113

  char *db = taosHashIterate(pUser->readDbs, NULL);
  while (db != NULL) {
114
    SDB_SET_BINARY(pRaw, dataPos, db, TSDB_DB_FNAME_LEN, _OVER);
115 116 117 118 119
    db = taosHashIterate(pUser->readDbs, db);
  }

  db = taosHashIterate(pUser->writeDbs, NULL);
  while (db != NULL) {
120
    SDB_SET_BINARY(pRaw, dataPos, db, TSDB_DB_FNAME_LEN, _OVER);
121 122 123
    db = taosHashIterate(pUser->writeDbs, db);
  }

124 125
  SDB_SET_RESERVE(pRaw, dataPos, USER_RESERVE_SIZE, _OVER)
  SDB_SET_DATALEN(pRaw, dataPos, _OVER)
126 127 128

  terrno = 0;

129
_OVER:
130 131 132 133 134
  if (terrno != 0) {
    mError("user:%s, failed to encode to raw:%p since %s", pUser->user, pRaw, terrstr());
    sdbFreeRaw(pRaw);
    return NULL;
  }
S
Shengliang Guan 已提交
135

S
Shengliang Guan 已提交
136
  mTrace("user:%s, encode to raw:%p, row:%p", pUser->user, pRaw, pUser);
S
Shengliang Guan 已提交
137
  return pRaw;
S
Shengliang Guan 已提交
138 139
}

S
Shengliang Guan 已提交
140
static SSdbRow *mndUserActionDecode(SSdbRaw *pRaw) {
141 142
  terrno = TSDB_CODE_OUT_OF_MEMORY;

S
Shengliang Guan 已提交
143
  int8_t sver = 0;
144
  if (sdbGetRawSoftVer(pRaw, &sver) != 0) goto _OVER;
S
Shengliang Guan 已提交
145

146
  if (sver != USER_VER_NUMBER) {
S
Shengliang Guan 已提交
147
    terrno = TSDB_CODE_SDB_INVALID_DATA_VER;
148
    goto _OVER;
S
Shengliang Guan 已提交
149
  }
S
Shengliang Guan 已提交
150

151
  SSdbRow *pRow = sdbAllocRow(sizeof(SUserObj));
152
  if (pRow == NULL) goto _OVER;
153

S
Shengliang Guan 已提交
154
  SUserObj *pUser = sdbGetRowObj(pRow);
155
  if (pUser == NULL) goto _OVER;
156

S
Shengliang Guan 已提交
157
  int32_t dataPos = 0;
158 159 160 161 162 163
  SDB_GET_BINARY(pRaw, dataPos, pUser->user, TSDB_USER_LEN, _OVER)
  SDB_GET_BINARY(pRaw, dataPos, pUser->pass, TSDB_PASSWORD_LEN, _OVER)
  SDB_GET_BINARY(pRaw, dataPos, pUser->acct, TSDB_USER_LEN, _OVER)
  SDB_GET_INT64(pRaw, dataPos, &pUser->createdTime, _OVER)
  SDB_GET_INT64(pRaw, dataPos, &pUser->updateTime, _OVER)
  SDB_GET_INT8(pRaw, dataPos, &pUser->superUser, _OVER)
164 165 166

  int32_t numOfReadDbs = 0;
  int32_t numOfWriteDbs = 0;
167 168
  SDB_GET_INT32(pRaw, dataPos, &numOfReadDbs, _OVER)
  SDB_GET_INT32(pRaw, dataPos, &numOfWriteDbs, _OVER)
S
Shengliang Guan 已提交
169 170 171
  pUser->readDbs = taosHashInit(numOfReadDbs, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_ENTRY_LOCK);
  pUser->writeDbs =
      taosHashInit(numOfWriteDbs, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_ENTRY_LOCK);
172
  if (pUser->readDbs == NULL || pUser->writeDbs == NULL) goto _OVER;
173 174 175

  for (int32_t i = 0; i < numOfReadDbs; ++i) {
    char db[TSDB_DB_FNAME_LEN] = {0};
176
    SDB_GET_BINARY(pRaw, dataPos, db, TSDB_DB_FNAME_LEN, _OVER)
177 178 179 180 181 182
    int32_t len = strlen(db) + 1;
    taosHashPut(pUser->readDbs, db, len, db, TSDB_DB_FNAME_LEN);
  }

  for (int32_t i = 0; i < numOfWriteDbs; ++i) {
    char db[TSDB_DB_FNAME_LEN] = {0};
183
    SDB_GET_BINARY(pRaw, dataPos, db, TSDB_DB_FNAME_LEN, _OVER)
184 185 186 187
    int32_t len = strlen(db) + 1;
    taosHashPut(pUser->writeDbs, db, len, db, TSDB_DB_FNAME_LEN);
  }

188
  SDB_GET_RESERVE(pRaw, dataPos, USER_RESERVE_SIZE, _OVER)
S
Shengliang Guan 已提交
189
  taosInitRWLatch(&pUser->lock);
190 191 192

  terrno = 0;

193
_OVER:
194 195
  if (terrno != 0) {
    mError("user:%s, failed to decode from raw:%p since %s", pUser->user, pRaw, terrstr());
196 197
    taosHashCleanup(pUser->readDbs);
    taosHashCleanup(pUser->writeDbs);
wafwerar's avatar
wafwerar 已提交
198
    taosMemoryFreeClear(pRow);
199 200
    return NULL;
  }
S
Shengliang Guan 已提交
201

S
Shengliang Guan 已提交
202
  mTrace("user:%s, decode from raw:%p, row:%p", pUser->user, pRaw, pUser);
S
Shengliang Guan 已提交
203
  return pRow;
S
Shengliang Guan 已提交
204
}
S
Shengliang Guan 已提交
205

S
Shengliang Guan 已提交
206
static int32_t mndUserActionInsert(SSdb *pSdb, SUserObj *pUser) {
S
Shengliang Guan 已提交
207
  mTrace("user:%s, perform insert action, row:%p", pUser->user, pUser);
S
Shengliang Guan 已提交
208

S
Shengliang Guan 已提交
209 210
  SAcctObj *pAcct = sdbAcquire(pSdb, SDB_ACCT, pUser->acct);
  if (pAcct == NULL) {
S
Shengliang Guan 已提交
211
    terrno = TSDB_CODE_MND_ACCT_NOT_EXIST;
S
Shengliang Guan 已提交
212
    mError("user:%s, failed to perform insert action since %s", pUser->user, terrstr());
S
Shengliang Guan 已提交
213
    return -1;
S
Shengliang Guan 已提交
214
  }
S
Shengliang Guan 已提交
215 216
  pUser->acctId = pAcct->acctId;
  sdbRelease(pSdb, pAcct);
S
Shengliang Guan 已提交
217

S
Shengliang Guan 已提交
218 219
  return 0;
}
S
Shengliang Guan 已提交
220

S
Shengliang Guan 已提交
221
static int32_t mndUserActionDelete(SSdb *pSdb, SUserObj *pUser) {
S
Shengliang Guan 已提交
222
  mTrace("user:%s, perform delete action, row:%p", pUser->user, pUser);
223 224
  taosHashCleanup(pUser->readDbs);
  taosHashCleanup(pUser->writeDbs);
225 226
  pUser->readDbs = NULL;
  pUser->writeDbs = NULL;
S
Shengliang Guan 已提交
227 228 229
  return 0;
}

S
Shengliang Guan 已提交
230
static int32_t mndUserActionUpdate(SSdb *pSdb, SUserObj *pOld, SUserObj *pNew) {
S
Shengliang Guan 已提交
231
  mTrace("user:%s, perform update action, old row:%p new row:%p", pOld->user, pOld, pNew);
S
Shengliang Guan 已提交
232
  taosWLockLatch(&pOld->lock);
S
Shengliang Guan 已提交
233
  pOld->updateTime = pNew->updateTime;
S
Shengliang Guan 已提交
234
  memcpy(pOld->pass, pNew->pass, TSDB_PASSWORD_LEN);
wafwerar's avatar
wafwerar 已提交
235 236
  TSWAP(pOld->readDbs, pNew->readDbs);
  TSWAP(pOld->writeDbs, pNew->writeDbs);
S
Shengliang Guan 已提交
237
  taosWUnLockLatch(&pOld->lock);
238

S
Shengliang Guan 已提交
239 240 241
  return 0;
}

242
SUserObj *mndAcquireUser(SMnode *pMnode, const char *userName) {
S
Shengliang Guan 已提交
243 244 245
  SSdb     *pSdb = pMnode->pSdb;
  SUserObj *pUser = sdbAcquire(pSdb, SDB_USER, userName);
  if (pUser == NULL) {
S
Shengliang Guan 已提交
246
    terrno = TSDB_CODE_MND_USER_NOT_EXIST;
S
Shengliang Guan 已提交
247 248
  }
  return pUser;
S
Shengliang Guan 已提交
249
}
S
Shengliang Guan 已提交
250

S
Shengliang Guan 已提交
251 252 253
void mndReleaseUser(SMnode *pMnode, SUserObj *pUser) {
  SSdb *pSdb = pMnode->pSdb;
  sdbRelease(pSdb, pUser);
S
Shengliang Guan 已提交
254 255
}

S
Shengliang Guan 已提交
256
static int32_t mndCreateUser(SMnode *pMnode, char *acct, SCreateUserReq *pCreate, SNodeMsg *pReq) {
S
Shengliang Guan 已提交
257
  SUserObj userObj = {0};
S
Shengliang Guan 已提交
258 259
  taosEncryptPass_c((uint8_t *)pCreate->pass, strlen(pCreate->pass), userObj.pass);
  tstrncpy(userObj.user, pCreate->user, TSDB_USER_LEN);
S
Shengliang Guan 已提交
260 261 262
  tstrncpy(userObj.acct, acct, TSDB_USER_LEN);
  userObj.createdTime = taosGetTimestampMs();
  userObj.updateTime = userObj.createdTime;
S
Shengliang Guan 已提交
263
  userObj.superUser = pCreate->superUser;
S
Shengliang Guan 已提交
264

S
Shengliang Guan 已提交
265
  STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_ROLLBACK, TRN_TYPE_CREATE_USER, &pReq->rpcMsg);
S
Shengliang Guan 已提交
266
  if (pTrans == NULL) {
S
Shengliang Guan 已提交
267
    mError("user:%s, failed to create since %s", pCreate->user, terrstr());
S
Shengliang Guan 已提交
268 269
    return -1;
  }
S
Shengliang Guan 已提交
270
  mDebug("trans:%d, used to create user:%s", pTrans->id, pCreate->user);
S
Shengliang Guan 已提交
271

S
Shengliang Guan 已提交
272
  SSdbRaw *pRedoRaw = mndUserActionEncode(&userObj);
S
Shengliang Guan 已提交
273
  if (pRedoRaw == NULL || mndTransAppendRedolog(pTrans, pRedoRaw) != 0) {
S
Shengliang Guan 已提交
274
    mError("trans:%d, failed to append redo log since %s", pTrans->id, terrstr());
S
Shengliang Guan 已提交
275
    mndTransDrop(pTrans);
S
Shengliang Guan 已提交
276
    return -1;
S
Shengliang Guan 已提交
277
  }
S
Shengliang Guan 已提交
278 279
  sdbSetRawStatus(pRedoRaw, SDB_STATUS_READY);

S
Shengliang Guan 已提交
280
  if (mndTransPrepare(pMnode, pTrans) != 0) {
S
Shengliang Guan 已提交
281
    mError("trans:%d, failed to prepare since %s", pTrans->id, terrstr());
S
Shengliang Guan 已提交
282
    mndTransDrop(pTrans);
S
Shengliang Guan 已提交
283
    return -1;
S
Shengliang Guan 已提交
284 285
  }

S
Shengliang Guan 已提交
286
  mndTransDrop(pTrans);
S
Shengliang Guan 已提交
287
  return 0;
S
Shengliang Guan 已提交
288 289
}

S
Shengliang Guan 已提交
290 291
static int32_t mndProcessCreateUserReq(SNodeMsg *pReq) {
  SMnode        *pMnode = pReq->pNode;
S
Shengliang Guan 已提交
292 293 294 295 296
  int32_t        code = -1;
  SUserObj      *pUser = NULL;
  SUserObj      *pOperUser = NULL;
  SCreateUserReq createReq = {0};

S
Shengliang Guan 已提交
297 298
  if (tDeserializeSCreateUserReq(pReq->rpcMsg.pCont, pReq->rpcMsg.contLen, &createReq) != 0) {
    terrno = TSDB_CODE_INVALID_MSG;
299
    goto _OVER;
S
Shengliang Guan 已提交
300
  }
S
Shengliang Guan 已提交
301

S
Shengliang Guan 已提交
302
  mDebug("user:%s, start to create", createReq.user);
S
Shengliang Guan 已提交
303

S
Shengliang Guan 已提交
304
  if (createReq.user[0] == 0) {
S
Shengliang Guan 已提交
305
    terrno = TSDB_CODE_MND_INVALID_USER_FORMAT;
306
    goto _OVER;
S
Shengliang Guan 已提交
307 308
  }

S
Shengliang Guan 已提交
309
  if (createReq.pass[0] == 0) {
S
Shengliang Guan 已提交
310
    terrno = TSDB_CODE_MND_INVALID_PASS_FORMAT;
311
    goto _OVER;
S
Shengliang Guan 已提交
312 313
  }

S
Shengliang Guan 已提交
314
  pUser = mndAcquireUser(pMnode, createReq.user);
S
Shengliang Guan 已提交
315
  if (pUser != NULL) {
S
Shengliang Guan 已提交
316
    terrno = TSDB_CODE_MND_USER_ALREADY_EXIST;
317
    goto _OVER;
S
Shengliang Guan 已提交
318 319
  }

S
Shengliang Guan 已提交
320
  pOperUser = mndAcquireUser(pMnode, pReq->user);
S
Shengliang Guan 已提交
321
  if (pOperUser == NULL) {
S
Shengliang Guan 已提交
322
    terrno = TSDB_CODE_MND_NO_USER_FROM_CONN;
323
    goto _OVER;
S
Shengliang Guan 已提交
324 325
  }

S
Shengliang Guan 已提交
326
  if (mndCheckCreateUserAuth(pOperUser) != 0) {
327
    goto _OVER;
S
Shengliang Guan 已提交
328 329 330
  }

  code = mndCreateUser(pMnode, pOperUser->acct, &createReq, pReq);
S
Shengliang Guan 已提交
331
  if (code == 0) code = TSDB_CODE_MND_ACTION_IN_PROGRESS;
S
Shengliang Guan 已提交
332

333
_OVER:
S
Shengliang Guan 已提交
334 335
  if (code != 0 && code != TSDB_CODE_MND_ACTION_IN_PROGRESS) {
    mError("user:%s, failed to create since %s", createReq.user, terrstr());
S
Shengliang Guan 已提交
336 337
  }

S
Shengliang Guan 已提交
338 339 340 341
  mndReleaseUser(pMnode, pUser);
  mndReleaseUser(pMnode, pOperUser);

  return code;
S
Shengliang Guan 已提交
342 343
}

S
Shengliang Guan 已提交
344
static int32_t mndAlterUser(SMnode *pMnode, SUserObj *pOld, SUserObj *pNew, SNodeMsg *pReq) {
S
Shengliang Guan 已提交
345
  STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_ROLLBACK, TRN_TYPE_ALTER_USER, &pReq->rpcMsg);
S
Shengliang Guan 已提交
346
  if (pTrans == NULL) {
S
Shengliang Guan 已提交
347
    mError("user:%s, failed to alter since %s", pOld->user, terrstr());
S
Shengliang Guan 已提交
348 349
    return -1;
  }
S
Shengliang Guan 已提交
350
  mDebug("trans:%d, used to alter user:%s", pTrans->id, pOld->user);
S
Shengliang Guan 已提交
351

S
Shengliang Guan 已提交
352
  SSdbRaw *pRedoRaw = mndUserActionEncode(pNew);
S
Shengliang Guan 已提交
353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369
  if (pRedoRaw == NULL || mndTransAppendRedolog(pTrans, pRedoRaw) != 0) {
    mError("trans:%d, failed to append redo log since %s", pTrans->id, terrstr());
    mndTransDrop(pTrans);
    return -1;
  }
  sdbSetRawStatus(pRedoRaw, SDB_STATUS_READY);

  if (mndTransPrepare(pMnode, pTrans) != 0) {
    mError("trans:%d, failed to prepare since %s", pTrans->id, terrstr());
    mndTransDrop(pTrans);
    return -1;
  }

  mndTransDrop(pTrans);
  return 0;
}

S
Shengliang Guan 已提交
370
static SHashObj *mndDupDbHash(SHashObj *pOld) {
S
Shengliang Guan 已提交
371 372
  SHashObj *pNew =
      taosHashInit(taosHashGetSize(pOld), taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_ENTRY_LOCK);
S
Shengliang Guan 已提交
373 374 375 376 377 378 379 380 381 382 383
  if (pNew == NULL) {
    terrno = TSDB_CODE_OUT_OF_MEMORY;
    return NULL;
  }

  char *db = taosHashIterate(pOld, NULL);
  while (db != NULL) {
    int32_t len = strlen(db) + 1;
    if (taosHashPut(pNew, db, len, db, TSDB_DB_FNAME_LEN) != 0) {
      taosHashCancelIterate(pOld, db);
      taosHashCleanup(pNew);
S
Shengliang Guan 已提交
384
      terrno = TSDB_CODE_OUT_OF_MEMORY;
S
Shengliang Guan 已提交
385 386 387 388 389 390 391 392
      return NULL;
    }
    db = taosHashIterate(pOld, db);
  }

  return pNew;
}

S
Shengliang Guan 已提交
393 394
static int32_t mndProcessAlterUserReq(SNodeMsg *pReq) {
  SMnode       *pMnode = pReq->pNode;
S
Shengliang Guan 已提交
395 396 397
  int32_t       code = -1;
  SUserObj     *pUser = NULL;
  SUserObj     *pOperUser = NULL;
S
Shengliang Guan 已提交
398
  SUserObj      newUser = {0};
S
Shengliang Guan 已提交
399 400
  SAlterUserReq alterReq = {0};

S
Shengliang Guan 已提交
401 402
  if (tDeserializeSAlterUserReq(pReq->rpcMsg.pCont, pReq->rpcMsg.contLen, &alterReq) != 0) {
    terrno = TSDB_CODE_INVALID_MSG;
403
    goto _OVER;
S
Shengliang Guan 已提交
404
  }
S
Shengliang Guan 已提交
405

S
Shengliang Guan 已提交
406
  mDebug("user:%s, start to alter", alterReq.user);
S
Shengliang Guan 已提交
407

S
Shengliang Guan 已提交
408
  if (alterReq.user[0] == 0) {
S
Shengliang Guan 已提交
409
    terrno = TSDB_CODE_MND_INVALID_USER_FORMAT;
410
    goto _OVER;
S
Shengliang Guan 已提交
411 412
  }

S
Shengliang Guan 已提交
413
  if (alterReq.pass[0] == 0) {
S
Shengliang Guan 已提交
414
    terrno = TSDB_CODE_MND_INVALID_PASS_FORMAT;
415
    goto _OVER;
S
Shengliang Guan 已提交
416 417
  }

S
Shengliang Guan 已提交
418
  pUser = mndAcquireUser(pMnode, alterReq.user);
S
Shengliang Guan 已提交
419 420
  if (pUser == NULL) {
    terrno = TSDB_CODE_MND_USER_NOT_EXIST;
421
    goto _OVER;
S
Shengliang Guan 已提交
422 423
  }

S
Shengliang Guan 已提交
424
  pOperUser = mndAcquireUser(pMnode, pReq->user);
S
Shengliang Guan 已提交
425 426
  if (pOperUser == NULL) {
    terrno = TSDB_CODE_MND_NO_USER_FROM_CONN;
427
    goto _OVER;
S
Shengliang Guan 已提交
428 429 430
  }

  memcpy(&newUser, pUser, sizeof(SUserObj));
S
Shengliang Guan 已提交
431 432

  taosRLockLatch(&pUser->lock);
S
Shengliang Guan 已提交
433 434
  newUser.readDbs = mndDupDbHash(pUser->readDbs);
  newUser.writeDbs = mndDupDbHash(pUser->writeDbs);
S
Shengliang Guan 已提交
435 436
  taosRUnLockLatch(&pUser->lock);

S
Shengliang Guan 已提交
437
  if (newUser.readDbs == NULL || newUser.writeDbs == NULL) {
438
    goto _OVER;
S
Shengliang Guan 已提交
439 440 441 442 443 444 445 446 447
  }

  int32_t len = strlen(alterReq.dbname) + 1;
  SDbObj *pDb = mndAcquireDb(pMnode, alterReq.dbname);
  mndReleaseDb(pMnode, pDb);

  if (alterReq.alterType == TSDB_ALTER_USER_PASSWD) {
    char pass[TSDB_PASSWORD_LEN + 1] = {0};
    taosEncryptPass_c((uint8_t *)alterReq.pass, strlen(alterReq.pass), pass);
448
    memcpy(newUser.pass, pass, TSDB_PASSWORD_LEN);
S
Shengliang Guan 已提交
449
  } else if (alterReq.alterType == TSDB_ALTER_USER_SUPERUSER) {
S
Shengliang Guan 已提交
450
    newUser.superUser = alterReq.superUser;
S
Shengliang Guan 已提交
451
  } else if (alterReq.alterType == TSDB_ALTER_USER_ADD_READ_DB) {
S
Shengliang Guan 已提交
452 453
    if (pDb == NULL) {
      terrno = TSDB_CODE_MND_DB_NOT_EXIST;
454
      goto _OVER;
S
Shengliang Guan 已提交
455 456 457
    }
    if (taosHashPut(newUser.readDbs, alterReq.dbname, len, alterReq.dbname, TSDB_DB_FNAME_LEN) != 0) {
      terrno = TSDB_CODE_OUT_OF_MEMORY;
458
      goto _OVER;
S
Shengliang Guan 已提交
459
    }
D
dapan 已提交
460
    newUser.authVersion++;
S
Shengliang Guan 已提交
461
  } else if (alterReq.alterType == TSDB_ALTER_USER_REMOVE_READ_DB) {
S
Shengliang Guan 已提交
462 463
    if (taosHashRemove(newUser.readDbs, alterReq.dbname, len) != 0) {
      terrno = TSDB_CODE_MND_DB_NOT_EXIST;
464
      goto _OVER;
S
Shengliang Guan 已提交
465
    }
D
dapan 已提交
466
    newUser.authVersion++;
S
Shengliang Guan 已提交
467
  } else if (alterReq.alterType == TSDB_ALTER_USER_CLEAR_READ_DB) {
S
Shengliang Guan 已提交
468
    taosHashClear(newUser.readDbs);
D
dapan 已提交
469
    newUser.authVersion++;
S
Shengliang Guan 已提交
470 471 472
  } else if (alterReq.alterType == TSDB_ALTER_USER_ADD_WRITE_DB) {
    if (pDb == NULL) {
      terrno = TSDB_CODE_MND_DB_NOT_EXIST;
473
      goto _OVER;
S
Shengliang Guan 已提交
474 475 476
    }
    if (taosHashPut(newUser.writeDbs, alterReq.dbname, len, alterReq.dbname, TSDB_DB_FNAME_LEN) != 0) {
      terrno = TSDB_CODE_OUT_OF_MEMORY;
477
      goto _OVER;
S
Shengliang Guan 已提交
478
    }
D
dapan 已提交
479
    newUser.authVersion++;
S
Shengliang Guan 已提交
480 481 482
  } else if (alterReq.alterType == TSDB_ALTER_USER_REMOVE_WRITE_DB) {
    if (taosHashRemove(newUser.writeDbs, alterReq.dbname, len) != 0) {
      terrno = TSDB_CODE_MND_DB_NOT_EXIST;
483
      goto _OVER;
S
Shengliang Guan 已提交
484
    }
D
dapan 已提交
485
    newUser.authVersion++;
S
Shengliang Guan 已提交
486
  } else if (alterReq.alterType == TSDB_ALTER_USER_CLEAR_WRITE_DB) {
S
Shengliang Guan 已提交
487
    taosHashClear(newUser.writeDbs);
D
dapan 已提交
488
    newUser.authVersion++;
S
Shengliang Guan 已提交
489 490
  } else {
    terrno = TSDB_CODE_MND_INVALID_ALTER_OPER;
491
    goto _OVER;
S
Shengliang Guan 已提交
492 493
  }

S
Shengliang Guan 已提交
494
  newUser.updateTime = taosGetTimestampMs();
S
Shengliang Guan 已提交
495

S
Shengliang Guan 已提交
496
  if (mndCheckAlterUserAuth(pOperUser, pUser, pDb, &alterReq) != 0) {
497
    goto _OVER;
S
Shengliang Guan 已提交
498 499
  }

S
Shengliang Guan 已提交
500
  code = mndAlterUser(pMnode, pUser, &newUser, pReq);
S
Shengliang Guan 已提交
501
  if (code == 0) code = TSDB_CODE_MND_ACTION_IN_PROGRESS;
S
Shengliang Guan 已提交
502

503
_OVER:
S
Shengliang Guan 已提交
504 505
  if (code != 0 && code != TSDB_CODE_MND_ACTION_IN_PROGRESS) {
    mError("user:%s, failed to alter since %s", alterReq.user, terrstr());
S
Shengliang Guan 已提交
506 507
  }

S
Shengliang Guan 已提交
508 509
  mndReleaseUser(pMnode, pOperUser);
  mndReleaseUser(pMnode, pUser);
S
Shengliang Guan 已提交
510 511
  taosHashCleanup(newUser.writeDbs);
  taosHashCleanup(newUser.readDbs);
S
Shengliang Guan 已提交
512 513

  return code;
S
Shengliang Guan 已提交
514 515
}

S
Shengliang Guan 已提交
516
static int32_t mndDropUser(SMnode *pMnode, SNodeMsg *pReq, SUserObj *pUser) {
S
Shengliang Guan 已提交
517
  STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_ROLLBACK, TRN_TYPE_DROP_USER, &pReq->rpcMsg);
S
Shengliang Guan 已提交
518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541
  if (pTrans == NULL) {
    mError("user:%s, failed to drop since %s", pUser->user, terrstr());
    return -1;
  }
  mDebug("trans:%d, used to drop user:%s", pTrans->id, pUser->user);

  SSdbRaw *pRedoRaw = mndUserActionEncode(pUser);
  if (pRedoRaw == NULL || mndTransAppendRedolog(pTrans, pRedoRaw) != 0) {
    mError("trans:%d, failed to append redo log since %s", pTrans->id, terrstr());
    mndTransDrop(pTrans);
    return -1;
  }
  sdbSetRawStatus(pRedoRaw, SDB_STATUS_DROPPED);

  if (mndTransPrepare(pMnode, pTrans) != 0) {
    mError("trans:%d, failed to prepare since %s", pTrans->id, terrstr());
    mndTransDrop(pTrans);
    return -1;
  }

  mndTransDrop(pTrans);
  return 0;
}

S
Shengliang Guan 已提交
542 543
static int32_t mndProcessDropUserReq(SNodeMsg *pReq) {
  SMnode      *pMnode = pReq->pNode;
S
Shengliang Guan 已提交
544 545 546 547 548
  int32_t      code = -1;
  SUserObj    *pUser = NULL;
  SUserObj    *pOperUser = NULL;
  SDropUserReq dropReq = {0};

S
Shengliang Guan 已提交
549 550
  if (tDeserializeSDropUserReq(pReq->rpcMsg.pCont, pReq->rpcMsg.contLen, &dropReq) != 0) {
    terrno = TSDB_CODE_INVALID_MSG;
551
    goto _OVER;
S
Shengliang Guan 已提交
552
  }
S
Shengliang Guan 已提交
553

S
Shengliang Guan 已提交
554
  mDebug("user:%s, start to drop", dropReq.user);
S
Shengliang Guan 已提交
555

S
Shengliang Guan 已提交
556
  if (dropReq.user[0] == 0) {
S
Shengliang Guan 已提交
557
    terrno = TSDB_CODE_MND_INVALID_USER_FORMAT;
558
    goto _OVER;
S
Shengliang Guan 已提交
559 560
  }

S
Shengliang Guan 已提交
561
  pUser = mndAcquireUser(pMnode, dropReq.user);
S
Shengliang Guan 已提交
562 563
  if (pUser == NULL) {
    terrno = TSDB_CODE_MND_USER_NOT_EXIST;
564
    goto _OVER;
S
Shengliang Guan 已提交
565 566
  }

S
Shengliang Guan 已提交
567
  pOperUser = mndAcquireUser(pMnode, pReq->user);
S
Shengliang Guan 已提交
568 569
  if (pOperUser == NULL) {
    terrno = TSDB_CODE_MND_NO_USER_FROM_CONN;
570
    goto _OVER;
S
Shengliang Guan 已提交
571 572
  }

S
Shengliang Guan 已提交
573
  if (mndCheckDropUserAuth(pOperUser) != 0) {
574
    goto _OVER;
S
Shengliang Guan 已提交
575 576
  }

S
Shengliang Guan 已提交
577 578
  code = mndDropUser(pMnode, pReq, pUser);
  if (code == 0) code = TSDB_CODE_MND_ACTION_IN_PROGRESS;
S
Shengliang Guan 已提交
579

580
_OVER:
S
Shengliang Guan 已提交
581 582
  if (code != 0 && code != TSDB_CODE_MND_ACTION_IN_PROGRESS) {
    mError("user:%s, failed to drop since %s", dropReq.user, terrstr());
S
Shengliang Guan 已提交
583 584
  }

S
Shengliang Guan 已提交
585 586 587 588
  mndReleaseUser(pMnode, pOperUser);
  mndReleaseUser(pMnode, pUser);

  return code;
S
Shengliang Guan 已提交
589 590
}

D
dapan 已提交
591 592 593 594
static int32_t mndSetUserAuthRsp(SMnode       *pMnode, SUserObj *pUser, SGetUserAuthRsp *pRsp) {
  memcpy(pRsp->user, pUser->user, TSDB_USER_LEN);
  pRsp->superAuth = pUser->superUser;
  pRsp->version = pUser->authVersion;
595
  taosRLockLatch(&pUser->lock);
D
dapan 已提交
596 597
  pRsp->readDbs = mndDupDbHash(pUser->readDbs);
  pRsp->writeDbs = mndDupDbHash(pUser->writeDbs);
598
  taosRUnLockLatch(&pUser->lock);
D
dapan 已提交
599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622
  pRsp->createdDbs = taosHashInit(4, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_NO_LOCK);
  if (NULL == pRsp->createdDbs) {
    terrno = TSDB_CODE_OUT_OF_MEMORY;
    return -1;
  }
  
  SSdb *pSdb = pMnode->pSdb;
  void *pIter = NULL;
  while (1) {
    SDbObj *pDb = NULL;
    pIter = sdbFetch(pSdb, SDB_DB, pIter, (void **)&pDb);
    if (pIter == NULL) break;

    if (strcmp(pDb->createUser, pUser->user) == 0) {
      int32_t len = strlen(pDb->name) + 1;
      taosHashPut(pRsp->createdDbs, pDb->name, len, pDb->name, len);
    }

    sdbRelease(pSdb, pDb);
  }

  return 0;
}

S
Shengliang Guan 已提交
623 624
static int32_t mndProcessGetUserAuthReq(SNodeMsg *pReq) {
  SMnode         *pMnode = pReq->pNode;
S
Shengliang Guan 已提交
625 626 627 628 629
  int32_t         code = -1;
  SUserObj       *pUser = NULL;
  SGetUserAuthReq authReq = {0};
  SGetUserAuthRsp authRsp = {0};

S
Shengliang Guan 已提交
630 631
  if (tDeserializeSGetUserAuthReq(pReq->rpcMsg.pCont, pReq->rpcMsg.contLen, &authReq) != 0) {
    terrno = TSDB_CODE_INVALID_MSG;
632
    goto _OVER;
S
Shengliang Guan 已提交
633
  }
S
Shengliang Guan 已提交
634 635 636 637 638 639

  mTrace("user:%s, start to get auth", authReq.user);

  pUser = mndAcquireUser(pMnode, authReq.user);
  if (pUser == NULL) {
    terrno = TSDB_CODE_MND_USER_NOT_EXIST;
640
    goto _OVER;
S
Shengliang Guan 已提交
641 642
  }

D
dapan 已提交
643 644 645
  code = mndSetUserAuthRsp(pMnode, pUser, &authRsp);
  if (code) {
    goto _OVER;
S
Shengliang Guan 已提交
646 647
  }

S
Shengliang Guan 已提交
648
  int32_t contLen = tSerializeSGetUserAuthRsp(NULL, 0, &authRsp);
S
Shengliang Guan 已提交
649 650 651
  void   *pRsp = rpcMallocCont(contLen);
  if (pRsp == NULL) {
    terrno = TSDB_CODE_OUT_OF_MEMORY;
652
    goto _OVER;
S
Shengliang Guan 已提交
653 654
  }

S
Shengliang Guan 已提交
655
  tSerializeSGetUserAuthRsp(pRsp, contLen, &authRsp);
S
Shengliang Guan 已提交
656

S
Shengliang Guan 已提交
657 658
  pReq->pRsp = pRsp;
  pReq->rspLen = contLen;
S
Shengliang Guan 已提交
659 660
  code = 0;

661
_OVER:
D
dapan 已提交
662
  
S
Shengliang Guan 已提交
663
  mndReleaseUser(pMnode, pUser);
S
Shengliang Guan 已提交
664
  tFreeSGetUserAuthRsp(&authRsp);
S
Shengliang Guan 已提交
665 666 667 668

  return code;
}

669
static int32_t mndRetrieveUsers(SNodeMsg *pReq, SShowObj *pShow, SSDataBlock *pBlock, int32_t rows) {
S
Shengliang Guan 已提交
670
  SMnode   *pMnode = pReq->pNode;
S
Shengliang Guan 已提交
671 672 673 674 675 676 677 678 679 680 681
  SSdb     *pSdb = pMnode->pSdb;
  int32_t   numOfRows = 0;
  SUserObj *pUser = NULL;
  int32_t   cols = 0;
  char     *pWrite;

  while (numOfRows < rows) {
    pShow->pIter = sdbFetch(pSdb, SDB_USER, pShow->pIter, (void **)&pUser);
    if (pShow->pIter == NULL) break;

    cols = 0;
682
    SColumnInfoData *pColInfo = taosArrayGet(pBlock->pDataBlock, cols);
683 684

    char name[TSDB_USER_LEN + VARSTR_HEADER_SIZE] = {0};
685
    STR_WITH_MAXSIZE_TO_VARSTR(name, pUser->user, pShow->pMeta->pSchemas[cols].bytes);
686

687
    colDataAppend(pColInfo, numOfRows, (const char *)name, false);
688

wafwerar's avatar
wafwerar 已提交
689 690
    cols++;
    pColInfo = taosArrayGet(pBlock->pDataBlock, cols);
691

692 693
    const char *src = pUser->superUser ? "super" : "normal";
    char        b[10 + VARSTR_HEADER_SIZE] = {0};
694
    STR_WITH_SIZE_TO_VARSTR(b, src, strlen(src));
695
    colDataAppend(pColInfo, numOfRows, (const char *)b, false);
696

wafwerar's avatar
wafwerar 已提交
697 698
    cols++;
    pColInfo = taosArrayGet(pBlock->pDataBlock, cols);
699
    colDataAppend(pColInfo, numOfRows, (const char *)&pUser->createdTime, false);
S
Shengliang Guan 已提交
700 701 702 703 704

    numOfRows++;
    sdbRelease(pSdb, pUser);
  }

705
  pShow->numOfRows += numOfRows;
S
Shengliang Guan 已提交
706 707 708 709 710 711
  return numOfRows;
}

static void mndCancelGetNextUser(SMnode *pMnode, void *pIter) {
  SSdb *pSdb = pMnode->pSdb;
  sdbCancelFetch(pSdb, pIter);
S
Shengliang Guan 已提交
712
}
D
dapan 已提交
713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781

int32_t mndValidateUserAuthInfo(SMnode *pMnode, SUserAuthVersion *pUsers, int32_t numOfUses, void **ppRsp, int32_t *pRspLen) {
  SUserAuthBatchRsp batchRsp = {0};
  batchRsp.pArray = taosArrayInit(numOfUses, sizeof(SGetUserAuthRsp));
  if (batchRsp.pArray == NULL) {
    terrno = TSDB_CODE_OUT_OF_MEMORY;
    return -1;
  }

  int32_t code = 0;
  for (int32_t i = 0; i < numOfUses; ++i) {
    SUserObj *pUser = mndAcquireUser(pMnode, pUsers[i].user);
    if (pUser == NULL) {
      mError("user:%s, failed to auth user since %s", pUsers[i].user, terrstr());
      continue;
    }

    if (pUser->authVersion <= pUsers[i].version) {
      mndReleaseUser(pMnode, pUser);
      continue;
    }
    
    SGetUserAuthRsp rsp = {0};
    code = mndSetUserAuthRsp(pMnode, pUser, &rsp);
    if (code) {
      mndReleaseUser(pMnode, pUser);
      tFreeSGetUserAuthRsp(&rsp);
      goto _OVER;
    }


    taosArrayPush(batchRsp.pArray, &rsp);
    mndReleaseUser(pMnode, pUser);
  }

  if (taosArrayGetSize(batchRsp.pArray) <= 0) {
    *ppRsp = NULL;
    *pRspLen = 0;
    
    tFreeSUserAuthBatchRsp(&batchRsp);
    return 0;
  }

  int32_t rspLen = tSerializeSUserAuthBatchRsp(NULL, 0, &batchRsp);
  void   *pRsp = taosMemoryMalloc(rspLen);
  if (pRsp == NULL) {
    terrno = TSDB_CODE_OUT_OF_MEMORY;
    tFreeSUserAuthBatchRsp(&batchRsp);
    return -1;
  }
  tSerializeSUserAuthBatchRsp(pRsp, rspLen, &batchRsp);

  *ppRsp = pRsp;
  *pRspLen = rspLen;

  tFreeSUserAuthBatchRsp(&batchRsp);
  return 0;

_OVER:

  *ppRsp = NULL;
  *pRspLen = 0;
  
  tFreeSUserAuthBatchRsp(&batchRsp);
  return code;
}