Introduce new redact helper (#64579)
parent
53aed22d5c
commit
520ba0a82e
|
@ -1,40 +1,27 @@
|
|||
"""Diagnostics support for AirVisual."""
|
||||
from __future__ import annotations
|
||||
|
||||
from types import MappingProxyType
|
||||
from typing import Any
|
||||
|
||||
from homeassistant.components.diagnostics import REDACTED
|
||||
from homeassistant.components.diagnostics import async_redact_data
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import CONF_API_KEY, CONF_LATITUDE, CONF_LONGITUDE, CONF_STATE
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator
|
||||
|
||||
from .const import CONF_CITY, CONF_COUNTRY, DOMAIN
|
||||
|
||||
CONF_COORDINATES = "coordinates"
|
||||
|
||||
|
||||
@callback
|
||||
def _async_redact_data(data: MappingProxyType | dict) -> dict[str, Any]:
|
||||
"""Redact sensitive data in a dict."""
|
||||
redacted = {**data}
|
||||
|
||||
for key, value in redacted.items():
|
||||
if key in (
|
||||
CONF_API_KEY,
|
||||
CONF_CITY,
|
||||
CONF_COORDINATES,
|
||||
CONF_COUNTRY,
|
||||
CONF_LATITUDE,
|
||||
CONF_LONGITUDE,
|
||||
CONF_STATE,
|
||||
):
|
||||
redacted[key] = REDACTED
|
||||
elif isinstance(value, dict):
|
||||
redacted[key] = _async_redact_data(value)
|
||||
|
||||
return redacted
|
||||
TO_REDACT = {
|
||||
CONF_API_KEY,
|
||||
CONF_CITY,
|
||||
CONF_COORDINATES,
|
||||
CONF_COUNTRY,
|
||||
CONF_LATITUDE,
|
||||
CONF_LONGITUDE,
|
||||
CONF_STATE,
|
||||
}
|
||||
|
||||
|
||||
async def async_get_config_entry_diagnostics(
|
||||
|
@ -46,8 +33,8 @@ async def async_get_config_entry_diagnostics(
|
|||
return {
|
||||
"entry": {
|
||||
"title": entry.title,
|
||||
"data": _async_redact_data(entry.data),
|
||||
"options": _async_redact_data(entry.options),
|
||||
"data": async_redact_data(entry.data, TO_REDACT),
|
||||
"options": async_redact_data(entry.options, TO_REDACT),
|
||||
},
|
||||
"data": _async_redact_data(coordinator.data["data"]),
|
||||
"data": async_redact_data(coordinator.data["data"], TO_REDACT),
|
||||
}
|
||||
|
|
|
@ -1,13 +1,12 @@
|
|||
"""Diagnostics support for Ambient PWS."""
|
||||
from __future__ import annotations
|
||||
|
||||
from types import MappingProxyType
|
||||
from typing import Any
|
||||
|
||||
from homeassistant.components.diagnostics import REDACTED
|
||||
from homeassistant.components.diagnostics import async_redact_data
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import CONF_API_KEY
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.core import HomeAssistant
|
||||
|
||||
from . import AmbientStation
|
||||
from .const import CONF_APP_KEY, DOMAIN
|
||||
|
@ -20,31 +19,17 @@ CONF_MAC_ADDRESS = "mac_address"
|
|||
CONF_MAC_ADDRESS_CAMEL = "macAddress"
|
||||
CONF_TZ = "tz"
|
||||
|
||||
|
||||
@callback
|
||||
def _async_redact_data(data: MappingProxyType | dict) -> dict[str, Any]:
|
||||
"""Redact sensitive data in a dict."""
|
||||
redacted = {**data}
|
||||
|
||||
for key, value in redacted.items():
|
||||
if key in (
|
||||
CONF_API_KEY,
|
||||
CONF_API_KEY_CAMEL,
|
||||
CONF_APP_KEY,
|
||||
CONF_APP_KEY_CAMEL,
|
||||
CONF_DEVICE_ID_CAMEL,
|
||||
CONF_LOCATION,
|
||||
CONF_MAC_ADDRESS,
|
||||
CONF_MAC_ADDRESS_CAMEL,
|
||||
CONF_TZ,
|
||||
):
|
||||
redacted[key] = REDACTED
|
||||
elif isinstance(value, dict):
|
||||
redacted[key] = _async_redact_data(value)
|
||||
elif isinstance(value, list):
|
||||
redacted[key] = [_async_redact_data(item) for item in value]
|
||||
|
||||
return redacted
|
||||
TO_REDACT = {
|
||||
CONF_API_KEY,
|
||||
CONF_API_KEY_CAMEL,
|
||||
CONF_APP_KEY,
|
||||
CONF_APP_KEY_CAMEL,
|
||||
CONF_DEVICE_ID_CAMEL,
|
||||
CONF_LOCATION,
|
||||
CONF_MAC_ADDRESS,
|
||||
CONF_MAC_ADDRESS_CAMEL,
|
||||
CONF_TZ,
|
||||
}
|
||||
|
||||
|
||||
async def async_get_config_entry_diagnostics(
|
||||
|
@ -56,7 +41,7 @@ async def async_get_config_entry_diagnostics(
|
|||
return {
|
||||
"entry": {
|
||||
"title": entry.title,
|
||||
"data": _async_redact_data(entry.data),
|
||||
"data": async_redact_data(entry.data, TO_REDACT),
|
||||
},
|
||||
"stations": _async_redact_data(ambient.stations),
|
||||
"stations": async_redact_data(ambient.stations, TO_REDACT),
|
||||
}
|
||||
|
|
|
@ -22,8 +22,9 @@ from homeassistant.util.json import (
|
|||
)
|
||||
|
||||
from .const import DOMAIN, REDACTED, DiagnosticsSubType, DiagnosticsType
|
||||
from .util import async_redact_data
|
||||
|
||||
__all__ = ["REDACTED"]
|
||||
__all__ = ["REDACTED", "async_redact_data"]
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
"""Diagnostic utilities."""
|
||||
from __future__ import annotations
|
||||
|
||||
from collections.abc import Iterable, Mapping
|
||||
from typing import Any
|
||||
|
||||
from homeassistant.core import callback
|
||||
|
||||
from .const import REDACTED
|
||||
|
||||
|
||||
@callback
|
||||
def async_redact_data(data: Mapping, to_redact: Iterable[Any]) -> dict[str, Any]:
|
||||
"""Redact sensitive data in a dict."""
|
||||
if not isinstance(data, (Mapping, list)):
|
||||
return data
|
||||
|
||||
redacted = {**data}
|
||||
|
||||
for key, value in redacted.items():
|
||||
if key in to_redact:
|
||||
redacted[key] = REDACTED
|
||||
elif isinstance(value, dict):
|
||||
redacted[key] = async_redact_data(value, to_redact)
|
||||
elif isinstance(value, list):
|
||||
redacted[key] = [async_redact_data(item, to_redact) for item in value]
|
||||
|
||||
return redacted
|
|
@ -1,13 +1,15 @@
|
|||
"""Diagnostics support for Evil Genius Labs."""
|
||||
from __future__ import annotations
|
||||
|
||||
from homeassistant.components.diagnostics import REDACTED
|
||||
from homeassistant.components.diagnostics import async_redact_data
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.core import HomeAssistant
|
||||
|
||||
from . import EvilGeniusUpdateCoordinator
|
||||
from .const import DOMAIN
|
||||
|
||||
TO_REDACT = {"wiFiSsidDefault", "wiFiSSID"}
|
||||
|
||||
|
||||
async def async_get_config_entry_diagnostics(
|
||||
hass: HomeAssistant, config_entry: ConfigEntry
|
||||
|
@ -16,10 +18,6 @@ async def async_get_config_entry_diagnostics(
|
|||
coordinator: EvilGeniusUpdateCoordinator = hass.data[DOMAIN][config_entry.entry_id]
|
||||
|
||||
return {
|
||||
"info": {
|
||||
**coordinator.info,
|
||||
"wiFiSsidDefault": REDACTED,
|
||||
"wiFiSSID": REDACTED,
|
||||
},
|
||||
"info": async_redact_data(coordinator.info, TO_REDACT),
|
||||
"data": coordinator.data,
|
||||
}
|
||||
|
|
|
@ -1,13 +1,25 @@
|
|||
"""Diagnostics support for Netatmo."""
|
||||
from __future__ import annotations
|
||||
|
||||
from homeassistant.components.diagnostics import REDACTED
|
||||
from homeassistant.components.diagnostics import async_redact_data
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.core import HomeAssistant
|
||||
|
||||
from .const import DATA_HANDLER, DOMAIN
|
||||
from .data_handler import NetatmoDataHandler
|
||||
|
||||
TO_REDACT = {
|
||||
"access_token",
|
||||
"refresh_token",
|
||||
"restricted_access_token",
|
||||
"restricted_refresh_token",
|
||||
"webhook_id",
|
||||
"lat_ne",
|
||||
"lat_sw",
|
||||
"lon_ne",
|
||||
"lon_sw",
|
||||
}
|
||||
|
||||
|
||||
async def async_get_config_entry_diagnostics(
|
||||
hass: HomeAssistant, config_entry: ConfigEntry
|
||||
|
@ -17,28 +29,13 @@ async def async_get_config_entry_diagnostics(
|
|||
DATA_HANDLER
|
||||
]
|
||||
|
||||
diagnostics_data = {
|
||||
"info": {
|
||||
**config_entry.as_dict(),
|
||||
"webhook_registered": data_handler.webhook,
|
||||
},
|
||||
"data": data_handler.data,
|
||||
return {
|
||||
"info": async_redact_data(
|
||||
{
|
||||
**config_entry.as_dict(),
|
||||
"webhook_registered": data_handler.webhook,
|
||||
},
|
||||
TO_REDACT,
|
||||
),
|
||||
"data": async_redact_data(data_handler.data, TO_REDACT),
|
||||
}
|
||||
|
||||
if "token" in diagnostics_data["info"]["data"]:
|
||||
diagnostics_data["info"]["data"]["token"]["access_token"] = REDACTED
|
||||
diagnostics_data["info"]["data"]["token"]["refresh_token"] = REDACTED
|
||||
diagnostics_data["info"]["data"]["token"]["restricted_access_token"] = REDACTED
|
||||
diagnostics_data["info"]["data"]["token"]["restricted_refresh_token"] = REDACTED
|
||||
|
||||
if "webhook_id" in diagnostics_data["info"]["data"]:
|
||||
diagnostics_data["info"]["data"]["webhook_id"] = REDACTED
|
||||
|
||||
if "weather_areas" in diagnostics_data["info"].get("options", {}):
|
||||
for area in diagnostics_data["info"]["options"]["weather_areas"]:
|
||||
for attr in ("lat_ne", "lat_sw", "lon_ne", "lon_sw"):
|
||||
diagnostics_data["info"]["options"]["weather_areas"][area][
|
||||
attr
|
||||
] = REDACTED
|
||||
|
||||
return diagnostics_data
|
||||
|
|
|
@ -1,42 +1,25 @@
|
|||
"""Diagnostics support for Renault."""
|
||||
from __future__ import annotations
|
||||
|
||||
from types import MappingProxyType
|
||||
from typing import Any
|
||||
|
||||
from homeassistant.components.diagnostics import REDACTED
|
||||
from homeassistant.components.diagnostics import async_redact_data
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import CONF_PASSWORD, CONF_USERNAME
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.device_registry import DeviceEntry
|
||||
|
||||
from . import RenaultHub
|
||||
from .const import CONF_KAMEREON_ACCOUNT_ID, DOMAIN
|
||||
|
||||
TO_REDACT = (
|
||||
TO_REDACT = {
|
||||
CONF_KAMEREON_ACCOUNT_ID,
|
||||
CONF_PASSWORD,
|
||||
CONF_USERNAME,
|
||||
"radioCode",
|
||||
"registrationNumber",
|
||||
"vin",
|
||||
)
|
||||
|
||||
|
||||
@callback
|
||||
def _async_redact_data(data: MappingProxyType | dict) -> dict[str, Any]:
|
||||
"""Redact sensitive data in a dict."""
|
||||
redacted = {**data}
|
||||
|
||||
for key, value in redacted.items():
|
||||
if key in TO_REDACT:
|
||||
redacted[key] = REDACTED
|
||||
elif isinstance(value, dict):
|
||||
redacted[key] = _async_redact_data(value)
|
||||
elif isinstance(value, list):
|
||||
redacted[key] = [_async_redact_data(item) for item in value]
|
||||
|
||||
return redacted
|
||||
}
|
||||
|
||||
|
||||
async def async_get_config_entry_diagnostics(
|
||||
|
@ -48,10 +31,10 @@ async def async_get_config_entry_diagnostics(
|
|||
return {
|
||||
"entry": {
|
||||
"title": entry.title,
|
||||
"data": _async_redact_data(entry.data),
|
||||
"data": async_redact_data(entry.data, TO_REDACT),
|
||||
},
|
||||
"vehicles": [
|
||||
_async_redact_data(vehicle.details.raw_data)
|
||||
async_redact_data(vehicle.details.raw_data, TO_REDACT)
|
||||
for vehicle in renault_hub.vehicles.values()
|
||||
],
|
||||
}
|
||||
|
@ -65,5 +48,7 @@ async def async_get_device_diagnostics(
|
|||
vin = next(iter(device.identifiers))[1]
|
||||
|
||||
return {
|
||||
"details": _async_redact_data(renault_hub.vehicles[vin].details.raw_data),
|
||||
"details": async_redact_data(
|
||||
renault_hub.vehicles[vin].details.raw_data, TO_REDACT
|
||||
),
|
||||
}
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
"""Test AirVisual diagnostics."""
|
||||
from homeassistant.components.diagnostics import REDACTED
|
||||
|
||||
from tests.components.diagnostics import get_diagnostics_for_config_entry
|
||||
|
||||
|
||||
|
@ -8,18 +10,18 @@ async def test_entry_diagnostics(hass, config_entry, hass_client, setup_airvisua
|
|||
"entry": {
|
||||
"title": "Mock Title",
|
||||
"data": {
|
||||
"api_key": "**REDACTED**",
|
||||
"api_key": REDACTED,
|
||||
"integration_type": "Geographical Location by Latitude/Longitude",
|
||||
"latitude": "**REDACTED**",
|
||||
"longitude": "**REDACTED**",
|
||||
"latitude": REDACTED,
|
||||
"longitude": REDACTED,
|
||||
},
|
||||
"options": {
|
||||
"show_on_map": True,
|
||||
},
|
||||
},
|
||||
"data": {
|
||||
"city": "**REDACTED**",
|
||||
"country": "**REDACTED**",
|
||||
"city": REDACTED,
|
||||
"country": REDACTED,
|
||||
"current": {
|
||||
"weather": {
|
||||
"ts": "2021-09-03T21:00:00.000Z",
|
||||
|
@ -39,9 +41,9 @@ async def test_entry_diagnostics(hass, config_entry, hass_client, setup_airvisua
|
|||
},
|
||||
},
|
||||
"location": {
|
||||
"coordinates": "**REDACTED**",
|
||||
"coordinates": REDACTED,
|
||||
"type": "Point",
|
||||
},
|
||||
"state": "**REDACTED**",
|
||||
"state": REDACTED,
|
||||
},
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
"""Test Ambient PWS diagnostics."""
|
||||
from homeassistant.components.ambient_station import DOMAIN
|
||||
from homeassistant.components.diagnostics import REDACTED
|
||||
|
||||
from tests.components.diagnostics import get_diagnostics_for_config_entry
|
||||
|
||||
|
@ -12,14 +13,14 @@ async def test_entry_diagnostics(
|
|||
ambient.stations = station_data
|
||||
assert await get_diagnostics_for_config_entry(hass, hass_client, config_entry) == {
|
||||
"entry": {
|
||||
"data": {"api_key": "**REDACTED**", "app_key": "**REDACTED**"},
|
||||
"data": {"api_key": REDACTED, "app_key": REDACTED},
|
||||
"title": "Mock Title",
|
||||
},
|
||||
"stations": {
|
||||
"devices": [
|
||||
{
|
||||
"apiKey": "**REDACTED**",
|
||||
"info": {"location": "**REDACTED**", "name": "Side Yard"},
|
||||
"apiKey": REDACTED,
|
||||
"info": {"location": REDACTED, "name": "Side Yard"},
|
||||
"lastData": {
|
||||
"baromabsin": 25.016,
|
||||
"baromrelin": 29.953,
|
||||
|
@ -27,7 +28,7 @@ async def test_entry_diagnostics(
|
|||
"dailyrainin": 0,
|
||||
"date": "2022-01-19T22:38:00.000Z",
|
||||
"dateutc": 1642631880000,
|
||||
"deviceId": "**REDACTED**",
|
||||
"deviceId": REDACTED,
|
||||
"dewPoint": 17.75,
|
||||
"dewPointin": 37,
|
||||
"eventrainin": 0,
|
||||
|
@ -43,14 +44,14 @@ async def test_entry_diagnostics(
|
|||
"tempf": 21,
|
||||
"tempinf": 70.9,
|
||||
"totalrainin": 35.398,
|
||||
"tz": "**REDACTED**",
|
||||
"tz": REDACTED,
|
||||
"uv": 0,
|
||||
"weeklyrainin": 0,
|
||||
"winddir": 25,
|
||||
"windgustmph": 1.1,
|
||||
"windspeedmph": 0.2,
|
||||
},
|
||||
"macAddress": "**REDACTED**",
|
||||
"macAddress": REDACTED,
|
||||
}
|
||||
],
|
||||
"method": "subscribe",
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
"""Test the Netatmo diagnostics."""
|
||||
from unittest.mock import AsyncMock, patch
|
||||
|
||||
from homeassistant.components.diagnostics import REDACTED
|
||||
from homeassistant.setup import async_setup_component
|
||||
|
||||
from .common import fake_post_request
|
||||
|
@ -34,11 +35,9 @@ async def test_entry_diagnostics(hass, hass_client, config_entry):
|
|||
"data": {
|
||||
"auth_implementation": "cloud",
|
||||
"token": {
|
||||
"access_token": "**REDACTED**",
|
||||
"restricted_access_token": "**REDACTED**",
|
||||
"access_token": REDACTED,
|
||||
"expires_in": 60,
|
||||
"refresh_token": "**REDACTED**",
|
||||
"restricted_refresh_token": "**REDACTED**",
|
||||
"refresh_token": REDACTED,
|
||||
"scope": [
|
||||
"read_station",
|
||||
"read_camera",
|
||||
|
@ -54,7 +53,7 @@ async def test_entry_diagnostics(hass, hass_client, config_entry):
|
|||
],
|
||||
"type": "Bearer",
|
||||
},
|
||||
"webhook_id": "**REDACTED**",
|
||||
"webhook_id": REDACTED,
|
||||
},
|
||||
"disabled_by": None,
|
||||
"domain": "netatmo",
|
||||
|
@ -62,19 +61,19 @@ async def test_entry_diagnostics(hass, hass_client, config_entry):
|
|||
"weather_areas": {
|
||||
"Home avg": {
|
||||
"area_name": "Home avg",
|
||||
"lat_ne": "**REDACTED**",
|
||||
"lat_sw": "**REDACTED**",
|
||||
"lon_ne": "**REDACTED**",
|
||||
"lon_sw": "**REDACTED**",
|
||||
"lat_ne": REDACTED,
|
||||
"lat_sw": REDACTED,
|
||||
"lon_ne": REDACTED,
|
||||
"lon_sw": REDACTED,
|
||||
"mode": "avg",
|
||||
"show_on_map": False,
|
||||
},
|
||||
"Home max": {
|
||||
"area_name": "Home max",
|
||||
"lat_ne": "**REDACTED**",
|
||||
"lat_sw": "**REDACTED**",
|
||||
"lon_ne": "**REDACTED**",
|
||||
"lon_sw": "**REDACTED**",
|
||||
"lat_ne": REDACTED,
|
||||
"lat_sw": REDACTED,
|
||||
"lon_ne": REDACTED,
|
||||
"lon_sw": REDACTED,
|
||||
"mode": "max",
|
||||
"show_on_map": True,
|
||||
},
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
"""Test Renault diagnostics."""
|
||||
import pytest
|
||||
|
||||
from homeassistant.components.diagnostics import REDACTED
|
||||
from homeassistant.components.renault import DOMAIN
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.core import HomeAssistant
|
||||
|
@ -14,7 +15,7 @@ from tests.components.diagnostics import (
|
|||
pytestmark = pytest.mark.usefixtures("patch_renault_account", "patch_get_vehicles")
|
||||
|
||||
VEHICLE_DETAILS = {
|
||||
"vin": "**REDACTED**",
|
||||
"vin": REDACTED,
|
||||
"registrationDate": "2017-08-01",
|
||||
"firstRegistrationDate": "2017-08-01",
|
||||
"engineType": "5AQ",
|
||||
|
@ -52,7 +53,7 @@ VEHICLE_DETAILS = {
|
|||
},
|
||||
"version": {"code": "INT MB 10R"},
|
||||
"energy": {"code": "ELEC", "label": "ELECTRIQUE", "group": "019"},
|
||||
"registrationNumber": "**REDACTED**",
|
||||
"registrationNumber": REDACTED,
|
||||
"vcd": "SYTINC/SKTPOU/SAND41/FDIU1/SSESM/MAPSUP/SSCALL/SAND88/SAND90/SQKDRO/SDIFPA/FACBA2/PRLEX1/SSRCAR/CABDO2/TCU0G2/SWALBO/EVTEC1/STANDA/X10/B10/EA2/MB/ELEC/DG/TEMP/TR4X2/RV/ABS/CAREG/LAC/VT003/CPE/RET03/SPROJA/RALU16/CEAVRH/AIRBA1/SERIE/DRA/DRAP08/HARM02/ATAR/TERQG/SFBANA/KM/DPRPN/AVREPL/SSDECA/ASRESP/RDAR02/ALEVA/CACBL2/SOP02C/CTHAB2/TRNOR/LVAVIP/LVAREL/SASURV/KTGREP/SGSCHA/APL03/ALOUCC/CMAR3P/NAV3G5/RAD37A/BVEL/AUTAUG/RNORM/ISOFIX/EQPEUR/HRGM01/SDPCLV/TLFRAN/SPRODI/SAN613/SSAPEX/GENEV1/ELC1/SANCML/PE2012/PHAS1/SAN913/045KWH/BT4AR1/VEC153/X101VE/NBT017/5AQ",
|
||||
"assets": [
|
||||
{
|
||||
|
@ -130,7 +131,7 @@ VEHICLE_DETAILS = {
|
|||
"deliveryDate": "2017-08-11",
|
||||
"retrievedFromDhs": False,
|
||||
"engineEnergyType": "ELEC",
|
||||
"radioCode": "**REDACTED**",
|
||||
"radioCode": REDACTED,
|
||||
}
|
||||
|
||||
|
||||
|
@ -146,10 +147,10 @@ async def test_entry_diagnostics(
|
|||
assert await get_diagnostics_for_config_entry(hass, hass_client, config_entry) == {
|
||||
"entry": {
|
||||
"data": {
|
||||
"kamereon_account_id": "**REDACTED**",
|
||||
"kamereon_account_id": REDACTED,
|
||||
"locale": "fr_FR",
|
||||
"password": "**REDACTED**",
|
||||
"username": "**REDACTED**",
|
||||
"password": REDACTED,
|
||||
"username": REDACTED,
|
||||
},
|
||||
"title": "Mock Title",
|
||||
},
|
||||
|
|
Loading…
Reference in New Issue