📄 sdbms_datastruct.cpp
字号:
}
/**********************************************************************
功能:释放内存
***********************************************************************/
CSdbms_Database::~CSdbms_Database()
{
if (m_bInit) //要求必须显示调用SaveDD函数
SaveDD();
// if (m_pGuestRole)
// delete m_pGuestRole;
// if (m_pOwnerRole)
// delete m_pOwnerRole;
ASSERT(m_pRole);
delete m_pRole;
// ASSERT(m_pCreatorRole);
// delete m_pCreatorRole;
POSITION pos = m_RoleUserList.GetHeadPosition();
while (pos != NULL)
{
delete m_RoleUserList.GetNext(pos);
}
m_RoleUserList.RemoveAll();
for (int i=0; i<m_TableArray.GetSize(); i++)
{
delete m_TableArray[i];
}
m_TableArray.RemoveAll();
pos = m_UserTableList.GetHeadPosition();
while (pos != NULL)
{
delete m_UserTableList.GetNext(pos);
}
m_UserTableList.RemoveAll();
}
/**********************************************************************
功能:根据角色名找到自定义角色的指针
算法:非递归先序搜索角色树
***********************************************************************/
BOOL CSdbms_Database::GetRole(CString strRoleName, CSdbms_Role **ppRole)
{
ASSERT(m_bInit && m_pRole); //DB必须已经初始化了
ASSERT(strRoleName.CompareNoCase(SYSTEM_ROLE_SYSTEM) != 0); //不能使用系统定义的角色名
ASSERT(strRoleName.CompareNoCase(SYSTEM_ROLE_DBSA) != 0);
ASSERT(strRoleName.CompareNoCase(SYSTEM_ROLE_DBA) != 0);
ASSERT(strRoleName.CompareNoCase(SYSTEM_ROLE_LOGIN) != 0);
ASSERT(strRoleName.CompareNoCase(SYSTEM_ROLE_GUEST) != 0);
ASSERT(strRoleName.CompareNoCase(SYSTEM_ROLE_OWNER) != 0);
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) //比较
{
*ppRole = pTop;
return TRUE;
}
else
{
nTop++;
pStack[nTop] = pTop->m_pNextBrotherRole; //压入左结点
}
}
*ppRole = NULL;
if (nTop >= 100)
g_msg.ThrowErrorMsg("栈溢出");
return FALSE;
}
/**********************************************************************
功能:根据角色内码找到自定义角色的指针
算法:非递归先序搜索角色树
***********************************************************************/
BOOL CSdbms_Database::GetRole(UINT nRoleID, CSdbms_Role **ppRole)
{
ASSERT(m_bInit && m_pRole); //DB必须已经初始化了
// ASSERT(nRoleID != ROLE_LOGIN); //不能使用系统定义的角色名
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 (nRoleID == pTop->m_nRoleID) //比较
{
*ppRole = pTop;
return TRUE;
}
else
{
nTop++;
pStack[nTop] = pTop->m_pNextBrotherRole; //压入左结点
}
}
*ppRole = NULL;
if (nTop >= 100)
g_msg.ThrowErrorMsg("栈溢出");
return FALSE;
}
/**********************************************************************
功能:根据关系名找到数据库中的表指针
算法:顺序遍历表链表,若表较多的话可考虑使用映射表
***********************************************************************/
BOOL CSdbms_Database::GetTable(CString strTableName, CSdbms_Table **ppTable)
{
ASSERT(!strTableName.IsEmpty());
for (int i=0; i<m_TableArray.GetSize(); i++)
{
CSdbms_Table *pTemp = m_TableArray[i];
if (strTableName.CompareNoCase(pTemp->m_strTableName) == 0)
{
*ppTable = pTemp;
return TRUE;
}
}
return FALSE;
}
/**********************************************************************
功能:计算用户在该表上的当前安全级
***********************************************************************/
CSdbms_SecurityLevel CSdbms_Database::GetUserCurSecLevel(CSdbms_User *pUser, CSdbms_Table *pTable)
{
CSdbms_SecurityLevel slUser;
POSITION pos;
if ((pos = FindUserTable(pUser, pTable)) != NULL) //先查找用户-关系表
{
//用户当前安全级<=用户允许安全级<=表安全级
CSdbms_UserTable *pUserTable = m_UserTableList.GetAt(pos);
ASSERT(!(pUserTable->m_CurSecLevel.IsEmpty()));
ASSERT(pUserTable->m_CurSecLevel <= pUserTable->m_AllowSecLevel);
ASSERT(pUserTable->m_AllowSecLevel <= pTable->m_SecLevel);
slUser = pUserTable->m_CurSecLevel;
}
else if (IsTableGuest(pUser, pTable))
{
//如果没找到,则密级等于用户密级与表密级的最小值,非分层范围等于表安全级的非分层范围
slUser = pTable->m_SecLevel;
slUser.m_nClassifaction = min(pUser->m_SecLevel.m_nClassifaction, pTable->m_SecLevel.m_nClassifaction);
}
else
{
//slUser.Empty();
}
return slUser;
}
/**********************************************************************
功能:计算用户在该表上的允许安全级
***********************************************************************/
CSdbms_SecurityLevel CSdbms_Database::GetUserAllowSecLevel(CSdbms_User *pUser, CSdbms_Table *pTable)
{
CSdbms_SecurityLevel slUser;
POSITION pos;
if ((pos = FindUserTable(pUser, pTable)) != NULL) //先查找用户-关系表
{
//用户当前安全级<=用户允许安全级<=表安全级
CSdbms_UserTable *pUserTable = m_UserTableList.GetAt(pos);
ASSERT(pUserTable->m_CurSecLevel <= pUserTable->m_AllowSecLevel);
ASSERT(pUserTable->m_AllowSecLevel <= pTable->m_SecLevel);
slUser = pUserTable->m_AllowSecLevel;
}
else if (IsTableGuest(pUser, pTable))
{
//如果没找到,则缺省的允许安全级的密级=min(表安全级密级,用户密级),非分层范围等于表安全级的非分层范围
slUser = pTable->m_SecLevel;
slUser.m_nClassifaction = min(pUser->m_SecLevel.m_nClassifaction, pTable->m_SecLevel.m_nClassifaction);
}
else
{
//slUser.Empty();
}
return slUser;
}
/**********************************************************************
功能:根据关系内码找到数据库中的表指针
算法:顺序遍历表链表,若表较多的话可考虑使用映射表
***********************************************************************/
BOOL CSdbms_Database::GetTable(UINT nTableID, CSdbms_Table **ppTable)
{
ASSERT(nTableID >= 0);
for (int i=0; i<m_TableArray.GetSize(); i++)
{
CSdbms_Table *pTemp = m_TableArray[i];
if (pTemp->m_nTableID == nTableID)
{
*ppTable = pTemp;
return TRUE;
}
else if (pTemp->m_nTableID > nTableID)
break;
}
return FALSE;
}
/**********************************************************************
功能:判断用户是否可连接到数据库上
算法:首先判断用户是否属于某自定义角色,再判断是否属于某表内的角色
***********************************************************************/
BOOL CSdbms_Database::IsOwnLoginRole(CSdbms_User *pUser)
{
ASSERT(m_bInit); //DB必须已经初始化了
ASSERT(pUser);
//判断用户是否属于某个角色
if (pUser->m_pos != NULL)
return TRUE;
return FALSE;
}
/**********************************************************************
功能:判断用户是否是数据库的创建者
***********************************************************************/
BOOL CSdbms_Database::IsDBCreator(UINT nUserID)
{
ASSERT(m_bInit); //DB必须已经初始化了
return (m_nCreatorID == nUserID);
}
/**********************************************************************
功能:判断用户是否是数据库中某表的创建者
***********************************************************************/
BOOL CSdbms_Database::IsTableCreator(UINT nUserID, CString strTableName)
{
//表是否存在
CSdbms_Table *pTable=NULL;
if (!GetTable(strTableName, &pTable))
{
sprintf(g_strMsg, "数据库%s中没有表名%s", m_strDBName, strTableName);
g_msg.ThrowErrorMsg(g_strMsg);
return FALSE;
}
ASSERT(pTable);
return pTable->IsTableCreator(nUserID);
}
/**********************************************************************
功能:判断用户是否是表上的客户
***********************************************************************/
BOOL CSdbms_Database::IsTableGuest(CSdbms_User *pUser, CSdbms_Table *pTable)
{
ASSERT(pUser && pTable);
UINT nUserID = pUser->m_nUserID;
UINT nTableID = pTable->m_nTableID;
if (IsDBCreator(nUserID)) //数据库创建者
return TRUE;
if (pTable->IsTableCreator(nUserID)) //表创建者
return TRUE;
if (g_sdbms.IsOwnDbaRole(nUserID)) //DBA用户
return TRUE;
//遍历用户所属的自定义角色
POSITION pos = pUser->m_pos;
while (pos)
{
CSdbms_RoleUser *pRoleUser = m_UserRoleList.GetNext(pos);
if (pRoleUser->m_pUser->m_nUserID != nUserID)
break;
CSdbms_Role *pRole = pRoleUser->m_pRole;
POSITION pos2 = pRole->m_ORList.GetHeadPosition();
while (pos2) //遍历角色所有的对象权限
{
CSdbms_RoleObjectRight *pRight = pRole->m_ORList.GetNext(pos2);
if (pRight->m_nTableID == nTableID)
return TRUE;
}
}
return FALSE;
}
/**********************************************************************
功能:用户在这个数据库上是否具有某些系统权限
***********************************************************************/
BOOL CSdbms_Database::HaveSystemRight(CSdbms_User *pUser, SystemRight nSqlID)
{
ASSERT(pUser);
POSITION pos = pUser->m_pos;
while (pos != NULL)
{
CSdbms_RoleUser *pRoleUser = m_UserRoleList.GetNext(pos);
if (pRoleUser->m_pUser->m_nUserID != pUser->m_nUserID)
break;
else if (pRoleUser->m_pRole->FindSystemRight(nSqlID))
return TRUE;
}
return FALSE;
}
/**********************************************************************
功能:用户在某个表的某个列上是否具有操作权限
算法:遍历用户所属的角色,查找是否具有指定权限(不管对象权限中有无与列相关的谓词条件)
***********************************************************************/
BOOL CSdbms_Database::FindObjectRight(CSdbms_User *pUser, CSdbms_Table *pTable, CSdbms_Field *pField, ObjectRight nObjectRight)
{
ASSERT(pUser && pTable && pField);
UINT nTableID = pTable->m_nTableID;
UINT nFieldID = pField->m_nFieldID;
if (g_sdbms.IsOwnDbaRole(pUser->m_nUserID) || //DBA
IsDBCreator(pUser->m_nUserID) || //数据库创建者
pTable->IsTableCreator(pUser->m_nUserID)) //表创建者
return TRUE;
//遍历用户所属角色
POSITION pos = pUser->m_pos;
while (pos != NULL)
{
CSdbms_RoleUser *pRoleUser = m_UserRoleList.GetNext(pos);
if (pRoleUser->m_pUser->m_nUserID == pUser->m_nUserID)
{
//遍历角色所拥有的角色-对象权限表
CSdbms_Role *pRole = pRoleUser->m_pRole;
if (pRole->FindObjectRight(nTableID, nFieldID, nObjectRight))
return TRUE;
}
else
break;
}
sprintf(g_strMsg, "用户%s没有在数据对象%s.%s.%s上的%s权限",
pUser->m_strUserName, m_strDBName, pTable->m_strTableName, pField->m_strFieldName, g_strObjectRight[nObjectRight]);
g_msg.ThrowErrorMsg(g_strMsg);
return FALSE;
}
/**********************************************************************
功能:用户在某个表的某个列上是否具有操作权限(要计算与数值相关的谓词条件)
算法:遍历用户所属的角色,检查是否具有指定权限
***********************************************************************/
BOOL CSdbms_Database::HaveObjectRight(CSdbms_User *pUser, CSdbms_Table *pTable,
CSdbms_Field *pField, ObjectRight nObjectRight, BYTE *pRecord)
{
ASSERT(pUser && pTable && pField);
if (g_sdbms.IsOwnDbaRole(pUser->m_nUserID) || //DBA
IsDBCreator(pUser->m_nUserID) || //数据库创建者
pTable->IsTableCreator(pUser->m_nUserID)) //表创建者
return TRUE;
//遍历用户所属角色
POSITION pos = pUser->m_pos;
while (pos != NULL)
{
CSdbms_RoleUser *pRoleUser = m_UserRoleList.GetNext(pos);
if (pRoleUser->m_pUser->m_nUserID == pUser->m_nUserID)
{
//遍历角色所拥有的角色-对象权限表
CSdbms_Role *pRole = pRoleUser->m_pRole;
if (pRole->HaveObjectRight(pTable, pField, nObjectRight, pRecord))
return TRUE;
}
else
break;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -