From 54ef0248f5d9671e78f2b165bf4de787ab575a43 Mon Sep 17 00:00:00 2001 From: Amir Date: Thu, 13 Feb 2025 16:38:29 +0100 Subject: [PATCH] #6 Verifikacija emaila zavrsena. --- backend/accounts/admin.py | 9 ++++++- backend/accounts/migrations/0001_initial.py | 24 +++++++++++++++++++ backend/accounts/models.py | 11 ++++++++- .../accounts/confirmation_expired.html | 8 +++++++ .../accounts/confirmation_success.html | 5 ++++ backend/accounts/urls.py | 2 ++ backend/accounts/utils.py | 24 +++++++++++++++++++ backend/accounts/views.py | 18 ++++++++++++++ backend/core/templates/thankyou.html | 1 - backend/core/utils.py | 4 ---- backend/core/views.py | 4 ++++ backend/settings.py | 12 ++++++++++ 12 files changed, 115 insertions(+), 7 deletions(-) create mode 100644 backend/accounts/migrations/0001_initial.py create mode 100644 backend/accounts/templates/accounts/confirmation_expired.html create mode 100644 backend/accounts/templates/accounts/confirmation_success.html create mode 100644 backend/accounts/utils.py diff --git a/backend/accounts/admin.py b/backend/accounts/admin.py index 8c38f3f..3e0e828 100644 --- a/backend/accounts/admin.py +++ b/backend/accounts/admin.py @@ -1,3 +1,10 @@ from django.contrib import admin +from .models import EmailConfirmation -# Register your models here. + +class EmailConfirmationAdmin(admin.ModelAdmin): + list_display= ['email', 'uuid', 'created_at'] + + + +admin.site.register(EmailConfirmation, EmailConfirmationAdmin) diff --git a/backend/accounts/migrations/0001_initial.py b/backend/accounts/migrations/0001_initial.py new file mode 100644 index 0000000..fba9e05 --- /dev/null +++ b/backend/accounts/migrations/0001_initial.py @@ -0,0 +1,24 @@ +# Generated by Django 5.1.3 on 2025-02-13 12:37 + +import uuid +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='EmailConfirmation', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('email', models.EmailField(max_length=254, unique=True)), + ('uuid', models.UUIDField(default=uuid.uuid4, unique=True)), + ('created_at', models.DateTimeField(auto_now_add=True)), + ], + ), + ] diff --git a/backend/accounts/models.py b/backend/accounts/models.py index 71a8362..9669cd6 100644 --- a/backend/accounts/models.py +++ b/backend/accounts/models.py @@ -1,3 +1,12 @@ from django.db import models +import uuid +from django.utils.timezone import now +from datetime import timedelta -# Create your models here. +class EmailConfirmation(models.Model): + email = models.EmailField(unique=True) + uuid = models.UUIDField(default=uuid.uuid4, unique=True) + created_at = models.DateTimeField(auto_now_add=True) + + def is_expired(self): + return now() > (self.created_at + timedelta(days=1)) \ No newline at end of file diff --git a/backend/accounts/templates/accounts/confirmation_expired.html b/backend/accounts/templates/accounts/confirmation_expired.html new file mode 100644 index 0000000..7624b9a --- /dev/null +++ b/backend/accounts/templates/accounts/confirmation_expired.html @@ -0,0 +1,8 @@ +{% extends "base_login.html" %} + + +

Link has expired!

+
+ {% csrf_token %} + +
\ No newline at end of file diff --git a/backend/accounts/templates/accounts/confirmation_success.html b/backend/accounts/templates/accounts/confirmation_success.html new file mode 100644 index 0000000..32a64d0 --- /dev/null +++ b/backend/accounts/templates/accounts/confirmation_success.html @@ -0,0 +1,5 @@ +{% extends "base_login.html" %} + + +

Email Confirmed!

+

Your email {{ email }} has been successfully verified.

diff --git a/backend/accounts/urls.py b/backend/accounts/urls.py index 2dfd3a1..1c5f9ff 100644 --- a/backend/accounts/urls.py +++ b/backend/accounts/urls.py @@ -10,4 +10,6 @@ urlpatterns = [ ), path('logout/', LogoutView.as_view(), name='logout'), path('signup/', v.SignUpView.as_view(), name='signup'), + path('confirm//', v.confirm_email, name='confirm_email'), + path('resend//', v.resend_confirmation, name='resend_confirmation'), ] diff --git a/backend/accounts/utils.py b/backend/accounts/utils.py new file mode 100644 index 0000000..6ed5ff0 --- /dev/null +++ b/backend/accounts/utils.py @@ -0,0 +1,24 @@ +from django.core.mail import send_mail +from django.urls import reverse +from .models import EmailConfirmation +import uuid +from django.conf import settings +from django.utils.timezone import now + + +def send_confirmation_email(email): + confirmation, created = EmailConfirmation.objects.get_or_create(email=email) + + if not created: + confirmation.uuid = uuid.uuid4() + confirmation.created_at = now() + confirmation.save() + + confirmation_link = f"http://127.0.0.1:8000{reverse('confirm_email', args=[confirmation.uuid])}" + + send_mail( + subject="Confirm your e-mail address", + message=f"Please click on the link to confirm your e-mail address: {confirmation_link}", + from_email= settings.EMAIL_HOST_USER, + recipient_list=[email] + ) \ No newline at end of file diff --git a/backend/accounts/views.py b/backend/accounts/views.py index 7c88121..ecf9c75 100644 --- a/backend/accounts/views.py +++ b/backend/accounts/views.py @@ -1,9 +1,27 @@ from django.urls import reverse_lazy from django.views.generic import CreateView from backend.accounts.forms import SignupForm +from .models import EmailConfirmation +from django.shortcuts import get_object_or_404, render +from django.http import HttpResponse +from backend.accounts.utils import send_confirmation_email class SignUpView(CreateView): form_class = SignupForm success_url = reverse_lazy('login') template_name = 'accounts/signup.html' + + +def confirm_email(request,uuid): + confirmation = get_object_or_404(EmailConfirmation, uuid=uuid) + + if confirmation.is_expired(): + return render(request,'confirmation_expired.html', {'email': confirmation.email}) + + return HttpResponse("Email is confirmed") + +def resend_confirmation(request,email): + if request.method == 'POST': + send_confirmation_email(email) + return HttpResponse("Confirmation email resent") \ No newline at end of file diff --git a/backend/core/templates/thankyou.html b/backend/core/templates/thankyou.html index 37cdddd..0dbbd16 100644 --- a/backend/core/templates/thankyou.html +++ b/backend/core/templates/thankyou.html @@ -5,7 +5,6 @@

Thank you.

We will send the document to {{ email }} when it is ready. - View Your Document
diff --git a/backend/core/utils.py b/backend/core/utils.py index ddc7039..a572c89 100644 --- a/backend/core/utils.py +++ b/backend/core/utils.py @@ -13,10 +13,6 @@ def extract_risk_factors(organization): risk_data[field.name] = value return risk_data -from openai import OpenAI -from django.conf import settings -from .models import Risk - def get_top_risk(organization): client = OpenAI(api_key=settings.OPENAI_API_KEY) diff --git a/backend/core/views.py b/backend/core/views.py index 56177f2..f7e6c11 100644 --- a/backend/core/views.py +++ b/backend/core/views.py @@ -5,6 +5,8 @@ from .forms import OrganizationForm from .models import Organization,Document,Risk from backend.core.utils import get_top_risk from django.urls import reverse +from backend.accounts.utils import send_confirmation_email + # @login_required # def index(request): # return HttpResponse('

Django

Página simples.

') @@ -44,6 +46,8 @@ def signup(request): document.add_segment('body',f"Identified Risks: \n\n{risk_content}") + send_confirmation_email(form.data['email']) + return render(request, 'thankyou.html', { 'email': form.data['email'], 'document_link': reverse('core:document', args=[str(document.id)]) diff --git a/backend/settings.py b/backend/settings.py index 885a7cd..746e89d 100644 --- a/backend/settings.py +++ b/backend/settings.py @@ -18,6 +18,7 @@ import os from dotenv import load_dotenv load_dotenv() + #API key OPENAI_API_KEY = os.getenv("OPENAI_API_KEY") @@ -131,6 +132,17 @@ USE_THOUSAND_SEPARATOR = True DECIMAL_SEPARATOR = ',' +#EMAIL SMTP +EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend' +EMAIL_HOST = 'smtp.gmail.com' +EMAIL_PORT = 587 +EMAIL_USE_TLS = True +EMAIL_HOST_USER = os.getenv("CONF_MAIL") +EMAIL_HOST_PASSWORD = os.getenv("CONF_MAIL_PASSWORD") + +print(f"Email: {EMAIL_HOST_USER}") +print(f"Password: {EMAIL_HOST_PASSWORD}") + # Static files (CSS, JavaScript, Images) # https://docs.djangoproject.com/en/5.1/howto/static-files/