diff --git a/homeassistant/components/onedrive/__init__.py b/homeassistant/components/onedrive/__init__.py index c82757dca31cf..4aa11daf39d1e 100644 --- a/homeassistant/components/onedrive/__init__.py +++ b/homeassistant/components/onedrive/__init__.py @@ -99,6 +99,11 @@ async def get_access_token() -> str: _async_notify_backup_listeners_soon(hass) await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS) + async def update_listener(hass: HomeAssistant, entry: OneDriveConfigEntry) -> None: + await hass.config_entries.async_reload(entry.entry_id) + + entry.async_on_unload(entry.add_update_listener(update_listener)) + return True diff --git a/homeassistant/components/onedrive/backup.py b/homeassistant/components/onedrive/backup.py index 674708b0cb384..f8a2a6699c416 100644 --- a/homeassistant/components/onedrive/backup.py +++ b/homeassistant/components/onedrive/backup.py @@ -31,7 +31,7 @@ from homeassistant.core import HomeAssistant, callback from homeassistant.helpers.aiohttp_client import async_get_clientsession -from .const import DATA_BACKUP_AGENT_LISTENERS, DOMAIN +from .const import CONF_DELETE_PERMANENTLY, DATA_BACKUP_AGENT_LISTENERS, DOMAIN from .coordinator import OneDriveConfigEntry _LOGGER = logging.getLogger(__name__) @@ -205,8 +205,12 @@ async def async_delete_backup( backup = backups[backup_id] - await self._client.delete_drive_item(backup.backup_file_id) - await self._client.delete_drive_item(backup.metadata_file_id) + delete_permanently = self._entry.options.get(CONF_DELETE_PERMANENTLY, False) + + await self._client.delete_drive_item(backup.backup_file_id, delete_permanently) + await self._client.delete_drive_item( + backup.metadata_file_id, delete_permanently + ) self._cache_expiration = time() @handle_backup_errors diff --git a/homeassistant/components/onedrive/config_flow.py b/homeassistant/components/onedrive/config_flow.py index 900db0177d940..06c9ec253e371 100644 --- a/homeassistant/components/onedrive/config_flow.py +++ b/homeassistant/components/onedrive/config_flow.py @@ -1,18 +1,23 @@ """Config flow for OneDrive.""" +from __future__ import annotations + from collections.abc import Mapping import logging from typing import Any, cast from onedrive_personal_sdk.clients.client import OneDriveClient from onedrive_personal_sdk.exceptions import OneDriveException +import voluptuous as vol -from homeassistant.config_entries import SOURCE_REAUTH, ConfigFlowResult +from homeassistant.config_entries import SOURCE_REAUTH, ConfigFlowResult, OptionsFlow from homeassistant.const import CONF_ACCESS_TOKEN, CONF_TOKEN +from homeassistant.core import callback from homeassistant.helpers.aiohttp_client import async_get_clientsession from homeassistant.helpers.config_entry_oauth2_flow import AbstractOAuth2FlowHandler -from .const import DOMAIN, OAUTH_SCOPES +from .const import CONF_DELETE_PERMANENTLY, DOMAIN, OAUTH_SCOPES +from .coordinator import OneDriveConfigEntry class OneDriveConfigFlow(AbstractOAuth2FlowHandler, domain=DOMAIN): @@ -86,3 +91,38 @@ async def async_step_reauth_confirm( if user_input is None: return self.async_show_form(step_id="reauth_confirm") return await self.async_step_user() + + @staticmethod + @callback + def async_get_options_flow( + config_entry: OneDriveConfigEntry, + ) -> OneDriveOptionsFlowHandler: + """Create the options flow.""" + return OneDriveOptionsFlowHandler() + + +class OneDriveOptionsFlowHandler(OptionsFlow): + """Handles options flow for the component.""" + + async def async_step_init( + self, user_input: dict[str, Any] | None = None + ) -> ConfigFlowResult: + """Manage the options for OneDrive.""" + if user_input: + return self.async_create_entry(title="", data=user_input) + + options_schema = vol.Schema( + { + vol.Optional( + CONF_DELETE_PERMANENTLY, + default=self.config_entry.options.get( + CONF_DELETE_PERMANENTLY, False + ), + ): bool, + } + ) + + return self.async_show_form( + step_id="init", + data_schema=options_schema, + ) diff --git a/homeassistant/components/onedrive/const.py b/homeassistant/components/onedrive/const.py index f9d49b141e567..7aefa26ea817c 100644 --- a/homeassistant/components/onedrive/const.py +++ b/homeassistant/components/onedrive/const.py @@ -7,6 +7,8 @@ DOMAIN: Final = "onedrive" +CONF_DELETE_PERMANENTLY: Final = "delete_permanently" + # replace "consumers" with "common", when adding SharePoint or OneDrive for Business support OAUTH2_AUTHORIZE: Final = ( "https://login.microsoftonline.com/consumers/oauth2/v2.0/authorize" diff --git a/homeassistant/components/onedrive/quality_scale.yaml b/homeassistant/components/onedrive/quality_scale.yaml index 84b980c5e0162..44754e76f2c11 100644 --- a/homeassistant/components/onedrive/quality_scale.yaml +++ b/homeassistant/components/onedrive/quality_scale.yaml @@ -30,10 +30,7 @@ rules: # Silver action-exceptions: done config-entry-unloading: done - docs-configuration-parameters: - status: exempt - comment: | - No Options flow. + docs-configuration-parameters: done docs-installation-parameters: done entity-unavailable: done integration-owner: done diff --git a/homeassistant/components/onedrive/strings.json b/homeassistant/components/onedrive/strings.json index 20d139a4bc0d4..27afe3e8a9bcc 100644 --- a/homeassistant/components/onedrive/strings.json +++ b/homeassistant/components/onedrive/strings.json @@ -29,6 +29,19 @@ "default": "[%key:common::config_flow::create_entry::authenticated%]" } }, + "options": { + "step": { + "init": { + "description": "By default, files are put into the Recycle Bin when deleted, where they remain available for another 30 days. If you enable this option, files will be deleted immediately when they are cleaned up by the backup system.", + "data": { + "delete_permanently": "Delete files permanently" + }, + "data_description": { + "delete_permanently": "Delete files without moving them to the Recycle Bin" + } + } + } + }, "issues": { "drive_full": { "title": "OneDrive data cap exceeded", diff --git a/tests/components/onedrive/test_config_flow.py b/tests/components/onedrive/test_config_flow.py index fb0d58b86c60f..1ae92332075a7 100644 --- a/tests/components/onedrive/test_config_flow.py +++ b/tests/components/onedrive/test_config_flow.py @@ -8,6 +8,7 @@ from homeassistant import config_entries from homeassistant.components.onedrive.const import ( + CONF_DELETE_PERMANENTLY, DOMAIN, OAUTH2_AUTHORIZE, OAUTH2_TOKEN, @@ -223,3 +224,29 @@ async def test_reauth_flow_id_changed( assert result["type"] is FlowResultType.ABORT assert result["reason"] == "wrong_drive" + + +async def test_options_flow( + hass: HomeAssistant, + mock_config_entry: MockConfigEntry, +) -> None: + """Test options flow.""" + await setup_integration(hass, mock_config_entry) + + result = await hass.config_entries.options.async_init(mock_config_entry.entry_id) + + assert result["type"] is FlowResultType.FORM + assert result["step_id"] == "init" + + result2 = await hass.config_entries.options.async_configure( + result["flow_id"], + user_input={ + CONF_DELETE_PERMANENTLY: True, + }, + ) + await hass.async_block_till_done() + + assert result2["type"] is FlowResultType.CREATE_ENTRY + assert result2["data"] == { + CONF_DELETE_PERMANENTLY: True, + }