From d7f52fea9e83b7b4f857f2b434eeb1040e328d21 Mon Sep 17 00:00:00 2001
From: Christian Dresen <c.dresen@fh-muenster.de>
Date: Mon, 19 Sep 2016 22:35:29 +0200
Subject: [PATCH] [WarpAuth] Send activation link feature

---
 www/web/templates/two_factor/core/login.html  |  3 +-
 www/web/warpauth/admin.py                     |  6 +-
 www/web/warpauth/models.py                    | 13 ++++-
 .../templates/warpauth/register/activate.html | 23 ++++++++
 .../warpauth/{ => register}/register.html     |  2 +-
 .../warpauth/register/resend_token.html       | 28 ++++++++++
 www/web/warpauth/urls.py                      |  8 ++-
 www/web/warpauth/views/register.py            | 55 ++++++++++++++++++-
 www/web/warpzone/settings.py                  |  6 +-
 9 files changed, 131 insertions(+), 13 deletions(-)
 create mode 100644 www/web/warpauth/templates/warpauth/register/activate.html
 rename www/web/warpauth/templates/warpauth/{ => register}/register.html (97%)
 create mode 100644 www/web/warpauth/templates/warpauth/register/resend_token.html

diff --git a/www/web/templates/two_factor/core/login.html b/www/web/templates/two_factor/core/login.html
index d545b97..0d36ba5 100644
--- a/www/web/templates/two_factor/core/login.html
+++ b/www/web/templates/two_factor/core/login.html
@@ -52,5 +52,6 @@
   </form>
   </div>
 <a class="btn" href="/reset_password">{% trans "Forgot Password?" %}</a><br>
-<a class="btn" href="/register">{% trans "Register" %}</a>
+<a class="btn" href="/account/registration/">{% trans "Register" %}</a><br>
+<a class="btn" href="/account/registration/resend">{% trans "Resend Activation Link" %}</a>
 {% endblock %}
\ No newline at end of file
diff --git a/www/web/warpauth/admin.py b/www/web/warpauth/admin.py
index 52146bc..f0e80bb 100644
--- a/www/web/warpauth/admin.py
+++ b/www/web/warpauth/admin.py
@@ -1,13 +1,17 @@
 from django.contrib import admin
 
 # Register your models here.
-from warpauth.models import PasswordResetToken, LdapUser
+from warpauth.models import PasswordResetToken, LdapUser, ActivationToken
 
 
 @admin.register(PasswordResetToken)
 class PasswordResetTokenAdmin(admin.ModelAdmin):
         pass
 
+@admin.register(ActivationToken)
+class ActivationTokenAdmin(admin.ModelAdmin):
+        pass
+        
 @admin.register(LdapUser)
 class LdapUserAdmin(admin.ModelAdmin):
         pass
\ No newline at end of file
diff --git a/www/web/warpauth/models.py b/www/web/warpauth/models.py
index 18108bd..2d10969 100644
--- a/www/web/warpauth/models.py
+++ b/www/web/warpauth/models.py
@@ -12,6 +12,17 @@ class PasswordResetToken(models.Model):
     
     def __str__(self):
         return self.hash
+
+class ActivationToken(models.Model):
+    user = models.CharField(max_length=100)
+    email = models.CharField(max_length=100)
+    token = models.CharField(max_length=100)
+    created = models.DateTimeField(auto_now_add=True)
+    
+    def __str__(self):
+        return self.token
+
+
 # LDAP
 
 
@@ -42,7 +53,7 @@ class LdapUserForm(ModelForm):
 
 
 class LdapGroup(ldapdb.models.Model):
-    base_dn = "ou=groups,dc=nodomain,dc=org"
+    base_dn = "ou=groups,dc=warpzone,dc=ms"
     object_classes = ['posixGroup']
 
     gid = IntegerField(db_column='gidNumber', unique=True)
diff --git a/www/web/warpauth/templates/warpauth/register/activate.html b/www/web/warpauth/templates/warpauth/register/activate.html
new file mode 100644
index 0000000..9a8eddb
--- /dev/null
+++ b/www/web/warpauth/templates/warpauth/register/activate.html
@@ -0,0 +1,23 @@
+{% extends "base.html" %}
+{% load i18n %}
+{% block title %}{% trans "Activation" %}{% endblock %}
+
+{% block content %}
+    {% if token_error %}
+        <div class="alert alert-danger">
+            {% blocktrans %}
+                The Token you have provided is invalid.
+            {% endblocktrans %}
+        </div>
+        <br>
+         <a class="btn" href="/">{% trans "Back" %}</a>
+    {% else %}
+        <div class="alert alert-success">
+            {% blocktrans %}
+                Your Account was successfully activated.
+            {% endblocktrans %}
+        </div>
+        <br>
+        <a class="btn" href="/">{% trans "Ok" %}</a>
+    {% endif %}
+{% endblock %}
diff --git a/www/web/warpauth/templates/warpauth/register.html b/www/web/warpauth/templates/warpauth/register/register.html
similarity index 97%
rename from www/web/warpauth/templates/warpauth/register.html
rename to www/web/warpauth/templates/warpauth/register/register.html
index 8d6e6d5..ef7f4f0 100644
--- a/www/web/warpauth/templates/warpauth/register.html
+++ b/www/web/warpauth/templates/warpauth/register/register.html
@@ -36,7 +36,7 @@
         {% endif %}
             <label for="inputUser">{% trans "Username" %}</label>
             <input name="username" type="user" id="inputUser" class="form-control" placeholder="{% trans "Username" %}" required autofocus><br>
-            <label for="inputUser">{% trans "Email" %}</label>
+            <label for="inputEmail">{% trans "Email" %}</label>
             <input name="email" type="email" id="inputEmail" class="form-control" placeholder="{% trans "Email" %}" required><br>
             <label for="inputPassword">{% trans "Password" %}</label>
             <input name="password" type="password" id="inputPassword" class="form-control" placeholder="{% trans "Password" %}" required><br>
diff --git a/www/web/warpauth/templates/warpauth/register/resend_token.html b/www/web/warpauth/templates/warpauth/register/resend_token.html
new file mode 100644
index 0000000..584d19e
--- /dev/null
+++ b/www/web/warpauth/templates/warpauth/register/resend_token.html
@@ -0,0 +1,28 @@
+{% extends "base.html" %}
+{% load i18n %}
+{% block title %}{% trans "Registration" %}{% endblock %}
+{% block content %}
+     {% if error %}
+        <div class="alert alert-danger">
+            {% blocktrans %}
+               Error processing your request. Please contact the administrator.
+            {% endblocktrans %}
+        </div>
+    {% elif success %}
+           <div class="alert alert-success">
+            {% blocktrans %}
+               Email resended
+            {% endblocktrans %}
+        </div>
+    {% endif %}
+    <form  class="form" style="max-width: 330px; margin: 0 auto; padding: 40px">
+        {% csrf_token %}
+        <h2 class="form">{% trans "Resend token" %}</h2>
+            <br>
+            <label for="inputUser">{% trans "Username" %}</label>
+            <input name="username" type="user" id="inputUser" class="form-control" placeholder="{% trans "Username" %}" required autofocus><br>
+            <label for="inputEmail">{% trans "Email" %}</label>
+            <input name="email" type="email" id="inputEmail" class="form-control" placeholder="{% trans "Email" %}" required><br>
+            <button class="btn btn-lg btn-primary btn-block" type="submit" formmethod="post" class="btn btn-default">{% trans "Resend" %}</button>
+        </form>
+{% endblock %}
diff --git a/www/web/warpauth/urls.py b/www/web/warpauth/urls.py
index 2e38924..4c294b4 100644
--- a/www/web/warpauth/urls.py
+++ b/www/web/warpauth/urls.py
@@ -9,10 +9,12 @@ from warpauth.views import login, reset_password, profile, register
 urlpatterns = [
     # Authentication Pages
     url(r'', include('two_factor.urls', 'two_factor')),
-    url(r'^logout/$', login.logout_view, name='logout'),
-    url(r'^register/$', register.register, name='register'),
-    url(r'^reset_password/$', reset_password.gen_token, name='reset_password'),
+    url(r'^account/logout/$', login.logout_view, name='logout'),
+    url(r'^account/registration/$', register.register, name='register'),
+    url(r'^account/registration/activate/(?P<token>\w+)/$', register.activate, name='activate'),
+    url(r'^account/registration/resend/$', register.resend_token, name='resend_token'),
 
+    url(r'^reset_password/$', reset_password.gen_token, name='reset_password'),
     url(r'^reset_password/(?P<reset_hash>\w+)/$', reset_password.change_password, name='index'),
 
     url(r'^profile/$', profile.index, name='index'),
diff --git a/www/web/warpauth/views/register.py b/www/web/warpauth/views/register.py
index 4f851ef..708885c 100644
--- a/www/web/warpauth/views/register.py
+++ b/www/web/warpauth/views/register.py
@@ -1,12 +1,22 @@
 import re
+import hashlib
+import os
 from django.core.exceptions import ValidationError
 from django import forms
 from django.shortcuts import render
 from django.http import HttpResponse
 from warpauth.ldap_connector import LDAPConnector
-from warpauth.models import LdapUser
+from warpauth.models import LdapUser, ActivationToken, LdapGroup
 from warpauth.util import *
+from django.utils.translation import ugettext as _
+from django.core.exceptions import ObjectDoesNotExist
 
+
+def send_token(token):
+    email_content = _("https://infra.warpzone.ms/activate/%(token)s") % {'token': token.token }
+    ret = send_email(token.email, _("Your registration for WarpInfra"), email_content )
+    return ret
+    
 def register(request):
     pages['success'] = False
     pages['error'] = False
@@ -43,8 +53,47 @@ def register(request):
                 user.save()
                 ldap_connector = LDAPConnector()
                 ldap_connector.change_user_password(user.build_dn(), None, request.POST["password"], True)
-                pages['success'] = True
+                token = ActivationToken()
+                token.user = username
+                token.email = email
+                token.token = hashlib.sha1(os.urandom(128)).hexdigest()
+                token.save()
+                ret = send_token(token)
+                if not ret:
+                    pages["error"] = "Error while sending the email. Please contact the administrator."
+                else:
+                    pages['success'] = True
             else:
                 pages['error'] = "username_not_available"
 
-    return HttpResponse(render(request, 'warpauth/register.html', pages))
+    return HttpResponse(render(request, 'warpauth/register/register.html', pages))
+
+
+def activate(request, token=None):
+    pages["token_error"] = False
+    try:
+        activation_token = ActivationToken.objects.get(token=token)
+        group = LdapGroup.objects.filter(name="active").get()
+        group.members.append(activation_token.user)
+        group.save()
+        activation_token.delete()
+    except ObjectDoesNotExist:
+        pages["token_error"] = True
+
+    return HttpResponse(render(request, 'warpauth/register/activate.html', pages))
+
+def resend_token(request):
+    pages["error"] = False
+    pages["success"] = False
+    if request.method == "POST":
+        try:
+            token = ActivationToken.objects.get(user=request.POST["username"])
+            if token.email == request.POST["email"]:
+                ret = send_token(token)
+                if not ret:
+                    pages["error"] = True
+                pages["success"] = True
+        except ObjectDoesNotExist:
+            pages["error"] = True
+            
+    return HttpResponse(render(request, 'warpauth/register/resend_token.html', pages))
diff --git a/www/web/warpzone/settings.py b/www/web/warpzone/settings.py
index 82d9c3f..1826080 100644
--- a/www/web/warpzone/settings.py
+++ b/www/web/warpzone/settings.py
@@ -69,9 +69,9 @@ INSTALLED_APPS = (
     'warpauth',
     'warpfood',
     # WARPPAY
-#    'rest_framework',
-#    'rest_framework.authtoken',
-#    'warppay'
+    # 'rest_framework',
+    # 'rest_framework.authtoken',
+    # 'warppay'
 )
 
 MIDDLEWARE_CLASSES = (
-- 
GitLab