diff --git a/api.md b/api.md
index 029ddaf24..0c51357cd 100644
--- a/api.md
+++ b/api.md
@@ -121,7 +121,6 @@ This page documents the Fronstage ui endpoints that can be hit.
`/account`
* GET and POST
* GET and POST `/change-password`
-* POST `/change-account-email-address`
* GET and POST `/change-account-details`
* GET `/something-else` Gets the something else once the option is selected
* POST `/something-else` Sends secure message for the something else pages
diff --git a/frontstage/models.py b/frontstage/models.py
index 1c06de1ff..47a684555 100644
--- a/frontstage/models.py
+++ b/frontstage/models.py
@@ -288,30 +288,38 @@ class ContactDetailsChangeForm(FlaskForm):
first_name = StringField(
_("First name"),
validators=[
- DataRequired(_("First name is required")),
+ DataRequired(_("Enter your first name")),
Length(max=254, message=_("Your first name must be less than 254 " "characters")),
],
)
last_name = StringField(
_("Last name"),
validators=[
- DataRequired(_("Last name is required")),
+ DataRequired(_("Enter your last name")),
Length(max=254, message=_("Your last name must be less than 254 characters")),
],
)
phone_number = StringField(
_("Telephone number"),
validators=[
- DataRequired(_("Phone number is required")),
- Length(min=9, max=15, message=_("This should be a valid phone number between 9 and 15 " "digits")),
+ DataRequired(_("Enter a phone number")),
+ Length(min=9, max=15, message=_("Enter a 9 to 15 digit number")),
],
default=None,
)
email_address = StringField(
_("Email address"),
validators=[
- DataRequired(_("Email address is required")),
- Email(message=_("Invalid email address")),
+ DataRequired(_("Enter an email address")),
+ Email(message=_("Enter an email address in the correct format, for example, name@example.com")),
+ Length(max=254, message=_("Your email must have fewer than 254 characters")),
+ ],
+ )
+ confirm_email_address = StringField(
+ _("Confirm email address"),
+ validators=[
+ DataRequired(_("Enter email addresses that match")),
+ EqualTo("email_address", "Enter email addresses that match"),
Length(max=254, message=_("Your email must have fewer than 254 characters")),
],
)
diff --git a/frontstage/templates/account/account-change-email-address-almost-done.html b/frontstage/templates/account/account-change-email-address-almost-done.html
deleted file mode 100644
index 753ea444c..000000000
--- a/frontstage/templates/account/account-change-email-address-almost-done.html
+++ /dev/null
@@ -1,45 +0,0 @@
-{% extends "layouts/_block_content.html" %}
-{% from "components/breadcrumbs/_macro.njk" import onsBreadcrumbs %}
-{% from "components/fieldset/_macro.njk" import onsFieldset %}
-{% from "components/button/_macro.njk" import onsButton %}
-
-{% set page_title = "Change email address" %}
-{% set breadcrumbsData = [
- {
- "text": "Surveys",
- "url": "/surveys/todo",
- "id": "b-item-1"
- },
- {
- "text": "Account",
- "url": "/my-account",
- "id": "b-item-2"
- },
- {
- "text": "Change your contact details",
- "url": "/my-account/change-account-details",
- "id": "b-item-3"
- },
-] %}
-
-{% block breadcrumbs %}
- {{
- onsBreadcrumbs({
- "ariaLabel": "Breadcrumbs",
- "id": "breadcrumbs",
- "itemsList": breadcrumbsData
- })
- }}
-{% endblock breadcrumbs %}
-
-{% block main %}
-
Almost done
- We have sent a verification email to your new email address.
- Follow the link in the email to verify the change.
- Email not arrived? It may be in your junk folder.
- If it does not arrive within 15 minutes, please contact us.
-
-{% endblock main %}
diff --git a/frontstage/templates/account/account-change-email-address-conflict.html b/frontstage/templates/account/account-change-email-address-conflict.html
deleted file mode 100644
index fec108f2e..000000000
--- a/frontstage/templates/account/account-change-email-address-conflict.html
+++ /dev/null
@@ -1,40 +0,0 @@
-{% extends "layouts/_block_content.html" %}
-{% from "components/breadcrumbs/_macro.njk" import onsBreadcrumbs %}
-{% from "components/fieldset/_macro.njk" import onsFieldset %}
-{% from "components/button/_macro.njk" import onsButton %}
-
-{% set page_title = "Change email address conflict" %}
-{% set breadcrumbsData = [
- {
- "text": "Surveys",
- "url": "/surveys/todo",
- "id": "b-item-1"
- },
- {
- "text": "Account",
- "url": "/my-account",
- "id": "b-item-2"
- },
- {
- "text": "Change your contact details",
- "url": "/my-account/change-account-details",
- "id": "b-item-3"
- },
-] %}
-
-{% block breadcrumbs %}
- {{
- onsBreadcrumbs({
- "ariaLabel": "Breadcrumbs",
- "id": "breadcrumbs",
- "itemsList": breadcrumbsData
- })
- }}
-{% endblock breadcrumbs %}
-
-{% block main %}
- We are not able to change your email address
- This is because the new address you have provided is being used on another account in our system.
- If you are no longer required to respond to your surveys, you can transfer surveys to a colleague instead.
- If you need further help, please contact us.
-{% endblock main %}
diff --git a/frontstage/templates/account/account-change-email-address.html b/frontstage/templates/account/account-change-email-address.html
deleted file mode 100644
index fa0133ff1..000000000
--- a/frontstage/templates/account/account-change-email-address.html
+++ /dev/null
@@ -1,87 +0,0 @@
-{% extends "layouts/_block_content.html" %}
-{% from "components/breadcrumbs/_macro.njk" import onsBreadcrumbs %}
-{% from "components/fieldset/_macro.njk" import onsFieldset %}
-{% from "components/button/_macro.njk" import onsButton %}
-
-{% set page_title = "Change email address" %}
-{% set breadcrumbsData = [
- {
- "text": "Surveys",
- "url": "/surveys/todo",
- "id": "b-item-1"
- },
- {
- "text": "Account",
- "url": "/my-account",
- "id": "b-item-2"
- },
- {
- "text": "Change your contact details",
- "url": "/my-account/change-account-details",
- "id": "b-item-3"
- },
-] %}
-
-{% block breadcrumbs %}
- {{
- onsBreadcrumbs({
- "ariaLabel": "Breadcrumbs",
- "id": "breadcrumbs",
- "itemsList": breadcrumbsData
- })
- }}
-{% endblock breadcrumbs %}
-
-{% block main %}
- {% with messages = get_flashed_messages(with_categories=true) %}
- {% if messages %}
- {% for category, message in messages %}
- {% if category == "error" %}
- {% call onsPanel({
- "variant": 'error',
- "id": 'error-id',
- "iconType": 'lock',
- "classes": 'ons-u-mb-m'
- }) %}
- {{ message }}
- {% endcall %}
- {% else %}
- {% call onsPanel({
- "variant": 'success',
- "id": 'success-id',
- "iconType": 'check',
- "classes": 'ons-u-mb-m'
- }) %}
- {{ message }}
- {% endcall %}
- {% endif %}
- {% endfor %}
- {% endif %}
- {% endwith %}
- Change email address
- You will need to authorise a change of email address.
- We will send a verification email to {{ new_email }}.
- {% call onsPanel({}) %}
-
- If you are longer required to respond to your surveys, you can transfer your surveys to a colleague.
-
- {% endcall %}
-
-{% endblock main %}
diff --git a/frontstage/templates/account/account-contact-detail-change.html b/frontstage/templates/account/account-contact-detail-change.html
index dec468bcb..852586351 100644
--- a/frontstage/templates/account/account-contact-detail-change.html
+++ b/frontstage/templates/account/account-contact-detail-change.html
@@ -8,14 +8,9 @@
{% set page_title = "Change contact details" %}
{% set breadcrumbsData = [
{
- "text": "Surveys",
- "url": "/surveys/todo",
- "id": "b-item-1"
- },
- {
- "text": "Account",
+ "text": "Back",
"url": "/my-account",
- "id": "b-item-2"
+ "id": "b-item-1"
}
] %}
@@ -31,25 +26,18 @@
{% block main %}
{% if errors|length > 0 %}
- {% if errors|length == 1 %}
- {% set errorTitle = 'There is 1 error on this page' %}
- {% elif errors|length > 1 %}
- {% set errorTitle = 'There are ' ~ errors|length ~ ' errors on this page' %}
- {% endif %}
{% call
onsPanel({
"variant": "error",
"classes": "ons-u-mb-s",
- "title": errorTitle
+ "title": "There is a problem with your answer"
})
%}
- These must be corrected to continue.
{% set errorData = [] %}
{% for error in errors %}
- {% set error_text = error %}
{% do errorData.append(
{
- "text": 'Problem with the ' ~ error_text.replace('_', ' '),
+ "text": error[0],
"url": "#" ~ error ~ '_error',
"classes": "ons-js-inpagelink"
}
@@ -117,6 +105,22 @@ Enter your new contact details
"value": emailAddress,
})
}}
+ {% if errors.email_address %}
+ {% set confirmErrorEmailAddress = { "text": errors['confirm_email_address'][0], "id": 'confirm_email_address_error' } %}
+ {% set confirmEmailAddress = form.confirm_email_address.data %}
+ {% endif %}
+ {{
+ onsInput({
+ "id": "confirm_email_address",
+ "name": "confirm_email_address",
+ "type": "text",
+ "label": {
+ "text": 'Confirm email address'
+ },
+ "error": errorConfirmEmailAddress,
+ "value": confirmEmailAddress,
+ })
+ }}
{% set phoneNumber = respondent.telephone %}
{% if errors.phone_number %}
{% set errorPhoneNumber = { "text": errors['phone_number'][0], "id": 'phone_number_error' } %}
@@ -130,7 +134,8 @@ Enter your new contact details
"autocomplete": "tel",
"classes": "input--w-8",
"label": {
- "text": 'Phone number'
+ "text": "Phone number",
+ "description": "We will use this number if we need to contact you about your answers. For international numbers include the country code."
},
"error": errorPhoneNumber,
"value": phoneNumber
@@ -139,20 +144,11 @@ Enter your new contact details
{{
onsButton({
- "text": "Save",
+ "text": "Change details",
"id": "btn-option-save",
"submitType": "timer"
})
}}
- {{
- onsButton({
- "id": "btn-account-change-detail-cancel",
- "url": url_for('account_bp.account'),
- "text": 'Cancel',
- "variants": 'secondary',
- "noIcon": true
- })
- }}
{% endblock main %}
diff --git a/frontstage/templates/account/account.html b/frontstage/templates/account/account.html
index 3367ae61a..c5703bc56 100644
--- a/frontstage/templates/account/account.html
+++ b/frontstage/templates/account/account.html
@@ -6,8 +6,40 @@
{% from "components/details/_macro.njk" import onsDetails %}
{% block main %}
-{% include "radio-option-select-error-panel.html" %}
+ {% with messages = get_flashed_messages(with_categories=true) %}
+ {% if messages %}
+ {% for category, message in messages %}
+ {% if category == "error" %}
+ {% call onsPanel({
+ "variant": 'error',
+ "id": 'error-id',
+ "iconType": 'lock',
+ "classes": 'ons-u-mb-m'
+ }) %}
+
{{ message }}
+ {% endcall %}
+ {% elif category == "warn" %}
+ {% call onsPanel({
+ "variant": 'warn',
+ "id": 'info-id',
+ "classes": 'ons-u-mb-m'
+ }) %}
+
{{ message }}
+ {% endcall %}
+ {% else %}
+ {% call onsPanel({
+ "variant": 'success',
+ "id": 'success-id',
+ "iconType": 'check',
+ "classes": 'ons-u-mb-m'
+ }) %}
+
{{ message }}
+ {% endcall %}
+ {% endif %}
+ {% endfor %}
+ {% endif %}
+ {% endwith %}
My Account
{{
onsDescriptionList({
diff --git a/frontstage/views/account/account.py b/frontstage/views/account/account.py
index f99683b24..c2c270f30 100644
--- a/frontstage/views/account/account.py
+++ b/frontstage/views/account/account.py
@@ -8,12 +8,7 @@
from frontstage.common.utilities import obfuscate_email
from frontstage.controllers import auth_controller, party_controller
from frontstage.exceptions.exceptions import ApiError, AuthError
-from frontstage.models import (
- ChangePasswordFrom,
- ConfirmEmailChangeForm,
- ContactDetailsChangeForm,
- OptionsForm,
-)
+from frontstage.models import ChangePasswordFrom, ContactDetailsChangeForm, OptionsForm
from frontstage.views.account import account_bp
from frontstage.views.template_helper import render_template
@@ -96,14 +91,11 @@ def change_password(session):
return render_template("account/account-change-password.html", session=session, form=form, errors=errors)
-@account_bp.route("/change-account-email-address", methods=["POST"])
-@jwt_authorization(request)
-def change_email_address(session):
- form = ConfirmEmailChangeForm(request.values)
+def change_email_address(session, new_email_address):
party_id = session.get_party_id()
respondent_details = party_controller.get_respondent_party_by_id(party_id)
respondent_details["email_address"] = respondent_details["emailAddress"]
- respondent_details["new_email_address"] = form["email_address"].data
+ respondent_details["new_email_address"] = new_email_address
respondent_details["change_requested_by_respondent"] = True
logger.info("Attempting to update email address changes on the account", party_id=party_id)
try:
@@ -113,11 +105,11 @@ def change_email_address(session):
logger.error("Failed to updated email on account", status=exc.status_code, party_id=party_id)
if exc.status_code == 409:
logger.info("The email requested already registered in our system. Request denied", party_id=party_id)
- return render_template("account/account-change-email-address-conflict.html")
+ return False
else:
raise exc
logger.info("Successfully updated email on account", party_id=party_id)
- return render_template("account/account-change-email-address-almost-done.html", session=session)
+ return True
@account_bp.route("/change-account-details", methods=["GET", "POST"])
@@ -142,16 +134,21 @@ def change_account_details(session):
logger.error("Failed to updated account", status=exc.status_code)
raise exc
logger.info("Successfully updated account", party_id=party_id)
- success_panel = create_success_message(attributes_changed, "We have updated your ")
- flash(success_panel)
is_email_update_required = form["email_address"].data != respondent_details["emailAddress"]
if is_email_update_required:
- return render_template(
- "account/account-change-email-address.html",
- new_email=form["email_address"].data,
- form=ConfirmEmailChangeForm(),
- )
- return redirect(url_for("surveys_bp.get_survey_list", tag="todo"))
+ if not change_email_address(session=session, new_email_address=form["email_address"].data):
+ form.errors["email_address"] = ["Email address has already been used to register an account"]
+ return render_template(
+ "account/account-contact-detail-change.html",
+ session=session,
+ form=form,
+ errors=form.errors,
+ respondent=respondent_details,
+ )
+ else:
+ flash("We have sent you an email to confirm your new email address.")
+ flash("Your contact details have changed")
+ return redirect(url_for("account_bp.account"))
else:
return render_template(
"account/account-contact-detail-change.html",
@@ -184,28 +181,3 @@ def check_attribute_change(form, attributes_changed, respondent_details, update_
update_required_flag = True
attributes_changed.append("telephone number")
return update_required_flag
-
-
-def create_success_message(attr, message):
- """
- Takes a string as message and a list of strings attr
- to append message with attributes adding ',' and 'and'
-
- for example: if message = "I ate "
- and attr = ["apple","banana","grapes"]
- result will be = "I ate apple, banana and grapes."
-
- :param attr: list of string
- :param message: string
- :returns: A string formatted using the two supplied variables
- :rtype: str
- """
- for x in attr:
- if x == attr[-1] and len(attr) >= 2:
- message += " and " + x
- elif x != attr[0] and len(attr) > 2:
- message += ", " + x
- else:
- message += x
-
- return message
diff --git a/tests/integration/views/account/test_account.py b/tests/integration/views/account/test_account.py
index a67f45743..bcb28ff07 100644
--- a/tests/integration/views/account/test_account.py
+++ b/tests/integration/views/account/test_account.py
@@ -6,7 +6,6 @@
from frontstage import app
from tests.integration.mocked_services import (
encoded_jwt_token,
- respondent_enrolments,
respondent_party,
survey_list_todo,
url_banner_api,
@@ -72,34 +71,10 @@ def test_account_contact_details_error(self, mock_request, get_respondent_party_
get_respondent_party_by_id.return_value = respondent_party
response = self.app.post("/my-account/change-account-details", data={"first_name": ""}, follow_redirects=True)
- self.assertIn("There are 4 errors on this page".encode(), response.data)
- self.assertIn("Problem with the first name".encode(), response.data)
- self.assertIn("Problem with the phone number".encode(), response.data)
- self.assertIn("Problem with the email address".encode(), response.data)
-
- @requests_mock.mock()
- @patch("frontstage.controllers.party_controller.get_respondent_party_by_id")
- @patch("frontstage.controllers.party_controller.update_account")
- @patch("frontstage.controllers.party_controller.get_case_list_for_respondent")
- @patch("frontstage.controllers.party_controller.get_respondent_enrolments")
- def test_account_contact_details_success(
- self, mock_request, get_respondent_enrolments, get_survey_list, _, get_respondent_party_by_id
- ):
- mock_request.get(url_banner_api, status_code=404)
- get_respondent_party_by_id.return_value = respondent_party
- get_survey_list.return_value = survey_list_todo
- get_respondent_enrolments.return_value = respondent_enrolments
- response = self.app.post(
- "/my-account/change-account-details",
- data={
- "first_name": "new first name",
- "last_name": "new last name",
- "phone_number": "8882257773",
- "email_address": "example@example.com",
- },
- follow_redirects=True,
- )
- self.assertIn("updated your first name, last name and telephone number".encode(), response.data)
+ self.assertIn("There is a problem with your answer".encode(), response.data)
+ self.assertIn("Enter your first name".encode(), response.data)
+ self.assertIn("Enter your last name".encode(), response.data)
+ self.assertIn("Enter an email address".encode(), response.data)
@requests_mock.mock()
@patch("frontstage.controllers.party_controller.get_respondent_party_by_id")
@@ -118,35 +93,12 @@ def test_account_change_account_email_address(
"last_name": "test_account",
"phone_number": "07772257773",
"email_address": "exampleone@example.com",
+ "confirm_email_address": "exampleone@example.com",
},
follow_redirects=True,
)
- self.assertIn("updated your first name, last name and telephone number".encode(), response.data)
- self.assertIn("Change email address".encode(), response.data)
- self.assertIn("You will need to authorise a change of email address.".encode(), response.data)
- self.assertIn("We will send a verification email to".encode(), response.data)
- self.assertIn("exampleone@example.com".encode(), response.data)
-
- @requests_mock.mock()
- @patch("frontstage.controllers.party_controller.get_respondent_party_by_id")
- @patch("frontstage.controllers.party_controller.update_account")
- @patch("frontstage.controllers.party_controller.get_case_list_for_respondent")
- def test_account_change_account_email_address_almost_done(
- self, mock_request, get_survey_list, update_account, get_respondent_party_by_id
- ):
- mock_request.get(url_banner_api, status_code=404)
- get_respondent_party_by_id.return_value = respondent_party
- get_survey_list.return_value = survey_list_todo
- response = self.app.post(
- "/my-account/change-account-email-address",
- data={"email_address": "exampleone@example.com"},
- follow_redirects=True,
- )
- self.assertIn("Almost done".encode(), response.data)
- self.assertIn("We have sent a verification email to your new email address.".encode(), response.data)
- self.assertIn("Follow the link in the email to verify the change.".encode(), response.data)
- self.assertIn("Email not arrived? It may be in your junk folder.".encode(), response.data)
- self.assertIn("If it does not arrive within 15 minutes, please".encode(), response.data)
+ self.assertIn("We have sent you an email to confirm your new email address.".encode(), response.data)
+ self.assertIn("Your contact details have changed".encode(), response.data)
@requests_mock.mock()
@patch("frontstage.controllers.party_controller.get_respondent_party_by_id")
diff --git a/tests/unit/test_account.py b/tests/unit/test_account.py
index 9dc707b79..f31fc6ae4 100644
--- a/tests/unit/test_account.py
+++ b/tests/unit/test_account.py
@@ -2,48 +2,10 @@
from werkzeug.datastructures import ImmutableMultiDict
-from frontstage.views.account.account import (
- check_attribute_change,
- create_success_message,
-)
+from frontstage.views.account.account import check_attribute_change
class TestAccount(unittest.TestCase):
- def test_message_success_with_three_attributes(self):
- attr = ["first_name", "second_name", "third_name"]
- message = "We have updated "
- actual_message = create_success_message(attr, message)
- expected_message = "We have updated first_name, second_name and third_name"
- self.assertTrue(actual_message == expected_message)
-
- def test_message_success_with_two_attributes(self):
- attr = ["first_name", "second_name"]
- message = "We have updated "
- actual_message = create_success_message(attr, message)
- expected_message = "We have updated first_name and second_name"
- self.assertTrue(actual_message == expected_message)
-
- def test_message_success_with_single_attribute(self):
- attr = ["first_name"]
- message = "We have updated "
- actual_message = create_success_message(attr, message)
- expected_message = "We have updated first_name"
- self.assertTrue(actual_message == expected_message)
-
- def test_message_success_with_four_attributes(self):
- attr = ["first_name", "second_name", "third_name", "email"]
- message = "We have updated "
- actual_message = create_success_message(attr, message)
- expected_message = "We have updated first_name, second_name, third_name and email"
- self.assertTrue(actual_message == expected_message)
-
- def test_message_success_with_no_attributes(self):
- attr = []
- message = "We have updated "
- actual_message = create_success_message(attr, message)
- expected_message = "We have updated "
- self.assertTrue(actual_message == expected_message)
-
def test_check_attribute_change_returns_true(self):
first_name = FormData("something")
last_name = FormData("test")