Commit b9fc86c3c5f84bb4ca1baf542a78c50f626d4724

Authored by Antoine Goutenoir
1 parent 16f69d07
Exists in master

Secure the admin a little.

README.md
... ... @@ -18,6 +18,8 @@ Tested only on Python `2.7`. _Sprint._
18 18 source venv/bin/activate
19 19 pip install -r requirements.txt
20 20 python manage.py createdb
  21 + cp .env.dist .env
  22 + nano .env
21 23  
22 24  
23 25 ## Development
... ...
flaskr/__init__.py
1 1 #! ../venv/bin/python
  2 +import os
  3 +from dotenv import load_dotenv, find_dotenv
  4 +load_dotenv(find_dotenv())
2 5  
3   -from flask import Flask
  6 +
  7 +from flask import Flask, url_for
4 8 from flask.cli import ScriptInfo
5 9 from webassets.loaders import PythonLoader as PythonAssetsLoader
6 10  
... ... @@ -14,7 +18,8 @@ from flaskr.extensions import (
14 18 cache,
15 19 assets_env,
16 20 debug_toolbar,
17   - login_manager
  21 + login_manager,
  22 + basic_auth
18 23 )
19 24  
20 25 from flaskr.content import content
... ... @@ -48,6 +53,7 @@ def create_app(object_name):
48 53 login_manager.init_app(app)
49 54 admin.init_app(app)
50 55 admin.add_view(EstimationView(Estimation, db.session))
  56 + basic_auth.init_app(app)
51 57  
52 58 # Import and register the different asset bundles
53 59 assets_env.init_app(app)
... ... @@ -58,6 +64,9 @@ def create_app(object_name):
58 64 # register our blueprints
59 65 app.register_blueprint(main)
60 66  
  67 + app.config['BASIC_AUTH_USERNAME'] = os.getenv('ADMIN_USERNAME')
  68 + app.config['BASIC_AUTH_PASSWORD'] = os.getenv('ADMIN_PASSWORD')
  69 +
61 70 # VERSION (move to version.py is necessary)
62 71 version = "0.0.0"
63 72 with open('VERSION', 'r') as version_file:
... ... @@ -76,4 +85,20 @@ def create_app(object_name):
76 85 def markdown_filter(text):
77 86 return markdown(text)
78 87  
  88 + # Authentication Gate for the Admin
  89 + @app.before_first_request
  90 + def restrict_admin_url():
  91 +
  92 + # print('VF', app.view_functions)
  93 +
  94 + endpoint = 'admin.index'
  95 + url = url_for(endpoint)
  96 + admin_index = app.view_functions.pop(endpoint)
  97 +
  98 + @app.route(url, endpoint=endpoint)
  99 + @basic_auth.required
  100 + # @roles_required('admin')
  101 + def secure_admin_index():
  102 + return admin_index()
  103 +
79 104 return app
... ...
flaskr/controllers/main_controller.py
... ... @@ -6,7 +6,7 @@ from flask import Blueprint, render_template, flash, request, redirect, \
6 6 url_for, abort, send_from_directory
7 7 from os.path import join
8 8  
9   -from flaskr.extensions import cache
  9 +from flaskr.extensions import cache, basic_auth
10 10 from flaskr.forms import LoginForm, EstimateForm
11 11 from flaskr.models import db, User, Estimation, StatusEnum
12 12 from flaskr.geocoder import CachedGeocoder
... ... @@ -54,7 +54,7 @@ def estimate():
54 54 estimation.status = StatusEnum.pending
55 55 estimation.origin_addresses = form.origin_addresses.data
56 56 estimation.destination_addresses = form.destination_addresses.data
57   - estimation.compute_optimal_destination = form.compute_optimal_destination.data
  57 + # estimation.compute_optimal_destination = form.compute_optimal_destination.data
58 58  
59 59 db.session.add(estimation)
60 60 db.session.commit()
... ... @@ -376,8 +376,8 @@ def compute(): # process the queue of estimation requests
376 376 return _respond(response)
377 377  
378 378  
379   -@main.route("/estimation/<public_id>.<format>")
380   -def consult_estimation(public_id, format):
  379 +@main.route("/estimation/<public_id>.<extension>")
  380 +def consult_estimation(public_id, extension):
381 381 try:
382 382 estimation = Estimation.query \
383 383 .filter_by(public_id=public_id) \
... ... @@ -394,7 +394,7 @@ def consult_estimation(public_id, format):
394 394  
395 395 unavailable_statuses = [StatusEnum.pending, StatusEnum.working]
396 396  
397   - if format in ['xhtml', 'html', 'htm']:
  397 + if extension in ['xhtml', 'html', 'htm']:
398 398  
399 399 if estimation.status in unavailable_statuses:
400 400 return render_template(
... ... @@ -407,14 +407,14 @@ def consult_estimation(public_id, format):
407 407 estimation=estimation
408 408 )
409 409  
410   - elif format in ['yaml', 'yml']:
  410 + elif extension in ['yaml', 'yml']:
411 411  
412 412 if estimation.status in unavailable_statuses:
413 413 abort(404)
414 414  
415 415 return estimation.output_yaml
416 416  
417   - elif 'csv' == format:
  417 + elif 'csv' == extension:
418 418  
419 419 if estimation.status in unavailable_statuses:
420 420 abort(404)
... ... @@ -447,3 +447,11 @@ def consult_estimation(public_id, format):
447 447  
448 448 else:
449 449 abort(404)
  450 +
  451 +
  452 +@main.route("/test")
  453 +@basic_auth.required
  454 +def dev_test():
  455 + import os
  456 +
  457 + return os.getenv('ADMIN_USERNAME')
... ...
flaskr/extensions.py
1 1 from flask_admin import Admin
  2 +from flask_basicauth import BasicAuth
2 3 from flask_caching import Cache
3 4 from flask_debugtoolbar import DebugToolbarExtension
4 5 from flask_login import LoginManager
... ... @@ -19,6 +20,7 @@ login_manager.login_view = &quot;main.login&quot;
19 20 login_manager.login_message_category = "warning"
20 21  
21 22 admin = Admin()
  23 +basic_auth = BasicAuth()
22 24  
23 25  
24 26 @login_manager.user_loader
... ...
flaskr/templates/estimate.html
... ... @@ -73,9 +73,9 @@
73 73 {{ render_field(form.destination_addresses) }}
74 74 <small class="form-text text-muted">Provide multiple destinations to compare them.</small>
75 75 </div>
76   - <div class="form-check form-group">
77   - {{ render_checkbox(form.compute_optimal_destination) }}
78   - </div>
  76 +{# <div class="form-check form-group">#}
  77 +{# {{ render_checkbox(form.compute_optimal_destination) }}#}
  78 +{# </div>#}
79 79 <div class="form-check form-group">
80 80 {{ render_checkbox(form.use_atmosfair_rfi) }}
81 81 <small class="form-text text-muted">Disabled. Work in Progress. RFI=1.9</small>
... ...
requirements.txt
... ... @@ -3,6 +3,7 @@ Flask==1.1.1
3 3 # Flask Extensions
4 4 Flask-Admin==1.5.4
5 5 Flask-Assets==0.12
  6 +Flask-BasicAuth==0.2.0
6 7 Flask-Caching==1.7.2
7 8 Flask-DebugToolbar==0.10.0
8 9 Flask-Login==0.4.0
... ... @@ -19,6 +20,7 @@ Markdown==3.1.1
19 20 numpy==1.16.5
20 21 enum34==1.1.6
21 22 geopy==1.20.0
  23 +python-dotenv==0.10.3
22 24  
23 25 # Testing
24 26 pytest==3.0.5
... ...