162 lines
6.2 KiB
Python
162 lines
6.2 KiB
Python
"""
|
|
Unit tests for RBAC bootstrap initialization.
|
|
Tests that bootstrap creates correct rules and initial data.
|
|
"""
|
|
|
|
import pytest
|
|
from unittest.mock import Mock, MagicMock, patch
|
|
from modules.interfaces.interfaceBootstrap import (
|
|
initBootstrap,
|
|
initRootMandate,
|
|
initAdminUser,
|
|
initEventUser,
|
|
initRbacRules,
|
|
createDefaultRoleRules,
|
|
createTableSpecificRules
|
|
)
|
|
from modules.datamodels.datamodelUam import UserInDB, Mandate, UserPrivilege, AuthAuthority
|
|
from modules.datamodels.datamodelRbac import AccessRule, AccessRuleContext
|
|
from modules.datamodels.datamodelUam import AccessLevel
|
|
|
|
|
|
class TestRbacBootstrap:
|
|
"""Test RBAC bootstrap initialization."""
|
|
|
|
def testInitRootMandateCreatesIfNotExists(self):
|
|
"""Test that initRootMandate creates mandate if it doesn't exist."""
|
|
db = Mock()
|
|
db.getRecordset = Mock(return_value=[]) # No existing mandates
|
|
db.recordCreate = Mock(return_value={"id": "mandate1", "name": "Root"})
|
|
|
|
mandateId = initRootMandate(db)
|
|
|
|
assert mandateId == "mandate1"
|
|
db.recordCreate.assert_called_once()
|
|
callArgs = db.recordCreate.call_args
|
|
assert isinstance(callArgs[0][1], Mandate)
|
|
assert callArgs[0][1].name == "Root"
|
|
|
|
def testInitRootMandateReturnsExisting(self):
|
|
"""Test that initRootMandate returns existing mandate ID."""
|
|
db = Mock()
|
|
db.getRecordset = Mock(return_value=[{"id": "existing_mandate"}])
|
|
|
|
mandateId = initRootMandate(db)
|
|
|
|
assert mandateId == "existing_mandate"
|
|
db.recordCreate.assert_not_called()
|
|
|
|
def testInitAdminUserCreatesWithSysadminRole(self):
|
|
"""Test that initAdminUser creates user with sysadmin role."""
|
|
db = Mock()
|
|
db.getRecordset = Mock(return_value=[]) # No existing users
|
|
db.recordCreate = Mock(return_value={"id": "admin1", "username": "admin"})
|
|
|
|
with patch('modules.interfaces.interfaceBootstrap._getPasswordHash', return_value="hashed"):
|
|
userId = initAdminUser(db, "mandate1")
|
|
|
|
assert userId == "admin1"
|
|
db.recordCreate.assert_called_once()
|
|
callArgs = db.recordCreate.call_args
|
|
user = callArgs[0][1]
|
|
assert isinstance(user, UserInDB)
|
|
assert user.username == "admin"
|
|
assert "sysadmin" in user.roleLabels
|
|
assert user.privilege == UserPrivilege.SYSADMIN
|
|
|
|
def testInitEventUserCreatesWithSysadminRole(self):
|
|
"""Test that initEventUser creates user with sysadmin role."""
|
|
db = Mock()
|
|
db.getRecordset = Mock(return_value=[]) # No existing users
|
|
db.recordCreate = Mock(return_value={"id": "event1", "username": "event"})
|
|
|
|
with patch('modules.interfaces.interfaceBootstrap._getPasswordHash', return_value="hashed"):
|
|
userId = initEventUser(db, "mandate1")
|
|
|
|
assert userId == "event1"
|
|
db.recordCreate.assert_called_once()
|
|
callArgs = db.recordCreate.call_args
|
|
user = callArgs[0][1]
|
|
assert isinstance(user, UserInDB)
|
|
assert user.username == "event"
|
|
assert "sysadmin" in user.roleLabels
|
|
|
|
def testCreateDefaultRoleRules(self):
|
|
"""Test that createDefaultRoleRules creates correct default rules."""
|
|
db = Mock()
|
|
db.recordCreate = Mock()
|
|
|
|
createDefaultRoleRules(db)
|
|
|
|
# Should create 4 default rules (sysadmin, admin, user, viewer)
|
|
assert db.recordCreate.call_count == 4
|
|
|
|
# Check sysadmin rule
|
|
sysadminCall = [call for call in db.recordCreate.call_args_list
|
|
if call[0][1].roleLabel == "sysadmin"][0]
|
|
sysadminRule = sysadminCall[0][1]
|
|
assert sysadminRule.context == AccessRuleContext.DATA
|
|
assert sysadminRule.item is None
|
|
assert sysadminRule.view == True
|
|
assert sysadminRule.read == AccessLevel.ALL
|
|
assert sysadminRule.create == AccessLevel.ALL
|
|
|
|
# Check user rule
|
|
userCall = [call for call in db.recordCreate.call_args_list
|
|
if call[0][1].roleLabel == "user"][0]
|
|
userRule = userCall[0][1]
|
|
assert userRule.read == AccessLevel.MY
|
|
assert userRule.create == AccessLevel.MY
|
|
|
|
def testCreateTableSpecificRules(self):
|
|
"""Test that createTableSpecificRules creates table-specific rules."""
|
|
db = Mock()
|
|
db.recordCreate = Mock()
|
|
|
|
createTableSpecificRules(db)
|
|
|
|
# Should create multiple rules for different tables
|
|
assert db.recordCreate.call_count > 0
|
|
|
|
# Check that Mandate table rules are created
|
|
mandateCalls = [call for call in db.recordCreate.call_args_list
|
|
if call[0][1].item == "Mandate"]
|
|
assert len(mandateCalls) > 0
|
|
|
|
# Check sysadmin rule for Mandate
|
|
sysadminMandateCall = [call for call in mandateCalls
|
|
if call[0][1].roleLabel == "sysadmin"][0]
|
|
sysadminRule = sysadminMandateCall[0][1]
|
|
assert sysadminRule.view == True
|
|
assert sysadminRule.read == AccessLevel.ALL
|
|
|
|
# Check that other roles have view=False for Mandate
|
|
otherMandateCalls = [call for call in mandateCalls
|
|
if call[0][1].roleLabel != "sysadmin"]
|
|
for call in otherMandateCalls:
|
|
rule = call[0][1]
|
|
assert rule.view == False
|
|
|
|
def testInitRbacRulesSkipsIfExists(self):
|
|
"""Test that initRbacRules skips creation if rules already exist."""
|
|
db = Mock()
|
|
db.getRecordset = Mock(return_value=[{"id": "rule1"}]) # Rules exist
|
|
|
|
initRbacRules(db)
|
|
|
|
# Should not create new rules
|
|
db.recordCreate.assert_not_called()
|
|
|
|
def testInitRbacRulesCreatesIfNotExists(self):
|
|
"""Test that initRbacRules creates rules if they don't exist."""
|
|
db = Mock()
|
|
db.getRecordset = Mock(side_effect=[
|
|
[], # No existing rules
|
|
[] # After creating default rules
|
|
])
|
|
db.recordCreate = Mock()
|
|
|
|
initRbacRules(db)
|
|
|
|
# Should create rules
|
|
assert db.recordCreate.call_count > 0
|