Skip to content

Commit

Permalink
Merge branch 'main' into DST-861
Browse files Browse the repository at this point in the history
  • Loading branch information
cencorroll authored Jan 7, 2025
2 parents 94bac35 + 6d8c95d commit 2a84a4d
Show file tree
Hide file tree
Showing 76 changed files with 2,717 additions and 1,470 deletions.
8 changes: 7 additions & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,13 @@ jobs:
command: |
sudo tee -a /etc/hosts \<<<'127.0.0.1 report-a-suspected-breach'
pipenv run playwright install --with-deps firefox
pipenv run pytest tests/test_frontend --browser firefox --junitxml=test-results/frontend/results.xml --create-db
pipenv run pytest \
--ignore tests/test_unit \
--browser firefox \
--circleci-parallelize \
--maxprocesses=4 \
-n=auto \
--junitxml=test-results/frontend/results.xml
- store_test_results:
path: test-results
Expand Down
5 changes: 4 additions & 1 deletion Pipfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ verify_ssl = true
name = "pypi"

[packages]
django = "~=4.2.16"
django = "~=4.2.17"
django-environ = "~=0.11"
psycopg = "~=3.1"
django-crispy-forms = "~=2.1"
Expand Down Expand Up @@ -39,6 +39,7 @@ certifi = "*"
cryptography = "~=43.0.3"
django-permissions-policy = "*"
playwright = "~=1.47.0"
PyJWT = "~=2.10"

[dev-packages]
black = "~=24.3"
Expand All @@ -55,6 +56,8 @@ localstack = "~=3.2"
pytest-playwright = "~=0.5.2"
coverage = "*"
pytest-cov = "*"
pytest-circleci-parallelized = "~=0.1.0"
pytest-xdist = "~=3.6.1"
django-debug-toolbar = "*"
pyinstrument = "*"
factory-boy = "*"
Expand Down
1,457 changes: 734 additions & 723 deletions Pipfile.lock

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion django_app/config/settings/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,7 @@
CSP_REPORT_ONLY = env.csp_report_only

# URL to send CSP violation reports to
CSP_REPORT_URI = env.csp_report_uri
# CSP_REPORT_URI = env.csp_report_uri

# Permissions policy header
PERMISSIONS_POLICY = {
Expand Down
4 changes: 2 additions & 2 deletions django_app/core/base_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,11 +63,11 @@ def form_valid(self, form):

# check what (if any) fields have changed. This is useful if we want to control where the user gets redirected
# to after the form is submitted depending on what they've changed
self.changed_fields = []
self.changed_fields = {}
if previous_data := get_dirty_form_data(self.request, self.step_name):
for key, value in previous_data.items():
if key in form_data and form_data[key] != value:
self.changed_fields.append(key)
self.changed_fields[key] = value

# now keep it in the session
self.request.session[self.step_name] = form_data
Expand Down
11 changes: 11 additions & 0 deletions django_app/core/choices.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
from django.db import models


class BaseChoices(models.TextChoices):
@classmethod
def active_choices(cls):
return [choice for choice in cls.choices if choice[0] not in cls.inactive_choices()]

@classmethod
def inactive_choices(cls):
pass
9 changes: 8 additions & 1 deletion django_app/feedback/choices.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
from typing import List

from core.choices import BaseChoices
from django.db import models


Expand All @@ -9,7 +12,11 @@ class RatingChoices(models.IntegerChoices):
VERY_DISSATISFIED = 1, "Very dissatisfied"


class DidYouExperienceAnyIssues(models.TextChoices):
class DidYouExperienceAnyIssues(BaseChoices):
@classmethod
def inactive_choices(cls) -> List[str]:
return ["no"]

NO = "no", "I did not experience any issues"
NOT_FOUND = "not_found", "I did not find what I was looking for"
DIFFICULT = "difficult", "I found it difficult to navigate"
Expand Down
12 changes: 9 additions & 3 deletions django_app/feedback/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,20 @@ class FeedbackForm(BaseModelForm):
submit_button_text = "Submit"

did_you_experience_any_issues = forms.MultipleChoiceField(
choices=DidYouExperienceAnyIssues.choices,
choices=DidYouExperienceAnyIssues.active_choices(),
widget=forms.CheckboxSelectMultiple,
label="Select all that apply",
required=False,
)

class Meta:
model = FeedbackItem
fields = ("rating", "did_you_experience_any_issues", "how_we_could_improve_the_service")
fields = ("rating", "did_you_experience_any_issues", "how_we_could_improve_the_service", "user_name", "user_email")
labels = {
"how_we_could_improve_the_service": "How could we improve the service?",
"rating": "Overall, how satisfied did you feel with using this service?",
"user_name": "Your name",
"user_email": "Your email address",
}
widgets = {
"rating": forms.RadioSelect,
Expand Down Expand Up @@ -64,5 +66,9 @@ def __init__(self, *args: Any, **kwargs: Any) -> None:
),
css_class="optional_question",
),
HTMLTemplate("feedback/feedback_disclaimer.html"),
Fieldset(
HTMLTemplate("feedback/participate_in_user_research.html"),
Field("user_name", context={"label_size": None}),
Field("user_email", context={"label_size": None}),
),
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Generated by Django 4.2.16 on 2024-12-18 16:41

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
("feedback", "0003_feedbackitem_url_historicalfeedbackitem_url"),
]

operations = [
migrations.AddField(
model_name="feedbackitem",
name="user_email",
field=models.EmailField(blank=True, max_length=254, null=True),
),
migrations.AddField(
model_name="feedbackitem",
name="user_name",
field=models.CharField(blank=True, max_length=255, null=True),
),
migrations.AddField(
model_name="historicalfeedbackitem",
name="user_email",
field=models.EmailField(blank=True, max_length=254, null=True),
),
migrations.AddField(
model_name="historicalfeedbackitem",
name="user_name",
field=models.CharField(blank=True, max_length=255, null=True),
),
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Generated by Django 4.2.16 on 2024-12-27 21:23

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
("feedback", "0004_feedbackitem_user_email_feedbackitem_user_name_and_more"),
]

operations = [
migrations.AlterField(
model_name="feedbackitem",
name="rating",
field=models.IntegerField(
choices=[(5, "Very satisfied"), (4, "Satisfied"), (3, "Neutral"), (2, "Dissatisfied"), (1, "Very dissatisfied")]
),
),
migrations.AlterField(
model_name="historicalfeedbackitem",
name="rating",
field=models.IntegerField(
choices=[(5, "Very satisfied"), (4, "Satisfied"), (3, "Neutral"), (2, "Dissatisfied"), (1, "Very dissatisfied")]
),
),
]
2 changes: 2 additions & 0 deletions django_app/feedback/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ class FeedbackItem(BaseModel):
)
how_we_could_improve_the_service = models.TextField(null=True, blank=True)
url = models.URLField(null=True, blank=True)
user_name = models.CharField(max_length=255, null=True, blank=True)
user_email = models.EmailField(null=True, blank=True)

def get_did_you_experience_any_issues_display(self) -> list[str]:
display = []
Expand Down
2 changes: 2 additions & 0 deletions django_app/feedback/static/feedback/javascript/feedback.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,6 @@ $(window).bind("pageshow", function(event) {
$('.optional_question').hide()
}
})

$("input[name='rating']:checked").trigger("change")
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
<h2 class="govuk-heading-m">Participating in further research</h2>
<p class="govuk-body">We're always improving our services and would like your help to make this one better. If you're happy for us to contact you about participating in further research, please leave your name and email address.</p>
18 changes: 11 additions & 7 deletions django_app/healthcheck/checks/s3.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,22 @@
import boto3
import sentry_sdk
from core.document_storage import PermanentDocumentStorage, TemporaryDocumentStorage
from django.conf import settings


def s3_check() -> bool:
"""
Performs a check on the S3 connection
Check if the S3 bucket exists and ensure the app can access it.
https://boto3.amazonaws.com/v1/documentation/api/1.35.9/reference/services/s3/client/head_bucket.html
"""
temporary_document_bucket = TemporaryDocumentStorage().bucket
permanent_document_bucket = PermanentDocumentStorage().bucket
client = boto3.client("s3")

bucket_names = [settings.TEMPORARY_S3_BUCKET_NAME, settings.PERMANENT_S3_BUCKET_NAME]

try:
assert temporary_document_bucket.creation_date
assert permanent_document_bucket.creation_date
return True
for bucket_name in bucket_names:
client.head_bucket(Bucket=bucket_name)
except Exception as e:
sentry_sdk.capture_exception(e)
return False

return True
6 changes: 3 additions & 3 deletions django_app/healthcheck/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from django.http import HttpRequest, HttpResponse
from django.shortcuts import render
from django.views.generic import View
from healthcheck.checks import db_check
from healthcheck.checks import db_check, s3_check


class HealthCheckView(View):
Expand All @@ -20,8 +20,8 @@ def get(self, request: HttpRequest, *args: object, **kwargs: object) -> HttpResp

start = time.time()
is_db_good = db_check()
# is_s3_good = s3_check()
all_good = is_db_good and True
is_s3_good = s3_check()
all_good = is_db_good and is_s3_good

end = time.time()
time_taken = round(end - start, 3)
Expand Down
10 changes: 10 additions & 0 deletions django_app/report_a_suspected_breach/forms/base_forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,18 @@ class Meta:
)

def __init__(self, *args: object, **kwargs: object) -> None:
if "is_uk_address" in kwargs:
explicit_address_passed = True
else:
explicit_address_passed = False
self.is_uk_address = kwargs.pop("is_uk_address", False)
super().__init__(*args, **kwargs)
if not explicit_address_passed and self.data and self.data.get("country") == "GB":
# if we're reloading this form with previously entered data, and we haven't explicitly set the
# `is_uk_address` flag we can work backwards to set the is_uk_address flag correctly. This is useful for
# retrieving the form from get_all_cleaned_data()
self.is_uk_address = True

if self.is_uk_address:
self.fields["country"].initial = "GB"
self.fields["country"].widget = forms.HiddenInput()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ def clean(self) -> dict[str, Any]:
company_details = get_details_from_companies_house(registered_company_number)
cleaned_data["registered_company_number"] = company_details["company_number"]
cleaned_data["registered_company_name"] = company_details["company_name"]
cleaned_data["name"] = company_details["company_name"]

# converting the companies house address dict into 'normal' format and also flattening the
# dictionary so the address keys are on the top-level key structure
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ def __init__(self, *args: object, **kwargs: object) -> None:

def clean_document(self) -> list[UploadedDocument]:
documents = self.cleaned_data.get("document")
if len(documents) > 10:
raise forms.ValidationError("You can only select up to 10 files at the same time", code="too_many")
for document in documents:

# does the document contain a virus?
Expand Down
14 changes: 10 additions & 4 deletions django_app/report_a_suspected_breach/forms/forms_supply_chain.py
Original file line number Diff line number Diff line change
Expand Up @@ -273,14 +273,20 @@ class Meta:
model = Breach
fields = ("were_there_other_addresses_in_the_supply_chain", "other_addresses_in_the_supply_chain")
labels = {
"were_there_other_addresses_in_the_supply_chain": "Were there any other addresses in the supply chain?",
"other_addresses_in_the_supply_chain": "Give all addresses",
"were_there_other_addresses_in_the_supply_chain": "Were any other people or businesses involved in the trade?",
"other_addresses_in_the_supply_chain": "Give all names and addresses",
}
error_messages = {
"were_there_other_addresses_in_the_supply_chain": {
"required": "Select yes if there were any other addresses in the supply chain"
"required": "Select yes if there were any other people or businesses involved in the trade"
},
"other_addresses_in_the_supply_chain": {"required": "Enter other addresses in the supply chain"},
"other_addresses_in_the_supply_chain": {
"required": "Enter names and addresses of other people or businesses involved in the trade"
},
}
help_texts = {
"were_there_other_addresses_in_the_supply_chain": "Examples include if the goods were sent via a consignee, "
"or if the services were brokered via a third party"
}

def __init__(self, *args: object, **kwargs: object) -> None:
Expand Down
Loading

0 comments on commit 2a84a4d

Please sign in to comment.