parent
ae9e3d83d7
commit
d1a621601d
42 changed files with 307 additions and 473 deletions
|
@ -78,11 +78,6 @@ class AuthManager:
|
|||
hass, self._async_create_login_flow,
|
||||
self._async_finish_login_flow)
|
||||
|
||||
@property
|
||||
def active(self) -> bool:
|
||||
"""Return if any auth providers are registered."""
|
||||
return bool(self._providers)
|
||||
|
||||
@property
|
||||
def support_legacy(self) -> bool:
|
||||
"""
|
||||
|
|
|
@ -14,6 +14,8 @@ from homeassistant.util.yaml import load_yaml, dump
|
|||
DOMAIN = 'config'
|
||||
DEPENDENCIES = ['http']
|
||||
SECTIONS = (
|
||||
'auth',
|
||||
'auth_provider_homeassistant',
|
||||
'automation',
|
||||
'config_entries',
|
||||
'core',
|
||||
|
@ -58,10 +60,6 @@ async def async_setup(hass, config):
|
|||
|
||||
tasks = [setup_panel(panel_name) for panel_name in SECTIONS]
|
||||
|
||||
if hass.auth.active:
|
||||
tasks.append(setup_panel('auth'))
|
||||
tasks.append(setup_panel('auth_provider_homeassistant'))
|
||||
|
||||
for panel_name in ON_DEMAND:
|
||||
if panel_name in hass.config.components:
|
||||
tasks.append(setup_panel(panel_name))
|
||||
|
|
|
@ -238,7 +238,7 @@ async def async_setup(hass, config):
|
|||
if os.path.isdir(local):
|
||||
hass.http.register_static_path("/local", local, not is_dev)
|
||||
|
||||
index_view = IndexView(repo_path, js_version, hass.auth.active)
|
||||
index_view = IndexView(repo_path, js_version)
|
||||
hass.http.register_view(index_view)
|
||||
hass.http.register_view(AuthorizeView(repo_path, js_version))
|
||||
|
||||
|
@ -364,11 +364,10 @@ class IndexView(HomeAssistantView):
|
|||
requires_auth = False
|
||||
extra_urls = ['/states', '/states/{extra}']
|
||||
|
||||
def __init__(self, repo_path, js_option, auth_active):
|
||||
def __init__(self, repo_path, js_option):
|
||||
"""Initialize the frontend view."""
|
||||
self.repo_path = repo_path
|
||||
self.js_option = js_option
|
||||
self.auth_active = auth_active
|
||||
self._template_cache = {}
|
||||
|
||||
def get_template(self, latest):
|
||||
|
@ -415,8 +414,6 @@ class IndexView(HomeAssistantView):
|
|||
# do not try to auto connect on load
|
||||
no_auth = '0'
|
||||
|
||||
use_oauth = '1' if self.auth_active else '0'
|
||||
|
||||
template = await hass.async_add_job(self.get_template, latest)
|
||||
|
||||
extra_key = DATA_EXTRA_HTML_URL if latest else DATA_EXTRA_HTML_URL_ES5
|
||||
|
@ -425,7 +422,7 @@ class IndexView(HomeAssistantView):
|
|||
no_auth=no_auth,
|
||||
theme_color=MANIFEST_JSON['theme_color'],
|
||||
extra_urls=hass.data[extra_key],
|
||||
use_oauth=use_oauth
|
||||
use_oauth='1'
|
||||
)
|
||||
|
||||
return web.Response(text=template.render(**template_params),
|
||||
|
|
|
@ -213,13 +213,7 @@ async def async_setup(hass, config):
|
|||
embed_iframe=True,
|
||||
)
|
||||
|
||||
# Temporary. No refresh token tells supervisor to use API password.
|
||||
if hass.auth.active:
|
||||
token = refresh_token.token
|
||||
else:
|
||||
token = None
|
||||
|
||||
await hassio.update_hass_api(config.get('http', {}), token)
|
||||
await hassio.update_hass_api(config.get('http', {}), refresh_token.token)
|
||||
|
||||
if 'homeassistant' in config:
|
||||
await hassio.update_hass_timezone(config['homeassistant'])
|
||||
|
|
|
@ -200,14 +200,13 @@ class HomeAssistantHTTP:
|
|||
if is_ban_enabled:
|
||||
setup_bans(hass, app, login_threshold)
|
||||
|
||||
if hass.auth.active and hass.auth.support_legacy:
|
||||
if hass.auth.support_legacy:
|
||||
_LOGGER.warning(
|
||||
"legacy_api_password support has been enabled. If you don't "
|
||||
"require it, remove the 'api_password' from your http config.")
|
||||
|
||||
setup_auth(app, trusted_networks, hass.auth.active,
|
||||
support_legacy=hass.auth.support_legacy,
|
||||
api_password=api_password)
|
||||
setup_auth(app, trusted_networks,
|
||||
api_password if hass.auth.support_legacy else None)
|
||||
|
||||
setup_cors(app, cors_origins)
|
||||
|
||||
|
|
|
@ -41,29 +41,26 @@ def async_sign_path(hass, refresh_token_id, path, expiration):
|
|||
|
||||
|
||||
@callback
|
||||
def setup_auth(app, trusted_networks, use_auth,
|
||||
support_legacy=False, api_password=None):
|
||||
def setup_auth(app, trusted_networks, api_password):
|
||||
"""Create auth middleware for the app."""
|
||||
old_auth_warning = set()
|
||||
legacy_auth = (not use_auth or support_legacy) and api_password
|
||||
|
||||
@middleware
|
||||
async def auth_middleware(request, handler):
|
||||
"""Authenticate as middleware."""
|
||||
authenticated = False
|
||||
|
||||
if use_auth and (HTTP_HEADER_HA_AUTH in request.headers or
|
||||
if (HTTP_HEADER_HA_AUTH in request.headers or
|
||||
DATA_API_PASSWORD in request.query):
|
||||
if request.path not in old_auth_warning:
|
||||
_LOGGER.log(
|
||||
logging.INFO if support_legacy else logging.WARNING,
|
||||
logging.INFO if api_password else logging.WARNING,
|
||||
'You need to use a bearer token to access %s from %s',
|
||||
request.path, request[KEY_REAL_IP])
|
||||
old_auth_warning.add(request.path)
|
||||
|
||||
if (hdrs.AUTHORIZATION in request.headers and
|
||||
await async_validate_auth_header(
|
||||
request, api_password if legacy_auth else None)):
|
||||
await async_validate_auth_header(request, api_password)):
|
||||
# it included both use_auth and api_password Basic auth
|
||||
authenticated = True
|
||||
|
||||
|
@ -73,7 +70,7 @@ def setup_auth(app, trusted_networks, use_auth,
|
|||
await async_validate_signed_request(request)):
|
||||
authenticated = True
|
||||
|
||||
elif (legacy_auth and HTTP_HEADER_HA_AUTH in request.headers and
|
||||
elif (api_password and HTTP_HEADER_HA_AUTH in request.headers and
|
||||
hmac.compare_digest(
|
||||
api_password.encode('utf-8'),
|
||||
request.headers[HTTP_HEADER_HA_AUTH].encode('utf-8'))):
|
||||
|
@ -82,7 +79,7 @@ def setup_auth(app, trusted_networks, use_auth,
|
|||
request['hass_user'] = await legacy_api_password.async_get_user(
|
||||
app['hass'])
|
||||
|
||||
elif (legacy_auth and DATA_API_PASSWORD in request.query and
|
||||
elif (api_password and DATA_API_PASSWORD in request.query and
|
||||
hmac.compare_digest(
|
||||
api_password.encode('utf-8'),
|
||||
request.query[DATA_API_PASSWORD].encode('utf-8'))):
|
||||
|
@ -98,11 +95,6 @@ def setup_auth(app, trusted_networks, use_auth,
|
|||
break
|
||||
authenticated = True
|
||||
|
||||
elif not use_auth and api_password is None:
|
||||
# If neither password nor auth_providers set,
|
||||
# just always set authenticated=True
|
||||
authenticated = True
|
||||
|
||||
request[KEY_AUTHENTICATED] = authenticated
|
||||
return await handler(request)
|
||||
|
||||
|
|
|
@ -242,7 +242,7 @@ class HTML5PushCallbackView(HomeAssistantView):
|
|||
# 2b. If decode is unsuccessful, return a 401.
|
||||
|
||||
target_check = jwt.decode(token, verify=False)
|
||||
if target_check[ATTR_TARGET] in self.registrations:
|
||||
if target_check.get(ATTR_TARGET) in self.registrations:
|
||||
possible_target = self.registrations[target_check[ATTR_TARGET]]
|
||||
key = possible_target[ATTR_SUBSCRIPTION][ATTR_KEYS][ATTR_AUTH]
|
||||
try:
|
||||
|
|
|
@ -14,10 +14,6 @@ STORAGE_VERSION = 1
|
|||
@callback
|
||||
def async_is_onboarded(hass):
|
||||
"""Return if Home Assistant has been onboarded."""
|
||||
# Temporarily: if auth not active, always set onboarded=True
|
||||
if not hass.auth.active:
|
||||
return True
|
||||
|
||||
return hass.data.get(DOMAIN, True)
|
||||
|
||||
|
||||
|
|
|
@ -69,7 +69,7 @@ class AuthPhase:
|
|||
self._send_message(auth_invalid_message(error_msg))
|
||||
raise Disconnect
|
||||
|
||||
if self._hass.auth.active and 'access_token' in msg:
|
||||
if 'access_token' in msg:
|
||||
self._logger.debug("Received access_token")
|
||||
refresh_token = \
|
||||
await self._hass.auth.async_validate_access_token(
|
||||
|
@ -78,8 +78,7 @@ class AuthPhase:
|
|||
return await self._async_finish_auth(
|
||||
refresh_token.user, refresh_token)
|
||||
|
||||
elif ((not self._hass.auth.active or self._hass.auth.support_legacy)
|
||||
and 'api_password' in msg):
|
||||
elif self._hass.auth.support_legacy and 'api_password' in msg:
|
||||
self._logger.debug("Received api_password")
|
||||
if validate_password(self._request, msg['api_password']):
|
||||
return await self._async_finish_auth(None, None)
|
||||
|
|
|
@ -21,7 +21,7 @@ NPR_NEWS_MP3_URL = "https://pd.npr.org/anon.npr-mp3/npr/news/newscast.mp3"
|
|||
|
||||
|
||||
@pytest.fixture
|
||||
def alexa_client(loop, hass, aiohttp_client):
|
||||
def alexa_client(loop, hass, hass_client):
|
||||
"""Initialize a Home Assistant server for testing this module."""
|
||||
@callback
|
||||
def mock_service(call):
|
||||
|
@ -49,7 +49,7 @@ def alexa_client(loop, hass, aiohttp_client):
|
|||
},
|
||||
}
|
||||
}))
|
||||
return loop.run_until_complete(aiohttp_client(hass.http.app))
|
||||
return loop.run_until_complete(hass_client())
|
||||
|
||||
|
||||
def _flash_briefing_req(client, briefing_id):
|
||||
|
|
|
@ -114,7 +114,6 @@ async def test_ws_current_user(hass, hass_ws_client, hass_access_token):
|
|||
user.credentials.append(credential)
|
||||
assert len(user.credentials) == 1
|
||||
|
||||
with patch('homeassistant.auth.AuthManager.active', return_value=True):
|
||||
client = await hass_ws_client(hass, hass_access_token)
|
||||
|
||||
await client.send_json({
|
||||
|
|
|
@ -5,11 +5,11 @@ from homeassistant.bootstrap import async_setup_component
|
|||
import homeassistant.util.dt as dt_util
|
||||
|
||||
|
||||
async def test_events_http_api(hass, aiohttp_client):
|
||||
async def test_events_http_api(hass, hass_client):
|
||||
"""Test the calendar demo view."""
|
||||
await async_setup_component(hass, 'calendar',
|
||||
{'calendar': {'platform': 'demo'}})
|
||||
client = await aiohttp_client(hass.http.app)
|
||||
client = await hass_client()
|
||||
response = await client.get(
|
||||
'/api/calendars/calendar.calendar_2')
|
||||
assert response.status == 400
|
||||
|
@ -24,11 +24,11 @@ async def test_events_http_api(hass, aiohttp_client):
|
|||
assert events[0]['title'] == 'Future Event'
|
||||
|
||||
|
||||
async def test_calendars_http_api(hass, aiohttp_client):
|
||||
async def test_calendars_http_api(hass, hass_client):
|
||||
"""Test the calendar demo view."""
|
||||
await async_setup_component(hass, 'calendar',
|
||||
{'calendar': {'platform': 'demo'}})
|
||||
client = await aiohttp_client(hass.http.app)
|
||||
client = await hass_client()
|
||||
response = await client.get('/api/calendars')
|
||||
assert response.status == 200
|
||||
data = await response.json()
|
||||
|
|
|
@ -7,7 +7,7 @@ from homeassistant.setup import async_setup_component
|
|||
|
||||
|
||||
@asyncio.coroutine
|
||||
def test_fetching_url(aioclient_mock, hass, aiohttp_client):
|
||||
def test_fetching_url(aioclient_mock, hass, hass_client):
|
||||
"""Test that it fetches the given url."""
|
||||
aioclient_mock.get('http://example.com', text='hello world')
|
||||
|
||||
|
@ -20,7 +20,7 @@ def test_fetching_url(aioclient_mock, hass, aiohttp_client):
|
|||
'password': 'pass'
|
||||
}})
|
||||
|
||||
client = yield from aiohttp_client(hass.http.app)
|
||||
client = yield from hass_client()
|
||||
|
||||
resp = yield from client.get('/api/camera_proxy/camera.config_test')
|
||||
|
||||
|
@ -34,7 +34,7 @@ def test_fetching_url(aioclient_mock, hass, aiohttp_client):
|
|||
|
||||
|
||||
@asyncio.coroutine
|
||||
def test_fetching_without_verify_ssl(aioclient_mock, hass, aiohttp_client):
|
||||
def test_fetching_without_verify_ssl(aioclient_mock, hass, hass_client):
|
||||
"""Test that it fetches the given url when ssl verify is off."""
|
||||
aioclient_mock.get('https://example.com', text='hello world')
|
||||
|
||||
|
@ -48,7 +48,7 @@ def test_fetching_without_verify_ssl(aioclient_mock, hass, aiohttp_client):
|
|||
'verify_ssl': 'false',
|
||||
}})
|
||||
|
||||
client = yield from aiohttp_client(hass.http.app)
|
||||
client = yield from hass_client()
|
||||
|
||||
resp = yield from client.get('/api/camera_proxy/camera.config_test')
|
||||
|
||||
|
@ -56,7 +56,7 @@ def test_fetching_without_verify_ssl(aioclient_mock, hass, aiohttp_client):
|
|||
|
||||
|
||||
@asyncio.coroutine
|
||||
def test_fetching_url_with_verify_ssl(aioclient_mock, hass, aiohttp_client):
|
||||
def test_fetching_url_with_verify_ssl(aioclient_mock, hass, hass_client):
|
||||
"""Test that it fetches the given url when ssl verify is explicitly on."""
|
||||
aioclient_mock.get('https://example.com', text='hello world')
|
||||
|
||||
|
@ -70,7 +70,7 @@ def test_fetching_url_with_verify_ssl(aioclient_mock, hass, aiohttp_client):
|
|||
'verify_ssl': 'true',
|
||||
}})
|
||||
|
||||
client = yield from aiohttp_client(hass.http.app)
|
||||
client = yield from hass_client()
|
||||
|
||||
resp = yield from client.get('/api/camera_proxy/camera.config_test')
|
||||
|
||||
|
@ -78,7 +78,7 @@ def test_fetching_url_with_verify_ssl(aioclient_mock, hass, aiohttp_client):
|
|||
|
||||
|
||||
@asyncio.coroutine
|
||||
def test_limit_refetch(aioclient_mock, hass, aiohttp_client):
|
||||
def test_limit_refetch(aioclient_mock, hass, hass_client):
|
||||
"""Test that it fetches the given url."""
|
||||
aioclient_mock.get('http://example.com/5a', text='hello world')
|
||||
aioclient_mock.get('http://example.com/10a', text='hello world')
|
||||
|
@ -94,7 +94,7 @@ def test_limit_refetch(aioclient_mock, hass, aiohttp_client):
|
|||
'limit_refetch_to_url_change': True,
|
||||
}})
|
||||
|
||||
client = yield from aiohttp_client(hass.http.app)
|
||||
client = yield from hass_client()
|
||||
|
||||
resp = yield from client.get('/api/camera_proxy/camera.config_test')
|
||||
|
||||
|
@ -139,7 +139,7 @@ def test_limit_refetch(aioclient_mock, hass, aiohttp_client):
|
|||
|
||||
|
||||
@asyncio.coroutine
|
||||
def test_camera_content_type(aioclient_mock, hass, aiohttp_client):
|
||||
def test_camera_content_type(aioclient_mock, hass, hass_client):
|
||||
"""Test generic camera with custom content_type."""
|
||||
svg_image = '<some image>'
|
||||
urlsvg = 'https://upload.wikimedia.org/wikipedia/commons/0/02/SVG_logo.svg'
|
||||
|
@ -158,7 +158,7 @@ def test_camera_content_type(aioclient_mock, hass, aiohttp_client):
|
|||
yield from async_setup_component(hass, 'camera', {
|
||||
'camera': [cam_config_svg, cam_config_normal]})
|
||||
|
||||
client = yield from aiohttp_client(hass.http.app)
|
||||
client = yield from hass_client()
|
||||
|
||||
resp_1 = yield from client.get('/api/camera_proxy/camera.config_test_svg')
|
||||
assert aioclient_mock.call_count == 1
|
||||
|
|
|
@ -11,7 +11,7 @@ from tests.common import mock_registry
|
|||
|
||||
|
||||
@asyncio.coroutine
|
||||
def test_loading_file(hass, aiohttp_client):
|
||||
def test_loading_file(hass, hass_client):
|
||||
"""Test that it loads image from disk."""
|
||||
mock_registry(hass)
|
||||
|
||||
|
@ -24,7 +24,7 @@ def test_loading_file(hass, aiohttp_client):
|
|||
'file_path': 'mock.file',
|
||||
}})
|
||||
|
||||
client = yield from aiohttp_client(hass.http.app)
|
||||
client = yield from hass_client()
|
||||
|
||||
m_open = mock.mock_open(read_data=b'hello')
|
||||
with mock.patch(
|
||||
|
@ -56,7 +56,7 @@ def test_file_not_readable(hass, caplog):
|
|||
|
||||
|
||||
@asyncio.coroutine
|
||||
def test_camera_content_type(hass, aiohttp_client):
|
||||
def test_camera_content_type(hass, hass_client):
|
||||
"""Test local_file camera content_type."""
|
||||
cam_config_jpg = {
|
||||
'name': 'test_jpg',
|
||||
|
@ -83,7 +83,7 @@ def test_camera_content_type(hass, aiohttp_client):
|
|||
'camera': [cam_config_jpg, cam_config_png,
|
||||
cam_config_svg, cam_config_noext]})
|
||||
|
||||
client = yield from aiohttp_client(hass.http.app)
|
||||
client = yield from hass_client()
|
||||
|
||||
image = 'hello'
|
||||
m_open = mock.mock_open(read_data=image.encode())
|
||||
|
|
|
@ -52,10 +52,10 @@ def setup_api(hass):
|
|||
|
||||
|
||||
@pytest.fixture
|
||||
def cloud_client(hass, aiohttp_client):
|
||||
def cloud_client(hass, hass_client):
|
||||
"""Fixture that can fetch from the cloud client."""
|
||||
with patch('homeassistant.components.cloud.Cloud.write_user_info'):
|
||||
yield hass.loop.run_until_complete(aiohttp_client(hass.http.app))
|
||||
yield hass.loop.run_until_complete(hass_client())
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
"""Test config entries API."""
|
||||
from unittest.mock import PropertyMock, patch
|
||||
|
||||
import pytest
|
||||
|
||||
from homeassistant.auth import models as auth_models
|
||||
|
@ -9,14 +7,6 @@ from homeassistant.components.config import auth as auth_config
|
|||
from tests.common import MockGroup, MockUser, CLIENT_ID
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def auth_active(hass):
|
||||
"""Mock that auth is active."""
|
||||
with patch('homeassistant.auth.AuthManager.active',
|
||||
PropertyMock(return_value=True)):
|
||||
yield
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def setup_config(hass, aiohttp_client):
|
||||
"""Fixture that sets up the auth provider homeassistant module."""
|
||||
|
@ -37,7 +27,7 @@ async def test_list_requires_owner(hass, hass_ws_client, hass_access_token):
|
|||
assert result['error']['code'] == 'unauthorized'
|
||||
|
||||
|
||||
async def test_list(hass, hass_ws_client):
|
||||
async def test_list(hass, hass_ws_client, hass_admin_user):
|
||||
"""Test get users."""
|
||||
group = MockGroup().add_to_hass(hass)
|
||||
|
||||
|
@ -80,8 +70,17 @@ async def test_list(hass, hass_ws_client):
|
|||
result = await client.receive_json()
|
||||
assert result['success'], result
|
||||
data = result['result']
|
||||
assert len(data) == 3
|
||||
assert len(data) == 4
|
||||
assert data[0] == {
|
||||
'id': hass_admin_user.id,
|
||||
'name': 'Mock User',
|
||||
'is_owner': False,
|
||||
'is_active': True,
|
||||
'system_generated': False,
|
||||
'group_ids': [group.id for group in hass_admin_user.groups],
|
||||
'credentials': []
|
||||
}
|
||||
assert data[1] == {
|
||||
'id': owner.id,
|
||||
'name': 'Test Owner',
|
||||
'is_owner': True,
|
||||
|
@ -90,7 +89,7 @@ async def test_list(hass, hass_ws_client):
|
|||
'group_ids': [group.id for group in owner.groups],
|
||||
'credentials': [{'type': 'homeassistant'}]
|
||||
}
|
||||
assert data[1] == {
|
||||
assert data[2] == {
|
||||
'id': system.id,
|
||||
'name': 'Test Hass.io',
|
||||
'is_owner': False,
|
||||
|
@ -99,7 +98,7 @@ async def test_list(hass, hass_ws_client):
|
|||
'group_ids': [],
|
||||
'credentials': [],
|
||||
}
|
||||
assert data[2] == {
|
||||
assert data[3] == {
|
||||
'id': inactive.id,
|
||||
'name': 'Inactive User',
|
||||
'is_owner': False,
|
||||
|
|
|
@ -6,12 +6,12 @@ from homeassistant.bootstrap import async_setup_component
|
|||
from homeassistant.components import config
|
||||
|
||||
|
||||
async def test_get_device_config(hass, aiohttp_client):
|
||||
async def test_get_device_config(hass, hass_client):
|
||||
"""Test getting device config."""
|
||||
with patch.object(config, 'SECTIONS', ['automation']):
|
||||
await async_setup_component(hass, 'config', {})
|
||||
|
||||
client = await aiohttp_client(hass.http.app)
|
||||
client = await hass_client()
|
||||
|
||||
def mock_read(path):
|
||||
"""Mock reading data."""
|
||||
|
@ -34,12 +34,12 @@ async def test_get_device_config(hass, aiohttp_client):
|
|||
assert result == {'id': 'moon'}
|
||||
|
||||
|
||||
async def test_update_device_config(hass, aiohttp_client):
|
||||
async def test_update_device_config(hass, hass_client):
|
||||
"""Test updating device config."""
|
||||
with patch.object(config, 'SECTIONS', ['automation']):
|
||||
await async_setup_component(hass, 'config', {})
|
||||
|
||||
client = await aiohttp_client(hass.http.app)
|
||||
client = await hass_client()
|
||||
|
||||
orig_data = [
|
||||
{
|
||||
|
@ -83,12 +83,12 @@ async def test_update_device_config(hass, aiohttp_client):
|
|||
assert written[0] == orig_data
|
||||
|
||||
|
||||
async def test_bad_formatted_automations(hass, aiohttp_client):
|
||||
async def test_bad_formatted_automations(hass, hass_client):
|
||||
"""Test that we handle automations without ID."""
|
||||
with patch.object(config, 'SECTIONS', ['automation']):
|
||||
await async_setup_component(hass, 'config', {})
|
||||
|
||||
client = await aiohttp_client(hass.http.app)
|
||||
client = await hass_client()
|
||||
|
||||
orig_data = [
|
||||
{
|
||||
|
|
|
@ -23,11 +23,11 @@ def mock_test_component(hass):
|
|||
|
||||
|
||||
@pytest.fixture
|
||||
def client(hass, aiohttp_client):
|
||||
def client(hass, hass_client):
|
||||
"""Fixture that can interact with the config manager API."""
|
||||
hass.loop.run_until_complete(async_setup_component(hass, 'http', {}))
|
||||
hass.loop.run_until_complete(config_entries.async_setup(hass))
|
||||
yield hass.loop.run_until_complete(aiohttp_client(hass.http.app))
|
||||
yield hass.loop.run_until_complete(hass_client())
|
||||
|
||||
|
||||
@asyncio.coroutine
|
||||
|
|
|
@ -8,14 +8,14 @@ from tests.common import mock_coro
|
|||
|
||||
|
||||
@asyncio.coroutine
|
||||
def test_validate_config_ok(hass, aiohttp_client):
|
||||
def test_validate_config_ok(hass, hass_client):
|
||||
"""Test checking config."""
|
||||
with patch.object(config, 'SECTIONS', ['core']):
|
||||
yield from async_setup_component(hass, 'config', {})
|
||||
|
||||
yield from asyncio.sleep(0.1, loop=hass.loop)
|
||||
|
||||
client = yield from aiohttp_client(hass.http.app)
|
||||
client = yield from hass_client()
|
||||
|
||||
with patch(
|
||||
'homeassistant.components.config.core.async_check_ha_config_file',
|
||||
|
|
|
@ -9,12 +9,12 @@ from homeassistant.config import DATA_CUSTOMIZE
|
|||
|
||||
|
||||
@asyncio.coroutine
|
||||
def test_get_entity(hass, aiohttp_client):
|
||||
def test_get_entity(hass, hass_client):
|
||||
"""Test getting entity."""
|
||||
with patch.object(config, 'SECTIONS', ['customize']):
|
||||
yield from async_setup_component(hass, 'config', {})
|
||||
|
||||
client = yield from aiohttp_client(hass.http.app)
|
||||
client = yield from hass_client()
|
||||
|
||||
def mock_read(path):
|
||||
"""Mock reading data."""
|
||||
|
@ -38,12 +38,12 @@ def test_get_entity(hass, aiohttp_client):
|
|||
|
||||
|
||||
@asyncio.coroutine
|
||||
def test_update_entity(hass, aiohttp_client):
|
||||
def test_update_entity(hass, hass_client):
|
||||
"""Test updating entity."""
|
||||
with patch.object(config, 'SECTIONS', ['customize']):
|
||||
yield from async_setup_component(hass, 'config', {})
|
||||
|
||||
client = yield from aiohttp_client(hass.http.app)
|
||||
client = yield from hass_client()
|
||||
|
||||
orig_data = {
|
||||
'hello.beer': {
|
||||
|
@ -89,12 +89,12 @@ def test_update_entity(hass, aiohttp_client):
|
|||
|
||||
|
||||
@asyncio.coroutine
|
||||
def test_update_entity_invalid_key(hass, aiohttp_client):
|
||||
def test_update_entity_invalid_key(hass, hass_client):
|
||||
"""Test updating entity."""
|
||||
with patch.object(config, 'SECTIONS', ['customize']):
|
||||
yield from async_setup_component(hass, 'config', {})
|
||||
|
||||
client = yield from aiohttp_client(hass.http.app)
|
||||
client = yield from hass_client()
|
||||
|
||||
resp = yield from client.post(
|
||||
'/api/config/customize/config/not_entity', data=json.dumps({
|
||||
|
@ -105,12 +105,12 @@ def test_update_entity_invalid_key(hass, aiohttp_client):
|
|||
|
||||
|
||||
@asyncio.coroutine
|
||||
def test_update_entity_invalid_json(hass, aiohttp_client):
|
||||
def test_update_entity_invalid_json(hass, hass_client):
|
||||
"""Test updating entity."""
|
||||
with patch.object(config, 'SECTIONS', ['customize']):
|
||||
yield from async_setup_component(hass, 'config', {})
|
||||
|
||||
client = yield from aiohttp_client(hass.http.app)
|
||||
client = yield from hass_client()
|
||||
|
||||
resp = yield from client.post(
|
||||
'/api/config/customize/config/hello.beer', data='not json')
|
||||
|
|
|
@ -11,12 +11,12 @@ VIEW_NAME = 'api:config:group:config'
|
|||
|
||||
|
||||
@asyncio.coroutine
|
||||
def test_get_device_config(hass, aiohttp_client):
|
||||
def test_get_device_config(hass, hass_client):
|
||||
"""Test getting device config."""
|
||||
with patch.object(config, 'SECTIONS', ['group']):
|
||||
yield from async_setup_component(hass, 'config', {})
|
||||
|
||||
client = yield from aiohttp_client(hass.http.app)
|
||||
client = yield from hass_client()
|
||||
|
||||
def mock_read(path):
|
||||
"""Mock reading data."""
|
||||
|
@ -40,12 +40,12 @@ def test_get_device_config(hass, aiohttp_client):
|
|||
|
||||
|
||||
@asyncio.coroutine
|
||||
def test_update_device_config(hass, aiohttp_client):
|
||||
def test_update_device_config(hass, hass_client):
|
||||
"""Test updating device config."""
|
||||
with patch.object(config, 'SECTIONS', ['group']):
|
||||
yield from async_setup_component(hass, 'config', {})
|
||||
|
||||
client = yield from aiohttp_client(hass.http.app)
|
||||
client = yield from hass_client()
|
||||
|
||||
orig_data = {
|
||||
'hello.beer': {
|
||||
|
@ -89,12 +89,12 @@ def test_update_device_config(hass, aiohttp_client):
|
|||
|
||||
|
||||
@asyncio.coroutine
|
||||
def test_update_device_config_invalid_key(hass, aiohttp_client):
|
||||
def test_update_device_config_invalid_key(hass, hass_client):
|
||||
"""Test updating device config."""
|
||||
with patch.object(config, 'SECTIONS', ['group']):
|
||||
yield from async_setup_component(hass, 'config', {})
|
||||
|
||||
client = yield from aiohttp_client(hass.http.app)
|
||||
client = yield from hass_client()
|
||||
|
||||
resp = yield from client.post(
|
||||
'/api/config/group/config/not a slug', data=json.dumps({
|
||||
|
@ -105,12 +105,12 @@ def test_update_device_config_invalid_key(hass, aiohttp_client):
|
|||
|
||||
|
||||
@asyncio.coroutine
|
||||
def test_update_device_config_invalid_data(hass, aiohttp_client):
|
||||
def test_update_device_config_invalid_data(hass, hass_client):
|
||||
"""Test updating device config."""
|
||||
with patch.object(config, 'SECTIONS', ['group']):
|
||||
yield from async_setup_component(hass, 'config', {})
|
||||
|
||||
client = yield from aiohttp_client(hass.http.app)
|
||||
client = yield from hass_client()
|
||||
|
||||
resp = yield from client.post(
|
||||
'/api/config/group/config/hello_beer', data=json.dumps({
|
||||
|
@ -121,12 +121,12 @@ def test_update_device_config_invalid_data(hass, aiohttp_client):
|
|||
|
||||
|
||||
@asyncio.coroutine
|
||||
def test_update_device_config_invalid_json(hass, aiohttp_client):
|
||||
def test_update_device_config_invalid_json(hass, hass_client):
|
||||
"""Test updating device config."""
|
||||
with patch.object(config, 'SECTIONS', ['group']):
|
||||
yield from async_setup_component(hass, 'config', {})
|
||||
|
||||
client = yield from aiohttp_client(hass.http.app)
|
||||
client = yield from hass_client()
|
||||
|
||||
resp = yield from client.post(
|
||||
'/api/config/group/config/hello_beer', data='not json')
|
||||
|
|
|
@ -34,13 +34,13 @@ def test_setup_check_env_works(hass, loop):
|
|||
|
||||
|
||||
@asyncio.coroutine
|
||||
def test_get_suites(hass, aiohttp_client):
|
||||
def test_get_suites(hass, hass_client):
|
||||
"""Test getting suites."""
|
||||
with patch.dict(os.environ, {'FORCE_HASSBIAN': '1'}), \
|
||||
patch.object(config, 'SECTIONS', ['hassbian']):
|
||||
yield from async_setup_component(hass, 'config', {})
|
||||
|
||||
client = yield from aiohttp_client(hass.http.app)
|
||||
client = yield from hass_client()
|
||||
resp = yield from client.get('/api/config/hassbian/suites')
|
||||
assert resp.status == 200
|
||||
result = yield from resp.json()
|
||||
|
@ -53,13 +53,13 @@ def test_get_suites(hass, aiohttp_client):
|
|||
|
||||
|
||||
@asyncio.coroutine
|
||||
def test_install_suite(hass, aiohttp_client):
|
||||
def test_install_suite(hass, hass_client):
|
||||
"""Test getting suites."""
|
||||
with patch.dict(os.environ, {'FORCE_HASSBIAN': '1'}), \
|
||||
patch.object(config, 'SECTIONS', ['hassbian']):
|
||||
yield from async_setup_component(hass, 'config', {})
|
||||
|
||||
client = yield from aiohttp_client(hass.http.app)
|
||||
client = yield from hass_client()
|
||||
resp = yield from client.post(
|
||||
'/api/config/hassbian/suites/openzwave/install')
|
||||
assert resp.status == 200
|
||||
|
|
|
@ -16,12 +16,12 @@ VIEW_NAME = 'api:config:zwave:device_config'
|
|||
|
||||
|
||||
@pytest.fixture
|
||||
def client(loop, hass, aiohttp_client):
|
||||
def client(loop, hass, hass_client):
|
||||
"""Client to communicate with Z-Wave config views."""
|
||||
with patch.object(config, 'SECTIONS', ['zwave']):
|
||||
loop.run_until_complete(async_setup_component(hass, 'config', {}))
|
||||
|
||||
return loop.run_until_complete(aiohttp_client(hass.http.app))
|
||||
return loop.run_until_complete(hass_client())
|
||||
|
||||
|
||||
@asyncio.coroutine
|
||||
|
|
|
@ -3,14 +3,12 @@ from unittest.mock import patch
|
|||
|
||||
import pytest
|
||||
|
||||
from homeassistant.auth.const import GROUP_ID_ADMIN, GROUP_ID_READ_ONLY
|
||||
from homeassistant.auth.providers import legacy_api_password, homeassistant
|
||||
from homeassistant.setup import async_setup_component
|
||||
from homeassistant.components.websocket_api.http import URL
|
||||
from homeassistant.components.websocket_api.auth import (
|
||||
TYPE_AUTH, TYPE_AUTH_OK, TYPE_AUTH_REQUIRED)
|
||||
|
||||
from tests.common import MockUser, CLIENT_ID, mock_coro
|
||||
from tests.common import mock_coro
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
|
@ -22,35 +20,15 @@ def prevent_io():
|
|||
|
||||
|
||||
@pytest.fixture
|
||||
def hass_ws_client(aiohttp_client):
|
||||
def hass_ws_client(aiohttp_client, hass_access_token):
|
||||
"""Websocket client fixture connected to websocket server."""
|
||||
async def create_client(hass, access_token=None):
|
||||
async def create_client(hass, access_token=hass_access_token):
|
||||
"""Create a websocket client."""
|
||||
assert await async_setup_component(hass, 'websocket_api')
|
||||
|
||||
client = await aiohttp_client(hass.http.app)
|
||||
|
||||
patches = []
|
||||
|
||||
if access_token is None:
|
||||
patches.append(patch(
|
||||
'homeassistant.auth.AuthManager.active', return_value=False))
|
||||
patches.append(patch(
|
||||
'homeassistant.auth.AuthManager.support_legacy',
|
||||
return_value=True))
|
||||
patches.append(patch(
|
||||
'homeassistant.components.websocket_api.auth.'
|
||||
'validate_password', return_value=True))
|
||||
else:
|
||||
patches.append(patch(
|
||||
'homeassistant.auth.AuthManager.active', return_value=True))
|
||||
patches.append(patch(
|
||||
'homeassistant.components.http.auth.setup_auth'))
|
||||
|
||||
for p in patches:
|
||||
p.start()
|
||||
|
||||
try:
|
||||
with patch('homeassistant.components.http.auth.setup_auth'):
|
||||
websocket = await client.ws_connect(URL)
|
||||
auth_resp = await websocket.receive_json()
|
||||
assert auth_resp['type'] == TYPE_AUTH_REQUIRED
|
||||
|
@ -69,76 +47,8 @@ def hass_ws_client(aiohttp_client):
|
|||
auth_ok = await websocket.receive_json()
|
||||
assert auth_ok['type'] == TYPE_AUTH_OK
|
||||
|
||||
finally:
|
||||
for p in patches:
|
||||
p.stop()
|
||||
|
||||
# wrap in client
|
||||
websocket.client = client
|
||||
return websocket
|
||||
|
||||
return create_client
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def hass_access_token(hass, hass_admin_user):
|
||||
"""Return an access token to access Home Assistant."""
|
||||
refresh_token = hass.loop.run_until_complete(
|
||||
hass.auth.async_create_refresh_token(hass_admin_user, CLIENT_ID))
|
||||
yield hass.auth.async_create_access_token(refresh_token)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def hass_owner_user(hass, local_auth):
|
||||
"""Return a Home Assistant admin user."""
|
||||
return MockUser(is_owner=True).add_to_hass(hass)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def hass_admin_user(hass, local_auth):
|
||||
"""Return a Home Assistant admin user."""
|
||||
admin_group = hass.loop.run_until_complete(hass.auth.async_get_group(
|
||||
GROUP_ID_ADMIN))
|
||||
return MockUser(groups=[admin_group]).add_to_hass(hass)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def hass_read_only_user(hass, local_auth):
|
||||
"""Return a Home Assistant read only user."""
|
||||
read_only_group = hass.loop.run_until_complete(hass.auth.async_get_group(
|
||||
GROUP_ID_READ_ONLY))
|
||||
return MockUser(groups=[read_only_group]).add_to_hass(hass)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def legacy_auth(hass):
|
||||
"""Load legacy API password provider."""
|
||||
prv = legacy_api_password.LegacyApiPasswordAuthProvider(
|
||||
hass, hass.auth._store, {
|
||||
'type': 'legacy_api_password'
|
||||
}
|
||||
)
|
||||
hass.auth._providers[(prv.type, prv.id)] = prv
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def local_auth(hass):
|
||||
"""Load local auth provider."""
|
||||
prv = homeassistant.HassAuthProvider(
|
||||
hass, hass.auth._store, {
|
||||
'type': 'homeassistant'
|
||||
}
|
||||
)
|
||||
hass.auth._providers[(prv.type, prv.id)] = prv
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def hass_client(hass, aiohttp_client, hass_access_token):
|
||||
"""Return an authenticated HTTP client."""
|
||||
async def auth_client():
|
||||
"""Return an authenticated client."""
|
||||
return await aiohttp_client(hass.http.app, headers={
|
||||
'Authorization': "Bearer {}".format(hass_access_token)
|
||||
})
|
||||
|
||||
return auth_client
|
||||
|
|
|
@ -19,7 +19,7 @@ def _url(data=None):
|
|||
|
||||
|
||||
@pytest.fixture
|
||||
def locative_client(loop, hass, aiohttp_client):
|
||||
def locative_client(loop, hass, hass_client):
|
||||
"""Locative mock client."""
|
||||
assert loop.run_until_complete(async_setup_component(
|
||||
hass, device_tracker.DOMAIN, {
|
||||
|
@ -29,7 +29,7 @@ def locative_client(loop, hass, aiohttp_client):
|
|||
}))
|
||||
|
||||
with patch('homeassistant.components.device_tracker.update_config'):
|
||||
yield loop.run_until_complete(aiohttp_client(hass.http.app))
|
||||
yield loop.run_until_complete(hass_client())
|
||||
|
||||
|
||||
@asyncio.coroutine
|
||||
|
|
|
@ -13,7 +13,7 @@ from homeassistant.components.device_tracker.meraki import URL
|
|||
|
||||
|
||||
@pytest.fixture
|
||||
def meraki_client(loop, hass, aiohttp_client):
|
||||
def meraki_client(loop, hass, hass_client):
|
||||
"""Meraki mock client."""
|
||||
assert loop.run_until_complete(async_setup_component(
|
||||
hass, device_tracker.DOMAIN, {
|
||||
|
@ -25,7 +25,7 @@ def meraki_client(loop, hass, aiohttp_client):
|
|||
}
|
||||
}))
|
||||
|
||||
yield loop.run_until_complete(aiohttp_client(hass.http.app))
|
||||
yield loop.run_until_complete(hass_client())
|
||||
|
||||
|
||||
@asyncio.coroutine
|
||||
|
|
|
@ -59,8 +59,16 @@ def mock_http_client_with_urls(hass, aiohttp_client):
|
|||
return hass.loop.run_until_complete(aiohttp_client(hass.http.app))
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_onboarded():
|
||||
"""Mock that we're onboarded."""
|
||||
with patch('homeassistant.components.onboarding.async_is_onboarded',
|
||||
return_value=True):
|
||||
yield
|
||||
|
||||
|
||||
@asyncio.coroutine
|
||||
def test_frontend_and_static(mock_http_client):
|
||||
def test_frontend_and_static(mock_http_client, mock_onboarded):
|
||||
"""Test if we can get the frontend."""
|
||||
resp = yield from mock_http_client.get('')
|
||||
assert resp.status == 200
|
||||
|
@ -220,7 +228,7 @@ async def test_missing_themes(hass, hass_ws_client):
|
|||
|
||||
|
||||
@asyncio.coroutine
|
||||
def test_extra_urls(mock_http_client_with_urls):
|
||||
def test_extra_urls(mock_http_client_with_urls, mock_onboarded):
|
||||
"""Test that extra urls are loaded."""
|
||||
resp = yield from mock_http_client_with_urls.get('/states?latest')
|
||||
assert resp.status == 200
|
||||
|
@ -229,7 +237,7 @@ def test_extra_urls(mock_http_client_with_urls):
|
|||
|
||||
|
||||
@asyncio.coroutine
|
||||
def test_extra_urls_es5(mock_http_client_with_urls):
|
||||
def test_extra_urls_es5(mock_http_client_with_urls, mock_onboarded):
|
||||
"""Test that es5 extra urls are loaded."""
|
||||
resp = yield from mock_http_client_with_urls.get('/states?es5')
|
||||
assert resp.status == 200
|
||||
|
@ -280,7 +288,7 @@ async def test_get_translations(hass, hass_ws_client):
|
|||
assert msg['result'] == {'resources': {'lang': 'nl'}}
|
||||
|
||||
|
||||
async def test_auth_load(mock_http_client):
|
||||
async def test_auth_load(mock_http_client, mock_onboarded):
|
||||
"""Test auth component loaded by default."""
|
||||
resp = await mock_http_client.get('/auth/providers')
|
||||
assert resp.status == 200
|
||||
|
|
|
@ -105,7 +105,7 @@ BEACON_EXIT_CAR = {
|
|||
|
||||
|
||||
@pytest.fixture
|
||||
def geofency_client(loop, hass, aiohttp_client):
|
||||
def geofency_client(loop, hass, hass_client):
|
||||
"""Geofency mock client."""
|
||||
assert loop.run_until_complete(async_setup_component(
|
||||
hass, DOMAIN, {
|
||||
|
@ -116,7 +116,7 @@ def geofency_client(loop, hass, aiohttp_client):
|
|||
loop.run_until_complete(hass.async_block_till_done())
|
||||
|
||||
with patch('homeassistant.components.device_tracker.update_config'):
|
||||
yield loop.run_until_complete(aiohttp_client(hass.http.app))
|
||||
yield loop.run_until_complete(hass_client())
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
|
|
|
@ -89,8 +89,7 @@ def test_setup_api_push_api_data_server_host(hass, aioclient_mock):
|
|||
async def test_setup_api_push_api_data_default(hass, aioclient_mock,
|
||||
hass_storage):
|
||||
"""Test setup with API push default data."""
|
||||
with patch.dict(os.environ, MOCK_ENVIRON), \
|
||||
patch('homeassistant.auth.AuthManager.active', return_value=True):
|
||||
with patch.dict(os.environ, MOCK_ENVIRON):
|
||||
result = await async_setup_component(hass, 'hassio', {
|
||||
'http': {},
|
||||
'hassio': {}
|
||||
|
@ -130,20 +129,6 @@ async def test_setup_adds_admin_group_to_user(hass, aioclient_mock,
|
|||
'version': 1
|
||||
}
|
||||
|
||||
with patch.dict(os.environ, MOCK_ENVIRON), \
|
||||
patch('homeassistant.auth.AuthManager.active', return_value=True):
|
||||
result = await async_setup_component(hass, 'hassio', {
|
||||
'http': {},
|
||||
'hassio': {}
|
||||
})
|
||||
assert result
|
||||
|
||||
assert user.is_admin
|
||||
|
||||
|
||||
async def test_setup_api_push_api_data_no_auth(hass, aioclient_mock,
|
||||
hass_storage):
|
||||
"""Test setup with API push default data."""
|
||||
with patch.dict(os.environ, MOCK_ENVIRON):
|
||||
result = await async_setup_component(hass, 'hassio', {
|
||||
'http': {},
|
||||
|
@ -151,11 +136,7 @@ async def test_setup_api_push_api_data_no_auth(hass, aioclient_mock,
|
|||
})
|
||||
assert result
|
||||
|
||||
assert aioclient_mock.call_count == 3
|
||||
assert not aioclient_mock.mock_calls[1][2]['ssl']
|
||||
assert aioclient_mock.mock_calls[1][2]['password'] is None
|
||||
assert aioclient_mock.mock_calls[1][2]['port'] == 8123
|
||||
assert aioclient_mock.mock_calls[1][2]['refresh_token'] is None
|
||||
assert user.is_admin
|
||||
|
||||
|
||||
async def test_setup_api_existing_hassio_user(hass, aioclient_mock,
|
||||
|
@ -169,8 +150,7 @@ async def test_setup_api_existing_hassio_user(hass, aioclient_mock,
|
|||
'hassio_user': user.id
|
||||
}
|
||||
}
|
||||
with patch.dict(os.environ, MOCK_ENVIRON), \
|
||||
patch('homeassistant.auth.AuthManager.active', return_value=True):
|
||||
with patch.dict(os.environ, MOCK_ENVIRON):
|
||||
result = await async_setup_component(hass, 'hassio', {
|
||||
'http': {},
|
||||
'hassio': {}
|
||||
|
|
|
@ -75,19 +75,10 @@ async def test_auth_middleware_loaded_by_default(hass):
|
|||
assert len(mock_setup.mock_calls) == 1
|
||||
|
||||
|
||||
async def test_access_without_password(app, aiohttp_client):
|
||||
"""Test access without password."""
|
||||
setup_auth(app, [], False, api_password=None)
|
||||
client = await aiohttp_client(app)
|
||||
|
||||
resp = await client.get('/')
|
||||
assert resp.status == 200
|
||||
|
||||
|
||||
async def test_access_with_password_in_header(app, aiohttp_client,
|
||||
legacy_auth, hass):
|
||||
"""Test access with password in header."""
|
||||
setup_auth(app, [], False, api_password=API_PASSWORD)
|
||||
setup_auth(app, [], api_password=API_PASSWORD)
|
||||
client = await aiohttp_client(app)
|
||||
user = await legacy_api_password.async_get_user(hass)
|
||||
|
||||
|
@ -107,7 +98,7 @@ async def test_access_with_password_in_header(app, aiohttp_client,
|
|||
async def test_access_with_password_in_query(app, aiohttp_client, legacy_auth,
|
||||
hass):
|
||||
"""Test access with password in URL."""
|
||||
setup_auth(app, [], False, api_password=API_PASSWORD)
|
||||
setup_auth(app, [], api_password=API_PASSWORD)
|
||||
client = await aiohttp_client(app)
|
||||
user = await legacy_api_password.async_get_user(hass)
|
||||
|
||||
|
@ -131,7 +122,7 @@ async def test_access_with_password_in_query(app, aiohttp_client, legacy_auth,
|
|||
|
||||
async def test_basic_auth_works(app, aiohttp_client, hass, legacy_auth):
|
||||
"""Test access with basic authentication."""
|
||||
setup_auth(app, [], False, api_password=API_PASSWORD)
|
||||
setup_auth(app, [], api_password=API_PASSWORD)
|
||||
client = await aiohttp_client(app)
|
||||
user = await legacy_api_password.async_get_user(hass)
|
||||
|
||||
|
@ -164,7 +155,7 @@ async def test_basic_auth_works(app, aiohttp_client, hass, legacy_auth):
|
|||
|
||||
async def test_access_with_trusted_ip(app2, aiohttp_client, hass_owner_user):
|
||||
"""Test access with an untrusted ip address."""
|
||||
setup_auth(app2, TRUSTED_NETWORKS, False, api_password='some-pass')
|
||||
setup_auth(app2, TRUSTED_NETWORKS, api_password='some-pass')
|
||||
|
||||
set_mock_ip = mock_real_ip(app2)
|
||||
client = await aiohttp_client(app2)
|
||||
|
@ -190,7 +181,7 @@ async def test_auth_active_access_with_access_token_in_header(
|
|||
hass, app, aiohttp_client, hass_access_token):
|
||||
"""Test access with access token in header."""
|
||||
token = hass_access_token
|
||||
setup_auth(app, [], True, api_password=None)
|
||||
setup_auth(app, [], api_password=None)
|
||||
client = await aiohttp_client(app)
|
||||
refresh_token = await hass.auth.async_validate_access_token(
|
||||
hass_access_token)
|
||||
|
@ -238,7 +229,7 @@ async def test_auth_active_access_with_access_token_in_header(
|
|||
async def test_auth_active_access_with_trusted_ip(app2, aiohttp_client,
|
||||
hass_owner_user):
|
||||
"""Test access with an untrusted ip address."""
|
||||
setup_auth(app2, TRUSTED_NETWORKS, True, api_password=None)
|
||||
setup_auth(app2, TRUSTED_NETWORKS, None)
|
||||
|
||||
set_mock_ip = mock_real_ip(app2)
|
||||
client = await aiohttp_client(app2)
|
||||
|
@ -260,31 +251,10 @@ async def test_auth_active_access_with_trusted_ip(app2, aiohttp_client,
|
|||
}
|
||||
|
||||
|
||||
async def test_auth_active_blocked_api_password_access(
|
||||
app, aiohttp_client, legacy_auth):
|
||||
"""Test access using api_password should be blocked when auth.active."""
|
||||
setup_auth(app, [], True, api_password=API_PASSWORD)
|
||||
client = await aiohttp_client(app)
|
||||
|
||||
req = await client.get(
|
||||
'/', headers={HTTP_HEADER_HA_AUTH: API_PASSWORD})
|
||||
assert req.status == 401
|
||||
|
||||
resp = await client.get('/', params={
|
||||
'api_password': API_PASSWORD
|
||||
})
|
||||
assert resp.status == 401
|
||||
|
||||
req = await client.get(
|
||||
'/',
|
||||
auth=BasicAuth('homeassistant', API_PASSWORD))
|
||||
assert req.status == 401
|
||||
|
||||
|
||||
async def test_auth_legacy_support_api_password_access(
|
||||
app, aiohttp_client, legacy_auth, hass):
|
||||
"""Test access using api_password if auth.support_legacy."""
|
||||
setup_auth(app, [], True, support_legacy=True, api_password=API_PASSWORD)
|
||||
setup_auth(app, [], API_PASSWORD)
|
||||
client = await aiohttp_client(app)
|
||||
user = await legacy_api_password.async_get_user(hass)
|
||||
|
||||
|
@ -320,7 +290,7 @@ async def test_auth_access_signed_path(
|
|||
"""Test access with signed url."""
|
||||
app.router.add_post('/', mock_handler)
|
||||
app.router.add_get('/another_path', mock_handler)
|
||||
setup_auth(app, [], True, api_password=None)
|
||||
setup_auth(app, [], None)
|
||||
client = await aiohttp_client(app)
|
||||
|
||||
refresh_token = await hass.auth.async_validate_access_token(
|
||||
|
|
|
@ -9,7 +9,7 @@ import homeassistant.components.mailbox as mailbox
|
|||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_http_client(hass, aiohttp_client):
|
||||
def mock_http_client(hass, hass_client):
|
||||
"""Start the Hass HTTP component."""
|
||||
config = {
|
||||
mailbox.DOMAIN: {
|
||||
|
@ -18,7 +18,7 @@ def mock_http_client(hass, aiohttp_client):
|
|||
}
|
||||
hass.loop.run_until_complete(
|
||||
async_setup_component(hass, mailbox.DOMAIN, config))
|
||||
return hass.loop.run_until_complete(aiohttp_client(hass.http.app))
|
||||
return hass.loop.run_until_complete(hass_client())
|
||||
|
||||
|
||||
@asyncio.coroutine
|
||||
|
|
|
@ -49,7 +49,7 @@ REGISTER_URL = '/api/notify.html5'
|
|||
PUBLISH_URL = '/api/notify.html5/callback'
|
||||
|
||||
|
||||
async def mock_client(hass, aiohttp_client, registrations=None):
|
||||
async def mock_client(hass, hass_client, registrations=None):
|
||||
"""Create a test client for HTML5 views."""
|
||||
if registrations is None:
|
||||
registrations = {}
|
||||
|
@ -62,7 +62,7 @@ async def mock_client(hass, aiohttp_client, registrations=None):
|
|||
}
|
||||
})
|
||||
|
||||
return await aiohttp_client(hass.http.app)
|
||||
return await hass_client()
|
||||
|
||||
|
||||
class TestHtml5Notify:
|
||||
|
@ -151,9 +151,9 @@ class TestHtml5Notify:
|
|||
assert mock_wp.mock_calls[4][2]['gcm_key'] is None
|
||||
|
||||
|
||||
async def test_registering_new_device_view(hass, aiohttp_client):
|
||||
async def test_registering_new_device_view(hass, hass_client):
|
||||
"""Test that the HTML view works."""
|
||||
client = await mock_client(hass, aiohttp_client)
|
||||
client = await mock_client(hass, hass_client)
|
||||
|
||||
with patch('homeassistant.components.notify.html5.save_json') as mock_save:
|
||||
resp = await client.post(REGISTER_URL, data=json.dumps(SUBSCRIPTION_1))
|
||||
|
@ -165,9 +165,9 @@ async def test_registering_new_device_view(hass, aiohttp_client):
|
|||
}
|
||||
|
||||
|
||||
async def test_registering_new_device_expiration_view(hass, aiohttp_client):
|
||||
async def test_registering_new_device_expiration_view(hass, hass_client):
|
||||
"""Test that the HTML view works."""
|
||||
client = await mock_client(hass, aiohttp_client)
|
||||
client = await mock_client(hass, hass_client)
|
||||
|
||||
with patch('homeassistant.components.notify.html5.save_json') as mock_save:
|
||||
resp = await client.post(REGISTER_URL, data=json.dumps(SUBSCRIPTION_4))
|
||||
|
@ -178,10 +178,10 @@ async def test_registering_new_device_expiration_view(hass, aiohttp_client):
|
|||
}
|
||||
|
||||
|
||||
async def test_registering_new_device_fails_view(hass, aiohttp_client):
|
||||
async def test_registering_new_device_fails_view(hass, hass_client):
|
||||
"""Test subs. are not altered when registering a new device fails."""
|
||||
registrations = {}
|
||||
client = await mock_client(hass, aiohttp_client, registrations)
|
||||
client = await mock_client(hass, hass_client, registrations)
|
||||
|
||||
with patch('homeassistant.components.notify.html5.save_json',
|
||||
side_effect=HomeAssistantError()):
|
||||
|
@ -191,10 +191,10 @@ async def test_registering_new_device_fails_view(hass, aiohttp_client):
|
|||
assert registrations == {}
|
||||
|
||||
|
||||
async def test_registering_existing_device_view(hass, aiohttp_client):
|
||||
async def test_registering_existing_device_view(hass, hass_client):
|
||||
"""Test subscription is updated when registering existing device."""
|
||||
registrations = {}
|
||||
client = await mock_client(hass, aiohttp_client, registrations)
|
||||
client = await mock_client(hass, hass_client, registrations)
|
||||
|
||||
with patch('homeassistant.components.notify.html5.save_json') as mock_save:
|
||||
await client.post(REGISTER_URL, data=json.dumps(SUBSCRIPTION_1))
|
||||
|
@ -209,10 +209,10 @@ async def test_registering_existing_device_view(hass, aiohttp_client):
|
|||
}
|
||||
|
||||
|
||||
async def test_registering_existing_device_fails_view(hass, aiohttp_client):
|
||||
async def test_registering_existing_device_fails_view(hass, hass_client):
|
||||
"""Test sub. is not updated when registering existing device fails."""
|
||||
registrations = {}
|
||||
client = await mock_client(hass, aiohttp_client, registrations)
|
||||
client = await mock_client(hass, hass_client, registrations)
|
||||
|
||||
with patch('homeassistant.components.notify.html5.save_json') as mock_save:
|
||||
await client.post(REGISTER_URL, data=json.dumps(SUBSCRIPTION_1))
|
||||
|
@ -225,9 +225,9 @@ async def test_registering_existing_device_fails_view(hass, aiohttp_client):
|
|||
}
|
||||
|
||||
|
||||
async def test_registering_new_device_validation(hass, aiohttp_client):
|
||||
async def test_registering_new_device_validation(hass, hass_client):
|
||||
"""Test various errors when registering a new device."""
|
||||
client = await mock_client(hass, aiohttp_client)
|
||||
client = await mock_client(hass, hass_client)
|
||||
|
||||
resp = await client.post(REGISTER_URL, data=json.dumps({
|
||||
'browser': 'invalid browser',
|
||||
|
@ -249,13 +249,13 @@ async def test_registering_new_device_validation(hass, aiohttp_client):
|
|||
assert resp.status == 400
|
||||
|
||||
|
||||
async def test_unregistering_device_view(hass, aiohttp_client):
|
||||
async def test_unregistering_device_view(hass, hass_client):
|
||||
"""Test that the HTML unregister view works."""
|
||||
registrations = {
|
||||
'some device': SUBSCRIPTION_1,
|
||||
'other device': SUBSCRIPTION_2,
|
||||
}
|
||||
client = await mock_client(hass, aiohttp_client, registrations)
|
||||
client = await mock_client(hass, hass_client, registrations)
|
||||
|
||||
with patch('homeassistant.components.notify.html5.save_json') as mock_save:
|
||||
resp = await client.delete(REGISTER_URL, data=json.dumps({
|
||||
|
@ -270,10 +270,10 @@ async def test_unregistering_device_view(hass, aiohttp_client):
|
|||
|
||||
|
||||
async def test_unregister_device_view_handle_unknown_subscription(
|
||||
hass, aiohttp_client):
|
||||
hass, hass_client):
|
||||
"""Test that the HTML unregister view handles unknown subscriptions."""
|
||||
registrations = {}
|
||||
client = await mock_client(hass, aiohttp_client, registrations)
|
||||
client = await mock_client(hass, hass_client, registrations)
|
||||
|
||||
with patch('homeassistant.components.notify.html5.save_json') as mock_save:
|
||||
resp = await client.delete(REGISTER_URL, data=json.dumps({
|
||||
|
@ -286,13 +286,13 @@ async def test_unregister_device_view_handle_unknown_subscription(
|
|||
|
||||
|
||||
async def test_unregistering_device_view_handles_save_error(
|
||||
hass, aiohttp_client):
|
||||
hass, hass_client):
|
||||
"""Test that the HTML unregister view handles save errors."""
|
||||
registrations = {
|
||||
'some device': SUBSCRIPTION_1,
|
||||
'other device': SUBSCRIPTION_2,
|
||||
}
|
||||
client = await mock_client(hass, aiohttp_client, registrations)
|
||||
client = await mock_client(hass, hass_client, registrations)
|
||||
|
||||
with patch('homeassistant.components.notify.html5.save_json',
|
||||
side_effect=HomeAssistantError()):
|
||||
|
@ -307,23 +307,23 @@ async def test_unregistering_device_view_handles_save_error(
|
|||
}
|
||||
|
||||
|
||||
async def test_callback_view_no_jwt(hass, aiohttp_client):
|
||||
async def test_callback_view_no_jwt(hass, hass_client):
|
||||
"""Test that the notification callback view works without JWT."""
|
||||
client = await mock_client(hass, aiohttp_client)
|
||||
client = await mock_client(hass, hass_client)
|
||||
resp = await client.post(PUBLISH_URL, data=json.dumps({
|
||||
'type': 'push',
|
||||
'tag': '3bc28d69-0921-41f1-ac6a-7a627ba0aa72'
|
||||
}))
|
||||
|
||||
assert resp.status == 401, resp.response
|
||||
assert resp.status == 401
|
||||
|
||||
|
||||
async def test_callback_view_with_jwt(hass, aiohttp_client):
|
||||
async def test_callback_view_with_jwt(hass, hass_client):
|
||||
"""Test that the notification callback view works with JWT."""
|
||||
registrations = {
|
||||
'device': SUBSCRIPTION_1
|
||||
}
|
||||
client = await mock_client(hass, aiohttp_client, registrations)
|
||||
client = await mock_client(hass, hass_client, registrations)
|
||||
|
||||
with patch('pywebpush.WebPusher') as mock_wp:
|
||||
await hass.services.async_call('notify', 'notify', {
|
||||
|
|
|
@ -38,7 +38,6 @@ async def test_setup_views_if_not_onboarded(hass):
|
|||
assert len(mock_setup.mock_calls) == 1
|
||||
assert onboarding.DOMAIN in hass.data
|
||||
|
||||
with patch('homeassistant.auth.AuthManager.active', return_value=True):
|
||||
assert not onboarding.async_is_onboarded(hass)
|
||||
|
||||
|
||||
|
@ -47,10 +46,6 @@ async def test_is_onboarded():
|
|||
hass = Mock()
|
||||
hass.data = {}
|
||||
|
||||
with patch('homeassistant.auth.AuthManager.active', return_value=False):
|
||||
assert onboarding.async_is_onboarded(hass)
|
||||
|
||||
with patch('homeassistant.auth.AuthManager.active', return_value=True):
|
||||
assert onboarding.async_is_onboarded(hass)
|
||||
|
||||
hass.data[onboarding.DOMAIN] = True
|
||||
|
|
|
@ -591,18 +591,18 @@ class TestComponentLogbook(unittest.TestCase):
|
|||
}, time_fired=event_time_fired)
|
||||
|
||||
|
||||
async def test_logbook_view(hass, aiohttp_client):
|
||||
async def test_logbook_view(hass, hass_client):
|
||||
"""Test the logbook view."""
|
||||
await hass.async_add_job(init_recorder_component, hass)
|
||||
await async_setup_component(hass, 'logbook', {})
|
||||
await hass.async_add_job(hass.data[recorder.DATA_INSTANCE].block_till_done)
|
||||
client = await aiohttp_client(hass.http.app)
|
||||
client = await hass_client()
|
||||
response = await client.get(
|
||||
'/api/logbook/{}'.format(dt_util.utcnow().isoformat()))
|
||||
assert response.status == 200
|
||||
|
||||
|
||||
async def test_logbook_view_period_entity(hass, aiohttp_client):
|
||||
async def test_logbook_view_period_entity(hass, hass_client):
|
||||
"""Test the logbook view with period and entity."""
|
||||
await hass.async_add_job(init_recorder_component, hass)
|
||||
await async_setup_component(hass, 'logbook', {})
|
||||
|
@ -617,7 +617,7 @@ async def test_logbook_view_period_entity(hass, aiohttp_client):
|
|||
await hass.async_block_till_done()
|
||||
await hass.async_add_job(hass.data[recorder.DATA_INSTANCE].block_till_done)
|
||||
|
||||
client = await aiohttp_client(hass.http.app)
|
||||
client = await hass_client()
|
||||
|
||||
# Today time 00:00:00
|
||||
start = dt_util.utcnow().date()
|
||||
|
|
|
@ -7,14 +7,14 @@ import homeassistant.components.prometheus as prometheus
|
|||
|
||||
|
||||
@pytest.fixture
|
||||
def prometheus_client(loop, hass, aiohttp_client):
|
||||
"""Initialize an aiohttp_client with Prometheus component."""
|
||||
def prometheus_client(loop, hass, hass_client):
|
||||
"""Initialize an hass_client with Prometheus component."""
|
||||
assert loop.run_until_complete(async_setup_component(
|
||||
hass,
|
||||
prometheus.DOMAIN,
|
||||
{prometheus.DOMAIN: {}},
|
||||
))
|
||||
return loop.run_until_complete(aiohttp_client(hass.http.app))
|
||||
return loop.run_until_complete(hass_client())
|
||||
|
||||
|
||||
@asyncio.coroutine
|
||||
|
|
|
@ -8,7 +8,7 @@ from homeassistant.setup import async_setup_component
|
|||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_http_client(loop, hass, aiohttp_client):
|
||||
def mock_http_client(loop, hass, hass_client):
|
||||
"""Set up test fixture."""
|
||||
config = {
|
||||
'rss_feed_template': {
|
||||
|
@ -21,7 +21,7 @@ def mock_http_client(loop, hass, aiohttp_client):
|
|||
loop.run_until_complete(async_setup_component(hass,
|
||||
'rss_feed_template',
|
||||
config))
|
||||
return loop.run_until_complete(aiohttp_client(hass.http.app))
|
||||
return loop.run_until_complete(hass_client())
|
||||
|
||||
|
||||
@asyncio.coroutine
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
import ctypes
|
||||
import os
|
||||
import shutil
|
||||
import json
|
||||
from unittest.mock import patch, PropertyMock
|
||||
|
||||
import pytest
|
||||
|
@ -14,7 +13,7 @@ from homeassistant.components.tts.demo import DemoProvider
|
|||
from homeassistant.components.media_player import (
|
||||
SERVICE_PLAY_MEDIA, MEDIA_TYPE_MUSIC, ATTR_MEDIA_CONTENT_ID,
|
||||
ATTR_MEDIA_CONTENT_TYPE, DOMAIN as DOMAIN_MP)
|
||||
from homeassistant.setup import setup_component
|
||||
from homeassistant.setup import setup_component, async_setup_component
|
||||
|
||||
from tests.common import (
|
||||
get_test_home_assistant, get_test_instance_port, assert_setup_component,
|
||||
|
@ -584,31 +583,32 @@ class TestTTS:
|
|||
assert req.status_code == 200
|
||||
assert req.content == demo_data
|
||||
|
||||
def test_setup_component_and_web_get_url(self):
|
||||
"""Set up the demo platform and receive wrong file from web."""
|
||||
|
||||
async def test_setup_component_and_web_get_url(hass, hass_client):
|
||||
"""Set up the demo platform and receive file from web."""
|
||||
config = {
|
||||
tts.DOMAIN: {
|
||||
'platform': 'demo',
|
||||
}
|
||||
}
|
||||
|
||||
with assert_setup_component(1, tts.DOMAIN):
|
||||
setup_component(self.hass, tts.DOMAIN, config)
|
||||
await async_setup_component(hass, tts.DOMAIN, config)
|
||||
|
||||
self.hass.start()
|
||||
client = await hass_client()
|
||||
|
||||
url = ("{}/api/tts_get_url").format(self.hass.config.api.base_url)
|
||||
url = "/api/tts_get_url"
|
||||
data = {'platform': 'demo',
|
||||
'message': "I person is on front of your door."}
|
||||
|
||||
req = requests.post(url, data=json.dumps(data))
|
||||
assert req.status_code == 200
|
||||
response = json.loads(req.text)
|
||||
assert response.get('url') == (("{}/api/tts_proxy/265944c108cbb00b2a62"
|
||||
"1be5930513e03a0bb2cd_en_-_demo.mp3")
|
||||
.format(self.hass.config.api.base_url))
|
||||
req = await client.post(url, json=data)
|
||||
assert req.status == 200
|
||||
response = await req.json()
|
||||
assert response.get('url') == \
|
||||
("{}/api/tts_proxy/265944c108cbb00b2a62"
|
||||
"1be5930513e03a0bb2cd_en_-_demo.mp3".format(hass.config.api.base_url))
|
||||
|
||||
def test_setup_component_and_web_get_url_bad_config(self):
|
||||
|
||||
async def test_setup_component_and_web_get_url_bad_config(hass, hass_client):
|
||||
"""Set up the demo platform and receive wrong file from web."""
|
||||
config = {
|
||||
tts.DOMAIN: {
|
||||
|
@ -616,13 +616,12 @@ class TestTTS:
|
|||
}
|
||||
}
|
||||
|
||||
with assert_setup_component(1, tts.DOMAIN):
|
||||
setup_component(self.hass, tts.DOMAIN, config)
|
||||
await async_setup_component(hass, tts.DOMAIN, config)
|
||||
|
||||
self.hass.start()
|
||||
client = await hass_client()
|
||||
|
||||
url = ("{}/api/tts_get_url").format(self.hass.config.api.base_url)
|
||||
url = "/api/tts_get_url"
|
||||
data = {'message': "I person is on front of your door."}
|
||||
|
||||
req = requests.post(url, data=data)
|
||||
assert req.status_code == 400
|
||||
req = await client.post(url, json=data)
|
||||
assert req.status == 400
|
||||
|
|
|
@ -13,7 +13,7 @@ from tests.common import mock_coro
|
|||
from . import API_PASSWORD
|
||||
|
||||
|
||||
async def test_auth_via_msg(no_auth_websocket_client):
|
||||
async def test_auth_via_msg(no_auth_websocket_client, legacy_auth):
|
||||
"""Test authenticating."""
|
||||
await no_auth_websocket_client.send_json({
|
||||
'type': TYPE_AUTH,
|
||||
|
@ -70,8 +70,6 @@ async def test_auth_active_with_token(hass, aiohttp_client, hass_access_token):
|
|||
client = await aiohttp_client(hass.http.app)
|
||||
|
||||
async with client.ws_connect(URL) as ws:
|
||||
with patch('homeassistant.auth.AuthManager.active') as auth_active:
|
||||
auth_active.return_value = True
|
||||
auth_msg = await ws.receive_json()
|
||||
assert auth_msg['type'] == TYPE_AUTH_REQUIRED
|
||||
|
||||
|
@ -99,8 +97,6 @@ async def test_auth_active_user_inactive(hass, aiohttp_client,
|
|||
client = await aiohttp_client(hass.http.app)
|
||||
|
||||
async with client.ws_connect(URL) as ws:
|
||||
with patch('homeassistant.auth.AuthManager.active') as auth_active:
|
||||
auth_active.return_value = True
|
||||
auth_msg = await ws.receive_json()
|
||||
assert auth_msg['type'] == TYPE_AUTH_REQUIRED
|
||||
|
||||
|
@ -124,8 +120,6 @@ async def test_auth_active_with_password_not_allow(hass, aiohttp_client):
|
|||
client = await aiohttp_client(hass.http.app)
|
||||
|
||||
async with client.ws_connect(URL) as ws:
|
||||
with patch('homeassistant.auth.AuthManager.active',
|
||||
return_value=True):
|
||||
auth_msg = await ws.receive_json()
|
||||
assert auth_msg['type'] == TYPE_AUTH_REQUIRED
|
||||
|
||||
|
@ -149,9 +143,7 @@ async def test_auth_legacy_support_with_password(hass, aiohttp_client):
|
|||
client = await aiohttp_client(hass.http.app)
|
||||
|
||||
async with client.ws_connect(URL) as ws:
|
||||
with patch('homeassistant.auth.AuthManager.active',
|
||||
return_value=True),\
|
||||
patch('homeassistant.auth.AuthManager.support_legacy',
|
||||
with patch('homeassistant.auth.AuthManager.support_legacy',
|
||||
return_value=True):
|
||||
auth_msg = await ws.receive_json()
|
||||
assert auth_msg['type'] == TYPE_AUTH_REQUIRED
|
||||
|
@ -176,8 +168,6 @@ async def test_auth_with_invalid_token(hass, aiohttp_client):
|
|||
client = await aiohttp_client(hass.http.app)
|
||||
|
||||
async with client.ws_connect(URL) as ws:
|
||||
with patch('homeassistant.auth.AuthManager.active') as auth_active:
|
||||
auth_active.return_value = True
|
||||
auth_msg = await ws.receive_json()
|
||||
assert auth_msg['type'] == TYPE_AUTH_REQUIRED
|
||||
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
"""Tests for WebSocket API commands."""
|
||||
from unittest.mock import patch
|
||||
|
||||
from async_timeout import timeout
|
||||
|
||||
from homeassistant.core import callback
|
||||
|
@ -201,8 +199,6 @@ async def test_call_service_context_with_user(hass, aiohttp_client,
|
|||
client = await aiohttp_client(hass.http.app)
|
||||
|
||||
async with client.ws_connect(URL) as ws:
|
||||
with patch('homeassistant.auth.AuthManager.active') as auth_active:
|
||||
auth_active.return_value = True
|
||||
auth_msg = await ws.receive_json()
|
||||
assert auth_msg['type'] == TYPE_AUTH_REQUIRED
|
||||
|
||||
|
@ -238,50 +234,6 @@ async def test_call_service_context_with_user(hass, aiohttp_client,
|
|||
assert call.context.user_id == refresh_token.user.id
|
||||
|
||||
|
||||
async def test_call_service_context_no_user(hass, aiohttp_client):
|
||||
"""Test that connection without user sets context."""
|
||||
assert await async_setup_component(hass, 'websocket_api', {
|
||||
'http': {
|
||||
'api_password': API_PASSWORD
|
||||
}
|
||||
})
|
||||
|
||||
calls = async_mock_service(hass, 'domain_test', 'test_service')
|
||||
client = await aiohttp_client(hass.http.app)
|
||||
|
||||
async with client.ws_connect(URL) as ws:
|
||||
auth_msg = await ws.receive_json()
|
||||
assert auth_msg['type'] == TYPE_AUTH_REQUIRED
|
||||
|
||||
await ws.send_json({
|
||||
'type': TYPE_AUTH,
|
||||
'api_password': API_PASSWORD
|
||||
})
|
||||
|
||||
auth_msg = await ws.receive_json()
|
||||
assert auth_msg['type'] == TYPE_AUTH_OK
|
||||
|
||||
await ws.send_json({
|
||||
'id': 5,
|
||||
'type': commands.TYPE_CALL_SERVICE,
|
||||
'domain': 'domain_test',
|
||||
'service': 'test_service',
|
||||
'service_data': {
|
||||
'hello': 'world'
|
||||
}
|
||||
})
|
||||
|
||||
msg = await ws.receive_json()
|
||||
assert msg['success']
|
||||
|
||||
assert len(calls) == 1
|
||||
call = calls[0]
|
||||
assert call.domain == 'domain_test'
|
||||
assert call.service == 'test_service'
|
||||
assert call.data == {'hello': 'world'}
|
||||
assert call.context.user_id is None
|
||||
|
||||
|
||||
async def test_subscribe_requires_admin(websocket_client, hass_admin_user):
|
||||
"""Test subscribing events without being admin."""
|
||||
hass_admin_user.groups = []
|
||||
|
|
|
@ -10,10 +10,12 @@ import requests_mock as _requests_mock
|
|||
|
||||
from homeassistant import util
|
||||
from homeassistant.util import location
|
||||
from homeassistant.auth.const import GROUP_ID_ADMIN, GROUP_ID_READ_ONLY
|
||||
from homeassistant.auth.providers import legacy_api_password, homeassistant
|
||||
|
||||
from tests.common import (
|
||||
async_test_home_assistant, INSTANCES, async_mock_mqtt_component, mock_coro,
|
||||
mock_storage as mock_storage)
|
||||
mock_storage as mock_storage, MockUser, CLIENT_ID)
|
||||
from tests.test_util.aiohttp import mock_aiohttp_client
|
||||
from tests.mock.zwave import MockNetwork, MockOption
|
||||
|
||||
|
@ -133,3 +135,67 @@ def mock_device_tracker_conf():
|
|||
side_effect=lambda *args: mock_coro(devices)
|
||||
):
|
||||
yield devices
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def hass_access_token(hass, hass_admin_user):
|
||||
"""Return an access token to access Home Assistant."""
|
||||
refresh_token = hass.loop.run_until_complete(
|
||||
hass.auth.async_create_refresh_token(hass_admin_user, CLIENT_ID))
|
||||
yield hass.auth.async_create_access_token(refresh_token)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def hass_owner_user(hass, local_auth):
|
||||
"""Return a Home Assistant admin user."""
|
||||
return MockUser(is_owner=True).add_to_hass(hass)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def hass_admin_user(hass, local_auth):
|
||||
"""Return a Home Assistant admin user."""
|
||||
admin_group = hass.loop.run_until_complete(hass.auth.async_get_group(
|
||||
GROUP_ID_ADMIN))
|
||||
return MockUser(groups=[admin_group]).add_to_hass(hass)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def hass_read_only_user(hass, local_auth):
|
||||
"""Return a Home Assistant read only user."""
|
||||
read_only_group = hass.loop.run_until_complete(hass.auth.async_get_group(
|
||||
GROUP_ID_READ_ONLY))
|
||||
return MockUser(groups=[read_only_group]).add_to_hass(hass)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def legacy_auth(hass):
|
||||
"""Load legacy API password provider."""
|
||||
prv = legacy_api_password.LegacyApiPasswordAuthProvider(
|
||||
hass, hass.auth._store, {
|
||||
'type': 'legacy_api_password'
|
||||
}
|
||||
)
|
||||
hass.auth._providers[(prv.type, prv.id)] = prv
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def local_auth(hass):
|
||||
"""Load local auth provider."""
|
||||
prv = homeassistant.HassAuthProvider(
|
||||
hass, hass.auth._store, {
|
||||
'type': 'homeassistant'
|
||||
}
|
||||
)
|
||||
hass.auth._providers[(prv.type, prv.id)] = prv
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def hass_client(hass, aiohttp_client, hass_access_token):
|
||||
"""Return an authenticated HTTP client."""
|
||||
async def auth_client():
|
||||
"""Return an authenticated client."""
|
||||
return await aiohttp_client(hass.http.app, headers={
|
||||
'Authorization': "Bearer {}".format(hass_access_token)
|
||||
})
|
||||
|
||||
return auth_client
|
||||
|
|
|
@ -14,7 +14,7 @@ from tests.common import get_test_home_assistant
|
|||
|
||||
|
||||
@pytest.fixture
|
||||
def camera_client(hass, aiohttp_client):
|
||||
def camera_client(hass, hass_client):
|
||||
"""Fixture to fetch camera streams."""
|
||||
assert hass.loop.run_until_complete(async_setup_component(hass, 'camera', {
|
||||
'camera': {
|
||||
|
@ -23,7 +23,7 @@ def camera_client(hass, aiohttp_client):
|
|||
'mjpeg_url': 'http://example.com/mjpeg_stream',
|
||||
}}))
|
||||
|
||||
yield hass.loop.run_until_complete(aiohttp_client(hass.http.app))
|
||||
yield hass.loop.run_until_complete(hass_client())
|
||||
|
||||
|
||||
class TestHelpersAiohttpClient(unittest.TestCase):
|
||||
|
|
|
@ -808,7 +808,6 @@ async def test_auth_provider_config(hass):
|
|||
assert len(hass.auth.auth_providers) == 2
|
||||
assert hass.auth.auth_providers[0].type == 'homeassistant'
|
||||
assert hass.auth.auth_providers[1].type == 'legacy_api_password'
|
||||
assert hass.auth.active is True
|
||||
assert len(hass.auth.auth_mfa_modules) == 2
|
||||
assert hass.auth.auth_mfa_modules[0].id == 'totp'
|
||||
assert hass.auth.auth_mfa_modules[1].id == 'second'
|
||||
|
@ -830,7 +829,6 @@ async def test_auth_provider_config_default(hass):
|
|||
|
||||
assert len(hass.auth.auth_providers) == 1
|
||||
assert hass.auth.auth_providers[0].type == 'homeassistant'
|
||||
assert hass.auth.active is True
|
||||
assert len(hass.auth.auth_mfa_modules) == 1
|
||||
assert hass.auth.auth_mfa_modules[0].id == 'totp'
|
||||
|
||||
|
@ -852,7 +850,6 @@ async def test_auth_provider_config_default_api_password(hass):
|
|||
assert len(hass.auth.auth_providers) == 2
|
||||
assert hass.auth.auth_providers[0].type == 'homeassistant'
|
||||
assert hass.auth.auth_providers[1].type == 'legacy_api_password'
|
||||
assert hass.auth.active is True
|
||||
|
||||
|
||||
async def test_auth_provider_config_default_trusted_networks(hass):
|
||||
|
@ -873,7 +870,6 @@ async def test_auth_provider_config_default_trusted_networks(hass):
|
|||
assert len(hass.auth.auth_providers) == 2
|
||||
assert hass.auth.auth_providers[0].type == 'homeassistant'
|
||||
assert hass.auth.auth_providers[1].type == 'trusted_networks'
|
||||
assert hass.auth.active is True
|
||||
|
||||
|
||||
async def test_disallowed_auth_provider_config(hass):
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue