diff --git a/frontend/public/locales/en/common.json b/frontend/public/locales/en/common.json index 40684e8e73052b57550fa757076ecbbb9c0bde8c..1e0c48cd70e63ce88fac87a23224870ab5705091 100644 --- a/frontend/public/locales/en/common.json +++ b/frontend/public/locales/en/common.json @@ -133,6 +133,7 @@ "roleEndRequired": "Role end date is required", "invalidEndDate": "Chosen role must have an earlier end date", "emailRequired": "E-mail is required", + "existingEmail": "This e-mail address is already in use", "consentRequired": "This consent is required", "invalidMobilePhoneNumber": "Invalid phone number", "invalidEmail": "Invalid e-mail address", diff --git a/frontend/public/locales/nb/common.json b/frontend/public/locales/nb/common.json index 38363b4a5cbdbed42072ad2c934097ee521e5f4b..782c45b018bbfdc4945fe9f1009eed13f1a6625d 100644 --- a/frontend/public/locales/nb/common.json +++ b/frontend/public/locales/nb/common.json @@ -133,6 +133,7 @@ "roleEndRequired": "Sluttdato for rolle er obligatorisk", "invalidEndDate": "Valgt rolle må ha en tidligere sluttdato", "emailRequired": "E-post er obligatorisk", + "existingEmail": "E-postadressen er allerede i bruk", "consentRequired": "Dette samtykket er obligatorisk", "invalidMobilePhoneNumber": "Ugyldig telefonnummer", "invalidEmail": "Ugyldig e-postadresse", diff --git a/frontend/public/locales/nn/common.json b/frontend/public/locales/nn/common.json index e1669b95a47a6271577507a777c978e79e0745ae..fa51387b89abd481ad81c76a5ed2ab83394e7795 100644 --- a/frontend/public/locales/nn/common.json +++ b/frontend/public/locales/nn/common.json @@ -133,6 +133,7 @@ "roleEndRequired": "Sluttdato for rolle er påkrevd", "invalidEndDate": "Vald rolle må ha ein tidlegare sluttdato", "emailRequired": "E-post er påkrevd", + "existingEmail": "E-postadressa er allereie i bruk", "consentRequired": "Dette samtykket er påkrevd", "invalidMobilePhoneNumber": "Ugyldig telefonnummer", "invalidEmail": "Ugyldig e-postadresse", diff --git a/frontend/src/routes/sponsor/register/stepPersonForm.tsx b/frontend/src/routes/sponsor/register/stepPersonForm.tsx index a07b9510bd8113cdc5c9510a14e3dc1e53ae2960..e9c8f5a15160262a9647743ed9b7edac23fcd90c 100644 --- a/frontend/src/routes/sponsor/register/stepPersonForm.tsx +++ b/frontend/src/routes/sponsor/register/stepPersonForm.tsx @@ -131,15 +131,6 @@ const StepPersonForm = forwardRef( useImperativeHandle(ref, () => ({ doSubmit })) - // const checkDuplicateEmail = (email: String) => { - // fetch(url til api).then((res) => { - // if (res.toString() === email) { - // return true - // } - // return false - // }) - // } - const validateStartDateBeforeEndDate = (startDate: Date | undefined) => { if (!startDate) { return t('validation.startDateMustBeSet') diff --git a/frontend/src/utils/index.test.ts b/frontend/src/utils/index.test.ts index 0c6a66c68bc18aecfa8544b4c0090b2e05405a70..5067541ad736df52b192d97638303fbbdb857e0c 100644 --- a/frontend/src/utils/index.test.ts +++ b/frontend/src/utils/index.test.ts @@ -30,16 +30,28 @@ test('Valid phone number', async () => { }) test('Valid e-mail', async () => { - expect(isValidEmail('test@example.org')).toEqual(true) - expect(isValidEmail('Test.Tester@example.org')).toEqual(true) + isValidEmail('test@example.org').then((data) => { + expect(data).toEqual(true) + }) + isValidEmail('test.testerson@example.org').then((data) => { + expect(data).toEqual(true) + }) }) test('Invalid e-mail', async () => { - expect(isValidEmail('testexample.org')).not.toEqual(true) - expect(isValidEmail('test')).not.toEqual(true) + isValidEmail('testexample.org').then((data) => { + expect(data).toEqual('common:validation.invalidEmail') + }) + isValidEmail('test').then((data) => { + expect(data).toEqual('common:validation.invalidEmail') + }) // Treat special characters as invalid, some services allow them though - expect(isValidEmail('Øyvind.Åsen@example.org')).not.toEqual(true) - expect(isValidEmail('Test.Tester@åsen.org')).not.toEqual(true) + isValidEmail('Øyvind.Åsen@example.org').then((data) => { + expect(data).toEqual('common:validation.invalidEmail') + }) + isValidEmail('Test.Tester@åsen.org').then((data) => { + expect(data).toEqual('common:validation.invalidEmail') + }) }) test('Body has values', async () => { diff --git a/frontend/src/utils/index.ts b/frontend/src/utils/index.ts index 681f6757998646ca1bc997b9de329c3298077053..1ca62996e81a0c64ad52511b8ac590cd10b25d86 100644 --- a/frontend/src/utils/index.ts +++ b/frontend/src/utils/index.ts @@ -102,12 +102,21 @@ export function isValidMobilePhoneNumber( return i18n.t<string>('common:validation.invalidMobilePhoneNumber') } -export function isValidEmail(data: string | undefined): boolean | string { +export async function isValidEmail(data: string | undefined) { if (!data) { return i18n.t<string>('common:validation.emailRequired') } if (validEmailRegex.test(data)) { - return true + const message = await fetch( + `/api/ui/v1/email/${data}`, + fetchJsonOpts() + ).then((res) => { + if (res.ok) { + return i18n.t<string>('common:validation.existingEmail') + } + return true + }) + return message } return i18n.t<string>('common:validation.invalidEmail') } diff --git a/gregui/api/serializers/email.py b/gregui/api/serializers/email.py deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/gregui/api/urls.py b/gregui/api/urls.py index cf2dd76c8371efe737c4a586b834a6623aed65b8..122e11e8cc8d3ea70bdd657a401c25b24df0ad00 100644 --- a/gregui/api/urls.py +++ b/gregui/api/urls.py @@ -1,6 +1,10 @@ from django.urls import re_path, path from rest_framework.routers import DefaultRouter -from gregui.api.views.identity import IdentityCheckView, IdentityViewSet +from gregui.api.views.identity import ( + IdentityCheckView, + IdentityViewSet, + EmailExistsView, +) from gregui.api.views.invitation import ( CheckInvitationView, @@ -43,4 +47,5 @@ urlpatterns += [ ), path("userinfo/", UserInfoView.as_view(), name="userinfo"), path("identitycheck/<int:id>", IdentityCheckView.as_view(), name="identitycheck"), + path("email/<str:value>", EmailExistsView.as_view(), name="email"), ] diff --git a/gregui/api/views/email.py b/gregui/api/views/email.py deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/gregui/api/views/identity.py b/gregui/api/views/identity.py index e9593e82249da8927468f42ddf43c7fa36c1fd67..d511db28ef99fb1d402537daaba59b68c75e34a6 100644 --- a/gregui/api/views/identity.py +++ b/gregui/api/views/identity.py @@ -2,10 +2,10 @@ from django.conf import settings from rest_framework.authentication import SessionAuthentication, BasicAuthentication from rest_framework.permissions import IsAuthenticated from rest_framework.viewsets import GenericViewSet -from rest_framework import mixins +from rest_framework import mixins, status from rest_framework.views import APIView from rest_framework.response import Response -from rest_framework import status +from rest_framework.generics import RetrieveAPIView from greg.models import Identity from greg.permissions import IsSponsor @@ -52,3 +52,15 @@ class IdentityCheckView(APIView): ) match = client.extid_search(ident.type, ident.value) return Response({"match": match.dict() if match else None}) + + +class EmailExistsView(RetrieveAPIView): + """ + View used for checking if an email is already in use + """ + + authentication_classes = [SessionAuthentication, BasicAuthentication] + permission_classes = [IsAuthenticated, IsSponsor] + serializer_class = IdentitySerializer + queryset = Identity.objects.filter(type="private_email") + lookup_field = "value" diff --git a/gregui/tests/api/views/test_identity.py b/gregui/tests/api/views/test_identity.py index f7a1ac313b62c1fc7b89cfcd03aec2d647307f95..3c59514d1f18ff110223fd11c9d36f058a7565e0 100644 --- a/gregui/tests/api/views/test_identity.py +++ b/gregui/tests/api/views/test_identity.py @@ -87,3 +87,16 @@ def test_identity_check_existing_fnr( url = reverse("gregui-v1:identitycheck", kwargs={"id": person_foo.fnr.id}) response = client.get(url) assert response.json() == {"match": {"first": "Ola", "last": "Nordmann"}} + + +@pytest.mark.django_db +def test_existing_email(client, log_in, user_sponsor, person_foo): + log_in(user_sponsor) + response = client.get( + reverse("gregui-v1:email", kwargs={"value": person_foo.private_email.value}) + ) + assert response.status_code == 200 + response = client.get( + reverse("gregui-v1:email", kwargs={"value": "nosuch@email.com"}) + ) + assert response.status_code == 404