From 4bb7a25fc7491f5f1722b8994c646f94fa3c6ec0 Mon Sep 17 00:00:00 2001 From: Xiaoyu Wang Date: Sun, 23 Apr 2023 16:30:28 +0800 Subject: [PATCH] feat: subtable level privilege --- include/common/tmsg.h | 1 + source/common/src/tmsg.c | 9 +- source/dnode/mnode/impl/src/mndUser.c | 2 + source/libs/catalog/src/ctgUtil.c | 9 +- source/libs/nodes/src/nodesUtilFuncs.c | 8 +- source/libs/parser/src/parAuthenticator.c | 15 +- source/libs/parser/src/parTranslater.c | 4 +- tests/script/tsim/user/privilege_table.sim | 280 +++++++++++++++++++++ 8 files changed, 307 insertions(+), 21 deletions(-) create mode 100644 tests/script/tsim/user/privilege_table.sim diff --git a/include/common/tmsg.h b/include/common/tmsg.h index 02c097b8d0..df76edffc9 100644 --- a/include/common/tmsg.h +++ b/include/common/tmsg.h @@ -689,6 +689,7 @@ typedef struct { int32_t tSerializeSAlterUserReq(void* buf, int32_t bufLen, SAlterUserReq* pReq); int32_t tDeserializeSAlterUserReq(void* buf, int32_t bufLen, SAlterUserReq* pReq); +void tFreeSAlterUserReq(SAlterUserReq* pReq); typedef struct { char user[TSDB_USER_LEN]; diff --git a/source/common/src/tmsg.c b/source/common/src/tmsg.c index d9802244b7..189fa1326f 100644 --- a/source/common/src/tmsg.c +++ b/source/common/src/tmsg.c @@ -1409,6 +1409,8 @@ int32_t tDeserializeSAlterUserReq(void *buf, int32_t bufLen, SAlterUserReq *pReq return 0; } +void tFreeSAlterUserReq(SAlterUserReq *pReq) { taosMemoryFreeClear(pReq->tagCond); } + int32_t tSerializeSGetUserAuthReq(void *buf, int32_t bufLen, SGetUserAuthReq *pReq) { SEncoder encoder = {0}; tEncoderInit(&encoder, buf, bufLen); @@ -1635,6 +1637,7 @@ int32_t tDeserializeSGetUserAuthRspImpl(SDecoder *pDecoder, SGetUserAuthRsp *pRs int32_t ref = 0; if (tDecodeI32(pDecoder, &ref) < 0) return -1; taosHashPut(pRsp->useDbs, key, strlen(key), &ref, sizeof(ref)); + taosMemoryFree(key); } } @@ -1831,7 +1834,6 @@ int32_t tSerializeSCreateFuncReq(void *buf, int32_t bufLen, SCreateFuncReq *pReq if (tEncodeCStr(&encoder, pReq->pComment) < 0) return -1; } - if (tEncodeI8(&encoder, pReq->orReplace) < 0) return -1; tEndEncode(&encoder); @@ -1876,7 +1878,6 @@ int32_t tDeserializeSCreateFuncReq(void *buf, int32_t bufLen, SCreateFuncReq *pR if (tDecodeCStrTo(&decoder, pReq->pComment) < 0) return -1; } - if (!tDecodeIsEnd(&decoder)) { if (tDecodeI8(&decoder, &pReq->orReplace) < 0) return -1; } else { @@ -2053,12 +2054,12 @@ int32_t tDeserializeSRetrieveFuncRsp(void *buf, int32_t bufLen, SRetrieveFuncRsp if (pRsp->pFuncExtraInfos == NULL) return -1; if (tDecodeIsEnd(&decoder)) { for (int32_t i = 0; i < pRsp->numOfFuncs; ++i) { - SFuncExtraInfo extraInfo = { 0 }; + SFuncExtraInfo extraInfo = {0}; taosArrayPush(pRsp->pFuncExtraInfos, &extraInfo); } } else { for (int32_t i = 0; i < pRsp->numOfFuncs; ++i) { - SFuncExtraInfo extraInfo = { 0 }; + SFuncExtraInfo extraInfo = {0}; if (tDecodeI32(&decoder, &extraInfo.funcVersion) < 0) return -1; if (tDecodeI64(&decoder, &extraInfo.funcCreatedTime) < 0) return -1; taosArrayPush(pRsp->pFuncExtraInfos, &extraInfo); diff --git a/source/dnode/mnode/impl/src/mndUser.c b/source/dnode/mnode/impl/src/mndUser.c index d08227927a..523753d7c6 100644 --- a/source/dnode/mnode/impl/src/mndUser.c +++ b/source/dnode/mnode/impl/src/mndUser.c @@ -390,6 +390,7 @@ static SSdbRow *mndUserActionDecode(SSdbRaw *pRaw) { SDB_GET_INT32(pRaw, dataPos, &ref, _OVER); taosHashPut(pUser->useDbs, key, keyLen, &ref, sizeof(ref)); + taosMemoryFree(key); } } @@ -956,6 +957,7 @@ _OVER: mError("user:%s, failed to alter since %s", alterReq.user, terrstr()); } + tFreeSAlterUserReq(&alterReq); mndReleaseUser(pMnode, pOperUser); mndReleaseUser(pMnode, pUser); mndUserFreeObj(&newUser); diff --git a/source/libs/catalog/src/ctgUtil.c b/source/libs/catalog/src/ctgUtil.c index 7ef2e34d1e..62896e4307 100644 --- a/source/libs/catalog/src/ctgUtil.c +++ b/source/libs/catalog/src/ctgUtil.c @@ -486,12 +486,12 @@ void ctgFreeBatchHash(void* hash) { taosMemoryFreeClear(pRes->pRes); } -void ctgFreeJsonTagVal(void *val) { +void ctgFreeJsonTagVal(void* val) { if (NULL == val) { return; } - STagVal *pVal = (STagVal *)val; + STagVal* pVal = (STagVal*)val; if (TSDB_DATA_TYPE_JSON == pVal->type) { taosMemoryFree(pVal->pData); @@ -545,6 +545,7 @@ void ctgFreeTaskRes(CTG_TASK_TYPE type, void** pRes) { taosArrayDestroy(*pRes); } *pRes = NULL; + break; } case CTG_TASK_GET_TB_META_BATCH: { SArray* pArray = (SArray*)*pRes; @@ -1363,7 +1364,7 @@ int32_t ctgChkSetTbAuthRes(SCatalog* pCtg, SCtgAuthReq* req, SCtgAuthRsp* res) { SGetUserAuthRsp* pInfo = &req->authInfo; SHashObj* pTbs = (AUTH_TYPE_READ == req->singleType) ? pInfo->readTbs : pInfo->writeTbs; char* stbName = NULL; - + char tbFName[TSDB_TABLE_FNAME_LEN]; char dbFName[TSDB_DB_FNAME_LEN]; tNameExtractFullName(&req->pRawReq->tbName, tbFName); @@ -1396,7 +1397,7 @@ int32_t ctgChkSetTbAuthRes(SCatalog* pCtg, SCtgAuthReq* req, SCtgAuthRsp* res) { SCtgTbMetaCtx ctx = {0}; ctx.pName = (SName*)&req->pRawReq->tbName; ctx.flag = CTG_FLAG_UNKNOWN_STB | CTG_FLAG_SYNC_OP; - + CTG_ERR_RET(ctgGetTbMeta(pCtg, req->pConn, &ctx, &pMeta)); } diff --git a/source/libs/nodes/src/nodesUtilFuncs.c b/source/libs/nodes/src/nodesUtilFuncs.c index 3f571e22ae..422a196c50 100644 --- a/source/libs/nodes/src/nodesUtilFuncs.c +++ b/source/libs/nodes/src/nodesUtilFuncs.c @@ -953,8 +953,12 @@ void nodesDestroyNode(SNode* pNode) { break; case QUERY_NODE_SPLIT_VGROUP_STMT: // no pointer field case QUERY_NODE_SYNCDB_STMT: // no pointer field - case QUERY_NODE_GRANT_STMT: // no pointer field - case QUERY_NODE_REVOKE_STMT: // no pointer field + break; + case QUERY_NODE_GRANT_STMT: + nodesDestroyNode(((SGrantStmt*)pNode)->pTagCond); + break; + case QUERY_NODE_REVOKE_STMT: + nodesDestroyNode(((SRevokeStmt*)pNode)->pTagCond); break; case QUERY_NODE_SHOW_DNODES_STMT: case QUERY_NODE_SHOW_MNODES_STMT: diff --git a/source/libs/parser/src/parAuthenticator.c b/source/libs/parser/src/parAuthenticator.c index b06d48a690..d182f5bd73 100644 --- a/source/libs/parser/src/parAuthenticator.c +++ b/source/libs/parser/src/parAuthenticator.c @@ -70,7 +70,7 @@ static EDealRes authSubquery(SAuthCxt* pCxt, SNode* pStmt) { return TSDB_CODE_SUCCESS == authQuery(pCxt, pStmt) ? DEAL_RES_CONTINUE : DEAL_RES_ERROR; } -static int32_t mergeStableTagCond(SNode** pWhere, SNode** pTagCond) { +static int32_t mergeStableTagCond(SNode** pWhere, SNode* pTagCond) { SLogicConditionNode* pLogicCond = (SLogicConditionNode*)nodesMakeNode(QUERY_NODE_LOGIC_CONDITION); if (NULL == pLogicCond) { return TSDB_CODE_OUT_OF_MEMORY; @@ -78,7 +78,7 @@ static int32_t mergeStableTagCond(SNode** pWhere, SNode** pTagCond) { pLogicCond->node.resType.type = TSDB_DATA_TYPE_BOOL; pLogicCond->node.resType.bytes = tDataTypes[TSDB_DATA_TYPE_BOOL].bytes; pLogicCond->condType = LOGIC_COND_TYPE_AND; - int32_t code = nodesListMakeStrictAppend(&pLogicCond->pParameterList, *pTagCond); + int32_t code = nodesListMakeStrictAppend(&pLogicCond->pParameterList, pTagCond); if (TSDB_CODE_SUCCESS == code) { code = nodesListMakeAppend(&pLogicCond->pParameterList, *pWhere); } @@ -91,22 +91,17 @@ static int32_t mergeStableTagCond(SNode** pWhere, SNode** pTagCond) { } static int32_t appendStableTagCond(SNode** pWhere, SNode* pTagCond) { - SNode* pTagCondCopy = nodesCloneNode(pTagCond); - if (NULL == pTagCondCopy) { - return TSDB_CODE_OUT_OF_MEMORY; - } - if (NULL == *pWhere) { - *pWhere = pTagCondCopy; + *pWhere = pTagCond; return TSDB_CODE_SUCCESS; } if (QUERY_NODE_LOGIC_CONDITION == nodeType(*pWhere) && LOGIC_COND_TYPE_AND == ((SLogicConditionNode*)*pWhere)->condType) { - return nodesListStrictAppend(((SLogicConditionNode*)*pWhere)->pParameterList, pTagCondCopy); + return nodesListStrictAppend(((SLogicConditionNode*)*pWhere)->pParameterList, pTagCond); } - return mergeStableTagCond(pWhere, &pTagCondCopy); + return mergeStableTagCond(pWhere, pTagCond); } static EDealRes authSelectImpl(SNode* pNode, void* pContext) { diff --git a/source/libs/parser/src/parTranslater.c b/source/libs/parser/src/parTranslater.c index b44c36dde1..200206755b 100644 --- a/source/libs/parser/src/parTranslater.c +++ b/source/libs/parser/src/parTranslater.c @@ -1310,7 +1310,8 @@ static EDealRes translateOperator(STranslateContext* pCxt, SOperatorNode* pOp) { } static EDealRes haveVectorFunction(SNode* pNode, void* pContext) { - if (isAggFunc(pNode) || isIndefiniteRowsFunc(pNode) || isWindowPseudoColumnFunc(pNode) || isInterpPseudoColumnFunc(pNode)) { + if (isAggFunc(pNode) || isIndefiniteRowsFunc(pNode) || isWindowPseudoColumnFunc(pNode) || + isInterpPseudoColumnFunc(pNode)) { *((bool*)pContext) = true; return DEAL_RES_END; } @@ -6617,6 +6618,7 @@ static int32_t translateGrant(STranslateContext* pCxt, SGrantStmt* pStmt) { if (TSDB_CODE_SUCCESS == code) { code = buildCmdMsg(pCxt, TDMT_MND_ALTER_USER, (FSerializeFunc)tSerializeSAlterUserReq, &req); } + tFreeSAlterUserReq(&req); return code; } diff --git a/tests/script/tsim/user/privilege_table.sim b/tests/script/tsim/user/privilege_table.sim new file mode 100644 index 0000000000..5256cdd21d --- /dev/null +++ b/tests/script/tsim/user/privilege_table.sim @@ -0,0 +1,280 @@ +system sh/stop_dnodes.sh +system sh/deploy.sh -n dnode1 -i 1 +system sh/exec.sh -n dnode1 -s start +sql connect + +print =============== init env +sql drop database if exists test; +sql create database test vgroups 1; +sql use test; +sql create stable st1(ts timestamp, i int) tags(id int, loc varchar(20)); +sql create table st1s1 using st1 tags(1, 'beijing'); +sql create table st1s2 using st1 tags(2, 'shanghai'); +sql insert into st1s1 values(now, 1) st1s2 values(now, 2); +sql create stable st2(ts timestamp, i int) tags(id int, loc varchar(20)); +sql create table st2s1 using st2 tags(1, 'beijing'); +sql create table st2s2 using st2 tags(2, 'shanghai'); +sql insert into st2s1 values(now, 1) st2s2 values(now, 2); +sql create user wxy pass 'taosdata'; + +print =============== case 1: database unauthorized and table unauthorized +sql close +sql connect wxy + +sql reset query cache; +sql_error select * from test.st1; +sql_error insert into test.st1s1 values(now, 10) test.st1s2 values(now, 20); +sql_error select * from test.st2; +sql_error insert into test.st2s1 values(now, 10) test.st2s2 values(now, 20); + + +print =============== case 2: database unauthorized and table read privilege +sql close +sql connect + +sql grant read on test.st1 to wxy; + +sql close +sql connect wxy + +sql reset query cache; +sql select * from test.st1; +if $rows != 2 then + return -1 +endi +sql_error insert into test.st1s1 values(now, 10) test.st1s2 values(now, 20); +sql_error select * from test.st2; +sql_error insert into test.st2s1 values(now, 10) test.st2s2 values(now, 20); + +print =============== case 3: database unauthorized and table read privilege with condition +sql close +sql connect + +sql revoke read on test.st1 from wxy; +sql grant read on test.st1 with id = 1 to wxy; + +sql close +sql connect wxy + +sql reset query cache; +sql select * from test.st1; +if $rows != 1 then + return -1 +endi +sql_error insert into test.st1s1 values(now, 10); +sql_error insert into test.st1s2 values(now, 20); +sql_error select * from test.st2; +sql_error insert into test.st2s1 values(now, 10) test.st2s2 values(now, 20); + +print =============== case 4: database unauthorized and table write privilege +sql close +sql connect + +sql revoke read on test.st1 with id = 1 from wxy; +sql grant write on test.st1 to wxy; + +sql close +sql connect wxy + +sql reset query cache; +sql_error select tbname, * from test.st1; +sql insert into test.st1s1 values(now, 10); +sql insert into test.st1s2 values(now, 20); +sql_error select * from test.st2; +sql_error insert into test.st2s1 values(now, 10) test.st2s2 values(now, 20); + +print =============== case 5: database unauthorized and table write privilege with condition +sql close +sql connect + +sql revoke write on test.st1 from wxy; +sql grant write on test.st1 with id = 1 to wxy; + +sql close +sql connect wxy + +sql reset query cache; +sql_error select tbname, * from test.st1; +sql insert into test.st1s1 values(now, 10); +sql_error insert into test.st1s2 values(now, 20); +sql_error select * from test.st2; +sql_error insert into test.st2s1 values(now, 10) test.st2s2 values(now, 20); + +print =============== case 6: database read privilege and table unauthorized +sql close +sql connect + +sql revoke write on test.st1 with id = 1 from wxy; +sql grant read on test.* to wxy; + +sql close +sql connect wxy + +sql reset query cache; +sql select * from test.st1; +if $rows != 5 then + return -1 +endi +sql_error insert into test.st1s1 values(now, 10) test.st1s2 values(now, 20); +sql select * from test.st2; +if $rows != 2 then + return -1 +endi +sql_error insert into test.st2s1 values(now, 10) test.st2s2 values(now, 20); + +print =============== case 7: database read privilege and table read privilege +sql close +sql connect + +sql grant read on test.st1 to wxy; + +sql close +sql connect wxy + +sql reset query cache; +sql select * from test.st1; +if $rows != 2 then + return -1 +endi +sql_error insert into test.st1s1 values(now, 10) test.st1s2 values(now, 20); +sql select * from test.st2; +if $rows != 2 then + return -1 +endi +sql_error insert into test.st2s1 values(now, 10) test.st2s2 values(now, 20); + +print =============== case 8: database read privilege and table read privilege with condition +sql close +sql connect + +sql revoke read on test.st1 from wxy; +sql grant read on test.st1 with id = 1 to wxy; + +sql close +sql connect wxy + +sql select * from test.st1; +if $rows != 1 then + return -1 +endi +sql_error insert into test.st1s1 values(now, 10) test.st1s2 values(now, 20); +sql select * from test.st2; +if $rows != 2 then + return -1 +endi +sql_error insert into test.st2s1 values(now, 10) test.st2s2 values(now, 20); + +print =============== case 9: database read privilege and table write privilege +sql close +sql connect + +sql revoke read on test.st1 with id = 1 from wxy; +sql grant write on test.st1 to wxy; + +sql close +sql connect wxy + +sql select * from test.st1; +if $rows != 2 then + return -1 +endi +sql insert into test.st1s1 values(now, 10) test.st1s2 values(now, 20); +sql select * from test.st2; +if $rows != 2 then + return -1 +endi +sql_error insert into test.st2s1 values(now, 10) test.st2s2 values(now, 20); + +print =============== case 10: database read privilege and table write privilege with condition +sql close +sql connect + +sql revoke write on test.st1 from wxy; +sql grant write on test.st1 with id = 1 to wxy; + +sql close +sql connect wxy + +sql select * from test.st1; +sql insert into test.st1s1 values(now, 10); +sql_error insert into test.st1s2 values(now, 20); +sql select * from test.st2; +sql_error insert into test.st2s1 values(now, 10) test.st2s2 values(now, 20); + +print =============== case 11: database write privilege and table unauthorized +sql close +sql connect + +sql revoke read on test.* from wxy; +sql revoke write on test.st1 with id = 1 from wxy; +sql grant write on test.* to wxy; + +sql close +sql connect wxy + +sql_error select * from test.st1; +sql insert into test.st1s1 values(now, 10) test.st1s2 values(now, 20); +sql_error select * from test.st2; +sql insert into test.st2s1 values(now, 10) test.st2s2 values(now, 20); + +print =============== case 12: database write privilege and table read privilege +sql close +sql connect + +sql grant read on test.st1 to wxy; + +sql close +sql connect wxy + +sql select * from test.st1; +sql insert into test.st1s1 values(now, 10) test.st1s2 values(now, 20); +sql_error select * from test.st2; +sql insert into test.st2s1 values(now, 10) test.st2s2 values(now, 20); + +print =============== case 13: database write privilege and table read privilege with condition +sql close +sql connect + +sql revoke read on test.st1 from wxy; +sql grant read on test.st1 with id = 1 to wxy; + +sql close +sql connect wxy + +sql select * from test.st1; +sql insert into test.st1s1 values(now, 10) test.st1s2 values(now, 20); +sql_error select * from test.st2; +sql insert into test.st2s1 values(now, 10) test.st2s2 values(now, 20); + +print =============== case 14: database write privilege and table write privilege +sql close +sql connect + +sql revoke read on test.st1 with id = 1 from wxy; +sql grant write on test.st1 to wxy; + +sql close +sql connect wxy + +sql_error select * from test.st1; +sql insert into test.st1s1 values(now, 10) test.st1s2 values(now, 20); +sql_error select * from test.st2; +sql insert into test.st2s1 values(now, 10) test.st2s2 values(now, 20); + +print =============== case 15: database write privilege and table write privilege with condition +sql close +sql connect + +sql revoke write on test.st1 from wxy; +sql grant write on test.st1 with id = 1 to wxy; + +sql close +sql connect wxy + +sql_error select * from test.st1; +sql insert into test.st1s1 values(now, 10); +sql_error insert into test.st1s2 values(now, 20); +sql_error select * from test.st2; +sql insert into test.st2s1 values(now, 10) test.st2s2 values(now, 20); + +system sh/exec.sh -n dnode1 -s stop -x SIGINT