Prefer HTTPStatus over int in HA view JSON functions (#56504)
* Prefer HTTPStatus over int in HA view JSON functions * Update zwave tests to not expect a fixed typo
This commit is contained in:
parent
39aaa383b3
commit
d8d34fdd3b
26 changed files with 191 additions and 190 deletions
|
@ -1,5 +1,6 @@
|
||||||
"""Rest API for Home Assistant."""
|
"""Rest API for Home Assistant."""
|
||||||
import asyncio
|
import asyncio
|
||||||
|
from http import HTTPStatus
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
|
@ -14,10 +15,6 @@ from homeassistant.components.http import HomeAssistantView
|
||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
EVENT_HOMEASSISTANT_STOP,
|
EVENT_HOMEASSISTANT_STOP,
|
||||||
EVENT_TIME_CHANGED,
|
EVENT_TIME_CHANGED,
|
||||||
HTTP_BAD_REQUEST,
|
|
||||||
HTTP_CREATED,
|
|
||||||
HTTP_NOT_FOUND,
|
|
||||||
HTTP_OK,
|
|
||||||
MATCH_ALL,
|
MATCH_ALL,
|
||||||
URL_API,
|
URL_API,
|
||||||
URL_API_COMPONENTS,
|
URL_API_COMPONENTS,
|
||||||
|
@ -231,7 +228,7 @@ class APIEntityStateView(HomeAssistantView):
|
||||||
state = request.app["hass"].states.get(entity_id)
|
state = request.app["hass"].states.get(entity_id)
|
||||||
if state:
|
if state:
|
||||||
return self.json(state)
|
return self.json(state)
|
||||||
return self.json_message("Entity not found.", HTTP_NOT_FOUND)
|
return self.json_message("Entity not found.", HTTPStatus.NOT_FOUND)
|
||||||
|
|
||||||
async def post(self, request, entity_id):
|
async def post(self, request, entity_id):
|
||||||
"""Update state of entity."""
|
"""Update state of entity."""
|
||||||
|
@ -241,12 +238,12 @@ class APIEntityStateView(HomeAssistantView):
|
||||||
try:
|
try:
|
||||||
data = await request.json()
|
data = await request.json()
|
||||||
except ValueError:
|
except ValueError:
|
||||||
return self.json_message("Invalid JSON specified.", HTTP_BAD_REQUEST)
|
return self.json_message("Invalid JSON specified.", HTTPStatus.BAD_REQUEST)
|
||||||
|
|
||||||
new_state = data.get("state")
|
new_state = data.get("state")
|
||||||
|
|
||||||
if new_state is None:
|
if new_state is None:
|
||||||
return self.json_message("No state specified.", HTTP_BAD_REQUEST)
|
return self.json_message("No state specified.", HTTPStatus.BAD_REQUEST)
|
||||||
|
|
||||||
attributes = data.get("attributes")
|
attributes = data.get("attributes")
|
||||||
force_update = data.get("force_update", False)
|
force_update = data.get("force_update", False)
|
||||||
|
@ -259,7 +256,7 @@ class APIEntityStateView(HomeAssistantView):
|
||||||
)
|
)
|
||||||
|
|
||||||
# Read the state back for our response
|
# Read the state back for our response
|
||||||
status_code = HTTP_CREATED if is_new_state else HTTP_OK
|
status_code = HTTPStatus.CREATED if is_new_state else HTTPStatus.OK
|
||||||
resp = self.json(hass.states.get(entity_id), status_code)
|
resp = self.json(hass.states.get(entity_id), status_code)
|
||||||
|
|
||||||
resp.headers.add("Location", f"/api/states/{entity_id}")
|
resp.headers.add("Location", f"/api/states/{entity_id}")
|
||||||
|
@ -273,7 +270,7 @@ class APIEntityStateView(HomeAssistantView):
|
||||||
raise Unauthorized(entity_id=entity_id)
|
raise Unauthorized(entity_id=entity_id)
|
||||||
if request.app["hass"].states.async_remove(entity_id):
|
if request.app["hass"].states.async_remove(entity_id):
|
||||||
return self.json_message("Entity removed.")
|
return self.json_message("Entity removed.")
|
||||||
return self.json_message("Entity not found.", HTTP_NOT_FOUND)
|
return self.json_message("Entity not found.", HTTPStatus.NOT_FOUND)
|
||||||
|
|
||||||
|
|
||||||
class APIEventListenersView(HomeAssistantView):
|
class APIEventListenersView(HomeAssistantView):
|
||||||
|
@ -303,12 +300,12 @@ class APIEventView(HomeAssistantView):
|
||||||
event_data = json.loads(body) if body else None
|
event_data = json.loads(body) if body else None
|
||||||
except ValueError:
|
except ValueError:
|
||||||
return self.json_message(
|
return self.json_message(
|
||||||
"Event data should be valid JSON.", HTTP_BAD_REQUEST
|
"Event data should be valid JSON.", HTTPStatus.BAD_REQUEST
|
||||||
)
|
)
|
||||||
|
|
||||||
if event_data is not None and not isinstance(event_data, dict):
|
if event_data is not None and not isinstance(event_data, dict):
|
||||||
return self.json_message(
|
return self.json_message(
|
||||||
"Event data should be a JSON object", HTTP_BAD_REQUEST
|
"Event data should be a JSON object", HTTPStatus.BAD_REQUEST
|
||||||
)
|
)
|
||||||
|
|
||||||
# Special case handling for event STATE_CHANGED
|
# Special case handling for event STATE_CHANGED
|
||||||
|
@ -355,7 +352,9 @@ class APIDomainServicesView(HomeAssistantView):
|
||||||
try:
|
try:
|
||||||
data = json.loads(body) if body else None
|
data = json.loads(body) if body else None
|
||||||
except ValueError:
|
except ValueError:
|
||||||
return self.json_message("Data should be valid JSON.", HTTP_BAD_REQUEST)
|
return self.json_message(
|
||||||
|
"Data should be valid JSON.", HTTPStatus.BAD_REQUEST
|
||||||
|
)
|
||||||
|
|
||||||
context = self.context(request)
|
context = self.context(request)
|
||||||
|
|
||||||
|
@ -403,7 +402,7 @@ class APITemplateView(HomeAssistantView):
|
||||||
return tpl.async_render(variables=data.get("variables"), parse_result=False)
|
return tpl.async_render(variables=data.get("variables"), parse_result=False)
|
||||||
except (ValueError, TemplateError) as ex:
|
except (ValueError, TemplateError) as ex:
|
||||||
return self.json_message(
|
return self.json_message(
|
||||||
f"Error rendering template: {ex}", HTTP_BAD_REQUEST
|
f"Error rendering template: {ex}", HTTPStatus.BAD_REQUEST
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -117,6 +117,7 @@ Result will be a long-lived access token:
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
|
from http import HTTPStatus
|
||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
from aiohttp import web
|
from aiohttp import web
|
||||||
|
@ -133,7 +134,7 @@ from homeassistant.components.http.auth import async_sign_path
|
||||||
from homeassistant.components.http.ban import log_invalid_auth
|
from homeassistant.components.http.ban import log_invalid_auth
|
||||||
from homeassistant.components.http.data_validator import RequestDataValidator
|
from homeassistant.components.http.data_validator import RequestDataValidator
|
||||||
from homeassistant.components.http.view import HomeAssistantView
|
from homeassistant.components.http.view import HomeAssistantView
|
||||||
from homeassistant.const import HTTP_BAD_REQUEST, HTTP_FORBIDDEN, HTTP_OK
|
from homeassistant.const import HTTP_OK
|
||||||
from homeassistant.core import HomeAssistant, callback
|
from homeassistant.core import HomeAssistant, callback
|
||||||
from homeassistant.loader import bind_hass
|
from homeassistant.loader import bind_hass
|
||||||
from homeassistant.util import dt as dt_util
|
from homeassistant.util import dt as dt_util
|
||||||
|
@ -259,7 +260,7 @@ class TokenView(HomeAssistantView):
|
||||||
return await self._async_handle_refresh_token(hass, data, request.remote)
|
return await self._async_handle_refresh_token(hass, data, request.remote)
|
||||||
|
|
||||||
return self.json(
|
return self.json(
|
||||||
{"error": "unsupported_grant_type"}, status_code=HTTP_BAD_REQUEST
|
{"error": "unsupported_grant_type"}, status_code=HTTPStatus.BAD_REQUEST
|
||||||
)
|
)
|
||||||
|
|
||||||
async def _async_handle_revoke_token(self, hass, data):
|
async def _async_handle_revoke_token(self, hass, data):
|
||||||
|
@ -289,7 +290,7 @@ class TokenView(HomeAssistantView):
|
||||||
if client_id is None or not indieauth.verify_client_id(client_id):
|
if client_id is None or not indieauth.verify_client_id(client_id):
|
||||||
return self.json(
|
return self.json(
|
||||||
{"error": "invalid_request", "error_description": "Invalid client id"},
|
{"error": "invalid_request", "error_description": "Invalid client id"},
|
||||||
status_code=HTTP_BAD_REQUEST,
|
status_code=HTTPStatus.BAD_REQUEST,
|
||||||
)
|
)
|
||||||
|
|
||||||
code = data.get("code")
|
code = data.get("code")
|
||||||
|
@ -297,7 +298,7 @@ class TokenView(HomeAssistantView):
|
||||||
if code is None:
|
if code is None:
|
||||||
return self.json(
|
return self.json(
|
||||||
{"error": "invalid_request", "error_description": "Invalid code"},
|
{"error": "invalid_request", "error_description": "Invalid code"},
|
||||||
status_code=HTTP_BAD_REQUEST,
|
status_code=HTTPStatus.BAD_REQUEST,
|
||||||
)
|
)
|
||||||
|
|
||||||
credential = self._retrieve_auth(client_id, RESULT_TYPE_CREDENTIALS, code)
|
credential = self._retrieve_auth(client_id, RESULT_TYPE_CREDENTIALS, code)
|
||||||
|
@ -305,7 +306,7 @@ class TokenView(HomeAssistantView):
|
||||||
if credential is None or not isinstance(credential, Credentials):
|
if credential is None or not isinstance(credential, Credentials):
|
||||||
return self.json(
|
return self.json(
|
||||||
{"error": "invalid_request", "error_description": "Invalid code"},
|
{"error": "invalid_request", "error_description": "Invalid code"},
|
||||||
status_code=HTTP_BAD_REQUEST,
|
status_code=HTTPStatus.BAD_REQUEST,
|
||||||
)
|
)
|
||||||
|
|
||||||
user = await hass.auth.async_get_or_create_user(credential)
|
user = await hass.auth.async_get_or_create_user(credential)
|
||||||
|
@ -313,7 +314,7 @@ class TokenView(HomeAssistantView):
|
||||||
if not user.is_active:
|
if not user.is_active:
|
||||||
return self.json(
|
return self.json(
|
||||||
{"error": "access_denied", "error_description": "User is not active"},
|
{"error": "access_denied", "error_description": "User is not active"},
|
||||||
status_code=HTTP_FORBIDDEN,
|
status_code=HTTPStatus.FORBIDDEN,
|
||||||
)
|
)
|
||||||
|
|
||||||
refresh_token = await hass.auth.async_create_refresh_token(
|
refresh_token = await hass.auth.async_create_refresh_token(
|
||||||
|
@ -326,7 +327,7 @@ class TokenView(HomeAssistantView):
|
||||||
except InvalidAuthError as exc:
|
except InvalidAuthError as exc:
|
||||||
return self.json(
|
return self.json(
|
||||||
{"error": "access_denied", "error_description": str(exc)},
|
{"error": "access_denied", "error_description": str(exc)},
|
||||||
status_code=HTTP_FORBIDDEN,
|
status_code=HTTPStatus.FORBIDDEN,
|
||||||
)
|
)
|
||||||
|
|
||||||
return self.json(
|
return self.json(
|
||||||
|
@ -346,21 +347,27 @@ class TokenView(HomeAssistantView):
|
||||||
if client_id is not None and not indieauth.verify_client_id(client_id):
|
if client_id is not None and not indieauth.verify_client_id(client_id):
|
||||||
return self.json(
|
return self.json(
|
||||||
{"error": "invalid_request", "error_description": "Invalid client id"},
|
{"error": "invalid_request", "error_description": "Invalid client id"},
|
||||||
status_code=HTTP_BAD_REQUEST,
|
status_code=HTTPStatus.BAD_REQUEST,
|
||||||
)
|
)
|
||||||
|
|
||||||
token = data.get("refresh_token")
|
token = data.get("refresh_token")
|
||||||
|
|
||||||
if token is None:
|
if token is None:
|
||||||
return self.json({"error": "invalid_request"}, status_code=HTTP_BAD_REQUEST)
|
return self.json(
|
||||||
|
{"error": "invalid_request"}, status_code=HTTPStatus.BAD_REQUEST
|
||||||
|
)
|
||||||
|
|
||||||
refresh_token = await hass.auth.async_get_refresh_token_by_token(token)
|
refresh_token = await hass.auth.async_get_refresh_token_by_token(token)
|
||||||
|
|
||||||
if refresh_token is None:
|
if refresh_token is None:
|
||||||
return self.json({"error": "invalid_grant"}, status_code=HTTP_BAD_REQUEST)
|
return self.json(
|
||||||
|
{"error": "invalid_grant"}, status_code=HTTPStatus.BAD_REQUEST
|
||||||
|
)
|
||||||
|
|
||||||
if refresh_token.client_id != client_id:
|
if refresh_token.client_id != client_id:
|
||||||
return self.json({"error": "invalid_request"}, status_code=HTTP_BAD_REQUEST)
|
return self.json(
|
||||||
|
{"error": "invalid_request"}, status_code=HTTPStatus.BAD_REQUEST
|
||||||
|
)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
access_token = hass.auth.async_create_access_token(
|
access_token = hass.auth.async_create_access_token(
|
||||||
|
@ -369,7 +376,7 @@ class TokenView(HomeAssistantView):
|
||||||
except InvalidAuthError as exc:
|
except InvalidAuthError as exc:
|
||||||
return self.json(
|
return self.json(
|
||||||
{"error": "access_denied", "error_description": str(exc)},
|
{"error": "access_denied", "error_description": str(exc)},
|
||||||
status_code=HTTP_FORBIDDEN,
|
status_code=HTTPStatus.FORBIDDEN,
|
||||||
)
|
)
|
||||||
|
|
||||||
return self.json(
|
return self.json(
|
||||||
|
@ -404,7 +411,7 @@ class LinkUserView(HomeAssistantView):
|
||||||
)
|
)
|
||||||
|
|
||||||
if credentials is None:
|
if credentials is None:
|
||||||
return self.json_message("Invalid code", status_code=HTTP_BAD_REQUEST)
|
return self.json_message("Invalid code", status_code=HTTPStatus.BAD_REQUEST)
|
||||||
|
|
||||||
await hass.auth.async_link_user(user, credentials)
|
await hass.auth.async_link_user(user, credentials)
|
||||||
return self.json_message("User linked")
|
return self.json_message("User linked")
|
||||||
|
|
|
@ -66,6 +66,7 @@ associate with an credential if "type" set to "link_user" in
|
||||||
"version": 1
|
"version": 1
|
||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
|
from http import HTTPStatus
|
||||||
from ipaddress import ip_address
|
from ipaddress import ip_address
|
||||||
|
|
||||||
from aiohttp import web
|
from aiohttp import web
|
||||||
|
@ -80,11 +81,7 @@ from homeassistant.components.http.ban import (
|
||||||
)
|
)
|
||||||
from homeassistant.components.http.data_validator import RequestDataValidator
|
from homeassistant.components.http.data_validator import RequestDataValidator
|
||||||
from homeassistant.components.http.view import HomeAssistantView
|
from homeassistant.components.http.view import HomeAssistantView
|
||||||
from homeassistant.const import (
|
from homeassistant.const import HTTP_METHOD_NOT_ALLOWED
|
||||||
HTTP_BAD_REQUEST,
|
|
||||||
HTTP_METHOD_NOT_ALLOWED,
|
|
||||||
HTTP_NOT_FOUND,
|
|
||||||
)
|
|
||||||
|
|
||||||
from . import indieauth
|
from . import indieauth
|
||||||
|
|
||||||
|
@ -109,7 +106,7 @@ class AuthProvidersView(HomeAssistantView):
|
||||||
if not hass.components.onboarding.async_is_user_onboarded():
|
if not hass.components.onboarding.async_is_user_onboarded():
|
||||||
return self.json_message(
|
return self.json_message(
|
||||||
message="Onboarding not finished",
|
message="Onboarding not finished",
|
||||||
status_code=HTTP_BAD_REQUEST,
|
status_code=HTTPStatus.BAD_REQUEST,
|
||||||
message_code="onboarding_required",
|
message_code="onboarding_required",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -177,7 +174,7 @@ class LoginFlowIndexView(HomeAssistantView):
|
||||||
request.app["hass"], data["client_id"], data["redirect_uri"]
|
request.app["hass"], data["client_id"], data["redirect_uri"]
|
||||||
):
|
):
|
||||||
return self.json_message(
|
return self.json_message(
|
||||||
"invalid client id or redirect uri", HTTP_BAD_REQUEST
|
"invalid client id or redirect uri", HTTPStatus.BAD_REQUEST
|
||||||
)
|
)
|
||||||
|
|
||||||
if isinstance(data["handler"], list):
|
if isinstance(data["handler"], list):
|
||||||
|
@ -194,9 +191,11 @@ class LoginFlowIndexView(HomeAssistantView):
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
except data_entry_flow.UnknownHandler:
|
except data_entry_flow.UnknownHandler:
|
||||||
return self.json_message("Invalid handler specified", HTTP_NOT_FOUND)
|
return self.json_message("Invalid handler specified", HTTPStatus.NOT_FOUND)
|
||||||
except data_entry_flow.UnknownStep:
|
except data_entry_flow.UnknownStep:
|
||||||
return self.json_message("Handler does not support init", HTTP_BAD_REQUEST)
|
return self.json_message(
|
||||||
|
"Handler does not support init", HTTPStatus.BAD_REQUEST
|
||||||
|
)
|
||||||
|
|
||||||
if result["type"] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY:
|
if result["type"] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY:
|
||||||
await process_success_login(request)
|
await process_success_login(request)
|
||||||
|
@ -221,7 +220,7 @@ class LoginFlowResourceView(HomeAssistantView):
|
||||||
|
|
||||||
async def get(self, request):
|
async def get(self, request):
|
||||||
"""Do not allow getting status of a flow in progress."""
|
"""Do not allow getting status of a flow in progress."""
|
||||||
return self.json_message("Invalid flow specified", HTTP_NOT_FOUND)
|
return self.json_message("Invalid flow specified", HTTPStatus.NOT_FOUND)
|
||||||
|
|
||||||
@RequestDataValidator(vol.Schema({"client_id": str}, extra=vol.ALLOW_EXTRA))
|
@RequestDataValidator(vol.Schema({"client_id": str}, extra=vol.ALLOW_EXTRA))
|
||||||
@log_invalid_auth
|
@log_invalid_auth
|
||||||
|
@ -230,7 +229,7 @@ class LoginFlowResourceView(HomeAssistantView):
|
||||||
client_id = data.pop("client_id")
|
client_id = data.pop("client_id")
|
||||||
|
|
||||||
if not indieauth.verify_client_id(client_id):
|
if not indieauth.verify_client_id(client_id):
|
||||||
return self.json_message("Invalid client id", HTTP_BAD_REQUEST)
|
return self.json_message("Invalid client id", HTTPStatus.BAD_REQUEST)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# do not allow change ip during login flow
|
# do not allow change ip during login flow
|
||||||
|
@ -238,13 +237,15 @@ class LoginFlowResourceView(HomeAssistantView):
|
||||||
if flow["flow_id"] == flow_id and flow["context"][
|
if flow["flow_id"] == flow_id and flow["context"][
|
||||||
"ip_address"
|
"ip_address"
|
||||||
] != ip_address(request.remote):
|
] != ip_address(request.remote):
|
||||||
return self.json_message("IP address changed", HTTP_BAD_REQUEST)
|
return self.json_message(
|
||||||
|
"IP address changed", HTTPStatus.BAD_REQUEST
|
||||||
|
)
|
||||||
|
|
||||||
result = await self._flow_mgr.async_configure(flow_id, data)
|
result = await self._flow_mgr.async_configure(flow_id, data)
|
||||||
except data_entry_flow.UnknownFlow:
|
except data_entry_flow.UnknownFlow:
|
||||||
return self.json_message("Invalid flow specified", HTTP_NOT_FOUND)
|
return self.json_message("Invalid flow specified", HTTPStatus.NOT_FOUND)
|
||||||
except vol.Invalid:
|
except vol.Invalid:
|
||||||
return self.json_message("User input malformed", HTTP_BAD_REQUEST)
|
return self.json_message("User input malformed", HTTPStatus.BAD_REQUEST)
|
||||||
|
|
||||||
if result["type"] != data_entry_flow.RESULT_TYPE_CREATE_ENTRY:
|
if result["type"] != data_entry_flow.RESULT_TYPE_CREATE_ENTRY:
|
||||||
# @log_invalid_auth does not work here since it returns HTTP 200
|
# @log_invalid_auth does not work here since it returns HTTP 200
|
||||||
|
@ -266,6 +267,6 @@ class LoginFlowResourceView(HomeAssistantView):
|
||||||
try:
|
try:
|
||||||
self._flow_mgr.async_abort(flow_id)
|
self._flow_mgr.async_abort(flow_id)
|
||||||
except data_entry_flow.UnknownFlow:
|
except data_entry_flow.UnknownFlow:
|
||||||
return self.json_message("Invalid flow specified", HTTP_NOT_FOUND)
|
return self.json_message("Invalid flow specified", HTTPStatus.NOT_FOUND)
|
||||||
|
|
||||||
return self.json_message("Flow aborted")
|
return self.json_message("Flow aborted")
|
||||||
|
|
|
@ -1,17 +1,13 @@
|
||||||
"""Component to configure Home Assistant via an API."""
|
"""Component to configure Home Assistant via an API."""
|
||||||
import asyncio
|
import asyncio
|
||||||
|
from http import HTTPStatus
|
||||||
import importlib
|
import importlib
|
||||||
import os
|
import os
|
||||||
|
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
from homeassistant.components.http import HomeAssistantView
|
from homeassistant.components.http import HomeAssistantView
|
||||||
from homeassistant.const import (
|
from homeassistant.const import CONF_ID, EVENT_COMPONENT_LOADED
|
||||||
CONF_ID,
|
|
||||||
EVENT_COMPONENT_LOADED,
|
|
||||||
HTTP_BAD_REQUEST,
|
|
||||||
HTTP_NOT_FOUND,
|
|
||||||
)
|
|
||||||
from homeassistant.core import callback
|
from homeassistant.core import callback
|
||||||
from homeassistant.exceptions import HomeAssistantError
|
from homeassistant.exceptions import HomeAssistantError
|
||||||
from homeassistant.setup import ATTR_COMPONENT
|
from homeassistant.setup import ATTR_COMPONENT
|
||||||
|
@ -125,7 +121,7 @@ class BaseEditConfigView(HomeAssistantView):
|
||||||
value = self._get_value(hass, current, config_key)
|
value = self._get_value(hass, current, config_key)
|
||||||
|
|
||||||
if value is None:
|
if value is None:
|
||||||
return self.json_message("Resource not found", HTTP_NOT_FOUND)
|
return self.json_message("Resource not found", HTTPStatus.NOT_FOUND)
|
||||||
|
|
||||||
return self.json(value)
|
return self.json(value)
|
||||||
|
|
||||||
|
@ -134,12 +130,12 @@ class BaseEditConfigView(HomeAssistantView):
|
||||||
try:
|
try:
|
||||||
data = await request.json()
|
data = await request.json()
|
||||||
except ValueError:
|
except ValueError:
|
||||||
return self.json_message("Invalid JSON specified", HTTP_BAD_REQUEST)
|
return self.json_message("Invalid JSON specified", HTTPStatus.BAD_REQUEST)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.key_schema(config_key)
|
self.key_schema(config_key)
|
||||||
except vol.Invalid as err:
|
except vol.Invalid as err:
|
||||||
return self.json_message(f"Key malformed: {err}", HTTP_BAD_REQUEST)
|
return self.json_message(f"Key malformed: {err}", HTTPStatus.BAD_REQUEST)
|
||||||
|
|
||||||
hass = request.app["hass"]
|
hass = request.app["hass"]
|
||||||
|
|
||||||
|
@ -151,7 +147,9 @@ class BaseEditConfigView(HomeAssistantView):
|
||||||
else:
|
else:
|
||||||
self.data_schema(data)
|
self.data_schema(data)
|
||||||
except (vol.Invalid, HomeAssistantError) as err:
|
except (vol.Invalid, HomeAssistantError) as err:
|
||||||
return self.json_message(f"Message malformed: {err}", HTTP_BAD_REQUEST)
|
return self.json_message(
|
||||||
|
f"Message malformed: {err}", HTTPStatus.BAD_REQUEST
|
||||||
|
)
|
||||||
|
|
||||||
path = hass.config.path(self.path)
|
path = hass.config.path(self.path)
|
||||||
|
|
||||||
|
@ -177,7 +175,7 @@ class BaseEditConfigView(HomeAssistantView):
|
||||||
path = hass.config.path(self.path)
|
path = hass.config.path(self.path)
|
||||||
|
|
||||||
if value is None:
|
if value is None:
|
||||||
return self.json_message("Resource not found", HTTP_NOT_FOUND)
|
return self.json_message("Resource not found", HTTPStatus.BAD_REQUEST)
|
||||||
|
|
||||||
self._delete_value(hass, current, config_key)
|
self._delete_value(hass, current, config_key)
|
||||||
await hass.async_add_executor_job(_write, path, current)
|
await hass.async_add_executor_job(_write, path, current)
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
"""Http views to control the config manager."""
|
"""Http views to control the config manager."""
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from http import HTTPStatus
|
||||||
|
|
||||||
import aiohttp.web_exceptions
|
import aiohttp.web_exceptions
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
|
@ -8,7 +10,6 @@ from homeassistant import config_entries, data_entry_flow
|
||||||
from homeassistant.auth.permissions.const import CAT_CONFIG_ENTRIES, POLICY_EDIT
|
from homeassistant.auth.permissions.const import CAT_CONFIG_ENTRIES, POLICY_EDIT
|
||||||
from homeassistant.components import websocket_api
|
from homeassistant.components import websocket_api
|
||||||
from homeassistant.components.http import HomeAssistantView
|
from homeassistant.components.http import HomeAssistantView
|
||||||
from homeassistant.const import HTTP_FORBIDDEN, HTTP_NOT_FOUND
|
|
||||||
from homeassistant.core import HomeAssistant, callback
|
from homeassistant.core import HomeAssistant, callback
|
||||||
from homeassistant.exceptions import Unauthorized
|
from homeassistant.exceptions import Unauthorized
|
||||||
from homeassistant.helpers.data_entry_flow import (
|
from homeassistant.helpers.data_entry_flow import (
|
||||||
|
@ -69,7 +70,7 @@ class ConfigManagerEntryResourceView(HomeAssistantView):
|
||||||
try:
|
try:
|
||||||
result = await hass.config_entries.async_remove(entry_id)
|
result = await hass.config_entries.async_remove(entry_id)
|
||||||
except config_entries.UnknownEntry:
|
except config_entries.UnknownEntry:
|
||||||
return self.json_message("Invalid entry specified", HTTP_NOT_FOUND)
|
return self.json_message("Invalid entry specified", HTTPStatus.NOT_FOUND)
|
||||||
|
|
||||||
return self.json(result)
|
return self.json(result)
|
||||||
|
|
||||||
|
@ -90,9 +91,9 @@ class ConfigManagerEntryResourceReloadView(HomeAssistantView):
|
||||||
try:
|
try:
|
||||||
result = await hass.config_entries.async_reload(entry_id)
|
result = await hass.config_entries.async_reload(entry_id)
|
||||||
except config_entries.OperationNotAllowed:
|
except config_entries.OperationNotAllowed:
|
||||||
return self.json_message("Entry cannot be reloaded", HTTP_FORBIDDEN)
|
return self.json_message("Entry cannot be reloaded", HTTPStatus.FORBIDDEN)
|
||||||
except config_entries.UnknownEntry:
|
except config_entries.UnknownEntry:
|
||||||
return self.json_message("Invalid entry specified", HTTP_NOT_FOUND)
|
return self.json_message("Invalid entry specified", HTTPStatus.NOT_FOUND)
|
||||||
|
|
||||||
return self.json({"require_restart": not result})
|
return self.json({"require_restart": not result})
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
"""Provide configuration end points for Z-Wave."""
|
"""Provide configuration end points for Z-Wave."""
|
||||||
from collections import deque
|
from collections import deque
|
||||||
|
from http import HTTPStatus
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from aiohttp.web import Response
|
from aiohttp.web import Response
|
||||||
|
|
||||||
from homeassistant.components.http import HomeAssistantView
|
from homeassistant.components.http import HomeAssistantView
|
||||||
from homeassistant.components.zwave import DEVICE_CONFIG_SCHEMA_ENTRY, const
|
from homeassistant.components.zwave import DEVICE_CONFIG_SCHEMA_ENTRY, const
|
||||||
from homeassistant.const import HTTP_ACCEPTED, HTTP_BAD_REQUEST, HTTP_NOT_FOUND, HTTP_OK
|
from homeassistant.const import HTTP_BAD_REQUEST
|
||||||
import homeassistant.core as ha
|
import homeassistant.core as ha
|
||||||
import homeassistant.helpers.config_validation as cv
|
import homeassistant.helpers.config_validation as cv
|
||||||
|
|
||||||
|
@ -82,10 +83,12 @@ class ZWaveConfigWriteView(HomeAssistantView):
|
||||||
hass = request.app["hass"]
|
hass = request.app["hass"]
|
||||||
network = hass.data.get(const.DATA_NETWORK)
|
network = hass.data.get(const.DATA_NETWORK)
|
||||||
if network is None:
|
if network is None:
|
||||||
return self.json_message("No Z-Wave network data found", HTTP_NOT_FOUND)
|
return self.json_message(
|
||||||
|
"No Z-Wave network data found", HTTPStatus.NOT_FOUND
|
||||||
|
)
|
||||||
_LOGGER.info("Z-Wave configuration written to file")
|
_LOGGER.info("Z-Wave configuration written to file")
|
||||||
network.write_config()
|
network.write_config()
|
||||||
return self.json_message("Z-Wave configuration saved to file", HTTP_OK)
|
return self.json_message("Z-Wave configuration saved to file")
|
||||||
|
|
||||||
|
|
||||||
class ZWaveNodeValueView(HomeAssistantView):
|
class ZWaveNodeValueView(HomeAssistantView):
|
||||||
|
@ -131,7 +134,7 @@ class ZWaveNodeGroupView(HomeAssistantView):
|
||||||
network = hass.data.get(const.DATA_NETWORK)
|
network = hass.data.get(const.DATA_NETWORK)
|
||||||
node = network.nodes.get(nodeid)
|
node = network.nodes.get(nodeid)
|
||||||
if node is None:
|
if node is None:
|
||||||
return self.json_message("Node not found", HTTP_NOT_FOUND)
|
return self.json_message("Node not found", HTTPStatus.NOT_FOUND)
|
||||||
groupdata = node.groups
|
groupdata = node.groups
|
||||||
groups = {}
|
groups = {}
|
||||||
for key, value in groupdata.items():
|
for key, value in groupdata.items():
|
||||||
|
@ -158,7 +161,7 @@ class ZWaveNodeConfigView(HomeAssistantView):
|
||||||
network = hass.data.get(const.DATA_NETWORK)
|
network = hass.data.get(const.DATA_NETWORK)
|
||||||
node = network.nodes.get(nodeid)
|
node = network.nodes.get(nodeid)
|
||||||
if node is None:
|
if node is None:
|
||||||
return self.json_message("Node not found", HTTP_NOT_FOUND)
|
return self.json_message("Node not found", HTTPStatus.NOT_FOUND)
|
||||||
config = {}
|
config = {}
|
||||||
for value in node.get_values(
|
for value in node.get_values(
|
||||||
class_id=const.COMMAND_CLASS_CONFIGURATION
|
class_id=const.COMMAND_CLASS_CONFIGURATION
|
||||||
|
@ -189,7 +192,7 @@ class ZWaveUserCodeView(HomeAssistantView):
|
||||||
network = hass.data.get(const.DATA_NETWORK)
|
network = hass.data.get(const.DATA_NETWORK)
|
||||||
node = network.nodes.get(nodeid)
|
node = network.nodes.get(nodeid)
|
||||||
if node is None:
|
if node is None:
|
||||||
return self.json_message("Node not found", HTTP_NOT_FOUND)
|
return self.json_message("Node not found", HTTPStatus.NOT_FOUND)
|
||||||
usercodes = {}
|
usercodes = {}
|
||||||
if not node.has_command_class(const.COMMAND_CLASS_USER_CODE):
|
if not node.has_command_class(const.COMMAND_CLASS_USER_CODE):
|
||||||
return self.json(usercodes)
|
return self.json(usercodes)
|
||||||
|
@ -220,7 +223,7 @@ class ZWaveProtectionView(HomeAssistantView):
|
||||||
"""Get protection data."""
|
"""Get protection data."""
|
||||||
node = network.nodes.get(nodeid)
|
node = network.nodes.get(nodeid)
|
||||||
if node is None:
|
if node is None:
|
||||||
return self.json_message("Node not found", HTTP_NOT_FOUND)
|
return self.json_message("Node not found", HTTPStatus.NOT_FOUND)
|
||||||
protection_options = {}
|
protection_options = {}
|
||||||
if not node.has_command_class(const.COMMAND_CLASS_PROTECTION):
|
if not node.has_command_class(const.COMMAND_CLASS_PROTECTION):
|
||||||
return self.json(protection_options)
|
return self.json(protection_options)
|
||||||
|
@ -247,16 +250,16 @@ class ZWaveProtectionView(HomeAssistantView):
|
||||||
selection = protection_data["selection"]
|
selection = protection_data["selection"]
|
||||||
value_id = int(protection_data[const.ATTR_VALUE_ID])
|
value_id = int(protection_data[const.ATTR_VALUE_ID])
|
||||||
if node is None:
|
if node is None:
|
||||||
return self.json_message("Node not found", HTTP_NOT_FOUND)
|
return self.json_message("Node not found", HTTPStatus.NOT_FOUND)
|
||||||
if not node.has_command_class(const.COMMAND_CLASS_PROTECTION):
|
if not node.has_command_class(const.COMMAND_CLASS_PROTECTION):
|
||||||
return self.json_message(
|
return self.json_message(
|
||||||
"No protection commandclass on this node", HTTP_NOT_FOUND
|
"No protection commandclass on this node", HTTPStatus.NOT_FOUND
|
||||||
)
|
)
|
||||||
state = node.set_protection(value_id, selection)
|
state = node.set_protection(value_id, selection)
|
||||||
if not state:
|
if not state:
|
||||||
return self.json_message(
|
return self.json_message(
|
||||||
"Protection setting did not complete", HTTP_ACCEPTED
|
"Protection setting did not complete", HTTPStatus.ACCEPTED
|
||||||
)
|
)
|
||||||
return self.json_message("Protection setting succsessfully set", HTTP_OK)
|
return self.json_message("Protection setting successfully set")
|
||||||
|
|
||||||
return await hass.async_add_executor_job(_set_protection)
|
return await hass.async_add_executor_job(_set_protection)
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
"""Support for functionality to have conversations with Home Assistant."""
|
"""Support for functionality to have conversations with Home Assistant."""
|
||||||
|
from http import HTTPStatus
|
||||||
import logging
|
import logging
|
||||||
import re
|
import re
|
||||||
|
|
||||||
|
@ -7,7 +8,6 @@ import voluptuous as vol
|
||||||
from homeassistant import core
|
from homeassistant import core
|
||||||
from homeassistant.components import http, websocket_api
|
from homeassistant.components import http, websocket_api
|
||||||
from homeassistant.components.http.data_validator import RequestDataValidator
|
from homeassistant.components.http.data_validator import RequestDataValidator
|
||||||
from homeassistant.const import HTTP_INTERNAL_SERVER_ERROR
|
|
||||||
from homeassistant.helpers import config_validation as cv, intent
|
from homeassistant.helpers import config_validation as cv, intent
|
||||||
from homeassistant.loader import bind_hass
|
from homeassistant.loader import bind_hass
|
||||||
|
|
||||||
|
@ -146,7 +146,7 @@ class ConversationProcessView(http.HomeAssistantView):
|
||||||
"message": str(err),
|
"message": str(err),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
status_code=HTTP_INTERNAL_SERVER_ERROR,
|
status_code=HTTPStatus.INTERNAL_SERVER_ERROR,
|
||||||
)
|
)
|
||||||
|
|
||||||
return self.json(intent_result)
|
return self.json(intent_result)
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
"""Support for a Hue API to control Home Assistant."""
|
"""Support for a Hue API to control Home Assistant."""
|
||||||
import asyncio
|
import asyncio
|
||||||
import hashlib
|
import hashlib
|
||||||
|
from http import HTTPStatus
|
||||||
from ipaddress import ip_address
|
from ipaddress import ip_address
|
||||||
import logging
|
import logging
|
||||||
import time
|
import time
|
||||||
|
@ -55,9 +56,6 @@ from homeassistant.const import (
|
||||||
ATTR_ENTITY_ID,
|
ATTR_ENTITY_ID,
|
||||||
ATTR_SUPPORTED_FEATURES,
|
ATTR_SUPPORTED_FEATURES,
|
||||||
ATTR_TEMPERATURE,
|
ATTR_TEMPERATURE,
|
||||||
HTTP_BAD_REQUEST,
|
|
||||||
HTTP_NOT_FOUND,
|
|
||||||
HTTP_UNAUTHORIZED,
|
|
||||||
SERVICE_CLOSE_COVER,
|
SERVICE_CLOSE_COVER,
|
||||||
SERVICE_OPEN_COVER,
|
SERVICE_OPEN_COVER,
|
||||||
SERVICE_TURN_OFF,
|
SERVICE_TURN_OFF,
|
||||||
|
@ -136,15 +134,15 @@ class HueUsernameView(HomeAssistantView):
|
||||||
async def post(self, request):
|
async def post(self, request):
|
||||||
"""Handle a POST request."""
|
"""Handle a POST request."""
|
||||||
if not is_local(ip_address(request.remote)):
|
if not is_local(ip_address(request.remote)):
|
||||||
return self.json_message("Only local IPs allowed", HTTP_UNAUTHORIZED)
|
return self.json_message("Only local IPs allowed", HTTPStatus.UNAUTHORIZED)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
data = await request.json()
|
data = await request.json()
|
||||||
except ValueError:
|
except ValueError:
|
||||||
return self.json_message("Invalid JSON", HTTP_BAD_REQUEST)
|
return self.json_message("Invalid JSON", HTTPStatus.BAD_REQUEST)
|
||||||
|
|
||||||
if "devicetype" not in data:
|
if "devicetype" not in data:
|
||||||
return self.json_message("devicetype not specified", HTTP_BAD_REQUEST)
|
return self.json_message("devicetype not specified", HTTPStatus.BAD_REQUEST)
|
||||||
|
|
||||||
return self.json([{"success": {"username": HUE_API_USERNAME}}])
|
return self.json([{"success": {"username": HUE_API_USERNAME}}])
|
||||||
|
|
||||||
|
@ -164,7 +162,7 @@ class HueAllGroupsStateView(HomeAssistantView):
|
||||||
def get(self, request, username):
|
def get(self, request, username):
|
||||||
"""Process a request to make the Brilliant Lightpad work."""
|
"""Process a request to make the Brilliant Lightpad work."""
|
||||||
if not is_local(ip_address(request.remote)):
|
if not is_local(ip_address(request.remote)):
|
||||||
return self.json_message("Only local IPs allowed", HTTP_UNAUTHORIZED)
|
return self.json_message("Only local IPs allowed", HTTPStatus.UNAUTHORIZED)
|
||||||
|
|
||||||
return self.json({})
|
return self.json({})
|
||||||
|
|
||||||
|
@ -184,7 +182,7 @@ class HueGroupView(HomeAssistantView):
|
||||||
def put(self, request, username):
|
def put(self, request, username):
|
||||||
"""Process a request to make the Logitech Pop working."""
|
"""Process a request to make the Logitech Pop working."""
|
||||||
if not is_local(ip_address(request.remote)):
|
if not is_local(ip_address(request.remote)):
|
||||||
return self.json_message("Only local IPs allowed", HTTP_UNAUTHORIZED)
|
return self.json_message("Only local IPs allowed", HTTPStatus.UNAUTHORIZED)
|
||||||
|
|
||||||
return self.json(
|
return self.json(
|
||||||
[
|
[
|
||||||
|
@ -214,7 +212,7 @@ class HueAllLightsStateView(HomeAssistantView):
|
||||||
def get(self, request, username):
|
def get(self, request, username):
|
||||||
"""Process a request to get the list of available lights."""
|
"""Process a request to get the list of available lights."""
|
||||||
if not is_local(ip_address(request.remote)):
|
if not is_local(ip_address(request.remote)):
|
||||||
return self.json_message("Only local IPs allowed", HTTP_UNAUTHORIZED)
|
return self.json_message("Only local IPs allowed", HTTPStatus.UNAUTHORIZED)
|
||||||
|
|
||||||
return self.json(create_list_of_entities(self.config, request))
|
return self.json(create_list_of_entities(self.config, request))
|
||||||
|
|
||||||
|
@ -234,7 +232,7 @@ class HueFullStateView(HomeAssistantView):
|
||||||
def get(self, request, username):
|
def get(self, request, username):
|
||||||
"""Process a request to get the list of available lights."""
|
"""Process a request to get the list of available lights."""
|
||||||
if not is_local(ip_address(request.remote)):
|
if not is_local(ip_address(request.remote)):
|
||||||
return self.json_message("only local IPs allowed", HTTP_UNAUTHORIZED)
|
return self.json_message("only local IPs allowed", HTTPStatus.UNAUTHORIZED)
|
||||||
if username != HUE_API_USERNAME:
|
if username != HUE_API_USERNAME:
|
||||||
return self.json(UNAUTHORIZED_USER)
|
return self.json(UNAUTHORIZED_USER)
|
||||||
|
|
||||||
|
@ -262,7 +260,7 @@ class HueConfigView(HomeAssistantView):
|
||||||
def get(self, request, username=""):
|
def get(self, request, username=""):
|
||||||
"""Process a request to get the configuration."""
|
"""Process a request to get the configuration."""
|
||||||
if not is_local(ip_address(request.remote)):
|
if not is_local(ip_address(request.remote)):
|
||||||
return self.json_message("only local IPs allowed", HTTP_UNAUTHORIZED)
|
return self.json_message("only local IPs allowed", HTTPStatus.UNAUTHORIZED)
|
||||||
|
|
||||||
json_response = create_config_model(self.config, request)
|
json_response = create_config_model(self.config, request)
|
||||||
|
|
||||||
|
@ -284,7 +282,7 @@ class HueOneLightStateView(HomeAssistantView):
|
||||||
def get(self, request, username, entity_id):
|
def get(self, request, username, entity_id):
|
||||||
"""Process a request to get the state of an individual light."""
|
"""Process a request to get the state of an individual light."""
|
||||||
if not is_local(ip_address(request.remote)):
|
if not is_local(ip_address(request.remote)):
|
||||||
return self.json_message("Only local IPs allowed", HTTP_UNAUTHORIZED)
|
return self.json_message("Only local IPs allowed", HTTPStatus.UNAUTHORIZED)
|
||||||
|
|
||||||
hass = request.app["hass"]
|
hass = request.app["hass"]
|
||||||
hass_entity_id = self.config.number_to_entity_id(entity_id)
|
hass_entity_id = self.config.number_to_entity_id(entity_id)
|
||||||
|
@ -294,17 +292,17 @@ class HueOneLightStateView(HomeAssistantView):
|
||||||
"Unknown entity number: %s not found in emulated_hue_ids.json",
|
"Unknown entity number: %s not found in emulated_hue_ids.json",
|
||||||
entity_id,
|
entity_id,
|
||||||
)
|
)
|
||||||
return self.json_message("Entity not found", HTTP_NOT_FOUND)
|
return self.json_message("Entity not found", HTTPStatus.NOT_FOUND)
|
||||||
|
|
||||||
entity = hass.states.get(hass_entity_id)
|
entity = hass.states.get(hass_entity_id)
|
||||||
|
|
||||||
if entity is None:
|
if entity is None:
|
||||||
_LOGGER.error("Entity not found: %s", hass_entity_id)
|
_LOGGER.error("Entity not found: %s", hass_entity_id)
|
||||||
return self.json_message("Entity not found", HTTP_NOT_FOUND)
|
return self.json_message("Entity not found", HTTPStatus.NOT_FOUND)
|
||||||
|
|
||||||
if not self.config.is_entity_exposed(entity):
|
if not self.config.is_entity_exposed(entity):
|
||||||
_LOGGER.error("Entity not exposed: %s", entity_id)
|
_LOGGER.error("Entity not exposed: %s", entity_id)
|
||||||
return self.json_message("Entity not exposed", HTTP_UNAUTHORIZED)
|
return self.json_message("Entity not exposed", HTTPStatus.UNAUTHORIZED)
|
||||||
|
|
||||||
json_response = entity_to_json(self.config, entity)
|
json_response = entity_to_json(self.config, entity)
|
||||||
|
|
||||||
|
@ -325,7 +323,7 @@ class HueOneLightChangeView(HomeAssistantView):
|
||||||
async def put(self, request, username, entity_number): # noqa: C901
|
async def put(self, request, username, entity_number): # noqa: C901
|
||||||
"""Process a request to set the state of an individual light."""
|
"""Process a request to set the state of an individual light."""
|
||||||
if not is_local(ip_address(request.remote)):
|
if not is_local(ip_address(request.remote)):
|
||||||
return self.json_message("Only local IPs allowed", HTTP_UNAUTHORIZED)
|
return self.json_message("Only local IPs allowed", HTTPStatus.UNAUTHORIZED)
|
||||||
|
|
||||||
config = self.config
|
config = self.config
|
||||||
hass = request.app["hass"]
|
hass = request.app["hass"]
|
||||||
|
@ -333,23 +331,23 @@ class HueOneLightChangeView(HomeAssistantView):
|
||||||
|
|
||||||
if entity_id is None:
|
if entity_id is None:
|
||||||
_LOGGER.error("Unknown entity number: %s", entity_number)
|
_LOGGER.error("Unknown entity number: %s", entity_number)
|
||||||
return self.json_message("Entity not found", HTTP_NOT_FOUND)
|
return self.json_message("Entity not found", HTTPStatus.NOT_FOUND)
|
||||||
|
|
||||||
entity = hass.states.get(entity_id)
|
entity = hass.states.get(entity_id)
|
||||||
|
|
||||||
if entity is None:
|
if entity is None:
|
||||||
_LOGGER.error("Entity not found: %s", entity_id)
|
_LOGGER.error("Entity not found: %s", entity_id)
|
||||||
return self.json_message("Entity not found", HTTP_NOT_FOUND)
|
return self.json_message("Entity not found", HTTPStatus.NOT_FOUND)
|
||||||
|
|
||||||
if not config.is_entity_exposed(entity):
|
if not config.is_entity_exposed(entity):
|
||||||
_LOGGER.error("Entity not exposed: %s", entity_id)
|
_LOGGER.error("Entity not exposed: %s", entity_id)
|
||||||
return self.json_message("Entity not exposed", HTTP_UNAUTHORIZED)
|
return self.json_message("Entity not exposed", HTTPStatus.UNAUTHORIZED)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
request_json = await request.json()
|
request_json = await request.json()
|
||||||
except ValueError:
|
except ValueError:
|
||||||
_LOGGER.error("Received invalid json")
|
_LOGGER.error("Received invalid json")
|
||||||
return self.json_message("Invalid JSON", HTTP_BAD_REQUEST)
|
return self.json_message("Invalid JSON", HTTPStatus.BAD_REQUEST)
|
||||||
|
|
||||||
# Get the entity's supported features
|
# Get the entity's supported features
|
||||||
entity_features = entity.attributes.get(ATTR_SUPPORTED_FEATURES, 0)
|
entity_features = entity.attributes.get(ATTR_SUPPORTED_FEATURES, 0)
|
||||||
|
@ -370,7 +368,7 @@ class HueOneLightChangeView(HomeAssistantView):
|
||||||
if HUE_API_STATE_ON in request_json:
|
if HUE_API_STATE_ON in request_json:
|
||||||
if not isinstance(request_json[HUE_API_STATE_ON], bool):
|
if not isinstance(request_json[HUE_API_STATE_ON], bool):
|
||||||
_LOGGER.error("Unable to parse data: %s", request_json)
|
_LOGGER.error("Unable to parse data: %s", request_json)
|
||||||
return self.json_message("Bad request", HTTP_BAD_REQUEST)
|
return self.json_message("Bad request", HTTPStatus.BAD_REQUEST)
|
||||||
parsed[STATE_ON] = request_json[HUE_API_STATE_ON]
|
parsed[STATE_ON] = request_json[HUE_API_STATE_ON]
|
||||||
else:
|
else:
|
||||||
parsed[STATE_ON] = entity.state != STATE_OFF
|
parsed[STATE_ON] = entity.state != STATE_OFF
|
||||||
|
@ -387,7 +385,7 @@ class HueOneLightChangeView(HomeAssistantView):
|
||||||
parsed[attr] = int(request_json[key])
|
parsed[attr] = int(request_json[key])
|
||||||
except ValueError:
|
except ValueError:
|
||||||
_LOGGER.error("Unable to parse data (2): %s", request_json)
|
_LOGGER.error("Unable to parse data (2): %s", request_json)
|
||||||
return self.json_message("Bad request", HTTP_BAD_REQUEST)
|
return self.json_message("Bad request", HTTPStatus.BAD_REQUEST)
|
||||||
if HUE_API_STATE_XY in request_json:
|
if HUE_API_STATE_XY in request_json:
|
||||||
try:
|
try:
|
||||||
parsed[STATE_XY] = (
|
parsed[STATE_XY] = (
|
||||||
|
@ -396,7 +394,7 @@ class HueOneLightChangeView(HomeAssistantView):
|
||||||
)
|
)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
_LOGGER.error("Unable to parse data (2): %s", request_json)
|
_LOGGER.error("Unable to parse data (2): %s", request_json)
|
||||||
return self.json_message("Bad request", HTTP_BAD_REQUEST)
|
return self.json_message("Bad request", HTTPStatus.BAD_REQUEST)
|
||||||
|
|
||||||
if HUE_API_STATE_BRI in request_json:
|
if HUE_API_STATE_BRI in request_json:
|
||||||
if entity.domain == light.DOMAIN:
|
if entity.domain == light.DOMAIN:
|
||||||
|
|
|
@ -1,16 +1,12 @@
|
||||||
"""Support for the Foursquare (Swarm) API."""
|
"""Support for the Foursquare (Swarm) API."""
|
||||||
|
from http import HTTPStatus
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
import requests
|
import requests
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
from homeassistant.components.http import HomeAssistantView
|
from homeassistant.components.http import HomeAssistantView
|
||||||
from homeassistant.const import (
|
from homeassistant.const import CONF_ACCESS_TOKEN, HTTP_CREATED, HTTP_OK
|
||||||
CONF_ACCESS_TOKEN,
|
|
||||||
HTTP_BAD_REQUEST,
|
|
||||||
HTTP_CREATED,
|
|
||||||
HTTP_OK,
|
|
||||||
)
|
|
||||||
import homeassistant.helpers.config_validation as cv
|
import homeassistant.helpers.config_validation as cv
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
@ -95,7 +91,7 @@ class FoursquarePushReceiver(HomeAssistantView):
|
||||||
try:
|
try:
|
||||||
data = await request.json()
|
data = await request.json()
|
||||||
except ValueError:
|
except ValueError:
|
||||||
return self.json_message("Invalid JSON", HTTP_BAD_REQUEST)
|
return self.json_message("Invalid JSON", HTTPStatus.BAD_REQUEST)
|
||||||
|
|
||||||
secret = data.pop("secret", None)
|
secret = data.pop("secret", None)
|
||||||
|
|
||||||
|
@ -105,6 +101,6 @@ class FoursquarePushReceiver(HomeAssistantView):
|
||||||
_LOGGER.error(
|
_LOGGER.error(
|
||||||
"Received Foursquare push with invalid push secret: %s", secret
|
"Received Foursquare push with invalid push secret: %s", secret
|
||||||
)
|
)
|
||||||
return self.json_message("Incorrect secret", HTTP_BAD_REQUEST)
|
return self.json_message("Incorrect secret", HTTPStatus.BAD_REQUEST)
|
||||||
|
|
||||||
request.app["hass"].bus.async_fire(EVENT_PUSH, data)
|
request.app["hass"].bus.async_fire(EVENT_PUSH, data)
|
||||||
|
|
|
@ -3,6 +3,7 @@ from __future__ import annotations
|
||||||
|
|
||||||
from collections.abc import Iterable
|
from collections.abc import Iterable
|
||||||
from datetime import datetime as dt, timedelta
|
from datetime import datetime as dt, timedelta
|
||||||
|
from http import HTTPStatus
|
||||||
import logging
|
import logging
|
||||||
import time
|
import time
|
||||||
from typing import cast
|
from typing import cast
|
||||||
|
@ -19,13 +20,7 @@ from homeassistant.components.recorder.statistics import (
|
||||||
statistics_during_period,
|
statistics_during_period,
|
||||||
)
|
)
|
||||||
from homeassistant.components.recorder.util import session_scope
|
from homeassistant.components.recorder.util import session_scope
|
||||||
from homeassistant.const import (
|
from homeassistant.const import CONF_DOMAINS, CONF_ENTITIES, CONF_EXCLUDE, CONF_INCLUDE
|
||||||
CONF_DOMAINS,
|
|
||||||
CONF_ENTITIES,
|
|
||||||
CONF_EXCLUDE,
|
|
||||||
CONF_INCLUDE,
|
|
||||||
HTTP_BAD_REQUEST,
|
|
||||||
)
|
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
import homeassistant.helpers.config_validation as cv
|
import homeassistant.helpers.config_validation as cv
|
||||||
from homeassistant.helpers.deprecation import deprecated_class, deprecated_function
|
from homeassistant.helpers.deprecation import deprecated_class, deprecated_function
|
||||||
|
@ -203,7 +198,7 @@ class HistoryPeriodView(HomeAssistantView):
|
||||||
datetime_ = dt_util.parse_datetime(datetime)
|
datetime_ = dt_util.parse_datetime(datetime)
|
||||||
|
|
||||||
if datetime_ is None:
|
if datetime_ is None:
|
||||||
return self.json_message("Invalid datetime", HTTP_BAD_REQUEST)
|
return self.json_message("Invalid datetime", HTTPStatus.BAD_REQUEST)
|
||||||
|
|
||||||
now = dt_util.utcnow()
|
now = dt_util.utcnow()
|
||||||
|
|
||||||
|
@ -222,7 +217,7 @@ class HistoryPeriodView(HomeAssistantView):
|
||||||
if end_time:
|
if end_time:
|
||||||
end_time = dt_util.as_utc(end_time)
|
end_time = dt_util.as_utc(end_time)
|
||||||
else:
|
else:
|
||||||
return self.json_message("Invalid end_time", HTTP_BAD_REQUEST)
|
return self.json_message("Invalid end_time", HTTPStatus.BAD_REQUEST)
|
||||||
else:
|
else:
|
||||||
end_time = start_time + one_day
|
end_time = start_time + one_day
|
||||||
entity_ids_str = request.query.get("filter_entity_id")
|
entity_ids_str = request.query.get("filter_entity_id")
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
from contextlib import suppress
|
from contextlib import suppress
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
from functools import partial
|
from functools import partial
|
||||||
|
from http import HTTPStatus
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
import time
|
import time
|
||||||
|
@ -26,13 +27,7 @@ from homeassistant.components.notify import (
|
||||||
PLATFORM_SCHEMA,
|
PLATFORM_SCHEMA,
|
||||||
BaseNotificationService,
|
BaseNotificationService,
|
||||||
)
|
)
|
||||||
from homeassistant.const import (
|
from homeassistant.const import ATTR_NAME, URL_ROOT
|
||||||
ATTR_NAME,
|
|
||||||
HTTP_BAD_REQUEST,
|
|
||||||
HTTP_INTERNAL_SERVER_ERROR,
|
|
||||||
HTTP_UNAUTHORIZED,
|
|
||||||
URL_ROOT,
|
|
||||||
)
|
|
||||||
from homeassistant.exceptions import HomeAssistantError
|
from homeassistant.exceptions import HomeAssistantError
|
||||||
from homeassistant.helpers import config_validation as cv
|
from homeassistant.helpers import config_validation as cv
|
||||||
from homeassistant.util import ensure_unique_string
|
from homeassistant.util import ensure_unique_string
|
||||||
|
@ -224,11 +219,11 @@ class HTML5PushRegistrationView(HomeAssistantView):
|
||||||
try:
|
try:
|
||||||
data = await request.json()
|
data = await request.json()
|
||||||
except ValueError:
|
except ValueError:
|
||||||
return self.json_message("Invalid JSON", HTTP_BAD_REQUEST)
|
return self.json_message("Invalid JSON", HTTPStatus.BAD_REQUEST)
|
||||||
try:
|
try:
|
||||||
data = REGISTER_SCHEMA(data)
|
data = REGISTER_SCHEMA(data)
|
||||||
except vol.Invalid as ex:
|
except vol.Invalid as ex:
|
||||||
return self.json_message(humanize_error(data, ex), HTTP_BAD_REQUEST)
|
return self.json_message(humanize_error(data, ex), HTTPStatus.BAD_REQUEST)
|
||||||
|
|
||||||
devname = data.get(ATTR_NAME)
|
devname = data.get(ATTR_NAME)
|
||||||
data.pop(ATTR_NAME, None)
|
data.pop(ATTR_NAME, None)
|
||||||
|
@ -252,7 +247,7 @@ class HTML5PushRegistrationView(HomeAssistantView):
|
||||||
self.registrations.pop(name)
|
self.registrations.pop(name)
|
||||||
|
|
||||||
return self.json_message(
|
return self.json_message(
|
||||||
"Error saving registration.", HTTP_INTERNAL_SERVER_ERROR
|
"Error saving registration.", HTTPStatus.INTERNAL_SERVER_ERROR
|
||||||
)
|
)
|
||||||
|
|
||||||
def find_registration_name(self, data, suggested=None):
|
def find_registration_name(self, data, suggested=None):
|
||||||
|
@ -269,7 +264,7 @@ class HTML5PushRegistrationView(HomeAssistantView):
|
||||||
try:
|
try:
|
||||||
data = await request.json()
|
data = await request.json()
|
||||||
except ValueError:
|
except ValueError:
|
||||||
return self.json_message("Invalid JSON", HTTP_BAD_REQUEST)
|
return self.json_message("Invalid JSON", HTTPStatus.BAD_REQUEST)
|
||||||
|
|
||||||
subscription = data.get(ATTR_SUBSCRIPTION)
|
subscription = data.get(ATTR_SUBSCRIPTION)
|
||||||
|
|
||||||
|
@ -295,7 +290,7 @@ class HTML5PushRegistrationView(HomeAssistantView):
|
||||||
except HomeAssistantError:
|
except HomeAssistantError:
|
||||||
self.registrations[found] = reg
|
self.registrations[found] = reg
|
||||||
return self.json_message(
|
return self.json_message(
|
||||||
"Error saving registration.", HTTP_INTERNAL_SERVER_ERROR
|
"Error saving registration.", HTTPStatus.INTERNAL_SERVER_ERROR
|
||||||
)
|
)
|
||||||
|
|
||||||
return self.json_message("Push notification subscriber unregistered.")
|
return self.json_message("Push notification subscriber unregistered.")
|
||||||
|
@ -330,7 +325,7 @@ class HTML5PushCallbackView(HomeAssistantView):
|
||||||
return jwt.decode(token, key, algorithms=["ES256", "HS256"])
|
return jwt.decode(token, key, algorithms=["ES256", "HS256"])
|
||||||
|
|
||||||
return self.json_message(
|
return self.json_message(
|
||||||
"No target found in JWT", status_code=HTTP_UNAUTHORIZED
|
"No target found in JWT", status_code=HTTPStatus.UNAUTHORIZED
|
||||||
)
|
)
|
||||||
|
|
||||||
# The following is based on code from Auth0
|
# The following is based on code from Auth0
|
||||||
|
@ -341,7 +336,7 @@ class HTML5PushCallbackView(HomeAssistantView):
|
||||||
auth = request.headers.get(AUTHORIZATION)
|
auth = request.headers.get(AUTHORIZATION)
|
||||||
if not auth:
|
if not auth:
|
||||||
return self.json_message(
|
return self.json_message(
|
||||||
"Authorization header is expected", status_code=HTTP_UNAUTHORIZED
|
"Authorization header is expected", status_code=HTTPStatus.UNAUTHORIZED
|
||||||
)
|
)
|
||||||
|
|
||||||
parts = auth.split()
|
parts = auth.split()
|
||||||
|
@ -349,19 +344,21 @@ class HTML5PushCallbackView(HomeAssistantView):
|
||||||
if parts[0].lower() != "bearer":
|
if parts[0].lower() != "bearer":
|
||||||
return self.json_message(
|
return self.json_message(
|
||||||
"Authorization header must start with Bearer",
|
"Authorization header must start with Bearer",
|
||||||
status_code=HTTP_UNAUTHORIZED,
|
status_code=HTTPStatus.UNAUTHORIZED,
|
||||||
)
|
)
|
||||||
if len(parts) != 2:
|
if len(parts) != 2:
|
||||||
return self.json_message(
|
return self.json_message(
|
||||||
"Authorization header must be Bearer token",
|
"Authorization header must be Bearer token",
|
||||||
status_code=HTTP_UNAUTHORIZED,
|
status_code=HTTPStatus.UNAUTHORIZED,
|
||||||
)
|
)
|
||||||
|
|
||||||
token = parts[1]
|
token = parts[1]
|
||||||
try:
|
try:
|
||||||
payload = self.decode_jwt(token)
|
payload = self.decode_jwt(token)
|
||||||
except jwt.exceptions.InvalidTokenError:
|
except jwt.exceptions.InvalidTokenError:
|
||||||
return self.json_message("token is invalid", status_code=HTTP_UNAUTHORIZED)
|
return self.json_message(
|
||||||
|
"token is invalid", status_code=HTTPStatus.UNAUTHORIZED
|
||||||
|
)
|
||||||
return payload
|
return payload
|
||||||
|
|
||||||
async def post(self, request):
|
async def post(self, request):
|
||||||
|
@ -373,7 +370,7 @@ class HTML5PushCallbackView(HomeAssistantView):
|
||||||
try:
|
try:
|
||||||
data = await request.json()
|
data = await request.json()
|
||||||
except ValueError:
|
except ValueError:
|
||||||
return self.json_message("Invalid JSON", HTTP_BAD_REQUEST)
|
return self.json_message("Invalid JSON", HTTPStatus.BAD_REQUEST)
|
||||||
|
|
||||||
event_payload = {
|
event_payload = {
|
||||||
ATTR_TAG: data.get(ATTR_TAG),
|
ATTR_TAG: data.get(ATTR_TAG),
|
||||||
|
|
|
@ -3,14 +3,13 @@ from __future__ import annotations
|
||||||
|
|
||||||
from collections.abc import Awaitable
|
from collections.abc import Awaitable
|
||||||
from functools import wraps
|
from functools import wraps
|
||||||
|
from http import HTTPStatus
|
||||||
import logging
|
import logging
|
||||||
from typing import Any, Callable
|
from typing import Any, Callable
|
||||||
|
|
||||||
from aiohttp import web
|
from aiohttp import web
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
from homeassistant.const import HTTP_BAD_REQUEST
|
|
||||||
|
|
||||||
from .view import HomeAssistantView
|
from .view import HomeAssistantView
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
@ -49,7 +48,7 @@ class RequestDataValidator:
|
||||||
except ValueError:
|
except ValueError:
|
||||||
if not self._allow_empty or (await request.content.read()) != b"":
|
if not self._allow_empty or (await request.content.read()) != b"":
|
||||||
_LOGGER.error("Invalid JSON received")
|
_LOGGER.error("Invalid JSON received")
|
||||||
return view.json_message("Invalid JSON.", HTTP_BAD_REQUEST)
|
return view.json_message("Invalid JSON.", HTTPStatus.BAD_REQUEST)
|
||||||
data = {}
|
data = {}
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -57,7 +56,7 @@ class RequestDataValidator:
|
||||||
except vol.Invalid as err:
|
except vol.Invalid as err:
|
||||||
_LOGGER.error("Data does not match schema: %s", err)
|
_LOGGER.error("Data does not match schema: %s", err)
|
||||||
return view.json_message(
|
return view.json_message(
|
||||||
f"Message format incorrect: {err}", HTTP_BAD_REQUEST
|
f"Message format incorrect: {err}", HTTPStatus.BAD_REQUEST
|
||||||
)
|
)
|
||||||
|
|
||||||
result = await method(view, request, *args, **kwargs)
|
result = await method(view, request, *args, **kwargs)
|
||||||
|
|
|
@ -3,6 +3,7 @@ from __future__ import annotations
|
||||||
|
|
||||||
import asyncio
|
import asyncio
|
||||||
from collections.abc import Awaitable, Callable
|
from collections.abc import Awaitable, Callable
|
||||||
|
from http import HTTPStatus
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
@ -48,7 +49,7 @@ class HomeAssistantView:
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def json(
|
def json(
|
||||||
result: Any,
|
result: Any,
|
||||||
status_code: int = HTTP_OK,
|
status_code: HTTPStatus | int = HTTPStatus.OK,
|
||||||
headers: LooseHeaders | None = None,
|
headers: LooseHeaders | None = None,
|
||||||
) -> web.Response:
|
) -> web.Response:
|
||||||
"""Return a JSON response."""
|
"""Return a JSON response."""
|
||||||
|
@ -60,7 +61,7 @@ class HomeAssistantView:
|
||||||
response = web.Response(
|
response = web.Response(
|
||||||
body=msg,
|
body=msg,
|
||||||
content_type=CONTENT_TYPE_JSON,
|
content_type=CONTENT_TYPE_JSON,
|
||||||
status=status_code,
|
status=int(status_code),
|
||||||
headers=headers,
|
headers=headers,
|
||||||
)
|
)
|
||||||
response.enable_compression()
|
response.enable_compression()
|
||||||
|
@ -69,7 +70,7 @@ class HomeAssistantView:
|
||||||
def json_message(
|
def json_message(
|
||||||
self,
|
self,
|
||||||
message: str,
|
message: str,
|
||||||
status_code: int = HTTP_OK,
|
status_code: HTTPStatus | int = HTTPStatus.OK,
|
||||||
message_code: str | None = None,
|
message_code: str | None = None,
|
||||||
headers: LooseHeaders | None = None,
|
headers: LooseHeaders | None = None,
|
||||||
) -> web.Response:
|
) -> web.Response:
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
"""Native Home Assistant iOS app component."""
|
"""Native Home Assistant iOS app component."""
|
||||||
import datetime
|
import datetime
|
||||||
|
from http import HTTPStatus
|
||||||
|
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
from homeassistant import config_entries
|
from homeassistant import config_entries
|
||||||
from homeassistant.components.http import HomeAssistantView
|
from homeassistant.components.http import HomeAssistantView
|
||||||
from homeassistant.const import HTTP_BAD_REQUEST, HTTP_INTERNAL_SERVER_ERROR
|
|
||||||
from homeassistant.core import callback
|
from homeassistant.core import callback
|
||||||
from homeassistant.exceptions import HomeAssistantError
|
from homeassistant.exceptions import HomeAssistantError
|
||||||
from homeassistant.helpers import config_validation as cv, discovery
|
from homeassistant.helpers import config_validation as cv, discovery
|
||||||
|
@ -333,7 +333,7 @@ class iOSIdentifyDeviceView(HomeAssistantView):
|
||||||
try:
|
try:
|
||||||
data = await request.json()
|
data = await request.json()
|
||||||
except ValueError:
|
except ValueError:
|
||||||
return self.json_message("Invalid JSON", HTTP_BAD_REQUEST)
|
return self.json_message("Invalid JSON", HTTPStatus.BAD_REQUEST)
|
||||||
|
|
||||||
hass = request.app["hass"]
|
hass = request.app["hass"]
|
||||||
|
|
||||||
|
@ -348,6 +348,8 @@ class iOSIdentifyDeviceView(HomeAssistantView):
|
||||||
try:
|
try:
|
||||||
save_json(self._config_path, hass.data[DOMAIN])
|
save_json(self._config_path, hass.data[DOMAIN])
|
||||||
except HomeAssistantError:
|
except HomeAssistantError:
|
||||||
return self.json_message("Error saving device.", HTTP_INTERNAL_SERVER_ERROR)
|
return self.json_message(
|
||||||
|
"Error saving device.", HTTPStatus.INTERNAL_SERVER_ERROR
|
||||||
|
)
|
||||||
|
|
||||||
return self.json({"status": "registered"})
|
return self.json({"status": "registered"})
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
"""Support for Konnected devices."""
|
"""Support for Konnected devices."""
|
||||||
import copy
|
import copy
|
||||||
import hmac
|
import hmac
|
||||||
|
from http import HTTPStatus
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
|
@ -28,9 +29,6 @@ from homeassistant.const import (
|
||||||
CONF_SWITCHES,
|
CONF_SWITCHES,
|
||||||
CONF_TYPE,
|
CONF_TYPE,
|
||||||
CONF_ZONE,
|
CONF_ZONE,
|
||||||
HTTP_BAD_REQUEST,
|
|
||||||
HTTP_NOT_FOUND,
|
|
||||||
HTTP_UNAUTHORIZED,
|
|
||||||
STATE_OFF,
|
STATE_OFF,
|
||||||
STATE_ON,
|
STATE_ON,
|
||||||
)
|
)
|
||||||
|
@ -325,7 +323,9 @@ class KonnectedView(HomeAssistantView):
|
||||||
(True for token in tokens if hmac.compare_digest(f"Bearer {token}", auth)),
|
(True for token in tokens if hmac.compare_digest(f"Bearer {token}", auth)),
|
||||||
False,
|
False,
|
||||||
):
|
):
|
||||||
return self.json_message("unauthorized", status_code=HTTP_UNAUTHORIZED)
|
return self.json_message(
|
||||||
|
"unauthorized", status_code=HTTPStatus.UNAUTHORIZED
|
||||||
|
)
|
||||||
|
|
||||||
try: # Konnected 2.2.0 and above supports JSON payloads
|
try: # Konnected 2.2.0 and above supports JSON payloads
|
||||||
payload = await request.json()
|
payload = await request.json()
|
||||||
|
@ -339,7 +339,7 @@ class KonnectedView(HomeAssistantView):
|
||||||
device = data[CONF_DEVICES].get(device_id)
|
device = data[CONF_DEVICES].get(device_id)
|
||||||
if device is None:
|
if device is None:
|
||||||
return self.json_message(
|
return self.json_message(
|
||||||
"unregistered device", status_code=HTTP_BAD_REQUEST
|
"unregistered device", status_code=HTTPStatus.BAD_REQUEST
|
||||||
)
|
)
|
||||||
|
|
||||||
panel = device.get("panel")
|
panel = device.get("panel")
|
||||||
|
@ -364,7 +364,7 @@ class KonnectedView(HomeAssistantView):
|
||||||
|
|
||||||
if zone_data is None:
|
if zone_data is None:
|
||||||
return self.json_message(
|
return self.json_message(
|
||||||
"unregistered sensor/actuator", status_code=HTTP_BAD_REQUEST
|
"unregistered sensor/actuator", status_code=HTTPStatus.BAD_REQUEST
|
||||||
)
|
)
|
||||||
|
|
||||||
zone_data["device_id"] = device_id
|
zone_data["device_id"] = device_id
|
||||||
|
@ -385,7 +385,7 @@ class KonnectedView(HomeAssistantView):
|
||||||
device = data[CONF_DEVICES].get(device_id)
|
device = data[CONF_DEVICES].get(device_id)
|
||||||
if not device:
|
if not device:
|
||||||
return self.json_message(
|
return self.json_message(
|
||||||
f"Device {device_id} not configured", status_code=HTTP_NOT_FOUND
|
f"Device {device_id} not configured", status_code=HTTPStatus.NOT_FOUND
|
||||||
)
|
)
|
||||||
|
|
||||||
panel = device.get("panel")
|
panel = device.get("panel")
|
||||||
|
@ -417,7 +417,7 @@ class KonnectedView(HomeAssistantView):
|
||||||
)
|
)
|
||||||
return self.json_message(
|
return self.json_message(
|
||||||
f"Switch on zone or pin {target} not configured",
|
f"Switch on zone or pin {target} not configured",
|
||||||
status_code=HTTP_NOT_FOUND,
|
status_code=HTTPStatus.NOT_FOUND,
|
||||||
)
|
)
|
||||||
|
|
||||||
resp = {}
|
resp = {}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
"""Event parser and human readable log generator."""
|
"""Event parser and human readable log generator."""
|
||||||
from contextlib import suppress
|
from contextlib import suppress
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
|
from http import HTTPStatus
|
||||||
from itertools import groupby
|
from itertools import groupby
|
||||||
import json
|
import json
|
||||||
import re
|
import re
|
||||||
|
@ -32,7 +33,6 @@ from homeassistant.const import (
|
||||||
EVENT_HOMEASSISTANT_STOP,
|
EVENT_HOMEASSISTANT_STOP,
|
||||||
EVENT_LOGBOOK_ENTRY,
|
EVENT_LOGBOOK_ENTRY,
|
||||||
EVENT_STATE_CHANGED,
|
EVENT_STATE_CHANGED,
|
||||||
HTTP_BAD_REQUEST,
|
|
||||||
)
|
)
|
||||||
from homeassistant.core import DOMAIN as HA_DOMAIN, callback, split_entity_id
|
from homeassistant.core import DOMAIN as HA_DOMAIN, callback, split_entity_id
|
||||||
from homeassistant.exceptions import InvalidEntityFormatError
|
from homeassistant.exceptions import InvalidEntityFormatError
|
||||||
|
@ -198,7 +198,7 @@ class LogbookView(HomeAssistantView):
|
||||||
datetime = dt_util.parse_datetime(datetime)
|
datetime = dt_util.parse_datetime(datetime)
|
||||||
|
|
||||||
if datetime is None:
|
if datetime is None:
|
||||||
return self.json_message("Invalid datetime", HTTP_BAD_REQUEST)
|
return self.json_message("Invalid datetime", HTTPStatus.BAD_REQUEST)
|
||||||
else:
|
else:
|
||||||
datetime = dt_util.start_of_local_day()
|
datetime = dt_util.start_of_local_day()
|
||||||
|
|
||||||
|
@ -226,7 +226,7 @@ class LogbookView(HomeAssistantView):
|
||||||
start_day = datetime
|
start_day = datetime
|
||||||
end_day = dt_util.parse_datetime(end_time)
|
end_day = dt_util.parse_datetime(end_time)
|
||||||
if end_day is None:
|
if end_day is None:
|
||||||
return self.json_message("Invalid end_time", HTTP_BAD_REQUEST)
|
return self.json_message("Invalid end_time", HTTPStatus.BAD_REQUEST)
|
||||||
|
|
||||||
hass = request.app["hass"]
|
hass = request.app["hass"]
|
||||||
|
|
||||||
|
@ -235,7 +235,7 @@ class LogbookView(HomeAssistantView):
|
||||||
|
|
||||||
if entity_ids and context_id:
|
if entity_ids and context_id:
|
||||||
return self.json_message(
|
return self.json_message(
|
||||||
"Can't combine entity with context_id", HTTP_BAD_REQUEST
|
"Can't combine entity with context_id", HTTPStatus.BAD_REQUEST
|
||||||
)
|
)
|
||||||
|
|
||||||
def json_events():
|
def json_events():
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
"""Config flow to configure Logi Circle component."""
|
"""Config flow to configure Logi Circle component."""
|
||||||
import asyncio
|
import asyncio
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
|
from http import HTTPStatus
|
||||||
|
|
||||||
import async_timeout
|
import async_timeout
|
||||||
from logi_circle import LogiCircle
|
from logi_circle import LogiCircle
|
||||||
|
@ -14,7 +15,6 @@ from homeassistant.const import (
|
||||||
CONF_CLIENT_ID,
|
CONF_CLIENT_ID,
|
||||||
CONF_CLIENT_SECRET,
|
CONF_CLIENT_SECRET,
|
||||||
CONF_SENSORS,
|
CONF_SENSORS,
|
||||||
HTTP_BAD_REQUEST,
|
|
||||||
)
|
)
|
||||||
from homeassistant.core import callback
|
from homeassistant.core import callback
|
||||||
|
|
||||||
|
@ -201,5 +201,6 @@ class LogiCircleAuthCallbackView(HomeAssistantView):
|
||||||
)
|
)
|
||||||
return self.json_message("Authorisation code saved")
|
return self.json_message("Authorisation code saved")
|
||||||
return self.json_message(
|
return self.json_message(
|
||||||
"Authorisation code missing from query string", status_code=HTTP_BAD_REQUEST
|
"Authorisation code missing from query string",
|
||||||
|
status_code=HTTPStatus.BAD_REQUEST,
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
"""Support for the Meraki CMX location service."""
|
"""Support for the Meraki CMX location service."""
|
||||||
|
from http import HTTPStatus
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
|
@ -9,7 +10,6 @@ from homeassistant.components.device_tracker import (
|
||||||
SOURCE_TYPE_ROUTER,
|
SOURCE_TYPE_ROUTER,
|
||||||
)
|
)
|
||||||
from homeassistant.components.http import HomeAssistantView
|
from homeassistant.components.http import HomeAssistantView
|
||||||
from homeassistant.const import HTTP_BAD_REQUEST, HTTP_UNPROCESSABLE_ENTITY
|
|
||||||
from homeassistant.core import callback
|
from homeassistant.core import callback
|
||||||
import homeassistant.helpers.config_validation as cv
|
import homeassistant.helpers.config_validation as cv
|
||||||
|
|
||||||
|
@ -56,21 +56,23 @@ class MerakiView(HomeAssistantView):
|
||||||
try:
|
try:
|
||||||
data = await request.json()
|
data = await request.json()
|
||||||
except ValueError:
|
except ValueError:
|
||||||
return self.json_message("Invalid JSON", HTTP_BAD_REQUEST)
|
return self.json_message("Invalid JSON", HTTPStatus.BAD_REQUEST)
|
||||||
_LOGGER.debug("Meraki Data from Post: %s", json.dumps(data))
|
_LOGGER.debug("Meraki Data from Post: %s", json.dumps(data))
|
||||||
if not data.get("secret", False):
|
if not data.get("secret", False):
|
||||||
_LOGGER.error("The secret is invalid")
|
_LOGGER.error("The secret is invalid")
|
||||||
return self.json_message("No secret", HTTP_UNPROCESSABLE_ENTITY)
|
return self.json_message("No secret", HTTPStatus.UNPROCESSABLE_ENTITY)
|
||||||
if data["secret"] != self.secret:
|
if data["secret"] != self.secret:
|
||||||
_LOGGER.error("Invalid Secret received from Meraki")
|
_LOGGER.error("Invalid Secret received from Meraki")
|
||||||
return self.json_message("Invalid secret", HTTP_UNPROCESSABLE_ENTITY)
|
return self.json_message("Invalid secret", HTTPStatus.UNPROCESSABLE_ENTITY)
|
||||||
if data["version"] != VERSION:
|
if data["version"] != VERSION:
|
||||||
_LOGGER.error("Invalid API version: %s", data["version"])
|
_LOGGER.error("Invalid API version: %s", data["version"])
|
||||||
return self.json_message("Invalid version", HTTP_UNPROCESSABLE_ENTITY)
|
return self.json_message("Invalid version", HTTPStatus.UNPROCESSABLE_ENTITY)
|
||||||
_LOGGER.debug("Valid Secret")
|
_LOGGER.debug("Valid Secret")
|
||||||
if data["type"] not in ("DevicesSeen", "BluetoothDevicesSeen"):
|
if data["type"] not in ("DevicesSeen", "BluetoothDevicesSeen"):
|
||||||
_LOGGER.error("Unknown Device %s", data["type"])
|
_LOGGER.error("Unknown Device %s", data["type"])
|
||||||
return self.json_message("Invalid device type", HTTP_UNPROCESSABLE_ENTITY)
|
return self.json_message(
|
||||||
|
"Invalid device type", HTTPStatus.UNPROCESSABLE_ENTITY
|
||||||
|
)
|
||||||
_LOGGER.debug("Processing %s", data["type"])
|
_LOGGER.debug("Processing %s", data["type"])
|
||||||
if not data["data"]["observations"]:
|
if not data["data"]["observations"]:
|
||||||
_LOGGER.debug("No observations found")
|
_LOGGER.debug("No observations found")
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from contextlib import suppress
|
from contextlib import suppress
|
||||||
|
from http import HTTPStatus
|
||||||
import secrets
|
import secrets
|
||||||
|
|
||||||
from aiohttp.web import Request, Response
|
from aiohttp.web import Request, Response
|
||||||
|
@ -11,7 +12,7 @@ import voluptuous as vol
|
||||||
|
|
||||||
from homeassistant.components.http import HomeAssistantView
|
from homeassistant.components.http import HomeAssistantView
|
||||||
from homeassistant.components.http.data_validator import RequestDataValidator
|
from homeassistant.components.http.data_validator import RequestDataValidator
|
||||||
from homeassistant.const import ATTR_DEVICE_ID, CONF_WEBHOOK_ID, HTTP_CREATED
|
from homeassistant.const import ATTR_DEVICE_ID, CONF_WEBHOOK_ID
|
||||||
from homeassistant.helpers import config_validation as cv
|
from homeassistant.helpers import config_validation as cv
|
||||||
from homeassistant.util import slugify
|
from homeassistant.util import slugify
|
||||||
|
|
||||||
|
@ -109,5 +110,5 @@ class RegistrationsView(HomeAssistantView):
|
||||||
CONF_SECRET: data.get(CONF_SECRET),
|
CONF_SECRET: data.get(CONF_SECRET),
|
||||||
CONF_WEBHOOK_ID: data[CONF_WEBHOOK_ID],
|
CONF_WEBHOOK_ID: data[CONF_WEBHOOK_ID],
|
||||||
},
|
},
|
||||||
status_code=HTTP_CREATED,
|
status_code=HTTPStatus.CREATED,
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
"""Onboarding views."""
|
"""Onboarding views."""
|
||||||
import asyncio
|
import asyncio
|
||||||
|
from http import HTTPStatus
|
||||||
|
|
||||||
from aiohttp.web_exceptions import HTTPUnauthorized
|
from aiohttp.web_exceptions import HTTPUnauthorized
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
@ -9,7 +10,6 @@ from homeassistant.components.auth import indieauth
|
||||||
from homeassistant.components.http.const import KEY_HASS_REFRESH_TOKEN_ID
|
from homeassistant.components.http.const import KEY_HASS_REFRESH_TOKEN_ID
|
||||||
from homeassistant.components.http.data_validator import RequestDataValidator
|
from homeassistant.components.http.data_validator import RequestDataValidator
|
||||||
from homeassistant.components.http.view import HomeAssistantView
|
from homeassistant.components.http.view import HomeAssistantView
|
||||||
from homeassistant.const import HTTP_BAD_REQUEST, HTTP_FORBIDDEN
|
|
||||||
from homeassistant.core import callback
|
from homeassistant.core import callback
|
||||||
from homeassistant.helpers.system_info import async_get_system_info
|
from homeassistant.helpers.system_info import async_get_system_info
|
||||||
|
|
||||||
|
@ -124,7 +124,7 @@ class UserOnboardingView(_BaseOnboardingView):
|
||||||
|
|
||||||
async with self._lock:
|
async with self._lock:
|
||||||
if self._async_is_done():
|
if self._async_is_done():
|
||||||
return self.json_message("User step already done", HTTP_FORBIDDEN)
|
return self.json_message("User step already done", HTTPStatus.FORBIDDEN)
|
||||||
|
|
||||||
provider = _async_get_hass_provider(hass)
|
provider = _async_get_hass_provider(hass)
|
||||||
await provider.async_initialize()
|
await provider.async_initialize()
|
||||||
|
@ -179,7 +179,7 @@ class CoreConfigOnboardingView(_BaseOnboardingView):
|
||||||
async with self._lock:
|
async with self._lock:
|
||||||
if self._async_is_done():
|
if self._async_is_done():
|
||||||
return self.json_message(
|
return self.json_message(
|
||||||
"Core config step already done", HTTP_FORBIDDEN
|
"Core config step already done", HTTPStatus.FORBIDDEN
|
||||||
)
|
)
|
||||||
|
|
||||||
await self._async_mark_done(hass)
|
await self._async_mark_done(hass)
|
||||||
|
@ -217,7 +217,7 @@ class IntegrationOnboardingView(_BaseOnboardingView):
|
||||||
async with self._lock:
|
async with self._lock:
|
||||||
if self._async_is_done():
|
if self._async_is_done():
|
||||||
return self.json_message(
|
return self.json_message(
|
||||||
"Integration step already done", HTTP_FORBIDDEN
|
"Integration step already done", HTTPStatus.FORBIDDEN
|
||||||
)
|
)
|
||||||
|
|
||||||
await self._async_mark_done(hass)
|
await self._async_mark_done(hass)
|
||||||
|
@ -227,13 +227,13 @@ class IntegrationOnboardingView(_BaseOnboardingView):
|
||||||
request.app["hass"], data["client_id"], data["redirect_uri"]
|
request.app["hass"], data["client_id"], data["redirect_uri"]
|
||||||
):
|
):
|
||||||
return self.json_message(
|
return self.json_message(
|
||||||
"invalid client id or redirect uri", HTTP_BAD_REQUEST
|
"invalid client id or redirect uri", HTTPStatus.BAD_REQUEST
|
||||||
)
|
)
|
||||||
|
|
||||||
refresh_token = await hass.auth.async_get_refresh_token(refresh_token_id)
|
refresh_token = await hass.auth.async_get_refresh_token(refresh_token_id)
|
||||||
if refresh_token is None or refresh_token.credential is None:
|
if refresh_token is None or refresh_token.credential is None:
|
||||||
return self.json_message(
|
return self.json_message(
|
||||||
"Credentials for user not available", HTTP_FORBIDDEN
|
"Credentials for user not available", HTTPStatus.FORBIDDEN
|
||||||
)
|
)
|
||||||
|
|
||||||
# Return authorization code so we can redirect user and log them in
|
# Return authorization code so we can redirect user and log them in
|
||||||
|
@ -257,7 +257,7 @@ class AnalyticsOnboardingView(_BaseOnboardingView):
|
||||||
async with self._lock:
|
async with self._lock:
|
||||||
if self._async_is_done():
|
if self._async_is_done():
|
||||||
return self.json_message(
|
return self.json_message(
|
||||||
"Analytics config step already done", HTTP_FORBIDDEN
|
"Analytics config step already done", HTTPStatus.FORBIDDEN
|
||||||
)
|
)
|
||||||
|
|
||||||
await self._async_mark_done(hass)
|
await self._async_mark_done(hass)
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
"""Support to manage a shopping list."""
|
"""Support to manage a shopping list."""
|
||||||
|
from http import HTTPStatus
|
||||||
import logging
|
import logging
|
||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
|
@ -7,7 +8,7 @@ import voluptuous as vol
|
||||||
from homeassistant import config_entries
|
from homeassistant import config_entries
|
||||||
from homeassistant.components import http, websocket_api
|
from homeassistant.components import http, websocket_api
|
||||||
from homeassistant.components.http.data_validator import RequestDataValidator
|
from homeassistant.components.http.data_validator import RequestDataValidator
|
||||||
from homeassistant.const import ATTR_NAME, HTTP_BAD_REQUEST, HTTP_NOT_FOUND
|
from homeassistant.const import ATTR_NAME
|
||||||
from homeassistant.core import callback
|
from homeassistant.core import callback
|
||||||
import homeassistant.helpers.config_validation as cv
|
import homeassistant.helpers.config_validation as cv
|
||||||
from homeassistant.util.json import load_json, save_json
|
from homeassistant.util.json import load_json, save_json
|
||||||
|
@ -293,9 +294,9 @@ class UpdateShoppingListItemView(http.HomeAssistantView):
|
||||||
request.app["hass"].bus.async_fire(EVENT)
|
request.app["hass"].bus.async_fire(EVENT)
|
||||||
return self.json(item)
|
return self.json(item)
|
||||||
except KeyError:
|
except KeyError:
|
||||||
return self.json_message("Item not found", HTTP_NOT_FOUND)
|
return self.json_message("Item not found", HTTPStatus.NOT_FOUND)
|
||||||
except vol.Invalid:
|
except vol.Invalid:
|
||||||
return self.json_message("Item not found", HTTP_BAD_REQUEST)
|
return self.json_message("Item not found", HTTPStatus.BAD_REQUEST)
|
||||||
|
|
||||||
|
|
||||||
class CreateShoppingListItemView(http.HomeAssistantView):
|
class CreateShoppingListItemView(http.HomeAssistantView):
|
||||||
|
|
|
@ -1,16 +1,13 @@
|
||||||
"""Support for Telegram bots using webhooks."""
|
"""Support for Telegram bots using webhooks."""
|
||||||
import datetime as dt
|
import datetime as dt
|
||||||
|
from http import HTTPStatus
|
||||||
from ipaddress import ip_address
|
from ipaddress import ip_address
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from telegram.error import TimedOut
|
from telegram.error import TimedOut
|
||||||
|
|
||||||
from homeassistant.components.http import HomeAssistantView
|
from homeassistant.components.http import HomeAssistantView
|
||||||
from homeassistant.const import (
|
from homeassistant.const import EVENT_HOMEASSISTANT_STOP
|
||||||
EVENT_HOMEASSISTANT_STOP,
|
|
||||||
HTTP_BAD_REQUEST,
|
|
||||||
HTTP_UNAUTHORIZED,
|
|
||||||
)
|
|
||||||
from homeassistant.helpers.network import get_url
|
from homeassistant.helpers.network import get_url
|
||||||
|
|
||||||
from . import (
|
from . import (
|
||||||
|
@ -98,13 +95,13 @@ class BotPushReceiver(HomeAssistantView, BaseTelegramBotEntity):
|
||||||
real_ip = ip_address(request.remote)
|
real_ip = ip_address(request.remote)
|
||||||
if not any(real_ip in net for net in self.trusted_networks):
|
if not any(real_ip in net for net in self.trusted_networks):
|
||||||
_LOGGER.warning("Access denied from %s", real_ip)
|
_LOGGER.warning("Access denied from %s", real_ip)
|
||||||
return self.json_message("Access denied", HTTP_UNAUTHORIZED)
|
return self.json_message("Access denied", HTTPStatus.UNAUTHORIZED)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
data = await request.json()
|
data = await request.json()
|
||||||
except ValueError:
|
except ValueError:
|
||||||
return self.json_message("Invalid JSON", HTTP_BAD_REQUEST)
|
return self.json_message("Invalid JSON", HTTPStatus.BAD_REQUEST)
|
||||||
|
|
||||||
if not self.process_message(data):
|
if not self.process_message(data):
|
||||||
return self.json_message("Invalid message", HTTP_BAD_REQUEST)
|
return self.json_message("Invalid message", HTTPStatus.BAD_REQUEST)
|
||||||
return None
|
return None
|
||||||
|
|
|
@ -4,6 +4,7 @@ from __future__ import annotations
|
||||||
import asyncio
|
import asyncio
|
||||||
import functools as ft
|
import functools as ft
|
||||||
import hashlib
|
import hashlib
|
||||||
|
from http import HTTPStatus
|
||||||
import io
|
import io
|
||||||
import logging
|
import logging
|
||||||
import mimetypes
|
import mimetypes
|
||||||
|
@ -29,7 +30,6 @@ from homeassistant.const import (
|
||||||
CONF_DESCRIPTION,
|
CONF_DESCRIPTION,
|
||||||
CONF_NAME,
|
CONF_NAME,
|
||||||
CONF_PLATFORM,
|
CONF_PLATFORM,
|
||||||
HTTP_BAD_REQUEST,
|
|
||||||
HTTP_NOT_FOUND,
|
HTTP_NOT_FOUND,
|
||||||
PLATFORM_FORMAT,
|
PLATFORM_FORMAT,
|
||||||
)
|
)
|
||||||
|
@ -598,10 +598,10 @@ class TextToSpeechUrlView(HomeAssistantView):
|
||||||
try:
|
try:
|
||||||
data = await request.json()
|
data = await request.json()
|
||||||
except ValueError:
|
except ValueError:
|
||||||
return self.json_message("Invalid JSON specified", HTTP_BAD_REQUEST)
|
return self.json_message("Invalid JSON specified", HTTPStatus.BAD_REQUEST)
|
||||||
if not data.get(ATTR_PLATFORM) and data.get(ATTR_MESSAGE):
|
if not data.get(ATTR_PLATFORM) and data.get(ATTR_MESSAGE):
|
||||||
return self.json_message(
|
return self.json_message(
|
||||||
"Must specify platform and message", HTTP_BAD_REQUEST
|
"Must specify platform and message", HTTPStatus.BAD_REQUEST
|
||||||
)
|
)
|
||||||
|
|
||||||
p_type = data[ATTR_PLATFORM]
|
p_type = data[ATTR_PLATFORM]
|
||||||
|
@ -616,7 +616,7 @@ class TextToSpeechUrlView(HomeAssistantView):
|
||||||
)
|
)
|
||||||
except HomeAssistantError as err:
|
except HomeAssistantError as err:
|
||||||
_LOGGER.error("Error on init tts: %s", err)
|
_LOGGER.error("Error on init tts: %s", err)
|
||||||
return self.json({"error": err}, HTTP_BAD_REQUEST)
|
return self.json({"error": err}, HTTPStatus.BAD_REQUEST)
|
||||||
|
|
||||||
base = self.tts.base_url or get_url(self.tts.hass)
|
base = self.tts.base_url or get_url(self.tts.hass)
|
||||||
url = base + path
|
url = base + path
|
||||||
|
|
|
@ -507,7 +507,7 @@ class ConfigEntryWithingsApi(AbstractWithingsApi):
|
||||||
|
|
||||||
def json_message_response(message: str, message_code: int) -> Response:
|
def json_message_response(message: str, message_code: int) -> Response:
|
||||||
"""Produce common json output."""
|
"""Produce common json output."""
|
||||||
return HomeAssistantView.json({"message": message, "code": message_code}, 200)
|
return HomeAssistantView.json({"message": message, "code": message_code})
|
||||||
|
|
||||||
|
|
||||||
class WebhookAvailability(IntEnum):
|
class WebhookAvailability(IntEnum):
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
"""Helpers for the data entry flow."""
|
"""Helpers for the data entry flow."""
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from http import HTTPStatus
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from aiohttp import web
|
from aiohttp import web
|
||||||
|
@ -9,7 +10,6 @@ import voluptuous as vol
|
||||||
from homeassistant import config_entries, data_entry_flow
|
from homeassistant import config_entries, data_entry_flow
|
||||||
from homeassistant.components.http import HomeAssistantView
|
from homeassistant.components.http import HomeAssistantView
|
||||||
from homeassistant.components.http.data_validator import RequestDataValidator
|
from homeassistant.components.http.data_validator import RequestDataValidator
|
||||||
from homeassistant.const import HTTP_BAD_REQUEST, HTTP_NOT_FOUND
|
|
||||||
import homeassistant.helpers.config_validation as cv
|
import homeassistant.helpers.config_validation as cv
|
||||||
|
|
||||||
|
|
||||||
|
@ -77,9 +77,11 @@ class FlowManagerIndexView(_BaseFlowManagerView):
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
except data_entry_flow.UnknownHandler:
|
except data_entry_flow.UnknownHandler:
|
||||||
return self.json_message("Invalid handler specified", HTTP_NOT_FOUND)
|
return self.json_message("Invalid handler specified", HTTPStatus.NOT_FOUND)
|
||||||
except data_entry_flow.UnknownStep:
|
except data_entry_flow.UnknownStep:
|
||||||
return self.json_message("Handler does not support user", HTTP_BAD_REQUEST)
|
return self.json_message(
|
||||||
|
"Handler does not support user", HTTPStatus.BAD_REQUEST
|
||||||
|
)
|
||||||
|
|
||||||
result = self._prepare_result_json(result)
|
result = self._prepare_result_json(result)
|
||||||
|
|
||||||
|
@ -94,7 +96,7 @@ class FlowManagerResourceView(_BaseFlowManagerView):
|
||||||
try:
|
try:
|
||||||
result = await self._flow_mgr.async_configure(flow_id)
|
result = await self._flow_mgr.async_configure(flow_id)
|
||||||
except data_entry_flow.UnknownFlow:
|
except data_entry_flow.UnknownFlow:
|
||||||
return self.json_message("Invalid flow specified", HTTP_NOT_FOUND)
|
return self.json_message("Invalid flow specified", HTTPStatus.NOT_FOUND)
|
||||||
|
|
||||||
result = self._prepare_result_json(result)
|
result = self._prepare_result_json(result)
|
||||||
|
|
||||||
|
@ -108,9 +110,9 @@ class FlowManagerResourceView(_BaseFlowManagerView):
|
||||||
try:
|
try:
|
||||||
result = await self._flow_mgr.async_configure(flow_id, data)
|
result = await self._flow_mgr.async_configure(flow_id, data)
|
||||||
except data_entry_flow.UnknownFlow:
|
except data_entry_flow.UnknownFlow:
|
||||||
return self.json_message("Invalid flow specified", HTTP_NOT_FOUND)
|
return self.json_message("Invalid flow specified", HTTPStatus.NOT_FOUND)
|
||||||
except vol.Invalid:
|
except vol.Invalid:
|
||||||
return self.json_message("User input malformed", HTTP_BAD_REQUEST)
|
return self.json_message("User input malformed", HTTPStatus.BAD_REQUEST)
|
||||||
|
|
||||||
result = self._prepare_result_json(result)
|
result = self._prepare_result_json(result)
|
||||||
|
|
||||||
|
@ -121,6 +123,6 @@ class FlowManagerResourceView(_BaseFlowManagerView):
|
||||||
try:
|
try:
|
||||||
self._flow_mgr.async_abort(flow_id)
|
self._flow_mgr.async_abort(flow_id)
|
||||||
except data_entry_flow.UnknownFlow:
|
except data_entry_flow.UnknownFlow:
|
||||||
return self.json_message("Invalid flow specified", HTTP_NOT_FOUND)
|
return self.json_message("Invalid flow specified", HTTPStatus.NOT_FOUND)
|
||||||
|
|
||||||
return self.json_message("Flow aborted")
|
return self.json_message("Flow aborted")
|
||||||
|
|
|
@ -455,7 +455,7 @@ async def test_set_protection_value(hass, client):
|
||||||
assert resp.status == 200
|
assert resp.status == 200
|
||||||
result = await resp.json()
|
result = await resp.json()
|
||||||
assert node.set_protection.called
|
assert node.set_protection.called
|
||||||
assert result == {"message": "Protection setting succsessfully set"}
|
assert result == {"message": "Protection setting successfully set"}
|
||||||
|
|
||||||
|
|
||||||
async def test_set_protection_value_failed(hass, client):
|
async def test_set_protection_value_failed(hass, client):
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue