async def async_step_verification_code(self, user_input=None, errors=None): """Ask the verification code to the user.""" if errors is None: errors = {} if user_input is None: return await self._show_verification_code_form(user_input, errors) self._verification_code = user_input[CONF_VERIFICATION_CODE] try: if self.api.requires_2fa: if not await self.hass.async_add_executor_job( self.api.validate_2fa_code, self._verification_code ): raise PyiCloudException("The code you entered is not valid.") else: if not await self.hass.async_add_executor_job( self.api.validate_verification_code, self._trusted_device, self._verification_code, ): raise PyiCloudException("The code you entered is not valid.") except PyiCloudException as error: # Reset to the initial 2FA state to allow the user to retry _LOGGER.error("Failed to verify verification code: %s", error) self._trusted_device = None self._verification_code = None errors["base"] = "validate_verification_code" if self.api.requires_2fa: try: self.api = await self.hass.async_add_executor_job( PyiCloudService, self._username, self._password, Store(self.hass, STORAGE_VERSION, STORAGE_KEY).path, True, None, self._with_family, ) return await self.async_step_verification_code(None, errors) except PyiCloudFailedLoginException as error_login: _LOGGER.error("Error logging into iCloud service: %s", error_login) self.api = None errors = {CONF_PASSWORD: "******"} return self._show_setup_form(user_input, errors, "user") else: return await self.async_step_trusted_device(None, errors) return await self.async_step_user( { CONF_USERNAME: self._username, CONF_PASSWORD: self._password, CONF_WITH_FAMILY: self._with_family, CONF_MAX_INTERVAL: self._max_interval, CONF_GPS_ACCURACY_THRESHOLD: self._gps_accuracy_threshold, } )
async def async_step_verification_code(self, user_input=None): """Ask the verification code to the user.""" errors = {} if user_input is None: return await self._show_verification_code_form(user_input) self._verification_code = user_input[CONF_VERIFICATION_CODE] try: if not await self.hass.async_add_executor_job( self.api.validate_verification_code, self._trusted_device, self._verification_code, ): raise PyiCloudException("The code you entered is not valid.") except PyiCloudException as error: # Reset to the initial 2FA state to allow the user to retry _LOGGER.error("Failed to verify verification code: %s", error) self._trusted_device = None self._verification_code = None errors["base"] = "validate_verification_code" return await self.async_step_trusted_device(None, errors) return await self.async_step_user( { CONF_USERNAME: self._username, CONF_PASSWORD: self._password, CONF_ACCOUNT_NAME: self._account_name, CONF_MAX_INTERVAL: self._max_interval, CONF_GPS_ACCURACY_THRESHOLD: self._gps_accuracy_threshold, } )
def icloud_verification_callback(self, callback_data): """Handle the chosen trusted device.""" from pyicloud.exceptions import PyiCloudException self._verification_code = callback_data.get('code') try: if not self.api.validate_verification_code( self._trusted_device, self._verification_code): raise PyiCloudException('Unknown failure') except PyiCloudException as error: # Reset to the initial 2FA state to allow the user to retry _LOGGER.error("Failed to verify verification code: %s", error) self._trusted_device = None self._verification_code = None # Trigger the next step immediately self.icloud_need_trusted_device() if self.accountname in _CONFIGURING: request_id = _CONFIGURING.pop(self.accountname) configurator = self.hass.components.configurator configurator.request_done(request_id)