Rafał Pitoń 11 лет назад
Родитель
Сommit
80e6e6de93

+ 2 - 2
misago/static/misago/admin/css/style.css

@@ -5791,14 +5791,14 @@ body {
   border-radius: 0;
   margin-bottom: 0px;
   padding: 16px 0px;
-  font-size: 18px;
+  font-size: 14px;
 }
 .misago-alerts .alert .alert-icon {
   margin: -12px 0px;
   margin-right: 6px;
   position: relative;
   top: 4.5px;
-  font-size: 32.4px;
+  font-size: 25.2px;
 }
 .btn.btn-default {
   background: #ededed;

+ 8 - 1
misago/templates/misago/emails/register/complete.txt

@@ -1,10 +1,17 @@
 {% extends "misago/emails/base.txt" %}
+{% load i18n %}
 
 {% block content %}
+{% blocktrans trimmed with username=recipient.username %}
 {{ username }}, thank you for joining us!
+{% endblocktrans %}
 
+{% blocktrans trimmed %}
 You may now join discussion on our forums. Why not spend a minute or two to have a look around and share your opinions and knowledge with rest of community?
+{% endblocktrans %}
 
-You can always sign in to your account using form below:
+{% blocktrans trimmed %}
+You can always sign in to your account using the form below:
+{% endblocktrans %}
 {{ SITE_ADDRESS }}{% url LOGIN_URL %}
 {% endblock content %}

+ 38 - 0
misago/templates/misago/emails/register/inactive.html

@@ -0,0 +1,38 @@
+{% extends "misago/emails/register/complete.html" %}
+{% load i18n misago_capture %}
+
+
+{% block activation-message %}
+{% if activation_by_admin %}
+  {% blocktrans trimmed %}
+  Before you will be able to join discussion on our forums, one of our administrators will have to activate your account.
+  {% endblocktrans %}
+  <br>
+  <br>
+  {% blocktrans trimmed %}
+  This may take a while, but you will receive e-mail with notification once it happens.
+  {% endblocktrans %}
+  <br>
+  <br>
+  {% blocktrans trimmed %}
+  Thank you for your patience and see you soon!
+  {% endblocktrans %}
+  <br>
+{% elif activation_by_user %}
+  {% blocktrans trimmed %}
+  Before you will be able to join discussion on our forums, you have to activate your account. To do so, simply click the link below:
+  {% endblocktrans %}
+  <br>
+  <br>
+  <a href="{{ SITE_ADDRESS }}{% url 'misago:activate_by_token' user_id=recipient.pk token=activation_token %}">{% trans "Activate my account!" %}</a>
+  <br>
+  <br>
+  {% capture trimmed as login_link %}
+  <a href="{{ SITE_ADDRESS }}{% url LOGIN_URL %}">{% trans "this form" %}</a>
+  {% endcapture %}
+  {% blocktrans trimmed with login_form=login_link|safe %}
+  Once your account is activated, you can always sign in to it using {{ login_form }}.
+  {% endblocktrans %}
+  <br>
+{% endif %}
+{% endblock activation-message %}

+ 34 - 0
misago/templates/misago/emails/register/inactive.txt

@@ -0,0 +1,34 @@
+{% extends "misago/emails/base.txt" %}
+{% load i18n %}
+
+{% block content %}
+{% blocktrans trimmed with username=recipient.username %}
+{{ username }}, thank you for joining us!
+{% endblocktrans %}
+{% if activation_by_admin %}
+  {% blocktrans trimmed %}
+  Before you will be able to join discussion on our forums, one of our administrators will have to activate your account.
+  {% endblocktrans %}
+
+
+  {% blocktrans trimmed %}
+  This may take a while, but you will receive e-mail with notification once it happens.
+  {% endblocktrans %}
+
+
+  {% blocktrans trimmed %}
+  Thank you for your patience and see you soon!
+  {% endblocktrans %}
+
+{% elif activation_by_user %}
+  {% blocktrans trimmed %}
+  Before you will be able to join discussion on our forums, you have to activate your account. To do so, simply click the link below:
+  {% endblocktrans %}
+  {{ SITE_ADDRESS }}{% url 'misago:activate_by_token' user_id=recipient.pk token=activation_token %}"
+
+  {% blocktrans trimmed with login_form=login_link|safe %}
+  Once your account is activated, you can always sign in to it using the form velow:
+  {% endblocktrans %}
+  {{ SITE_ADDRESS }}{% url LOGIN_URL %}
+{% endif %}
+{% endblock content %}

+ 53 - 4
misago/users/tests/test_registration_views.py

@@ -31,7 +31,56 @@ class RegisterViewTests(TestCase):
         response = self.client.get(reverse('misago:register'))
         self.assertEqual(response.status_code, 200)
 
-    def test_register_view_post_returns_302(self):
-        """register view creates user on POST"""
-        response = self.client.post(reverse('misago:register'))
-        self.assertEqual(response.status_code, 200)
+    def test_register_view_post_creates_active_user(self):
+        """register view creates active and signed in user on POST"""
+        settings.override_setting('account_activation', 'none')
+
+        response = self.client.post(reverse('misago:register'),
+                                    data={'username': 'Bob',
+                                          'email': 'bob@bob.com',
+                                          'password': 'pass123'})
+        self.assertEqual(response.status_code, 302)
+
+        response = self.client.get(reverse('misago:index'))
+        self.assertIn('Bob', response.content)
+
+        User = get_user_model()
+        user = User.objects.get_by_username('Bob')
+        user = User.objects.get_by_email('bob@bob.com')
+
+        response = self.client.get(reverse('misago:index'))
+        self.assertIn('Bob', response.content)
+
+    def test_register_view_post_creates_inactive_user(self):
+        """register view creates inactive user on POST"""
+        settings.override_setting('account_activation', 'user')
+
+        response = self.client.post(reverse('misago:register'),
+                                    data={'username': 'Bob',
+                                          'email': 'bob@bob.com',
+                                          'password': 'pass123'})
+        self.assertEqual(response.status_code, 302)
+
+        response = self.client.get(reverse('misago:register_completed'))
+        self.assertIn('bob@bob.com', response.content)
+
+        User = get_user_model()
+        user = User.objects.get_by_username('Bob')
+        user = User.objects.get_by_email('bob@bob.com')
+
+    def test_register_view_post_creates_admin_activated_user(self):
+        """register view creates admin activated user on POST"""
+        settings.override_setting('account_activation', 'admin')
+
+        response = self.client.post(reverse('misago:register'),
+                                    data={'username': 'Bob',
+                                          'email': 'bob@bob.com',
+                                          'password': 'pass123'})
+        self.assertEqual(response.status_code, 302)
+
+        response = self.client.get(reverse('misago:register_completed'))
+        self.assertIn('administrator', response.content)
+
+        User = get_user_model()
+        user = User.objects.get_by_username('Bob')
+        user = User.objects.get_by_email('bob@bob.com')

+ 2 - 2
misago/users/tests/test_tokens.py

@@ -15,6 +15,6 @@ class TokensTests(TestCase):
         token_a = tokens.make(user_a, 'test')
         token_b = tokens.make(user_b, 'test')
 
-        self.assertTrue(tokens.is_valid(token_a, user_a, 'test'))
-        self.assertTrue(tokens.is_valid(token_b, user_b, 'test'))
+        self.assertTrue(tokens.is_valid(user_a, 'test', token_a))
+        self.assertTrue(tokens.is_valid(user_b, 'test', token_b))
         self.assertTrue(token_a != token_b)

+ 3 - 3
misago/users/tokens.py

@@ -16,7 +16,7 @@ def make(user, token_type):
     return sha256('+'.join([unicode(s) for s in seeds])).hexdigest()[:12]
 
 
-def is_valid(token, user, token_type):
+def is_valid(user, token_type, token):
     return token == make(user, token_type)
 
 
@@ -30,5 +30,5 @@ def make_activation_token(user):
     return make(user, ACTIVATION_TOKEN)
 
 
-def is_activation_token_valid(token, user):
-    return is_valid(token, user, ACTIVATION_TOKEN)
+def is_activation_token_valid(user, token):
+    return is_valid(user, ACTIVATION_TOKEN, token)

+ 6 - 1
misago/users/urls.py

@@ -10,7 +10,12 @@ urlpatterns = patterns('misago.users.views.auth',
 
 urlpatterns += patterns('misago.users.views.register',
     url(r'^register/$', 'register', name='register'),
-    url(r'^register/completed/$', 'registration_completed', name='register_completed'),
+    url(r'^register/completed/$', 'register_completed', name='register_completed'),
+)
+
+
+urlpatterns += patterns('misago.users.views.activation',
+    url(r'^activation/(?P<user_id>\d+)/(?P<token>[a-zA-Z0-9]+)/$', 'activate_by_token', name="activate_by_token"),
 )
 
 

+ 59 - 0
misago/users/views/activation.py

@@ -0,0 +1,59 @@
+from django.contrib import messages
+from django.contrib.auth import get_user_model
+from django.http import Http404
+from django.shortcuts import get_object_or_404, redirect, render
+from django.utils.translation import ugettext as _
+
+from misago.conf import settings
+from misago.users.decorators import deny_authenticated, deny_banned_ips
+from misago.users.models import (ACTIVATION_REQUIRED_NONE,
+                                 ACTIVATION_REQUIRED_USER,
+                                 ACTIVATION_REQUIRED_ADMIN)
+from misago.users.tokens import (make_activation_token,
+                                 is_activation_token_valid)
+
+
+class ActivationStopped(Exception):
+    pass
+
+
+class ActivationError(Exception):
+    pass
+
+
+@deny_authenticated
+@deny_banned_ips
+def activate_by_token(request, user_id, token):
+    User = get_user_model()
+    inactive_user = get_object_or_404(User.objects, pk=user_id)
+
+    try:
+        if not inactive_user.requires_activation:
+            message = _("%(username)s, your account is already active.")
+            message = message % {'username': inactive_user.username}
+            raise ActivationStopped(message)
+        if inactive_user.requires_activation == ACTIVATION_REQUIRED_ADMIN:
+            message = _("%(username)s, your account can be activated "
+                        "only by one ofthe  administrators.")
+            message = message % {'username': inactive_user.username}
+            raise ActivationStopped(message)
+        if not is_activation_token_valid(inactive_user, token):
+            message = _("%(username)s, your activation link is invalid. "
+                        "Try again or request new activation message.")
+            message = message % {'username': inactive_user.username}
+            raise ActivationError(message)
+    except ActivationStopped as e:
+        messages.info(request, e.args[0])
+        return redirect('misago:index')
+    except ActivationError as e:
+        messages.error(request, e.args[0])
+        return redirect('misago:index')
+
+    inactive_user.requires_activation = ACTIVATION_REQUIRED_NONE
+    inactive_user.save(update_fields=['requires_activation'])
+
+    message = _("%(username)s, your account has been activated!")
+    message = message % {'username': inactive_user.username}
+    messages.success(request, message)
+
+    return redirect(settings.LOGIN_URL)

+ 3 - 3
misago/users/views/register.py

@@ -19,7 +19,7 @@ from misago.users.tokens import make_activation_token
 def register_decorator(f):
     def decorator(request):
         if settings.account_activation == 'disabled':
-            return registration_disabled(request)
+            return register_disabled(request)
         else:
             return f(request)
     return decorator
@@ -91,11 +91,11 @@ def register(request):
     return render(request, 'misago/register/form.html', {'form': form, 'testname': 'and<b>rzej'})
 
 
-def registration_disabled(request):
+def register_disabled(request):
     return render(request, 'misago/register/disabled.html')
 
 
-def registration_completed(request):
+def register_completed(request):
     """
     If user needs to activate his account, we display him page with message
     """