2024-12-25 22:33:32 +00:00

133 lines
4.2 KiB
Python

"""Config flow to configure the Backblaze B2 Cloud Storage integration."""
from __future__ import annotations
from collections.abc import Sequence
from typing import Any
from b2sdk.v2 import AuthInfoCache, B2Api, Bucket, InMemoryAccountInfo
from b2sdk.v2.exception import InvalidAuthToken
import voluptuous as vol
from homeassistant.config_entries import ConfigFlow, ConfigFlowResult
from homeassistant.helpers.selector import (
SelectOptionDict,
SelectSelector,
SelectSelectorConfig,
SelectSelectorMode,
TextSelector,
TextSelectorConfig,
TextSelectorType,
)
from .const import (
CONF_APPLICATION_KEY,
CONF_APPLICATION_KEY_ID,
CONF_BUCKET,
DOMAIN,
LOGGER,
)
class BackblazeFlowHandler(ConfigFlow, domain=DOMAIN):
"""Handle a Backblaze config flow."""
VERSION = 1
_buckets: Sequence[Bucket]
_authorization: dict[str, Any]
async def async_step_user(
self, user_input: dict[str, Any] | None = None
) -> ConfigFlowResult:
"""Handle a flow initiated by the user."""
errors = {}
if user_input is not None:
info = InMemoryAccountInfo()
backblaze = B2Api(info, cache=AuthInfoCache(info))
try:
await self.hass.async_add_executor_job(
backblaze.authorize_account,
"production",
user_input[CONF_APPLICATION_KEY_ID],
user_input[CONF_APPLICATION_KEY],
)
self._buckets = await self.hass.async_add_executor_job(
backblaze.list_buckets,
)
except InvalidAuthToken:
errors["base"] = "invalid_auth"
except Exception: # noqa: BLE001
LOGGER.exception("Unexpected exception")
errors["base"] = "unknown"
else:
self._authorization = user_input
return await self.async_step_bucket()
else:
user_input = {}
return self.async_show_form(
step_id="user",
data_schema=vol.Schema(
{
vol.Required(
CONF_APPLICATION_KEY_ID,
default=user_input.get(CONF_APPLICATION_KEY_ID),
): TextSelector(
config=TextSelectorConfig(
autocomplete="off",
),
),
vol.Required(CONF_APPLICATION_KEY): TextSelector(
config=TextSelectorConfig(
type=TextSelectorType.PASSWORD,
),
),
}
),
errors=errors,
)
async def async_step_bucket(
self, user_input: dict[str, Any] | None = None
) -> ConfigFlowResult:
"""Handle a bucket selection."""
if user_input is not None:
await self.async_set_unique_id(user_input[CONF_BUCKET])
self._abort_if_unique_id_configured()
return self.async_create_entry(
title=(
next(
bucket.name
for bucket in self._buckets
if bucket.id_ == user_input[CONF_BUCKET]
)
or "Backblaze"
),
data=self._authorization | user_input,
)
return self.async_show_form(
step_id="bucket",
data_schema=vol.Schema(
{
vol.Required(
CONF_BUCKET,
): SelectSelector(
config=SelectSelectorConfig(
mode=SelectSelectorMode.DROPDOWN,
options=[
SelectOptionDict(
value=bucket.id_,
label=bucket.name,
)
for bucket in self._buckets
],
sort=True,
)
),
}
),
)