From 78338f161f8dbfa2bde3bd10fed76f5539fdc8ad Mon Sep 17 00:00:00 2001 From: Erik Montnemery Date: Tue, 1 Apr 2025 16:13:18 +0200 Subject: [PATCH] Add base class for onboarding views (#141970) --- homeassistant/components/onboarding/views.py | 79 +++++++++----------- 1 file changed, 34 insertions(+), 45 deletions(-) diff --git a/homeassistant/components/onboarding/views.py b/homeassistant/components/onboarding/views.py index f0638e72d94..52f63d91770 100644 --- a/homeassistant/components/onboarding/views.py +++ b/homeassistant/components/onboarding/views.py @@ -51,7 +51,7 @@ async def async_setup( hass: HomeAssistant, data: OnboardingStoreData, store: OnboardingStorage ) -> None: """Set up the onboarding view.""" - hass.http.register_view(OnboardingView(data, store)) + hass.http.register_view(OnboardingStatusView(data, store)) hass.http.register_view(InstallationTypeOnboardingView(data)) hass.http.register_view(UserOnboardingView(data, store)) hass.http.register_view(CoreConfigOnboardingView(data, store)) @@ -63,17 +63,30 @@ async def async_setup( setup_cloud_views(hass, data) -class OnboardingView(HomeAssistantView): - """Return the onboarding status.""" +class _BaseOnboardingView(HomeAssistantView): + """Base class for onboarding views.""" + + def __init__(self, data: OnboardingStoreData) -> None: + """Initialize the onboarding view.""" + self._data = data + + +class _NoAuthBaseOnboardingView(_BaseOnboardingView): + """Base class for unauthenticated onboarding views.""" requires_auth = False + + +class OnboardingStatusView(_NoAuthBaseOnboardingView): + """Return the onboarding status.""" + url = "/api/onboarding" name = "api:onboarding" def __init__(self, data: OnboardingStoreData, store: OnboardingStorage) -> None: """Initialize the onboarding view.""" + super().__init__(data) self._store = store - self._data = data async def get(self, request: web.Request) -> web.Response: """Return the onboarding status.""" @@ -82,17 +95,12 @@ class OnboardingView(HomeAssistantView): ) -class InstallationTypeOnboardingView(HomeAssistantView): +class InstallationTypeOnboardingView(_NoAuthBaseOnboardingView): """Return the installation type during onboarding.""" - requires_auth = False url = "/api/onboarding/installation_type" name = "api:onboarding:installation_type" - def __init__(self, data: OnboardingStoreData) -> None: - """Initialize the onboarding installation type view.""" - self._data = data - async def get(self, request: web.Request) -> web.Response: """Return the onboarding status.""" if self._data["done"]: @@ -103,15 +111,15 @@ class InstallationTypeOnboardingView(HomeAssistantView): return self.json({"installation_type": info["installation_type"]}) -class _BaseOnboardingView(HomeAssistantView): - """Base class for onboarding.""" +class _BaseOnboardingStepView(_BaseOnboardingView): + """Base class for an onboarding step.""" step: str def __init__(self, data: OnboardingStoreData, store: OnboardingStorage) -> None: """Initialize the onboarding view.""" + super().__init__(data) self._store = store - self._data = data self._lock = asyncio.Lock() @callback @@ -131,7 +139,7 @@ class _BaseOnboardingView(HomeAssistantView): listener() -class UserOnboardingView(_BaseOnboardingView): +class UserOnboardingView(_BaseOnboardingStepView): """View to handle create user onboarding step.""" url = "/api/onboarding/users" @@ -197,7 +205,7 @@ class UserOnboardingView(_BaseOnboardingView): return self.json({"auth_code": auth_code}) -class CoreConfigOnboardingView(_BaseOnboardingView): +class CoreConfigOnboardingView(_BaseOnboardingStepView): """View to finish core config onboarding step.""" url = "/api/onboarding/core_config" @@ -243,7 +251,7 @@ class CoreConfigOnboardingView(_BaseOnboardingView): return self.json({}) -class IntegrationOnboardingView(_BaseOnboardingView): +class IntegrationOnboardingView(_BaseOnboardingStepView): """View to finish integration onboarding step.""" url = "/api/onboarding/integration" @@ -290,7 +298,7 @@ class IntegrationOnboardingView(_BaseOnboardingView): return self.json({"auth_code": auth_code}) -class AnalyticsOnboardingView(_BaseOnboardingView): +class AnalyticsOnboardingView(_BaseOnboardingStepView): """View to finish analytics onboarding step.""" url = "/api/onboarding/analytics" @@ -312,17 +320,7 @@ class AnalyticsOnboardingView(_BaseOnboardingView): return self.json({}) -class BackupOnboardingView(HomeAssistantView): - """Backup onboarding view.""" - - requires_auth = False - - def __init__(self, data: OnboardingStoreData) -> None: - """Initialize the view.""" - self._data = data - - -def with_backup_manager[_ViewT: BackupOnboardingView, **_P]( +def with_backup_manager[_ViewT: _BaseOnboardingView, **_P]( func: Callable[ Concatenate[_ViewT, BackupManager, web.Request, _P], Coroutine[Any, Any, web.Response], @@ -354,7 +352,7 @@ def with_backup_manager[_ViewT: BackupOnboardingView, **_P]( return with_backup -class BackupInfoView(BackupOnboardingView): +class BackupInfoView(_NoAuthBaseOnboardingView): """Get backup info view.""" url = "/api/onboarding/backup/info" @@ -373,7 +371,7 @@ class BackupInfoView(BackupOnboardingView): ) -class RestoreBackupView(BackupOnboardingView): +class RestoreBackupView(_NoAuthBaseOnboardingView): """Restore backup view.""" url = "/api/onboarding/backup/restore" @@ -418,7 +416,7 @@ class RestoreBackupView(BackupOnboardingView): return web.Response(status=HTTPStatus.OK) -class UploadBackupView(BackupOnboardingView, backup_http.UploadBackupView): +class UploadBackupView(_NoAuthBaseOnboardingView, backup_http.UploadBackupView): """Upload backup view.""" url = "/api/onboarding/backup/upload" @@ -442,16 +440,7 @@ def setup_cloud_views(hass: HomeAssistant, data: OnboardingStoreData) -> None: # pylint: disable-next=import-outside-toplevel,hass-component-root-import from homeassistant.components.cloud.const import DATA_CLOUD - class CloudOnboardingView(HomeAssistantView): - """Cloud onboarding view.""" - - requires_auth = False - - def __init__(self, data: OnboardingStoreData) -> None: - """Initialize the view.""" - self._data = data - - def with_cloud[_ViewT: CloudOnboardingView, **_P]( + def with_cloud[_ViewT: _BaseOnboardingView, **_P]( func: Callable[ Concatenate[_ViewT, web.Request, _P], Coroutine[Any, Any, web.Response], @@ -486,7 +475,7 @@ def setup_cloud_views(hass: HomeAssistant, data: OnboardingStoreData) -> None: return _with_cloud class CloudForgotPasswordView( - CloudOnboardingView, cloud_http.CloudForgotPasswordView + _NoAuthBaseOnboardingView, cloud_http.CloudForgotPasswordView ): """View to start Forgot Password flow.""" @@ -498,7 +487,7 @@ def setup_cloud_views(hass: HomeAssistant, data: OnboardingStoreData) -> None: """Handle forgot password request.""" return await super()._post(request) - class CloudLoginView(CloudOnboardingView, cloud_http.CloudLoginView): + class CloudLoginView(_NoAuthBaseOnboardingView, cloud_http.CloudLoginView): """Login to Home Assistant Cloud.""" url = "/api/onboarding/cloud/login" @@ -509,7 +498,7 @@ def setup_cloud_views(hass: HomeAssistant, data: OnboardingStoreData) -> None: """Handle login request.""" return await super()._post(request) - class CloudLogoutView(CloudOnboardingView, cloud_http.CloudLogoutView): + class CloudLogoutView(_NoAuthBaseOnboardingView, cloud_http.CloudLogoutView): """Log out of the Home Assistant cloud.""" url = "/api/onboarding/cloud/logout" @@ -520,7 +509,7 @@ def setup_cloud_views(hass: HomeAssistant, data: OnboardingStoreData) -> None: """Handle logout request.""" return await super()._post(request) - class CloudStatusView(CloudOnboardingView): + class CloudStatusView(_NoAuthBaseOnboardingView): """Get cloud status view.""" url = "/api/onboarding/cloud/status"