Add and use HTTP_FORBIDDEN constant (#33839)
parent
70ee9d7f26
commit
bc26be3c11
|
@ -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)
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
@ -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"),
|
||||
],
|
||||
)
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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())})
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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"}}
|
||||
|
|
Loading…
Reference in New Issue