diff --git a/crispy_ai/settings.py b/crispy_ai/settings.py index f0e7af3..e46ffef 100644 --- a/crispy_ai/settings.py +++ b/crispy_ai/settings.py @@ -126,8 +126,12 @@ LOGIN_REDIRECT_URL = '/users/' # LOGOUT_REDIRECT_URL = '/' -EMAIL_HOST = 'localhost' +EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend' +EMAIL_HOST = 'smtp.gmail.com' EMAIL_PORT = 587 +EMAIL_HOST_USER = os.environ.get('HOST_EMAIL') +EMAIL_HOST_PASSWORD = os.environ.get('HOST_EMAIL_PASSWORD') +EMAIL_USE_TLS = True # crispy_forms CRISPY_TEMPLATE_PACK = 'bootstrap4' diff --git a/users/forms.py b/users/forms.py index 2b9c135..3391dc6 100644 --- a/users/forms.py +++ b/users/forms.py @@ -2,6 +2,7 @@ from django import forms from django.contrib.auth.models import User from .models import ProfileModel +from django.forms import ValidationError class UserRegisterForm(UserCreationForm): @@ -11,6 +12,19 @@ class Meta: model = User fields = ['username', 'email', 'password1', 'password2'] + def clean(self): + cleaned_data = super(UserRegisterForm, self).clean() + + try: + email = cleaned_data['email'] + except KeyError: + raise ValidationError("") + + if email and User.objects.filter(email=email).count() > 0: + raise ValidationError(u"Email already exists.") + + return cleaned_data + class UserUpdateForm(forms.ModelForm): email = forms.EmailField(max_length=254, help_text='Please provide a valid email address.') diff --git a/users/templates/registration/account_activated.html b/users/templates/registration/account_activated.html new file mode 100644 index 0000000..24ea887 --- /dev/null +++ b/users/templates/registration/account_activated.html @@ -0,0 +1,13 @@ +{% extends 'baseApp/base.html' %} + +{% block title %} + Login{% endblock %} + +{% block content %} +
+
+

Your account has been activated.

+

Please use this link to Login to Crispy AI

+
+
+{% endblock %} diff --git a/users/templates/registration/account_activation_email.html b/users/templates/registration/account_activation_email.html new file mode 100644 index 0000000..276a64e --- /dev/null +++ b/users/templates/registration/account_activation_email.html @@ -0,0 +1,5 @@ +{% autoescape off %} + Hi {{ user.username }}, + Please click on the link below to confirm your registration: + http://{{ domain }}{% url 'activate' uidb64=uid token=token %} +{% endautoescape %} \ No newline at end of file diff --git a/users/templates/registration/account_activation_invalid.html b/users/templates/registration/account_activation_invalid.html new file mode 100644 index 0000000..545d8db --- /dev/null +++ b/users/templates/registration/account_activation_invalid.html @@ -0,0 +1,12 @@ +{% extends 'baseApp/base.html' %} + +{% block title %} + Login{% endblock %} + +{% block content %} +
+
+

The confirmation link was invalid, possibly because it has already been used.

+
+
+{% endblock %} diff --git a/users/templates/registration/email_sent.html b/users/templates/registration/email_sent.html new file mode 100644 index 0000000..d1a96ff --- /dev/null +++ b/users/templates/registration/email_sent.html @@ -0,0 +1,12 @@ +{% extends 'baseApp/base.html' %} + +{% block title %} + Login{% endblock %} + +{% block content %} +
+
+

Email with activation link is sent to you!

+
+
+{% endblock %} diff --git a/users/tokens.py b/users/tokens.py new file mode 100644 index 0000000..879cf56 --- /dev/null +++ b/users/tokens.py @@ -0,0 +1,13 @@ +from django.contrib.auth.tokens import PasswordResetTokenGenerator +from django.utils import six + + +class AccountActivationTokenGenerator(PasswordResetTokenGenerator): + + def _make_hash_value(self, user, timestamp): + return ( + six.text_type(user.pk) + six.text_type(timestamp) + ) + + +account_activation_token = AccountActivationTokenGenerator() diff --git a/users/urls.py b/users/urls.py index c3412e4..2abae02 100644 --- a/users/urls.py +++ b/users/urls.py @@ -1,5 +1,5 @@ from django.contrib import admin -from django.urls import path, include +from django.urls import path, include, re_path from . import views urlpatterns = [ @@ -9,6 +9,7 @@ path('register/', views.register_user, name='register'), path('profile/', views.profile, name='profile'), path('course/', views.course_display, name='course_display'), - path('course/lectures/', views.lecture_display, name='lecture_display') - + path('course/lectures/', views.lecture_display, name='lecture_display'), + re_path(r'^activate/(?P[0-9A-Za-z_\-]+)/(?P[0-9A-Za-z]{1,13}-[0-9A-Za-z]{1,20})/$', + views.activate, name='activate'), ] diff --git a/users/views.py b/users/views.py index 3b1fa44..9c5078e 100644 --- a/users/views.py +++ b/users/views.py @@ -1,4 +1,14 @@ from django.shortcuts import render, redirect +from django.contrib.auth import authenticate, login +from django.core.mail import send_mail +from django.forms import ValidationError +from django.contrib.auth.models import User +from django.contrib.sites.shortcuts import get_current_site +from django.template.loader import render_to_string +from django.utils.http import urlsafe_base64_encode, urlsafe_base64_decode +from django.utils.encoding import force_bytes, force_text +from .tokens import account_activation_token +from crispy_ai.settings import EMAIL_HOST_USER from django.contrib.auth.decorators import login_required from .forms import UserRegisterForm, UserUpdateForm, ProfileUpdateForm from validate_email import validate_email @@ -15,22 +25,44 @@ def home(request): def register_user(request): - form = UserRegisterForm() if request.method == 'POST': form = UserRegisterForm(request.POST) if form.is_valid(): email = form.cleaned_data.get('email') - is_valid = validate_email(email) - if is_valid: - username = form.cleaned_data.get('username') - messages.success(request, 'Account Created for' + username) - form.save() - return redirect('Home') - - # if invalid, refill form + user = form.save(commit=False) + user.is_active = False + user.save() + current_site = get_current_site(request) + subject = 'Activate Your Crispy AI Account' + message = render_to_string('registration/account_activation_email.html', { + 'user': user, + 'domain': current_site.domain, + 'uid': urlsafe_base64_encode(force_bytes(user.pk)), + 'token': account_activation_token.make_token(user), + }) + from_mail = EMAIL_HOST_USER + to_mail = [user.email] + send_mail(subject, message, from_mail, to_mail, fail_silently=False) + return render(request, 'registration/email_sent.html') + else: + form = UserRegisterForm() return render(request, 'registration/register.html', {'form': form}) +# when user click on email link then this function execute +def activate(request, uidb64, token): + try: + uid = force_text(urlsafe_base64_decode(uidb64)) + user = User.objects.get(pk=uid) + except (TypeError, ValueError, OverflowError, User.DoesNotExist): + user = None + if user is not None and account_activation_token.check_token(user, token): + user.is_active = True + user.save() + return render(request, 'registration/account_activated.html') + else: + return render(request, 'registration/account_activation_invalid.html') + @login_required(login_url="/users/login/") def profile(request): if request.method == "POST":