⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sdbms_datastruct.cpp

📁 使用yacc的一个例子
💻 CPP
📖 第 1 页 / 共 5 页
字号:
	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 + -