commit
27351880e2
2 changed files with 34 additions and 10 deletions
|
@ -1,3 +1,8 @@
|
||||||
|
Version 0.3.2 (2018-08-09)
|
||||||
|
- Allow `PASSWORD` to be numeric (Issue #108) @danielperna84
|
||||||
|
- Sanity check for `ALLOWED_NETWORKS`, `BANNED_IPS` and `IGNORE_PATTERN` (Issue #109) @danielperna84
|
||||||
|
- Reading files as UTF-8 (Issue #80) @danielperna84
|
||||||
|
|
||||||
Version 0.3.1 (2018-07-15)
|
Version 0.3.1 (2018-07-15)
|
||||||
- Fix SESAME / SESAME_TOTP_SECRET bug (Issue #103) @danielperna84
|
- Fix SESAME / SESAME_TOTP_SECRET bug (Issue #103) @danielperna84
|
||||||
- Added client IP to network status modal @danielperna84
|
- Added client IP to network status modal @danielperna84
|
||||||
|
|
|
@ -101,7 +101,7 @@ SO.setFormatter(
|
||||||
logging.Formatter('%(levelname)s:%(asctime)s:%(name)s:%(message)s'))
|
logging.Formatter('%(levelname)s:%(asctime)s:%(name)s:%(message)s'))
|
||||||
LOG.addHandler(SO)
|
LOG.addHandler(SO)
|
||||||
RELEASEURL = "https://api.github.com/repos/danielperna84/hass-configurator/releases/latest"
|
RELEASEURL = "https://api.github.com/repos/danielperna84/hass-configurator/releases/latest"
|
||||||
VERSION = "0.3.1"
|
VERSION = "0.3.2"
|
||||||
BASEDIR = "."
|
BASEDIR = "."
|
||||||
DEV = False
|
DEV = False
|
||||||
LISTENPORT = None
|
LISTENPORT = None
|
||||||
|
@ -3489,10 +3489,31 @@ def load_settings(settingsfile):
|
||||||
HASS_API_PASSWORD = settings.get("HASS_API_PASSWORD", HASS_API_PASSWORD)
|
HASS_API_PASSWORD = settings.get("HASS_API_PASSWORD", HASS_API_PASSWORD)
|
||||||
CREDENTIALS = settings.get("CREDENTIALS", CREDENTIALS)
|
CREDENTIALS = settings.get("CREDENTIALS", CREDENTIALS)
|
||||||
ALLOWED_NETWORKS = settings.get("ALLOWED_NETWORKS", ALLOWED_NETWORKS)
|
ALLOWED_NETWORKS = settings.get("ALLOWED_NETWORKS", ALLOWED_NETWORKS)
|
||||||
|
if ALLOWED_NETWORKS and not all(ALLOWED_NETWORKS):
|
||||||
|
LOG.warning("Invalid value for ALLOWED_NETWORKS. Using empty list.")
|
||||||
|
ALLOWED_NETWORKS = []
|
||||||
|
for net in ALLOWED_NETWORKS:
|
||||||
|
try:
|
||||||
|
ipaddress.ip_network(net)
|
||||||
|
except Exception:
|
||||||
|
LOG.warning("Invalid network in ALLOWED_NETWORKS: %s", net)
|
||||||
|
ALLOWED_NETWORKS.remove(net)
|
||||||
BANNED_IPS = settings.get("BANNED_IPS", BANNED_IPS)
|
BANNED_IPS = settings.get("BANNED_IPS", BANNED_IPS)
|
||||||
|
if BANNED_IPS and not all(BANNED_IPS):
|
||||||
|
LOG.warning("Invalid value for BANNED_IPS. Using empty list.")
|
||||||
|
BANNED_IPS = []
|
||||||
|
for banned_ip in BANNED_IPS:
|
||||||
|
try:
|
||||||
|
ipaddress.ip_address(banned_ip)
|
||||||
|
except Exception:
|
||||||
|
LOG.warning("Invalid IP address in BANNED_IPS: %s", banned_ip)
|
||||||
|
BANNED_IPS.remove(banned_ip)
|
||||||
BANLIMIT = settings.get("BANLIMIT", BANLIMIT)
|
BANLIMIT = settings.get("BANLIMIT", BANLIMIT)
|
||||||
DEV = settings.get("DEV", DEV)
|
DEV = settings.get("DEV", DEV)
|
||||||
IGNORE_PATTERN = settings.get("IGNORE_PATTERN", IGNORE_PATTERN)
|
IGNORE_PATTERN = settings.get("IGNORE_PATTERN", IGNORE_PATTERN)
|
||||||
|
if IGNORE_PATTERN and not all(IGNORE_PATTERN):
|
||||||
|
LOG.warning("Invalid value for IGNORE_PATTERN. Using empty list.")
|
||||||
|
IGNORE_PATTERN = []
|
||||||
DIRSFIRST = settings.get("DIRSFIRST", DIRSFIRST)
|
DIRSFIRST = settings.get("DIRSFIRST", DIRSFIRST)
|
||||||
SESAME = settings.get("SESAME", SESAME)
|
SESAME = settings.get("SESAME", SESAME)
|
||||||
SESAME_TOTP_SECRET = settings.get("SESAME_TOTP_SECRET", SESAME_TOTP_SECRET)
|
SESAME_TOTP_SECRET = settings.get("SESAME_TOTP_SECRET", SESAME_TOTP_SECRET)
|
||||||
|
@ -3504,6 +3525,7 @@ def load_settings(settingsfile):
|
||||||
ssl._create_default_https_context = ssl._create_unverified_context
|
ssl._create_default_https_context = ssl._create_unverified_context
|
||||||
USERNAME = settings.get("USERNAME", USERNAME)
|
USERNAME = settings.get("USERNAME", USERNAME)
|
||||||
PASSWORD = settings.get("PASSWORD", PASSWORD)
|
PASSWORD = settings.get("PASSWORD", PASSWORD)
|
||||||
|
PASSWORD = str(PASSWORD) if PASSWORD else None
|
||||||
if CREDENTIALS and (USERNAME is None or PASSWORD is None):
|
if CREDENTIALS and (USERNAME is None or PASSWORD is None):
|
||||||
USERNAME = CREDENTIALS.split(":")[0]
|
USERNAME = CREDENTIALS.split(":")[0]
|
||||||
PASSWORD = ":".join(CREDENTIALS.split(":")[1:])
|
PASSWORD = ":".join(CREDENTIALS.split(":")[1:])
|
||||||
|
@ -3663,7 +3685,6 @@ class RequestHandler(BaseHTTPRequestHandler):
|
||||||
# pylint: disable=redefined-builtin
|
# pylint: disable=redefined-builtin
|
||||||
def log_message(self, format, *args):
|
def log_message(self, format, *args):
|
||||||
LOG.info("%s - %s" % (self.client_address[0], format % args))
|
LOG.info("%s - %s" % (self.client_address[0], format % args))
|
||||||
return
|
|
||||||
|
|
||||||
# pylint: disable=invalid-name
|
# pylint: disable=invalid-name
|
||||||
def do_BLOCK(self, status=420, reason="Policy not fulfilled"):
|
def do_BLOCK(self, status=420, reason="Policy not fulfilled"):
|
||||||
|
@ -3718,6 +3739,7 @@ class RequestHandler(BaseHTTPRequestHandler):
|
||||||
return
|
return
|
||||||
query = parse_qs(req.query)
|
query = parse_qs(req.query)
|
||||||
self.send_response(200)
|
self.send_response(200)
|
||||||
|
# pylint: disable=no-else-return
|
||||||
if req.path.endswith('/api/file'):
|
if req.path.endswith('/api/file'):
|
||||||
content = ""
|
content = ""
|
||||||
self.send_header('Content-type', 'text/text')
|
self.send_header('Content-type', 'text/text')
|
||||||
|
@ -3729,8 +3751,8 @@ class RequestHandler(BaseHTTPRequestHandler):
|
||||||
if ENFORCE_BASEPATH and not is_safe_path(BASEPATH, filename):
|
if ENFORCE_BASEPATH and not is_safe_path(BASEPATH, filename):
|
||||||
raise OSError('Access denied.')
|
raise OSError('Access denied.')
|
||||||
if os.path.isfile(os.path.join(BASEDIR.encode('utf-8'), filename)):
|
if os.path.isfile(os.path.join(BASEDIR.encode('utf-8'), filename)):
|
||||||
with open(os.path.join(BASEDIR.encode('utf-8'), filename)) as fptr:
|
with open(os.path.join(BASEDIR.encode('utf-8'), filename), 'rb') as fptr:
|
||||||
content += fptr.read()
|
content += fptr.read().decode('utf-8')
|
||||||
else:
|
else:
|
||||||
content = "File not found"
|
content = "File not found"
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
|
@ -3756,7 +3778,6 @@ class RequestHandler(BaseHTTPRequestHandler):
|
||||||
self.end_headers()
|
self.end_headers()
|
||||||
self.wfile.write(filecontent)
|
self.wfile.write(filecontent)
|
||||||
return
|
return
|
||||||
else:
|
|
||||||
content = "File not found"
|
content = "File not found"
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
LOG.warning(err)
|
LOG.warning(err)
|
||||||
|
@ -4692,7 +4713,6 @@ class AuthHandler(RequestHandler):
|
||||||
LOG.warning("Blocking access from %s" % self.client_address[0])
|
LOG.warning("Blocking access from %s" % self.client_address[0])
|
||||||
self.do_BLOCK()
|
self.do_BLOCK()
|
||||||
return
|
return
|
||||||
else:
|
|
||||||
FAIL2BAN_IPS[self.client_address[0]] = bancounter + 1
|
FAIL2BAN_IPS[self.client_address[0]] = bancounter + 1
|
||||||
self.do_AUTHHEAD()
|
self.do_AUTHHEAD()
|
||||||
self.wfile.write(bytes('Authentication required', 'utf-8'))
|
self.wfile.write(bytes('Authentication required', 'utf-8'))
|
||||||
|
@ -4725,7 +4745,6 @@ class AuthHandler(RequestHandler):
|
||||||
LOG.warning("Blocking access from %s" % self.client_address[0])
|
LOG.warning("Blocking access from %s" % self.client_address[0])
|
||||||
self.do_BLOCK()
|
self.do_BLOCK()
|
||||||
return
|
return
|
||||||
else:
|
|
||||||
FAIL2BAN_IPS[self.client_address[0]] = bancounter + 1
|
FAIL2BAN_IPS[self.client_address[0]] = bancounter + 1
|
||||||
self.do_AUTHHEAD()
|
self.do_AUTHHEAD()
|
||||||
self.wfile.write(bytes('Authentication required', 'utf-8'))
|
self.wfile.write(bytes('Authentication required', 'utf-8'))
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue