From 654db6b2874da435f5222d4511f44ed357835672 Mon Sep 17 00:00:00 2001
From: ddahan
Date: Wed, 27 Mar 2024 09:14:27 +0000
Subject: [PATCH 1/4] Re-Send verification mail with normal send mail
---
api/urls.py | 5 +++
api/views/__init__.py | 8 +++-
api/views/user.py | 30 +++++++++----
.../SendNewSignupVerificationEmail.vue | 42 +++++++++++++++++++
frontend/src/views/SignupPage.vue | 8 ++--
5 files changed, 78 insertions(+), 15 deletions(-)
create mode 100644 frontend/src/components/SendNewSignupVerificationEmail.vue
diff --git a/api/urls.py b/api/urls.py
index 1ba85081..481b7d1c 100644
--- a/api/urls.py
+++ b/api/urls.py
@@ -26,6 +26,11 @@
path("signup/", views.SignupView.as_view(), name="signup"),
path("generate-username/", views.GenerateUsernameView.as_view(), name="generate_username"),
path("verify-email/", views.VerifyEmailView.as_view(), name="verify_email"),
+ path(
+ "send-new-signup-verification-email/",
+ views.SendNewSignupVerificationEmailView.as_view(),
+ name="send_new_signup_verification_email",
+ ),
}
urlpatterns = format_suffix_patterns(urlpatterns)
diff --git a/api/views/__init__.py b/api/views/__init__.py
index a2bbeffe..bf47d0f1 100644
--- a/api/views/__init__.py
+++ b/api/views/__init__.py
@@ -1,7 +1,13 @@
from .blog import BlogPostsView, BlogPostView # noqa: F401
from .newsletter import SubscribeNewsletter # noqa: F401
from .report_issue import ReportIssue # noqa: F401
-from .user import LoggedUserView, SignupView, GenerateUsernameView, VerifyEmailView # noqa: F401
+from .user import ( # noqa: F401
+ LoggedUserView,
+ SignupView,
+ GenerateUsernameView,
+ VerifyEmailView,
+ SendNewSignupVerificationEmailView,
+)
from .webinar import WebinarView # noqa
from .search import SearchView # noqa: F401
from .plant import PlantRetrieveView, PlantPartListView # noqa: F401
diff --git a/api/views/user.py b/api/views/user.py
index 98f61cfb..3af52545 100644
--- a/api/views/user.py
+++ b/api/views/user.py
@@ -3,6 +3,7 @@
from django.contrib.auth import login
from django.middleware.csrf import get_token
from django.core.mail import send_mail
+from django.shortcuts import get_object_or_404
from rest_framework.views import APIView
from rest_framework.generics import RetrieveAPIView
from rest_framework.response import Response
@@ -31,20 +32,31 @@ def get_object(self):
return self.request.user
+def _send_verification_mail(request, user):
+ new_token = MagicLinkToken.objects.create(user=user, usage=MagicLinkUsage.VERIFY_EMAIL_ADDRESS)
+ verification_url = urljoin(get_base_url(request), new_token.as_url(key=new_token.key))
+ send_mail(
+ subject="Vérifiez votre adresse e-mail",
+ message=f"Cliquez sur le lien suivant pour vérifier votre adresse e-mail : {verification_url}",
+ from_email=settings.DEFAULT_FROM_EMAIL,
+ recipient_list=[user.email],
+ )
+
+
class SignupView(APIView):
def post(self, request, *args, **kwargs):
serializer = UserInputSerializer(data=request.data)
if serializer.is_valid(raise_exception=True):
new_user = serializer.save()
- new_token = MagicLinkToken.objects.create(user=new_user, usage=MagicLinkUsage.VERIFY_EMAIL_ADDRESS)
- verification_url = urljoin(get_base_url(request), new_token.as_url(key=new_token.key))
- send_mail(
- subject="Vérifiez votre adresse e-mail",
- message=f"Cliquez sur le lien suivant pour vérifier votre adresse e-mail : {verification_url}",
- from_email=settings.DEFAULT_FROM_EMAIL,
- recipient_list=[new_user.email],
- )
- return Response({}, status=status.HTTP_201_CREATED)
+ _send_verification_mail(request, new_user)
+ return Response({"user_id": new_user.id}, status=status.HTTP_201_CREATED)
+
+
+class SendNewSignupVerificationEmailView(APIView):
+ def get(self, request, user_id, *args, **kwargs):
+ user = get_object_or_404(User, id=user_id)
+ _send_verification_mail(request, user)
+ return Response(None, status=status.HTTP_204_NO_CONTENT)
class GenerateUsernameView(APIView):
diff --git a/frontend/src/components/SendNewSignupVerificationEmail.vue b/frontend/src/components/SendNewSignupVerificationEmail.vue
new file mode 100644
index 00000000..99816bd6
--- /dev/null
+++ b/frontend/src/components/SendNewSignupVerificationEmail.vue
@@ -0,0 +1,42 @@
+
+
+
+
+
+ Si vous n'avez pas reçu d'email au bout de quelques minutes, veuillez vérifier l'adresse e-mail entrée, ainsi
+ que vos courriers indésirables. Sinon, cliquez sur le bouton ci-dessous pour recevoir un nouvel e-mail :
+
+
+
+
+
+
+
diff --git a/frontend/src/views/SignupPage.vue b/frontend/src/views/SignupPage.vue
index 59e34620..b9d6584a 100644
--- a/frontend/src/views/SignupPage.vue
+++ b/frontend/src/views/SignupPage.vue
@@ -91,10 +91,7 @@
Veuillez cliquez dans le lien à l'intérieur pour vérifier votre adresse e-email et pouvoir utiliser votre
compte.
-
- Si vous n'avez pas reçu l'email au bout de quelques minutes, veuillez vérifier l'adresse e-mail entrée, ainsi
- que vos courriers indésirables.
-
+
@@ -103,6 +100,7 @@
import { computed, ref } from "vue"
import { useVuelidate } from "@vuelidate/core"
import SingleItemWrapper from "@/components/SingleItemWrapper"
+import SendNewSignupVerificationEmail from "@/components/SendNewSignupVerificationEmail"
import FormWrapper from "@/components/FormWrapper"
import { errorRequiredField, errorRequiredEmail, firstErrorMsg } from "@/utils/forms"
import { useFetch } from "@vueuse/core"
@@ -136,7 +134,7 @@ const $externalResults = ref({})
const v$ = useVuelidate(rules, state, { $externalResults })
// Main request definition
-const { response, execute, isFetching } = useFetch(
+const { data, response, execute, isFetching } = useFetch(
"/api/v1/signup/",
{
headers: headers(),
From bcdaa169b2a2aa549b2a257c27df9ad40f4122e9 Mon Sep 17 00:00:00 2001
From: ddahan
Date: Wed, 27 Mar 2024 15:16:46 +0000
Subject: [PATCH 2/4] Add modal, extra data to error handling, and a dirty hack
---
api/exception_handling.py | 5 +++
api/views/authentication.py | 3 +-
.../SendNewSignupVerificationEmail.vue | 37 +++++++++++++------
frontend/src/icons.js | 9 +++++
frontend/src/utils/error-handling.js | 4 +-
frontend/src/views/LoginPage.vue | 12 ++++++
6 files changed, 56 insertions(+), 14 deletions(-)
diff --git a/api/exception_handling.py b/api/exception_handling.py
index bead912f..7949449e 100644
--- a/api/exception_handling.py
+++ b/api/exception_handling.py
@@ -38,6 +38,7 @@ def __init__(
non_field_errors: list[str] | None = None,
field_errors: dict[str, list[str]] | None = None,
log_level: int | None = logging.INFO,
+ extra: dict = None,
**kwargs
):
super().__init__(**kwargs)
@@ -60,6 +61,10 @@ def __init__(
if not any([self.global_error, self.non_field_errors, self.field_errors]):
raise ValueError("An exception must contain at least one error type.")
+ # Inject addtional data of your choice into the response
+ if extra:
+ self.extra = extra
+
# Create an optional log using provided log level
if log_level:
logger.log(level=log_level, msg=self.__class__.__name__, extra=self.__dict__)
diff --git a/api/views/authentication.py b/api/views/authentication.py
index 6fb7dfa1..85d46d5d 100644
--- a/api/views/authentication.py
+++ b/api/views/authentication.py
@@ -15,7 +15,8 @@ def post(self, request, *args, **kwargs):
raise ProjectAPIException(
non_field_errors=[
"Votre compte n'est pas encore vérifié. Veuillez vérifier vos e-mails reçus, et vos courriers indésirables."
- ]
+ ],
+ extra={"user_id": user.id},
)
login(request, user) # will create the user session
return Response({"csrf_token": get_token(request)})
diff --git a/frontend/src/components/SendNewSignupVerificationEmail.vue b/frontend/src/components/SendNewSignupVerificationEmail.vue
index 99816bd6..5453ead7 100644
--- a/frontend/src/components/SendNewSignupVerificationEmail.vue
+++ b/frontend/src/components/SendNewSignupVerificationEmail.vue
@@ -1,18 +1,19 @@
-
-
+
+
Si vous n'avez pas reçu d'email au bout de quelques minutes, veuillez vérifier l'adresse e-mail entrée, ainsi
que vos courriers indésirables. Sinon, cliquez sur le bouton ci-dessous pour recevoir un nouvel e-mail :
-
-
+
@@ -23,12 +24,13 @@ import { handleError } from "@/utils/error-handling"
import useToaster from "@/composables/use-toaster"
const props = defineProps({ userId: Number })
+const opened = ref(false)
-const emailNotReceived = ref(false)
+const close = () => (opened.value = false)
// Main request definition
const url = computed(() => `/api/v1/send-new-signup-verification-email/${props.userId}`)
-const { response, execute, isFetching, isFinished } = useFetch(url, {
+const { response, execute } = useFetch(url, {
immediate: false,
}).json()
@@ -38,5 +40,18 @@ const resendEmail = async () => {
if (response.value.ok) {
useToaster().addSuccessMessage("L'email de vérification a été renvoyé.")
}
+ close()
}
+
+const actions = [
+ {
+ label: "Renvoyer un nouvel e-mail",
+ onClick: resendEmail,
+ },
+ {
+ label: "Annuler",
+ onClick: close,
+ secondary: true,
+ },
+]
diff --git a/frontend/src/icons.js b/frontend/src/icons.js
index a21670fd..90b61907 100644
--- a/frontend/src/icons.js
+++ b/frontend/src/icons.js
@@ -191,3 +191,12 @@ export const RiEyeOffLine = {
height: 24,
raw: '',
}
+
+export const RiMailForbidLine = {
+ name: "ri-mail-forbid-line",
+ minX: 0,
+ minY: 0,
+ width: 24,
+ height: 24,
+ raw: '',
+}
diff --git a/frontend/src/utils/error-handling.js b/frontend/src/utils/error-handling.js
index 97d10c29..379e030a 100644
--- a/frontend/src/utils/error-handling.js
+++ b/frontend/src/utils/error-handling.js
@@ -22,9 +22,9 @@ export const handleError = async (response) => {
// show an error toast
addErrorMessage(backErrorData.globalError)
}
- // Return other errors to be handled by Vuelidate directly
+ // Return other errors to be handled by Vuelidate directly (and "extra" parameters to get additional data)
// If you don't have a form and expect global errors only, just ignore the result of this function when called.
- return { nonFieldErrors: backErrorData.nonFieldErrors, ...backErrorData.fieldErrors }
+ return { nonFieldErrors: backErrorData.nonFieldErrors, ...backErrorData.fieldErrors, extra: backErrorData.extra }
// TODO LATER: auto logout (in case of 401) could be handled here
// TODO LATER: timeout could be handled here too
diff --git a/frontend/src/views/LoginPage.vue b/frontend/src/views/LoginPage.vue
index 0697201d..d85fd729 100644
--- a/frontend/src/views/LoginPage.vue
+++ b/frontend/src/views/LoginPage.vue
@@ -2,6 +2,7 @@
Se connecter
+
@@ -45,6 +46,7 @@ import { useRouter } from "vue-router"
import { useRootStore } from "@/stores/root"
import FormWrapper from "@/components/FormWrapper"
import SingleItemWrapper from "@/components/SingleItemWrapper"
+import SendNewSignupVerificationEmail from "@/components/SendNewSignupVerificationEmail"
const router = useRouter()
const rootStore = useRootStore()
@@ -76,6 +78,9 @@ const { data, response, execute, isFetching } = useFetch(
.post(state)
.json()
+const showSendNewConfirmationMail = ref(false)
+const userIdForNewConfirmationMail = ref()
+
// Form validation
const submit = async () => {
v$.value.$validate()
@@ -85,6 +90,13 @@ const submit = async () => {
await execute()
$externalResults.value = await handleError(response)
+ // Give the ability to ask for a new e-email, only if the user is not verified yet.
+ // ⛔️ TODO: change this dirty hack: we use error message until having appropriate error codes in responses
+ if ($externalResults.value.nonFieldErrors[0].includes("vérifié")) {
+ showSendNewConfirmationMail.value = true
+ userIdForNewConfirmationMail.value = $externalResults.value.extra.userId
+ }
+
if (response.value.ok) {
{
await rootStore.fetchInitialData()
From 91da5848cecbe8a4cb9b2bf2cc191377e94f40a2 Mon Sep 17 00:00:00 2001
From: ddahan
Date: Wed, 27 Mar 2024 18:36:41 +0000
Subject: [PATCH 3/4] typo
---
frontend/src/components/SendNewSignupVerificationEmail.vue | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/frontend/src/components/SendNewSignupVerificationEmail.vue b/frontend/src/components/SendNewSignupVerificationEmail.vue
index 5453ead7..e6d0e10e 100644
--- a/frontend/src/components/SendNewSignupVerificationEmail.vue
+++ b/frontend/src/components/SendNewSignupVerificationEmail.vue
@@ -11,7 +11,7 @@
>
Si vous n'avez pas reçu d'email au bout de quelques minutes, veuillez vérifier l'adresse e-mail entrée, ainsi
- que vos courriers indésirables. Sinon, cliquez sur le bouton ci-dessous pour recevoir un nouvel e-mail :
+ que vos courriers indésirables. Sinon, cliquez sur le bouton ci-dessous pour recevoir un nouvel e-mail.
From 8c5c702e8069697385940fff0fd93a1a1728af66 Mon Sep 17 00:00:00 2001
From: Alejandro MG
Date: Thu, 28 Mar 2024 11:17:23 +0100
Subject: [PATCH 4/4] Secondaty button for email resending
---
.../src/components/SendNewSignupVerificationEmail.vue | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/frontend/src/components/SendNewSignupVerificationEmail.vue b/frontend/src/components/SendNewSignupVerificationEmail.vue
index e6d0e10e..c551dc5b 100644
--- a/frontend/src/components/SendNewSignupVerificationEmail.vue
+++ b/frontend/src/components/SendNewSignupVerificationEmail.vue
@@ -1,6 +1,13 @@
-
+