diff --git a/include/common/tmsg.h b/include/common/tmsg.h index af5ca3def9..a090f6925c 100644 --- a/include/common/tmsg.h +++ b/include/common/tmsg.h @@ -135,7 +135,7 @@ typedef enum _mgmt_table { #define TSDB_ALTER_USER_CLEAR_READ_DB 0x5 #define TSDB_ALTER_USER_ADD_WRITE_DB 0x6 #define TSDB_ALTER_USER_REMOVE_WRITE_DB 0x7 -#define TSDB_ALTER_USER_CLEAR_WRITE_DB 0x7 +#define TSDB_ALTER_USER_CLEAR_WRITE_DB 0x8 #define TSDB_ALTER_USER_PRIVILEGES 0x2 @@ -371,15 +371,32 @@ void* tDeserializeSCreateUserReq(void* buf, SCreateUserReq* pReq); typedef struct { int8_t alterType; + int8_t superUser; char user[TSDB_USER_LEN]; char pass[TSDB_PASSWORD_LEN]; char dbname[TSDB_DB_FNAME_LEN]; - int8_t superUser; } SAlterUserReq; int32_t tSerializeSAlterUserReq(void** buf, SAlterUserReq* pReq); void* tDeserializeSAlterUserReq(void* buf, SAlterUserReq* pReq); +typedef struct { + char user[TSDB_USER_LEN]; +} SGetUserAuthReq; + +int32_t tSerializeSGetUserAuthReq(void** buf, SGetUserAuthReq* pReq); +void* tDeserializeSGetUserAuthReq(void* buf, SGetUserAuthReq* pReq); + +typedef struct { + char user[TSDB_USER_LEN]; + int8_t superAuth; + SHashObj* readDbs; + SHashObj* writeDbs; +} SGetUserAuthRsp; + +int32_t tSerializeSGetUserAuthRsp(void** buf, SGetUserAuthRsp* pReq); +void* tDeserializeSGetUserAuthRsp(void* buf, SGetUserAuthRsp* pReq); + typedef struct { int16_t colId; // column id int16_t colIndex; // column index in colList if it is a normal column or index in tagColList if a tag diff --git a/include/common/tmsgdef.h b/include/common/tmsgdef.h index f95fe8dd08..98d2b2c519 100644 --- a/include/common/tmsgdef.h +++ b/include/common/tmsgdef.h @@ -97,6 +97,7 @@ enum { TD_DEF_MSG_TYPE(TDMT_MND_CREATE_USER, "mnode-create-user", NULL, NULL) TD_DEF_MSG_TYPE(TDMT_MND_ALTER_USER, "mnode-alter-user", NULL, NULL) TD_DEF_MSG_TYPE(TDMT_MND_DROP_USER, "mnode-drop-user", NULL, NULL) + TD_DEF_MSG_TYPE(TDMT_MND_GET_USER_AUTH, "mnode-get-user-auth", NULL, NULL) TD_DEF_MSG_TYPE(TDMT_MND_CREATE_DNODE, "mnode-create-dnode", NULL, NULL) TD_DEF_MSG_TYPE(TDMT_MND_CONFIG_DNODE, "mnode-config-dnode", NULL, NULL) TD_DEF_MSG_TYPE(TDMT_MND_ALTER_DNODE, "mnode-alter-dnode", NULL, NULL) diff --git a/source/common/src/tmsg.c b/source/common/src/tmsg.c index 17120a6a5e..33add3eb6b 100644 --- a/source/common/src/tmsg.c +++ b/source/common/src/tmsg.c @@ -670,4 +670,72 @@ void *tDeserializeSAlterUserReq(void *buf, SAlterUserReq *pReq) { buf = taosDecodeStringTo(buf, pReq->dbname); buf = taosDecodeFixedI8(buf, &pReq->superUser); return buf; -} \ No newline at end of file +} + +int32_t tSerializeSGetUserAuthReq(void **buf, SGetUserAuthReq *pReq) { + int32_t tlen = 0; + tlen += taosEncodeString(buf, pReq->user); + return tlen; +} + +void *tDeserializeSGetUserAuthReq(void *buf, SGetUserAuthReq *pReq) { + buf = taosDecodeStringTo(buf, pReq->user); + return buf; +} + +int32_t tSerializeSGetUserAuthRsp(void **buf, SGetUserAuthRsp *pReq) { + int32_t tlen = 0; + tlen += taosEncodeString(buf, pReq->user); + tlen += taosEncodeFixedI8(buf, pReq->superAuth); + + int32_t numOfReadDbs = taosHashGetSize(pReq->readDbs); + int32_t numOfWriteDbs = taosHashGetSize(pReq->writeDbs); + tlen += taosEncodeFixedI32(buf, numOfReadDbs); + tlen += taosEncodeFixedI32(buf, numOfWriteDbs); + + char *db = taosHashIterate(pReq->readDbs, NULL); + while (db != NULL) { + tlen += taosEncodeString(buf, db); + db = taosHashIterate(pReq->readDbs, db); + } + + db = taosHashIterate(pReq->writeDbs, NULL); + while (db != NULL) { + tlen += taosEncodeString(buf, db); + db = taosHashIterate(pReq->writeDbs, db); + } + + return tlen; +} + +void *tDeserializeSGetUserAuthRsp(void *buf, SGetUserAuthRsp *pReq) { + buf = taosDecodeStringTo(buf, pReq->user); + buf = taosDecodeFixedI8(buf, &pReq->superAuth); + + pReq->readDbs = taosHashInit(4, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, false); + pReq->writeDbs = taosHashInit(4, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, false); + if (pReq->readDbs == NULL || pReq->writeDbs == NULL) { + return NULL; + } + + int32_t numOfReadDbs = 0; + int32_t numOfWriteDbs = 0; + buf = taosDecodeFixedI32(buf, &numOfReadDbs); + buf = taosDecodeFixedI32(buf, &numOfWriteDbs); + + for (int32_t i = 0; i < numOfReadDbs; ++i) { + char db[TSDB_DB_FNAME_LEN] = {0}; + buf = taosDecodeStringTo(buf, db); + int32_t len = strlen(db) + 1; + taosHashPut(pReq->readDbs, db, len, db, len); + } + + for (int32_t i = 0; i < numOfWriteDbs; ++i) { + char db[TSDB_DB_FNAME_LEN] = {0}; + buf = taosDecodeStringTo(buf, db); + int32_t len = strlen(db) + 1; + taosHashPut(pReq->writeDbs, db, len, db, len); + } + + return buf; +} diff --git a/source/dnode/mgmt/impl/src/dndTransport.c b/source/dnode/mgmt/impl/src/dndTransport.c index 257c72bff5..9b3ab40226 100644 --- a/source/dnode/mgmt/impl/src/dndTransport.c +++ b/source/dnode/mgmt/impl/src/dndTransport.c @@ -73,6 +73,7 @@ static void dndInitMsgFp(STransMgmt *pMgmt) { pMgmt->msgFp[TMSG_INDEX(TDMT_MND_CREATE_USER)] = dndProcessMnodeWriteMsg; pMgmt->msgFp[TMSG_INDEX(TDMT_MND_ALTER_USER)] = dndProcessMnodeWriteMsg; pMgmt->msgFp[TMSG_INDEX(TDMT_MND_DROP_USER)] = dndProcessMnodeWriteMsg; + pMgmt->msgFp[TMSG_INDEX(TDMT_MND_GET_USER_AUTH)] = dndProcessMnodeReadMsg; pMgmt->msgFp[TMSG_INDEX(TDMT_MND_CREATE_DNODE)] = dndProcessMnodeWriteMsg; pMgmt->msgFp[TMSG_INDEX(TDMT_MND_CONFIG_DNODE)] = dndProcessMnodeWriteMsg; pMgmt->msgFp[TMSG_INDEX(TDMT_MND_DROP_DNODE)] = dndProcessMnodeWriteMsg; diff --git a/source/dnode/mnode/impl/inc/mndAuth.h b/source/dnode/mnode/impl/inc/mndAuth.h index b426ce23cf..c37ae7add5 100644 --- a/source/dnode/mnode/impl/inc/mndAuth.h +++ b/source/dnode/mnode/impl/inc/mndAuth.h @@ -25,6 +25,10 @@ extern "C" { int32_t mndInitAuth(SMnode *pMnode); void mndCleanupAuth(SMnode *pMnode); +int32_t mndCheckCreateUserAuth(SUserObj *pOperUser); +int32_t mndCheckAlterUserAuth(SUserObj *pOperUser, SUserObj *pUser, SDbObj *pDb, SAlterUserReq *pAlter); +int32_t mndCheckDropUserAuth(SUserObj *pOperUser); + #ifdef __cplusplus } #endif diff --git a/source/dnode/mnode/impl/inc/mndDef.h b/source/dnode/mnode/impl/inc/mndDef.h index 7c346edbea..c4897a635c 100644 --- a/source/dnode/mnode/impl/inc/mndDef.h +++ b/source/dnode/mnode/impl/inc/mndDef.h @@ -261,7 +261,7 @@ typedef struct { typedef struct { char name[TSDB_DB_FNAME_LEN]; char acct[TSDB_USER_LEN]; - char createdUser[TSDB_USER_LEN]; + char createUser[TSDB_USER_LEN]; int64_t createdTime; int64_t updateTime; uint64_t uid; diff --git a/source/dnode/mnode/impl/src/mndAuth.c b/source/dnode/mnode/impl/src/mndAuth.c index 44a5836bd6..99b48adb85 100644 --- a/source/dnode/mnode/impl/src/mndAuth.c +++ b/source/dnode/mnode/impl/src/mndAuth.c @@ -56,4 +56,57 @@ static int32_t mndProcessAuthReq(SMnodeMsg *pReq) { int32_t code = mndRetriveAuth(pReq->pMnode, pAuth->user, &pRsp->spi, &pRsp->encrypt, pRsp->secret, pRsp->ckey); mTrace("user:%s, auth req received, spi:%d encrypt:%d ruser:%s", pReq->user, pAuth->spi, pAuth->encrypt, pAuth->user); return code; +} + +int32_t mndCheckCreateUserAuth(SUserObj *pOperUser) { + if (pOperUser->superUser) { + return 0; + } + + terrno = TSDB_CODE_MND_NO_RIGHTS; + return -1; +} + +int32_t mndCheckAlterUserAuth(SUserObj *pOperUser, SUserObj *pUser, SDbObj *pDb, SAlterUserReq *pAlter) { + if (pAlter->alterType == TSDB_ALTER_USER_PASSWD) { + if (pOperUser->superUser || strcmp(pUser->user, pOperUser->user) == 0) { + return 0; + } + } + + if (pAlter->alterType == TSDB_ALTER_USER_SUPERUSER) { + if (strcmp(pUser->user, TSDB_DEFAULT_USER) == 0) { + terrno = TSDB_CODE_MND_NO_RIGHTS; + return -1; + } + + if (pOperUser->superUser) { + return 0; + } + } + + if (pAlter->alterType == TSDB_ALTER_USER_CLEAR_WRITE_DB || pAlter->alterType == TSDB_ALTER_USER_CLEAR_READ_DB) { + if (pOperUser->superUser) { + return 0; + } + } + + if (pAlter->alterType == TSDB_ALTER_USER_ADD_READ_DB || pAlter->alterType == TSDB_ALTER_USER_REMOVE_READ_DB || + pAlter->alterType == TSDB_ALTER_USER_ADD_WRITE_DB || pAlter->alterType == TSDB_ALTER_USER_REMOVE_WRITE_DB) { + if (pOperUser->superUser || strcmp(pUser->user, pDb->createUser) == 0) { + return 0; + } + } + + terrno = TSDB_CODE_MND_NO_RIGHTS; + return -1; +} + +int32_t mndCheckDropUserAuth(SUserObj *pOperUser) { + if (pOperUser->superUser) { + return 0; + } + + terrno = TSDB_CODE_MND_NO_RIGHTS; + return -1; } \ No newline at end of file diff --git a/source/dnode/mnode/impl/src/mndDb.c b/source/dnode/mnode/impl/src/mndDb.c index 04c6c3dfa8..5ed3e9e8df 100644 --- a/source/dnode/mnode/impl/src/mndDb.c +++ b/source/dnode/mnode/impl/src/mndDb.c @@ -73,7 +73,7 @@ static SSdbRaw *mndDbActionEncode(SDbObj *pDb) { int32_t dataPos = 0; SDB_SET_BINARY(pRaw, dataPos, pDb->name, TSDB_DB_FNAME_LEN, DB_ENCODE_OVER) SDB_SET_BINARY(pRaw, dataPos, pDb->acct, TSDB_USER_LEN, DB_ENCODE_OVER) - SDB_SET_BINARY(pRaw, dataPos, pDb->createdUser, TSDB_USER_LEN, DB_ENCODE_OVER) + SDB_SET_BINARY(pRaw, dataPos, pDb->createUser, TSDB_USER_LEN, DB_ENCODE_OVER) SDB_SET_INT64(pRaw, dataPos, pDb->createdTime, DB_ENCODE_OVER) SDB_SET_INT64(pRaw, dataPos, pDb->updateTime, DB_ENCODE_OVER) SDB_SET_INT64(pRaw, dataPos, pDb->uid, DB_ENCODE_OVER) @@ -134,7 +134,7 @@ static SSdbRow *mndDbActionDecode(SSdbRaw *pRaw) { int32_t dataPos = 0; SDB_GET_BINARY(pRaw, dataPos, pDb->name, TSDB_DB_FNAME_LEN, DB_DECODE_OVER) SDB_GET_BINARY(pRaw, dataPos, pDb->acct, TSDB_USER_LEN, DB_DECODE_OVER) - SDB_GET_BINARY(pRaw, dataPos, pDb->createdUser, TSDB_USER_LEN, DB_DECODE_OVER) + SDB_GET_BINARY(pRaw, dataPos, pDb->createUser, TSDB_USER_LEN, DB_DECODE_OVER) SDB_GET_INT64(pRaw, dataPos, &pDb->createdTime, DB_DECODE_OVER) SDB_GET_INT64(pRaw, dataPos, &pDb->updateTime, DB_DECODE_OVER) SDB_GET_INT64(pRaw, dataPos, &pDb->uid, DB_DECODE_OVER) @@ -390,6 +390,7 @@ static int32_t mndCreateDb(SMnode *pMnode, SMnodeMsg *pReq, SCreateDbReq *pCreat dbObj.cfgVersion = 1; dbObj.vgVersion = 1; dbObj.hashMethod = 1; + memcpy(dbObj.createUser, pUser->user, TSDB_USER_LEN); dbObj.cfg = (SDbCfg){.numOfVgroups = pCreate->numOfVgroups, .cacheBlockSize = pCreate->cacheBlockSize, .totalBlocks = pCreate->totalBlocks, diff --git a/source/dnode/mnode/impl/src/mndUser.c b/source/dnode/mnode/impl/src/mndUser.c index 9703b73b1e..b54200f114 100644 --- a/source/dnode/mnode/impl/src/mndUser.c +++ b/source/dnode/mnode/impl/src/mndUser.c @@ -15,6 +15,7 @@ #define _DEFAULT_SOURCE #include "mndUser.h" +#include "mndAuth.h" #include "mndDb.h" #include "mndShow.h" #include "mndTrans.h" @@ -29,10 +30,11 @@ static SSdbRow *mndUserActionDecode(SSdbRaw *pRaw); static int32_t mndUserActionInsert(SSdb *pSdb, SUserObj *pUser); static int32_t mndUserActionDelete(SSdb *pSdb, SUserObj *pUser); static int32_t mndUserActionUpdate(SSdb *pSdb, SUserObj *pOld, SUserObj *pNew); -static int32_t mndCreateUser(SMnode *pMnode, char *acct, char *user, char *pass, SMnodeMsg *pReq); +static int32_t mndCreateUser(SMnode *pMnode, char *acct, SCreateUserReq *pCreate, SMnodeMsg *pReq); static int32_t mndProcessCreateUserReq(SMnodeMsg *pReq); static int32_t mndProcessAlterUserReq(SMnodeMsg *pReq); static int32_t mndProcessDropUserReq(SMnodeMsg *pReq); +static int32_t mndProcessGetUserAuthReq(SMnodeMsg *pReq); static int32_t mndGetUserMeta(SMnodeMsg *pReq, SShowObj *pShow, STableMetaRsp *pMeta); static int32_t mndRetrieveUsers(SMnodeMsg *pReq, SShowObj *pShow, char *data, int32_t rows); static void mndCancelGetNextUser(SMnode *pMnode, void *pIter); @@ -50,6 +52,7 @@ int32_t mndInitUser(SMnode *pMnode) { mndSetMsgHandle(pMnode, TDMT_MND_CREATE_USER, mndProcessCreateUserReq); mndSetMsgHandle(pMnode, TDMT_MND_ALTER_USER, mndProcessAlterUserReq); mndSetMsgHandle(pMnode, TDMT_MND_DROP_USER, mndProcessDropUserReq); + mndSetMsgHandle(pMnode, TDMT_MND_GET_USER_AUTH, mndProcessGetUserAuthReq); mndAddShowMetaHandle(pMnode, TSDB_MGMT_TABLE_USER, mndGetUserMeta); mndAddShowRetrieveHandle(pMnode, TSDB_MGMT_TABLE_USER, mndRetrieveUsers); @@ -96,7 +99,11 @@ static int32_t mndCreateDefaultUsers(SMnode *pMnode) { static SSdbRaw *mndUserActionEncode(SUserObj *pUser) { terrno = TSDB_CODE_OUT_OF_MEMORY; - SSdbRaw *pRaw = sdbAllocRaw(SDB_USER, TSDB_USER_VER_NUMBER, sizeof(SUserObj) + TSDB_USER_RESERVE_SIZE); + int32_t numOfReadDbs = taosHashGetSize(pUser->readDbs); + int32_t numOfWriteDbs = taosHashGetSize(pUser->writeDbs); + int32_t size = sizeof(SUserObj) + TSDB_USER_RESERVE_SIZE + (numOfReadDbs + numOfWriteDbs) * TSDB_DB_FNAME_LEN; + + SSdbRaw *pRaw = sdbAllocRaw(SDB_USER, TSDB_USER_VER_NUMBER, size); if (pRaw == NULL) goto USER_ENCODE_OVER; int32_t dataPos = 0; @@ -106,9 +113,6 @@ static SSdbRaw *mndUserActionEncode(SUserObj *pUser) { SDB_SET_INT64(pRaw, dataPos, pUser->createdTime, USER_ENCODE_OVER) SDB_SET_INT64(pRaw, dataPos, pUser->updateTime, USER_ENCODE_OVER) SDB_SET_INT8(pRaw, dataPos, pUser->superUser, USER_ENCODE_OVER) - - int32_t numOfReadDbs = taosHashGetSize(pUser->readDbs); - int32_t numOfWriteDbs = taosHashGetSize(pUser->writeDbs); SDB_SET_INT32(pRaw, dataPos, numOfReadDbs, USER_ENCODE_OVER) SDB_SET_INT32(pRaw, dataPos, numOfWriteDbs, USER_ENCODE_OVER) @@ -257,21 +261,21 @@ void mndReleaseUser(SMnode *pMnode, SUserObj *pUser) { sdbRelease(pSdb, pUser); } -static int32_t mndCreateUser(SMnode *pMnode, char *acct, char *user, char *pass, SMnodeMsg *pReq) { +static int32_t mndCreateUser(SMnode *pMnode, char *acct, SCreateUserReq *pCreate, SMnodeMsg *pReq) { SUserObj userObj = {0}; - taosEncryptPass_c((uint8_t *)pass, strlen(pass), userObj.pass); - tstrncpy(userObj.user, user, TSDB_USER_LEN); + taosEncryptPass_c((uint8_t *)pCreate->pass, strlen(pCreate->pass), userObj.pass); + tstrncpy(userObj.user, pCreate->user, TSDB_USER_LEN); tstrncpy(userObj.acct, acct, TSDB_USER_LEN); userObj.createdTime = taosGetTimestampMs(); userObj.updateTime = userObj.createdTime; - userObj.superUser = 0; + userObj.superUser = pCreate->superUser; STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_ROLLBACK, &pReq->rpcMsg); if (pTrans == NULL) { - mError("user:%s, failed to create since %s", user, terrstr()); + mError("user:%s, failed to create since %s", pCreate->user, terrstr()); return -1; } - mDebug("trans:%d, used to create user:%s", pTrans->id, user); + mDebug("trans:%d, used to create user:%s", pTrans->id, pCreate->user); SSdbRaw *pRedoRaw = mndUserActionEncode(&userObj); if (pRedoRaw == NULL || mndTransAppendRedolog(pTrans, pRedoRaw) != 0) { @@ -324,7 +328,11 @@ static int32_t mndProcessCreateUserReq(SMnodeMsg *pReq) { goto CREATE_USER_OVER; } - code = mndCreateUser(pMnode, pOperUser->acct, createReq.user, createReq.pass, pReq); + if (mndCheckCreateUserAuth(pOperUser) != 0) { + goto CREATE_USER_OVER; + } + + code = mndCreateUser(pMnode, pOperUser->acct, &createReq, pReq); if (code == 0) code = TSDB_CODE_MND_ACTION_IN_PROGRESS; CREATE_USER_OVER: @@ -391,6 +399,7 @@ static int32_t mndProcessAlterUserReq(SMnodeMsg *pReq) { int32_t code = -1; SUserObj *pUser = NULL; SUserObj *pOperUser = NULL; + SUserObj newUser = {0}; SAlterUserReq alterReq = {0}; if (tDeserializeSAlterUserReq(pReq->rpcMsg.pCont, &alterReq) == NULL) goto ALTER_USER_OVER; @@ -419,7 +428,6 @@ static int32_t mndProcessAlterUserReq(SMnodeMsg *pReq) { goto ALTER_USER_OVER; } - SUserObj newUser = {0}; memcpy(&newUser, pUser, sizeof(SUserObj)); newUser.readDbs = mndDupDbHash(pUser->readDbs); newUser.writeDbs = mndDupDbHash(pUser->writeDbs); @@ -435,9 +443,9 @@ static int32_t mndProcessAlterUserReq(SMnodeMsg *pReq) { char pass[TSDB_PASSWORD_LEN + 1] = {0}; taosEncryptPass_c((uint8_t *)alterReq.pass, strlen(alterReq.pass), pass); memcpy(pUser->pass, pass, TSDB_PASSWORD_LEN); - } else if (alterReq.alterType == TSDB_ALTER_USER_SUPERUSER) { + } else if (alterReq.alterType == TSDB_ALTER_USER_SUPERUSER) { newUser.superUser = alterReq.superUser; - } else if (alterReq.alterType == TSDB_ALTER_USER_ADD_READ_DB) { + } else if (alterReq.alterType == TSDB_ALTER_USER_ADD_READ_DB) { if (pDb == NULL) { terrno = TSDB_CODE_MND_DB_NOT_EXIST; goto ALTER_USER_OVER; @@ -446,12 +454,12 @@ static int32_t mndProcessAlterUserReq(SMnodeMsg *pReq) { terrno = TSDB_CODE_OUT_OF_MEMORY; goto ALTER_USER_OVER; } - } else if (alterReq.alterType == TSDB_ALTER_USER_REMOVE_READ_DB) { + } else if (alterReq.alterType == TSDB_ALTER_USER_REMOVE_READ_DB) { if (taosHashRemove(newUser.readDbs, alterReq.dbname, len) != 0) { terrno = TSDB_CODE_MND_DB_NOT_EXIST; goto ALTER_USER_OVER; } - } else if (alterReq.alterType == TSDB_ALTER_USER_CLEAR_READ_DB) { + } else if (alterReq.alterType == TSDB_ALTER_USER_CLEAR_READ_DB) { taosHashClear(newUser.readDbs); } else if (alterReq.alterType == TSDB_ALTER_USER_ADD_WRITE_DB) { if (pDb == NULL) { @@ -467,7 +475,7 @@ static int32_t mndProcessAlterUserReq(SMnodeMsg *pReq) { terrno = TSDB_CODE_MND_DB_NOT_EXIST; goto ALTER_USER_OVER; } - } else if (alterReq.alterType == TSDB_ALTER_USER_CLEAR_WRITE_DB) { + } else if (alterReq.alterType == TSDB_ALTER_USER_CLEAR_WRITE_DB) { taosHashClear(newUser.writeDbs); } else { terrno = TSDB_CODE_MND_INVALID_ALTER_OPER; @@ -476,17 +484,22 @@ static int32_t mndProcessAlterUserReq(SMnodeMsg *pReq) { newUser.updateTime = taosGetTimestampMs(); + if (mndCheckAlterUserAuth(pOperUser, pUser, pDb, &alterReq) != 0) { + goto ALTER_USER_OVER; + } + code = mndUpdateUser(pMnode, pUser, &newUser, pReq); if (code == 0) code = TSDB_CODE_MND_ACTION_IN_PROGRESS; ALTER_USER_OVER: - if (code != 0 && code != TSDB_CODE_MND_ACTION_IN_PROGRESS) { mError("user:%s, failed to alter since %s", alterReq.user, terrstr()); } mndReleaseUser(pMnode, pOperUser); mndReleaseUser(pMnode, pUser); + taosHashCleanup(newUser.writeDbs); + taosHashCleanup(newUser.readDbs); return code; } @@ -545,6 +558,10 @@ static int32_t mndProcessDropUserReq(SMnodeMsg *pReq) { goto DROP_USER_OVER; } + if (mndCheckDropUserAuth(pOperUser) != 0) { + goto DROP_USER_OVER; + } + code = mndDropUser(pMnode, pReq, pUser); if (code == 0) code = TSDB_CODE_MND_ACTION_IN_PROGRESS; @@ -559,6 +576,66 @@ DROP_USER_OVER: return code; } +static int32_t mndProcessGetUserAuthReq(SMnodeMsg *pReq) { + SMnode *pMnode = pReq->pMnode; + int32_t code = -1; + SUserObj *pUser = NULL; + SGetUserAuthReq authReq = {0}; + SGetUserAuthRsp authRsp = {0}; + + if (tDeserializeSGetUserAuthReq(pReq->rpcMsg.pCont, &authReq) == NULL) goto GET_AUTH_OVER; + + mTrace("user:%s, start to get auth", authReq.user); + + pUser = mndAcquireUser(pMnode, authReq.user); + if (pUser == NULL) { + terrno = TSDB_CODE_MND_USER_NOT_EXIST; + goto GET_AUTH_OVER; + } + + memcpy(authRsp.user, pUser->user, TSDB_USER_LEN); + authRsp.superAuth = pUser->superUser; + authRsp.readDbs = mndDupDbHash(pUser->readDbs); + authRsp.writeDbs = mndDupDbHash(pUser->writeDbs); + + 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(authRsp.readDbs, pDb->name, len, pDb->name, len); + taosHashPut(authRsp.writeDbs, pDb->name, len, pDb->name, len); + } + + sdbRelease(pSdb, pDb); + } + + int32_t contLen = tSerializeSGetUserAuthRsp(NULL, &authRsp); + void *pRsp = rpcMallocCont(contLen); + if (pRsp == NULL) { + terrno = TSDB_CODE_OUT_OF_MEMORY; + goto GET_AUTH_OVER; + } + + void *pBuf = pRsp; + tSerializeSGetUserAuthRsp(&pBuf, &authRsp); + + pReq->pCont = pRsp; + pReq->contLen = contLen; + code = 0; + +GET_AUTH_OVER: + mndReleaseUser(pMnode, pUser); + taosHashCleanup(authRsp.readDbs); + taosHashCleanup(authRsp.writeDbs); + + return code; +} + static int32_t mndGetUserMeta(SMnodeMsg *pReq, SShowObj *pShow, STableMetaRsp *pMeta) { SMnode *pMnode = pReq->pMnode; SSdb *pSdb = pMnode->pSdb; @@ -653,4 +730,4 @@ static int32_t mndRetrieveUsers(SMnodeMsg *pReq, SShowObj *pShow, char *data, in static void mndCancelGetNextUser(SMnode *pMnode, void *pIter) { SSdb *pSdb = pMnode->pSdb; sdbCancelFetch(pSdb, pIter); -} \ No newline at end of file +} diff --git a/source/dnode/mnode/impl/test/user/user.cpp b/source/dnode/mnode/impl/test/user/user.cpp index a86566a778..5d8c958f15 100644 --- a/source/dnode/mnode/impl/test/user/user.cpp +++ b/source/dnode/mnode/impl/test/user/user.cpp @@ -102,16 +102,108 @@ TEST_F(MndTestUser, 02_Create_User) { SRpcMsg* pRsp = test.SendReq(TDMT_MND_CREATE_USER, pReq, contLen); ASSERT_NE(pRsp, nullptr); ASSERT_EQ(pRsp->code, 0); + + test.SendShowMetaReq(TSDB_MGMT_TABLE_USER, ""); + test.SendShowRetrieveReq(); + EXPECT_EQ(test.GetShowRows(), 2); + + CheckBinary("u1", TSDB_USER_LEN); + CheckBinary("root", TSDB_USER_LEN); + CheckBinary("normal", 10); + CheckBinary("super", 10); + CheckTimestamp(); + CheckTimestamp(); + CheckBinary("root", TSDB_USER_LEN); + CheckBinary("root", TSDB_USER_LEN); } - test.SendShowMetaReq(TSDB_MGMT_TABLE_USER, ""); - CHECK_META("show users", 4); + { + SDropUserReq dropReq = {0}; + strcpy(dropReq.user, "u1"); - test.SendShowRetrieveReq(); - EXPECT_EQ(test.GetShowRows(), 2); + int32_t contLen = tSerializeSDropUserReq(NULL, &dropReq); + void* pReq = rpcMallocCont(contLen); + void* pBuf = pReq; + tSerializeSDropUserReq(&pBuf, &dropReq); + + SRpcMsg* pRsp = test.SendReq(TDMT_MND_DROP_USER, pReq, contLen); + ASSERT_NE(pRsp, nullptr); + ASSERT_EQ(pRsp->code, 0); + + test.SendShowMetaReq(TSDB_MGMT_TABLE_USER, ""); + test.SendShowRetrieveReq(); + EXPECT_EQ(test.GetShowRows(), 1); + } + + { + SCreateUserReq createReq = {0}; + strcpy(createReq.user, "u2"); + strcpy(createReq.pass, "p1"); + createReq.superUser = 1; + + int32_t contLen = tSerializeSCreateUserReq(NULL, &createReq); + void* pReq = rpcMallocCont(contLen); + void* pBuf = pReq; + tSerializeSCreateUserReq(&pBuf, &createReq); + + SRpcMsg* pRsp = test.SendReq(TDMT_MND_CREATE_USER, pReq, contLen); + ASSERT_NE(pRsp, nullptr); + ASSERT_EQ(pRsp->code, 0); + + test.SendShowMetaReq(TSDB_MGMT_TABLE_USER, ""); + test.SendShowRetrieveReq(); + EXPECT_EQ(test.GetShowRows(), 2); + + CheckBinary("root", TSDB_USER_LEN); + CheckBinary("u2", TSDB_USER_LEN); + CheckBinary("super", 10); + CheckBinary("super", 10); + CheckTimestamp(); + CheckTimestamp(); + CheckBinary("root", TSDB_USER_LEN); + CheckBinary("root", TSDB_USER_LEN); + } + + { + SDropUserReq dropReq = {0}; + strcpy(dropReq.user, "u2"); + + int32_t contLen = tSerializeSDropUserReq(NULL, &dropReq); + void* pReq = rpcMallocCont(contLen); + void* pBuf = pReq; + tSerializeSDropUserReq(&pBuf, &dropReq); + + SRpcMsg* pRsp = test.SendReq(TDMT_MND_DROP_USER, pReq, contLen); + ASSERT_NE(pRsp, nullptr); + ASSERT_EQ(pRsp->code, 0); + + test.SendShowMetaReq(TSDB_MGMT_TABLE_USER, ""); + test.SendShowRetrieveReq(); + EXPECT_EQ(test.GetShowRows(), 1); + } } TEST_F(MndTestUser, 03_Alter_User) { + { + SCreateUserReq createReq = {0}; + strcpy(createReq.user, "u3"); + strcpy(createReq.pass, "p1"); + createReq.superUser = 1; + + int32_t contLen = tSerializeSCreateUserReq(NULL, &createReq); + void* pReq = rpcMallocCont(contLen); + void* pBuf = pReq; + tSerializeSCreateUserReq(&pBuf, &createReq); + + SRpcMsg* pRsp = test.SendReq(TDMT_MND_CREATE_USER, pReq, contLen); + ASSERT_NE(pRsp, nullptr); + ASSERT_EQ(pRsp->code, 0); + + test.SendShowMetaReq(TSDB_MGMT_TABLE_USER, ""); + test.SendShowRetrieveReq(); + EXPECT_EQ(test.GetShowRows(), 2); + } + { SAlterUserReq alterReq = {0}; alterReq.alterType = TSDB_ALTER_USER_PASSWD; @@ -131,7 +223,7 @@ TEST_F(MndTestUser, 03_Alter_User) { { SAlterUserReq alterReq = {0}; alterReq.alterType = TSDB_ALTER_USER_PASSWD; - strcpy(alterReq.user, "u1"); + strcpy(alterReq.user, "u3"); strcpy(alterReq.pass, ""); int32_t contLen = tSerializeSAlterUserReq(NULL, &alterReq); @@ -163,7 +255,7 @@ TEST_F(MndTestUser, 03_Alter_User) { { SAlterUserReq alterReq = {0}; alterReq.alterType = TSDB_ALTER_USER_PASSWD; - strcpy(alterReq.user, "u1"); + strcpy(alterReq.user, "u3"); strcpy(alterReq.pass, "1"); int32_t contLen = tSerializeSAlterUserReq(NULL, &alterReq); @@ -175,9 +267,202 @@ TEST_F(MndTestUser, 03_Alter_User) { ASSERT_NE(pRsp, nullptr); ASSERT_EQ(pRsp->code, 0); } + + { + SAlterUserReq alterReq = {0}; + alterReq.alterType = TSDB_ALTER_USER_SUPERUSER; + strcpy(alterReq.user, "u3"); + strcpy(alterReq.pass, "1"); + alterReq.superUser = 1; + + int32_t contLen = tSerializeSAlterUserReq(NULL, &alterReq); + void* pReq = rpcMallocCont(contLen); + void* pBuf = pReq; + tSerializeSAlterUserReq(&pBuf, &alterReq); + + SRpcMsg* pRsp = test.SendReq(TDMT_MND_ALTER_USER, pReq, contLen); + ASSERT_NE(pRsp, nullptr); + ASSERT_EQ(pRsp->code, 0); + } + + { + SAlterUserReq alterReq = {0}; + alterReq.alterType = TSDB_ALTER_USER_CLEAR_WRITE_DB; + strcpy(alterReq.user, "u3"); + strcpy(alterReq.pass, "1"); + + int32_t contLen = tSerializeSAlterUserReq(NULL, &alterReq); + void* pReq = rpcMallocCont(contLen); + void* pBuf = pReq; + tSerializeSAlterUserReq(&pBuf, &alterReq); + + SRpcMsg* pRsp = test.SendReq(TDMT_MND_ALTER_USER, pReq, contLen); + ASSERT_NE(pRsp, nullptr); + ASSERT_EQ(pRsp->code, 0); + } + + { + SAlterUserReq alterReq = {0}; + alterReq.alterType = TSDB_ALTER_USER_CLEAR_READ_DB; + strcpy(alterReq.user, "u3"); + strcpy(alterReq.pass, "1"); + + int32_t contLen = tSerializeSAlterUserReq(NULL, &alterReq); + void* pReq = rpcMallocCont(contLen); + void* pBuf = pReq; + tSerializeSAlterUserReq(&pBuf, &alterReq); + + SRpcMsg* pRsp = test.SendReq(TDMT_MND_ALTER_USER, pReq, contLen); + ASSERT_NE(pRsp, nullptr); + ASSERT_EQ(pRsp->code, 0); + } + + { + SAlterUserReq alterReq = {0}; + alterReq.alterType = TSDB_ALTER_USER_ADD_READ_DB; + strcpy(alterReq.user, "u3"); + strcpy(alterReq.pass, "1"); + strcpy(alterReq.dbname, "d1"); + + int32_t contLen = tSerializeSAlterUserReq(NULL, &alterReq); + void* pReq = rpcMallocCont(contLen); + void* pBuf = pReq; + tSerializeSAlterUserReq(&pBuf, &alterReq); + + SRpcMsg* pRsp = test.SendReq(TDMT_MND_ALTER_USER, pReq, contLen); + ASSERT_NE(pRsp, nullptr); + ASSERT_EQ(pRsp->code, TSDB_CODE_MND_DB_NOT_EXIST); + } + + { + int32_t contLen = sizeof(SCreateDbReq); + + SCreateDbReq* pReq = (SCreateDbReq*)rpcMallocCont(contLen); + strcpy(pReq->db, "1.d2"); + pReq->numOfVgroups = htonl(2); + pReq->cacheBlockSize = htonl(16); + pReq->totalBlocks = htonl(10); + pReq->daysPerFile = htonl(10); + pReq->daysToKeep0 = htonl(3650); + pReq->daysToKeep1 = htonl(3650); + pReq->daysToKeep2 = htonl(3650); + pReq->minRows = htonl(100); + pReq->maxRows = htonl(4096); + pReq->commitTime = htonl(3600); + pReq->fsyncPeriod = htonl(3000); + pReq->walLevel = 1; + pReq->precision = 0; + pReq->compression = 2; + pReq->replications = 1; + pReq->quorum = 1; + pReq->update = 0; + pReq->cacheLastRow = 0; + pReq->ignoreExist = 1; + + SRpcMsg* pRsp = test.SendReq(TDMT_MND_CREATE_DB, pReq, contLen); + ASSERT_NE(pRsp, nullptr); + ASSERT_EQ(pRsp->code, 0); + } + + { + SAlterUserReq alterReq = {0}; + alterReq.alterType = TSDB_ALTER_USER_ADD_READ_DB; + strcpy(alterReq.user, "u3"); + strcpy(alterReq.pass, "1"); + strcpy(alterReq.dbname, "1.d2"); + + int32_t contLen = tSerializeSAlterUserReq(NULL, &alterReq); + void* pReq = rpcMallocCont(contLen); + void* pBuf = pReq; + tSerializeSAlterUserReq(&pBuf, &alterReq); + + SRpcMsg* pRsp = test.SendReq(TDMT_MND_ALTER_USER, pReq, contLen); + ASSERT_NE(pRsp, nullptr); + ASSERT_EQ(pRsp->code, 0); + } + + { + SAlterUserReq alterReq = {0}; + alterReq.alterType = TSDB_ALTER_USER_ADD_READ_DB; + strcpy(alterReq.user, "u3"); + strcpy(alterReq.pass, "1"); + strcpy(alterReq.dbname, "1.d2"); + + int32_t contLen = tSerializeSAlterUserReq(NULL, &alterReq); + void* pReq = rpcMallocCont(contLen); + void* pBuf = pReq; + tSerializeSAlterUserReq(&pBuf, &alterReq); + + SRpcMsg* pRsp = test.SendReq(TDMT_MND_ALTER_USER, pReq, contLen); + ASSERT_NE(pRsp, nullptr); + ASSERT_EQ(pRsp->code, 0); + } + + { + SGetUserAuthReq authReq = {0}; + strcpy(authReq.user, "u3"); + int32_t contLen = tSerializeSGetUserAuthReq(NULL, &authReq); + void* pReq = rpcMallocCont(contLen); + void* pBuf = pReq; + tSerializeSGetUserAuthReq(&pBuf, &authReq); + + SRpcMsg* pRsp = test.SendReq(TDMT_MND_GET_USER_AUTH, pReq, contLen); + ASSERT_NE(pRsp, nullptr); + ASSERT_EQ(pRsp->code, 0); + + SGetUserAuthRsp authRsp = {0}; + tDeserializeSGetUserAuthRsp(pRsp->pCont, &authRsp); + EXPECT_STREQ(authRsp.user, "u3"); + EXPECT_EQ(authRsp.superAuth, 1); + int32_t numOfReadDbs = taosHashGetSize(authRsp.readDbs); + int32_t numOfWriteDbs = taosHashGetSize(authRsp.writeDbs); + EXPECT_EQ(numOfReadDbs, 1); + EXPECT_EQ(numOfWriteDbs, 0); + + char* dbname = (char*)taosHashGet(authRsp.readDbs, "1.d2", 5); + EXPECT_STREQ(dbname, "1.d2"); + + taosHashCleanup(authRsp.readDbs); + taosHashCleanup(authRsp.writeDbs); + } + + { + SAlterUserReq alterReq = {0}; + alterReq.alterType = TSDB_ALTER_USER_REMOVE_READ_DB; + strcpy(alterReq.user, "u3"); + strcpy(alterReq.pass, "1"); + strcpy(alterReq.dbname, "1.d2"); + + int32_t contLen = tSerializeSAlterUserReq(NULL, &alterReq); + void* pReq = rpcMallocCont(contLen); + void* pBuf = pReq; + tSerializeSAlterUserReq(&pBuf, &alterReq); + + SRpcMsg* pRsp = test.SendReq(TDMT_MND_ALTER_USER, pReq, contLen); + ASSERT_NE(pRsp, nullptr); + ASSERT_EQ(pRsp->code, 0); + } + + { + SDropUserReq dropReq = {0}; + strcpy(dropReq.user, "u3"); + + int32_t contLen = tSerializeSDropUserReq(NULL, &dropReq); + void* pReq = rpcMallocCont(contLen); + void* pBuf = pReq; + tSerializeSDropUserReq(&pBuf, &dropReq); + + SRpcMsg* pRsp = test.SendReq(TDMT_MND_DROP_USER, pReq, contLen); + ASSERT_NE(pRsp, nullptr); + ASSERT_EQ(pRsp->code, 0); + + test.SendShowMetaReq(TSDB_MGMT_TABLE_USER, ""); + test.SendShowRetrieveReq(); + EXPECT_EQ(test.GetShowRows(), 1); + } } -TEST_F(MndTestUser, 04_Drop_User) { +TEST_F(MndTestUser, 05_Drop_User) { { SDropUserReq dropReq = {0}; strcpy(dropReq.user, ""); @@ -206,6 +491,21 @@ TEST_F(MndTestUser, 04_Drop_User) { ASSERT_EQ(pRsp->code, TSDB_CODE_MND_USER_NOT_EXIST); } + { + SCreateUserReq createReq = {0}; + strcpy(createReq.user, "u1"); + strcpy(createReq.pass, "p1"); + + int32_t contLen = tSerializeSCreateUserReq(NULL, &createReq); + void* pReq = rpcMallocCont(contLen); + void* pBuf = pReq; + tSerializeSCreateUserReq(&pBuf, &createReq); + + SRpcMsg* pRsp = test.SendReq(TDMT_MND_CREATE_USER, pReq, contLen); + ASSERT_NE(pRsp, nullptr); + ASSERT_EQ(pRsp->code, 0); + } + { SDropUserReq dropReq = {0}; strcpy(dropReq.user, "u1"); @@ -227,7 +527,7 @@ TEST_F(MndTestUser, 04_Drop_User) { EXPECT_EQ(test.GetShowRows(), 1); } -TEST_F(MndTestUser, 05_Create_Drop_Alter_User) { +TEST_F(MndTestUser, 06_Create_Drop_Alter_User) { { SCreateUserReq createReq = {0}; strcpy(createReq.user, "u1");