Skip to content

Commit

Permalink
Add means test form protection
Browse files Browse the repository at this point in the history
  • Loading branch information
said-moj committed Mar 10, 2025
1 parent ec8af6e commit 738b128
Show file tree
Hide file tree
Showing 6 changed files with 79 additions and 16 deletions.
15 changes: 15 additions & 0 deletions app/categories/mixins.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
from flask import session, redirect, url_for


class InScopeMixin:
def dispatch_request(self):
response = self.ensure_in_scope()
if not response:
response = super().dispatch_request()

return response

def ensure_in_scope(self):
if not session.in_scope:
return redirect(url_for("main.session_expired"))
return None
2 changes: 1 addition & 1 deletion app/categories/results/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
CannotFindYourProblemPage,
NextStepsPage,
)
from app.mixins import InScopeMixin
from app.categories.mixins import InScopeMixin


class InScopeResultPage(InScopeMixin, ResultPage):
Expand Down
31 changes: 23 additions & 8 deletions app/contact/urls.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,34 @@
from app.contact import bp
from app.contact.address_finder.widgets import FormattedAddressLookup
from app.contact.views import ContactUs, ReasonForContacting
from flask import render_template, jsonify
from app.means_test.api import EligibilityState, is_eligible
from flask import render_template, jsonify, session, redirect, url_for
import logging


logger = logging.getLogger(__name__)


class EligibleContactUsPage(ContactUs):
def dispatch_request(self):
if not session.ec_reference:
return redirect(url_for("main.session_expired"))

state = is_eligible(session.ec_reference)
if state != EligibilityState.YES:
return redirect(url_for("main.session_expired"))

return super().dispatch_request()


bp.add_url_rule(
"/eligible",
view_func=EligibleContactUsPage.as_view(
"eligible", template="contact/eligible.html", attach_eligiblity_data=True
),
)


bp.add_url_rule(
"/reasons-for-contacting",
view_func=ReasonForContacting.as_view("reasons_for_contacting"),
Expand All @@ -32,10 +54,3 @@ def geocode(postcode):
"/contact-us",
view_func=ContactUs.as_view("contact_us", attach_eligiblity_data=False),
)

bp.add_url_rule(
"/eligible",
view_func=ContactUs.as_view(
"eligible", template="contact/eligible.html", attach_eligiblity_data=True
),
)
18 changes: 13 additions & 5 deletions app/means_test/api.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from enum import Enum
from app.api import cla_backend
from flask import session
from app.means_test.forms.income import IncomeForm
Expand All @@ -7,10 +8,16 @@
from app.means_test.money_interval import MoneyInterval


class EligibilityState(str, Enum):
YES: str = "yes"
NO: str = "no"
UNKNOWN: str = "unknown"


def update_means_test(payload):
means_test_endpoint = "checker/api/v1/eligibility_check/"

ec_reference = session.get("ec_reference")
ec_reference = session.ec_reference

if ec_reference:
response = cla_backend.patch(
Expand All @@ -19,14 +26,15 @@ def update_means_test(payload):
return response
else:
response = cla_backend.post(means_test_endpoint, json=payload)
session["ec_reference"] = response["reference"]
session.ec_reference = response["reference"]
return response


def is_eligible(reference):
def is_eligible(reference) -> EligibilityState:
means_test_endpoint = "checker/api/v1/eligibility_check/"
response = cla_backend.post(f"{means_test_endpoint}{reference}/is_eligible/")
return response["is_eligible"]
response = cla_backend.post(f"{means_test_endpoint}{reference}/is_eligible/", {})
state = response["is_eligible"]
return getattr(EligibilityState, state.upper(), EligibilityState.UNKNOWN)


def get_means_test_payload(eligibility_data) -> dict:
Expand Down
21 changes: 19 additions & 2 deletions app/means_test/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
from app.means_test.forms.outgoings import OutgoingsForm
from app.means_test.forms.review import ReviewForm, BaseMeansTestForm
from app.categories.models import CategoryAnswer
from app.mixins import InScopeMixin
from app.categories.mixins import InScopeMixin


class FormsMixin:
Expand Down Expand Up @@ -50,11 +50,28 @@ def handle_multiple_properties_ajax_request(self, form):

return None

def ensure_form_protection(self, current_form):
progress = self.get_form_progress(current_form=current_form)
for form in progress["steps"]:
if form["is_current"]:
break
if not form["is_completed"]:
return redirect(url_for("main.session_expired"))
return None

def dispatch_request(self):
self.ensure_in_scope()
in_scope_redirect = self.ensure_in_scope()
if in_scope_redirect:
return in_scope_redirect

eligibility = session.get_eligibility()
form_data = eligibility.forms.get(self.current_name, {})
form = self.form_class(formdata=request.form or None, data=form_data)

form_protection_redirect = self.ensure_form_protection(form)
if form_protection_redirect:
return form_protection_redirect

if isinstance(form, MultiplePropertiesForm):
response = self.handle_multiple_properties_ajax_request(form)
if response is not None:
Expand Down
8 changes: 8 additions & 0 deletions app/session.py
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,14 @@ def get_eligibility(self):
def clear_eligibility(self):
self["eligibility"] = Eligibility(forms={}, _notes={})

@property
def ec_reference(self):
return self.get("_ec_reference", None)

@ec_reference.setter
def ec_reference(self, ec_reference):
self["_ec_reference"] = ec_reference

@property
def category(self) -> Category | None:
"""Get the category from the session.
Expand Down

0 comments on commit 738b128

Please sign in to comment.