Skip to content
This repository has been archived by the owner on Dec 18, 2024. It is now read-only.

Commit

Permalink
Merge pull request #350 from communitiesuk/bau-cleanup-config-paths
Browse files Browse the repository at this point in the history
BAU: cleanup config paths
  • Loading branch information
gidsg authored Nov 6, 2024
2 parents 2c445cb + 0db9a4e commit 42b01d7
Show file tree
Hide file tree
Showing 15 changed files with 37 additions and 75 deletions.
7 changes: 4 additions & 3 deletions api/magic_links/routes.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import json
import urllib.parse
from datetime import datetime
from urllib.parse import urlencode
from urllib.parse import urljoin

from api.session.auth_session import AuthSessionView
from config import Config
Expand Down Expand Up @@ -87,8 +88,8 @@ def use(self, link_id: str):
"round": round_short_name,
}
query_params = {k: v for k, v in query_params.items() if v is not None}
query_string = urllib.parse.urlencode(query_params)
frontend_account_url = f"{Config.MAGIC_LINK_REDIRECT_URL}?{query_string}"
query_string = urlencode(query_params)
frontend_account_url = urljoin(Config.APPLICANT_FRONTEND_HOST, f"account?{query_string}")
current_app.logger.warning(
f"The magic link with hash: '{link_hash}' has already been"
f" used but the user with account_id: '{g.account_id}' is"
Expand Down
5 changes: 4 additions & 1 deletion api/sso/routes.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import warnings
from urllib.parse import urlencode
from urllib.parse import urljoin
from urllib.parse import urlparse

import msal
Expand Down Expand Up @@ -115,7 +116,9 @@ def get_token(self):
roles=session["user"].get("roles") or [],
)

redirect_url = Config.ASSESSMENT_POST_LOGIN_URL # TODO: Remove defaulting to Assessment, instead use return_app
redirect_url = urljoin( # TODO: Remove defaulting to Assessment, instead use return_app
Config.ASSESSMENT_FRONTEND_HOST, "/assess/fund_dashboard"
)
if return_app := session.get("return_app"):
if safe_app := Config.SAFE_RETURN_APPS.get(return_app):
if return_path := session.get("return_path"):
Expand Down
16 changes: 8 additions & 8 deletions app.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
from pathlib import Path
from typing import Any
from typing import Dict
from urllib.parse import urlencode
from urllib.parse import urljoin

import connexion
import prance
Expand Down Expand Up @@ -114,17 +116,15 @@ def before_request_modifier():
# This is silently used by flask in the background.
@flask_app.context_processor
def inject_global_constants():
query_params = urlencode({"fund": request.args.get("fund", ""), "round": request.args.get("round", "")})
return dict(
stage="beta",
service_meta_author="Department for Levelling up Housing and Communities",
accessibility_statement_url=Config.APPLICANT_FRONTEND_ACCESSIBILITY_STATEMENT_URL, # noqa
cookie_policy_url=Config.APPLICANT_FRONTEND_COOKIE_POLICY_URL,
contact_us_url=Config.APPLICANT_FRONTEND_CONTACT_US_URL
+ f"?fund={request.args.get('fund', '')}&round={request.args.get('round', '')}",
privacy_url=Config.APPLICANT_FRONTEND_PRIVACY_URL
+ f"?fund={request.args.get('fund', '')}&round={request.args.get('round', '')}",
feedback_url=Config.APPLICANT_FRONTEND_FEEDBACK_URL
+ f"?fund={request.args.get('fund', '')}&round={request.args.get('round', '')}",
accessibility_statement_url=urljoin(Config.APPLICANT_FRONTEND_HOST, "/accessibility_statement"), # noqa
cookie_policy_url=urljoin(Config.APPLICANT_FRONTEND_HOST, "/cookie_policy"),
contact_us_url=urljoin(Config.APPLICANT_FRONTEND_HOST, f"/contact_us?{query_params}"),
privacy_url=urljoin(Config.APPLICANT_FRONTEND_HOST, f"/privacy?{query_params}"),
feedback_url=urljoin(Config.APPLICANT_FRONTEND_HOST, f"/feedback?{query_params}"),
)

@flask_app.context_processor
Expand Down
28 changes: 4 additions & 24 deletions config/envs/default.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from os import environ
from os import getenv
from pathlib import Path
from urllib.parse import urljoin

import redis
from distutils.util import strtobool
Expand Down Expand Up @@ -40,8 +41,6 @@ class DefaultConfig(object):
# Hostname for this service
AUTHENTICATOR_HOST = environ.get("AUTHENTICATOR_HOST", "")
NEW_LINK_ENDPOINT = "/service/magic-links/new"
SSO_LOGOUT_ENDPOINT = "api_sso_routes_SsoView_logout_get"
SSO_LOGIN_ENDPOINT = "api_sso_routes_SsoView_login"
SSO_POST_SIGN_OUT_URL = AUTHENTICATOR_HOST + "/service/sso/signed-out/signout-request"

AUTO_REDIRECT_LOGIN = False
Expand All @@ -61,13 +60,9 @@ class DefaultConfig(object):
"https://login.microsoftonline.com/"
+ AZURE_AD_TENANT_ID
)
AZURE_AD_REDIRECT_PATH = (
# Used for forming an absolute URL to your redirect URI.
"/sso/get-token"
)
# The absolute URL must match the redirect URI you set
# in the app's registration in the Azure portal.
AZURE_AD_REDIRECT_URI = AUTHENTICATOR_HOST + AZURE_AD_REDIRECT_PATH
AZURE_AD_REDIRECT_URI = urljoin(AUTHENTICATOR_HOST, "/sso/get-token")

# You can find the proper permission names from this document
# https://docs.microsoft.com/en-us/graph/permissions-reference
Expand Down Expand Up @@ -100,24 +95,15 @@ class DefaultConfig(object):
"""
# Account Store
ACCOUNT_STORE_API_HOST = environ.get("ACCOUNT_STORE_API_HOST")
ACCOUNTS_ENDPOINT = "/accounts"
ACCOUNT_ENDPOINT = "/accounts/{account_id}"

# Notification Service
DISABLE_NOTIFICATION_SERVICE = False

# Applicant Frontend
APPLICANT_FRONTEND_HOST = environ.get("APPLICANT_FRONTEND_HOST", "frontend")
APPLICANT_FRONTEND_ACCESSIBILITY_STATEMENT_URL = APPLICANT_FRONTEND_HOST + "/accessibility_statement"
APPLICANT_FRONTEND_COOKIE_POLICY_URL = APPLICANT_FRONTEND_HOST + "/cookie_policy"
APPLICANT_FRONTEND_CONTACT_US_URL = APPLICANT_FRONTEND_HOST + "/contact_us"
APPLICANT_FRONTEND_PRIVACY_URL = APPLICANT_FRONTEND_HOST + "/privacy"
APPLICANT_FRONTEND_FEEDBACK_URL = APPLICANT_FRONTEND_HOST + "/feedback"
APPLICATION_ALL_QUESTIONS_URL = APPLICANT_FRONTEND_HOST + "/all_questions/{fund_short_name}/{round_short_name}"

# Assessment Frontend
ASSESSMENT_FRONTEND_HOST = environ.get("ASSESSMENT_FRONTEND_HOST", "")
ASSESSMENT_POST_LOGIN_URL = ASSESSMENT_FRONTEND_HOST + "/assess/fund_dashboard"
FSD_ASSESSMENT_SESSION_TIMEOUT_SECONDS = CommonConfig.FSD_SESSION_TIMEOUT_SECONDS

# Fund store service
Expand All @@ -128,21 +114,19 @@ class DefaultConfig(object):

# Post-award frontend
POST_AWARD_FRONTEND_HOST = environ.get("POST_AWARD_FRONTEND_HOST", "")
POST_AWARD_FRONTEND_LOGIN_URL = POST_AWARD_FRONTEND_HOST + "/"

# Post-award submit
POST_AWARD_SUBMIT_HOST = environ.get("POST_AWARD_SUBMIT_HOST", "")
POST_AWARD_SUBMIT_LOGIN_URL = POST_AWARD_SUBMIT_HOST + "/"

# Safe list of return applications
SAFE_RETURN_APPS = {
SupportedApp.POST_AWARD_FRONTEND.value: SafeAppConfig(
login_url=POST_AWARD_FRONTEND_LOGIN_URL,
login_url=urljoin(POST_AWARD_FRONTEND_HOST, "/"),
logout_endpoint="sso_bp.signed_out",
service_title="Find monitoring and evaluation data",
),
SupportedApp.POST_AWARD_SUBMIT.value: SafeAppConfig(
login_url=POST_AWARD_SUBMIT_LOGIN_URL,
login_url=urljoin(POST_AWARD_SUBMIT_HOST, "/"),
logout_endpoint="sso_bp.signed_out",
service_title="Submit monitoring and evaluation data",
),
Expand All @@ -153,10 +137,6 @@ class DefaultConfig(object):
"""
MAGIC_LINK_EXPIRY_DAYS = 1
MAGIC_LINK_EXPIRY_SECONDS = 86400 * MAGIC_LINK_EXPIRY_DAYS
if APPLICANT_FRONTEND_HOST:
MAGIC_LINK_REDIRECT_URL = APPLICANT_FRONTEND_HOST + "/account"
else:
MAGIC_LINK_REDIRECT_URL = "https://www.gov.uk/error"
MAGIC_LINK_RECORD_PREFIX = "link"
MAGIC_LINK_USER_PREFIX = "account"
MAGIC_LINK_LANDING_PAGE = "/service/magic-links/landing/"
Expand Down
10 changes: 0 additions & 10 deletions config/envs/development.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,18 +20,8 @@ class DevelopmentConfig(Config):

# Hostname for this service
AUTHENTICATOR_HOST = getenv("AUTHENTICATOR_HOST", "http://localhost:5000")
SSO_POST_SIGN_OUT_URL = AUTHENTICATOR_HOST + "/service/sso/signed-out/signout-request"

# Azure Active Directory Config
AZURE_AD_AUTHORITY = (
# consumers|organizations|<tenant_id> - signifies the Azure AD
# tenant endpoint
"https://login.microsoftonline.com/organizations"
)

# The absolute URL must match the redirect URI you set
# in the app's registration in the Azure portal.
AZURE_AD_REDIRECT_URI = AUTHENTICATOR_HOST + Config.AZURE_AD_REDIRECT_PATH

# Session Settings
SESSION_TYPE = (
Expand Down
12 changes: 0 additions & 12 deletions config/envs/unit_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,6 @@ class UnitTestConfig(Config):
+ AZURE_AD_TENANT_ID
)

# The absolute URL must match the redirect URI you set
# in the app's registration in the Azure portal.
AZURE_AD_REDIRECT_URI = AUTHENTICATOR_HOST + Config.AZURE_AD_REDIRECT_PATH

SESSION_TYPE = (
# Specifies how the token cache should be stored
# in server-side session
Expand Down Expand Up @@ -66,14 +62,6 @@ class UnitTestConfig(Config):
Config.TALISMAN_SETTINGS["force_https"] = False
WTF_CSRF_ENABLED = False

APPLICANT_FRONTEND_HOST = "frontend"
APPLICANT_FRONTEND_ACCESSIBILITY_STATEMENT_URL = "/accessibility_statement"
APPLICANT_FRONTEND_COOKIE_POLICY_URL = "/cookie_policy"

# Assessment Frontend
ASSESSMENT_FRONTEND_HOST = ""
ASSESSMENT_POST_LOGIN_URL = ""

# ---------------
# S3 Config
# ---------------
Expand Down
3 changes: 2 additions & 1 deletion frontend/default/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ def internal_server_error(error):
return (
render_template(
"500.html",
contact_us_url=Config.APPLICANT_FRONTEND_CONTACT_US_URL
contact_us_url=Config.APPLICANT_FRONTEND_HOST
+ "/contact_us"
+ f"?fund={request.args.get('fund', '')}&round={request.args.get('round', '')}",
),
500,
Expand Down
5 changes: 1 addition & 4 deletions frontend/magic_links/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,10 +84,7 @@ def landing(link_id):
app_guidance = None
if round_data.application_guidance:
app_guidance = round_data.application_guidance.format(
all_questions_url=Config.APPLICATION_ALL_QUESTIONS_URL.format(
fund_short_name=fund_short_name,
round_short_name=round_short_name,
)
all_questions_url=f"{Config.APPLICANT_FRONTEND_HOST}/all_questions/{fund_short_name}/{round_short_name}"
)
round_prospectus = round_data.prospectus if round_data.prospectus else None
return render_template(
Expand Down
3 changes: 1 addition & 2 deletions frontend/sso/routes.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
from config import Config
from flask import Blueprint
from flask import render_template
from flask import request
Expand All @@ -20,7 +19,7 @@ def signed_out(status):
render_template(
"sso_signed_out.html",
status=status,
login_url=url_for(Config.SSO_LOGIN_ENDPOINT, return_app=return_app, return_path=return_path),
login_url=url_for("api_sso_routes_SsoView_login", return_app=return_app, return_path=return_path),
),
200,
)
4 changes: 2 additions & 2 deletions frontend/user/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ def user():
"user.html",
roles_required=roles_required,
logged_in_user=logged_in_user,
login_url=url_for(Config.SSO_LOGIN_ENDPOINT),
logout_url=url_for(Config.SSO_LOGOUT_ENDPOINT),
login_url=url_for("api_sso_routes_SsoView_login"),
logout_url=url_for("api_sso_routes_SsoView_logout_get"),
support_mailbox=Config.SUPPORT_MAILBOX_EMAIL,
),
status_code,
Expand Down
6 changes: 3 additions & 3 deletions models/account.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ def get_account(email: str = None, account_id: str = None, azure_ad_subject_id=N
if email is account_id is azure_ad_subject_id is None:
raise TypeError("Requires an email address, azure_ad_subject_id or account_id")

url = Config.ACCOUNT_STORE_API_HOST + Config.ACCOUNTS_ENDPOINT
url = Config.ACCOUNT_STORE_API_HOST + "/accounts"
params = {
"email_address": email,
"azure_ad_subject_id": azure_ad_subject_id,
Expand Down Expand Up @@ -103,7 +103,7 @@ def update_account(
Returns:
Account object or None
"""
url = Config.ACCOUNT_STORE_API_HOST + Config.ACCOUNT_ENDPOINT.format(account_id=id)
url = Config.ACCOUNT_STORE_API_HOST + "/accounts/{account_id}".format(account_id=id)

if config.FLASK_ENV == "development" and not roles:
account = get_account_data(email)
Expand Down Expand Up @@ -131,7 +131,7 @@ def create_account(email: str) -> Account | None:
Returns:
Account object or None
"""
url = Config.ACCOUNT_STORE_API_HOST + Config.ACCOUNTS_ENDPOINT
url = Config.ACCOUNT_STORE_API_HOST + "/accounts"
params = {"email_address": email}
response = post_data(url, params)

Expand Down
2 changes: 1 addition & 1 deletion models/data.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ def get_round_data_fail_gracefully(fund_id, round_id, use_short_name=False):


def get_account_data(email: str):
url = Config.ACCOUNT_STORE_API_HOST + Config.ACCOUNTS_ENDPOINT
url = Config.ACCOUNT_STORE_API_HOST + "/accounts"
params = {
"email_address": email,
}
Expand Down
5 changes: 4 additions & 1 deletion models/magic_link.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from datetime import timedelta
from typing import List
from typing import TYPE_CHECKING
from urllib.parse import urljoin

from config import Config
from flask import abort
Expand Down Expand Up @@ -191,7 +192,9 @@ def create_magic_link(
self.clear_existing_user_record(account.id)

if not redirect_url:
redirect_url = Config.MAGIC_LINK_REDIRECT_URL + "?fund=" + fund_short_name + "&round=" + round_short_name
redirect_url = urljoin(
Config.APPLICANT_FRONTEND_HOST, f"/account?fund={fund_short_name}&round={round_short_name}"
)

new_link_json = self._make_link_json(account, redirect_url)

Expand Down
4 changes: 2 additions & 2 deletions tests/test_signout.py
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ def test_session_sign_out_using_correct_route_with_specified_return_app(self, fl
:param flask_test_client:
"""
mocker.patch(
"frontend.sso.routes.Config.SAFE_RETURN_APPS",
"config.Config.SAFE_RETURN_APPS",
new_callable=PropertyMock,
return_value={
"test-app": SafeAppConfig(
Expand Down Expand Up @@ -229,7 +229,7 @@ def test_sign_out_template_service_title_is_dynamic(self, flask_test_client, moc
:param flask_test_client:
"""
mocker.patch(
"frontend.sso.routes.Config.SAFE_RETURN_APPS",
"config.Config.SAFE_RETURN_APPS",
new_callable=PropertyMock,
return_value={
"test-app": SafeAppConfig(
Expand Down
2 changes: 1 addition & 1 deletion tests/test_signout_get.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ def test_session_sign_out_using_correct_route_with_specified_return_app(self, fl
:param flask_test_client:
"""
mocker.patch(
"frontend.sso.routes.Config.SAFE_RETURN_APPS",
"config.Config.SAFE_RETURN_APPS",
new_callable=PropertyMock,
return_value={
"test-app": SafeAppConfig(
Expand Down

0 comments on commit 42b01d7

Please sign in to comment.