Skip to content

Commit

Permalink
FS-4805 - Centralising authentication route decoration
Browse files Browse the repository at this point in the history
Instead of having login_required and check_internal_user added above each and every route, we can have a central @app.before_request decorator to add the decorators to every route, except those that require public access - static, healthcheck, login and index.
  • Loading branch information
wjrm500 committed Dec 10, 2024
1 parent 2615825 commit 209ce70
Show file tree
Hide file tree
Showing 5 changed files with 24 additions and 70 deletions.
17 changes: 0 additions & 17 deletions app/blueprints/dev/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,6 @@
from flask import redirect
from flask import request
from flask import url_for
from fsd_utils.authentication.decorators import SupportedApp
from fsd_utils.authentication.decorators import check_internal_user
from fsd_utils.authentication.decorators import login_required

from app.blueprints.self_serve.data.data_access import clear_all_responses
from app.blueprints.self_serve.data.data_access import get_all_components
Expand All @@ -25,8 +22,6 @@


@dev_bp.route("/responses")
@login_required(return_app=SupportedApp.FUND_APPLICATION_BUILDER)
@check_internal_user
def view_responses():
"""
Retrieves all responses received from a 'Save per page' callback when a form is in preview mode.
Expand All @@ -37,8 +32,6 @@ def view_responses():


@dev_bp.route("/responses/clear")
@login_required(return_app=SupportedApp.FUND_APPLICATION_BUILDER)
@check_internal_user
def clear_responses():
"""
Clears all responses received from a 'Save per page' callback when a form is in preview mode.
Expand All @@ -48,8 +41,6 @@ def clear_responses():


@dev_bp.route("/save", methods=["PUT"])
@login_required(return_app=SupportedApp.FUND_APPLICATION_BUILDER)
@check_internal_user
def save_per_page():
"""
Mock version of the 'save per page' route in application store - used to save and enable viewing of save
Expand All @@ -75,32 +66,24 @@ def save_per_page():


@dev_bp.route("/forms")
@login_required(return_app=SupportedApp.FUND_APPLICATION_BUILDER)
@check_internal_user
def view_forms():
forms = get_saved_forms()
return forms


@dev_bp.route("/pages")
@login_required(return_app=SupportedApp.FUND_APPLICATION_BUILDER)
@check_internal_user
def view_pages():
forms = get_all_pages()
return forms


@dev_bp.route("/sections")
@login_required(return_app=SupportedApp.FUND_APPLICATION_BUILDER)
@check_internal_user
def view_sections():
forms = get_all_sections()
return forms


@dev_bp.route("/questions")
@login_required(return_app=SupportedApp.FUND_APPLICATION_BUILDER)
@check_internal_user
def view_questions():
forms = get_all_components()
return forms
29 changes: 0 additions & 29 deletions app/blueprints/fund_builder/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,7 @@
from flask import request
from flask import send_file
from flask import url_for
from fsd_utils.authentication.decorators import SupportedApp
from fsd_utils.authentication.decorators import check_internal_user
from fsd_utils.authentication.decorators import login_requested
from fsd_utils.authentication.decorators import login_required

from app.all_questions.metadata_utils import generate_print_data_for_sections
from app.blueprints.fund_builder.forms.fund import FundForm
Expand Down Expand Up @@ -92,15 +89,11 @@ def login():


@build_fund_bp.route("/dashboard", methods=["GET"])
@login_required(return_app=SupportedApp.FUND_APPLICATION_BUILDER)
@check_internal_user
def dashboard():
return render_template("index.html")


@build_fund_bp.route("/fund/round/<round_id>/section", methods=["GET", "POST"])
@login_required(return_app=SupportedApp.FUND_APPLICATION_BUILDER)
@check_internal_user
def section(round_id):
round_obj = get_round_by_id(round_id)
fund_obj = get_fund_by_id(round_obj.fund_id)
Expand Down Expand Up @@ -163,8 +156,6 @@ def section(round_id):


@build_fund_bp.route("/fund/round/<round_id>/section/<section_id>/forms", methods=["POST", "GET"])
@login_required(return_app=SupportedApp.FUND_APPLICATION_BUILDER)
@check_internal_user
def configure_forms_in_section(round_id, section_id):
if request.method == "GET":
if request.args.get("action") == "remove":
Expand Down Expand Up @@ -193,8 +184,6 @@ def all_funds_as_govuk_select_items(all_funds: list) -> list:


@build_fund_bp.route("/fund/view", methods=["GET", "POST"])
@login_required(return_app=SupportedApp.FUND_APPLICATION_BUILDER)
@check_internal_user
def view_fund():
"""
Renders a template providing a drop down list of funds. If a fund is selected, renders its config info
Expand All @@ -218,8 +207,6 @@ def view_fund():


@build_fund_bp.route("/fund/round/<round_id>/application_config")
@login_required(return_app=SupportedApp.FUND_APPLICATION_BUILDER)
@check_internal_user
def build_application(round_id):
"""
Renders a template displaying application configuration info for the chosen round
Expand All @@ -235,8 +222,6 @@ def build_application(round_id):


@build_fund_bp.route("/fund/<fund_id>/round/<round_id>/clone")
@login_required(return_app=SupportedApp.FUND_APPLICATION_BUILDER)
@check_internal_user
def clone_round(round_id, fund_id):
cloned = clone_single_round(
round_id=round_id, new_fund_id=fund_id, new_short_name=f"R-C{randint(0, 999)}" # nosec B311
Expand All @@ -248,8 +233,6 @@ def clone_round(round_id, fund_id):

@build_fund_bp.route("/fund", methods=["GET", "POST"])
@build_fund_bp.route("/fund/<fund_id>", methods=["GET", "POST"])
@login_required(return_app=SupportedApp.FUND_APPLICATION_BUILDER)
@check_internal_user
def fund(fund_id=None):
"""
Renders a template to allow a user to add or update a fund, when saved validates the form data and saves to DB
Expand Down Expand Up @@ -315,8 +298,6 @@ def fund(fund_id=None):

@build_fund_bp.route("/round", methods=["GET", "POST"])
@build_fund_bp.route("/round/<round_id>", methods=["GET", "POST"])
@login_required(return_app=SupportedApp.FUND_APPLICATION_BUILDER)
@check_internal_user
def round(round_id=None):
"""
Renders a template to select a fund and add or update a round to that fund. If saved, validates the round form data
Expand Down Expand Up @@ -572,8 +553,6 @@ def create_new_round(form):


@build_fund_bp.route("/preview/<form_id>", methods=["GET"])
@login_required(return_app=SupportedApp.FUND_APPLICATION_BUILDER)
@check_internal_user
def preview_form(form_id):
"""
Generates the form json for a chosen form, does not persist this, but publishes it to the form runner using the
Expand All @@ -595,8 +574,6 @@ def preview_form(form_id):


@build_fund_bp.route("/download/<form_id>", methods=["GET"])
@login_required(return_app=SupportedApp.FUND_APPLICATION_BUILDER)
@check_internal_user
def download_form_json(form_id):
"""
Generates form json for the selected form and returns it as a file download
Expand All @@ -612,8 +589,6 @@ def download_form_json(form_id):


@build_fund_bp.route("/fund/round/<round_id>/all_questions", methods=["GET"])
@login_required(return_app=SupportedApp.FUND_APPLICATION_BUILDER)
@check_internal_user
def view_all_questions(round_id):
"""
Generates the form data for all sections in the selected round, then uses that to generate the 'All Questions'
Expand Down Expand Up @@ -642,8 +617,6 @@ def view_all_questions(round_id):


@build_fund_bp.route("/fund/round/<round_id>/all_questions/<form_id>", methods=["GET"])
@login_required(return_app=SupportedApp.FUND_APPLICATION_BUILDER)
@check_internal_user
def view_form_questions(round_id, form_id):
"""
Generates the form data for this form, then uses that to generate the 'All Questions'
Expand Down Expand Up @@ -679,8 +652,6 @@ def create_export_zip(directory_to_zip, zip_file_name, random_post_fix) -> str:


@build_fund_bp.route("/create_export_files/<round_id>", methods=["GET"])
@login_required(return_app=SupportedApp.FUND_APPLICATION_BUILDER)
@check_internal_user
def create_export_files(round_id):
round_short_name = get_round_by_id(round_id).short_name
# Construct the path to the output directory relative to this file's location
Expand Down
17 changes: 0 additions & 17 deletions app/blueprints/self_serve/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,6 @@
from flask import render_template
from flask import request
from flask import url_for
from fsd_utils.authentication.decorators import SupportedApp
from fsd_utils.authentication.decorators import check_internal_user
from fsd_utils.authentication.decorators import login_required

from app.all_questions.metadata_utils import generate_print_data_for_sections
from app.blueprints.self_serve.data.data_access import get_all_components
Expand Down Expand Up @@ -41,8 +38,6 @@


@self_serve_bp.route("/download_json", methods=["POST"])
@login_required(return_app=SupportedApp.FUND_APPLICATION_BUILDER)
@check_internal_user
def generate_json():
form_json = generate_form_config_from_request()["form_json"]

Expand Down Expand Up @@ -71,8 +66,6 @@ def generate_form_config_from_request():


@self_serve_bp.route("/form_questions", methods=["POST"])
@login_required(return_app=SupportedApp.FUND_APPLICATION_BUILDER)
@check_internal_user
def view_form_questions():
form_config = generate_form_config_from_request()
print_data = generate_print_data_for_sections(
Expand All @@ -89,8 +82,6 @@ def view_form_questions():


@self_serve_bp.route("/section_questions", methods=["POST"])
@login_required(return_app=SupportedApp.FUND_APPLICATION_BUILDER)
@check_internal_user
def view_section_questions():
# form_config = generate_form_config_from_request()
# print_data = generate_print_data_for_sections(
Expand All @@ -112,8 +103,6 @@ def view_section_questions():

# Create routes
@self_serve_bp.route("section", methods=["GET", "POST", "PUT", "DELETE"])
@login_required(return_app=SupportedApp.FUND_APPLICATION_BUILDER)
@check_internal_user
def section():
# TODO: Create frontend routes and connect to middleware
if request.method == "PUT":
Expand Down Expand Up @@ -142,8 +131,6 @@ def section():


@self_serve_bp.route("/form", methods=["GET", "POST", "PUT", "DELETE"])
@login_required(return_app=SupportedApp.FUND_APPLICATION_BUILDER)
@check_internal_user
def form():
# TODO: Create frontend routes and connect to middleware
if request.method == "PUT":
Expand Down Expand Up @@ -182,8 +169,6 @@ def form():


@self_serve_bp.route("/page", methods=["GET", "POST", "PUT", "DELETE"])
@login_required(return_app=SupportedApp.FUND_APPLICATION_BUILDER)
@check_internal_user
def page():
# TODO: Create frontend routes and connect to middleware
if request.method == "PUT":
Expand Down Expand Up @@ -216,8 +201,6 @@ def page():


@self_serve_bp.route("/question", methods=["GET", "PUT", "POST", "DELETE"])
@login_required(return_app=SupportedApp.FUND_APPLICATION_BUILDER)
@check_internal_user
def question():
# TODO: Create frontend routes and connect to middleware
if request.method == "PUT":
Expand Down
7 changes: 0 additions & 7 deletions app/blueprints/templates/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,6 @@
from flask import render_template
from flask import request
from flask import url_for
from fsd_utils.authentication.decorators import SupportedApp
from fsd_utils.authentication.decorators import check_internal_user
from fsd_utils.authentication.decorators import login_required
from werkzeug.utils import secure_filename

from app.blueprints.fund_builder.forms.templates import TemplateFormForm
Expand Down Expand Up @@ -57,8 +54,6 @@ def _build_rows(forms: list[Form]) -> list[dict]:


@template_bp.route("/all", methods=["GET", "POST"])
@login_required(return_app=SupportedApp.FUND_APPLICATION_BUILDER)
@check_internal_user
def view_templates():
sections = get_all_template_sections()
forms = get_all_template_forms()
Expand Down Expand Up @@ -97,8 +92,6 @@ def view_templates():


@template_bp.route("/forms/<form_id>", methods=["GET", "POST"])
@login_required(return_app=SupportedApp.FUND_APPLICATION_BUILDER)
@check_internal_user
def edit_form_template(form_id):
template_form = TemplateFormForm()
params = {
Expand Down
24 changes: 24 additions & 0 deletions app/create_app.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
from flask import Flask
from flask import render_template
from flask_assets import Environment
from fsd_utils.authentication.decorators import SupportedApp
from fsd_utils.authentication.decorators import check_internal_user
from fsd_utils.authentication.decorators import login_required
from fsd_utils.logging import logging
from jinja2 import ChoiceLoader
from jinja2 import PackageLoader
Expand All @@ -15,6 +18,25 @@
from app.db.models import Round # noqa:F401


PUBLIC_ROUTES = [
"static",
"build_fund_bp.healthcheck",
"build_fund_bp.index",
"build_fund_bp.login",
]


def protect_private_routes(flask_app: Flask) -> Flask:
for endpoint, view_func in flask_app.view_functions.items():
if endpoint in PUBLIC_ROUTES:
continue
flask_app.view_functions[endpoint] = login_required(
check_internal_user(view_func),
return_app=SupportedApp.FUND_APPLICATION_BUILDER
)
return flask_app


def create_app() -> Flask:

flask_app = Flask("__name__", static_url_path="/assets")
Expand All @@ -23,6 +45,8 @@ def create_app() -> Flask:
flask_app.register_blueprint(build_fund_bp)
flask_app.register_blueprint(template_bp)

protect_private_routes(flask_app)

flask_app.config.from_object("config.Config")

flask_app.static_folder = "app/static/dist"
Expand Down

0 comments on commit 209ce70

Please sign in to comment.