Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 2 additions & 9 deletions homeassistant/components/google_sheets/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,10 @@
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.selector import ConfigEntrySelector

from .const import DATA_CONFIG_ENTRY, DEFAULT_ACCESS, DOMAIN
from .const import DOMAIN

DATA = "data"
DATA_CONFIG_ENTRY = "config_entry"
WORKSHEET = "worksheet"

SERVICE_APPEND_SHEET = "append_sheet"
Expand Down Expand Up @@ -51,21 +52,13 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
raise ConfigEntryNotReady from err
except aiohttp.ClientError as err:
raise ConfigEntryNotReady from err

if not async_entry_has_scopes(hass, entry):
raise ConfigEntryAuthFailed("Required scopes are not present, reauth required")
hass.data.setdefault(DOMAIN, {})[entry.entry_id] = session

await async_setup_service(hass)

return True


def async_entry_has_scopes(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Verify that the config entry desired scope is present in the oauth token."""
return DEFAULT_ACCESS in entry.data.get(CONF_TOKEN, {}).get("scope", "").split(" ")


async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Unload a config entry."""
hass.data[DOMAIN].pop(entry.entry_id)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,9 @@
"""application_credentials platform for Google Sheets."""

import oauth2client

from homeassistant.components.application_credentials import AuthorizationServer
from homeassistant.core import HomeAssistant

AUTHORIZATION_SERVER = AuthorizationServer(
oauth2client.GOOGLE_AUTH_URI, oauth2client.GOOGLE_TOKEN_URI
)


async def async_get_authorization_server(hass: HomeAssistant) -> AuthorizationServer:
"""Return authorization server."""
Expand Down
4 changes: 2 additions & 2 deletions homeassistant/components/google_sheets/config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
from homeassistant.data_entry_flow import FlowResult
from homeassistant.helpers import config_entry_oauth2_flow

from .const import DEFAULT_ACCESS, DEFAULT_NAME, DOMAIN
from .const import DEFAULT_NAME, DOMAIN

_LOGGER = logging.getLogger(__name__)

Expand All @@ -36,7 +36,7 @@ def logger(self) -> logging.Logger:
def extra_authorize_data(self) -> dict[str, Any]:
"""Extra data that needs to be appended to the authorize url."""
return {
"scope": DEFAULT_ACCESS,
"scope": "https://www.googleapis.com/auth/drive.file",
# Add params to ensure we get back a refresh token
"access_type": "offline",
"prompt": "consent",
Expand Down
4 changes: 0 additions & 4 deletions homeassistant/components/google_sheets/const.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
"""Constants for Google Sheets integration."""
from __future__ import annotations

from typing import Final

DOMAIN = "google_sheets"

DATA_CONFIG_ENTRY: Final = "config_entry"
DEFAULT_NAME = "Google Sheets"
DEFAULT_ACCESS = "https://www.googleapis.com/auth/drive.file"
4 changes: 0 additions & 4 deletions homeassistant/components/google_sheets/strings.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,6 @@
"pick_implementation": {
"title": "[%key:common::config_flow::title::oauth2_pick_implementation%]"
},
"reauth_confirm": {
"title": "[%key:common::config_flow::title::reauth%]",
"description": "The Google Sheets integration needs to re-authenticate your account"
},
"auth": {
"title": "Link Google Account"
},
Expand Down
30 changes: 1 addition & 29 deletions tests/components/google_sheets/test_init.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,40 +92,13 @@ async def test_setup_success(

assert not hass.data.get(DOMAIN)
assert entries[0].state is ConfigEntryState.NOT_LOADED
assert not len(hass.services.async_services().get(DOMAIN, {}))


@pytest.mark.parametrize(
"scopes",
[
[],
[
"https://www.googleapis.com/auth/drive.file+plus+extra"
], # Required scope is a prefix
["https://www.googleapis.com/auth/drive.readonly"],
],
ids=["no_scope", "required_scope_prefix", "other_scope"],
)
async def test_missing_required_scopes_requires_reauth(
hass: HomeAssistant, setup_integration: ComponentSetup
) -> None:
"""Test that reauth is invoked when required scopes are not present."""
await setup_integration()

entries = hass.config_entries.async_entries(DOMAIN)
assert len(entries) == 1
assert entries[0].state is ConfigEntryState.SETUP_ERROR

flows = hass.config_entries.flow.async_progress()
assert len(flows) == 1
assert flows[0]["step_id"] == "reauth_confirm"
assert not hass.services.async_services().get(DOMAIN, {})


@pytest.mark.parametrize("expires_at", [time.time() - 3600], ids=["expired"])
async def test_expired_token_refresh_success(
hass: HomeAssistant,
setup_integration: ComponentSetup,
scopes: list[str],
aioclient_mock: AiohttpClientMocker,
) -> None:
"""Test expired token is refreshed."""
Expand Down Expand Up @@ -168,7 +141,6 @@ async def test_expired_token_refresh_success(
async def test_expired_token_refresh_failure(
hass: HomeAssistant,
setup_integration: ComponentSetup,
scopes: list[str],
aioclient_mock: AiohttpClientMocker,
status: http.HTTPStatus,
expected_state: ConfigEntryState,
Expand Down