Repository: home-assistant/core
File: homeassistant/components/vesync/config_flow.py (Python)

Code before:
            await manager.login()
        except VeSyncError as e:
            _LOGGER.error("VeSync login failed: %s", str(e))
            return self._show_form(errors={"base": "invalid_auth"})

        return self.async_create_entry(
            title=username,
            data={CONF_USERNAME: username, CONF_PASSWORD: password},
        )

    async def async_step_reauth(
        self, entry_data: Mapping[str, Any]
    ) -> ConfigFlowResult:
        """Handle re-authentication with vesync."""
        return await self.async_step_reauth_confirm()

    async def async_step_reauth_confirm(
        self, user_input: dict[str, Any] | None = None
    ) -> ConfigFlowResult:
        """Confirm re-authentication with vesync."""

        if user_input:
            username = user_input[CONF_USERNAME].lower()
            password = user_input[CONF_PASSWORD]

            await self.async_set_unique_id(username)
            self._async_abort_entries_match({CONF_USERNAME: username})
            time_zone = str(self.hass.config.time_zone)

            manager = VeSync(
                username,
                password,
                time_zone=time_zone,
                session=async_get_clientsession(self.hass),
            )
            try:
                await manager.login()
            except VeSyncError as e:
                _LOGGER.error("VeSync login failed: %s", str(e))
                return self.async_show_form(
                    step_id="reauth_confirm",
                    data_schema=DATA_SCHEMA,
                    description_placeholders={"name": "VeSync"},
                    errors={"base": "invalid_auth"},
                )

            return self.async_update_reload_and_abort(
                self._get_reauth_entry(),
                unique_id=username,
                data_updates={
                    CONF_USERNAME: username,

Review comment (security):
Is it possible to change the username? If yes, that’s not a valid source for a unique id, but we'd need to use the `account id` from the auth token for example. And if that’s not possible either fall back to `abort_entries_match`

Code after:
            return self._show_form(errors={"base": "invalid_auth"})

        await self.async_set_unique_id(manager.account_id)
        self._abort_if_unique_id_configured()

        return self.async_create_entry(
            title=username,
            data={CONF_USERNAME: username, CONF_PASSWORD: password},
        )

    async def async_step_reauth(
        self, entry_data: Mapping[str, Any]
    ) -> ConfigFlowResult:
        """Handle re-authentication with vesync."""
        return await self.async_step_reauth_confirm()

    async def async_step_reauth_confirm(
        self, user_input: dict[str, Any] | None = None
    ) -> ConfigFlowResult:
        """Confirm re-authentication with vesync."""

        if user_input:
            username = user_input[CONF_USERNAME]
            password = user_input[CONF_PASSWORD]

            time_zone = str(self.hass.config.time_zone)

            manager = VeSync(
                username,
                password,
                time_zone=time_zone,
                session=async_get_clientsession(self.hass),
            )
            try:
                await manager.login()
            except VeSyncError as e:
                _LOGGER.error("VeSync login failed: %s", str(e))
                return self.async_show_form(
                    step_id="reauth_confirm",
                    data_schema=DATA_SCHEMA,
                    description_placeholders={"name": "VeSync"},
                    errors={"base": "invalid_auth"},
                )

            await self.async_set_unique_id(manager.account_id)
            self._abort_if_unique_id_mismatch(reason="wrong_account")

            return self.async_update_reload_and_abort(
                self._get_reauth_entry(),
                unique_id=manager.account_id,
                data_updates={