Black
This commit is contained in:
parent
da05dfe708
commit
4de97abc3a
2676 changed files with 163166 additions and 140084 deletions
|
@ -71,8 +71,7 @@ import voluptuous as vol
|
|||
|
||||
from homeassistant import data_entry_flow
|
||||
from homeassistant.components.http import KEY_REAL_IP
|
||||
from homeassistant.components.http.ban import process_wrong_login, \
|
||||
log_invalid_auth
|
||||
from homeassistant.components.http.ban import process_wrong_login, log_invalid_auth
|
||||
from homeassistant.components.http.data_validator import RequestDataValidator
|
||||
from homeassistant.components.http.view import HomeAssistantView
|
||||
from . import indieauth
|
||||
|
@ -81,56 +80,55 @@ from . import indieauth
|
|||
async def async_setup(hass, store_result):
|
||||
"""Component to allow users to login."""
|
||||
hass.http.register_view(AuthProvidersView)
|
||||
hass.http.register_view(
|
||||
LoginFlowIndexView(hass.auth.login_flow, store_result))
|
||||
hass.http.register_view(
|
||||
LoginFlowResourceView(hass.auth.login_flow, store_result))
|
||||
hass.http.register_view(LoginFlowIndexView(hass.auth.login_flow, store_result))
|
||||
hass.http.register_view(LoginFlowResourceView(hass.auth.login_flow, store_result))
|
||||
|
||||
|
||||
class AuthProvidersView(HomeAssistantView):
|
||||
"""View to get available auth providers."""
|
||||
|
||||
url = '/auth/providers'
|
||||
name = 'api:auth:providers'
|
||||
url = "/auth/providers"
|
||||
name = "api:auth:providers"
|
||||
requires_auth = False
|
||||
|
||||
async def get(self, request):
|
||||
"""Get available auth providers."""
|
||||
hass = request.app['hass']
|
||||
hass = request.app["hass"]
|
||||
if not hass.components.onboarding.async_is_user_onboarded():
|
||||
return self.json_message(
|
||||
message='Onboarding not finished',
|
||||
message="Onboarding not finished",
|
||||
status_code=400,
|
||||
message_code='onboarding_required'
|
||||
message_code="onboarding_required",
|
||||
)
|
||||
|
||||
return self.json([{
|
||||
'name': provider.name,
|
||||
'id': provider.id,
|
||||
'type': provider.type,
|
||||
} for provider in hass.auth.auth_providers])
|
||||
return self.json(
|
||||
[
|
||||
{"name": provider.name, "id": provider.id, "type": provider.type}
|
||||
for provider in hass.auth.auth_providers
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
def _prepare_result_json(result):
|
||||
"""Convert result to JSON."""
|
||||
if result['type'] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY:
|
||||
if result["type"] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY:
|
||||
data = result.copy()
|
||||
data.pop('result')
|
||||
data.pop('data')
|
||||
data.pop("result")
|
||||
data.pop("data")
|
||||
return data
|
||||
|
||||
if result['type'] != data_entry_flow.RESULT_TYPE_FORM:
|
||||
if result["type"] != data_entry_flow.RESULT_TYPE_FORM:
|
||||
return result
|
||||
|
||||
import voluptuous_serialize
|
||||
|
||||
data = result.copy()
|
||||
|
||||
schema = data['data_schema']
|
||||
schema = data["data_schema"]
|
||||
if schema is None:
|
||||
data['data_schema'] = []
|
||||
data["data_schema"] = []
|
||||
else:
|
||||
data['data_schema'] = voluptuous_serialize.convert(schema)
|
||||
data["data_schema"] = voluptuous_serialize.convert(schema)
|
||||
|
||||
return data
|
||||
|
||||
|
@ -138,8 +136,8 @@ def _prepare_result_json(result):
|
|||
class LoginFlowIndexView(HomeAssistantView):
|
||||
"""View to create a config flow."""
|
||||
|
||||
url = '/auth/login_flow'
|
||||
name = 'api:auth:login_flow'
|
||||
url = "/auth/login_flow"
|
||||
name = "api:auth:login_flow"
|
||||
requires_auth = False
|
||||
|
||||
def __init__(self, flow_mgr, store_result):
|
||||
|
@ -151,39 +149,45 @@ class LoginFlowIndexView(HomeAssistantView):
|
|||
"""Do not allow index of flows in progress."""
|
||||
return web.Response(status=405)
|
||||
|
||||
@RequestDataValidator(vol.Schema({
|
||||
vol.Required('client_id'): str,
|
||||
vol.Required('handler'): vol.Any(str, list),
|
||||
vol.Required('redirect_uri'): str,
|
||||
vol.Optional('type', default='authorize'): str,
|
||||
}))
|
||||
@RequestDataValidator(
|
||||
vol.Schema(
|
||||
{
|
||||
vol.Required("client_id"): str,
|
||||
vol.Required("handler"): vol.Any(str, list),
|
||||
vol.Required("redirect_uri"): str,
|
||||
vol.Optional("type", default="authorize"): str,
|
||||
}
|
||||
)
|
||||
)
|
||||
@log_invalid_auth
|
||||
async def post(self, request, data):
|
||||
"""Create a new login flow."""
|
||||
if not await indieauth.verify_redirect_uri(
|
||||
request.app['hass'], data['client_id'], data['redirect_uri']):
|
||||
return self.json_message('invalid client id or redirect uri', 400)
|
||||
request.app["hass"], data["client_id"], data["redirect_uri"]
|
||||
):
|
||||
return self.json_message("invalid client id or redirect uri", 400)
|
||||
|
||||
if isinstance(data['handler'], list):
|
||||
handler = tuple(data['handler'])
|
||||
if isinstance(data["handler"], list):
|
||||
handler = tuple(data["handler"])
|
||||
else:
|
||||
handler = data['handler']
|
||||
handler = data["handler"]
|
||||
|
||||
try:
|
||||
result = await self._flow_mgr.async_init(
|
||||
handler, context={
|
||||
'ip_address': request[KEY_REAL_IP],
|
||||
'credential_only': data.get('type') == 'link_user',
|
||||
})
|
||||
handler,
|
||||
context={
|
||||
"ip_address": request[KEY_REAL_IP],
|
||||
"credential_only": data.get("type") == "link_user",
|
||||
},
|
||||
)
|
||||
except data_entry_flow.UnknownHandler:
|
||||
return self.json_message('Invalid handler specified', 404)
|
||||
return self.json_message("Invalid handler specified", 404)
|
||||
except data_entry_flow.UnknownStep:
|
||||
return self.json_message('Handler does not support init', 400)
|
||||
return self.json_message("Handler does not support init", 400)
|
||||
|
||||
if result['type'] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY:
|
||||
result.pop('data')
|
||||
result['result'] = self._store_result(
|
||||
data['client_id'], result['result'])
|
||||
if result["type"] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY:
|
||||
result.pop("data")
|
||||
result["result"] = self._store_result(data["client_id"], result["result"])
|
||||
return self.json(result)
|
||||
|
||||
return self.json(_prepare_result_json(result))
|
||||
|
@ -192,8 +196,8 @@ class LoginFlowIndexView(HomeAssistantView):
|
|||
class LoginFlowResourceView(HomeAssistantView):
|
||||
"""View to interact with the flow manager."""
|
||||
|
||||
url = '/auth/login_flow/{flow_id}'
|
||||
name = 'api:auth:login_flow:resource'
|
||||
url = "/auth/login_flow/{flow_id}"
|
||||
name = "api:auth:login_flow:resource"
|
||||
requires_auth = False
|
||||
|
||||
def __init__(self, flow_mgr, store_result):
|
||||
|
@ -203,44 +207,43 @@ class LoginFlowResourceView(HomeAssistantView):
|
|||
|
||||
async def get(self, request):
|
||||
"""Do not allow getting status of a flow in progress."""
|
||||
return self.json_message('Invalid flow specified', 404)
|
||||
return self.json_message("Invalid flow specified", 404)
|
||||
|
||||
@RequestDataValidator(vol.Schema({
|
||||
'client_id': str
|
||||
}, extra=vol.ALLOW_EXTRA))
|
||||
@RequestDataValidator(vol.Schema({"client_id": str}, extra=vol.ALLOW_EXTRA))
|
||||
@log_invalid_auth
|
||||
async def post(self, request, flow_id, data):
|
||||
"""Handle progressing a login flow request."""
|
||||
client_id = data.pop('client_id')
|
||||
client_id = data.pop("client_id")
|
||||
|
||||
if not indieauth.verify_client_id(client_id):
|
||||
return self.json_message('Invalid client id', 400)
|
||||
return self.json_message("Invalid client id", 400)
|
||||
|
||||
try:
|
||||
# do not allow change ip during login flow
|
||||
for flow in self._flow_mgr.async_progress():
|
||||
if (flow['flow_id'] == flow_id and
|
||||
flow['context']['ip_address'] !=
|
||||
request.get(KEY_REAL_IP)):
|
||||
return self.json_message('IP address changed', 400)
|
||||
if flow["flow_id"] == flow_id and flow["context"][
|
||||
"ip_address"
|
||||
] != request.get(KEY_REAL_IP):
|
||||
return self.json_message("IP address changed", 400)
|
||||
|
||||
result = await self._flow_mgr.async_configure(flow_id, data)
|
||||
except data_entry_flow.UnknownFlow:
|
||||
return self.json_message('Invalid flow specified', 404)
|
||||
return self.json_message("Invalid flow specified", 404)
|
||||
except vol.Invalid:
|
||||
return self.json_message('User input malformed', 400)
|
||||
return self.json_message("User input malformed", 400)
|
||||
|
||||
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
|
||||
# need manually log failed login attempts
|
||||
if (result.get('errors') is not None and
|
||||
result['errors'].get('base') in ['invalid_auth',
|
||||
'invalid_code']):
|
||||
if result.get("errors") is not None and result["errors"].get("base") in [
|
||||
"invalid_auth",
|
||||
"invalid_code",
|
||||
]:
|
||||
await process_wrong_login(request)
|
||||
return self.json(_prepare_result_json(result))
|
||||
|
||||
result.pop('data')
|
||||
result['result'] = self._store_result(client_id, result['result'])
|
||||
result.pop("data")
|
||||
result["result"] = self._store_result(client_id, result["result"])
|
||||
|
||||
return self.json(result)
|
||||
|
||||
|
@ -249,6 +252,6 @@ class LoginFlowResourceView(HomeAssistantView):
|
|||
try:
|
||||
self._flow_mgr.async_abort(flow_id)
|
||||
except data_entry_flow.UnknownFlow:
|
||||
return self.json_message('Invalid flow specified', 404)
|
||||
return self.json_message("Invalid flow specified", 404)
|
||||
|
||||
return self.json_message('Flow aborted')
|
||||
return self.json_message("Flow aborted")
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue