mirror of
https://github.com/jkingsman/Remote-Terminal-for-MeshCore.git
synced 2026-05-14 21:36:03 +02:00
Fix gap in don't-ingest logic. Closes #247.
This commit is contained in:
@@ -237,6 +237,24 @@ async def on_new_contact(event: "Event") -> None:
|
||||
logger.debug("New contact: %s", public_key[:12])
|
||||
|
||||
contact_upsert = ContactUpsert.from_radio_dict(public_key.lower(), payload, on_radio=False)
|
||||
|
||||
# Block new contacts whose type is in discovery_blocked_types, matching
|
||||
# the same guard in _process_advertisement. Existing contacts (already
|
||||
# in the DB) are always updated.
|
||||
existing = await ContactRepository.get_by_key(public_key.lower())
|
||||
contact_type = contact_upsert.type or 0
|
||||
if existing is None and contact_type > 0:
|
||||
from app.repository import AppSettingsRepository
|
||||
|
||||
settings = await AppSettingsRepository.get()
|
||||
if contact_type in settings.discovery_blocked_types:
|
||||
logger.debug(
|
||||
"Skipping new contact %s: type %d is in discovery_blocked_types",
|
||||
public_key[:12],
|
||||
contact_type,
|
||||
)
|
||||
return
|
||||
|
||||
# Intentionally do not set first_seen or last_seen here: NEW_CONTACT
|
||||
# fires from the radio's stored contact DB, not an RF observation.
|
||||
# Both first_seen and last_seen are RF-only timestamps — they track
|
||||
|
||||
@@ -1182,3 +1182,62 @@ class TestOnNewContact:
|
||||
|
||||
contacts = await ContactRepository.get_all()
|
||||
assert len(contacts) == 0
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_blocks_new_contact_with_discovery_blocked_type(self, test_db):
|
||||
"""NEW_CONTACT for a blocked type should not create a contact."""
|
||||
from app.event_handlers import on_new_contact
|
||||
from app.repository import AppSettingsRepository
|
||||
|
||||
# Block clients (type 1) and rooms (type 3)
|
||||
await AppSettingsRepository.update(discovery_blocked_types=[1, 3])
|
||||
|
||||
with (
|
||||
patch("app.event_handlers.broadcast_event") as mock_broadcast,
|
||||
patch("app.event_handlers.time") as mock_time,
|
||||
):
|
||||
mock_time.time.return_value = 1700000000
|
||||
|
||||
class MockEvent:
|
||||
payload = {
|
||||
"public_key": "dd" * 32,
|
||||
"adv_name": "BlockedClient",
|
||||
"type": 1,
|
||||
"flags": 0,
|
||||
}
|
||||
|
||||
await on_new_contact(MockEvent())
|
||||
|
||||
contact = await ContactRepository.get_by_key("dd" * 32)
|
||||
assert contact is None
|
||||
mock_broadcast.assert_not_called()
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_allows_new_contact_with_non_blocked_type(self, test_db):
|
||||
"""NEW_CONTACT for a non-blocked type should still be created."""
|
||||
from app.event_handlers import on_new_contact
|
||||
from app.repository import AppSettingsRepository
|
||||
|
||||
# Block only clients (type 1)
|
||||
await AppSettingsRepository.update(discovery_blocked_types=[1])
|
||||
|
||||
with (
|
||||
patch("app.event_handlers.broadcast_event") as mock_broadcast,
|
||||
patch("app.event_handlers.time") as mock_time,
|
||||
):
|
||||
mock_time.time.return_value = 1700000000
|
||||
|
||||
class MockEvent:
|
||||
payload = {
|
||||
"public_key": "ee" * 32,
|
||||
"adv_name": "AllowedRepeater",
|
||||
"type": 2,
|
||||
"flags": 0,
|
||||
}
|
||||
|
||||
await on_new_contact(MockEvent())
|
||||
|
||||
contact = await ContactRepository.get_by_key("ee" * 32)
|
||||
assert contact is not None
|
||||
assert contact.name == "AllowedRepeater"
|
||||
mock_broadcast.assert_called_once()
|
||||
|
||||
Reference in New Issue
Block a user