Commit b9fc86c3c5f84bb4ca1baf542a78c50f626d4724
1 parent
16f69d07
Exists in
master
Secure the admin a little.
Showing
6 changed files
with
51 additions
and
12 deletions
Show diff stats
README.md
@@ -18,6 +18,8 @@ Tested only on Python `2.7`. _Sprint._ | @@ -18,6 +18,8 @@ Tested only on Python `2.7`. _Sprint._ | ||
18 | source venv/bin/activate | 18 | source venv/bin/activate |
19 | pip install -r requirements.txt | 19 | pip install -r requirements.txt |
20 | python manage.py createdb | 20 | python manage.py createdb |
21 | + cp .env.dist .env | ||
22 | + nano .env | ||
21 | 23 | ||
22 | 24 | ||
23 | ## Development | 25 | ## Development |
flaskr/__init__.py
1 | #! ../venv/bin/python | 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 | from flask.cli import ScriptInfo | 8 | from flask.cli import ScriptInfo |
5 | from webassets.loaders import PythonLoader as PythonAssetsLoader | 9 | from webassets.loaders import PythonLoader as PythonAssetsLoader |
6 | 10 | ||
@@ -14,7 +18,8 @@ from flaskr.extensions import ( | @@ -14,7 +18,8 @@ from flaskr.extensions import ( | ||
14 | cache, | 18 | cache, |
15 | assets_env, | 19 | assets_env, |
16 | debug_toolbar, | 20 | debug_toolbar, |
17 | - login_manager | 21 | + login_manager, |
22 | + basic_auth | ||
18 | ) | 23 | ) |
19 | 24 | ||
20 | from flaskr.content import content | 25 | from flaskr.content import content |
@@ -48,6 +53,7 @@ def create_app(object_name): | @@ -48,6 +53,7 @@ def create_app(object_name): | ||
48 | login_manager.init_app(app) | 53 | login_manager.init_app(app) |
49 | admin.init_app(app) | 54 | admin.init_app(app) |
50 | admin.add_view(EstimationView(Estimation, db.session)) | 55 | admin.add_view(EstimationView(Estimation, db.session)) |
56 | + basic_auth.init_app(app) | ||
51 | 57 | ||
52 | # Import and register the different asset bundles | 58 | # Import and register the different asset bundles |
53 | assets_env.init_app(app) | 59 | assets_env.init_app(app) |
@@ -58,6 +64,9 @@ def create_app(object_name): | @@ -58,6 +64,9 @@ def create_app(object_name): | ||
58 | # register our blueprints | 64 | # register our blueprints |
59 | app.register_blueprint(main) | 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 | # VERSION (move to version.py is necessary) | 70 | # VERSION (move to version.py is necessary) |
62 | version = "0.0.0" | 71 | version = "0.0.0" |
63 | with open('VERSION', 'r') as version_file: | 72 | with open('VERSION', 'r') as version_file: |
@@ -76,4 +85,20 @@ def create_app(object_name): | @@ -76,4 +85,20 @@ def create_app(object_name): | ||
76 | def markdown_filter(text): | 85 | def markdown_filter(text): |
77 | return markdown(text) | 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 | return app | 104 | return app |
flaskr/controllers/main_controller.py
@@ -6,7 +6,7 @@ from flask import Blueprint, render_template, flash, request, redirect, \ | @@ -6,7 +6,7 @@ from flask import Blueprint, render_template, flash, request, redirect, \ | ||
6 | url_for, abort, send_from_directory | 6 | url_for, abort, send_from_directory |
7 | from os.path import join | 7 | from os.path import join |
8 | 8 | ||
9 | -from flaskr.extensions import cache | 9 | +from flaskr.extensions import cache, basic_auth |
10 | from flaskr.forms import LoginForm, EstimateForm | 10 | from flaskr.forms import LoginForm, EstimateForm |
11 | from flaskr.models import db, User, Estimation, StatusEnum | 11 | from flaskr.models import db, User, Estimation, StatusEnum |
12 | from flaskr.geocoder import CachedGeocoder | 12 | from flaskr.geocoder import CachedGeocoder |
@@ -54,7 +54,7 @@ def estimate(): | @@ -54,7 +54,7 @@ def estimate(): | ||
54 | estimation.status = StatusEnum.pending | 54 | estimation.status = StatusEnum.pending |
55 | estimation.origin_addresses = form.origin_addresses.data | 55 | estimation.origin_addresses = form.origin_addresses.data |
56 | estimation.destination_addresses = form.destination_addresses.data | 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 | db.session.add(estimation) | 59 | db.session.add(estimation) |
60 | db.session.commit() | 60 | db.session.commit() |
@@ -376,8 +376,8 @@ def compute(): # process the queue of estimation requests | @@ -376,8 +376,8 @@ def compute(): # process the queue of estimation requests | ||
376 | return _respond(response) | 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 | try: | 381 | try: |
382 | estimation = Estimation.query \ | 382 | estimation = Estimation.query \ |
383 | .filter_by(public_id=public_id) \ | 383 | .filter_by(public_id=public_id) \ |
@@ -394,7 +394,7 @@ def consult_estimation(public_id, format): | @@ -394,7 +394,7 @@ def consult_estimation(public_id, format): | ||
394 | 394 | ||
395 | unavailable_statuses = [StatusEnum.pending, StatusEnum.working] | 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 | if estimation.status in unavailable_statuses: | 399 | if estimation.status in unavailable_statuses: |
400 | return render_template( | 400 | return render_template( |
@@ -407,14 +407,14 @@ def consult_estimation(public_id, format): | @@ -407,14 +407,14 @@ def consult_estimation(public_id, format): | ||
407 | estimation=estimation | 407 | estimation=estimation |
408 | ) | 408 | ) |
409 | 409 | ||
410 | - elif format in ['yaml', 'yml']: | 410 | + elif extension in ['yaml', 'yml']: |
411 | 411 | ||
412 | if estimation.status in unavailable_statuses: | 412 | if estimation.status in unavailable_statuses: |
413 | abort(404) | 413 | abort(404) |
414 | 414 | ||
415 | return estimation.output_yaml | 415 | return estimation.output_yaml |
416 | 416 | ||
417 | - elif 'csv' == format: | 417 | + elif 'csv' == extension: |
418 | 418 | ||
419 | if estimation.status in unavailable_statuses: | 419 | if estimation.status in unavailable_statuses: |
420 | abort(404) | 420 | abort(404) |
@@ -447,3 +447,11 @@ def consult_estimation(public_id, format): | @@ -447,3 +447,11 @@ def consult_estimation(public_id, format): | ||
447 | 447 | ||
448 | else: | 448 | else: |
449 | abort(404) | 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 | from flask_admin import Admin | 1 | from flask_admin import Admin |
2 | +from flask_basicauth import BasicAuth | ||
2 | from flask_caching import Cache | 3 | from flask_caching import Cache |
3 | from flask_debugtoolbar import DebugToolbarExtension | 4 | from flask_debugtoolbar import DebugToolbarExtension |
4 | from flask_login import LoginManager | 5 | from flask_login import LoginManager |
@@ -19,6 +20,7 @@ login_manager.login_view = "main.login" | @@ -19,6 +20,7 @@ login_manager.login_view = "main.login" | ||
19 | login_manager.login_message_category = "warning" | 20 | login_manager.login_message_category = "warning" |
20 | 21 | ||
21 | admin = Admin() | 22 | admin = Admin() |
23 | +basic_auth = BasicAuth() | ||
22 | 24 | ||
23 | 25 | ||
24 | @login_manager.user_loader | 26 | @login_manager.user_loader |
flaskr/templates/estimate.html
@@ -73,9 +73,9 @@ | @@ -73,9 +73,9 @@ | ||
73 | {{ render_field(form.destination_addresses) }} | 73 | {{ render_field(form.destination_addresses) }} |
74 | <small class="form-text text-muted">Provide multiple destinations to compare them.</small> | 74 | <small class="form-text text-muted">Provide multiple destinations to compare them.</small> |
75 | </div> | 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 | <div class="form-check form-group"> | 79 | <div class="form-check form-group"> |
80 | {{ render_checkbox(form.use_atmosfair_rfi) }} | 80 | {{ render_checkbox(form.use_atmosfair_rfi) }} |
81 | <small class="form-text text-muted">Disabled. Work in Progress. RFI=1.9</small> | 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,6 +3,7 @@ Flask==1.1.1 | ||
3 | # Flask Extensions | 3 | # Flask Extensions |
4 | Flask-Admin==1.5.4 | 4 | Flask-Admin==1.5.4 |
5 | Flask-Assets==0.12 | 5 | Flask-Assets==0.12 |
6 | +Flask-BasicAuth==0.2.0 | ||
6 | Flask-Caching==1.7.2 | 7 | Flask-Caching==1.7.2 |
7 | Flask-DebugToolbar==0.10.0 | 8 | Flask-DebugToolbar==0.10.0 |
8 | Flask-Login==0.4.0 | 9 | Flask-Login==0.4.0 |
@@ -19,6 +20,7 @@ Markdown==3.1.1 | @@ -19,6 +20,7 @@ Markdown==3.1.1 | ||
19 | numpy==1.16.5 | 20 | numpy==1.16.5 |
20 | enum34==1.1.6 | 21 | enum34==1.1.6 |
21 | geopy==1.20.0 | 22 | geopy==1.20.0 |
23 | +python-dotenv==0.10.3 | ||
22 | 24 | ||
23 | # Testing | 25 | # Testing |
24 | pytest==3.0.5 | 26 | pytest==3.0.5 |