core/homeassistant/components/azure_devops/config_flow.py

131 lines
4.4 KiB
Python
Raw Normal View History

"""Config flow to configure the Azure DevOps integration."""
from aioazuredevops.client import DevOpsClient
import aiohttp
import voluptuous as vol
from homeassistant import config_entries
from homeassistant.components.azure_devops.const import ( # pylint:disable=unused-import
CONF_ORG,
CONF_PAT,
CONF_PROJECT,
DOMAIN,
)
from homeassistant.config_entries import ConfigFlow
class AzureDevOpsFlowHandler(ConfigFlow, domain=DOMAIN):
"""Handle a Azure DevOps config flow."""
VERSION = 1
CONNECTION_CLASS = config_entries.CONN_CLASS_CLOUD_POLL
def __init__(self):
"""Initialize config flow."""
self._organization = None
self._project = None
self._pat = None
async def _show_setup_form(self, errors=None):
"""Show the setup form to the user."""
return self.async_show_form(
step_id="user",
data_schema=vol.Schema(
{
vol.Required(CONF_ORG, default=self._organization): str,
vol.Required(CONF_PROJECT, default=self._project): str,
vol.Optional(CONF_PAT): str,
}
),
errors=errors or {},
)
async def _show_reauth_form(self, errors=None):
"""Show the reauth form to the user."""
return self.async_show_form(
step_id="reauth",
description_placeholders={
"project_url": f"{self._organization}/{self._project}"
},
data_schema=vol.Schema({vol.Required(CONF_PAT): str}),
errors=errors or {},
)
async def _check_setup(self):
"""Check the setup of the flow."""
errors = {}
client = DevOpsClient()
try:
if self._pat is not None:
await client.authorize(self._pat, self._organization)
if not client.authorized:
errors["base"] = "invalid_auth"
return errors
project_info = await client.get_project(self._organization, self._project)
if project_info is None:
errors["base"] = "project_error"
return errors
except aiohttp.ClientError:
errors["base"] = "cannot_connect"
return errors
return None
async def async_step_user(self, user_input=None):
"""Handle a flow initiated by the user."""
if user_input is None:
return await self._show_setup_form(user_input)
self._organization = user_input[CONF_ORG]
self._project = user_input[CONF_PROJECT]
self._pat = user_input.get(CONF_PAT)
await self.async_set_unique_id(f"{self._organization}_{self._project}")
self._abort_if_unique_id_configured()
errors = await self._check_setup()
if errors is not None:
return await self._show_setup_form(errors)
return self._async_create_entry()
async def async_step_reauth(self, user_input):
"""Handle configuration by re-auth."""
if user_input.get(CONF_ORG) and user_input.get(CONF_PROJECT):
self._organization = user_input[CONF_ORG]
self._project = user_input[CONF_PROJECT]
self._pat = user_input[CONF_PAT]
# pylint: disable=no-member
self.context["title_placeholders"] = {
"project_url": f"{self._organization}/{self._project}",
}
await self.async_set_unique_id(f"{self._organization}_{self._project}")
errors = await self._check_setup()
if errors is not None:
return await self._show_reauth_form(errors)
for entry in self._async_current_entries():
if entry.unique_id == self.unique_id:
self.hass.config_entries.async_update_entry(
entry,
data={
CONF_ORG: self._organization,
CONF_PROJECT: self._project,
CONF_PAT: self._pat,
},
)
return self.async_abort(reason="reauth_successful")
def _async_create_entry(self):
"""Handle create entry."""
return self.async_create_entry(
title=f"{self._organization}/{self._project}",
data={
CONF_ORG: self._organization,
CONF_PROJECT: self._project,
CONF_PAT: self._pat,
},
)