mirror of
https://github.com/python-kasa/python-kasa.git
synced 2025-08-06 10:44:04 +00:00
Allow serializing and passing of credentials_hashes in DeviceConfig (#607)
* Allow passing of credentials_hashes in DeviceConfig * Update following review
This commit is contained in:
@@ -430,6 +430,7 @@ def discovery_mock(all_fixture_data, mocker):
|
||||
query_data: dict
|
||||
device_type: str
|
||||
encrypt_type: str
|
||||
login_version: Optional[int] = None
|
||||
port_override: Optional[int] = None
|
||||
|
||||
if "discovery_result" in all_fixture_data:
|
||||
@@ -438,6 +439,9 @@ def discovery_mock(all_fixture_data, mocker):
|
||||
encrypt_type = all_fixture_data["discovery_result"]["mgt_encrypt_schm"][
|
||||
"encrypt_type"
|
||||
]
|
||||
login_version = all_fixture_data["discovery_result"]["mgt_encrypt_schm"].get(
|
||||
"lv"
|
||||
)
|
||||
datagram = (
|
||||
b"\x02\x00\x00\x01\x01[\x00\x00\x00\x00\x00\x00W\xcev\xf8"
|
||||
+ json_dumps(discovery_data).encode()
|
||||
@@ -450,12 +454,14 @@ def discovery_mock(all_fixture_data, mocker):
|
||||
all_fixture_data,
|
||||
device_type,
|
||||
encrypt_type,
|
||||
login_version,
|
||||
)
|
||||
else:
|
||||
sys_info = all_fixture_data["system"]["get_sysinfo"]
|
||||
discovery_data = {"system": {"get_sysinfo": sys_info}}
|
||||
device_type = sys_info.get("mic_type") or sys_info.get("type")
|
||||
encrypt_type = "XOR"
|
||||
login_version = None
|
||||
datagram = TPLinkSmartHomeProtocol.encrypt(json_dumps(discovery_data))[4:]
|
||||
dm = _DiscoveryMock(
|
||||
"127.0.0.123",
|
||||
@@ -465,6 +471,7 @@ def discovery_mock(all_fixture_data, mocker):
|
||||
all_fixture_data,
|
||||
device_type,
|
||||
encrypt_type,
|
||||
login_version,
|
||||
)
|
||||
|
||||
def mock_discover(self):
|
||||
|
@@ -1,3 +1,4 @@
|
||||
import base64
|
||||
import copy
|
||||
import logging
|
||||
import re
|
||||
@@ -320,6 +321,11 @@ class FakeSmartTransport(BaseTransport):
|
||||
"""Default port for the transport."""
|
||||
return 80
|
||||
|
||||
@property
|
||||
def credentials_hash(self):
|
||||
"""The hashed credentials used by the transport."""
|
||||
return self._credentials.username + self._credentials.password + "hash"
|
||||
|
||||
async def send(self, request: str):
|
||||
request_dict = json_loads(request)
|
||||
method = request_dict["method"]
|
||||
|
@@ -19,3 +19,30 @@ def test_serialization():
|
||||
config2_dict = json_loads(config_json)
|
||||
config2 = DeviceConfig.from_dict(config2_dict)
|
||||
assert config == config2
|
||||
|
||||
|
||||
def test_credentials_hash():
|
||||
config = DeviceConfig(
|
||||
host="Foo",
|
||||
http_client=httpx.AsyncClient(),
|
||||
credentials=Credentials("foo", "bar"),
|
||||
)
|
||||
config_dict = config.to_dict(credentials_hash="credhash")
|
||||
config_json = json_dumps(config_dict)
|
||||
config2_dict = json_loads(config_json)
|
||||
config2 = DeviceConfig.from_dict(config2_dict)
|
||||
assert config2.credentials_hash == "credhash"
|
||||
assert config2.credentials is None
|
||||
|
||||
|
||||
def test_no_credentials_serialization():
|
||||
config = DeviceConfig(
|
||||
host="Foo",
|
||||
http_client=httpx.AsyncClient(),
|
||||
credentials=Credentials("foo", "bar"),
|
||||
)
|
||||
config_dict = config.to_dict(exclude_credentials=True)
|
||||
config_json = json_dumps(config_dict)
|
||||
config2_dict = json_loads(config_json)
|
||||
config2 = DeviceConfig.from_dict(config2_dict)
|
||||
assert config2.credentials is None
|
||||
|
@@ -110,11 +110,17 @@ async def test_discover_single(discovery_mock, custom_port, mocker):
|
||||
assert update_mock.call_count == 0
|
||||
|
||||
ct = ConnectionType.from_values(
|
||||
discovery_mock.device_type, discovery_mock.encrypt_type
|
||||
discovery_mock.device_type,
|
||||
discovery_mock.encrypt_type,
|
||||
discovery_mock.login_version,
|
||||
)
|
||||
uses_http = discovery_mock.default_port == 80
|
||||
config = DeviceConfig(
|
||||
host=host, port_override=custom_port, connection_type=ct, uses_http=uses_http
|
||||
host=host,
|
||||
port_override=custom_port,
|
||||
connection_type=ct,
|
||||
uses_http=uses_http,
|
||||
credentials=Credentials(),
|
||||
)
|
||||
assert x.config == config
|
||||
|
||||
|
@@ -9,8 +9,11 @@ import sys
|
||||
|
||||
import pytest
|
||||
|
||||
from ..aestransport import AesTransport
|
||||
from ..credentials import Credentials
|
||||
from ..deviceconfig import DeviceConfig
|
||||
from ..exceptions import SmartDeviceException
|
||||
from ..klaptransport import KlapTransport, KlapTransportV2
|
||||
from ..protocol import (
|
||||
BaseTransport,
|
||||
TPLinkProtocol,
|
||||
@@ -298,3 +301,19 @@ def test_transport_init_signature(class_name_obj):
|
||||
assert (
|
||||
params[1].name == "config" and params[1].kind == inspect.Parameter.KEYWORD_ONLY
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"transport_class", [AesTransport, KlapTransport, KlapTransportV2, _XorTransport]
|
||||
)
|
||||
async def test_transport_credentials_hash(mocker, transport_class):
|
||||
host = "127.0.0.1"
|
||||
|
||||
credentials = Credentials("Foo", "Bar")
|
||||
config = DeviceConfig(host, credentials=credentials)
|
||||
transport = transport_class(config=config)
|
||||
credentials_hash = transport.credentials_hash
|
||||
config = DeviceConfig(host, credentials_hash=credentials_hash)
|
||||
transport = transport_class(config=config)
|
||||
|
||||
assert transport.credentials_hash == credentials_hash
|
||||
|
Reference in New Issue
Block a user