From 49733c0015585bfd1d606ed5924fe8e6b29dd7ac Mon Sep 17 00:00:00 2001 From: marcelkornblum Date: Sat, 8 Jul 2023 13:32:20 +0100 Subject: [PATCH 01/31] add verified email validation --- src/peoplefinder/forms/profile.py | 18 +++++++++++++++++- src/peoplefinder/models.py | 2 +- src/peoplefinder/services/person.py | 19 +++++++++++++++++++ .../templates/peoplefinder/profile-edit.html | 14 -------------- 4 files changed, 37 insertions(+), 16 deletions(-) diff --git a/src/peoplefinder/forms/profile.py b/src/peoplefinder/forms/profile.py index 10fbf6a04..3bc0f59cd 100644 --- a/src/peoplefinder/forms/profile.py +++ b/src/peoplefinder/forms/profile.py @@ -1,8 +1,9 @@ from django import forms from django.contrib.auth import get_user_model -from django.core.validators import ValidationError +from django.core.validators import ValidationError, validate_email from peoplefinder.models import Person +from peoplefinder.services.person import PersonService User = get_user_model() @@ -202,6 +203,21 @@ def clean_manager(self): return manager + def clean_email(self): + email = self.cleaned_data["email"] + + validate_email(email) + + verified_emails = PersonService.get_verified_emails(self.instance) + if verified_emails == []: + raise Exception("Could not retrieve valid emails for this user") + if email not in verified_emails: + raise ValidationError( + "That email address has not been verified through SSO authentication" + ) + + return email + def clean(self): cleaned_data = super().clean() diff --git a/src/peoplefinder/models.py b/src/peoplefinder/models.py index 0211ec19b..8d0bfa2ac 100644 --- a/src/peoplefinder/models.py +++ b/src/peoplefinder/models.py @@ -352,7 +352,7 @@ class Meta: email = models.EmailField( "Main work email address", help_text=( - "Enter your own official work email address provided by the" + "Choose your own official work email address provided by the" " organisation you are directly employed by or contracted to." ), ) diff --git a/src/peoplefinder/services/person.py b/src/peoplefinder/services/person.py index 2f42d8e06..7e35ffc98 100644 --- a/src/peoplefinder/services/person.py +++ b/src/peoplefinder/services/person.py @@ -1,5 +1,6 @@ import logging from typing import Optional +import requests from django.conf import settings from django.contrib.auth.models import Group @@ -314,6 +315,24 @@ def notify_about_deletion(self, person: Person, deleted_by: User) -> None: personalisation=context, ) + @staticmethod + def get_verified_emails(person: Person) -> list[str]: + user_email = person.user.email # @TODO prefer UUID if we can get it from SSO + url = f"{settings.AUTHBROKER_URL}/api/v1/user/emails/" + params = {"email": user_email} + headers = {"Authorization": f"bearer {settings.AUTHBROKER_INTROSPECTION_TOKEN}"} + + response = requests.get(url, params, headers=headers) + + if response.status_code == 200: + resp_json = response.json() + return resp_json["emails"] + else: + logger.error( + f"Response code [{response.status_code}] from authbroker emails endpoint for {user_email}" + ) + return [] + class PersonAuditLogSerializer(AuditLogSerializer): model = Person diff --git a/src/peoplefinder/templates/peoplefinder/profile-edit.html b/src/peoplefinder/templates/peoplefinder/profile-edit.html index fe527e141..8977f5486 100644 --- a/src/peoplefinder/templates/peoplefinder/profile-edit.html +++ b/src/peoplefinder/templates/peoplefinder/profile-edit.html @@ -39,20 +39,6 @@

Email addresses

{% include 'peoplefinder/components/input.html' with field=form.email %} -
- - - Warning - Do not enter any of the following as your main work email address: -
    -
  • a shared email address, for example, a Private Office or jobshare mailbox
  • -
  • a secondary work email address, for example, a trade.gov.uk email address if you are employed by FCO at post
  • -
  • an alternative work email address that is not safe for official information, for example, fcowebmail.gov.uk
  • -
  • a personal email address, for example, Gmail
  • -
-
-
-

If you want to show a different email address on your profile for your colleagues to contact you on instead, for example a jobshare mailbox or your Private Office address, you can: From fe58b47ce0975425b679ad585e3f3663901b7e3d Mon Sep 17 00:00:00 2001 From: marcelkornblum Date: Sat, 8 Jul 2023 13:54:50 +0100 Subject: [PATCH 02/31] attempt to use select widget --- src/config/settings/base.py | 2 ++ src/peoplefinder/forms/profile.py | 16 +++++++++++++- .../migrations/0103_alter_person_email.py | 21 +++++++++++++++++++ src/peoplefinder/services/person.py | 3 ++- 4 files changed, 40 insertions(+), 2 deletions(-) create mode 100644 src/peoplefinder/migrations/0103_alter_person_email.py diff --git a/src/config/settings/base.py b/src/config/settings/base.py index 5dd9ec73e..1094de891 100644 --- a/src/config/settings/base.py +++ b/src/config/settings/base.py @@ -489,6 +489,8 @@ "team-api-teams-list", ) +AUTHBROKER_INTROSPECTION_TOKEN = env("AUTHBROKER_INTROSPECTION_TOKEN", default="XXX") + # There are some big pages with lots of content that need to send many fields. DATA_UPLOAD_MAX_NUMBER_FIELDS = 10240 diff --git a/src/peoplefinder/forms/profile.py b/src/peoplefinder/forms/profile.py index 3bc0f59cd..b834d3ca8 100644 --- a/src/peoplefinder/forms/profile.py +++ b/src/peoplefinder/forms/profile.py @@ -44,6 +44,7 @@ class Meta: "photo", ] widgets = { + "email": forms.widgets.Select, "workdays": forms.CheckboxSelectMultiple, "key_skills": forms.CheckboxSelectMultiple, "learning_interests": forms.CheckboxSelectMultiple, @@ -94,7 +95,10 @@ def __init__(self, *args, **kwargs) -> None: {"class": "govuk-input govuk-!-width-one-half"} ) self.fields["email"].widget.attrs.update( - {"class": "govuk-input govuk-!-width-one-half"} + { + "class": "govuk-input govuk-!-width-one-half", + "choices": self.get_email_choices(), + } ) self.fields["contact_email"].widget.attrs.update( {"class": "govuk-input govuk-!-width-one-half"} @@ -225,6 +229,16 @@ def clean(self): return cleaned_data + def get_email_choices(self): + verified_emails = PersonService.get_verified_emails(self.instance) + choices = [] + if self.instance.email in verified_emails: + choices += (self.instance.email, self.instance.email) + choices += [ + (email, email) for email in verified_emails if (email, email) not in choices + ] + return choices + def validate_photo(self, photo): if not hasattr(photo, "image"): return diff --git a/src/peoplefinder/migrations/0103_alter_person_email.py b/src/peoplefinder/migrations/0103_alter_person_email.py new file mode 100644 index 000000000..6e1d8974f --- /dev/null +++ b/src/peoplefinder/migrations/0103_alter_person_email.py @@ -0,0 +1,21 @@ +# Generated by Django 4.1.9 on 2023-07-08 12:48 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ("peoplefinder", "0102_remove_person_manager_cannot_be_self_and_more"), + ] + + operations = [ + migrations.AlterField( + model_name="person", + name="email", + field=models.EmailField( + help_text="Choose your own official work email address provided by the organisation you are directly employed by or contracted to.", + max_length=254, + verbose_name="Main work email address", + ), + ), + ] diff --git a/src/peoplefinder/services/person.py b/src/peoplefinder/services/person.py index 7e35ffc98..f92c8ca75 100644 --- a/src/peoplefinder/services/person.py +++ b/src/peoplefinder/services/person.py @@ -318,7 +318,7 @@ def notify_about_deletion(self, person: Person, deleted_by: User) -> None: @staticmethod def get_verified_emails(person: Person) -> list[str]: user_email = person.user.email # @TODO prefer UUID if we can get it from SSO - url = f"{settings.AUTHBROKER_URL}/api/v1/user/emails/" + url = f"{settings.AUTHBROKER_URL}api/v1/user/emails/" params = {"email": user_email} headers = {"Authorization": f"bearer {settings.AUTHBROKER_INTROSPECTION_TOKEN}"} @@ -326,6 +326,7 @@ def get_verified_emails(person: Person) -> list[str]: if response.status_code == 200: resp_json = response.json() + print(resp_json) return resp_json["emails"] else: logger.error( From 31f27ecb5acf9f8fd8e76ebf48590b12a98e4280 Mon Sep 17 00:00:00 2001 From: marcelkornblum Date: Mon, 10 Jul 2023 14:20:03 +0100 Subject: [PATCH 03/31] better default --- src/peoplefinder/forms/profile.py | 4 ++++ src/peoplefinder/services/person.py | 1 - 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/peoplefinder/forms/profile.py b/src/peoplefinder/forms/profile.py index b834d3ca8..1b1b325a6 100644 --- a/src/peoplefinder/forms/profile.py +++ b/src/peoplefinder/forms/profile.py @@ -237,6 +237,10 @@ def get_email_choices(self): choices += [ (email, email) for email in verified_emails if (email, email) not in choices ] + if choices == []: + choices = [ + (self.instance.email, self.instance.email), + ] return choices def validate_photo(self, photo): diff --git a/src/peoplefinder/services/person.py b/src/peoplefinder/services/person.py index f92c8ca75..da81fc218 100644 --- a/src/peoplefinder/services/person.py +++ b/src/peoplefinder/services/person.py @@ -326,7 +326,6 @@ def get_verified_emails(person: Person) -> list[str]: if response.status_code == 200: resp_json = response.json() - print(resp_json) return resp_json["emails"] else: logger.error( From af83e28fca75063542f17d2ef4cbc927036756f4 Mon Sep 17 00:00:00 2001 From: marcelkornblum Date: Mon, 10 Jul 2023 14:21:27 +0100 Subject: [PATCH 04/31] lint --- src/peoplefinder/services/person.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/peoplefinder/services/person.py b/src/peoplefinder/services/person.py index da81fc218..760c82c76 100644 --- a/src/peoplefinder/services/person.py +++ b/src/peoplefinder/services/person.py @@ -322,7 +322,7 @@ def get_verified_emails(person: Person) -> list[str]: params = {"email": user_email} headers = {"Authorization": f"bearer {settings.AUTHBROKER_INTROSPECTION_TOKEN}"} - response = requests.get(url, params, headers=headers) + response = requests.get(url, params, headers=headers, timeout=5) if response.status_code == 200: resp_json = response.json() From 1781f650fb4ec67eda278a13f41bd037fc8fc251 Mon Sep 17 00:00:00 2001 From: Sam Dudley Date: Mon, 10 Jul 2023 15:27:52 +0100 Subject: [PATCH 05/31] Add profile card API and web component Co-authored-by: Marcel Kornblum --- src/config/settings/base.py | 1 + .../static/peoplefinder/profile-card.js | 138 ++++++++++++++++++ .../peoplefinder/components/profile-card.html | 24 +++ src/peoplefinder/urls.py | 6 + src/peoplefinder/views/profile.py | 32 ++++ 5 files changed, 201 insertions(+) create mode 100644 src/peoplefinder/static/peoplefinder/profile-card.js create mode 100644 src/peoplefinder/templates/peoplefinder/components/profile-card.html diff --git a/src/config/settings/base.py b/src/config/settings/base.py index 5dd9ec73e..d0f121236 100644 --- a/src/config/settings/base.py +++ b/src/config/settings/base.py @@ -487,6 +487,7 @@ "person-api-people-list", "person-api-people-detail", "team-api-teams-list", + "profile-get-card", ) # There are some big pages with lots of content that need to send many fields. diff --git a/src/peoplefinder/static/peoplefinder/profile-card.js b/src/peoplefinder/static/peoplefinder/profile-card.js new file mode 100644 index 000000000..d8492b681 --- /dev/null +++ b/src/peoplefinder/static/peoplefinder/profile-card.js @@ -0,0 +1,138 @@ +(function () { + /** + * + * @param {String} html + * @returns {Node} + */ + function htmlTemplate(html) { + const template = document.createElement("template"); + template.innerHTML = html; + + return template.content.cloneNode(true); + } + + /** + * + * @returns {String} + */ + function getStaffSsoUrl() { + const metaName = "peoplefinder:staff-sso-url"; + const meta = document.querySelector(`meta[name="${metaName}"]`); + + return meta.content; + } + + /** + * + * @returns {Node} + */ + async function getProfileCard() { + const url = getStaffSsoUrl() + "/profile/"; + + const response = await fetch(url, { + credentials: "include", + cache: "default", + }); + + if (!response.ok) { + throw new Error("Error fetching profile card"); + } + + const html = await response.text(); + + return htmlTemplate(html); + } + + /** + * + */ + class ProfileCard extends HTMLElement { + constructor() { + super(); + + const css = ` + +

+
+
+
    +
  • +
  • Loading...
  • +
+
+
+ `; + + const cssTemplate = htmlTemplate(css); + + this.attachShadow({ mode: "open" }); + this.shadowRoot.append(cssTemplate); + } + + async connectedCallback() { + const profileName = this.getAttribute("profile-name"); + + if (profileName) { + this.find(".profile-name").innerHTML = profileName; + } + + let html = null; + + try { + html = await getProfileCard(); + } catch (error) { + console.log(error); + } + + if (html) { + this.shadowRoot.querySelector(".loading").style.display = "none"; + this.shadowRoot.append(html); + } + } + + find(selector) { + return this.shadowRoot.querySelector(selector); + } + } + + customElements.define("profile-card", ProfileCard); +})(); diff --git a/src/peoplefinder/templates/peoplefinder/components/profile-card.html b/src/peoplefinder/templates/peoplefinder/components/profile-card.html new file mode 100644 index 000000000..ceb083b71 --- /dev/null +++ b/src/peoplefinder/templates/peoplefinder/components/profile-card.html @@ -0,0 +1,24 @@ +{% comment %} +context: + profile (Person) + profile_url (str) + no_photo_url (str) +{% endcomment %} + +
+ {% if profile and profile.photo_small %} + Photo of {{ profile.full_name }} + {% else %} + No photo + {% endif %} +
    + {% if profile %} +
  • Hi {{ profile.first_name }}
  • +
  • View your profile{% if profile.profile_completion < 100 %} ({{ profile.profile_completion|floatformat:0 }}% complete){% endif %}
  • + {% else %} +
  • No profile found
  • + {% endif %} +
+
+ +
\ No newline at end of file diff --git a/src/peoplefinder/urls.py b/src/peoplefinder/urls.py index 4ef8b12b8..8741c36d1 100644 --- a/src/peoplefinder/urls.py +++ b/src/peoplefinder/urls.py @@ -23,6 +23,7 @@ ProfileLegacyView, ProfileUpdateUserView, get_profile_by_staff_sso_id, + get_profile_card, ) from peoplefinder.views.role import RoleFormView, TeamSelectView from peoplefinder.views.team import ( @@ -119,6 +120,11 @@ ProfileUpdateUserView.as_view(), name="profile-update-user", ), + path( + "/card", + get_profile_card, + name="profile-get-card", + ), path( "get-by-staff-sso-id//", get_profile_by_staff_sso_id, diff --git a/src/peoplefinder/views/profile.py b/src/peoplefinder/views/profile.py index 10486ec8c..c33de56de 100644 --- a/src/peoplefinder/views/profile.py +++ b/src/peoplefinder/views/profile.py @@ -2,6 +2,10 @@ from pathlib import Path from django.contrib import messages +from django.template.response import TemplateResponse +from django.utils.decorators import decorator_from_middleware +from django_hawk.middleware import HawkResponseMiddleware +from django_hawk.utils import DjangoHawkAuthenticationFailed, authenticate_request from django.contrib.auth import get_user_model from django.contrib.auth.mixins import PermissionRequiredMixin, UserPassesTestMixin from django.contrib.messages.views import SuccessMessageMixin @@ -14,6 +18,7 @@ from django.views.generic import TemplateView from django.views.generic.detail import DetailView, SingleObjectMixin from django.views.generic.edit import FormView, UpdateView +from webpack_loader.utils import get_static from peoplefinder.forms.profile import ( ProfileForm, @@ -359,3 +364,30 @@ def get_profile_by_staff_sso_id(request, staff_sso_id): person = get_object_or_404(Person, user__legacy_sso_user_id=staff_sso_id) return redirect(person) + + +@decorator_from_middleware(HawkResponseMiddleware) +def get_profile_card(request, staff_sso_email_user_id): + try: + authenticate_request(request=request) + except DjangoHawkAuthenticationFailed: + return HttpResponse(status=401) + + try: + person = ( + Person.objects.with_profile_completion() + .filter(user__username=staff_sso_email_user_id) + .get() + ) + except (Person.DoesNotExist, Person.MultipleObjectsReturned): + person = None + + return TemplateResponse( + request, + "peoplefinder/components/profile-card.html", + { + "profile": person, + "profile_url": request.build_absolute_uri(person.get_absolute_url()), + "no_photo_url": request.build_absolute_uri(get_static("no-photo.png")), + }, + ) From 9dd0d350be5c4e83aabab7de1ef5f394e795f677 Mon Sep 17 00:00:00 2001 From: marcelkornblum Date: Tue, 11 Jul 2023 09:12:59 +0100 Subject: [PATCH 06/31] rollback select --- src/peoplefinder/forms/profile.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/peoplefinder/forms/profile.py b/src/peoplefinder/forms/profile.py index 1b1b325a6..dde3a67f3 100644 --- a/src/peoplefinder/forms/profile.py +++ b/src/peoplefinder/forms/profile.py @@ -44,7 +44,7 @@ class Meta: "photo", ] widgets = { - "email": forms.widgets.Select, + # "email": forms.widgets.Select, "workdays": forms.CheckboxSelectMultiple, "key_skills": forms.CheckboxSelectMultiple, "learning_interests": forms.CheckboxSelectMultiple, @@ -97,7 +97,7 @@ def __init__(self, *args, **kwargs) -> None: self.fields["email"].widget.attrs.update( { "class": "govuk-input govuk-!-width-one-half", - "choices": self.get_email_choices(), + # "choices": self.get_email_choices(), } ) self.fields["contact_email"].widget.attrs.update( From 7c1f39e583f49eb9c44008a0dd8c759c40efba51 Mon Sep 17 00:00:00 2001 From: Sam Dudley Date: Mon, 10 Jul 2023 15:27:52 +0100 Subject: [PATCH 07/31] Add profile card API and web component Co-authored-by: Marcel Kornblum --- .../templates/peoplefinder/components/profile-card.html | 2 +- src/peoplefinder/views/profile.py | 6 +----- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/src/peoplefinder/templates/peoplefinder/components/profile-card.html b/src/peoplefinder/templates/peoplefinder/components/profile-card.html index ceb083b71..1bedb8d96 100644 --- a/src/peoplefinder/templates/peoplefinder/components/profile-card.html +++ b/src/peoplefinder/templates/peoplefinder/components/profile-card.html @@ -14,7 +14,7 @@
    {% if profile %}
  • Hi {{ profile.first_name }}
  • -
  • View your profile{% if profile.profile_completion < 100 %} ({{ profile.profile_completion|floatformat:0 }}% complete){% endif %}
  • +
  • View your profile{% if profile.profile_completion < 100 %} ({{ profile.profile_completion }}% complete){% endif %}
  • {% else %}
  • No profile found
  • {% endif %} diff --git a/src/peoplefinder/views/profile.py b/src/peoplefinder/views/profile.py index c33de56de..c667e2483 100644 --- a/src/peoplefinder/views/profile.py +++ b/src/peoplefinder/views/profile.py @@ -374,11 +374,7 @@ def get_profile_card(request, staff_sso_email_user_id): return HttpResponse(status=401) try: - person = ( - Person.objects.with_profile_completion() - .filter(user__username=staff_sso_email_user_id) - .get() - ) + person = Person.objects.filter(user__username=staff_sso_email_user_id).get() except (Person.DoesNotExist, Person.MultipleObjectsReturned): person = None From 859c5d504f914b9dfb4d302819963bef2b5a7680 Mon Sep 17 00:00:00 2001 From: Sam Dudley Date: Tue, 11 Jul 2023 10:03:50 +0100 Subject: [PATCH 08/31] merge migrations --- .../migrations/0104_merge_20230711_0903.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 src/peoplefinder/migrations/0104_merge_20230711_0903.py diff --git a/src/peoplefinder/migrations/0104_merge_20230711_0903.py b/src/peoplefinder/migrations/0104_merge_20230711_0903.py new file mode 100644 index 000000000..61e2f2b09 --- /dev/null +++ b/src/peoplefinder/migrations/0104_merge_20230711_0903.py @@ -0,0 +1,12 @@ +# Generated by Django 4.1.7 on 2023-07-11 09:03 + +from django.db import migrations + + +class Migration(migrations.Migration): + dependencies = [ + ("peoplefinder", "0103_alter_person_email"), + ("peoplefinder", "0103_person_profile_completion"), + ] + + operations = [] From 0d1b98b568b644a9fd7e620e889c9683d77dd04c Mon Sep 17 00:00:00 2001 From: Sam Dudley Date: Tue, 11 Jul 2023 10:11:13 +0100 Subject: [PATCH 09/31] fix djlint config --- pyproject.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/pyproject.toml b/pyproject.toml index 0250194dc..cc61d6de6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -123,3 +123,4 @@ extension="html" profile="django" ignore="T002,H006,H017,H023" preserve_blank_lines=true +extend_exclude="htmlcov,staticfiles,static,node_modules" From bbbe8a77a793947a05b4bff1086ddcd4ed53f05b Mon Sep 17 00:00:00 2001 From: Cameron Lamb Date: Tue, 11 Jul 2023 10:15:48 +0100 Subject: [PATCH 10/31] Make migrations linear --- ...er_person_email.py => 0104_alter_person_email.py} | 2 +- .../migrations/0104_merge_20230711_0903.py | 12 ------------ 2 files changed, 1 insertion(+), 13 deletions(-) rename src/peoplefinder/migrations/{0103_alter_person_email.py => 0104_alter_person_email.py} (87%) delete mode 100644 src/peoplefinder/migrations/0104_merge_20230711_0903.py diff --git a/src/peoplefinder/migrations/0103_alter_person_email.py b/src/peoplefinder/migrations/0104_alter_person_email.py similarity index 87% rename from src/peoplefinder/migrations/0103_alter_person_email.py rename to src/peoplefinder/migrations/0104_alter_person_email.py index 6e1d8974f..31935016e 100644 --- a/src/peoplefinder/migrations/0103_alter_person_email.py +++ b/src/peoplefinder/migrations/0104_alter_person_email.py @@ -5,7 +5,7 @@ class Migration(migrations.Migration): dependencies = [ - ("peoplefinder", "0102_remove_person_manager_cannot_be_self_and_more"), + ("peoplefinder", "0103_person_profile_completion"), ] operations = [ diff --git a/src/peoplefinder/migrations/0104_merge_20230711_0903.py b/src/peoplefinder/migrations/0104_merge_20230711_0903.py deleted file mode 100644 index 61e2f2b09..000000000 --- a/src/peoplefinder/migrations/0104_merge_20230711_0903.py +++ /dev/null @@ -1,12 +0,0 @@ -# Generated by Django 4.1.7 on 2023-07-11 09:03 - -from django.db import migrations - - -class Migration(migrations.Migration): - dependencies = [ - ("peoplefinder", "0103_alter_person_email"), - ("peoplefinder", "0103_person_profile_completion"), - ] - - operations = [] From f9bc4c72a45385f02218fa45b8ef4d940cac138e Mon Sep 17 00:00:00 2001 From: Sam Dudley Date: Tue, 11 Jul 2023 10:26:59 +0100 Subject: [PATCH 11/31] fix meta name --- src/peoplefinder/static/peoplefinder/profile-card.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/peoplefinder/static/peoplefinder/profile-card.js b/src/peoplefinder/static/peoplefinder/profile-card.js index d8492b681..99c6da690 100644 --- a/src/peoplefinder/static/peoplefinder/profile-card.js +++ b/src/peoplefinder/static/peoplefinder/profile-card.js @@ -16,7 +16,7 @@ * @returns {String} */ function getStaffSsoUrl() { - const metaName = "peoplefinder:staff-sso-url"; + const metaName = "profile-card-url"; const meta = document.querySelector(`meta[name="${metaName}"]`); return meta.content; From 86c6ca52fa362aab27141ddd816d63473def9900 Mon Sep 17 00:00:00 2001 From: Sam Dudley Date: Tue, 11 Jul 2023 10:36:40 +0100 Subject: [PATCH 12/31] more fixes for the web component --- src/peoplefinder/static/peoplefinder/profile-card.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/peoplefinder/static/peoplefinder/profile-card.js b/src/peoplefinder/static/peoplefinder/profile-card.js index 99c6da690..9f0889dd7 100644 --- a/src/peoplefinder/static/peoplefinder/profile-card.js +++ b/src/peoplefinder/static/peoplefinder/profile-card.js @@ -15,7 +15,7 @@ * * @returns {String} */ - function getStaffSsoUrl() { + function getProfileCardUrl() { const metaName = "profile-card-url"; const meta = document.querySelector(`meta[name="${metaName}"]`); @@ -27,7 +27,7 @@ * @returns {Node} */ async function getProfileCard() { - const url = getStaffSsoUrl() + "/profile/"; + const url = getProfileCardUrl(); const response = await fetch(url, { credentials: "include", From 9f0ba40aefc0a1865bc9ce54de3b6c53406df11b Mon Sep 17 00:00:00 2001 From: marcelkornblum Date: Tue, 11 Jul 2023 12:04:18 +0100 Subject: [PATCH 13/31] missing / --- src/peoplefinder/services/person.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/peoplefinder/services/person.py b/src/peoplefinder/services/person.py index cca589674..0a9816869 100644 --- a/src/peoplefinder/services/person.py +++ b/src/peoplefinder/services/person.py @@ -358,7 +358,7 @@ def profile_completion_field_statuses(self, person: "Person") -> Dict[str, bool] @staticmethod def get_verified_emails(person: Person) -> list[str]: user_email = person.user.email # @TODO prefer UUID if we can get it from SSO - url = f"{settings.AUTHBROKER_URL}api/v1/user/emails/" + url = f"{settings.AUTHBROKER_URL}/api/v1/user/emails/" params = {"email": user_email} headers = {"Authorization": f"bearer {settings.AUTHBROKER_INTROSPECTION_TOKEN}"} From 011f175e182db044cdaad73b68a245ce56830a47 Mon Sep 17 00:00:00 2001 From: marcelkornblum Date: Tue, 11 Jul 2023 12:19:05 +0100 Subject: [PATCH 14/31] try changing email to select --- src/peoplefinder/forms/profile.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/peoplefinder/forms/profile.py b/src/peoplefinder/forms/profile.py index dde3a67f3..1b1b325a6 100644 --- a/src/peoplefinder/forms/profile.py +++ b/src/peoplefinder/forms/profile.py @@ -44,7 +44,7 @@ class Meta: "photo", ] widgets = { - # "email": forms.widgets.Select, + "email": forms.widgets.Select, "workdays": forms.CheckboxSelectMultiple, "key_skills": forms.CheckboxSelectMultiple, "learning_interests": forms.CheckboxSelectMultiple, @@ -97,7 +97,7 @@ def __init__(self, *args, **kwargs) -> None: self.fields["email"].widget.attrs.update( { "class": "govuk-input govuk-!-width-one-half", - # "choices": self.get_email_choices(), + "choices": self.get_email_choices(), } ) self.fields["contact_email"].widget.attrs.update( From d86b865e8b0f5e15fb4e48bc125058ea471bdcf5 Mon Sep 17 00:00:00 2001 From: marcelkornblum Date: Tue, 11 Jul 2023 12:31:28 +0100 Subject: [PATCH 15/31] try again with choices --- src/peoplefinder/forms/profile.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/peoplefinder/forms/profile.py b/src/peoplefinder/forms/profile.py index 1b1b325a6..2b4374e82 100644 --- a/src/peoplefinder/forms/profile.py +++ b/src/peoplefinder/forms/profile.py @@ -97,9 +97,9 @@ def __init__(self, *args, **kwargs) -> None: self.fields["email"].widget.attrs.update( { "class": "govuk-input govuk-!-width-one-half", - "choices": self.get_email_choices(), } ) + self.fields["email"].choices = (self.get_email_choices(),) self.fields["contact_email"].widget.attrs.update( {"class": "govuk-input govuk-!-width-one-half"} ) @@ -217,7 +217,7 @@ def clean_email(self): raise Exception("Could not retrieve valid emails for this user") if email not in verified_emails: raise ValidationError( - "That email address has not been verified through SSO authentication" + "Email address must be officially assigned and verified by SSO authentication" ) return email @@ -233,7 +233,9 @@ def get_email_choices(self): verified_emails = PersonService.get_verified_emails(self.instance) choices = [] if self.instance.email in verified_emails: - choices += (self.instance.email, self.instance.email) + choices += [ + (self.instance.email, self.instance.email), + ] choices += [ (email, email) for email in verified_emails if (email, email) not in choices ] From 730cd45eb6a2ca3d0d4e5ea0ce618a85aedd0dce Mon Sep 17 00:00:00 2001 From: marcelkornblum Date: Tue, 11 Jul 2023 12:46:06 +0100 Subject: [PATCH 16/31] too many brackets :( --- src/peoplefinder/forms/profile.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/peoplefinder/forms/profile.py b/src/peoplefinder/forms/profile.py index 2b4374e82..39205acef 100644 --- a/src/peoplefinder/forms/profile.py +++ b/src/peoplefinder/forms/profile.py @@ -95,9 +95,7 @@ def __init__(self, *args, **kwargs) -> None: {"class": "govuk-input govuk-!-width-one-half"} ) self.fields["email"].widget.attrs.update( - { - "class": "govuk-input govuk-!-width-one-half", - } + {"class": "govuk-input govuk-!-width-one-half"} ) self.fields["email"].choices = (self.get_email_choices(),) self.fields["contact_email"].widget.attrs.update( From da5027c8843f9f59a29e30dd6222da166ed21854 Mon Sep 17 00:00:00 2001 From: marcelkornblum Date: Tue, 11 Jul 2023 13:02:36 +0100 Subject: [PATCH 17/31] stupid brackets --- src/peoplefinder/forms/profile.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/peoplefinder/forms/profile.py b/src/peoplefinder/forms/profile.py index 39205acef..d6c486d76 100644 --- a/src/peoplefinder/forms/profile.py +++ b/src/peoplefinder/forms/profile.py @@ -97,7 +97,7 @@ def __init__(self, *args, **kwargs) -> None: self.fields["email"].widget.attrs.update( {"class": "govuk-input govuk-!-width-one-half"} ) - self.fields["email"].choices = (self.get_email_choices(),) + self.fields["email"].choices = self.get_email_choices() self.fields["contact_email"].widget.attrs.update( {"class": "govuk-input govuk-!-width-one-half"} ) From 0532c5386f090772bc95f97074e78fae82c78452 Mon Sep 17 00:00:00 2001 From: marcelkornblum Date: Tue, 11 Jul 2023 13:14:06 +0100 Subject: [PATCH 18/31] dont use tuples --- src/peoplefinder/forms/profile.py | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/peoplefinder/forms/profile.py b/src/peoplefinder/forms/profile.py index d6c486d76..97d78d5a8 100644 --- a/src/peoplefinder/forms/profile.py +++ b/src/peoplefinder/forms/profile.py @@ -44,7 +44,7 @@ class Meta: "photo", ] widgets = { - "email": forms.widgets.Select, + "email": forms.Select, "workdays": forms.CheckboxSelectMultiple, "key_skills": forms.CheckboxSelectMultiple, "learning_interests": forms.CheckboxSelectMultiple, @@ -232,14 +232,12 @@ def get_email_choices(self): choices = [] if self.instance.email in verified_emails: choices += [ - (self.instance.email, self.instance.email), + self.instance.email, ] - choices += [ - (email, email) for email in verified_emails if (email, email) not in choices - ] - if choices == []: + choices += [email for email in verified_emails if email not in choices] + if not choices: choices = [ - (self.instance.email, self.instance.email), + self.instance.email, ] return choices From 554ad07d4ebb87d66d5d585b07fee734a65403af Mon Sep 17 00:00:00 2001 From: marcelkornblum Date: Tue, 11 Jul 2023 13:21:44 +0100 Subject: [PATCH 19/31] comment out select --- src/peoplefinder/forms/profile.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/peoplefinder/forms/profile.py b/src/peoplefinder/forms/profile.py index 97d78d5a8..23e6a16c4 100644 --- a/src/peoplefinder/forms/profile.py +++ b/src/peoplefinder/forms/profile.py @@ -44,7 +44,7 @@ class Meta: "photo", ] widgets = { - "email": forms.Select, + # "email": forms.Select, "workdays": forms.CheckboxSelectMultiple, "key_skills": forms.CheckboxSelectMultiple, "learning_interests": forms.CheckboxSelectMultiple, @@ -97,7 +97,7 @@ def __init__(self, *args, **kwargs) -> None: self.fields["email"].widget.attrs.update( {"class": "govuk-input govuk-!-width-one-half"} ) - self.fields["email"].choices = self.get_email_choices() + # self.fields["email"].choices = self.get_email_choices() self.fields["contact_email"].widget.attrs.update( {"class": "govuk-input govuk-!-width-one-half"} ) From 0fc32e540a2947479b247f452e22379cd48ef739 Mon Sep 17 00:00:00 2001 From: marcelkornblum Date: Tue, 11 Jul 2023 14:19:23 +0100 Subject: [PATCH 20/31] attempt --- src/peoplefinder/forms/profile.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/peoplefinder/forms/profile.py b/src/peoplefinder/forms/profile.py index 23e6a16c4..139980d49 100644 --- a/src/peoplefinder/forms/profile.py +++ b/src/peoplefinder/forms/profile.py @@ -7,6 +7,7 @@ User = get_user_model() +email_choice_field = forms.ChoiceField(widget=forms.Select) class ProfileForm(forms.ModelForm): @@ -44,7 +45,7 @@ class Meta: "photo", ] widgets = { - # "email": forms.Select, + "email": email_choice_field, "workdays": forms.CheckboxSelectMultiple, "key_skills": forms.CheckboxSelectMultiple, "learning_interests": forms.CheckboxSelectMultiple, @@ -95,9 +96,9 @@ def __init__(self, *args, **kwargs) -> None: {"class": "govuk-input govuk-!-width-one-half"} ) self.fields["email"].widget.attrs.update( - {"class": "govuk-input govuk-!-width-one-half"} + {"class": "govuk-select govuk-!-width-one-half"} ) - # self.fields["email"].choices = self.get_email_choices() + self.fields["email"].choices = self.get_email_choices() self.fields["contact_email"].widget.attrs.update( {"class": "govuk-input govuk-!-width-one-half"} ) From f11a400e485f77cd76cce2241a04bd13e6919dbc Mon Sep 17 00:00:00 2001 From: marcelkornblum Date: Tue, 11 Jul 2023 14:37:26 +0100 Subject: [PATCH 21/31] revert --- src/peoplefinder/forms/profile.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/peoplefinder/forms/profile.py b/src/peoplefinder/forms/profile.py index 139980d49..23e6a16c4 100644 --- a/src/peoplefinder/forms/profile.py +++ b/src/peoplefinder/forms/profile.py @@ -7,7 +7,6 @@ User = get_user_model() -email_choice_field = forms.ChoiceField(widget=forms.Select) class ProfileForm(forms.ModelForm): @@ -45,7 +44,7 @@ class Meta: "photo", ] widgets = { - "email": email_choice_field, + # "email": forms.Select, "workdays": forms.CheckboxSelectMultiple, "key_skills": forms.CheckboxSelectMultiple, "learning_interests": forms.CheckboxSelectMultiple, @@ -96,9 +95,9 @@ def __init__(self, *args, **kwargs) -> None: {"class": "govuk-input govuk-!-width-one-half"} ) self.fields["email"].widget.attrs.update( - {"class": "govuk-select govuk-!-width-one-half"} + {"class": "govuk-input govuk-!-width-one-half"} ) - self.fields["email"].choices = self.get_email_choices() + # self.fields["email"].choices = self.get_email_choices() self.fields["contact_email"].widget.attrs.update( {"class": "govuk-input govuk-!-width-one-half"} ) From aa3168e92575e8b2a402e1fdc4b97df56f3298fb Mon Sep 17 00:00:00 2001 From: Cameron Lamb Date: Mon, 11 Sep 2023 16:56:48 +0100 Subject: [PATCH 22/31] Run `make fix` --- src/peoplefinder/forms/profile.py | 2 +- .../peoplefinder/components/profile-card.html | 15 +++++++++++---- src/peoplefinder/views/profile.py | 17 +++++------------ 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/peoplefinder/forms/profile.py b/src/peoplefinder/forms/profile.py index d919b9f76..7392a8420 100644 --- a/src/peoplefinder/forms/profile.py +++ b/src/peoplefinder/forms/profile.py @@ -2,7 +2,7 @@ from django import forms from django.contrib.auth import get_user_model -from django.core.validators import ValidationError, validate_email +from django.core.validators import ValidationError User = get_user_model() diff --git a/src/peoplefinder/templates/peoplefinder/components/profile-card.html b/src/peoplefinder/templates/peoplefinder/components/profile-card.html index 1bedb8d96..d2820a181 100644 --- a/src/peoplefinder/templates/peoplefinder/components/profile-card.html +++ b/src/peoplefinder/templates/peoplefinder/components/profile-card.html @@ -7,18 +7,25 @@
    {% if profile and profile.photo_small %} - Photo of {{ profile.full_name }} + Photo of {{ profile.full_name }} {% else %} No photo {% endif %}
      {% if profile %}
    • Hi {{ profile.first_name }}
    • -
    • View your profile{% if profile.profile_completion < 100 %} ({{ profile.profile_completion }}% complete){% endif %}
    • +
    • + View your profile + {% if profile.profile_completion < 100 %} + ({{ profile.profile_completion }}% complete) + {% endif %} +
    • {% else %}
    • No profile found
    • {% endif %}
    -
    -
    \ No newline at end of file + + diff --git a/src/peoplefinder/views/profile.py b/src/peoplefinder/views/profile.py index e6b3478fd..df82d99f7 100644 --- a/src/peoplefinder/views/profile.py +++ b/src/peoplefinder/views/profile.py @@ -3,10 +3,6 @@ from typing import Any, Dict from django.contrib import messages -from django.template.response import TemplateResponse -from django.utils.decorators import decorator_from_middleware -from django_hawk.middleware import HawkResponseMiddleware -from django_hawk.utils import DjangoHawkAuthenticationFailed, authenticate_request from django.contrib.auth import get_user_model from django.contrib.auth.mixins import PermissionRequiredMixin, UserPassesTestMixin from django.contrib.messages.views import SuccessMessageMixin @@ -19,19 +15,16 @@ HttpResponseRedirect, ) from django.shortcuts import get_object_or_404, redirect, render, reverse +from django.template.response import TemplateResponse from django.urls import reverse_lazy from django.utils import timezone -from django.utils.decorators import method_decorator +from django.utils.decorators import decorator_from_middleware, method_decorator from django.views.generic import TemplateView from django.views.generic.detail import DetailView, SingleObjectMixin -from django.views.generic.edit import FormView, UpdateView -from webpack_loader.utils import get_static - -from peoplefinder.forms.profile import ( - ProfileForm, - ProfileLeavingDitForm, - ProfileUpdateUserForm, from django.views.generic.edit import UpdateView +from django_hawk.middleware import HawkResponseMiddleware +from django_hawk.utils import DjangoHawkAuthenticationFailed, authenticate_request +from webpack_loader.utils import get_static from peoplefinder.forms.crispy_helper import RoleFormsetFormHelper from peoplefinder.forms.profile import ProfileUpdateUserForm From 2fb7df0c3226bc553fb62b91679061bdfafd0865 Mon Sep 17 00:00:00 2001 From: Cameron Lamb Date: Mon, 11 Sep 2023 17:11:25 +0100 Subject: [PATCH 23/31] Add email choices to the new forms --- src/peoplefinder/forms/profile_edit.py | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/peoplefinder/forms/profile_edit.py b/src/peoplefinder/forms/profile_edit.py index e20e4b916..d97d9fd5b 100644 --- a/src/peoplefinder/forms/profile_edit.py +++ b/src/peoplefinder/forms/profile_edit.py @@ -1,3 +1,5 @@ +from typing import List + from crispy_forms_gds.helper import FormHelper from crispy_forms_gds.layout import HTML, Field, Fieldset, Layout, Size from django import forms @@ -144,6 +146,9 @@ class Meta: "primary_phone_number", "secondary_phone_number", ] + widgets = { + "email": GovUkRadioSelect, + } def __init__(self, *args, **kwargs): self.request_user = kwargs.pop("request_user", None) @@ -151,7 +156,8 @@ def __init__(self, *args, **kwargs): email_label = self.fields["email"].label self.fields["email"].label = "" - self.fields["email"].choices = self.get_email_choices() + emails: List[str] = self.get_email_choices() + self.fields["email"].choices = [(email, email) for email in emails] contact_email_label = self.fields["contact_email"].label + " (optional)" self.fields["contact_email"].label = "" @@ -189,18 +195,14 @@ def __init__(self, *args, **kwargs): ), ) - def get_email_choices(self): + def get_email_choices(self) -> List[str]: verified_emails = PersonService.get_verified_emails(self.instance) choices = [] if self.instance.email in verified_emails: - choices += [ - self.instance.email, - ] + choices += [self.instance.email] choices += [email for email in verified_emails if email not in choices] if not choices: - choices = [ - self.instance.email, - ] + return [self.instance.email] return choices def clean_email(self): From 90c16fc77a1c2e4ad538469f92fa347bc41d54e3 Mon Sep 17 00:00:00 2001 From: Cameron Lamb Date: Mon, 11 Sep 2023 17:17:19 +0100 Subject: [PATCH 24/31] Update migrations --- ...104_alter_person_email.py => 0110_alter_person_email.py} | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) rename src/peoplefinder/migrations/{0104_alter_person_email.py => 0110_alter_person_email.py} (72%) diff --git a/src/peoplefinder/migrations/0104_alter_person_email.py b/src/peoplefinder/migrations/0110_alter_person_email.py similarity index 72% rename from src/peoplefinder/migrations/0104_alter_person_email.py rename to src/peoplefinder/migrations/0110_alter_person_email.py index 31935016e..1cbcdb63f 100644 --- a/src/peoplefinder/migrations/0104_alter_person_email.py +++ b/src/peoplefinder/migrations/0110_alter_person_email.py @@ -1,11 +1,11 @@ -# Generated by Django 4.1.9 on 2023-07-08 12:48 +# Generated by Django 4.1.10 on 2023-09-11 16:17 from django.db import migrations, models class Migration(migrations.Migration): dependencies = [ - ("peoplefinder", "0103_person_profile_completion"), + ("peoplefinder", "0109_person_preferred_first_name"), ] operations = [ @@ -13,7 +13,7 @@ class Migration(migrations.Migration): model_name="person", name="email", field=models.EmailField( - help_text="Choose your own official work email address provided by the organisation you are directly employed by or contracted to.", + help_text="Choose your own official work email address provided by the organisation you are directly employed by or contracted to. This is the email you use to log into Digital Workspace.", max_length=254, verbose_name="Main work email address", ), From ab46ad25345c67454da34f89f405144d95a9475b Mon Sep 17 00:00:00 2001 From: Cameron Lamb Date: Mon, 11 Sep 2023 17:23:05 +0100 Subject: [PATCH 25/31] Update the profile-card --- .../templates/peoplefinder/components/profile-card.html | 2 +- src/peoplefinder/templatetags/profile.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/peoplefinder/templates/peoplefinder/components/profile-card.html b/src/peoplefinder/templates/peoplefinder/components/profile-card.html index d2820a181..f1b6ea9ce 100644 --- a/src/peoplefinder/templates/peoplefinder/components/profile-card.html +++ b/src/peoplefinder/templates/peoplefinder/components/profile-card.html @@ -15,7 +15,7 @@ {% endif %}
      {% if profile %} -
    • Hi {{ profile.first_name }}
    • +
    • Hi {{ profile.preferred_first_name }}
    • View your profile {% if profile.profile_completion < 100 %} diff --git a/src/peoplefinder/templatetags/profile.py b/src/peoplefinder/templatetags/profile.py index 69e88a8af..9f2c1ee63 100644 --- a/src/peoplefinder/templatetags/profile.py +++ b/src/peoplefinder/templatetags/profile.py @@ -17,7 +17,7 @@ def byte_hash(val: str): "style": ( f"--color-1: {byte_hash(profile.first_name)};" f" --color-2: {byte_hash(profile.last_name)};" - f" --color-3: {byte_hash(profile.first_name + profile.last_name)}" + f" --color-3: {byte_hash(profile.preferred_first_name)}" ), } return mark_safe(" ".join([f'{k}="{v}"' for k, v in attrs.items()])) # noqa S308 From 41d92de51b8df8823671295b32dbc4456d456c42 Mon Sep 17 00:00:00 2001 From: Cameron Lamb Date: Tue, 12 Sep 2023 11:05:16 +0100 Subject: [PATCH 26/31] Fix the email select field --- src/peoplefinder/forms/profile_edit.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/peoplefinder/forms/profile_edit.py b/src/peoplefinder/forms/profile_edit.py index d97d9fd5b..b95673c1e 100644 --- a/src/peoplefinder/forms/profile_edit.py +++ b/src/peoplefinder/forms/profile_edit.py @@ -147,17 +147,22 @@ class Meta: "secondary_phone_number", ] widgets = { - "email": GovUkRadioSelect, + "email": forms.Select, } + email = forms.ChoiceField( + label=Person._meta.get_field("email").verbose_name, + help_text=Person._meta.get_field("email").help_text, + required=True, + ) + def __init__(self, *args, **kwargs): self.request_user = kwargs.pop("request_user", None) super().__init__(*args, **kwargs) email_label = self.fields["email"].label self.fields["email"].label = "" - emails: List[str] = self.get_email_choices() - self.fields["email"].choices = [(email, email) for email in emails] + self.fields["email"].choices = [(e, e) for e in self.get_email_choices()] contact_email_label = self.fields["contact_email"].label + " (optional)" self.fields["contact_email"].label = "" @@ -174,7 +179,7 @@ def __init__(self, *args, **kwargs): self.helper.form_tag = False self.helper.layout = Layout( Fieldset( - "email", + Field.select("email"), legend_size=Size.MEDIUM, legend=email_label, ), From 08583976d70aa4543b927b860a12dc22aca88b3e Mon Sep 17 00:00:00 2001 From: Cameron Lamb Date: Tue, 12 Sep 2023 12:38:56 +0100 Subject: [PATCH 27/31] Revert the form field to being read only --- src/peoplefinder/forms/profile_edit.py | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/src/peoplefinder/forms/profile_edit.py b/src/peoplefinder/forms/profile_edit.py index b95673c1e..b3b8dd502 100644 --- a/src/peoplefinder/forms/profile_edit.py +++ b/src/peoplefinder/forms/profile_edit.py @@ -146,15 +146,6 @@ class Meta: "primary_phone_number", "secondary_phone_number", ] - widgets = { - "email": forms.Select, - } - - email = forms.ChoiceField( - label=Person._meta.get_field("email").verbose_name, - help_text=Person._meta.get_field("email").help_text, - required=True, - ) def __init__(self, *args, **kwargs): self.request_user = kwargs.pop("request_user", None) @@ -162,7 +153,7 @@ def __init__(self, *args, **kwargs): email_label = self.fields["email"].label self.fields["email"].label = "" - self.fields["email"].choices = [(e, e) for e in self.get_email_choices()] + self.fields["email"].disabled = True contact_email_label = self.fields["contact_email"].label + " (optional)" self.fields["contact_email"].label = "" @@ -179,7 +170,7 @@ def __init__(self, *args, **kwargs): self.helper.form_tag = False self.helper.layout = Layout( Fieldset( - Field.select("email"), + "email", legend_size=Size.MEDIUM, legend=email_label, ), From d106a17f1dc1ea85f2da7cac1fd9df0876cfe2bb Mon Sep 17 00:00:00 2001 From: Cameron Lamb Date: Tue, 12 Sep 2023 12:40:39 +0100 Subject: [PATCH 28/31] Remove clean and get choices methods --- src/peoplefinder/forms/profile_edit.py | 25 ------------------------- 1 file changed, 25 deletions(-) diff --git a/src/peoplefinder/forms/profile_edit.py b/src/peoplefinder/forms/profile_edit.py index b3b8dd502..035a8bbf8 100644 --- a/src/peoplefinder/forms/profile_edit.py +++ b/src/peoplefinder/forms/profile_edit.py @@ -191,31 +191,6 @@ def __init__(self, *args, **kwargs): ), ) - def get_email_choices(self) -> List[str]: - verified_emails = PersonService.get_verified_emails(self.instance) - choices = [] - if self.instance.email in verified_emails: - choices += [self.instance.email] - choices += [email for email in verified_emails if email not in choices] - if not choices: - return [self.instance.email] - return choices - - def clean_email(self): - email = self.cleaned_data["email"] - - validate_email(email) - - verified_emails = PersonService.get_verified_emails(self.instance) - if verified_emails == []: - raise Exception("Could not retrieve valid emails for this user") - if email not in verified_emails: - raise ValidationError( - "Email address must be officially assigned and verified by SSO authentication" - ) - - return email - class TeamsProfileEditForm(forms.ModelForm): class Meta: From abf834c7fec26ce891b7d76a0e914380e344c8e8 Mon Sep 17 00:00:00 2001 From: Cameron Lamb Date: Tue, 12 Sep 2023 12:43:40 +0100 Subject: [PATCH 29/31] Revert the help text changes --- .../migrations/0110_alter_person_email.py | 21 ------------------- src/peoplefinder/models.py | 6 +++--- 2 files changed, 3 insertions(+), 24 deletions(-) delete mode 100644 src/peoplefinder/migrations/0110_alter_person_email.py diff --git a/src/peoplefinder/migrations/0110_alter_person_email.py b/src/peoplefinder/migrations/0110_alter_person_email.py deleted file mode 100644 index 1cbcdb63f..000000000 --- a/src/peoplefinder/migrations/0110_alter_person_email.py +++ /dev/null @@ -1,21 +0,0 @@ -# Generated by Django 4.1.10 on 2023-09-11 16:17 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - ("peoplefinder", "0109_person_preferred_first_name"), - ] - - operations = [ - migrations.AlterField( - model_name="person", - name="email", - field=models.EmailField( - help_text="Choose your own official work email address provided by the organisation you are directly employed by or contracted to. This is the email you use to log into Digital Workspace.", - max_length=254, - verbose_name="Main work email address", - ), - ), - ] diff --git a/src/peoplefinder/models.py b/src/peoplefinder/models.py index accafbade..f38681947 100644 --- a/src/peoplefinder/models.py +++ b/src/peoplefinder/models.py @@ -560,9 +560,9 @@ class RemoteWorking(models.TextChoices): email = models.EmailField( "Main work email address", help_text=( - "Choose your own official work email address provided by the" - " organisation you are directly employed by or contracted to." - " This is the email you use to log into Digital Workspace." + "The work email address provided by the organisation you are" + " directly employed by or contracted to. This is the email you use" + " to log into Digital Workspace.", ), ) pronouns = models.CharField(max_length=40, null=True, blank=True) From e3ebab5c73f1b80084f196144dbbf213b7f2edf3 Mon Sep 17 00:00:00 2001 From: Cameron Lamb Date: Tue, 12 Sep 2023 12:59:48 +0100 Subject: [PATCH 30/31] Remove unused imports --- src/peoplefinder/forms/profile_edit.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/peoplefinder/forms/profile_edit.py b/src/peoplefinder/forms/profile_edit.py index 035a8bbf8..e7554347d 100644 --- a/src/peoplefinder/forms/profile_edit.py +++ b/src/peoplefinder/forms/profile_edit.py @@ -1,16 +1,13 @@ -from typing import List - from crispy_forms_gds.helper import FormHelper from crispy_forms_gds.layout import HTML, Field, Fieldset, Layout, Size from django import forms -from django.core.validators import ValidationError, validate_email +from django.core.validators import ValidationError from django.template import Context, Template from peoplefinder.forms.crispy_layout import GovUKDetails from peoplefinder.forms.profile import GovUkRadioSelect, GroupedModelChoiceField from peoplefinder.forms.role import RoleForm from peoplefinder.models import Person, TeamMember, UkStaffLocation -from peoplefinder.services.person import PersonService class PersonalProfileEditForm(forms.ModelForm): From a6c3957d1b166aee8c5ff72654ffb03da59e397a Mon Sep 17 00:00:00 2001 From: Cameron Lamb Date: Tue, 12 Sep 2023 13:04:28 +0100 Subject: [PATCH 31/31] Remove typo --- src/peoplefinder/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/peoplefinder/models.py b/src/peoplefinder/models.py index f38681947..cfec8e22d 100644 --- a/src/peoplefinder/models.py +++ b/src/peoplefinder/models.py @@ -562,7 +562,7 @@ class RemoteWorking(models.TextChoices): help_text=( "The work email address provided by the organisation you are" " directly employed by or contracted to. This is the email you use" - " to log into Digital Workspace.", + " to log into Digital Workspace." ), ) pronouns = models.CharField(max_length=40, null=True, blank=True)