Home Assistant Unofficial Reference 2024.12.1
config_flow.py
Go to the documentation of this file.
1 """Config flow to configure the Azure DevOps integration."""
2 
3 from __future__ import annotations
4 
5 from collections.abc import Mapping
6 from typing import Any
7 
8 from aioazuredevops.client import DevOpsClient
9 import aiohttp
10 import voluptuous as vol
11 
12 from homeassistant.config_entries import ConfigFlow, ConfigFlowResult
13 from homeassistant.helpers.aiohttp_client import async_get_clientsession
14 
15 from .const import CONF_ORG, CONF_PAT, CONF_PROJECT, DOMAIN
16 
17 
18 class AzureDevOpsFlowHandler(ConfigFlow, domain=DOMAIN):
19  """Handle a Azure DevOps config flow."""
20 
21  VERSION = 1
22 
23  def __init__(self) -> None:
24  """Initialize config flow."""
25  self._organization_organization: str | None = None
26  self._project_project: str | None = None
27  self._pat_pat: str | None = None
28 
29  async def _show_setup_form(
30  self, errors: dict[str, str] | None = None
31  ) -> ConfigFlowResult:
32  """Show the setup form to the user."""
33  return self.async_show_formasync_show_formasync_show_form(
34  step_id="user",
35  data_schema=vol.Schema(
36  {
37  vol.Required(CONF_ORG, default=self._organization_organization): str,
38  vol.Required(CONF_PROJECT, default=self._project_project): str,
39  vol.Optional(CONF_PAT): str,
40  }
41  ),
42  errors=errors or {},
43  )
44 
45  async def _check_setup(self) -> dict[str, str] | None:
46  """Check the setup of the flow."""
47  errors: dict[str, str] = {}
48 
49  aiohttp_session = async_get_clientsession(self.hass)
50  client = DevOpsClient(session=aiohttp_session)
51 
52  try:
53  if self._pat_pat is not None:
54  await client.authorize(self._pat_pat, self._organization_organization)
55  if not client.authorized:
56  errors["base"] = "invalid_auth"
57  return errors
58  project_info = await client.get_project(self._organization_organization, self._project_project)
59  if project_info is None:
60  errors["base"] = "project_error"
61  return errors
62  except aiohttp.ClientError:
63  errors["base"] = "cannot_connect"
64  return errors
65  return None
66 
67  async def async_step_user(
68  self, user_input: dict[str, str] | None = None
69  ) -> ConfigFlowResult:
70  """Handle a flow initiated by the user."""
71  if user_input is None:
72  return await self._show_setup_form_show_setup_form()
73 
74  self._organization_organization = user_input[CONF_ORG]
75  self._project_project = user_input[CONF_PROJECT]
76  self._pat_pat = user_input.get(CONF_PAT)
77 
78  await self.async_set_unique_idasync_set_unique_id(f"{self._organization}_{self._project}")
79  self._abort_if_unique_id_configured_abort_if_unique_id_configured()
80 
81  errors = await self._check_setup_check_setup()
82  if errors is not None:
83  return await self._show_setup_form_show_setup_form(errors)
84  return self._async_create_entry_async_create_entry()
85 
86  async def async_step_reauth(
87  self, entry_data: Mapping[str, Any]
88  ) -> ConfigFlowResult:
89  """Handle configuration by re-auth."""
90  if entry_data.get(CONF_ORG) and entry_data.get(CONF_PROJECT):
91  self._organization_organization = entry_data[CONF_ORG]
92  self._project_project = entry_data[CONF_PROJECT]
93  self._pat_pat = entry_data[CONF_PAT]
94 
95  self.context["title_placeholders"] = {
96  "project_url": f"{self._organization}/{self._project}",
97  }
98  return await self.async_step_reauth_confirmasync_step_reauth_confirm()
99 
101  self, user_input: dict[str, str] | None = None
102  ) -> ConfigFlowResult:
103  """Handle configuration by re-auth."""
104  errors: dict[str, str] | None = None
105  if user_input is not None:
106  errors = await self._check_setup_check_setup()
107  if errors is None:
108  self.hass.config_entries.async_update_entry(
109  self._get_reauth_entry_get_reauth_entry(),
110  data={
111  CONF_ORG: self._organization_organization,
112  CONF_PROJECT: self._project_project,
113  CONF_PAT: self._pat_pat,
114  },
115  )
116  return self.async_abortasync_abortasync_abort(reason="reauth_successful")
117  return self.async_show_formasync_show_formasync_show_form(
118  step_id="reauth_confirm",
119  description_placeholders={
120  "project_url": f"{self._organization}/{self._project}"
121  },
122  data_schema=vol.Schema({vol.Required(CONF_PAT): str}),
123  errors=errors or {},
124  )
125 
126  def _async_create_entry(self) -> ConfigFlowResult:
127  """Handle create entry."""
128  return self.async_create_entryasync_create_entryasync_create_entry(
129  title=f"{self._organization}/{self._project}",
130  data={
131  CONF_ORG: self._organization_organization,
132  CONF_PROJECT: self._project_project,
133  CONF_PAT: self._pat_pat,
134  },
135  )
ConfigFlowResult async_step_user(self, dict[str, str]|None user_input=None)
Definition: config_flow.py:69
ConfigFlowResult async_step_reauth_confirm(self, dict[str, str]|None user_input=None)
Definition: config_flow.py:102
ConfigFlowResult async_step_reauth(self, Mapping[str, Any] entry_data)
Definition: config_flow.py:88
ConfigFlowResult _show_setup_form(self, dict[str, str]|None errors=None)
Definition: config_flow.py:31
None _abort_if_unique_id_configured(self, dict[str, Any]|None updates=None, bool reload_on_update=True, *str error="already_configured")
ConfigEntry|None async_set_unique_id(self, str|None unique_id=None, *bool raise_on_progress=True)
ConfigFlowResult async_create_entry(self, *str title, Mapping[str, Any] data, str|None description=None, Mapping[str, str]|None description_placeholders=None, Mapping[str, Any]|None options=None)
ConfigFlowResult async_abort(self, *str reason, Mapping[str, str]|None description_placeholders=None)
ConfigFlowResult async_show_form(self, *str|None step_id=None, vol.Schema|None data_schema=None, dict[str, str]|None errors=None, Mapping[str, str]|None description_placeholders=None, bool|None last_step=None, str|None preview=None)
_FlowResultT async_show_form(self, *str|None step_id=None, vol.Schema|None data_schema=None, dict[str, str]|None errors=None, Mapping[str, str]|None description_placeholders=None, bool|None last_step=None, str|None preview=None)
_FlowResultT async_create_entry(self, *str|None title=None, Mapping[str, Any] data, str|None description=None, Mapping[str, str]|None description_placeholders=None)
_FlowResultT async_abort(self, *str reason, Mapping[str, str]|None description_placeholders=None)
aiohttp.ClientSession async_get_clientsession(HomeAssistant hass, bool verify_ssl=True, socket.AddressFamily family=socket.AF_UNSPEC, ssl_util.SSLCipherList ssl_cipher=ssl_util.SSLCipherList.PYTHON_DEFAULT)