Skip to content

Commit 4e12628

Browse files
johanzanderepenet
authored andcommitted
Fix Growatt integration authentication error for legacy config entries (home-assistant#155993)
Co-authored-by: epenet <[email protected]>
1 parent e6d8d4d commit 4e12628

File tree

2 files changed

+98
-1
lines changed

2 files changed

+98
-1
lines changed

homeassistant/components/growatt_server/__init__.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,21 @@ async def async_setup_entry(
136136
new_data[CONF_URL] = url
137137
hass.config_entries.async_update_entry(config_entry, data=new_data)
138138

139+
# Migrate legacy config entries without auth_type field
140+
if CONF_AUTH_TYPE not in config:
141+
new_data = dict(config_entry.data)
142+
# Detect auth type based on which fields are present
143+
if CONF_TOKEN in config:
144+
new_data[CONF_AUTH_TYPE] = AUTH_API_TOKEN
145+
elif CONF_USERNAME in config:
146+
new_data[CONF_AUTH_TYPE] = AUTH_PASSWORD
147+
else:
148+
raise ConfigEntryError(
149+
"Unable to determine authentication type from config entry."
150+
)
151+
hass.config_entries.async_update_entry(config_entry, data=new_data)
152+
config = config_entry.data
153+
139154
# Determine API version
140155
if config.get(CONF_AUTH_TYPE) == AUTH_API_TOKEN:
141156
api_version = "v1"

tests/components/growatt_server/test_init.py

Lines changed: 83 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,14 @@
99
import pytest
1010
from syrupy.assertion import SnapshotAssertion
1111

12-
from homeassistant.components.growatt_server.const import DOMAIN
12+
from homeassistant.components.growatt_server.const import (
13+
AUTH_API_TOKEN,
14+
AUTH_PASSWORD,
15+
CONF_AUTH_TYPE,
16+
DOMAIN,
17+
)
1318
from homeassistant.config_entries import ConfigEntryState
19+
from homeassistant.const import CONF_PASSWORD, CONF_TOKEN, CONF_URL, CONF_USERNAME
1420
from homeassistant.core import HomeAssistant
1521
from homeassistant.helpers import device_registry as dr
1622

@@ -174,3 +180,79 @@ async def test_multiple_devices_discovered(
174180
assert device1 == snapshot(name="device_min123456")
175181
assert device2 is not None
176182
assert device2 == snapshot(name="device_min789012")
183+
184+
185+
async def test_migrate_legacy_api_token_config(
186+
hass: HomeAssistant,
187+
mock_growatt_v1_api,
188+
) -> None:
189+
"""Test migration of legacy config entry with API token but no auth_type."""
190+
# Create a legacy config entry without CONF_AUTH_TYPE
191+
legacy_config = {
192+
CONF_TOKEN: "test_token_123",
193+
CONF_URL: "https://openapi.growatt.com/",
194+
"plant_id": "plant_123",
195+
}
196+
mock_config_entry = MockConfigEntry(
197+
domain=DOMAIN,
198+
data=legacy_config,
199+
unique_id="plant_123",
200+
)
201+
202+
await setup_integration(hass, mock_config_entry)
203+
204+
# Verify migration occurred and auth_type was added
205+
assert mock_config_entry.data[CONF_AUTH_TYPE] == AUTH_API_TOKEN
206+
assert mock_config_entry.state is ConfigEntryState.LOADED
207+
208+
209+
async def test_migrate_legacy_password_config(
210+
hass: HomeAssistant,
211+
mock_growatt_classic_api,
212+
) -> None:
213+
"""Test migration of legacy config entry with password auth but no auth_type."""
214+
# Create a legacy config entry without CONF_AUTH_TYPE
215+
legacy_config = {
216+
CONF_USERNAME: "test_user",
217+
CONF_PASSWORD: "test_password",
218+
CONF_URL: "https://server.growatt.com/",
219+
"plant_id": "plant_456",
220+
}
221+
mock_config_entry = MockConfigEntry(
222+
domain=DOMAIN,
223+
data=legacy_config,
224+
unique_id="plant_456",
225+
)
226+
227+
# Classic API doesn't support MIN devices - use TLX device instead
228+
mock_growatt_classic_api.device_list.return_value = [
229+
{"deviceSn": "TLX123456", "deviceType": "tlx"}
230+
]
231+
232+
await setup_integration(hass, mock_config_entry)
233+
234+
# Verify migration occurred and auth_type was added
235+
assert mock_config_entry.data[CONF_AUTH_TYPE] == AUTH_PASSWORD
236+
assert mock_config_entry.state is ConfigEntryState.LOADED
237+
238+
239+
async def test_migrate_legacy_config_no_auth_fields(
240+
hass: HomeAssistant,
241+
) -> None:
242+
"""Test that config entry with no recognizable auth fields raises error."""
243+
# Create a config entry without any auth fields
244+
invalid_config = {
245+
CONF_URL: "https://openapi.growatt.com/",
246+
"plant_id": "plant_789",
247+
}
248+
mock_config_entry = MockConfigEntry(
249+
domain=DOMAIN,
250+
data=invalid_config,
251+
unique_id="plant_789",
252+
)
253+
254+
await setup_integration(hass, mock_config_entry)
255+
256+
# The ConfigEntryError is caught by the config entry system
257+
# and the entry state is set to SETUP_ERROR
258+
assert mock_config_entry.state is ConfigEntryState.SETUP_ERROR

0 commit comments

Comments
 (0)