apply authentication to the whole app, track exceptions
This commit is contained in:
parent
0a754d72a3
commit
d693db7dbb
@ -15,6 +15,7 @@ from atst.routes.workspaces import bp as workspace_routes
|
|||||||
from atst.routes.requests import requests_bp
|
from atst.routes.requests import requests_bp
|
||||||
from atst.routes.dev import bp as dev_routes
|
from atst.routes.dev import bp as dev_routes
|
||||||
from atst.domain.authnid.crl.validator import Validator
|
from atst.domain.authnid.crl.validator import Validator
|
||||||
|
from atst.domain.auth import apply_authentication
|
||||||
|
|
||||||
|
|
||||||
ENV = os.getenv("FLASK_ENV", "dev")
|
ENV = os.getenv("FLASK_ENV", "dev")
|
||||||
@ -47,6 +48,8 @@ def make_app(config):
|
|||||||
if ENV != "production":
|
if ENV != "production":
|
||||||
app.register_blueprint(dev_routes)
|
app.register_blueprint(dev_routes)
|
||||||
|
|
||||||
|
apply_authentication(app)
|
||||||
|
|
||||||
return app
|
return app
|
||||||
|
|
||||||
|
|
||||||
@ -136,3 +139,4 @@ def make_crl_validator(app):
|
|||||||
)
|
)
|
||||||
for e in app.crl_validator.errors:
|
for e in app.crl_validator.errors:
|
||||||
app.logger.error(e)
|
app.logger.error(e)
|
||||||
|
|
||||||
|
@ -1,22 +1,23 @@
|
|||||||
from functools import wraps
|
from flask import g, redirect, url_for, session, request
|
||||||
from flask import g, redirect, url_for, session
|
|
||||||
|
|
||||||
from atst.domain.users import Users
|
from atst.domain.users import Users
|
||||||
|
|
||||||
|
|
||||||
def login_required(f):
|
UNPROTECTED_ROUTES = ["atst.root", "atst.login_dev", "atst.login_redirect", "atst.unauthorized"]
|
||||||
|
|
||||||
@wraps(f)
|
def apply_authentication(app):
|
||||||
def decorated_function(*args, **kwargs):
|
@app.before_request
|
||||||
|
# pylint: disable=unused-variable
|
||||||
|
def enforce_login():
|
||||||
|
|
||||||
|
if not _unprotected_route(request):
|
||||||
user = get_current_user()
|
user = get_current_user()
|
||||||
if user:
|
if user:
|
||||||
g.current_user = user
|
g.current_user = user
|
||||||
return f(*args, **kwargs)
|
|
||||||
|
|
||||||
else:
|
else:
|
||||||
return redirect(url_for("atst.root"))
|
return redirect(url_for("atst.root"))
|
||||||
|
|
||||||
return decorated_function
|
|
||||||
|
|
||||||
def get_current_user():
|
def get_current_user():
|
||||||
user_id = session.get("user_id")
|
user_id = session.get("user_id")
|
||||||
@ -24,3 +25,8 @@ def get_current_user():
|
|||||||
return Users.get(user_id)
|
return Users.get(user_id)
|
||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
def _unprotected_route(request):
|
||||||
|
if request.endpoint in UNPROTECTED_ROUTES:
|
||||||
|
return True
|
||||||
|
|
||||||
|
@ -5,7 +5,6 @@ import pendulum
|
|||||||
from atst.domain.requests import Requests
|
from atst.domain.requests import Requests
|
||||||
from atst.domain.users import Users
|
from atst.domain.users import Users
|
||||||
from atst.domain.authnid.utils import parse_sdn
|
from atst.domain.authnid.utils import parse_sdn
|
||||||
from atst.domain.auth import login_required
|
|
||||||
|
|
||||||
bp = Blueprint("atst", __name__)
|
bp = Blueprint("atst", __name__)
|
||||||
|
|
||||||
@ -16,19 +15,16 @@ def root():
|
|||||||
|
|
||||||
|
|
||||||
@bp.route("/home")
|
@bp.route("/home")
|
||||||
@login_required
|
|
||||||
def home():
|
def home():
|
||||||
return render_template("home.html")
|
return render_template("home.html")
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/styleguide")
|
@bp.route("/styleguide")
|
||||||
@login_required
|
|
||||||
def styleguide():
|
def styleguide():
|
||||||
return render_template("styleguide.html")
|
return render_template("styleguide.html")
|
||||||
|
|
||||||
|
|
||||||
@bp.route('/<path:path>')
|
@bp.route('/<path:path>')
|
||||||
@login_required
|
|
||||||
def catch_all(path):
|
def catch_all(path):
|
||||||
return render_template("{}.html".format(path))
|
return render_template("{}.html".format(path))
|
||||||
|
|
||||||
|
@ -4,11 +4,9 @@ from flask import request as http_request
|
|||||||
from . import requests_bp
|
from . import requests_bp
|
||||||
from atst.domain.requests import Requests
|
from atst.domain.requests import Requests
|
||||||
from atst.forms.financial import FinancialForm
|
from atst.forms.financial import FinancialForm
|
||||||
from atst.domain.auth import login_required
|
|
||||||
|
|
||||||
|
|
||||||
@requests_bp.route("/requests/verify/<string:request_id>", methods=["GET"])
|
@requests_bp.route("/requests/verify/<string:request_id>", methods=["GET"])
|
||||||
@login_required
|
|
||||||
def financial_verification(request_id=None):
|
def financial_verification(request_id=None):
|
||||||
request = Requests.get(request_id)
|
request = Requests.get(request_id)
|
||||||
form = FinancialForm(data=request.body.get("financial_verification"))
|
form = FinancialForm(data=request.body.get("financial_verification"))
|
||||||
@ -18,7 +16,6 @@ def financial_verification(request_id=None):
|
|||||||
|
|
||||||
|
|
||||||
@requests_bp.route("/requests/verify/<string:request_id>", methods=["POST"])
|
@requests_bp.route("/requests/verify/<string:request_id>", methods=["POST"])
|
||||||
@login_required
|
|
||||||
def update_financial_verification(request_id):
|
def update_financial_verification(request_id):
|
||||||
post_data = http_request.form
|
post_data = http_request.form
|
||||||
existing_request = Requests.get(request_id)
|
existing_request = Requests.get(request_id)
|
||||||
@ -43,6 +40,5 @@ def update_financial_verification(request_id):
|
|||||||
|
|
||||||
|
|
||||||
@requests_bp.route("/requests/financial_verification_submitted")
|
@requests_bp.route("/requests/financial_verification_submitted")
|
||||||
@login_required
|
|
||||||
def financial_verification_submitted():
|
def financial_verification_submitted():
|
||||||
pass
|
pass
|
||||||
|
@ -3,7 +3,6 @@ from flask import render_template, g
|
|||||||
|
|
||||||
from . import requests_bp
|
from . import requests_bp
|
||||||
from atst.domain.requests import Requests
|
from atst.domain.requests import Requests
|
||||||
from atst.domain.auth import login_required
|
|
||||||
|
|
||||||
|
|
||||||
def map_request(user, request):
|
def map_request(user, request):
|
||||||
@ -21,7 +20,6 @@ def map_request(user, request):
|
|||||||
|
|
||||||
|
|
||||||
@requests_bp.route("/requests", methods=["GET"])
|
@requests_bp.route("/requests", methods=["GET"])
|
||||||
@login_required
|
|
||||||
def requests_index():
|
def requests_index():
|
||||||
requests = []
|
requests = []
|
||||||
if (
|
if (
|
||||||
|
@ -3,11 +3,9 @@ from flask import g, redirect, render_template, url_for, request as http_request
|
|||||||
from . import requests_bp
|
from . import requests_bp
|
||||||
from atst.domain.requests import Requests
|
from atst.domain.requests import Requests
|
||||||
from atst.routes.requests.jedi_request_flow import JEDIRequestFlow
|
from atst.routes.requests.jedi_request_flow import JEDIRequestFlow
|
||||||
from atst.domain.auth import login_required
|
|
||||||
|
|
||||||
|
|
||||||
@requests_bp.route("/requests/new/<int:screen>", methods=["GET"])
|
@requests_bp.route("/requests/new/<int:screen>", methods=["GET"])
|
||||||
@login_required
|
|
||||||
def requests_form_new(screen):
|
def requests_form_new(screen):
|
||||||
jedi_flow = JEDIRequestFlow(screen, request=None)
|
jedi_flow = JEDIRequestFlow(screen, request=None)
|
||||||
|
|
||||||
@ -26,7 +24,6 @@ def requests_form_new(screen):
|
|||||||
"/requests/new/<int:screen>", methods=["GET"], defaults={"request_id": None}
|
"/requests/new/<int:screen>", methods=["GET"], defaults={"request_id": None}
|
||||||
)
|
)
|
||||||
@requests_bp.route("/requests/new/<int:screen>/<string:request_id>", methods=["GET"])
|
@requests_bp.route("/requests/new/<int:screen>/<string:request_id>", methods=["GET"])
|
||||||
@login_required
|
|
||||||
def requests_form_update(screen=1, request_id=None):
|
def requests_form_update(screen=1, request_id=None):
|
||||||
request = Requests.get(request_id) if request_id is not None else None
|
request = Requests.get(request_id) if request_id is not None else None
|
||||||
jedi_flow = JEDIRequestFlow(screen, request, request_id=request_id)
|
jedi_flow = JEDIRequestFlow(screen, request, request_id=request_id)
|
||||||
@ -47,7 +44,6 @@ def requests_form_update(screen=1, request_id=None):
|
|||||||
"/requests/new/<int:screen>", methods=["POST"], defaults={"request_id": None}
|
"/requests/new/<int:screen>", methods=["POST"], defaults={"request_id": None}
|
||||||
)
|
)
|
||||||
@requests_bp.route("/requests/new/<int:screen>/<string:request_id>", methods=["POST"])
|
@requests_bp.route("/requests/new/<int:screen>/<string:request_id>", methods=["POST"])
|
||||||
@login_required
|
|
||||||
def requests_update(screen=1, request_id=None):
|
def requests_update(screen=1, request_id=None):
|
||||||
screen = int(screen)
|
screen = int(screen)
|
||||||
post_data = http_request.form
|
post_data = http_request.form
|
||||||
@ -92,7 +88,6 @@ def requests_update(screen=1, request_id=None):
|
|||||||
|
|
||||||
|
|
||||||
@requests_bp.route("/requests/submit/<string:request_id>", methods=["POST"])
|
@requests_bp.route("/requests/submit/<string:request_id>", methods=["POST"])
|
||||||
@login_required
|
|
||||||
def requests_submit(request_id=None):
|
def requests_submit(request_id=None):
|
||||||
request = Requests.get(request_id)
|
request = Requests.get(request_id)
|
||||||
Requests.submit(request)
|
Requests.submit(request)
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
from flask import Blueprint, render_template
|
from flask import Blueprint, render_template
|
||||||
|
|
||||||
from atst.domain.workspaces import Projects, Members
|
from atst.domain.workspaces import Projects, Members
|
||||||
from atst.domain.auth import login_required
|
|
||||||
|
|
||||||
|
|
||||||
bp = Blueprint("workspaces", __name__)
|
bp = Blueprint("workspaces", __name__)
|
||||||
@ -17,13 +16,11 @@ mock_workspaces = [
|
|||||||
|
|
||||||
|
|
||||||
@bp.route("/workspaces")
|
@bp.route("/workspaces")
|
||||||
@login_required
|
|
||||||
def workspaces():
|
def workspaces():
|
||||||
return render_template("workspaces.html", page=5, workspaces=mock_workspaces)
|
return render_template("workspaces.html", page=5, workspaces=mock_workspaces)
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/workspaces/<workspace_id>/projects")
|
@bp.route("/workspaces/<workspace_id>/projects")
|
||||||
@login_required
|
|
||||||
def workspace_projects(workspace_id):
|
def workspace_projects(workspace_id):
|
||||||
projects_repo = Projects()
|
projects_repo = Projects()
|
||||||
projects = projects_repo.get_many(workspace_id)
|
projects = projects_repo.get_many(workspace_id)
|
||||||
@ -33,7 +30,6 @@ def workspace_projects(workspace_id):
|
|||||||
|
|
||||||
|
|
||||||
@bp.route("/workspaces/<workspace_id>/members")
|
@bp.route("/workspaces/<workspace_id>/members")
|
||||||
@login_required
|
|
||||||
def workspace_members(workspace_id):
|
def workspace_members(workspace_id):
|
||||||
members_repo = Members()
|
members_repo = Members()
|
||||||
members = members_repo.get_many(workspace_id)
|
members = members_repo.get_many(workspace_id)
|
||||||
|
@ -15,8 +15,7 @@ def test_successful_login_redirect(client, monkeypatch):
|
|||||||
resp = client.get(
|
resp = client.get(
|
||||||
"/login-redirect",
|
"/login-redirect",
|
||||||
environ_base={
|
environ_base={
|
||||||
"HTTP_X_SSL_CLIENT_VERIFY": "SUCCESS",
|
"HTTP_X_SSL_CLIENT_VERIFY": "SUCCESS", "HTTP_X_SSL_CLIENT_S_DN": DOD_SDN
|
||||||
"HTTP_X_SSL_CLIENT_S_DN": DOD_SDN,
|
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -32,9 +31,10 @@ def test_unsuccessful_login_redirect(client, monkeypatch):
|
|||||||
assert "unauthorized" in resp.headers["Location"]
|
assert "unauthorized" in resp.headers["Location"]
|
||||||
assert "user_id" not in session
|
assert "user_id" not in session
|
||||||
|
|
||||||
UNPROTECTED_ROUTES = ["/", "/login-dev", "/login-redirect", "/unauthorized"]
|
|
||||||
|
|
||||||
# checks that all of the routes in the app are protected by auth
|
# checks that all of the routes in the app are protected by auth
|
||||||
|
|
||||||
|
|
||||||
def test_routes_are_protected(client, app):
|
def test_routes_are_protected(client, app):
|
||||||
for rule in app.url_map.iter_rules():
|
for rule in app.url_map.iter_rules():
|
||||||
args = [1] * len(rule.arguments)
|
args = [1] * len(rule.arguments)
|
||||||
@ -54,10 +54,14 @@ def test_routes_are_protected(client, app):
|
|||||||
assert resp.headers["Location"] == "http://localhost/"
|
assert resp.headers["Location"] == "http://localhost/"
|
||||||
|
|
||||||
|
|
||||||
|
UNPROTECTED_ROUTES = ["/", "/login-dev", "/login-redirect", "/unauthorized"]
|
||||||
|
|
||||||
# this implicitly relies on the test config and test CRL in tests/fixtures/crl
|
# this implicitly relies on the test config and test CRL in tests/fixtures/crl
|
||||||
|
|
||||||
|
|
||||||
def test_crl_validation_on_login(client):
|
def test_crl_validation_on_login(client):
|
||||||
good_cert = open('ssl/client-certs/atat.mil.crt', 'rb').read()
|
good_cert = open("ssl/client-certs/atat.mil.crt", "rb").read()
|
||||||
bad_cert = open('ssl/client-certs/bad-atat.mil.crt', 'rb').read()
|
bad_cert = open("ssl/client-certs/bad-atat.mil.crt", "rb").read()
|
||||||
|
|
||||||
# bad cert is on the test CRL
|
# bad cert is on the test CRL
|
||||||
resp = client.get(
|
resp = client.get(
|
||||||
@ -65,7 +69,7 @@ def test_crl_validation_on_login(client):
|
|||||||
environ_base={
|
environ_base={
|
||||||
"HTTP_X_SSL_CLIENT_VERIFY": "SUCCESS",
|
"HTTP_X_SSL_CLIENT_VERIFY": "SUCCESS",
|
||||||
"HTTP_X_SSL_CLIENT_S_DN": DOD_SDN,
|
"HTTP_X_SSL_CLIENT_S_DN": DOD_SDN,
|
||||||
"HTTP_X_SSL_CLIENT_CERT": bad_cert.decode()
|
"HTTP_X_SSL_CLIENT_CERT": bad_cert.decode(),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
assert resp.status_code == 302
|
assert resp.status_code == 302
|
||||||
@ -78,10 +82,9 @@ def test_crl_validation_on_login(client):
|
|||||||
environ_base={
|
environ_base={
|
||||||
"HTTP_X_SSL_CLIENT_VERIFY": "SUCCESS",
|
"HTTP_X_SSL_CLIENT_VERIFY": "SUCCESS",
|
||||||
"HTTP_X_SSL_CLIENT_S_DN": DOD_SDN,
|
"HTTP_X_SSL_CLIENT_S_DN": DOD_SDN,
|
||||||
"HTTP_X_SSL_CLIENT_CERT": good_cert.decode()
|
"HTTP_X_SSL_CLIENT_CERT": good_cert.decode(),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
assert resp.status_code == 302
|
assert resp.status_code == 302
|
||||||
assert "home" in resp.headers["Location"]
|
assert "home" in resp.headers["Location"]
|
||||||
assert session["user_id"]
|
assert session["user_id"]
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user