Fix host IP and scheme entry issues in TP-Link Omada (#89130)

Fixing host IP and scheme entry issues
This commit is contained in:
MarkGodwin 2023-03-06 04:47:45 +00:00 committed by Franck Nijhof
parent 8252aeead2
commit c9999cd08c
No known key found for this signature in database
GPG Key ID: D62583BA8AB11CA3
2 changed files with 87 additions and 8 deletions

View File

@ -3,9 +3,12 @@ from __future__ import annotations
from collections.abc import Mapping from collections.abc import Mapping
import logging import logging
import re
from types import MappingProxyType from types import MappingProxyType
from typing import Any, NamedTuple from typing import Any, NamedTuple
from urllib.parse import urlsplit
from aiohttp import CookieJar
from tplink_omada_client.exceptions import ( from tplink_omada_client.exceptions import (
ConnectionFailed, ConnectionFailed,
LoginFailed, LoginFailed,
@ -20,7 +23,10 @@ from homeassistant.const import CONF_HOST, CONF_PASSWORD, CONF_USERNAME, CONF_VE
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.data_entry_flow import FlowResult from homeassistant.data_entry_flow import FlowResult
from homeassistant.helpers import selector from homeassistant.helpers import selector
from homeassistant.helpers.aiohttp_client import async_get_clientsession from homeassistant.helpers.aiohttp_client import (
async_create_clientsession,
async_get_clientsession,
)
from .const import DOMAIN from .const import DOMAIN
@ -42,11 +48,26 @@ async def create_omada_client(
hass: HomeAssistant, data: MappingProxyType[str, Any] hass: HomeAssistant, data: MappingProxyType[str, Any]
) -> OmadaClient: ) -> OmadaClient:
"""Create a TP-Link Omada client API for the given config entry.""" """Create a TP-Link Omada client API for the given config entry."""
host = data[CONF_HOST]
host: str = data[CONF_HOST]
verify_ssl = bool(data[CONF_VERIFY_SSL]) verify_ssl = bool(data[CONF_VERIFY_SSL])
if not host.lower().startswith(("http://", "https://")):
host = "https://" + host
host_parts = urlsplit(host)
if (
host_parts.hostname
and re.fullmatch(r"\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}", host_parts.hostname)
is not None
):
# TP-Link API uses cookies for login session, so an unsafe cookie jar is required for IP addresses
websession = async_create_clientsession(hass, cookie_jar=CookieJar(unsafe=True))
else:
websession = async_get_clientsession(hass, verify_ssl=verify_ssl)
username = data[CONF_USERNAME] username = data[CONF_USERNAME]
password = data[CONF_PASSWORD] password = data[CONF_PASSWORD]
websession = async_get_clientsession(hass, verify_ssl=verify_ssl)
return OmadaClient(host, username, password, websession=websession) return OmadaClient(host, username, password, websession=websession)

View File

@ -22,14 +22,14 @@ from homeassistant.data_entry_flow import FlowResultType
from tests.common import MockConfigEntry from tests.common import MockConfigEntry
MOCK_USER_DATA = { MOCK_USER_DATA = {
"host": "1.1.1.1", "host": "https://fake.omada.host",
"verify_ssl": True, "verify_ssl": True,
"username": "test-username", "username": "test-username",
"password": "test-password", "password": "test-password",
} }
MOCK_ENTRY_DATA = { MOCK_ENTRY_DATA = {
"host": "1.1.1.1", "host": "https://fake.omada.host",
"verify_ssl": True, "verify_ssl": True,
"site": "SiteId", "site": "SiteId",
"username": "test-username", "username": "test-username",
@ -111,7 +111,7 @@ async def test_form_multiple_sites(hass: HomeAssistant) -> None:
assert result3["type"] == FlowResultType.CREATE_ENTRY assert result3["type"] == FlowResultType.CREATE_ENTRY
assert result3["title"] == "OC200 (Site 2)" assert result3["title"] == "OC200 (Site 2)"
assert result3["data"] == { assert result3["data"] == {
"host": "1.1.1.1", "host": "https://fake.omada.host",
"verify_ssl": True, "verify_ssl": True,
"site": "second", "site": "second",
"username": "test-username", "username": "test-username",
@ -272,7 +272,7 @@ async def test_async_step_reauth_success(hass: HomeAssistant) -> None:
mocked_validate.assert_called_once_with( mocked_validate.assert_called_once_with(
hass, hass,
{ {
"host": "1.1.1.1", "host": "https://fake.omada.host",
"verify_ssl": True, "verify_ssl": True,
"site": "SiteId", "site": "SiteId",
"username": "new_uname", "username": "new_uname",
@ -353,6 +353,64 @@ async def test_create_omada_client_parses_args(hass: HomeAssistant) -> None:
assert result is not None assert result is not None
mock_client.assert_called_once_with( mock_client.assert_called_once_with(
"1.1.1.1", "test-username", "test-password", "ws" "https://fake.omada.host", "test-username", "test-password", "ws"
) )
mock_clientsession.assert_called_once_with(hass, verify_ssl=True) mock_clientsession.assert_called_once_with(hass, verify_ssl=True)
async def test_create_omada_client_adds_missing_scheme(hass: HomeAssistant) -> None:
"""Test config arguments are passed to Omada client."""
with patch(
"homeassistant.components.tplink_omada.config_flow.OmadaClient", autospec=True
) as mock_client, patch(
"homeassistant.components.tplink_omada.config_flow.async_get_clientsession",
return_value="ws",
) as mock_clientsession:
result = await create_omada_client(
hass,
{
"host": "fake.omada.host",
"verify_ssl": True,
"username": "test-username",
"password": "test-password",
},
)
assert result is not None
mock_client.assert_called_once_with(
"https://fake.omada.host", "test-username", "test-password", "ws"
)
mock_clientsession.assert_called_once_with(hass, verify_ssl=True)
async def test_create_omada_client_with_ip_creates_clientsession(
hass: HomeAssistant,
) -> None:
"""Test config arguments are passed to Omada client."""
with patch(
"homeassistant.components.tplink_omada.config_flow.OmadaClient", autospec=True
) as mock_client, patch(
"homeassistant.components.tplink_omada.config_flow.CookieJar", autospec=True
) as mock_jar, patch(
"homeassistant.components.tplink_omada.config_flow.async_create_clientsession",
return_value="ws",
) as mock_create_clientsession:
result = await create_omada_client(
hass,
{
"host": "10.10.10.10",
"verify_ssl": True, # Verify is meaningless for IP
"username": "test-username",
"password": "test-password",
},
)
assert result is not None
mock_client.assert_called_once_with(
"https://10.10.10.10", "test-username", "test-password", "ws"
)
mock_create_clientsession.assert_called_once_with(
hass, cookie_jar=mock_jar.return_value
)