Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add email confirmation for registration #59

Merged
merged 3 commits into from
Jul 27, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion crispy_ai/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -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'
14 changes: 14 additions & 0 deletions users/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand All @@ -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.')
Expand Down
13 changes: 13 additions & 0 deletions users/templates/registration/account_activated.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{% extends 'baseApp/base.html' %}

{% block title %}
<title>Login</title>{% endblock %}

{% block content %}
<div class="card bg-light">
<div class="card-body">
<h4 class="card-title">Your account has been activated.</h4>
<p class="card-text">Please use this link to <a href="{% url 'login' %}">Login</a> to Crispy AI</p>
</div>
</div>
{% endblock %}
5 changes: 5 additions & 0 deletions users/templates/registration/account_activation_email.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{% autoescape off %}
Hi {{ user.username }},
Please click on the link below to confirm your registration:
http:https://{{ domain }}{% url 'activate' uidb64=uid token=token %}
{% endautoescape %}
12 changes: 12 additions & 0 deletions users/templates/registration/account_activation_invalid.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{% extends 'baseApp/base.html' %}

{% block title %}
<title>Login</title>{% endblock %}

{% block content %}
<div class="card bg-light">
<div class="card-body">
<h4 class="card-title">The confirmation link was invalid, possibly because it has already been used.</h4>
</div>
</div>
{% endblock %}
12 changes: 12 additions & 0 deletions users/templates/registration/email_sent.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{% extends 'baseApp/base.html' %}

{% block title %}
<title>Login</title>{% endblock %}

{% block content %}
<div class="card bg-light">
<div class="card-body">
<h4 class="card-title">Email with activation link is sent to you!</h4>
</div>
</div>
{% endblock %}
13 changes: 13 additions & 0 deletions users/tokens.py
Original file line number Diff line number Diff line change
@@ -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()
7 changes: 4 additions & 3 deletions users/urls.py
Original file line number Diff line number Diff line change
@@ -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 = [
Expand All @@ -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<uidb64>[0-9A-Za-z_\-]+)/(?P<token>[0-9A-Za-z]{1,13}-[0-9A-Za-z]{1,20})/$',
views.activate, name='activate'),
]
50 changes: 41 additions & 9 deletions users/views.py
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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":
Expand Down