From f351f35eb56e02cb3253e8f7ec741d0bb89e0cb6 Mon Sep 17 00:00:00 2001
From: Tamas Gal <tgal@km3net.de>
Date: Sat, 23 Feb 2019 10:32:50 +0100
Subject: [PATCH] Add authentication option. Closes #7

---
 app/routes.py | 51 +++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 49 insertions(+), 2 deletions(-)

diff --git a/app/routes.py b/app/routes.py
index 4029298..925e0da 100644
--- a/app/routes.py
+++ b/app/routes.py
@@ -1,8 +1,13 @@
-from os.path import join
-from flask import render_template, send_from_directory
+from os.path import join, exists
+from functools import wraps
+import toml
+from flask import render_template, send_from_directory, request, Response
 from app import app
 
+CONFIG_PATH = "pipeline.toml"
 PLOTS_PATH = "../plots"
+USERNAME = None
+PASSWORD = None
 app.config['FREEZER_DESTINATION'] = '../km3web'
 
 PLOTS = [['dom_activity', 'dom_rates'], ['pmt_rates', 'pmt_hrv'],
@@ -13,6 +18,42 @@ TRIGGER_PLOTS = [['trigger_rates'], ['trigger_rates_lin']]
 K40_PLOTS = [['intradom'], ['angular_k40rate_distribution']]
 RTTC_PLOTS = [['rttc']]
 
+if exists(CONFIG_PATH):
+    config = toml.load(CONFIG_PATH)
+    if "WebServer" in config:
+        print("Reading authentication information from '%s'" % CONFIG_PATH)
+        USERNAME = config["WebServer"]["username"]
+        PASSWORD = config["WebServer"]["password"]
+
+
+def check_auth(username, password):
+    """This function is called to check if a username /
+    password combination is valid.
+    """
+    if USERNAME is not None and PASSWORD is not None:
+        return username == USERNAME and password == PASSWORD
+    else:
+        return True
+
+
+def authenticate():
+    """Sends a 401 response that enables basic auth"""
+    return Response(
+        'Could not verify your access level for that URL.\n'
+        'You have to login with proper credentials', 401,
+        {'WWW-Authenticate': 'Basic realm="Login Required"'})
+
+
+def requires_auth(f):
+    @wraps(f)
+    def decorated(*args, **kwargs):
+        auth = request.authorization
+        if not auth or not check_auth(auth.username, auth.password):
+            return authenticate()
+        return f(*args, **kwargs)
+
+    return decorated
+
 
 @app.after_request
 def add_header(r):
@@ -28,16 +69,19 @@ def add_header(r):
 
 @app.route('/')
 @app.route('/index.html')
+@requires_auth
 def index():
     return render_template('plots.html', plots=PLOTS)
 
 
 @app.route('/ahrs.html')
+@requires_auth
 def ahrs():
     return render_template('plots.html', plots=AHRS_PLOTS)
 
 
 @app.route('/rttc.html')
+@requires_auth
 def rttc():
     return render_template(
         'plots.html',
@@ -50,6 +94,7 @@ def rttc():
 
 
 @app.route('/k40.html')
+@requires_auth
 def k40():
     return render_template(
         'plots.html',
@@ -62,11 +107,13 @@ def k40():
 
 
 @app.route('/trigger.html')
+@requires_auth
 def trigger():
     return render_template('plots.html', plots=TRIGGER_PLOTS)
 
 
 @app.route('/plots/<path:filename>')
+@requires_auth
 def custom_static(filename):
     print(filename)
     filepath = join(app.root_path, PLOTS_PATH)
-- 
GitLab