Skip to content

Commit

Permalink
Рефакторинг авторизации, базовая поддержка мультиаккаунта (#29)
Browse files Browse the repository at this point in the history
  • Loading branch information
dext0r committed Apr 23, 2024
1 parent 4475aef commit 347d89e
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 31 deletions.
4 changes: 2 additions & 2 deletions custom_components/yandex_station_intents/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -165,8 +165,8 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
try:
if not await session.refresh_cookies():
hass.components.persistent_notification.async_create(
"Необходимо заново авторизоваться в Яндексе. Для этого удалите интеграцию и [добавьте "
"снова](/config/integrations).",
"Необходимо заново авторизоваться в Яндексе. Для этого "
"[добавьте новую интеграцию](/config/integrations) с тем же логином.",
title=NOTIFICATION_TITLE,
)
return False
Expand Down
50 changes: 23 additions & 27 deletions custom_components/yandex_station_intents/config_flow.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from enum import StrEnum
from functools import lru_cache
import json
import logging
Expand All @@ -8,14 +9,16 @@
import voluptuous as vol

from . import DOMAIN
from .const import CONF_X_TOKEN
from .const import CONF_X_TOKEN, YANDEX_STATION_DOMAIN
from .yandex_session import AuthException, LoginResponse, YandexSession

_LOGGER = logging.getLogger(__name__)

METHOD_COOKIES = "cookies"
METHOD_TOKEN = "token"
METHOD_YANDEX_STATION = "yandex_station"

class AuthMethod(StrEnum):
COOKIES = "cookies"
TOKEN = "token"
YANDEX_STATION = "yandex_station"


class YandexSmartHomeIntentsFlowHandler(ConfigFlow, domain=DOMAIN):
Expand All @@ -25,26 +28,23 @@ def _session(self) -> YandexSession:
return YandexSession(self.hass)

async def async_step_user(self, user_input: ConfigType | None = None) -> FlowResult: # type: ignore
if self._async_current_entries():
return self.async_abort(reason="single_instance_allowed")

if user_input is None:
return self.async_show_form(
step_id="user",
data_schema=vol.Schema(
{
vol.Required("method", default=METHOD_YANDEX_STATION): vol.In(
vol.Required("method", default=AuthMethod.YANDEX_STATION): vol.In(
{
METHOD_YANDEX_STATION: "Через компонент Yandex.Station",
METHOD_COOKIES: "Cookies",
METHOD_TOKEN: "Токен",
AuthMethod.YANDEX_STATION: "Через компонент Yandex.Station",
AuthMethod.COOKIES: "Cookies",
AuthMethod.TOKEN: "Токен",
}
)
}
),
)

if user_input["method"] == METHOD_YANDEX_STATION:
if user_input["method"] == AuthMethod.YANDEX_STATION:
return await self.async_step_yandex_station()

return await self._show_form(user_input["method"])
Expand All @@ -57,7 +57,7 @@ async def async_step_yandex_station(self, user_input: ConfigType | None = None)
if user_input:
for entry in entries:
if entry.entry_id == user_input["account"]:
return await self.async_step_token({METHOD_TOKEN: entry.data[CONF_X_TOKEN]})
return await self.async_step_token({AuthMethod.TOKEN: entry.data[CONF_X_TOKEN]})

accounts = {entry.entry_id: entry.title for entry in entries}

Expand All @@ -72,34 +72,30 @@ async def async_step_yandex_station(self, user_input: ConfigType | None = None)

async def async_step_cookies(self, user_input: ConfigType) -> FlowResult:
try:
cookies = {p["name"]: p["value"] for p in json.loads(user_input[METHOD_COOKIES])}
cookies = {p["name"]: p["value"] for p in json.loads(user_input[AuthMethod.COOKIES])}
except (TypeError, KeyError, json.decoder.JSONDecodeError):
return await self._show_form(METHOD_COOKIES, errors={"base": "cookies.invalid_format"})
return await self._show_form(AuthMethod.COOKIES, errors={"base": "cookies.invalid_format"})

try:
response = await self._session.login_cookies(cookies)
except AuthException as e:
_LOGGER.error(f"Ошибка авторизации: {e}")
return await self._show_form(METHOD_COOKIES, errors={"base": "auth.error"})
return await self._show_form(AuthMethod.COOKIES, errors={"base": "auth.error"})

return await self._check_yandex_response(response, METHOD_COOKIES)
return await self._check_yandex_response(response, AuthMethod.COOKIES)

async def async_step_token(self, user_input: ConfigType) -> FlowResult:
response = await self._session.validate_token(user_input[METHOD_TOKEN])
return await self._check_yandex_response(response, METHOD_TOKEN)
response = await self._session.validate_token(user_input[AuthMethod.TOKEN])
return await self._check_yandex_response(response, AuthMethod.TOKEN)

async def _show_form(self, method: str, errors: dict[str, str] | None = None) -> FlowResult:
async def _show_form(self, method: AuthMethod, errors: dict[str, str] | None = None) -> FlowResult:
return self.async_show_form(
step_id=method,
step_id=str(method),
errors=errors,
data_schema=vol.Schema(
{
vol.Required(method): str,
}
),
data_schema=vol.Schema({vol.Required(str(method)): str}),
)

async def _check_yandex_response(self, response: LoginResponse, method: str) -> FlowResult:
async def _check_yandex_response(self, response: LoginResponse, method: AuthMethod) -> FlowResult:
if response.ok:
await self.async_set_unique_id(response.display_login)
return self.async_create_entry(title=response.display_login, data={CONF_X_TOKEN: response.x_token})
Expand Down
2 changes: 0 additions & 2 deletions custom_components/yandex_station_intents/translations/en.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
{
"config": {
"abort": {
"account_updated": "Данные обновлены, перезапустите Home Assistant",
"single_instance_allowed": "Разрешена только одна настройка Yandex.Station Intents",
"install_yandex_station": "Чтобы воспользоваться этим способом авторизации установите и настройте интеграцию [Yandex.Station](https://github.com/AlexxIT/YandexStation)"
},
"error": {
Expand Down

0 comments on commit 347d89e

Please sign in to comment.