Skip to content

Commit

Permalink
FS-4805 - Adding authentication to FAB
Browse files Browse the repository at this point in the history
  • Loading branch information
wjrm500 committed Dec 6, 2024
1 parent d2c6660 commit dcccc5a
Show file tree
Hide file tree
Showing 6 changed files with 76 additions and 6 deletions.
30 changes: 30 additions & 0 deletions app/blueprints/fund_builder/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,15 @@
from flask import Response
from flask import after_this_request
from flask import flash
from flask import g
from flask import redirect
from flask import render_template
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 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 @@ -67,11 +71,26 @@


@build_fund_bp.route("/")
@login_requested
def index():
if not g.is_authenticated:
return redirect(url_for("build_fund_bp.login"))
return redirect(url_for("build_fund_bp.dashboard"))


@build_fund_bp.route("/login", methods=["GET"])
def login():
return render_template("login.html")


@build_fund_bp.route("/dashboard", methods=["GET"])
@login_required(return_app=SupportedApp.FUND_APPLICATION_BUILDER)
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)
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 @@ -134,6 +153,7 @@ 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)
def configure_forms_in_section(round_id, section_id):
if request.method == "GET":
if request.args.get("action") == "remove":
Expand Down Expand Up @@ -162,6 +182,7 @@ 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)
def view_fund():
"""
Renders a template providing a drop down list of funds. If a fund is selected, renders its config info
Expand All @@ -185,6 +206,7 @@ def view_fund():


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


@build_fund_bp.route("/fund/<fund_id>/round/<round_id>/clone")
@login_required(return_app=SupportedApp.FUND_APPLICATION_BUILDER)
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 @@ -211,6 +234,7 @@ 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)
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 @@ -276,6 +300,7 @@ 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)
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 @@ -531,6 +556,7 @@ def create_new_round(form):


@build_fund_bp.route("/preview/<form_id>", methods=["GET"])
@login_required(return_app=SupportedApp.FUND_APPLICATION_BUILDER)
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 @@ -552,6 +578,7 @@ def preview_form(form_id):


@build_fund_bp.route("/download/<form_id>", methods=["GET"])
@login_required(return_app=SupportedApp.FUND_APPLICATION_BUILDER)
def download_form_json(form_id):
"""
Generates form json for the selected form and returns it as a file download
Expand All @@ -567,6 +594,7 @@ 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)
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 @@ -595,6 +623,7 @@ 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)
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 @@ -630,6 +659,7 @@ 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)
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
21 changes: 21 additions & 0 deletions app/blueprints/fund_builder/templates/login.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{% extends "base.html" %}

{%- from 'govuk_frontend_jinja/components/button/macro.html' import govukButton -%}

{# Override main width to two thirds #}
{% set mainClasses = "govuk-!-width-two-thirds" %}

{% block content %}
<div class="govuk-width-container">
<h1 class="govuk-heading-l">Sign in to use FAB</h1>
<p class="govuk-body">
Sign in using the Microsoft account for your work email address.
</p>

{{ govukButton({
"text": "Sign in using Microsoft",
"href": config['AUTHENTICATOR_HOST'] + "/sso/login?return_app=fund-application-builder",
"classes": "login-button"
}) }}
</div>
{% endblock content %}
10 changes: 10 additions & 0 deletions config/envs/default.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import base64
import logging
from os import environ
from os import getenv
Expand All @@ -12,6 +13,7 @@ class DefaultConfig(object):
# Logging
FSD_LOG_LEVEL = logging.WARNING

FLASK_ENV = CommonConfig.FLASK_ENV
SECRET_KEY = CommonConfig.SECRET_KEY

FAB_HOST = getenv("FAB_HOST", "fab:8080/")
Expand All @@ -22,3 +24,11 @@ class DefaultConfig(object):

TEMP_FILE_PATH = Path("/tmp")
GENERATE_LOCAL_CONFIG = False

FSD_USER_TOKEN_COOKIE_NAME = "fsd_user_token"
AUTHENTICATOR_HOST = getenv("AUTHENTICATOR_HOST", "http://authenticator.levellingup.gov.localhost:3004")

# RSA 256 Keys
RSA256_PUBLIC_KEY_BASE64 = getenv("RSA256_PUBLIC_KEY_BASE64")
if RSA256_PUBLIC_KEY_BASE64:
RSA256_PUBLIC_KEY: str = base64.b64decode(RSA256_PUBLIC_KEY_BASE64).decode()
9 changes: 9 additions & 0 deletions config/envs/development.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,12 @@ class DevelopmentConfig(Config):
TEMP_FILE_PATH = Path("app") / "export_config" / "output"

GENERATE_LOCAL_CONFIG = True

DEBUG_USER_ON = True
DEBUG_USER = {
"full_name": "Development User",
"email": "[email protected]",
"roles": [],
"highest_role_map": {},
}
DEBUG_USER_ACCOUNT_ID = "00000000-0000-0000-0000-000000000000"
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ dependencies = [
"flask-talisman==1.1.0",
"flask-wtf==1.2.1",
"flask==3.0.3",
"funding-service-design-utils==5.1.5",
"funding-service-design-utils==5.2.0",
"govuk-frontend-jinja==3.4.0",
"jsmin==3.0.1",
"jsonschema==4.23.0",
Expand Down
10 changes: 5 additions & 5 deletions uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit dcccc5a

Please sign in to comment.