Add and use HTTP_FORBIDDEN constant (#33839)

pull/33898/head
springstan 2020-04-09 17:41:17 +02:00 committed by GitHub
parent 70ee9d7f26
commit bc26be3c11
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 60 additions and 37 deletions

View File

@ -132,7 +132,7 @@ from homeassistant.components.http.auth import async_sign_path
from homeassistant.components.http.ban import log_invalid_auth
from homeassistant.components.http.data_validator import RequestDataValidator
from homeassistant.components.http.view import HomeAssistantView
from homeassistant.const import HTTP_OK
from homeassistant.const import HTTP_FORBIDDEN, HTTP_OK
from homeassistant.core import HomeAssistant, callback
from homeassistant.loader import bind_hass
from homeassistant.util import dt as dt_util
@ -313,7 +313,7 @@ class TokenView(HomeAssistantView):
if not user.is_active:
return self.json(
{"error": "access_denied", "error_description": "User is not active"},
status_code=403,
status_code=HTTP_FORBIDDEN,
)
refresh_token = await hass.auth.async_create_refresh_token(user, client_id)

View File

@ -8,6 +8,7 @@ from homeassistant.components.notify import PLATFORM_SCHEMA, BaseNotificationSer
from homeassistant.const import (
CONF_ACCESS_TOKEN,
CONF_USERNAME,
HTTP_FORBIDDEN,
HTTP_INTERNAL_SERVER_ERROR,
)
import homeassistant.helpers.config_validation as cv
@ -39,7 +40,7 @@ class FreeSMSNotificationService(BaseNotificationService):
_LOGGER.error("At least one parameter is missing")
elif resp.status_code == 402:
_LOGGER.error("Too much SMS send in a few time")
elif resp.status_code == 403:
elif resp.status_code == HTTP_FORBIDDEN:
_LOGGER.error("Wrong Username/Password")
elif resp.status_code == HTTP_INTERNAL_SERVER_ERROR:
_LOGGER.error("Server error, try later")

View File

@ -9,7 +9,7 @@ import pymelcloud
import voluptuous as vol
from homeassistant import config_entries
from homeassistant.const import CONF_PASSWORD, CONF_TOKEN, CONF_USERNAME
from homeassistant.const import CONF_PASSWORD, CONF_TOKEN, CONF_USERNAME, HTTP_FORBIDDEN
from .const import DOMAIN # pylint: disable=unused-import
@ -27,7 +27,7 @@ class FlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
await self.async_set_unique_id(username)
self._abort_if_unique_id_configured({CONF_TOKEN: token})
return self.async_create_entry(
title=username, data={CONF_USERNAME: username, CONF_TOKEN: token},
title=username, data={CONF_USERNAME: username, CONF_TOKEN: token}
)
async def _create_client(
@ -40,7 +40,7 @@ class FlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
"""Create client."""
if password is None and token is None:
raise ValueError(
"Invalid internal state. Called without either password or token",
"Invalid internal state. Called without either password or token"
)
try:
@ -57,7 +57,7 @@ class FlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
self.hass.helpers.aiohttp_client.async_get_clientsession(),
)
except ClientResponseError as err:
if err.status == 401 or err.status == 403:
if err.status == 401 or err.status == HTTP_FORBIDDEN:
return self.async_abort(reason="invalid_auth")
return self.async_abort(reason="cannot_connect")
except (asyncio.TimeoutError, ClientError):

View File

@ -6,6 +6,7 @@ import voluptuous as vol
from homeassistant.auth.const import GROUP_ID_ADMIN
from homeassistant.components.http.data_validator import RequestDataValidator
from homeassistant.components.http.view import HomeAssistantView
from homeassistant.const import HTTP_FORBIDDEN
from homeassistant.core import callback
from .const import (
@ -95,7 +96,7 @@ class UserOnboardingView(_BaseOnboardingView):
async with self._lock:
if self._async_is_done():
return self.json_message("User step already done", 403)
return self.json_message("User step already done", HTTP_FORBIDDEN)
provider = _async_get_hass_provider(hass)
await provider.async_initialize()
@ -147,7 +148,9 @@ class CoreConfigOnboardingView(_BaseOnboardingView):
async with self._lock:
if self._async_is_done():
return self.json_message("Core config step already done", 403)
return self.json_message(
"Core config step already done", HTTP_FORBIDDEN
)
await self._async_mark_done(hass)
@ -173,7 +176,9 @@ class IntegrationOnboardingView(_BaseOnboardingView):
async with self._lock:
if self._async_is_done():
return self.json_message("Integration step already done", 403)
return self.json_message(
"Integration step already done", HTTP_FORBIDDEN
)
await self._async_mark_done(hass)

View File

@ -9,7 +9,7 @@ from pysmartapp.event import EVENT_TYPE_DEVICE
from pysmartthings import Attribute, Capability, SmartThings
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_ACCESS_TOKEN
from homeassistant.const import CONF_ACCESS_TOKEN, HTTP_FORBIDDEN
from homeassistant.exceptions import ConfigEntryNotReady
from homeassistant.helpers.aiohttp_client import async_get_clientsession
from homeassistant.helpers.dispatcher import (
@ -145,7 +145,7 @@ async def async_setup_entry(hass: HomeAssistantType, entry: ConfigEntry):
hass.data[DOMAIN][DATA_BROKERS][entry.entry_id] = broker
except ClientResponseError as ex:
if ex.status in (401, 403):
if ex.status in (401, HTTP_FORBIDDEN):
_LOGGER.exception(
"Unable to setup configuration entry '%s' - please reconfigure the integration",
entry.title,
@ -182,7 +182,7 @@ async def async_get_entry_scenes(entry: ConfigEntry, api):
try:
return await api.scenes(location_id=entry.data[CONF_LOCATION_ID])
except ClientResponseError as ex:
if ex.status == 403:
if ex.status == HTTP_FORBIDDEN:
_LOGGER.exception(
"Unable to load scenes for configuration entry '%s' because the access token does not have the required access",
entry.title,
@ -209,12 +209,12 @@ async def async_remove_entry(hass: HomeAssistantType, entry: ConfigEntry) -> Non
"""Perform clean-up when entry is being removed."""
api = SmartThings(async_get_clientsession(hass), entry.data[CONF_ACCESS_TOKEN])
# Remove the installed_app, which if already removed raises a 403 error.
# Remove the installed_app, which if already removed raises a HTTP_FORBIDDEN error.
installed_app_id = entry.data[CONF_INSTALLED_APP_ID]
try:
await api.delete_installed_app(installed_app_id)
except ClientResponseError as ex:
if ex.status == 403:
if ex.status == HTTP_FORBIDDEN:
_LOGGER.debug(
"Installed app %s has already been removed",
installed_app_id,
@ -225,7 +225,7 @@ async def async_remove_entry(hass: HomeAssistantType, entry: ConfigEntry) -> Non
_LOGGER.debug("Removed installed app %s", installed_app_id)
# Remove the app if not referenced by other entries, which if already
# removed raises a 403 error.
# removed raises a HTTP_FORBIDDEN error.
all_entries = hass.config_entries.async_entries(DOMAIN)
app_id = entry.data[CONF_APP_ID]
app_count = sum(1 for entry in all_entries if entry.data[CONF_APP_ID] == app_id)
@ -239,7 +239,7 @@ async def async_remove_entry(hass: HomeAssistantType, entry: ConfigEntry) -> Non
try:
await api.delete_app(app_id)
except ClientResponseError as ex:
if ex.status == 403:
if ex.status == HTTP_FORBIDDEN:
_LOGGER.debug("App %s has already been removed", app_id, exc_info=True)
else:
raise

View File

@ -6,7 +6,7 @@ from pysmartthings import APIResponseError, AppOAuth, SmartThings
import voluptuous as vol
from homeassistant import config_entries
from homeassistant.const import CONF_ACCESS_TOKEN
from homeassistant.const import CONF_ACCESS_TOKEN, HTTP_FORBIDDEN
from homeassistant.helpers.aiohttp_client import async_get_clientsession
from .const import (
@ -122,7 +122,7 @@ class SmartThingsFlowHandler(config_entries.ConfigFlow):
except ClientResponseError as ex:
if ex.status == 401:
errors[CONF_ACCESS_TOKEN] = "token_unauthorized"
elif ex.status == 403:
elif ex.status == HTTP_FORBIDDEN:
errors[CONF_ACCESS_TOKEN] = "token_forbidden"
else:
errors["base"] = "app_setup_error"

View File

@ -527,6 +527,7 @@ HTTP_CREATED = 201
HTTP_MOVED_PERMANENTLY = 301
HTTP_BAD_REQUEST = 400
HTTP_UNAUTHORIZED = 401
HTTP_FORBIDDEN = 403
HTTP_NOT_FOUND = 404
HTTP_METHOD_NOT_ALLOWED = 405
HTTP_UNPROCESSABLE_ENTITY = 422

View File

@ -7,7 +7,13 @@ from asynctest import patch
from homeassistant import data_entry_flow
from homeassistant.components.airly.const import DOMAIN
from homeassistant.config_entries import SOURCE_USER
from homeassistant.const import CONF_API_KEY, CONF_LATITUDE, CONF_LONGITUDE, CONF_NAME
from homeassistant.const import (
CONF_API_KEY,
CONF_LATITUDE,
CONF_LONGITUDE,
CONF_NAME,
HTTP_FORBIDDEN,
)
from tests.common import MockConfigEntry, load_fixture
@ -33,7 +39,9 @@ async def test_invalid_api_key(hass):
"""Test that errors are shown when API key is invalid."""
with patch(
"airly._private._RequestsHandler.get",
side_effect=AirlyError(403, {"message": "Invalid authentication credentials"}),
side_effect=AirlyError(
HTTP_FORBIDDEN, {"message": "Invalid authentication credentials"}
),
):
result = await hass.config_entries.flow.async_init(

View File

@ -12,6 +12,7 @@ from homeassistant.const import (
CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
CONCENTRATION_PARTS_PER_BILLION,
CONCENTRATION_PARTS_PER_MILLION,
HTTP_FORBIDDEN,
HTTP_INTERNAL_SERVER_ERROR,
TEMP_CELSIUS,
UNIT_PERCENTAGE,
@ -71,7 +72,7 @@ async def test_setup_permanent_error(hass, aioclient_mock):
"""Expected failures caused by permanent errors in API response."""
fake_async_add_entities = MagicMock()
errors = [400, 401, 403]
errors = [400, 401, HTTP_FORBIDDEN]
for error in errors:
aioclient_mock.get(re.compile("api.foobot.io/v2/owner/.*"), status=error)
result = await foobot.async_setup_platform(

View File

@ -20,6 +20,7 @@ from homeassistant.components.http.ban import (
setup_bans,
)
from homeassistant.components.http.view import request_handler_factory
from homeassistant.const import HTTP_FORBIDDEN
from homeassistant.setup import async_setup_component
from . import mock_real_ip
@ -55,12 +56,16 @@ async def test_access_from_banned_ip(hass, aiohttp_client):
for remote_addr in BANNED_IPS:
set_real_ip(remote_addr)
resp = await client.get("/")
assert resp.status == 403
assert resp.status == HTTP_FORBIDDEN
@pytest.mark.parametrize(
"remote_addr, bans, status",
list(zip(BANNED_IPS_WITH_SUPERVISOR, [1, 1, 0], [403, 403, 401])),
list(
zip(
BANNED_IPS_WITH_SUPERVISOR, [1, 1, 0], [HTTP_FORBIDDEN, HTTP_FORBIDDEN, 401]
)
),
)
async def test_access_from_supervisor_ip(
remote_addr, bans, status, hass, aiohttp_client, hassio_env
@ -78,7 +83,7 @@ async def test_access_from_supervisor_ip(
mock_real_ip(app)(remote_addr)
with patch(
"homeassistant.components.http.ban.async_load_ip_bans_config", return_value=[],
"homeassistant.components.http.ban.async_load_ip_bans_config", return_value=[]
):
client = await aiohttp_client(app)
@ -151,7 +156,7 @@ async def test_ip_bans_file_creation(hass, aiohttp_client):
m_open.assert_called_once_with(hass.config.path(IP_BANS_FILE), "a")
resp = await client.get("/")
assert resp.status == 403
assert resp.status == HTTP_FORBIDDEN
assert m_open.call_count == 1

View File

@ -8,7 +8,7 @@ import pytest
from homeassistant import config_entries
from homeassistant.components.melcloud.const import DOMAIN
from homeassistant.const import HTTP_INTERNAL_SERVER_ERROR
from homeassistant.const import HTTP_FORBIDDEN, HTTP_INTERNAL_SERVER_ERROR
from tests.common import MockConfigEntry
@ -92,7 +92,7 @@ async def test_form_errors(hass, mock_login, mock_get_devices, error, reason):
"error,message",
[
(401, "invalid_auth"),
(403, "invalid_auth"),
(HTTP_FORBIDDEN, "invalid_auth"),
(HTTP_INTERNAL_SERVER_ERROR, "cannot_connect"),
],
)

View File

@ -6,6 +6,7 @@ import pytest
from homeassistant.components import onboarding
from homeassistant.components.onboarding import const, views
from homeassistant.const import HTTP_FORBIDDEN
from homeassistant.setup import async_setup_component
from . import mock_storage
@ -65,7 +66,7 @@ async def test_onboarding_user_already_done(hass, hass_storage, aiohttp_client):
},
)
assert resp.status == 403
assert resp.status == HTTP_FORBIDDEN
async def test_onboarding_user(hass, hass_storage, aiohttp_client):
@ -179,7 +180,7 @@ async def test_onboarding_user_race(hass, hass_storage, aiohttp_client):
res1, res2 = await asyncio.gather(resp1, resp2)
assert sorted([res1.status, res2.status]) == [200, 403]
assert sorted([res1.status, res2.status]) == [200, HTTP_FORBIDDEN]
async def test_onboarding_integration(hass, hass_storage, hass_client):

View File

@ -15,7 +15,7 @@ from homeassistant.components.smartthings.const import (
CONF_REFRESH_TOKEN,
DOMAIN,
)
from homeassistant.const import HTTP_NOT_FOUND
from homeassistant.const import HTTP_FORBIDDEN, HTTP_NOT_FOUND
from homeassistant.setup import async_setup_component
from tests.common import MockConfigEntry, mock_coro
@ -103,7 +103,7 @@ async def test_token_forbidden(hass, smartthings_mock):
request_info = Mock(real_url="http://example.com")
smartthings_mock.apps.side_effect = ClientResponseError(
request_info=request_info, history=None, status=403
request_info=request_info, history=None, status=HTTP_FORBIDDEN
)
result = await flow.async_step_user({"access_token": str(uuid4())})

View File

@ -17,7 +17,7 @@ from homeassistant.components.smartthings.const import (
SIGNAL_SMARTTHINGS_UPDATE,
SUPPORTED_PLATFORMS,
)
from homeassistant.const import HTTP_INTERNAL_SERVER_ERROR
from homeassistant.const import HTTP_FORBIDDEN, HTTP_INTERNAL_SERVER_ERROR
from homeassistant.exceptions import ConfigEntryNotReady
from homeassistant.helpers.dispatcher import async_dispatcher_connect
from homeassistant.setup import async_setup_component
@ -155,7 +155,7 @@ async def test_scenes_unauthorized_loads_platforms(
smartthings_mock.installed_app.return_value = installed_app
smartthings_mock.devices.return_value = [device]
smartthings_mock.scenes.side_effect = ClientResponseError(
request_info=request_info, history=None, status=403
request_info=request_info, history=None, status=HTTP_FORBIDDEN
)
mock_token = Mock()
mock_token.access_token = str(uuid4())
@ -307,10 +307,10 @@ async def test_remove_entry_already_deleted(hass, config_entry, smartthings_mock
request_info = Mock(real_url="http://example.com")
# Arrange
smartthings_mock.delete_installed_app.side_effect = ClientResponseError(
request_info=request_info, history=None, status=403
request_info=request_info, history=None, status=HTTP_FORBIDDEN
)
smartthings_mock.delete_app.side_effect = ClientResponseError(
request_info=request_info, history=None, status=403
request_info=request_info, history=None, status=HTTP_FORBIDDEN
)
# Act
await smartthings.async_remove_entry(hass, config_entry)

View File

@ -8,6 +8,7 @@ from homeassistant.components.media_player.const import (
SERVICE_PLAY_MEDIA,
)
import homeassistant.components.tts as tts
from homeassistant.const import HTTP_FORBIDDEN
from homeassistant.setup import setup_component
from tests.common import assert_setup_component, get_test_home_assistant, mock_service
@ -198,7 +199,7 @@ class TestTTSYandexPlatform:
"speed": 1,
}
aioclient_mock.get(
self._base_url, status=403, content=b"test", params=url_param
self._base_url, status=HTTP_FORBIDDEN, content=b"test", params=url_param
)
config = {tts.DOMAIN: {"platform": "yandextts", "api_key": "1234567xx"}}