Browse Source

#362: Login form

Rafał Pitoń 11 years ago
parent
commit
e123c6c286

+ 21 - 9
misago/templates/misago/login.html

@@ -19,16 +19,28 @@
             <h1>{% trans "Sign in" %}</h1>
           </div>
 
-          <div class="form-body no-fieldsets">
-
-            {% for error in form.non_field_errors %}
-            <div class="misago-alerts">
-              <p class="alert alert-danger lead">
+          {% for error in form.non_field_errors %}
+          <div class="form-errors-block">
+            <ul class="list-unstyled">
+              <li>
                 {{ error }}
-                <br>{% trans "Please try again." %}
-              </p>
-            </div>
-            {% endfor %}
+              </li>
+              {% if form.user_ban and form.user_ban.user_message %}
+              <li>
+                <small>
+                  {{ form.user_ban.user_message|escape|linebreaksbr|urlize }}
+                </small>
+              </li>
+              {% elif form.user_cache.activation_by_user %}
+              <li>
+                <a href="#">{% trans "Click here to activate your account." %}</a>
+              </li>
+              {% endif %}
+            </ul>
+          </div>
+          {% endfor %}
+
+          <div class="form-body no-fieldsets">
 
             <div class="form-group">
               <div class="control-input">

+ 40 - 4
misago/users/forms/auth.py

@@ -2,9 +2,11 @@ from django.core.exceptions import ValidationError
 from django.contrib.auth import authenticate
 from django.contrib.auth.forms import (AuthenticationForm as
                                        BaseAuthenticationForm)
+from django.template.defaultfilters import date as format_date
 from django.utils.translation import ugettext_lazy as _
 
 from misago.core import forms
+from misago.users.bans import get_user_ban
 
 
 class AuthenticationForm(forms.Form, BaseAuthenticationForm):
@@ -21,7 +23,10 @@ class AuthenticationForm(forms.Form, BaseAuthenticationForm):
     error_messages = {
         'empty_data': _("You have to fill out both fields."),
         'invalid_login': _("Your login or password is incorrect."),
-        'inactive': _("This account is inactive."),
+        'inactive_user': _("You have to activate your account before "
+                           "you will be able to sign in."),
+        'inactive_admin': _("Administrator has to activate your account "
+                            "before you will be able to sign in."),
     }
 
     def clean(self):
@@ -31,7 +36,7 @@ class AuthenticationForm(forms.Form, BaseAuthenticationForm):
         if username and password:
             self.user_cache = authenticate(username=username,
                                            password=password)
-            if self.user_cache is None:
+            if self.user_cache is None or not self.user_cache.is_active:
                 raise ValidationError(
                     self.error_messages['invalid_login'],
                     code='invalid_login',
@@ -47,8 +52,39 @@ class AuthenticationForm(forms.Form, BaseAuthenticationForm):
         return self.cleaned_data
 
     def confirm_login_allowed(self, user):
-        # TODO: CHECK ACTIVATION AND BANS
-        pass
+        if user.requires_activation_by_admin:
+            raise ValidationError(
+                self.error_messages['inactive_admin'],
+                code='inactive_admin',
+            )
+
+        if user.requires_activation_by_user:
+            raise ValidationError(
+                self.error_messages['inactive_user'],
+                code='inactive_user',
+            )
+
+        self.user_ban = get_user_ban(user)
+        if self.user_ban:
+            if self.user_ban.valid_until:
+                if self.user_ban.user_message:
+                    message = _("%(username)s, your account is "
+                                "banned until %(date)s for:")
+                else:
+                    message = _("%(username)s, your account "
+                                "is banned until %(date)s.")
+                date_format = {'date': format_date(self.user_ban.valid_until)}
+                message = message % date_format
+            else:
+                if self.user_ban.user_message:
+                    message = _("%(username)s, your account is banned for:")
+                else:
+                    message = _("%(username)s, your account is banned.")
+
+            raise ValidationError(
+                message % {'username': self.user_cache.username},
+                code='banned',
+            )
 
 
 class AdminAuthenticationForm(AuthenticationForm):

+ 8 - 0
misago/users/models/user.py

@@ -234,6 +234,14 @@ class User(AbstractBaseUser, PermissionsMixin):
         raise TypeError('Cannot make User instances ACL aware')
 
     @property
+    def requires_activation_by_admin(self):
+        return self.requires_activation == ACTIVATION_REQUIRED_ADMIN
+
+    @property
+    def requires_activation_by_user(self):
+        return self.requires_activation == ACTIVATION_REQUIRED_USER
+
+    @property
     def staff_level(self):
         if self.is_superuser:
             return 2

+ 37 - 0
misago/users/tests/test_auth_views.py

@@ -2,6 +2,8 @@ from django.contrib.auth import get_user_model
 from django.core.urlresolvers import reverse
 from django.test import TestCase
 
+from misago.users.models import Ban, BAN_USERNAME
+
 
 class LoginViewTests(TestCase):
     def test_view_get_returns_200(self):
@@ -32,3 +34,38 @@ class LoginViewTests(TestCase):
         response = self.client.get(reverse('misago:index'))
         self.assertEqual(response.status_code, 200)
         self.assertIn('Bob', response.content)
+
+    def test_view_signin_banned(self):
+        """login view fails to sign banned user in"""
+        User = get_user_model()
+        User.objects.create_user('Bob', 'bob@test.com', 'Pass.123')
+        Ban.objects.create(test=BAN_USERNAME, banned_value='bob',
+                           user_message='Nope!')
+
+        response = self.client.post(
+            reverse('misago:login'),
+            data={'username': 'Bob', 'password': 'Pass.123'})
+
+        self.assertEqual(response.status_code, 200)
+        self.assertIn('Nope!', response.content)
+
+        response = self.client.get(reverse('misago:index'))
+        self.assertEqual(response.status_code, 200)
+        self.assertNotIn('Bob', response.content)
+
+    def test_view_signin_inactive(self):
+        """login view fails to sign inactive user in"""
+        User = get_user_model()
+        User.objects.create_user('Bob', 'bob@test.com', 'Pass.123',
+                                 requires_activation=1)
+
+        response = self.client.post(
+            reverse('misago:login'),
+            data={'username': 'Bob', 'password': 'Pass.123'})
+
+        self.assertEqual(response.status_code, 200)
+        self.assertIn('activate', response.content)
+
+        response = self.client.get(reverse('misago:index'))
+        self.assertEqual(response.status_code, 200)
+        self.assertNotIn('Bob', response.content)

+ 0 - 1
misago/users/urls.py

@@ -3,7 +3,6 @@ from django.conf.urls import patterns, url
 
 urlpatterns = patterns('misago.users.views.auth',
     url(r'^login/$', 'login', name='login'),
-    url(r'^login/banned/$', 'login_banned', name='login_banned'),
     url(r'^logout/$', 'logout', name='logout'),
 )
 

+ 2 - 4
misago/users/views/activation.py

@@ -6,9 +6,7 @@ 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.models import ACTIVATION_REQUIRED_NONE
 from misago.users.tokens import (make_activation_token,
                                  is_activation_token_valid)
 
@@ -32,7 +30,7 @@ def activate_by_token(request, user_id, token):
             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:
+        if inactive_user.requires_activation_by_admin:
             message = _("%(username)s, your account can be activated "
                         "only by one ofthe  administrators.")
             message = message % {'username': inactive_user.username}

+ 2 - 12
misago/users/views/auth.py

@@ -3,9 +3,9 @@ from django.contrib import auth, messages
 from django.http import Http404
 from django.shortcuts import render, redirect
 from django.utils.translation import ugettext as _
-from django.views.decorators.debug import sensitive_post_parameters
 from django.views.decorators.cache import never_cache
 from django.views.decorators.csrf import csrf_protect
+from django.views.decorators.debug import sensitive_post_parameters
 
 from misago.core.decorators import require_POST
 
@@ -23,12 +23,12 @@ def login(request):
     if request.method == 'POST':
         form = AuthenticationForm(request, data=request.POST)
         if form.is_valid():
+
             message = _("Welcome back, %(username)s! You have been "
                         "signed in successfully.")
             messages.success(
                 request, message % {'username': form.user_cache.username})
             auth.login(request, form.user_cache)
-            request.session.pop('login_ban', None)
             return redirect(settings.LOGIN_REDIRECT_URL)
 
     return render(request, 'misago/login.html', {'form': form})
@@ -44,13 +44,3 @@ def logout(request):
         request, message % {'username': request.user.username})
     auth.logout(request)
     return redirect('misago:index')
-
-
-@never_cache
-def login_banned(request):
-    try:
-        ban = request.session['login_ban']
-    except KeyError:
-        Http404()
-
-    return render(request, 'misago/errorpages/banned.html', {'ban': ban})