Use proper signals (#18613)
* Emulated Hue not use deprecated handler * Remove no longer needed workaround * Add middleware directly * Dont always load the ban config file * Update homeassistant/components/http/ban.py Co-Authored-By: balloob <paulus@home-assistant.io> * Update __init__.pypull/18623/head
parent
5b3e9399a9
commit
1341ecd2eb
|
@ -97,8 +97,8 @@ async def async_setup(hass, yaml_config):
|
||||||
app._on_startup.freeze()
|
app._on_startup.freeze()
|
||||||
await app.startup()
|
await app.startup()
|
||||||
|
|
||||||
handler = None
|
runner = None
|
||||||
server = None
|
site = None
|
||||||
|
|
||||||
DescriptionXmlView(config).register(app, app.router)
|
DescriptionXmlView(config).register(app, app.router)
|
||||||
HueUsernameView().register(app, app.router)
|
HueUsernameView().register(app, app.router)
|
||||||
|
@ -115,25 +115,24 @@ async def async_setup(hass, yaml_config):
|
||||||
async def stop_emulated_hue_bridge(event):
|
async def stop_emulated_hue_bridge(event):
|
||||||
"""Stop the emulated hue bridge."""
|
"""Stop the emulated hue bridge."""
|
||||||
upnp_listener.stop()
|
upnp_listener.stop()
|
||||||
if server:
|
if site:
|
||||||
server.close()
|
await site.stop()
|
||||||
await server.wait_closed()
|
if runner:
|
||||||
await app.shutdown()
|
await runner.cleanup()
|
||||||
if handler:
|
|
||||||
await handler.shutdown(10)
|
|
||||||
await app.cleanup()
|
|
||||||
|
|
||||||
async def start_emulated_hue_bridge(event):
|
async def start_emulated_hue_bridge(event):
|
||||||
"""Start the emulated hue bridge."""
|
"""Start the emulated hue bridge."""
|
||||||
upnp_listener.start()
|
upnp_listener.start()
|
||||||
nonlocal handler
|
nonlocal site
|
||||||
nonlocal server
|
nonlocal runner
|
||||||
|
|
||||||
handler = app.make_handler(loop=hass.loop)
|
runner = web.AppRunner(app)
|
||||||
|
await runner.setup()
|
||||||
|
|
||||||
|
site = web.TCPSite(runner, config.host_ip_addr, config.listen_port)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
server = await hass.loop.create_server(
|
await site.start()
|
||||||
handler, config.host_ip_addr, config.listen_port)
|
|
||||||
except OSError as error:
|
except OSError as error:
|
||||||
_LOGGER.error("Failed to create HTTP server at port %d: %s",
|
_LOGGER.error("Failed to create HTTP server at port %d: %s",
|
||||||
config.listen_port, error)
|
config.listen_port, error)
|
||||||
|
|
|
@ -302,12 +302,6 @@ class HomeAssistantHTTP:
|
||||||
|
|
||||||
async def start(self):
|
async def start(self):
|
||||||
"""Start the aiohttp server."""
|
"""Start the aiohttp server."""
|
||||||
# We misunderstood the startup signal. You're not allowed to change
|
|
||||||
# anything during startup. Temp workaround.
|
|
||||||
# pylint: disable=protected-access
|
|
||||||
self.app._on_startup.freeze()
|
|
||||||
await self.app.startup()
|
|
||||||
|
|
||||||
if self.ssl_certificate:
|
if self.ssl_certificate:
|
||||||
try:
|
try:
|
||||||
if self.ssl_profile == SSL_INTERMEDIATE:
|
if self.ssl_profile == SSL_INTERMEDIATE:
|
||||||
|
@ -335,6 +329,7 @@ class HomeAssistantHTTP:
|
||||||
# However in Home Assistant components can be discovered after boot.
|
# However in Home Assistant components can be discovered after boot.
|
||||||
# This will now raise a RunTimeError.
|
# This will now raise a RunTimeError.
|
||||||
# To work around this we now prevent the router from getting frozen
|
# To work around this we now prevent the router from getting frozen
|
||||||
|
# pylint: disable=protected-access
|
||||||
self.app._router.freeze = lambda: None
|
self.app._router.freeze = lambda: None
|
||||||
|
|
||||||
self.runner = web.AppRunner(self.app)
|
self.runner = web.AppRunner(self.app)
|
||||||
|
|
|
@ -96,11 +96,7 @@ def setup_auth(app, trusted_networks, use_auth,
|
||||||
request[KEY_AUTHENTICATED] = authenticated
|
request[KEY_AUTHENTICATED] = authenticated
|
||||||
return await handler(request)
|
return await handler(request)
|
||||||
|
|
||||||
async def auth_startup(app):
|
app.middlewares.append(auth_middleware)
|
||||||
"""Initialize auth middleware when app starts up."""
|
|
||||||
app.middlewares.append(auth_middleware)
|
|
||||||
|
|
||||||
app.on_startup.append(auth_startup)
|
|
||||||
|
|
||||||
|
|
||||||
def _is_trusted_ip(request, trusted_networks):
|
def _is_trusted_ip(request, trusted_networks):
|
||||||
|
|
|
@ -9,7 +9,7 @@ from aiohttp.web import middleware
|
||||||
from aiohttp.web_exceptions import HTTPForbidden, HTTPUnauthorized
|
from aiohttp.web_exceptions import HTTPForbidden, HTTPUnauthorized
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
from homeassistant.core import callback
|
from homeassistant.core import callback, HomeAssistant
|
||||||
from homeassistant.config import load_yaml_config_file
|
from homeassistant.config import load_yaml_config_file
|
||||||
from homeassistant.exceptions import HomeAssistantError
|
from homeassistant.exceptions import HomeAssistantError
|
||||||
import homeassistant.helpers.config_validation as cv
|
import homeassistant.helpers.config_validation as cv
|
||||||
|
@ -36,13 +36,14 @@ SCHEMA_IP_BAN_ENTRY = vol.Schema({
|
||||||
@callback
|
@callback
|
||||||
def setup_bans(hass, app, login_threshold):
|
def setup_bans(hass, app, login_threshold):
|
||||||
"""Create IP Ban middleware for the app."""
|
"""Create IP Ban middleware for the app."""
|
||||||
|
app.middlewares.append(ban_middleware)
|
||||||
|
app[KEY_FAILED_LOGIN_ATTEMPTS] = defaultdict(int)
|
||||||
|
app[KEY_LOGIN_THRESHOLD] = login_threshold
|
||||||
|
|
||||||
async def ban_startup(app):
|
async def ban_startup(app):
|
||||||
"""Initialize bans when app starts up."""
|
"""Initialize bans when app starts up."""
|
||||||
app.middlewares.append(ban_middleware)
|
app[KEY_BANNED_IPS] = await async_load_ip_bans_config(
|
||||||
app[KEY_BANNED_IPS] = await hass.async_add_job(
|
hass, hass.config.path(IP_BANS_FILE))
|
||||||
load_ip_bans_config, hass.config.path(IP_BANS_FILE))
|
|
||||||
app[KEY_FAILED_LOGIN_ATTEMPTS] = defaultdict(int)
|
|
||||||
app[KEY_LOGIN_THRESHOLD] = login_threshold
|
|
||||||
|
|
||||||
app.on_startup.append(ban_startup)
|
app.on_startup.append(ban_startup)
|
||||||
|
|
||||||
|
@ -149,7 +150,7 @@ class IpBan:
|
||||||
self.banned_at = banned_at or datetime.utcnow()
|
self.banned_at = banned_at or datetime.utcnow()
|
||||||
|
|
||||||
|
|
||||||
def load_ip_bans_config(path: str):
|
async def async_load_ip_bans_config(hass: HomeAssistant, path: str):
|
||||||
"""Load list of banned IPs from config file."""
|
"""Load list of banned IPs from config file."""
|
||||||
ip_list = []
|
ip_list = []
|
||||||
|
|
||||||
|
@ -157,7 +158,7 @@ def load_ip_bans_config(path: str):
|
||||||
return ip_list
|
return ip_list
|
||||||
|
|
||||||
try:
|
try:
|
||||||
list_ = load_yaml_config_file(path)
|
list_ = await hass.async_add_executor_job(load_yaml_config_file, path)
|
||||||
except HomeAssistantError as err:
|
except HomeAssistantError as err:
|
||||||
_LOGGER.error('Unable to load %s: %s', path, str(err))
|
_LOGGER.error('Unable to load %s: %s', path, str(err))
|
||||||
return ip_list
|
return ip_list
|
||||||
|
|
|
@ -33,8 +33,4 @@ def setup_real_ip(app, use_x_forwarded_for, trusted_proxies):
|
||||||
|
|
||||||
return await handler(request)
|
return await handler(request)
|
||||||
|
|
||||||
async def app_startup(app):
|
app.middlewares.append(real_ip_middleware)
|
||||||
"""Initialize bans when app starts up."""
|
|
||||||
app.middlewares.append(real_ip_middleware)
|
|
||||||
|
|
||||||
app.on_startup.append(app_startup)
|
|
||||||
|
|
|
@ -9,7 +9,15 @@ from homeassistant.components.websocket_api.http import URL
|
||||||
from homeassistant.components.websocket_api.auth import (
|
from homeassistant.components.websocket_api.auth import (
|
||||||
TYPE_AUTH, TYPE_AUTH_OK, TYPE_AUTH_REQUIRED)
|
TYPE_AUTH, TYPE_AUTH_OK, TYPE_AUTH_REQUIRED)
|
||||||
|
|
||||||
from tests.common import MockUser, CLIENT_ID
|
from tests.common import MockUser, CLIENT_ID, mock_coro
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(autouse=True)
|
||||||
|
def prevent_io():
|
||||||
|
"""Fixture to prevent certain I/O from happening."""
|
||||||
|
with patch('homeassistant.components.http.ban.async_load_ip_bans_config',
|
||||||
|
side_effect=lambda *args: mock_coro([])):
|
||||||
|
yield
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
|
|
|
@ -16,6 +16,9 @@ from homeassistant.components.http.ban import (
|
||||||
|
|
||||||
from . import mock_real_ip
|
from . import mock_real_ip
|
||||||
|
|
||||||
|
from tests.common import mock_coro
|
||||||
|
|
||||||
|
|
||||||
BANNED_IPS = ['200.201.202.203', '100.64.0.2']
|
BANNED_IPS = ['200.201.202.203', '100.64.0.2']
|
||||||
|
|
||||||
|
|
||||||
|
@ -25,9 +28,9 @@ async def test_access_from_banned_ip(hass, aiohttp_client):
|
||||||
setup_bans(hass, app, 5)
|
setup_bans(hass, app, 5)
|
||||||
set_real_ip = mock_real_ip(app)
|
set_real_ip = mock_real_ip(app)
|
||||||
|
|
||||||
with patch('homeassistant.components.http.ban.load_ip_bans_config',
|
with patch('homeassistant.components.http.ban.async_load_ip_bans_config',
|
||||||
return_value=[IpBan(banned_ip) for banned_ip
|
return_value=mock_coro([IpBan(banned_ip) for banned_ip
|
||||||
in BANNED_IPS]):
|
in BANNED_IPS])):
|
||||||
client = await aiohttp_client(app)
|
client = await aiohttp_client(app)
|
||||||
|
|
||||||
for remote_addr in BANNED_IPS:
|
for remote_addr in BANNED_IPS:
|
||||||
|
@ -71,9 +74,9 @@ async def test_ip_bans_file_creation(hass, aiohttp_client):
|
||||||
setup_bans(hass, app, 1)
|
setup_bans(hass, app, 1)
|
||||||
mock_real_ip(app)("200.201.202.204")
|
mock_real_ip(app)("200.201.202.204")
|
||||||
|
|
||||||
with patch('homeassistant.components.http.ban.load_ip_bans_config',
|
with patch('homeassistant.components.http.ban.async_load_ip_bans_config',
|
||||||
return_value=[IpBan(banned_ip) for banned_ip
|
return_value=mock_coro([IpBan(banned_ip) for banned_ip
|
||||||
in BANNED_IPS]):
|
in BANNED_IPS])):
|
||||||
client = await aiohttp_client(app)
|
client = await aiohttp_client(app)
|
||||||
|
|
||||||
m = mock_open()
|
m = mock_open()
|
||||||
|
|
Loading…
Reference in New Issue