Skip to content

Commit

Permalink
Use decorator to clean up code
Browse files Browse the repository at this point in the history
  • Loading branch information
awarecan committed Jul 20, 2018
1 parent 94dde04 commit 4d011ae
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 19 deletions.
29 changes: 11 additions & 18 deletions homeassistant/components/auth/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,8 @@
import voluptuous as vol

from homeassistant import data_entry_flow
from homeassistant.components.http.ban import process_wrong_login
from homeassistant.components.http.ban import process_wrong_login, \
log_invalid_auth
from homeassistant.core import callback
from homeassistant.helpers.data_entry_flow import (
FlowManagerIndexView, FlowManagerResourceView)
Expand Down Expand Up @@ -184,11 +185,11 @@ async def get(self, request):
vol.Required('handler'): vol.Any(str, list),
vol.Required('redirect_uri'): str,
}))
@log_invalid_auth
async def post(self, request, data):
"""Create a new login flow."""
if not indieauth.verify_redirect_uri(data['client_id'],
data['redirect_uri']):
await process_wrong_login(request)
return self.json_message('invalid client id or redirect uri', 400)

# pylint: disable=no-value-for-parameter
Expand All @@ -214,24 +215,24 @@ async def get(self, request, flow_id):
@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')

if not indieauth.verify_client_id(client_id):
await process_wrong_login(request)
return self.json_message('Invalid client id', 400)

try:
result = await self._flow_mgr.async_configure(flow_id, data)
except data_entry_flow.UnknownFlow:
await process_wrong_login(request)
return self.json_message('Invalid flow specified', 404)
except vol.Invalid:
await process_wrong_login(request)
return self.json_message('User input malformed', 400)

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['errors'] is not None and \
result['errors'].get('base') == 'invalid_auth':
await process_wrong_login(request)
Expand All @@ -255,14 +256,14 @@ def __init__(self, retrieve_credentials):
"""Initialize the grant token view."""
self._retrieve_credentials = retrieve_credentials

@log_invalid_auth
async def post(self, request):
"""Grant a token."""
hass = request.app['hass']
data = await request.post()

client_id = data.get('client_id')
if client_id is None or not indieauth.verify_client_id(client_id):
await process_wrong_login(request)
return self.json({
'error': 'invalid_request',
'error_description': 'Invalid client id',
Expand All @@ -271,32 +272,28 @@ async def post(self, request):
grant_type = data.get('grant_type')

if grant_type == 'authorization_code':
return await self._async_handle_auth_code(
hass, request, client_id, data)
return await self._async_handle_auth_code(hass, client_id, data)

elif grant_type == 'refresh_token':
return await self._async_handle_refresh_token(
hass, request, client_id, data)
hass, client_id, data)

await process_wrong_login(request)
return self.json({
'error': 'unsupported_grant_type',
}, status_code=400)

async def _async_handle_auth_code(self, hass, request, client_id, data):
async def _async_handle_auth_code(self, hass, client_id, data):
"""Handle authorization code request."""
code = data.get('code')

if code is None:
await process_wrong_login(request)
return self.json({
'error': 'invalid_request',
}, status_code=400)

credentials = self._retrieve_credentials(client_id, code)

if credentials is None:
await process_wrong_login(request)
return self.json({
'error': 'invalid_request',
'error_description': 'Invalid code',
Expand All @@ -305,7 +302,6 @@ async def _async_handle_auth_code(self, hass, request, client_id, data):
user = await hass.auth.async_get_or_create_user(credentials)

if not user.is_active:
await process_wrong_login(request)
return self.json({
'error': 'access_denied',
'error_description': 'User is not active',
Expand All @@ -323,21 +319,18 @@ async def _async_handle_auth_code(self, hass, request, client_id, data):
int(refresh_token.access_token_expiration.total_seconds()),
})

async def _async_handle_refresh_token(
self, hass, request, client_id, data):
async def _async_handle_refresh_token(self, hass, client_id, data):
"""Handle authorization code request."""
token = data.get('refresh_token')

if token is None:
await process_wrong_login(request)
return self.json({
'error': 'invalid_request',
}, status_code=400)

refresh_token = await hass.auth.async_get_refresh_token(token)

if refresh_token is None or refresh_token.client_id != client_id:
await process_wrong_login(request)
return self.json({
'error': 'invalid_grant',
}, status_code=400)
Expand Down
12 changes: 11 additions & 1 deletion homeassistant/components/http/ban.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
"""Ban logic for HTTP component."""

from collections import defaultdict
from datetime import datetime
from ipaddress import ip_address
Expand Down Expand Up @@ -71,6 +70,17 @@ async def ban_middleware(request, handler):
raise


def log_invalid_auth(func):
"""Decorator to handle invalid auth or failed login attempts."""
async def handle_req(view, request, *args, **kwargs):
"""Try to log failed login attempts if response status >= 400."""
resp = await func(view, request, *args, **kwargs)
if resp.status >= 400:
await process_wrong_login(request)
return resp
return handle_req


async def process_wrong_login(request):
"""Process a wrong login attempt.
Expand Down

0 comments on commit 4d011ae

Please sign in to comment.