Don't add indirectly referenced config entities to service calls (#57671)

This commit is contained in:
Erik Montnemery 2021-10-15 17:46:43 +02:00 committed by GitHub
parent 6881ab58d1
commit 2b37943355
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 40 additions and 13 deletions

View File

@ -61,7 +61,7 @@ async def async_setup(hass: ha.HomeAssistant, config: ConfigType) -> bool: # no
async def async_handle_turn_service(service):
"""Handle calls to homeassistant.turn_on/off."""
referenced = await async_extract_referenced_entity_ids(hass, service)
referenced = async_extract_referenced_entity_ids(hass, service)
all_referenced = referenced.referenced | referenced.indirectly_referenced
# Generic turn on/off method requires entity id

View File

@ -396,7 +396,7 @@ def _async_register_events_and_services(hass: HomeAssistant):
async def async_handle_homekit_unpair(service):
"""Handle unpair HomeKit service call."""
referenced = await async_extract_referenced_entity_ids(hass, service)
referenced = async_extract_referenced_entity_ids(hass, service)
dev_reg = device_registry.async_get(hass)
for device_id in referenced.referenced_devices:
dev_reg_ent = dev_reg.async_get(device_id)

View File

@ -20,6 +20,8 @@ from homeassistant.const import (
CONF_SERVICE_DATA,
CONF_SERVICE_TEMPLATE,
CONF_TARGET,
ENTITY_CATEGORY_CONFIG,
ENTITY_CATEGORY_DIAGNOSTIC,
ENTITY_MATCH_ALL,
ENTITY_MATCH_NONE,
)
@ -279,9 +281,7 @@ async def async_extract_entities(
if data_ent_id == ENTITY_MATCH_ALL:
return [entity for entity in entities if entity.available]
referenced = await async_extract_referenced_entity_ids(
hass, service_call, expand_group
)
referenced = async_extract_referenced_entity_ids(hass, service_call, expand_group)
combined = referenced.referenced | referenced.indirectly_referenced
found = []
@ -310,9 +310,7 @@ async def async_extract_entity_ids(
Will convert group entity ids to the entity ids it represents.
"""
referenced = await async_extract_referenced_entity_ids(
hass, service_call, expand_group
)
referenced = async_extract_referenced_entity_ids(hass, service_call, expand_group)
return referenced.referenced | referenced.indirectly_referenced
@ -322,7 +320,7 @@ def _has_match(ids: str | list | None) -> bool:
@bind_hass
async def async_extract_referenced_entity_ids(
def async_extract_referenced_entity_ids(
hass: HomeAssistant, service_call: ServiceCall, expand_group: bool = True
) -> SelectedEntities:
"""Extract referenced entity IDs from a service call."""
@ -363,6 +361,13 @@ async def async_extract_referenced_entity_ids(
return selected
for ent_entry in ent_reg.entities.values():
# Do not add config or diagnostic entities referenced by areas or devices
if ent_entry.entity_category in (
ENTITY_CATEGORY_CONFIG,
ENTITY_CATEGORY_DIAGNOSTIC,
):
continue
if (
# when area matches the target area
ent_entry.area_id in selector.area_ids
@ -384,9 +389,7 @@ async def async_extract_config_entry_ids(
hass: HomeAssistant, service_call: ServiceCall, expand_group: bool = True
) -> set:
"""Extract referenced config entry ids from a service call."""
referenced = await async_extract_referenced_entity_ids(
hass, service_call, expand_group
)
referenced = async_extract_referenced_entity_ids(hass, service_call, expand_group)
ent_reg = entity_registry.async_get(hass)
dev_reg = device_registry.async_get(hass)
config_entry_ids: set[str] = set()
@ -545,7 +548,7 @@ async def entity_service_call(
all_referenced: set[str] | None = None
else:
# A set of entities we're trying to target.
referenced = await async_extract_referenced_entity_ids(hass, call, True)
referenced = async_extract_referenced_entity_ids(hass, call, True)
all_referenced = referenced.referenced | referenced.indirectly_referenced
# If the service function is a string, we'll pass it the service call data

View File

@ -113,12 +113,26 @@ def area_mock(hass):
platform="test",
area_id="own-area",
)
config_entity_in_own_area = ent_reg.RegistryEntry(
entity_id="light.config_in_own_area",
unique_id="config-in-own-area-id",
platform="test",
area_id="own-area",
entity_category="config",
)
entity_in_area = ent_reg.RegistryEntry(
entity_id="light.in_area",
unique_id="in-area-id",
platform="test",
device_id=device_in_area.id,
)
config_entity_in_area = ent_reg.RegistryEntry(
entity_id="light.config_in_area",
unique_id="config-in-area-id",
platform="test",
device_id=device_in_area.id,
entity_category="config",
)
entity_in_other_area = ent_reg.RegistryEntry(
entity_id="light.in_other_area",
unique_id="in-area-a-id",
@ -139,6 +153,13 @@ def area_mock(hass):
platform="test",
device_id=device_no_area.id,
)
config_entity_no_area = ent_reg.RegistryEntry(
entity_id="light.config_no_area",
unique_id="config-no-area-id",
platform="test",
device_id=device_no_area.id,
entity_category="config",
)
entity_diff_area = ent_reg.RegistryEntry(
entity_id="light.diff_area",
unique_id="diff-area-id",
@ -163,10 +184,13 @@ def area_mock(hass):
hass,
{
entity_in_own_area.entity_id: entity_in_own_area,
config_entity_in_own_area.entity_id: config_entity_in_own_area,
entity_in_area.entity_id: entity_in_area,
config_entity_in_area.entity_id: config_entity_in_area,
entity_in_other_area.entity_id: entity_in_other_area,
entity_assigned_to_area.entity_id: entity_assigned_to_area,
entity_no_area.entity_id: entity_no_area,
config_entity_no_area.entity_id: config_entity_no_area,
entity_diff_area.entity_id: entity_diff_area,
entity_in_area_a.entity_id: entity_in_area_a,
entity_in_area_b.entity_id: entity_in_area_b,