"""Scope evaluation for the All PCs policy target. These are pure unit tests: policyscope has no db or Flask dependency, so the whole grammar can be exercised with plain dicts. build_endpoint_context needs only duck-typed stand-ins for a Computer row. """ import pytest from plugins.computers.services.policyresolver import build_endpoint_context from plugins.computers.services.policyscope import ( ScopeError, evaluate_scope, validate_scope, ) class FakeComputerType: def __init__(self, icon): self.icon = icon class FakeComputer: """Minimal stand-in for a Computer row, no db required.""" def __init__(self, computertypeid=None, icon=None, installedapps=()): self.computertypeid = computertypeid self.computertype = FakeComputerType(icon) if icon is not None else None self.installedapps = installedapps def test_allpcs_is_a_valid_scope_node(): validate_scope({'type': 'allpcs'}) def test_allpcs_matches_an_ordinary_pc(): context = {'computertypeid': 1, 'appids': set(), 'isserver': False} assert evaluate_scope({'type': 'allpcs'}, context) is True def test_allpcs_does_not_match_a_server(): """The whole point of the option: servers are excluded.""" context = {'computertypeid': 4, 'appids': set(), 'isserver': True} assert evaluate_scope({'type': 'allpcs'}, context) is False def test_allpcs_matches_an_endpoint_with_no_type_designation(): """An untyped endpoint is an ordinary PC until something says otherwise.""" context = {'computertypeid': None, 'appids': set()} assert evaluate_scope({'type': 'allpcs'}, context) is True def test_true_still_matches_a_server(): """'true' keeps its old meaning so existing policies do not silently shift.""" context = {'computertypeid': 4, 'appids': set(), 'isserver': True} assert evaluate_scope({'type': 'true'}, context) is True def test_allpcs_composes_with_other_nodes(): """AND of allpcs and an app still excludes a server running that app.""" scope = { 'type': 'and', 'nodes': [{'type': 'allpcs'}, {'type': 'app', 'id': 7}], } pc = {'computertypeid': 1, 'appids': {7}, 'isserver': False} server = {'computertypeid': 4, 'appids': {7}, 'isserver': True} assert evaluate_scope(scope, pc) is True assert evaluate_scope(scope, server) is False def test_context_marks_a_server_icon_type_as_a_server(): computer = FakeComputer(computertypeid=4, icon='server') assert build_endpoint_context(computer)['isserver'] is True def test_context_does_not_mark_a_desktop_type_as_a_server(): computer = FakeComputer(computertypeid=1, icon='desktop') assert build_endpoint_context(computer)['isserver'] is False def test_context_handles_a_computer_with_no_type(): computer = FakeComputer() assert build_endpoint_context(computer)['isserver'] is False def test_an_unknown_node_type_is_still_rejected(): with pytest.raises(ScopeError): validate_scope({'type': 'allpc'})