📄 sdbms_datastruct.cpp
字号:
return FALSE;
}
/**********************************************************************
功能:删掉数据库中与该用户相关的信息
***********************************************************************/
BOOL CSdbms_Database::DeleteUser(CSdbms_User *pUser)
{
ASSERT(m_bInit && m_pRole); //DB必须已经初始化了
ASSERT(pUser);
//删除由该用户授权的系统权限和对象权限
VERIFY(Revoke(pUser));
//判断用户是不是数据库的创建者
if (IsDBCreator(pUser->m_nUserID))
{
m_nCreatorID = 0; //如果数据库创建者被删除了,把DBA作为数据库的创建者
//改变用户角色关系
CSdbms_User *pDbaUser=NULL;
// pDbaUser = g_sdbms.FindRoleUser(g_sdbms.GetD)->m_pUser; //得到用户dba的指针
VERIFY(g_sdbms.GetUser(SYSTEM_ROLE_DBA, &pDbaUser)); //得到用户dba的指针
ASSERT(pDbaUser);
CSdbms_RoleUser *pTemp = RemoveUserRoleList(pUser, m_pCreatorRole);
ASSERT(pTemp == m_RoleUserList.GetHead());//因为m_pCreatorRole的ID最小且只有一个用户
pTemp->m_pUser = pDbaUser; //改变m_RoleUserList
VERIFY(InsertUserRoleList(pTemp)); //改变m_UserRoleList
}
//判断用户是不是表的创建者
for (int i=0; i<m_TableArray.GetSize(); i++)
{
CSdbms_Table *pTable = m_TableArray[i];
if (pUser->m_nUserID == pTable->m_nCreatorID)
{
pTable->m_nCreatorID = 0; //如果表创建者被删除了,把DBA作为表的创建者
//改变用户角色关系
CSdbms_User *pDbaUser;
// pDbaUser = g_sdbms.GetDbaRoleUser()->m_pUser; //得到用户dba的指针
VERIFY(g_sdbms.GetUser(SYSTEM_ROLE_DBA, &pDbaUser)); //得到用户dba的指针
ASSERT(pDbaUser);
CSdbms_RoleUser *pTemp1 = RemoveRoleUserList(pUser, m_TableArray[i]->m_pCreatorRole);
CSdbms_RoleUser *pTemp2 = RemoveUserRoleList(pUser, m_TableArray[i]->m_pCreatorRole);
ASSERT(pTemp1 == pTemp2);
pTemp1->m_pUser = pDbaUser; //用户dba
VERIFY(InsertRoleUserList(pTemp1));
VERIFY(InsertUserRoleList(pTemp1));
}
}
//删除相应的角色用户关系
POSITION pos = pUser->m_pos;
while (pos != NULL)
{
POSITION prepos = pos;
CSdbms_RoleUser *pRoleUser = m_UserRoleList.GetNext(pos);
if (pRoleUser->m_pUser->m_nUserID != pUser->m_nUserID)
break;
//从角色用户表中删除
VERIFY(RemoveRoleUserList(pUser, pRoleUser->m_pRole) == pRoleUser);
m_UserRoleList.RemoveAt(prepos); //从m_UserRoleList中删去
delete pRoleUser; //释放该结点
}
return TRUE;
}
/**********************************************************************
功能:创建新角色
***********************************************************************/
BOOL CSdbms_Database::CreateRole(CString strRoleName)
{
//检查角色名是否已存在
CSdbms_Role *pTempRole = NULL;
if (GetRole(strRoleName, &pTempRole))
{
sprintf(g_strMsg, "角色%s已存在", strRoleName);
g_msg.ThrowErrorMsg(g_strMsg);
return FALSE;
}
//创建新角色对象
// m_nMaxRoleID++;
CSdbms_Role *pRole = new CSdbms_Role(strRoleName, m_nMaxRoleID++);
//把角色插入到角色树中(第一层)
pTempRole = m_pRole;
while (pTempRole->m_pNextBrotherRole)
pTempRole = pTempRole->m_pNextBrotherRole;
pTempRole->m_pNextBrotherRole = pRole;
sprintf(g_strMsg, "增加新角色%s成功", strRoleName);
g_msg.ThrowSuccessMsg(g_strMsg);
return TRUE;
}
/**********************************************************************
功能:删除角色
算法:调整角色树。父角色被删除,子角色升级到上一层。相应的角色用户关系也要删除
***********************************************************************/
BOOL CSdbms_Database::DropRole(CString strRoleName)
{
CSdbms_Role *pTop=NULL; //角色strRoleName
//调整角色树
if (!AdjustRoleTree(strRoleName, &pTop))
return FALSE;
//收回该角色所有的对象权限
VERIFY(Revoke(pTop));
//删除相应的角色用户关系
POSITION pos = pTop->m_pos;
while (pos != NULL)
{
POSITION prepos = pos;
CSdbms_RoleUser *pRoleUser = m_RoleUserList.GetNext(pos);
if (pRoleUser->m_pRole->m_nRoleID != pTop->m_nRoleID)
break;
//从用户角色表中删除
VERIFY(RemoveUserRoleList(pRoleUser->m_pUser, pTop) == pRoleUser);
m_RoleUserList.RemoveAt(prepos); //从角色用户链中删除
delete pRoleUser;
}
delete pTop;
sprintf(g_strMsg, "成功删除角色%s", strRoleName);
g_msg.ThrowSuccessMsg(g_strMsg);
return TRUE;
}
/**********************************************************************
功能:设置一个角色为另一个角色的父角色
算法:1.调整角色树
2.父角色及其祖先角色要拥有子角色的权限(隐含的执行授权操作,授权人是该命令的执行者)
***********************************************************************/
BOOL CSdbms_Database::SetParentRole(CString strParentRoleName, CString strChildRoleName)
{
CSdbms_Role *pRole1 = NULL; //子角色
CSdbms_Role *pRole2 = NULL; //父角色
//调整角色树
if (!AdjustRoleTree(strParentRoleName, strChildRoleName, &pRole2, &pRole1))
return FALSE;
/*******系统权限只能由DBA用户显示授权。不要求父角色拥有子角色拥有的系统权限************/
//设置父角色的权限
//比较系统权限表
/* POSITION pos1 = pRole1->m_SRList.GetHeadPosition(); //子
POSITION pos2 = pRole2->m_SRList.GetHeadPosition(); //父
POSITION prepos2 = pos2;
CSdbms_RoleSystemRight *pSR2 = pos2 ? pRole2->m_SRList.GetHead() : NULL;
while ((pos1 != NULL) && (pos2 != NULL))
{
CSdbms_RoleSystemRight *pSR1 = pRole1->m_SRList.GetNext(pos1);
while (prepos2 != NULL)
{
if ((pSR1->m_nSqlID <= pSR2->m_nSqlID) || (pos2 == NULL))
break;
prepos2 = pos2;
pSR2 = pRole2->m_SRList.GetNext(pos2);
}
if (pSR1->m_nSqlID == pSR2->m_nSqlID) //父角色也有子角色这个权限
{
//子角色的权限表中加入对父角色的指向
for (int i=0; i<pSR1->m_ToRoleList.GetSize(); i++)
if (pSR1->m_ToRoleList[i] >= pRole2->m_nRoleID)
break;
if (pSR1->m_ToRoleList[i] > pRole2->m_nRoleID)
pSR1->m_ToRoleList.InsertAt(i, pRole2->m_nRoleID);
//父角色的权限表中加入对子角色的指向
for (i=0; i<pSR2->m_FromRoleList.GetSize(); i++)
if (pSR2->m_FromRoleList[i] >= pRole1->m_nRoleID)
break;
if (pSR2->m_FromRoleList[i] > pRole1->m_nRoleID)
pSR2->m_FromRoleList.InsertAt(i, pRole1->m_nRoleID);
prepos2 = pos2;
pSR1 = pRole1->m_SRList.GetNext(pos1);
pSR2 = pRole2->m_SRList.GetNext(pos2);
}
else
{
//子角色的权限表中加入对父角色的指向
for (int i=0; i<pSR1->m_ToRoleList.GetSize(); i++)
if (pSR1->m_ToRoleList[i] > pRole2->m_nRoleID)
break;
pSR1->m_ToRoleList.InsertAt(i, pRole2->m_nRoleID);
//父角色中加入子角色的这一权限
CSdbms_RoleSystemRight *pTemp = new CSdbms_RoleSystemRight;
pTemp->m_nSqlID = pSR1->m_nSqlID;
pTemp->m_bCanGrant = false;
pTemp->m_FromRoleList.Add(pRole1->m_nRoleID);
if (pSR1->m_nSqlID < pSR2->m_nSqlID)
pRole2->m_SRList.InsertBefore(prepos2, pTemp);
else //pos2==NULL
pRole2->m_SRList.AddTail(pTemp);
}
}
*/
//比较对象权限表,把子角色拥有的所有对象权限都GRANT给父角色及其祖先角色,授权人是当前用户
CSdbms_Role *pParent = pRole2;
while (pParent)
{
POSITION pos1 = pRole1->m_ORList.GetHeadPosition();
while (pos1 != NULL)
{
bool bGrant = false;
CSdbms_RoleObjectRight *pOR1 = pRole1->m_ORList.GetNext(pos1);
if (g_sdbms.IsOwnDbaRole(g_sdbms.GetCurUser()->m_nUserID)) //当前用户属于DBA
{
CSdbms_RoleUser *pTemp = g_sdbms.FindRoleUser(g_sdbms.GetCurUser(), g_sdbms.GetDbaRole());
ASSERT(pTemp);
if (pParent->InsertORList(pOR1->m_nSqlID, pOR1->m_nTableID,
pOR1->m_nFieldID, pTemp, FALSE, pOR1->m_pCondition))
{
bGrant = true;
CSdbms_RoleObjectRight *pRight = pTemp->m_pRole->m_ORList.GetHead();
ASSERT(pRight);
VERIFY(pRight->InsertToRoleArray(pParent)); //系统预定义角色都只有一个对象权限结点
}
}
if (IsDBCreator(g_sdbms.GetCurUser()->m_nUserID)) //当前用户是DB创建者
{
CSdbms_RoleUser *pTemp = m_RoleUserList.GetHead(); //是第一个结点
ASSERT(pTemp);
if (pParent->InsertORList(pOR1->m_nSqlID, pOR1->m_nTableID,
pOR1->m_nFieldID, pTemp, FALSE, pOR1->m_pCondition))
{
bGrant = true;
CSdbms_RoleObjectRight *pRight = pTemp->m_pRole->m_ORList.GetHead();
ASSERT(pRight);
VERIFY(pRight->InsertToRoleArray(pParent)); //系统预定义角色都只有一个对象权限结点
}
}
}
pParent = pParent->m_pParentRole;
}
sprintf(g_strMsg, "角色%s成功设置为角色%s的父角色", strParentRoleName, strChildRoleName);
g_msg.ThrowSuccessMsg(g_strMsg);
return TRUE;
}
/**********************************************************************
功能:设置一个角色是另一个角色的子角色
算法:1.调整角色树
2.收回子角色及其子孙角色所有的对象权限
***********************************************************************/
BOOL CSdbms_Database::SetChildRole(CString strParentRoleName, CString strChildRoleName)
{
CSdbms_Role *pRole1 = NULL; //子角色
CSdbms_Role *pRole2 = NULL; //父角色
//调整角色树
if (!AdjustRoleTree(strParentRoleName, strChildRoleName, &pRole2, &pRole1))
return FALSE;
ASSERT(pRole1 && pRole2);
//收回子角色及其子孙角色所有的对象权限
CSdbms_Role *pStack[100]; //栈大小设为100
CSdbms_Role *pTop; //栈顶元素,=pStack[pTop]
int nTop = 0; //栈顶指针
pStack[nTop] = pRole1;
while (nTop < 100) //当栈没溢出
{
pTop = pStack[nTop];
if (pTop == NULL) //退栈操作
{
if (nTop == 0)
break;
else
{
nTop--;
pStack[nTop] = pStack[nTop]->m_pFirstChildRole; //压入右结点
}
}
else
{
VERIFY(Revoke(pTop)); //收回角色的对象权限
nTop++;
pStack[nTop] = pTop->m_pNextBrotherRole; //压入左结点
}
}
if (nTop >= 100)
{
g_msg.ThrowErrorMsg("栈溢出");
return FALSE;
}
ASSERT(nTop == 0);
sprintf(g_strMsg, "角色%s成功设置为角色%s的子角色", strChildRoleName, strParentRoleName);
g_msg.ThrowSuccessMsg(g_strMsg);
return TRUE;
}
/**********************************************************************
功能:设置角色为顶层角色
算法:调整角色树,角色移到顶层,其子角色升级到上一层
***********************************************************************/
BOOL CSdbms_Database::SetTopRole(CString strRoleName)
{
CSdbms_Role *pRole=m_pRole->m_pNextBrotherRole;
bool bSuccess = false;
//查找顶层角色,如果角色已经是顶层角色了,不用再调整角色树了
while (pRole != NULL)
{
if (strRoleName.CompareNoCase(pRole->m_strRoleName) == 0)
{
bSuccess = true;
break;
}
pRole = pRole->m_pNextBrotherRole;
}
if (!bSuccess)
{
//非递归先序遍历角色树
CSdbms_Role *pStack[100]; //栈大小设为100
CSdbms_Role *pTop; //栈顶元素,=pStack[pTop]
int nTop = 0; //栈顶指针
pStack[nTop] = m_pRole;
while (nTop < 100) //当栈没溢出
{
pTop = pStack[nTop];
if (pTop == NULL) //退栈操作
{
if (nTop == 0)
break;
else
{
nTop--;
pStack[nTop] = pStack[nTop]->m_pFirstChildRole; //压入右结点
}
}
else if (strRoleName.CompareNoCase(pTop->m_strRoleName) == 0) //比较
{
if (pTop->m_pParentRole->m_pFirstChildRole == pTop) //是父角色的第一个子结点
pTop->m_pParentRole->m_pFirstChildRole = pTop->m_pNextBrotherRole;
else //不是父角色的第一个子角色
{
ASSERT(nTop >= 1);
CSdbms_Role *pPreBrother = pStack[nTop-1]; //得到上一个兄弟结点
ASSERT(pPreBrother->m_pNextBrotherRole == pTop);
pPreBrother->m_pNextBrotherRole = pTop->m_pNextBrotherRole;
}
break;
}
else
{
nTop++;
pStack[nTop] = pTop->m_pNextBrotherRole; //压入左结点
}
}
if (nTop == 0)
{
sprintf(g_strMsg, "角色%s不存在", strRoleName);
g_msg.ThrowErrorMsg(g_strMsg);
return FALSE;
}
if (nTop >= 100)
{
g_msg.ThrowErrorMsg("栈溢出");
return FALSE;
}
//把角色移到顶层最后
pTop->m_pParentRole = NULL;
pTop->m_pNextBrotherRole = NULL;
pRole = m_pRole;
while (pRole->m_pNextBrotherRole != NULL)
pRole = pRole->m_pNextBrotherRole;
pRole->m_pNextBrotherRole = pTop;
}
sprintf(g_strMsg, "成功设置角色%s为顶层角色", strRoleName);
g_msg.ThrowSuccessMsg(g_strMsg);
return TRUE;
}
/**********************************************************************
功能:调整角色树,被SetParentRole,SetChildRole调用
算法:把一个子树移到另一个结点下面
***********************************************************************/
BOOL CSdbms_Database::AdjustRoleTree(CString strParentRoleName, CString strChildRoleName,
CSdbms_Role **ppParentRole, CSdbms_Role **ppChildRole)
{
//非递归先序查找父角色和子角色
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -