TDengine/source/common/src/tpriv.c

810 lines
No EOL
34 KiB
C

/*
* 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/>.
*/
#define _DEFAULT_SOURCE
#include "systable.h"
#include "tpriv.h"
#include "tmsg.h"
#include "tutil.h"
static TdThreadOnce privInit = PTHREAD_ONCE_INIT;
typedef struct {
const char* name;
int32_t level;
} SPrivObjInfo;
static const SPrivObjInfo __privObjInfo[] = {
{"CLUSTER", 0}, {"NODE", 0}, {"DATABASE", 0}, {"TABLE", 1}, {"FUNCTION", 0}, {"INDEX", 1},
{"VIEW", 1}, {"USER", 0}, {"ROLE", 0}, {"RSMA", 1}, {"TSMA", 1}, {"TOPIC", 1},
{"STREAM", 1}, {"MOUNT", 0}, {"AUDIT", 0}, {"TOKEN", 0}, {"NONE", 1}, {"XTASK", 0},
};
/**
* N.B. increase the macro PRIV_INFO_TABLE_VERSION for any update of privInfoTable
*/
#define SYS_ADMIN_BASIC_ROLES (T_ROLE_SYSDBA | T_ROLE_SYSSEC | T_ROLE_SYSAUDIT)
#define SYS_ADMIN_CORE_ROLES (T_ROLE_SYSDBA | T_ROLE_SYSSEC)
#define SYS_ADMIN_INFO1_ROLES (SYS_ADMIN_BASIC_ROLES | T_ROLE_SYSINFO_1)
#define SYS_ADMIN_INFO_ROLES (SYS_ADMIN_BASIC_ROLES | T_ROLE_SYSINFO_0 | T_ROLE_SYSINFO_1)
#define SYS_ADMIN_EXT_ROLES (T_ROLE_SYSINFO_0 | T_ROLE_SYSINFO_1 | T_ROLE_SYSAUDIT_LOG)
#define SYS_ADMIN_ALL_ROLES (SYS_ADMIN_BASIC_ROLES | T_ROLE_SYSAUDIT_LOG | T_ROLE_SYSINFO_0 | T_ROLE_SYSINFO_1)
static SPrivInfo privInfoTable[] = {
// ==================== common privileges ====================
{PRIV_CM_ALL, PRIV_CATEGORY_COMMON, 0, 0, 0, 0, "", "ALL"},
{PRIV_CM_ALTER, PRIV_CATEGORY_COMMON, 0, 0, 0, 0, "", "ALTER"},
{PRIV_CM_DROP, PRIV_CATEGORY_COMMON, 0, 0, 0, 0, "", "DROP"},
{PRIV_CM_SHOW, PRIV_CATEGORY_COMMON, 0, 0, 0, 0, "", "SHOW"},
{PRIV_CM_SHOW_CREATE, PRIV_CATEGORY_COMMON, 0, 0, 0, 0, "", "SHOW CREATE"},
{PRIV_CM_START, PRIV_CATEGORY_COMMON, 0, 0, 0, 0, "", "START"},
{PRIV_CM_STOP, PRIV_CATEGORY_COMMON, 0, 0, 0, 0, "", "STOP"},
{PRIV_CM_RECALC, PRIV_CATEGORY_COMMON, 0, 0, 0, 0, "", "RECALCULATE"},
{PRIV_CM_KILL, PRIV_CATEGORY_COMMON, 0, 0, 0, 0, "", "KILL"},
{PRIV_CM_SUBSCRIBE, PRIV_CATEGORY_COMMON, 0, 0, 0, 0, "", "SUBSCRIBE"},
// ==================== system privileges ====================
// Database Management
{PRIV_DB_CREATE, PRIV_CATEGORY_SYSTEM, 0, 0, T_ROLE_SYSDBA, 0, "", "CREATE DATABASE"},
{PRIV_VG_BALANCE, PRIV_CATEGORY_SYSTEM, 0, 0, T_ROLE_SYSDBA, 0, "", "BALANCE VGROUP"},
{PRIV_VG_BALANCE_LEADER, PRIV_CATEGORY_SYSTEM, 0, 0, T_ROLE_SYSDBA, 0, "", "BALANCE VGROUP LEADER"},
{PRIV_VG_MERGE, PRIV_CATEGORY_SYSTEM, 0, 0, T_ROLE_SYSDBA, 0, "", "MERGE VGROUP"},
{PRIV_VG_REDISTRIBUTE, PRIV_CATEGORY_SYSTEM, 0, 0, T_ROLE_SYSDBA, 0, "", "REDISTRIBUTE VGROUP"},
{PRIV_VG_SPLIT, PRIV_CATEGORY_SYSTEM, 0, 0, T_ROLE_SYSDBA, 0, "", "SPLIT VGROUP"},
// Function Privileges
{PRIV_FUNC_CREATE, PRIV_CATEGORY_SYSTEM, 0, 0, T_ROLE_SYSDBA, 0, "", "CREATE FUNCTION"},
{PRIV_FUNC_DROP, PRIV_CATEGORY_SYSTEM, 0, 0, T_ROLE_SYSDBA, 0, "", "DROP FUNCTION"},
{PRIV_FUNC_SHOW, PRIV_CATEGORY_SYSTEM, 0, 0, SYS_ADMIN_INFO_ROLES, 0, "", "SHOW FUNCTIONS"},
// Mount Privileges
{PRIV_MOUNT_CREATE, PRIV_CATEGORY_SYSTEM, 0, 0, T_ROLE_SYSDBA, 0, "", "CREATE MOUNT"},
{PRIV_MOUNT_DROP, PRIV_CATEGORY_SYSTEM, 0, 0, T_ROLE_SYSDBA, 0, "", "DROP MOUNT"},
{PRIV_MOUNT_SHOW, PRIV_CATEGORY_SYSTEM, 0, 0, SYS_ADMIN_INFO1_ROLES, 0, "", "SHOW MOUNTS"},
// User Management
{PRIV_USER_CREATE, PRIV_CATEGORY_SYSTEM, 0, 0, T_ROLE_SYSDBA, 0, "", "CREATE USER"},
{PRIV_USER_DROP, PRIV_CATEGORY_SYSTEM, 0, 0, T_ROLE_SYSDBA, 0, "", "DROP USER"},
{PRIV_USER_SET_SECURITY, PRIV_CATEGORY_SYSTEM, 0, 0, T_ROLE_SYSDBA | T_ROLE_SYSSEC, 0, "",
"SET USER SECURITY INFORMATION"},
{PRIV_USER_SET_AUDIT, PRIV_CATEGORY_SYSTEM, 0, 0, T_ROLE_SYSDBA | T_ROLE_SYSAUDIT, 0, "",
"SET USER AUDIT INFORMATION"},
{PRIV_USER_SET_BASIC, PRIV_CATEGORY_SYSTEM, 0, 0, T_ROLE_SYSDBA, 0, "", "SET USER BASIC INFORMATION"},
{PRIV_USER_UNLOCK, PRIV_CATEGORY_SYSTEM, 0, 0, SYS_ADMIN_CORE_ROLES, 0, "", "UNLOCK USER"},
{PRIV_USER_LOCK, PRIV_CATEGORY_SYSTEM, 0, 0, SYS_ADMIN_CORE_ROLES, 0, "", "LOCK USER"},
{PRIV_USER_SHOW, PRIV_CATEGORY_SYSTEM, 0, 0, SYS_ADMIN_INFO1_ROLES, 0, "", "SHOW USERS"},
{PRIV_USER_ALTER, PRIV_CATEGORY_SYSTEM, 0, 0, SYS_ADMIN_INFO_ROLES, 0, "", "ALTER USER"},
{PRIV_USER_SHOW_SECURITY, PRIV_CATEGORY_SYSTEM, 0, 0, SYS_ADMIN_BASIC_ROLES, 0, "",
"SHOW USERS SECURITY INFORMATION"},
// Role Management
{PRIV_ROLE_CREATE, PRIV_CATEGORY_SYSTEM, 0, 0, T_ROLE_SYSDBA, 0, "", "CREATE ROLE"},
{PRIV_ROLE_DROP, PRIV_CATEGORY_SYSTEM, 0, 0, T_ROLE_SYSDBA, 0, "", "DROP ROLE"},
{PRIV_ROLE_UNLOCK, PRIV_CATEGORY_SYSTEM, 0, 0, SYS_ADMIN_CORE_ROLES, 0, "", "UNLOCK ROLE"},
{PRIV_ROLE_LOCK, PRIV_CATEGORY_SYSTEM, 0, 0, SYS_ADMIN_CORE_ROLES, 0, "", "LOCK ROLE"},
{PRIV_ROLE_SHOW, PRIV_CATEGORY_SYSTEM, 0, 0, SYS_ADMIN_INFO1_ROLES, 0, "", "SHOW ROLES"},
// Token Privileges
{PRIV_TOKEN_CREATE, PRIV_CATEGORY_SYSTEM, 0, 0, T_ROLE_SYSSEC, 0, "", "CREATE TOKEN"},
{PRIV_TOKEN_DROP, PRIV_CATEGORY_SYSTEM, 0, 0, T_ROLE_SYSSEC, 0, "", "DROP TOKEN"},
{PRIV_TOKEN_ALTER, PRIV_CATEGORY_SYSTEM, 0, 0, T_ROLE_SYSSEC, 0, "", "ALTER TOKEN"},
{PRIV_TOKEN_SHOW, PRIV_CATEGORY_SYSTEM, 0, 0, SYS_ADMIN_BASIC_ROLES, 0, "", "SHOW TOKENS"},
// Node Management
{PRIV_NODE_CREATE, PRIV_CATEGORY_SYSTEM, 0, 0, T_ROLE_SYSDBA, 0, "", "CREATE NODE"},
{PRIV_NODE_ALTER, PRIV_CATEGORY_SYSTEM, 0, 0, T_ROLE_SYSDBA, 0, "", "ALTER NODE"},
{PRIV_NODE_DROP, PRIV_CATEGORY_SYSTEM, 0, 0, T_ROLE_SYSDBA, 0, "", "DROP NODE"},
{PRIV_NODES_SHOW, PRIV_CATEGORY_SYSTEM, 0, 0, SYS_ADMIN_INFO1_ROLES, 0, "", "SHOW NODES"},
// System Variables
{PRIV_VAR_SECURITY_ALTER, PRIV_CATEGORY_SYSTEM, 0, 0, T_ROLE_SYSSEC, 0, "", "ALTER SECURITY VARIABLE"},
{PRIV_VAR_AUDIT_ALTER, PRIV_CATEGORY_SYSTEM, 0, 0, T_ROLE_SYSAUDIT, 0, "", "ALTER AUDIT VARIABLE"},
{PRIV_VAR_SYSTEM_ALTER, PRIV_CATEGORY_SYSTEM, 0, 0, T_ROLE_SYSDBA, 0, "", "ALTER SYSTEM VARIABLE"},
{PRIV_VAR_DEBUG_ALTER, PRIV_CATEGORY_SYSTEM, 0, 0, T_ROLE_SYSDBA, 0, "", "ALTER DEBUG VARIABLE"},
{PRIV_VAR_SECURITY_SHOW, PRIV_CATEGORY_SYSTEM, 0, 0, SYS_ADMIN_INFO1_ROLES, 0, "", "SHOW SECURITY VARIABLE"},
{PRIV_VAR_AUDIT_SHOW, PRIV_CATEGORY_SYSTEM, 0, 0, SYS_ADMIN_INFO1_ROLES, 0, "", "SHOW AUDIT VARIABLE"},
{PRIV_VAR_SYSTEM_SHOW, PRIV_CATEGORY_SYSTEM, 0, 0, SYS_ADMIN_INFO_ROLES, 0, "", "SHOW SYSTEM VARIABLE"},
{PRIV_VAR_DEBUG_SHOW, PRIV_CATEGORY_SYSTEM, 0, 0, SYS_ADMIN_INFO_ROLES, 0, "", "SHOW DEBUG VARIABLE"},
// Key/Password Management
{PRIV_KEY_UPDATE, PRIV_CATEGORY_SYSTEM, 0, 0, T_ROLE_SYSDBA, 0, "", "UPDATE KEY"},
{PRIV_TOTP_CREATE, PRIV_CATEGORY_SYSTEM, 0, 0, T_ROLE_SYSSEC, 0, "", "CREATE TOTP_SECRET"},
{PRIV_TOTP_DROP, PRIV_CATEGORY_SYSTEM, 0, 0, T_ROLE_SYSSEC, 0, "", "DROP TOTP_SECRET"},
{PRIV_PASS_ALTER, PRIV_CATEGORY_SYSTEM, 0, 0, T_ROLE_SYSDBA, 0, "", "ALTER PASS"},
{PRIV_PASS_ALTER_SELF, PRIV_CATEGORY_SYSTEM, 0, 0, SYS_ADMIN_INFO_ROLES, 0, "", "ALTER SELF PASS"},
// Grant/Revoke Privileges
{PRIV_GRANT_PRIVILEGE, PRIV_CATEGORY_SYSTEM, 0, 0, T_ROLE_SYSSEC, 0, "", "GRANT PRIVILEGE"},
{PRIV_REVOKE_PRIVILEGE, PRIV_CATEGORY_SYSTEM, 0, 0, T_ROLE_SYSSEC, 0, "", "REVOKE PRIVILEGE"},
{PRIV_SHOW_PRIVILEGES, PRIV_CATEGORY_SYSTEM, 0, 0, SYS_ADMIN_INFO1_ROLES, 0, "", "SHOW PRIVILEGES"},
{PRIV_GRANT_SYSDBA, PRIV_CATEGORY_SYSTEM, 0, 0, T_ROLE_SYSDBA, 0, "", "GRANT SYSDBA PRIVILEGE"},
{PRIV_REVOKE_SYSDBA, PRIV_CATEGORY_SYSTEM, 0, 0, T_ROLE_SYSDBA, 0, "", "REVOKE SYSDBA PRIVILEGE"},
{PRIV_GRANT_SYSSEC, PRIV_CATEGORY_SYSTEM, 0, 0, T_ROLE_SYSSEC, 0, "", "GRANT SYSSEC PRIVILEGE"},
{PRIV_REVOKE_SYSSEC, PRIV_CATEGORY_SYSTEM, 0, 0, T_ROLE_SYSSEC, 0, "", "REVOKE SYSSEC PRIVILEGE"},
{PRIV_GRANT_SYSAUDIT, PRIV_CATEGORY_SYSTEM, 0, 0, T_ROLE_SYSAUDIT, 0, "", "GRANT SYSAUDIT PRIVILEGE"},
{PRIV_REVOKE_SYSAUDIT, PRIV_CATEGORY_SYSTEM, 0, 0, T_ROLE_SYSAUDIT, 0, "", "REVOKE SYSAUDIT PRIVILEGE"},
// Audit Management
{PRIV_AUDIT_DB_DROP, PRIV_CATEGORY_SYSTEM, 0, 0, T_ROLE_SYSAUDIT, 0, "", "DROP AUDIT DATABASE"},
{PRIV_AUDIT_DB_ALTER, PRIV_CATEGORY_SYSTEM, 0, 0, T_ROLE_SYSAUDIT, 0, "", "ALTER AUDIT DATABASE"},
{PRIV_AUDIT_DB_USE, PRIV_CATEGORY_SYSTEM, 0, 0, T_ROLE_SYSAUDIT | T_ROLE_SYSAUDIT_LOG, 0, "", "USE AUDIT DATABASE"},
{PRIV_AUDIT_TBL_CREATE, PRIV_CATEGORY_SYSTEM, 0, 0, T_ROLE_SYSAUDIT_LOG, 0, "", "CREATE AUDIT TABLE"},
{PRIV_AUDIT_TBL_SELECT, PRIV_CATEGORY_SYSTEM, 0, 0, T_ROLE_SYSAUDIT, 0, "", "SELECT AUDIT TABLE"},
{PRIV_AUDIT_TBL_INSERT, PRIV_CATEGORY_SYSTEM, 0, 0, T_ROLE_SYSAUDIT_LOG, 0, "", "INSERT AUDIT TABLE"},
// System Administration
{PRIV_TRANS_SHOW, PRIV_CATEGORY_SYSTEM, 0, 0, SYS_ADMIN_INFO_ROLES, 0, "", "SHOW TRANS"},
{PRIV_TRANS_KILL, PRIV_CATEGORY_SYSTEM, 0, 0, T_ROLE_SYSDBA, 0, "", "KILL TRANS"},
{PRIV_CONN_SHOW, PRIV_CATEGORY_SYSTEM, 0, 0, SYS_ADMIN_INFO_ROLES, 0, "", "SHOW CONNECTIONS"},
{PRIV_CONN_KILL, PRIV_CATEGORY_SYSTEM, 0, 0, T_ROLE_SYSDBA, 0, "", "KILL CONNECTION"},
{PRIV_QUERY_SHOW, PRIV_CATEGORY_SYSTEM, 0, 0, SYS_ADMIN_INFO_ROLES, 0, "", "SHOW QUERIES"},
{PRIV_QUERY_KILL, PRIV_CATEGORY_SYSTEM, 0, 0, T_ROLE_SYSDBA, 0, "", "KILL QUERY"},
{PRIV_INFO_SCHEMA_READ_BASIC, PRIV_CATEGORY_SYSTEM, 0, 0, SYS_ADMIN_INFO_ROLES, 0, "",
"READ INFORMATION SCHEMA BASIC"},
{PRIV_INFO_SCHEMA_READ_SEC, PRIV_CATEGORY_SYSTEM, 0, 0, SYS_ADMIN_INFO1_ROLES, 0, "",
"READ INFORMATION SCHEMA SECURITY"},
{PRIV_INFO_SCHEMA_READ_AUDIT, PRIV_CATEGORY_SYSTEM, 0, 0, SYS_ADMIN_INFO1_ROLES, 0, "",
"READ INFORMATION SCHEMA AUDIT"},
{PRIV_INFO_SCHEMA_READ_PRIVILEGED, PRIV_CATEGORY_SYSTEM, 0, 0, SYS_ADMIN_INFO1_ROLES, 0, "",
"READ INFORMATION SCHEMA PRIVILEGED"},
{PRIV_PERF_SCHEMA_READ_BASIC, PRIV_CATEGORY_SYSTEM, 0, 0, SYS_ADMIN_INFO_ROLES, 0, "",
"READ PERFORMANCE SCHEMA BASIC"},
{PRIV_PERF_SCHEMA_READ_PRIVILEGED, PRIV_CATEGORY_SYSTEM, 0, 0, SYS_ADMIN_INFO1_ROLES, 0, "",
"READ PERFORMANCE SCHEMA PRIVILEGED"},
{PRIV_GRANTS_SHOW, PRIV_CATEGORY_SYSTEM, 0, 0, SYS_ADMIN_INFO1_ROLES, 0, "", "SHOW GRANTS"},
{PRIV_CLUSTER_SHOW, PRIV_CATEGORY_SYSTEM, 0, 0, SYS_ADMIN_INFO1_ROLES, 0, "", "SHOW CLUSTER"},
{PRIV_APPS_SHOW, PRIV_CATEGORY_SYSTEM, 0, 0, SYS_ADMIN_INFO_ROLES, 0, "", "SHOW APPS"},
// Xnode Task Management
{PRIV_XNODE_TASK_CREATE, PRIV_CATEGORY_SYSTEM, 0, 0, T_ROLE_SYSDBA, 0, "", "CREATE XNODE TASK"},
// ==================== object privileges ====================
// Database Privileges
{PRIV_CM_ALTER, PRIV_CATEGORY_OBJECT, PRIV_OBJ_DB, 0, T_ROLE_SYSDBA, 2, "", "ALTER DATABASE"},
{PRIV_CM_DROP, PRIV_CATEGORY_OBJECT, PRIV_OBJ_DB, 0, T_ROLE_SYSDBA, 2, "", "DROP DATABASE"},
{PRIV_DB_USE, PRIV_CATEGORY_OBJECT, PRIV_OBJ_DB, 0, SYS_ADMIN_BASIC_ROLES, 3, "", "USE DATABASE"},
{PRIV_DB_USE, PRIV_CATEGORY_OBJECT, PRIV_OBJ_DB, 0, SYS_ADMIN_EXT_ROLES, 3, TSDB_INFORMATION_SCHEMA_DB,
"USE DATABASE"},
{PRIV_DB_USE, PRIV_CATEGORY_OBJECT, PRIV_OBJ_DB, 0, SYS_ADMIN_EXT_ROLES, 3, TSDB_PERFORMANCE_SCHEMA_DB,
"USE DATABASE"},
{PRIV_DB_FLUSH, PRIV_CATEGORY_OBJECT, PRIV_OBJ_DB, 0, T_ROLE_SYSDBA, 2, "", "FLUSH DATABASE"},
{PRIV_DB_COMPACT, PRIV_CATEGORY_OBJECT, PRIV_OBJ_DB, 0, T_ROLE_SYSDBA, 2, "", "COMPACT DATABASE"},
{PRIV_DB_TRIM, PRIV_CATEGORY_OBJECT, PRIV_OBJ_DB, 0, T_ROLE_SYSDBA, 2, "", "TRIM DATABASE"},
{PRIV_DB_ROLLUP, PRIV_CATEGORY_OBJECT, PRIV_OBJ_DB, 0, T_ROLE_SYSDBA, 2, "", "ROLLUP DATABASE"},
{PRIV_DB_SCAN, PRIV_CATEGORY_OBJECT, PRIV_OBJ_DB, 0, T_ROLE_SYSDBA, 1, "", "SCAN DATABASE"},
{PRIV_DB_SSMIGRATE, PRIV_CATEGORY_OBJECT, PRIV_OBJ_DB, 0, T_ROLE_SYSDBA, 2, "", "SSMIGRATE DATABASE"},
{PRIV_CM_SHOW, PRIV_CATEGORY_OBJECT, PRIV_OBJ_DB, 0, SYS_ADMIN_INFO_ROLES, 1, "", "SHOW DATABASES"},
{PRIV_CM_SHOW_CREATE, PRIV_CATEGORY_OBJECT, PRIV_OBJ_DB, 0, SYS_ADMIN_INFO_ROLES, 1, "", "SHOW CREATE DATABASE"},
{PRIV_SHOW_VNODES, PRIV_CATEGORY_OBJECT, PRIV_OBJ_DB, 0, SYS_ADMIN_INFO1_ROLES, 1, "", "SHOW VNODES"},
{PRIV_SHOW_VGROUPS, PRIV_CATEGORY_OBJECT, PRIV_OBJ_DB, 0, SYS_ADMIN_INFO1_ROLES, 1, "", "SHOW VGROUPS"},
{PRIV_SHOW_COMPACTS, PRIV_CATEGORY_OBJECT, PRIV_OBJ_DB, 0, SYS_ADMIN_INFO1_ROLES, 1, "", "SHOW COMPACTS"},
{PRIV_SHOW_RETENTIONS, PRIV_CATEGORY_OBJECT, PRIV_OBJ_DB, 0, SYS_ADMIN_INFO1_ROLES, 1, "", "SHOW RETENTIONS"},
{PRIV_SHOW_SCANS, PRIV_CATEGORY_OBJECT, PRIV_OBJ_DB, 0, SYS_ADMIN_INFO1_ROLES, 1, "", "SHOW SCANS"},
{PRIV_SHOW_SSMIGRATES, PRIV_CATEGORY_OBJECT, PRIV_OBJ_DB, 0, SYS_ADMIN_INFO1_ROLES, 1, "", "SHOW SSMIGRATES"},
// Table Privileges
{PRIV_TBL_CREATE, PRIV_CATEGORY_OBJECT, PRIV_OBJ_DB, 0, T_ROLE_SYSDBA, 2, "", "CREATE TABLE"},
{PRIV_CM_DROP, PRIV_CATEGORY_OBJECT, PRIV_OBJ_TBL, 1, T_ROLE_SYSDBA, 2, "", "DROP TABLE"},
{PRIV_CM_ALTER, PRIV_CATEGORY_OBJECT, PRIV_OBJ_TBL, 1, T_ROLE_SYSDBA, 2, "", "ALTER TABLE"},
{PRIV_CM_SHOW, PRIV_CATEGORY_OBJECT, PRIV_OBJ_TBL, 1, SYS_ADMIN_INFO_ROLES, 1, "", "SHOW TABLES"},
{PRIV_CM_SHOW_CREATE, PRIV_CATEGORY_OBJECT, PRIV_OBJ_TBL, 1, SYS_ADMIN_INFO_ROLES, 1, "", "SHOW CREATE TABLE"},
{PRIV_TBL_SELECT, PRIV_CATEGORY_OBJECT, PRIV_OBJ_TBL, 1, 0, 1, "", "SELECT"},
{PRIV_TBL_INSERT, PRIV_CATEGORY_OBJECT, PRIV_OBJ_TBL, 1, 0, 2, "", "INSERT"},
{PRIV_TBL_UPDATE, PRIV_CATEGORY_OBJECT, PRIV_OBJ_TBL, 1, 0, 2, "", "UPDATE"},
{PRIV_TBL_DELETE, PRIV_CATEGORY_OBJECT, PRIV_OBJ_TBL, 1, 0, 2, "", "DELETE"},
// Index Privileges
{PRIV_IDX_CREATE, PRIV_CATEGORY_OBJECT, PRIV_OBJ_TBL, 1, T_ROLE_SYSDBA, 2, "", "CREATE INDEX"},
{PRIV_CM_DROP, PRIV_CATEGORY_OBJECT, PRIV_OBJ_IDX, 1, T_ROLE_SYSDBA, 2, "", "DROP INDEX"},
{PRIV_CM_SHOW, PRIV_CATEGORY_OBJECT, PRIV_OBJ_IDX, 1, SYS_ADMIN_INFO_ROLES, 1, "", "SHOW INDEXES"},
{PRIV_CM_SHOW_CREATE, PRIV_CATEGORY_OBJECT, PRIV_OBJ_IDX, 1, SYS_ADMIN_INFO_ROLES, 1, "", "SHOW CREATE INDEX"},
// RSMA Privileges
{PRIV_RSMA_CREATE, PRIV_CATEGORY_OBJECT, PRIV_OBJ_TBL, 1, T_ROLE_SYSDBA, 2, "", "CREATE RSMA"},
{PRIV_CM_DROP, PRIV_CATEGORY_OBJECT, PRIV_OBJ_RSMA, 1, T_ROLE_SYSDBA, 2, "", "DROP RSMA"},
{PRIV_CM_ALTER, PRIV_CATEGORY_OBJECT, PRIV_OBJ_RSMA, 1, T_ROLE_SYSDBA, 2, "", "ALTER RSMA"},
{PRIV_CM_SHOW, PRIV_CATEGORY_OBJECT, PRIV_OBJ_RSMA, 1, SYS_ADMIN_INFO_ROLES, 1, "", "SHOW RSMAS"},
{PRIV_CM_SHOW_CREATE, PRIV_CATEGORY_OBJECT, PRIV_OBJ_RSMA, 1, SYS_ADMIN_INFO_ROLES, 1, "", "SHOW CREATE RSMA"},
// TSMA Privileges
{PRIV_TSMA_CREATE, PRIV_CATEGORY_OBJECT, PRIV_OBJ_TBL, 1, T_ROLE_SYSDBA, 2, "", "CREATE TSMA"},
{PRIV_CM_DROP, PRIV_CATEGORY_OBJECT, PRIV_OBJ_TSMA, 1, T_ROLE_SYSDBA, 2, "", "DROP TSMA"},
{PRIV_CM_SHOW, PRIV_CATEGORY_OBJECT, PRIV_OBJ_TSMA, 1, SYS_ADMIN_INFO_ROLES, 1, "", "SHOW TSMAS"},
{PRIV_CM_SHOW_CREATE, PRIV_CATEGORY_OBJECT, PRIV_OBJ_TSMA, 1, SYS_ADMIN_INFO_ROLES, 1, "", "SHOW CREATE TSMA"},
// View Privileges
{PRIV_VIEW_CREATE, PRIV_CATEGORY_OBJECT, PRIV_OBJ_DB, 0, T_ROLE_SYSDBA, 2, "", "CREATE VIEW"},
{PRIV_CM_DROP, PRIV_CATEGORY_OBJECT, PRIV_OBJ_VIEW, 1, T_ROLE_SYSDBA, 2, "", "DROP VIEW"},
{PRIV_CM_ALTER, PRIV_CATEGORY_OBJECT, PRIV_OBJ_VIEW, 1, T_ROLE_SYSDBA, 2, "", "ALTER VIEW"},
{PRIV_CM_SHOW, PRIV_CATEGORY_OBJECT, PRIV_OBJ_VIEW, 1, SYS_ADMIN_INFO_ROLES, 1, "", "SHOW VIEWS"},
{PRIV_CM_SHOW_CREATE, PRIV_CATEGORY_OBJECT, PRIV_OBJ_VIEW, 1, SYS_ADMIN_INFO_ROLES, 1, "", "SHOW CREATE VIEW"},
{PRIV_VIEW_SELECT, PRIV_CATEGORY_OBJECT, PRIV_OBJ_VIEW, 1, 0, 1, "", "SELECT VIEW"},
// Topic Privileges
{PRIV_TOPIC_CREATE, PRIV_CATEGORY_OBJECT, PRIV_OBJ_DB, 0, T_ROLE_SYSDBA, 2, "", "CREATE TOPIC"},
{PRIV_CM_DROP, PRIV_CATEGORY_OBJECT, PRIV_OBJ_TOPIC, 1, T_ROLE_SYSDBA, 2, "", "DROP TOPIC"},
{PRIV_CM_SHOW, PRIV_CATEGORY_OBJECT, PRIV_OBJ_TOPIC, 1, SYS_ADMIN_INFO_ROLES, 1, "", "SHOW TOPICS"},
{PRIV_CM_SHOW_CREATE, PRIV_CATEGORY_OBJECT, PRIV_OBJ_TOPIC, 1, SYS_ADMIN_INFO_ROLES, 1, "", "SHOW CREATE TOPIC"},
{PRIV_CM_SUBSCRIBE, PRIV_CATEGORY_OBJECT, PRIV_OBJ_TOPIC, 1, 0, 1, "", "SUBSCRIBE TOPIC"},
{PRIV_CONSUMER_SHOW, PRIV_CATEGORY_OBJECT, PRIV_OBJ_TOPIC, 1, SYS_ADMIN_INFO_ROLES, 1, "", "SHOW CONSUMERS"},
{PRIV_SUBSCRIPTION_SHOW, PRIV_CATEGORY_OBJECT, PRIV_OBJ_TOPIC, 1, SYS_ADMIN_INFO_ROLES, 1, "",
"SHOW SUBSCRIPTIONS"},
// Stream Privileges
{PRIV_STREAM_CREATE, PRIV_CATEGORY_OBJECT, PRIV_OBJ_DB, 0, T_ROLE_SYSDBA, 2, "", "CREATE STREAM"},
{PRIV_CM_DROP, PRIV_CATEGORY_OBJECT, PRIV_OBJ_STREAM, 1, T_ROLE_SYSDBA, 2, "", "DROP STREAM"},
{PRIV_CM_SHOW, PRIV_CATEGORY_OBJECT, PRIV_OBJ_STREAM, 1, SYS_ADMIN_INFO_ROLES, 1, "", "SHOW STREAMS"},
{PRIV_CM_SHOW_CREATE, PRIV_CATEGORY_OBJECT, PRIV_OBJ_STREAM, 1, SYS_ADMIN_INFO_ROLES, 1, "", "SHOW CREATE STREAM"},
{PRIV_CM_START, PRIV_CATEGORY_OBJECT, PRIV_OBJ_STREAM, 1, T_ROLE_SYSDBA, 2, "", "START STREAM"},
{PRIV_CM_STOP, PRIV_CATEGORY_OBJECT, PRIV_OBJ_STREAM, 1, T_ROLE_SYSDBA, 2, "", "STOP STREAM"},
{PRIV_CM_RECALC, PRIV_CATEGORY_OBJECT, PRIV_OBJ_STREAM, 1, T_ROLE_SYSDBA, 2, "", "RECALCULATE STREAM"},
// Xnode/Xnode Task Privileges
{PRIV_CM_SHOW, PRIV_CATEGORY_OBJECT, PRIV_OBJ_XTASK, 0, T_ROLE_SYSDBA, 1, "", "SHOW XNODE TASKS"},
{PRIV_CM_ALTER, PRIV_CATEGORY_OBJECT, PRIV_OBJ_XTASK, 0, T_ROLE_SYSDBA, 2, "", "ALTER XNODE TASK"},
{PRIV_CM_DROP, PRIV_CATEGORY_OBJECT, PRIV_OBJ_XTASK, 0, T_ROLE_SYSDBA, 2, "", "DROP XNODE TASK"},
};
static SPrivInfo* privLookup[MAX_PRIV_TYPE + 1] = {0};
static void initPrivLookup(void) {
for (size_t i = 0; i < sizeof(privInfoTable) / sizeof(privInfoTable[0]); ++i) {
EPrivType privType = privInfoTable[i].privType;
if (privType <= MAX_PRIV_TYPE &&
!privLookup[privType]) { // duplicated items for other purpose, e.g. createDefaultRoles.
privLookup[privType] = &privInfoTable[i];
}
}
}
int32_t privExpandAll(SPrivSet* privSet, EPrivObjType pObjType, uint8_t pObjLevel) {
if (!privSet) return TSDB_CODE_APP_ERROR;
if (!PRIV_HAS(privSet, PRIV_CM_ALL)) return TSDB_CODE_SUCCESS;
SPrivInfoIter iter = {0};
privInfoIterInit(&iter);
SPrivInfo* pPrivInfo = NULL;
while (privInfoIterNext(&iter, &pPrivInfo)) {
if (pPrivInfo->objType != pObjType) continue;
if (pPrivInfo->objLevel != pObjLevel) {
uWarn("privExpandAll: skip privType %d due to level mismatch, expected %d vs %d", pPrivInfo->privType, pObjLevel,
pPrivInfo->objLevel);
continue;
}
if (pPrivInfo->category != PRIV_CATEGORY_OBJECT) {
uWarn("privExpandAll: skip privType %d due to category mismatch, expected OBJECT vs %d", pPrivInfo->privType,
pPrivInfo->category);
continue;
}
privAddType(privSet, pPrivInfo->privType);
}
return TSDB_CODE_SUCCESS;
}
int32_t privExpandRw(SPrivSet* privSet, EPrivObjType pObjType, uint8_t pObjLevel) {
if (!privSet) return TSDB_CODE_APP_ERROR;
bool hasRead = PRIV_HAS(privSet, PRIV_CM_READ);
bool hasWrite = PRIV_HAS(privSet, PRIV_CM_WRITE);
if (!hasRead && !hasWrite) return TSDB_CODE_SUCCESS;
// Remove the legacy types
if (hasRead) privRemoveType(privSet, PRIV_CM_READ);
if (hasWrite) privRemoveType(privSet, PRIV_CM_WRITE);
SPrivInfoIter iter = {0};
privInfoIterInit(&iter);
SPrivInfo* pPrivInfo = NULL;
while (privInfoIterNext(&iter, &pPrivInfo)) {
if (pPrivInfo->objType != pObjType) continue;
if (pPrivInfo->objLevel != pObjLevel) continue;
if (pPrivInfo->category != PRIV_CATEGORY_OBJECT) continue;
// Check rwAttr and add corresponding privileges
// rwAttr: 1 = read, 2 = write, 3 = read/write
if (hasRead && (pPrivInfo->rwAttr & PRIV_RW_ATTR_READ)) {
privAddType(privSet, pPrivInfo->privType);
}
if (hasWrite && (pPrivInfo->rwAttr & PRIV_RW_ATTR_WRITE)) {
privAddType(privSet, pPrivInfo->privType);
}
}
return TSDB_CODE_SUCCESS;
}
int32_t privUpgradeRwDb(SHashObj* objPrivs, const char* dbFName, const char* tbName, uint8_t rwAttr) {
if (!objPrivs) return TSDB_CODE_APP_ERROR;
int32_t code = 0, lino = 0;
char key[TSDB_PRIV_MAX_KEY_LEN] = {0};
SPrivInfoIter iter = {0};
privInfoIterInit(&iter);
SPrivInfo* pPrivInfo = NULL;
while (privInfoIterNext(&iter, &pPrivInfo)) {
if ((pPrivInfo->rwAttr & rwAttr) == 0) continue;
SPrivInfo privInfo = {.objType = pPrivInfo->objType, .objLevel = pPrivInfo->objLevel};
int32_t keyLen = privObjKeyF(&privInfo, dbFName, tbName, key, sizeof(key));
SPrivObjPolicies* policies = taosHashGet(objPrivs, key, keyLen + 1);
if (policies == NULL) {
SPrivObjPolicies policy = {0};
privAddType(&policy.policy, pPrivInfo->privType);
TAOS_CHECK_EXIT(taosHashPut(objPrivs, key, keyLen + 1, &policy, sizeof(SPrivObjPolicies)));
} else {
privAddType(&policies->policy, pPrivInfo->privType);
}
}
_exit:
return code;
}
int32_t privCheckConflicts(const SPrivSet* privSet, EPrivCategory* pCategory, EPrivObjType* pObjType,
uint8_t* pObjLevel, EPrivType* conflict0, EPrivType* conflict1) {
(void)taosThreadOnce(&privInit, initPrivLookup);
if (!privSet) return TSDB_CODE_APP_ERROR;
int32_t code = 0;
const SPrivInfo* privInfo = NULL;
bool hasSystemPriv = false;
bool hasObjectPriv = false;
bool hasCommonPriv = false;
EPrivType lastPriv = PRIV_TYPE_UNKNOWN;
for (int32_t i = 0; i < PRIV_GROUP_CNT; ++i) {
uint64_t chunk = privSet->set[i];
if (chunk == 0) continue;
while (chunk != 0) {
int32_t bitPos = BUILDIN_CTZL(chunk);
EPrivType privType = (i << 6) + bitPos;
chunk &= ~(1ULL << bitPos);
privInfo = privLookup[privType];
if (privInfo == NULL) continue;
switch (privInfo->category) {
case PRIV_CATEGORY_SYSTEM: {
if (hasObjectPriv || hasCommonPriv) {
code = 1;
goto _exit;
}
hasSystemPriv = true;
lastPriv = privInfo->privType;
break;
}
case PRIV_CATEGORY_OBJECT: {
if (hasSystemPriv) {
code = 1;
goto _exit;
}
if ((*pObjType != privInfo->objType) && (*pObjType != PRIV_OBJ_NONE)) {
code = 2;
goto _exit;
}
if (*pObjLevel != privInfo->objLevel) {
code = 3;
goto _exit;
}
hasObjectPriv = true;
lastPriv = privInfo->privType;
break;
}
case PRIV_CATEGORY_COMMON: {
if (hasSystemPriv) {
code = 1;
goto _exit;
}
hasCommonPriv = true;
lastPriv = privInfo->privType;
break;
}
default:
break;
}
}
}
_exit:
if (code != 0) {
if (conflict0) *conflict0 = lastPriv;
if (conflict1 && privInfo) *conflict1 = privInfo->privType;
return code;
}
if (pCategory) {
*pCategory = hasSystemPriv ? PRIV_CATEGORY_SYSTEM
: hasObjectPriv ? PRIV_CATEGORY_OBJECT
: hasCommonPriv ? PRIV_CATEGORY_COMMON
: PRIV_CATEGORY_UNKNOWN;
}
return 0;
}
void privIterInit(SPrivIter* pIter, SPrivSet* privSet) {
(void)taosThreadOnce(&privInit, initPrivLookup);
pIter->privSet = privSet;
pIter->groupIndex = 0;
pIter->curPriv = privSet->set[0];
}
bool privIterNext(SPrivIter* iter, SPrivInfo** ppPrivInfo) {
_loop:
while (iter->curPriv == 0) {
if (++iter->groupIndex >= PRIV_GROUP_CNT) {
return false;
}
iter->curPriv = iter->privSet->set[iter->groupIndex];
}
int32_t bitPos = BUILDIN_CTZL(iter->curPriv);
EPrivType privType = (iter->groupIndex << 6) + bitPos;
iter->curPriv &= (iter->curPriv -1);
if (ppPrivInfo) {
*ppPrivInfo = privLookup[privType];
if (!(*ppPrivInfo)) goto _loop;
}
return true;
}
void privInfoIterInit(SPrivInfoIter* pIter) {
(void)taosThreadOnce(&privInit, initPrivLookup);
pIter->privInfo = privInfoTable;
pIter->privInfoCnt = sizeof(privInfoTable) / sizeof(privInfoTable[0]);
pIter->index = 0;
}
bool privInfoIterNext(SPrivInfoIter* iter, SPrivInfo** ppPrivInfo) {
if (iter->index < iter->privInfoCnt) {
if (ppPrivInfo) {
*ppPrivInfo = &iter->privInfo[iter->index++];
} else {
iter->index++;
}
return true;
}
return false;
}
// objType.1.db.tb or objType.1.db
int32_t privObjKeyF(const SPrivInfo* pPrivInfo, const char* fname, const char* tb, char* buf, int32_t bufLen) {
return (pPrivInfo->objLevel == 0)
? snprintf(buf, bufLen, "%d.%s", pPrivInfo->objType, fname ? fname : "")
: snprintf(buf, bufLen, "%d.%s.%s", pPrivInfo->objType, fname ? fname : "", tb ? tb : "");
}
int32_t privObjKey(const SPrivInfo* pPrivInfo, int32_t acctId, const char* name, const char* tb, char* buf,
int32_t bufLen) {
return (pPrivInfo->objLevel == 0)
? snprintf(buf, bufLen, "%d.%d.%s", pPrivInfo->objType, acctId, name ? name : "")
: snprintf(buf, bufLen, "%d.%d.%s.%s", pPrivInfo->objType, acctId, name ? name : "", tb ? tb : "");
}
// objType.1.db or objType.1.db.tb
int32_t privObjKeyParse(const char* str, EPrivObjType* pObjType, char* db, int32_t dbLen, char* tb, int32_t tbLen,
bool fullDb) {
char* p = strchr(str, '.');
if (!p) {
return TSDB_CODE_INVALID_DATA_FMT;
}
*pObjType = taosStr2Int32(str, NULL, 10);
if (errno == ERANGE || *pObjType < PRIV_OBJ_CLUSTER || *pObjType >= PRIV_OBJ_MAX) {
return TSDB_CODE_INVALID_DATA_FMT;
}
char* pNext = strchr(p + 1, '.');
if (!pNext) {
return TSDB_CODE_INVALID_DATA_FMT;
}
char* qNext = strchr(pNext + 1, '.');
if (qNext) {
size_t dbLength = qNext - (fullDb ? (p + 1) : (pNext + 1));
if (dbLength >= (size_t)dbLen) {
return TSDB_CODE_INVALID_DATA_FMT;
}
tstrncpy(db, fullDb ? (p + 1) : (pNext + 1), dbLength + 1);
tstrncpy(tb, qNext + 1, tbLen);
} else {
tstrncpy(db, fullDb ? (p + 1) : (pNext + 1), dbLen);
tb[0] = '\0';
}
return TSDB_CODE_SUCCESS;
}
const char* privObjGetName(EPrivObjType objType) {
if (objType < PRIV_OBJ_CLUSTER || objType >= PRIV_OBJ_MAX) {
return "UNKNOWN";
}
return __privObjInfo[objType].name;
}
int32_t privObjGetLevel(EPrivObjType objType) {
if (objType < PRIV_OBJ_CLUSTER || objType >= PRIV_OBJ_MAX) {
return -1;
}
return __privObjInfo[objType].level;
}
int32_t getSysRoleType(const char* roleName) {
if (strcmp(roleName, TSDB_ROLE_SYSDBA) == 0) {
return T_ROLE_SYSDBA;
} else if (strcmp(roleName, TSDB_ROLE_SYSSEC) == 0) {
return T_ROLE_SYSSEC;
} else if (strcmp(roleName, TSDB_ROLE_SYSAUDIT) == 0) {
return T_ROLE_SYSAUDIT;
} else if (strcmp(roleName, TSDB_ROLE_SYSAUDIT_LOG) == 0) {
return T_ROLE_SYSAUDIT_LOG;
} else if (strcmp(roleName, TSDB_ROLE_SYSINFO_0) == 0) {
return T_ROLE_SYSINFO_0;
} else if (strcmp(roleName, TSDB_ROLE_SYSINFO_1) == 0) {
return T_ROLE_SYSINFO_1;
}
return 0;
}
bool isPrivInheritName(const char* name) {
if (name && (name[0] == 'S' || name[0] == 's')) {
if (taosStrncasecmp(name, TSDB_ROLE_SYSDBA, 7) == 0 || taosStrncasecmp(name, TSDB_ROLE_SYSSEC, 7) == 0 ||
taosStrncasecmp(name, TSDB_ROLE_SYSAUDIT, 9) == 0 || taosStrncasecmp(name, TSDB_ROLE_SYSAUDIT_LOG, 13) == 0 ||
taosStrncasecmp(name, TSDB_ROLE_SYSINFO_0, 10) == 0 || taosStrncasecmp(name, TSDB_ROLE_SYSINFO_1, 10) == 0) {
return true;
}
}
return false;
}
int32_t privTblPolicyCopy(SPrivTblPolicy* dest, SPrivTblPolicy* src) {
dest->updateUs = src->updateUs;
dest->condLen = src->condLen;
if (src->cond) {
if (!(dest->cond = taosStrdup(src->cond))) {
return terrno;
}
} else {
dest->cond = NULL;
}
if (taosArrayGetSize(src->cols) > 0) {
dest->cols = taosArrayDup(src->cols, NULL);
if (!dest->cols) return terrno;
} else {
dest->cols = NULL;
}
return 0;
}
int32_t privTblPoliciesAdd(SPrivTblPolicies* dest, SPrivTblPolicies* src, bool deepCopy, bool setUpdateTimeMax) {
int32_t code = 0, lino = 0;
if (deepCopy) {
if (taosArrayGetSize(src->policy) == 0) {
dest->policy = NULL;
goto _exit;
}
if (!dest->policy) {
dest->policy = taosArrayInit(TARRAY_SIZE(src->policy), sizeof(SPrivTblPolicy));
if (!dest->policy) {
TAOS_CHECK_EXIT(terrno);
}
}
for (int32_t j = 0; j < TARRAY_SIZE(src->policy); ++j) {
SPrivTblPolicy* pSrcPolicy = (SPrivTblPolicy*)TARRAY_GET_ELEM(src->policy, j);
SPrivTblPolicy destPolicy = {0};
if ((code = privTblPolicyCopy(&destPolicy, pSrcPolicy))) {
privTblPolicyFree(&destPolicy);
TAOS_CHECK_EXIT(code);
}
if (setUpdateTimeMax) destPolicy.updateUs = INT64_MAX;
if (!taosArrayPush(dest->policy, &destPolicy)) {
privTblPolicyFree(&destPolicy);
TAOS_CHECK_EXIT(terrno);
}
}
} else {
dest->policy = src->policy;
}
_exit:
return code;
}
int32_t privTblPoliciesMerge(SPrivTblPolicies* dest, SPrivTblPolicies* src, bool updateWithLatest) {
int32_t code = 0, lino = 0;
if (taosArrayGetSize(src->policy) == 0) {
dest->policy = NULL;
goto _exit;
}
if (!dest->policy) {
dest->policy = taosArrayInit(TARRAY_SIZE(src->policy), sizeof(SPrivTblPolicy));
if (!dest->policy) {
TAOS_CHECK_EXIT(terrno);
}
}
// only 1 element exist in the table policy array currently
for (int32_t j = 0; j < TARRAY_SIZE(src->policy); ++j) {
SPrivTblPolicy* pSrcPolicy = (SPrivTblPolicy*)TARRAY_GET_ELEM(src->policy, j);
SPrivTblPolicy* pDestPolicy = taosArrayGet(dest->policy, 0);
bool needAdd = false;
if (!pDestPolicy) {
needAdd = true;
} else if (updateWithLatest && (pSrcPolicy->updateUs > pDestPolicy->updateUs)) {
taosArrayClearEx(dest->policy, privTblPolicyFree);
needAdd = true;
}
if (!needAdd) {
break;
}
SPrivTblPolicy destPolicy = {0};
if ((code = privTblPolicyCopy(&destPolicy, pSrcPolicy))) {
privTblPolicyFree(&destPolicy);
TAOS_CHECK_EXIT(code);
}
if (!taosArrayPush(dest->policy, &destPolicy)) {
privTblPolicyFree(&destPolicy);
TAOS_CHECK_EXIT(terrno);
}
}
_exit:
return code;
}
bool privHasObjPrivilege(SHashObj* privs, int32_t acctId, const char* objName, const char* tbName,
const SPrivInfo* privInfo, bool recursive) {
if (tbName != NULL) {
if (privInfo->objLevel == 0 || privInfo->objType <= PRIV_OBJ_DB) {
uError("invalid privilege info for table level check, privType:%d, objType:%d, objLevel:%d\n", privInfo->privType,
privInfo->objType, privInfo->objLevel);
}
}
if (taosHashGetSize(privs) == 0) return false;
const char* pObjName = objName;
const char* pTbName = tbName;
char key[TSDB_PRIV_MAX_KEY_LEN] = {0};
int32_t klen = 0;
_retry:
klen = privObjKey(privInfo, acctId, pObjName, pTbName, key, sizeof(key));
SPrivObjPolicies* policies = taosHashGet(privs, key, klen + 1);
if (policies && PRIV_HAS(&policies->policy, privInfo->privType)) {
return true;
}
if (!recursive) goto _exit;
if (pTbName && !(pTbName[0] == '*' && pTbName[1] == 0)) {
pTbName = "*";
goto _retry;
}
if (pObjName && !(pObjName[0] == '*' && pObjName[1] == 0)) {
pObjName = "*";
goto _retry;
}
_exit:
return false;
}
SPrivTblPolicy* privGetConstraintTblPrivileges(SHashObj* privs, int32_t acctId, const char* objName, const char* tbName,
const SPrivInfo* privInfo) {
if (taosHashGetSize(privs) == 0) return NULL;
const char* pObjName = objName;
const char* pTbName = tbName;
char key[TSDB_PRIV_MAX_KEY_LEN] = {0};
int32_t klen = 0;
klen = privObjKey(privInfo, acctId, pObjName, pTbName, key, sizeof(key));
SPrivTblPolicies* policies = taosHashGet(privs, key, klen + 1);
if (policies) {
return (SPrivTblPolicy*)taosArrayGet(policies->policy, 0);
}
return NULL;
}
const SPrivInfo* privInfoGet(EPrivType privType) {
(void)taosThreadOnce(&privInit, initPrivLookup);
SPrivInfo* result = (privType >= 0 && privType <= MAX_PRIV_TYPE) ? privLookup[privType] : NULL;
if (!result) terrno = TSDB_CODE_APP_ERROR;
return result;
}
const char* privInfoGetName(EPrivType privType) {
const SPrivInfo* privInfo = privInfoGet(privType);
return privInfo ? privInfo->name : "privUnkown";
}
void privAddSetByObjType(SPrivSet* fromSet, SPrivSet* toSet, uint8_t objType) {
SPrivIter privIter = {0};
privIterInit(&privIter, fromSet);
SPrivInfo* pPrivInfo = NULL;
while (privIterNext(&privIter, &pPrivInfo)) {
if (pPrivInfo->objType == objType) {
privAddType(toSet, pPrivInfo->privType);
}
}
}
EPrivObjType privDeduceObjType(SPrivSet* privSet) {
uint32_t objTypeMask = 0; // extend to uint64_t if needed
if (PRIV_OBJ_MAX >= 32) {
return PRIV_OBJ_NONE;
}
SPrivIter privIter = {0};
privIterInit(&privIter, privSet);
SPrivInfo* pPrivInfo = NULL;
while (privIterNext(&privIter, &pPrivInfo)) {
if (pPrivInfo->category == PRIV_CATEGORY_SYSTEM) {
return PRIV_OBJ_NONE;
}
if (pPrivInfo->category == PRIV_CATEGORY_OBJECT) {
switch (pPrivInfo->objType) {
case PRIV_OBJ_DB:
objTypeMask |= (1 << PRIV_OBJ_DB);
break;
case PRIV_OBJ_TBL:
objTypeMask |= (1 << PRIV_OBJ_TBL);
break;
case PRIV_OBJ_VIEW:
objTypeMask |= (1 << PRIV_OBJ_VIEW);
break;
case PRIV_OBJ_TOPIC:
objTypeMask |= (1 << PRIV_OBJ_TOPIC);
break;
case PRIV_OBJ_IDX:
objTypeMask |= (1 << PRIV_OBJ_IDX);
break;
case PRIV_OBJ_RSMA:
objTypeMask |= (1 << PRIV_OBJ_RSMA);
break;
case PRIV_OBJ_TSMA:
objTypeMask |= (1 << PRIV_OBJ_TSMA);
break;
case PRIV_OBJ_STREAM:
objTypeMask |= (1 << PRIV_OBJ_STREAM);
break;
case PRIV_OBJ_XTASK:
objTypeMask |= (1 << PRIV_OBJ_XTASK);
break;
default:
return PRIV_OBJ_NONE;
}
} else if (pPrivInfo->privType == PRIV_CM_SUBSCRIBE) {
objTypeMask |= (1 << PRIV_OBJ_TOPIC);
}
if (objTypeMask > 0) {
uint32_t mask = objTypeMask & (objTypeMask - 1);
if (mask > 0) return PRIV_OBJ_NONE;
}
}
if (objTypeMask == 0) return PRIV_OBJ_NONE;
int32_t bitPos = BUILDIN_CTZL(objTypeMask);
if (bitPos < 0 || bitPos >= PRIV_OBJ_MAX) {
return PRIV_OBJ_NONE;
}
return bitPos;
}