Skip to content

Commit

Permalink
Add support for reauth flow
Browse files Browse the repository at this point in the history
  • Loading branch information
functionpointer committed Aug 2, 2024
1 parent 0516456 commit 4da844b
Show file tree
Hide file tree
Showing 6 changed files with 118 additions and 45 deletions.
85 changes: 41 additions & 44 deletions custom_components/opensprinkler/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from aiohttp.client_exceptions import InvalidURL
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import (
CONF_NAME,
CONF_PASSWORD,
CONF_SCAN_INTERVAL,
CONF_URL,
Expand All @@ -32,6 +33,7 @@
from .const import (
CONF_INDEX,
CONF_RUN_SECONDS,
DEFAULT_NAME,
DEFAULT_SCAN_INTERVAL,
DOMAIN,
SCHEMA_SERVICE_PAUSE_STATIONS,
Expand Down Expand Up @@ -69,53 +71,48 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry):
url = entry.data.get(CONF_URL)
password = entry.data.get(CONF_PASSWORD)
verify_ssl = entry.data.get(CONF_VERIFY_SSL)
try:
opts = {"session": async_get_clientsession(hass), "verify_ssl": verify_ssl}
controller = OpenSprinkler(url, password, opts)
controller.refresh_on_update = False

async def async_update_data():
"""Fetch data from OpenSprinkler."""
_LOGGER.debug("refreshing data")
async with async_timeout.timeout(TIMEOUT):
try:
await controller.refresh()
except OpenSprinklerAuthError as e:
# wrong password, tell user to re-enter the password
raise ConfigEntryAuthFailed from e
except (
InvalidURL,
OpenSprinklerConnectionError,
) as e:
raise UpdateFailed from e

if not controller._state:
raise UpdateFailed("Error fetching OpenSprinkler state")

return controller._state

scan_interval = entry.options.get(CONF_SCAN_INTERVAL, DEFAULT_SCAN_INTERVAL)
coordinator = DataUpdateCoordinator(
hass,
_LOGGER,
name="OpenSprinkler resource status",
update_method=async_update_data,
update_interval=timedelta(seconds=scan_interval),
)
opts = {"session": async_get_clientsession(hass), "verify_ssl": verify_ssl}

# initial load before loading platforms
await coordinator.async_refresh()
if not coordinator.last_update_success:
raise ConfigEntryNotReady
controller = OpenSprinkler(url, password, opts)
controller.refresh_on_update = False

hass.data[DOMAIN][entry.entry_id] = {
"coordinator": coordinator,
"controller": controller,
}
async def async_update_data():
"""Fetch data from OpenSprinkler."""
_LOGGER.debug("refreshing data")
async with async_timeout.timeout(TIMEOUT):
try:
await controller.refresh()
except OpenSprinklerAuthError as e:
# wrong password, tell user to re-enter the password
_LOGGER.debug(f"auth failure: {e}")
raise ConfigEntryAuthFailed from e
except (
InvalidURL,
OpenSprinklerConnectionError,
) as e:
raise UpdateFailed from e

if not controller._state:
raise UpdateFailed("Error fetching OpenSprinkler state")

return controller._state

scan_interval = entry.options.get(CONF_SCAN_INTERVAL, DEFAULT_SCAN_INTERVAL)
coordinator = DataUpdateCoordinator(
hass,
_LOGGER,
name=f"{entry.data.get(CONF_NAME, DEFAULT_NAME)} resource status",
update_method=async_update_data,
update_interval=timedelta(seconds=scan_interval),
)

# initial load before loading platforms
await coordinator.async_config_entry_first_refresh()

except (OpenSprinklerAuthError, OpenSprinklerConnectionError) as exc:
_LOGGER.error("Unable to connect to OpenSprinkler controller: %s", str(exc))
raise ConfigEntryNotReady
hass.data[DOMAIN][entry.entry_id] = {
"coordinator": coordinator,
"controller": controller,
}

await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)

Expand Down
48 changes: 48 additions & 0 deletions custom_components/opensprinkler/config_flow.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"""Config flow for OpenSprinkler integration."""

import logging
from typing import Any

import voluptuous as vol
from aiohttp.client_exceptions import InvalidURL
Expand All @@ -12,6 +13,7 @@
CONF_URL,
CONF_VERIFY_SSL,
)
from homeassistant.data_entry_flow import FlowResult
from homeassistant.helpers.aiohttp_client import async_get_clientsession
from homeassistant.util import slugify
from pyopensprinkler import Controller as OpenSprinkler
Expand All @@ -30,6 +32,11 @@
vol.Optional(CONF_NAME, default=DEFAULT_NAME): str,
}
)
REAUTH_SCHEMA = vol.Schema(
{
vol.Required(CONF_PASSWORD): str,
}
)


class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
Expand Down Expand Up @@ -93,6 +100,47 @@ async def async_step_import(self, user_input):
"""Handle import."""
return await self.async_step_user(user_input)

async def async_step_reauth(self, user_input: dict[str, Any]) -> FlowResult:
"""Handle reauthorization."""

existing_entry = self.hass.config_entries.async_get_entry(
self.context["entry_id"]
)
errors = {}
if user_input is not None:
password = user_input[CONF_PASSWORD]

url = existing_entry.data[CONF_URL]
verify_ssl = existing_entry.data[CONF_VERIFY_SSL]
opts = {
"session": async_get_clientsession(self.hass),
"verify_ssl": verify_ssl,
}

try:
controller = OpenSprinkler(url, password, opts)
await controller.refresh()
except InvalidURL:
errors["base"] = "invalid_url"
except OpenSprinklerConnectionError:
errors["base"] = "cannot_connect"
except OpenSprinklerAuthError:
errors["base"] = "invalid_auth"
else:
self.hass.config_entries.async_update_entry(
existing_entry,
data={
**existing_entry.data,
CONF_PASSWORD: password,
},
)
await self.hass.config_entries.async_reload(existing_entry.entry_id)
return self.async_abort(reason="reauth_successful")

return self.async_show_form(
step_id="reauth", data_schema=REAUTH_SCHEMA, errors=errors
)


class MacAddressRequiredError(Exception):
"""Error to mac address required."""
7 changes: 7 additions & 0 deletions custom_components/opensprinkler/strings.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,13 @@
"name": "Controller Name"
},
"title": "Connect to the OpenSprinkler controller"
},
"reauth": {
"data": {
"url": "URL",
"password": "Password"
},
"title": "Enter new password"
}
}
},
Expand Down
7 changes: 7 additions & 0 deletions custom_components/opensprinkler/translations/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,13 @@
"name": "Controller Name"
},
"title": "Stellen Sie eine Verbindung zum OpenSprinkler-Controller her"
},
"reauth": {
"data": {
"url": "URL",
"password": "Passwort"
},
"title": "Neues Passwort eingeben"
}
}
},
Expand Down
9 changes: 8 additions & 1 deletion custom_components/opensprinkler/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,13 @@
"name": "Controller Name"
},
"title": "Connect to the OpenSprinkler controller"
},
"reauth": {
"data": {
"url": "URL",
"password": "Password"
},
"title": "Enter new password"
}
}
},
Expand Down Expand Up @@ -91,7 +98,7 @@
},
"pause_duration": {
"name": "Pause duration",
"description": "Pause duration in seconds."
"description": "Duration to pause in seconds."
}
}
},
Expand Down
7 changes: 7 additions & 0 deletions custom_components/opensprinkler/translations/sk.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,13 @@
"name": "Názov ovládača"
},
"title": "Pripojte sa k ovládaču OpenSprinkler"
},
"reauth": {
"data": {
"url": "URL",
"password": "Heslo"
},
"title": "Zadajte nové heslo"
}
}
},
Expand Down

0 comments on commit 4da844b

Please sign in to comment.