Просмотр исходного кода

Refractored messaging compotent of Misago.

Ralfp 12 лет назад
Родитель
Сommit
95ee150951
92 измененных файлов с 440 добавлено и 623 удалено
  1. 13 15
      misago/admin/widgets.py
  2. 7 7
      misago/banning/admin/views.py
  3. 3 3
      misago/banning/models.py
  4. 11 5
      misago/banning/views.py
  5. 2 2
      misago/forms/__init__.py
  6. 23 32
      misago/messages/__init__.py
  7. 0 21
      misago/messages/messages.py
  8. 1 1
      misago/messages/middleware.py
  9. 9 10
      misago/overview/admin/views.py
  10. 23 15
      misago/security/auth.py
  11. 5 5
      misago/security/decorators.py
  12. 19 8
      misago/security/views.py
  13. 6 7
      misago/settings/admin/views.py
  14. 5 5
      misago/users/admin/ranks/views.py
  15. 10 10
      misago/users/admin/roles/views.py
  16. 17 17
      misago/users/admin/users/views.py
  17. 1 1
      misago/users/forms.py
  18. 1 1
      misago/users/middleware.py
  19. 16 13
      misago/users/views/__init__.py
  20. 51 45
      misago/users/views/activation.py
  21. 19 11
      misago/users/views/password.py
  22. 2 2
      misago/users/views/profiles.py
  23. 16 8
      misago/views.py
  24. 1 1
      static/sora/css/sora.css
  25. 3 1
      static/sora/css/sora/alerts.less
  26. 0 24
      templates/_message/banned.html
  27. 0 1
      templates/_message/base.html
  28. 0 7
      templates/_message/form_contains_errors.html
  29. 0 7
      templates/_message/invalid_request.html
  30. 0 9
      templates/_message/security/bad_credentials.html
  31. 0 6
      templates/_message/security/forbidden_authenticated.html
  32. 0 7
      templates/_message/security/forbidden_guest.html
  33. 0 11
      templates/_message/security/forbidden_jammed.html
  34. 0 7
      templates/_message/security/forbidden_request.html
  35. 0 7
      templates/_message/security/signed_in.html
  36. 0 7
      templates/_message/security/signed_out.html
  37. 0 7
      templates/_message/users/activation/admin.html
  38. 0 8
      templates/_message/users/activation/credentials.html
  39. 0 8
      templates/_message/users/activation/new.html
  40. 0 7
      templates/_message/users/activation/not_required.html
  41. 0 7
      templates/_message/users/activation/only_by_admin.html
  42. 0 9
      templates/_message/users/activation/required.html
  43. 0 8
      templates/_message/users/activation/resent.html
  44. 0 9
      templates/_message/users/activation/user.html
  45. 0 6
      templates/_message/users/invalid_confirmation_link.html
  46. 0 8
      templates/_message/users/password/reset_confirm.html
  47. 0 9
      templates/_message/users/password/reset_done.html
  48. 0 10
      templates/_message/users/registration/activation_admin.html
  49. 0 8
      templates/_message/users/registration/activation_none.html
  50. 0 9
      templates/_message/users/registration/activation_user.html
  51. 0 7
      templates/_message/users/registration/registrations_off.html
  52. 0 7
      templates/_message/users/search_empty.html
  53. 0 2
      templates/admin/admin/form.html
  54. 2 3
      templates/admin/admin/layout.html
  55. 0 2
      templates/admin/admin/list.html
  56. 2 2
      templates/admin/banning/list.html
  57. 8 6
      templates/admin/error403.html
  58. 8 6
      templates/admin/error404.html
  59. 0 11
      templates/admin/index.html
  60. 2 2
      templates/admin/layout.html
  61. 23 1
      templates/admin/macros.html
  62. 0 1
      templates/admin/message/base.html
  63. 0 7
      templates/admin/message/form_contains_errors.html
  64. 0 7
      templates/admin/message/invalid_request.html
  65. 0 9
      templates/admin/message/security/bad_credentials.html
  66. 0 8
      templates/admin/message/security/not_admin.html
  67. 0 7
      templates/admin/message/security/signed_in.html
  68. 0 7
      templates/admin/message/security/signed_out.html
  69. 0 17
      templates/admin/messages.html
  70. 2 2
      templates/admin/settings/search_results.html
  71. 2 3
      templates/admin/settings/settings.html
  72. 5 3
      templates/admin/signin.html
  73. 5 7
      templates/sora/error403.html
  74. 37 0
      templates/sora/error403_banned.html
  75. 5 7
      templates/sora/error404.html
  76. 4 3
      templates/sora/layout.html
  77. 23 1
      templates/sora/macros.html
  78. 8 2
      templates/sora/signin.html
  79. 3 4
      templates/sora/users/forgot_password.html
  80. 10 4
      templates/sora/users/list.html
  81. 2 1
      templates/sora/users/profile.html
  82. 3 4
      templates/sora/users/register.html
  83. 3 4
      templates/sora/users/resend_activation.html
  84. 2 1
      templates/sora/users/usercp/avatar.html
  85. 2 1
      templates/sora/users/usercp/avatar_banned.html
  86. 2 1
      templates/sora/users/usercp/credentials.html
  87. 3 2
      templates/sora/users/usercp/ignored.html
  88. 2 2
      templates/sora/users/usercp/options.html
  89. 2 1
      templates/sora/users/usercp/signature.html
  90. 3 2
      templates/sora/users/usercp/signature_banned.html
  91. 1 3
      templates/sora/users/usercp/usercp.html
  92. 2 1
      templates/sora/users/usercp/username.html

+ 13 - 15
misago/admin/widgets.py

@@ -7,7 +7,7 @@ from jinja2 import TemplateNotFound
 import math
 from misago.forms import Form
 from misago.forms.layouts import *
-from misago.messages import Message, BasicMessage
+from misago.messages import Message
 from misago.search import SearchException
 
 """
@@ -70,9 +70,9 @@ class BaseWidget(object):
             self.get_target(request, model)
             return model
         except self.admin.model.DoesNotExist:
-            request.messages.set_flash(BasicMessage(self.notfound_message), 'error', self.admin.id)
+            request.messages.set_flash(Message(self.notfound_message), 'error', self.admin.id)
         except ValueError as e:
-            request.messages.set_flash(BasicMessage(e.args[0]), 'error', self.admin.id)
+            request.messages.set_flash(Message(e.args[0]), 'error', self.admin.id)
         return None
 
 
@@ -311,12 +311,12 @@ class ListWidget(BaseWidget):
                             if len(criteria) > 0:
                                 search_criteria[field] = criteria
                         if not search_criteria:
-                            message = BasicMessage(_("No search criteria have been defined."))
+                            message = Message(_("No search criteria have been defined."))
                         else:
                             request.session[self.get_token('filter')] = search_criteria
                             return redirect(self.get_url())
                     else:
-                        message = BasicMessage(_("Search form contains errors."))
+                        message = Message(_("Search form contains errors."))
                     message.type = 'error'
                 else:
                     search_form = SearchForm(request=request)
@@ -324,7 +324,7 @@ class ListWidget(BaseWidget):
                 # Kill search
                 if request.POST.get('origin') == 'clear' and self.is_filtering and request.csrf.request_secure(request):
                     request.session[self.get_token('filter')] = None
-                    request.messages.set_flash(BasicMessage(_("Search criteria have been cleared.")), 'info', self.admin.id)
+                    request.messages.set_flash(Message(_("Search criteria have been cleared.")), 'info', self.admin.id)
                     return redirect(self.get_url())
             else:
                 if self.is_filtering:
@@ -344,8 +344,7 @@ class ListWidget(BaseWidget):
                         request.messages.set_flash(message, message.type, self.admin.id)
                         return redirect(redirect_url)
                 else:
-                    message = Message(request, table_form.non_field_errors()[0])
-                    message.type = 'error'
+                    message = Message(table_form.non_field_errors()[0], 'error')
             else:
                 table_form = TableForm(request=request)
         
@@ -363,14 +362,14 @@ class ListWidget(BaseWidget):
                             request.messages.set_flash(message, message.type, self.admin.id)
                             return redirect(redirect_url)
                     except AttributeError:
-                        message = BasicMessage(_("Action requested is incorrect."))
+                        message = Message(_("Action requested is incorrect."))
                 else:
                     if 'list_items' in list_form.errors:
-                        message = BasicMessage(self.nothing_checked_message)
+                        message = Message(self.nothing_checked_message)
                     elif 'list_action' in list_form.errors:
-                        message = BasicMessage(_("Action requested is incorrect."))
+                        message = Message(_("Action requested is incorrect."))
                     else:
-                        message = Message(request, list_form.non_field_errors()[0])
+                        message = Message(list_form.non_field_errors()[0])
                 message.type = 'error'
             else:
                 list_form = ListForm(request=request)
@@ -473,8 +472,7 @@ class FormWidget(BaseWidget):
                         pass
                     return redirect(self.get_fallback_url(request))
             else:
-                message = Message(request, form.non_field_errors()[0])
-                message.type = 'error'
+                message = Message(form.non_field_errors()[0], 'error')
         else:
             form = self.get_form_instance(FormType, request, model, self.get_initial_data(request, model))
             
@@ -515,7 +513,7 @@ class ButtonWidget(BaseWidget):
             
         # Crash if this is invalid request
         if not request.csrf.request_secure(request):
-            request.messages.set_flash(BasicMessage(_("Action authorization is invalid.")), 'error', self.admin.id)
+            request.messages.set_flash(Message(_("Action authorization is invalid.")), 'error', self.admin.id)
             return redirect(self.get_fallback_url(request))
         
         # Do something

+ 7 - 7
misago/banning/admin/views.py

@@ -56,7 +56,7 @@ class List(ListWidget):
     def action_delete(self, request, items, checked):
         Ban.objects.filter(id__in=checked).delete()
         request.monitor['bans_version'] = int(request.monitor['bans_version']) + 1
-        return BasicMessage(_('Selected bans have been lifted successfully.'), 'success'), reverse('admin_users_bans')
+        return Message(_('Selected bans have been lifted successfully.'), 'success'), reverse('admin_users_bans')
     
 
 class New(FormWidget):
@@ -85,7 +85,7 @@ class New(FormWidget):
                      )
         new_ban.save(force_insert=True)
         request.monitor['bans_version'] = int(request.monitor['bans_version']) + 1
-        return new_ban, BasicMessage(_('New Ban has been set.'), 'success')
+        return new_ban, Message(_('New Ban has been set.'), 'success')
     
    
 class Edit(FormWidget):
@@ -124,7 +124,7 @@ class Edit(FormWidget):
         target.expires = form.cleaned_data['expires']
         target.save(force_update=True)
         request.monitor['bans_version'] = int(request.monitor['bans_version']) + 1
-        return target, BasicMessage(_('Changes in ban have been saved.'), 'success')
+        return target, Message(_('Changes in ban have been saved.'), 'success')
 
 
 class Delete(ButtonWidget):
@@ -140,12 +140,12 @@ class Delete(ButtonWidget):
         target.delete()
         request.monitor['bans_version'] = int(request.monitor['bans_version']) + 1
         if target.type == 0:
-            return BasicMessage(_('E-mail and username Ban "%(ban)s" has been lifted.' % {'ban': target.ban}), 'success'), False
+            return Message(_('E-mail and username Ban "%(ban)s" has been lifted.') % {'ban': target.ban}, 'success'), False
         if target.type == 1:
-            return BasicMessage(_('Username Ban "%(ban)s" has been lifted.' % {'ban': target.ban}), 'success'), False
+            return Message(_('Username Ban "%(ban)s" has been lifted.') % {'ban': target.ban}, 'success'), False
         if target.type == 2:
-            return BasicMessage(_('E-mail Ban "%(ban)s" has been lifted.' % {'ban': target.ban}), 'success'), False
+            return Message(_('E-mail Ban "%(ban)s" has been lifted.') % {'ban': target.ban}, 'success'), False
         if target.type == 3:
-            return BasicMessage(_('IP Ban "%(ban)s" has been lifted.' % {'ban': target.ban}), 'success'), False
+            return Message(_('IP Ban "%(ban)s" has been lifted.') % {'ban': target.ban}, 'success'), False
         
         

+ 3 - 3
misago/banning/models.py

@@ -49,7 +49,7 @@ class BanCache(object):
         self.banned = False
         self.type = None
         self.expires = None
-        self.reason = None
+        self.reason_user = None
         self.version = 0
         
     def check_for_updates(self, request):
@@ -70,12 +70,12 @@ class BanCache(object):
             # Update ban cache
             if ban:
                 self.banned = True
-                self.reason = ban.reason_user
+                self.reason_user = ban.reason_user
                 self.expires = ban.expires
                 self.type = ban.type
             else:
                 self.banned = False
-                self.reason = None
+                self.reason_user = None
                 self.expires = None
                 self.type = None
             return True

+ 11 - 5
misago/banning/views.py

@@ -1,10 +1,16 @@
-from django.utils.translation import ugettext as _
+from django.template import RequestContext
 from misago.messages import Message
-from misago.views import error403
 
 def error_banned(request, user=None, ban=None):
-    if not user:
-        user = request.user
     if not ban:
         ban = request.ban
-    return error403(request, Message(request, 'banned', extra={'user': user, 'ban': ban}), _("You are banned"));
+    response = request.theme.render_to_response('error403_banned.html',
+                                                {
+                                                 'banned_user': user,
+                                                 'ban': ban,
+                                                 'hide_signin': True,
+                                                 'exception_response': True,
+                                                 },
+                                                context_instance=RequestContext(request));
+    response.status_code = 403
+    return response

+ 2 - 2
misago/forms/__init__.py

@@ -131,14 +131,14 @@ class Form(forms.Form):
         
     def _check_csrf(self):
         if not self.request.csrf.request_secure(self.request):
-            raise forms.ValidationError('invalid_request')
+            raise forms.ValidationError(_("Request authorization is invalid. Please resubmit your form."))
         
     def _check_fields_errors(self):
         if self.errors:
             if self.error_source and self.error_source in self.errors:
                 field_error, self.errors[self.error_source] = self.errors[self.error_source][0], []
                 raise forms.ValidationError(field_error)
-            raise forms.ValidationError('form_contains_errors')
+            raise forms.ValidationError(_("Form contains errors."))
         
         
 class YesNoSwitch(forms.CheckboxInput):

+ 23 - 32
misago/messages/__init__.py

@@ -1,37 +1,28 @@
-from coffin.template.loader import select_template
+class Messages(object):
+    def __init__(self, session):
+        self.session = session
+        self.messages = session.get('messages_list', [])
+        self.session['messages_list'] = []
+        
+    def set_message(self, message, type='info', owner=None):
+        message.type = type
+        message.owner = owner
+        self.messages.append(message)
+    
+    def set_flash(self, message, type='info', owner=None):
+        self.set_message(message, type, owner)
+        self.session['messages_list'].append(message)
+        
+    def get_message(self, owner=None):
+        for index, message in enumerate(self.messages):
+            if message.owner == owner:
+                del self.messages[index]
+                return message
+        return None
 
-class Message(object):
-    """
-    Template based mesage used by frontend
-    """
-    def __init__(self, request, type='base', message=None, extra={}, owner=None):
-        self.type = type
-        self.message = message
-        self.owner = owner
-        for key, value in extra.iteritems():
-            setattr(self, key, value)
-        self.tpl = select_template((
-                                    '%s/message/%s.html' % (request.theme.get_theme(), type),
-                                    '_message/%s.html' % type,
-                                    '%s/message/base.html' % request.theme.get_theme(),
-                                    '_message/base.html'
-                                    ))
-        self.tpl = self.tpl.name
-        if self.tpl[9:-5] == 'base':
-            self.message = type
-            
-    def is_basic(self):
-        return False
 
-
-class BasicMessage(object):
-    """
-    Text based mesage used by ACP
-    """
+class Message(object):
     def __init__(self, message=None, type='info', owner=None):
         self.type = type
         self.message = message
-        self.owner = owner
-            
-    def is_basic(self):
-        return True
+        self.owner = owner

+ 0 - 21
misago/messages/messages.py

@@ -1,21 +0,0 @@
-class Messages(object):
-    def __init__(self, session):
-        self.session = session
-        self.messages = session.get('messages_list', [])
-        self.session['messages_list'] = []
-        
-    def set_message(self, message, type='info', owner=None):
-        message.type = type
-        message.owner = owner
-        self.messages.append(message)
-    
-    def set_flash(self, message, type='info', owner=None):
-        self.set_message(message, type, owner)
-        self.session['messages_list'].append(message)
-        
-    def get_message(self, owner=None):
-        for index, message in enumerate(self.messages):
-            if message.owner == owner:
-                del self.messages[index]
-                return message
-        return None

+ 1 - 1
misago/messages/middleware.py

@@ -1,4 +1,4 @@
-from misago.messages.messages import Messages
+from misago.messages import Messages
 
 class MessagesMiddleware(object):
     def process_request(self, request):

+ 9 - 10
misago/overview/admin/views.py

@@ -3,7 +3,6 @@ from datetime import datetime, timedelta
 from django.conf import settings
 from django.core.urlresolvers import reverse
 from django.db import models
-from django.http import Http404
 from django.shortcuts import redirect
 from django.template import RequestContext
 from django.utils import formats, timezone
@@ -12,10 +11,11 @@ from misago.admin import site
 from misago.admin.widgets import *
 from misago.forms import FormLayout
 from misago.forums.models import Thread, Post
-from misago.messages import Message, BasicMessage
+from misago.messages import Message
 from misago.overview.admin.forms import GenerateStatisticsForm, SearchSessionsForm
 from misago.sessions.models import Session
 from misago.users.models import User
+from misago.views import error404
 
 def overview_home(request):
     return request.theme.render_to_response('overview/home.html', {
@@ -62,11 +62,11 @@ def overview_stats(request):
                 date_start = date_temp
             # Assert that dates are correct
             if date_end == date_start:
-                message = BasicMessage(_('Start and end date are same'), type='error')
+                message = Message(_('Start and end date are same'), type='error')
             elif check_dates(date_start, date_end, form.cleaned_data['stats_precision']):
                 message = check_dates(date_start, date_end, form.cleaned_data['stats_precision'])
             else:
-                request.messages.set_flash(BasicMessage(_('Statistical report has been created.')), 'success', 'admin_stats')
+                request.messages.set_flash(Message(_('Statistical report has been created.')), 'success', 'admin_stats')
                 return redirect(reverse('admin_overview_graph', kwargs={
                                                        'model': form.cleaned_data['provider_model'],
                                                        'date_start': date_start.strftime('%Y-%m-%d'),
@@ -74,8 +74,7 @@ def overview_stats(request):
                                                        'precision': form.cleaned_data['stats_precision']
                                                         }))
         else:
-            message = Message(request, form.non_field_errors()[0])
-            message.type = 'error'
+            message = Message(form.non_field_errors()[0], 'error')
     else:
         form = GenerateStatisticsForm(provider_choices=statistics_providers, request=request)
     
@@ -91,7 +90,7 @@ def overview_graph(request, model, date_start, date_end, precision):
     """
     if date_start == date_end:
         # Bad dates
-        raise Http404()
+        raise error404()
     
     # Turn stuff into datetime's
     date_start = datetime.strptime(date_start, '%Y-%m-%d')
@@ -115,7 +114,7 @@ def overview_graph(request, model, date_start, date_end, precision):
     
     if not model in models_map or check_dates(date_start, date_end, precision):
         # Bad model name or graph data!
-        raise Http404()
+        raise error404()
     
     form = GenerateStatisticsForm(
                                   provider_choices=statistics_providers,
@@ -137,12 +136,12 @@ def check_dates(date_start, date_end, precision):
         or (precision == 'week' and date_diff / 604800 > 60)
         or (precision == 'month' and date_diff / 2592000 > 60)
         or (precision == 'year' and date_diff / 31536000 > 60)):
-        return BasicMessage(_('Too many many items to display on graph.'), type='error')
+        return Message(_('Too many many items to display on graph.'), 'error')
     elif ((precision == 'day' and date_diff / 86400 < 1)
           or (precision == 'week' and date_diff / 604800 < 1)
           or (precision == 'month' and date_diff / 2592000 < 1)
           or (precision == 'year' and date_diff / 31536000 < 1)):
-        return BasicMessage(_('Too few items to display on graph'), type='error')
+        return Message(_('Too few items to display on graph'), 'error')
     return None
         
 

+ 23 - 15
misago/security/auth.py

@@ -10,20 +10,22 @@ from misago.users.models import User
 """
 Exception constants
 """
-CREDENTIALS = 'security/bad_credentials'
-ACTIVATION_USER = 'users/activation_user'
-ACTIVATION_ADMIN = 'users/activation_admin'
-BANNED = 'banned'
-NOT_ADMIN = 'security/not_admin'
+CREDENTIALS = 0
+ACTIVATION_USER = 1
+ACTIVATION_ADMIN = 2
+BANNED = 3
+NOT_ADMIN = 4
 
 
 class AuthException(Exception):
     """
     Auth Exception is thrown when auth_* method finds problem with allowing user to sign-in
     """
-    def __init__(self, type=None, user=None, ban=None):
+    def __init__(self, type=None, error=None, password=False, activation=False, ban=False):
         self.type = type
-        self.user = user
+        self.error = error
+        self.password = password
+        self.activation = activation
         self.ban = ban
         
     def __str__(self):
@@ -37,17 +39,17 @@ def get_user(email, password, admin=False):
     try:
         user = User.objects.get_by_email(email)
         if not user.check_password(password):
-            raise AuthException(CREDENTIALS, user)
+            raise AuthException(CREDENTIALS, _("Your e-mail address or password is incorrect. Please try again."), password=True)
         if not admin:
             if user.activation == User.ACTIVATION_ADMIN:
                 # Only admin can activate your account.
-                raise AuthException(ACTIVATION_ADMIN, user)
+                raise AuthException(ACTIVATION_ADMIN, _("Board Administrator has not yet accepted your account."))
             if user.activation != User.ACTIVATION_NONE:
-                # Only admin can activate your account.
-                raise AuthException(ACTIVATION_USER, user)
-        
+                # You have to activate your account - new member
+                raise AuthException(ACTIVATION_USER, _("You have to activate your account before you will be able to sign-in."), activation=True)
+    
     except User.DoesNotExist:
-        raise AuthException(CREDENTIALS)
+        raise AuthException(CREDENTIALS, _("Your e-mail address or password is incorrect. Please try again."), password=True)
     return user;
 
 
@@ -58,7 +60,9 @@ def auth_forum(request, email, password):
     user = get_user(email, password)
     user_ban = check_ban(username=user.username, email=user.email)
     if user_ban:
-        raise AuthException(BANNED, user, user_ban)
+        if user_ban.reason_user:
+            raise AuthException(BANNED, _("Your account has been banned for following reason:"), ban=user_ban)
+        raise AuthException(BANNED, _("Your account has been banned."), ban=user_ban)
     return user;
 
 
@@ -81,14 +85,17 @@ def auth_remember(request, ip):
         except Token.DoesNotExist:
             request.cookie_jar.delete('TOKEN')
             raise AuthException()
+        
         # See if token is not expired
         token_expires = timezone.now() - timedelta(days=request.settings['remember_me_lifetime'])
         if request.settings['remember_me_extensible'] and token_rk.accessed < token_expires:
             # Token expired because it's last use is smaller than expiration date
             raise AuthException()
+        
         if not request.settings['remember_me_extensible'] and token_rk.created < token_expires:
             # Token expired because it was created before expiration date
             raise AuthException()
+        
         # Update token date
         token_rk.accessed = timezone.now()
         token_rk.save(force_update=True)
@@ -104,7 +111,7 @@ def auth_admin(request, email, password):
     """
     user = get_user(email, password, True)
     if not user.is_admin():
-        raise AuthException(NOT_ADMIN)
+        raise AuthException(NOT_ADMIN, _("Your account does not have admin privileges."))
     return user;
 
 
@@ -115,5 +122,6 @@ def sign_user_in(request, user):
                         )
     user.save(force_update=True)
     request.session.set_user(user)
+    
     if request.settings['sessions_hidden']:
         request.session.set_hidden(user.hide_activity > 0)

+ 5 - 5
misago/security/decorators.py

@@ -1,4 +1,4 @@
-from misago.messages import Message
+from django.utils.translation import ugettext_lazy as _
 from misago.security.models import SignInAttempt
 from misago.views import error403
 
@@ -6,7 +6,7 @@ def block_authenticated(f):
     def decorator(*args, **kwargs):
         request = args[0]
         if not request.firewall.admin and request.user.is_authenticated():
-            return error403(request, Message(request, 'security/forbidden_authenticated'))
+            return error403(request, _("%{username}s, this page is not available to signed in users.") % {'username': request.user.username})
         return f(*args, **kwargs)
     return decorator
 
@@ -15,7 +15,7 @@ def block_jammed(f):
     def decorator(*args, **kwargs):
         request = args[0]
         if not request.firewall.admin and request.jam.is_jammed():
-            return error403(request, Message(request, 'security/forbidden_jammed'))
+            return error403(request, _("You have used up allowed sign-in attempts quota and we temporarily banned you from signing in."))
         return f(*args, **kwargs)
     return decorator
 
@@ -24,7 +24,7 @@ def block_guest(f):
     def decorator(*args, **kwargs):
         request = args[0]
         if not request.user.is_authenticated():
-            return error403(request, Message(request, 'security/forbidden_guest'))
+            return error403(request, _("Dear Guest, only signed in members are allowed to access this page. Please sign in or register and try again."))
         return f(*args, **kwargs)
     return decorator
 
@@ -33,6 +33,6 @@ def check_csrf(f):
     def decorator(*args, **kwargs):
         request = args[0]
         if not request.csrf.request_secure(request):
-            return error403(request, Message(request, 'security/forbidden_request'))
+            return error403(request, _("Request authorization is invalid. Please try again."))
         return f(*args, **kwargs)
     return decorator

+ 19 - 8
misago/security/views.py

@@ -20,12 +20,17 @@ from forms import SignInForm
 @block_jammed
 def signin(request):
     message = request.messages.get_message('security')
+    bad_password = False
+    not_active = False
+    banned_account = False   
+    
     if request.method == 'POST':
         form = SignInForm(
                           request.POST,
                           show_remember_me=not request.firewall.admin and request.settings['remember_me_allow'],
                           request=request
                           )
+        
         if form.is_valid():
             try:
                 # Configure correct auth and redirect links
@@ -44,8 +49,8 @@ def signin(request):
                                   )
                 
                 sign_user_in(request, user)     
-                           
                 remember_me_token = False
+                
                 if not request.firewall.admin and request.settings['remember_me_allow'] and form.cleaned_data['user_remember_me']:
                     remember_me_token = get_random_string(42)
                     remember_me = Token(
@@ -57,21 +62,24 @@ def signin(request):
                     remember_me.save()
                 if remember_me_token:
                     request.cookie_jar.set('TOKEN', remember_me_token, True)
-                request.messages.set_flash(Message(request, 'security/signed_in', extra={'user': user}), 'success', 'security')
+                request.messages.set_flash(Message(_("Welcome back, %(username)s!") % {'username': user.username}), 'success', 'security')
                 return redirect(success_redirect)
             except AuthException as e:
-                message = Message(request, e.type, extra={'user':e.user, 'ban':e.ban})
-                message.type = 'error'
+                message = Message(e.error, 'error')
+                bad_password = e.password
+                banned_account = e.ban
+                not_active = e.activation
+                
                 # If not in Admin, register failed attempt
                 if not request.firewall.admin and e.type == auth.CREDENTIALS:
                     SignInAttempt.objects.register_attempt(request.session.get_ip(request))
+                    
                     # Have we jammed our account?
                     if SignInAttempt.objects.is_jammed(request.settings, request.session.get_ip(request)):
                         request.jam.expires = timezone.now()
                         return redirect(reverse('sign_in'))
         else:
-            message = Message(request, form.non_field_errors()[0])
-            message.type = 'error'
+            message = Message(form.non_field_errors()[0], 'error')
     else:
         form = SignInForm(
                           show_remember_me=not request.firewall.admin and request.settings['remember_me_allow'],
@@ -80,9 +88,12 @@ def signin(request):
     return request.theme.render_to_response('signin.html',
                                             {
                                              'message': message,
+                                             'bad_password': bad_password,
+                                             'banned_account': banned_account,
+                                             'not_active': not_active,
                                              'form': FormLayout(form),
                                              'hide_signin': True, 
-                                            },
+                                             },
                                             context_instance=RequestContext(request));
 
 
@@ -91,7 +102,7 @@ def signin(request):
 def signout(request):
     user = request.user
     request.session.sign_out(request)
-    request.messages.set_flash(Message(request, 'security/signed_out', extra={'user': user}), 'info', 'security')
+    request.messages.set_flash(Message(_("You have been signed out.")), 'info', 'security')
     if request.firewall.admin:
         return redirect(reverse(site.get_admin_index()))
     return redirect(reverse('index'))

+ 6 - 7
misago/settings/admin/views.py

@@ -4,7 +4,7 @@ from django.template import RequestContext
 from django.utils.translation import ungettext, ugettext as _
 from misago.forms import Form
 from misago.forms.layouts import FormLayout, FormFields
-from misago.messages import Message, BasicMessage
+from misago.messages import Message
 from misago.search import SearchQuery, SearchException
 from misago.settings.admin.forms import SearchForm
 from misago.settings.models import Group, Setting
@@ -23,7 +23,7 @@ def settings(request, group_id=None, group_slug=None):
                 active_group = group
                 break
         else:
-            return error404(request, BasicMessage(_('The requested settings group could not be found.')))
+            return error404(request, _('The requested settings group could not be found.'))
             
     # Load selected group settings and turn them into form
     group_settings = Setting.objects.filter(group=active_group).order_by('position')
@@ -47,14 +47,13 @@ def settings(request, group_id=None, group_slug=None):
         if form.is_valid():
             for setting in form.cleaned_data.keys():
                 request.settings[setting] = form.cleaned_data[setting]
-            request.messages.set_flash(BasicMessage(_('Configuration has been saved.')), 'success', 'admin_settings')
+            request.messages.set_flash(Message(_('Configuration have been saved.')), 'success', 'admin_settings')
             return redirect(reverse('admin_settings', kwargs={
                                                        'group_id': active_group.pk,
                                                        'group_slug': active_group.key,
                                                        }))
         else:
-            message = Message(request, form.non_field_errors()[0])
-            message.type = 'error'
+            message = Message(form.non_field_errors()[0], 'error')
     else:
         form = SettingsGroupForm(request=request)
     
@@ -91,7 +90,7 @@ def settings_search(request):
                         
                 # Scream if nothing could be found
                 if found_settings:
-                    message = BasicMessage(ungettext(
+                    message = Message(ungettext(
                                                     'One setting that match search criteria has been found.',
                                                     '%(count)d settings that match search criteria have been found.',
                                                 len(found_settings)) % {
@@ -104,7 +103,7 @@ def settings_search(request):
         else:
             raise SearchException(_('Search query is invalid.'))
     except SearchException as e: 
-        message = BasicMessage(e.message, 'error')
+        message = Message(e.message, 'error')
     return request.theme.render_to_response('settings/search_results.html',
                                     {
                                     'message': message,

+ 5 - 5
misago/users/admin/ranks/views.py

@@ -50,7 +50,7 @@ class List(ListWidget):
         for item in page_items:
             item.order = cleaned_data['pos_' + str(item.pk)]
             item.save(force_update=True)
-        return BasicMessage(_('Ranks order has been changed'), 'success'), reverse('admin_users_ranks')
+        return Message(_('Ranks order has been changed'), 'success'), reverse('admin_users_ranks')
     
     def sort_items(self, request, page_items, sorting_method):
         return page_items.order_by('order')
@@ -63,7 +63,7 @@ class List(ListWidget):
 
     def action_delete(self, request, items, checked):
         Rank.objects.filter(id__in=checked).delete()
-        return BasicMessage(_('Selected ranks have been deleted successfully.'), 'success'), reverse('admin_users_ranks')
+        return Message(_('Selected ranks have been deleted successfully.'), 'success'), reverse('admin_users_ranks')
 
 
 class New(FormWidget):
@@ -94,7 +94,7 @@ class New(FormWidget):
                       criteria = form.cleaned_data['criteria']
                      )
         new_rank.save(force_insert=True)
-        return new_rank, BasicMessage(_('New Rank has been created.'), 'success')
+        return new_rank, Message(_('New Rank has been created.'), 'success')
     
    
 class Edit(FormWidget):
@@ -134,7 +134,7 @@ class Edit(FormWidget):
         target.as_tab = form.cleaned_data['as_tab']
         target.criteria = form.cleaned_data['criteria']
         target.save(force_update=True)
-        return target, BasicMessage(_('Changes in rank "%(name)s" have been saved.' % {'name': self.original_name}), 'success')
+        return target, Message(_('Changes in rank "%(name)s" have been saved.') % {'name': self.original_name}, 'success')
 
 
 class Delete(ButtonWidget):
@@ -145,4 +145,4 @@ class Delete(ButtonWidget):
     
     def action(self, request, target):
         target.delete()
-        return BasicMessage(_('Rank "%(name)s" has been deleted.' % {'name': target.name}), 'success'), False
+        return Message(_('Rank "%(name)s" has been deleted.') % {'name': target.name}, 'success'), False

+ 10 - 10
misago/users/admin/roles/views.py

@@ -41,14 +41,14 @@ class List(ListWidget):
         for item in items:
             if unicode(item.pk) in checked:
                 if item.token:
-                    return BasicMessage(_('You cannot delete system roles.'), 'error'), reverse('admin_users_roles')
+                    return Message(_('You cannot delete system roles.'), 'error'), reverse('admin_users_roles')
                 if item.protected and not request.user.is_god():
-                    return BasicMessage(_('You cannot delete protected roles.'), 'error'), reverse('admin_users_roles')
+                    return Message(_('You cannot delete protected roles.'), 'error'), reverse('admin_users_roles')
                 if item.user_set.count() > 0:
-                    return BasicMessage(_('You cannot delete roles that are assigned to users.'), 'error'), reverse('admin_users_roles')
+                    return Message(_('You cannot delete roles that are assigned to users.'), 'error'), reverse('admin_users_roles')
         
         Role.objects.filter(id__in=checked).delete()
-        return BasicMessage(_('Selected roles have been deleted successfully.'), 'success'), reverse('admin_users_roles')
+        return Message(_('Selected roles have been deleted successfully.'), 'success'), reverse('admin_users_roles')
 
 
 class New(FormWidget):
@@ -69,7 +69,7 @@ class New(FormWidget):
                       name = form.cleaned_data['name'],
                      )
         new_role.save(force_insert=True)
-        return new_role, BasicMessage(_('New Role has been created.'), 'success')
+        return new_role, Message(_('New Role has been created.'), 'success')
     
    
 class Edit(FormWidget):
@@ -96,7 +96,7 @@ class Edit(FormWidget):
     def submit_form(self, request, form, target):
         target.name = form.cleaned_data['name']
         target.save(force_update=True)
-        return target, BasicMessage(_('Changes in role "%(name)s" have been saved.' % {'name': self.original_name}), 'success')
+        return target, Message(_('Changes in role "%(name)s" have been saved.') % {'name': self.original_name}, 'success')
 
 
 class Delete(ButtonWidget):
@@ -107,11 +107,11 @@ class Delete(ButtonWidget):
     
     def action(self, request, target):
         if target.token:
-            return BasicMessage(_('You cannot delete system roles.'), 'error'), reverse('admin_users_roles')
+            return Message(_('You cannot delete system roles.'), 'error'), reverse('admin_users_roles')
         if target.protected and not request.user.is_god():
-            return BasicMessage(_('This role is protected.'), 'error'), reverse('admin_users_roles')
+            return Message(_('This role is protected.'), 'error'), reverse('admin_users_roles')
         if target.user_set.count() > 0:
-            return BasicMessage(_('This role is assigned to one or more usets.'), 'error'), reverse('admin_users_roles')
+            return Message(_('This role is assigned to one or more usets.'), 'error'), reverse('admin_users_roles')
 
         target.delete()
-        return BasicMessage(_('Role "%(name)s" has been deleted.' % {'name': target.name}), 'success'), False
+        return Message(_('Role "%(name)s" has been deleted.') % {'name': target.name}, 'success'), False

+ 17 - 17
misago/users/admin/users/views.py

@@ -74,14 +74,14 @@ class List(ListWidget):
                                 _("Your Account has been activated"),
                                 )
                 
-        return BasicMessage(_('Selected users accounts have been activated.'), 'success'), reverse('admin_users')
+        return Message(_('Selected users accounts have been activated.'), 'success'), reverse('admin_users')
     
     def action_deactivate(self, request, items, checked):
         # First loop - check for errors
         for user in items:
             if unicode(user.pk) in checked:
                 if user.is_protected() and not request.user.is_god():
-                    return BasicMessage(_('You cannot force validation of protected members e-mails.'), 'error'), reverse('admin_users')
+                    return Message(_('You cannot force validation of protected members e-mails.'), 'error'), reverse('admin_users')
                 
         # Second loop - reset passwords
         for user in items:
@@ -95,14 +95,14 @@ class List(ListWidget):
                                 _("Account Activation"),
                                 )
                 
-        return BasicMessage(_('Selected users accounts have been deactivated and new activation links have been sent to them.'), 'success'), reverse('admin_users')
+        return Message(_('Selected users accounts have been deactivated and new activation links have been sent to them.'), 'success'), reverse('admin_users')
 
     def action_remove_av(self, request, items, checked):
         # First loop - check for errors
         for user in items:
             if unicode(user.pk) in checked:
                 if user.is_protected() and not request.user.is_god():
-                    return BasicMessage(_('You cannot remove and block protected members avatars.'), 'error'), reverse('admin_users')
+                    return Message(_('You cannot remove and block protected members avatars.'), 'error'), reverse('admin_users')
                 
         # Second loop - reset passwords
         for user in items:
@@ -110,14 +110,14 @@ class List(ListWidget):
                 user.lock_avatar()
                 user.save(force_update=True)
                 
-        return BasicMessage(_('Selected users avatars were deleted and locked.'), 'success'), reverse('admin_users')
+        return Message(_('Selected users avatars were deleted and locked.'), 'success'), reverse('admin_users')
 
     def action_remove_sig(self, request, items, checked):
         # First loop - check for errors
         for user in items:
             if unicode(user.pk) in checked:
                 if user.is_protected() and not request.user.is_god():
-                    return BasicMessage(_('You cannot remove and block protected members signatures.'), 'error'), reverse('admin_users')
+                    return Message(_('You cannot remove and block protected members signatures.'), 'error'), reverse('admin_users')
                 
         # Second loop - reset passwords
         for user in items:
@@ -127,7 +127,7 @@ class List(ListWidget):
                 user.signature_preparsed = ''
                 user.save(force_update=True)
                 
-        return BasicMessage(_('Selected users signatures were deleted and locked.'), 'success'), reverse('admin_users')
+        return Message(_('Selected users signatures were deleted and locked.'), 'success'), reverse('admin_users')
    
     def action_remove_locks(self, request, items, checked):
         for user in items:
@@ -137,14 +137,14 @@ class List(ListWidget):
                 user.signature_ban = False
                 user.save(force_update=True)
                 
-        return BasicMessage(_('Selected users can now edit their avatars and signatures.'), 'success'), reverse('admin_users')
+        return Message(_('Selected users can now edit their avatars and signatures.'), 'success'), reverse('admin_users')
     
     def action_reset(self, request, items, checked):
         # First loop - check for errors
         for user in items:
             if unicode(user.pk) in checked:
                 if user.is_protected() and not request.user.is_god():
-                    return BasicMessage(_('You cannot reset protected members passwords.'), 'error'), reverse('admin_users')
+                    return Message(_('You cannot reset protected members passwords.'), 'error'), reverse('admin_users')
                 
         # Second loop - reset passwords
         for user in items:
@@ -161,19 +161,19 @@ class List(ListWidget):
                                  },
                                 )
                 
-        return BasicMessage(_('Selected users passwords have been reset successfully.'), 'success'), reverse('admin_users')
+        return Message(_('Selected users passwords have been reset successfully.'), 'success'), reverse('admin_users')
 
     def action_delete(self, request, items, checked):
         for user in items:
             if unicode(user.pk) in checked:
                 if user.pk == request.user.id:
-                    return BasicMessage(_('You cannot delete yourself.'), 'error'), reverse('admin_users')
+                    return Message(_('You cannot delete yourself.'), 'error'), reverse('admin_users')
                 if user.is_protected():
-                    return BasicMessage(_('You cannot delete protected members.'), 'error'), reverse('admin_users')
+                    return Message(_('You cannot delete protected members.'), 'error'), reverse('admin_users')
                 
         User.objects.filter(id__in=checked).delete()
         User.objects.resync_monitor(request.monitor)
-        return BasicMessage(_('Selected users have been deleted successfully.'), 'success'), reverse('admin_users')
+        return Message(_('Selected users have been deleted successfully.'), 'success'), reverse('admin_users')
     
 
 class Edit(FormWidget):
@@ -245,7 +245,7 @@ class Edit(FormWidget):
                 target.roles.add(role)
         
         target.save(force_update=True)
-        return target, BasicMessage(_('Changes in user\'s "%(name)s" account have been saved.' % {'name': self.original_name}), 'success')
+        return target, Message(_('Changes in user\'s "%(name)s" account have been saved.') % {'name': self.original_name}, 'success')
 
 
 class Delete(ButtonWidget):
@@ -256,12 +256,12 @@ class Delete(ButtonWidget):
     
     def action(self, request, target):
         if target.pk == request.user.id:
-            return BasicMessage(_('You cannot delete yourself.'), 'error'), False
+            return Message(_('You cannot delete yourself.'), 'error'), False
         if target.is_protected():
-            return BasicMessage(_('You cannot delete protected member.'), 'error'), False
+            return Message(_('You cannot delete protected member.'), 'error'), False
         target.delete()
         User.objects.resync_monitor(request.monitor)
-        return BasicMessage(_('User "%(name)s" has been deleted.' % {'name': target.username}), 'success'), False
+        return Message(_('User "%(name)s" has been deleted.') % {'name': target.username}, 'success'), False
     
 
 def inactive(request):

+ 1 - 1
misago/users/forms.py

@@ -85,7 +85,7 @@ class UserSendSpecialMailForm(Form):
     layout = [
               (
                None,
-               [('email', {'label': _("Your E-mail Address"), 'help_text': _("Your account's email address."), 'attrs': {'placeholder': _("Enter your e-mail address.")}})]
+               [('email', {'label': _("Your E-mail Address"), 'help_text': _("Enter email address you use to sign in to forums."), 'attrs': {'placeholder': _("Enter your e-mail address.")}})]
                ),
               (
                None,

+ 1 - 1
misago/users/middleware.py

@@ -20,7 +20,7 @@ class UserMiddleware(object):
             
             # Display "welcome back!" message
             if request.session.remember_me:
-                request.messages.set_message(_("We have signed you in automatically."), 'info', _("Welcome back, %(username)s!" % {'username': request.user.username}))
+                request.messages.set_message(_("Welcome back, %(username)s! We've signed you in automatically for your convenience.") % {'username': request.user.username}, 'info')
         else:
             # Set guest's timezone
             set_timezone(request.settings['default_timezone'])

+ 16 - 13
misago/users/views/__init__.py

@@ -10,14 +10,15 @@ from misago.security.auth import sign_user_in
 from misago.security.decorators import *
 from misago.users.forms import *
 from misago.users.models import User
-from misago.views import error403
+from misago.views import redirect_message
 
 @block_banned
 @block_authenticated
 @block_jammed
 def register(request):
     if request.settings['account_activation'] == 'block':
-        return error403(request, Message(request, 'users/registration/registrations_off'))
+       return redirect_message(request, Message(_("We are sorry but we don't allow new members registrations at this time.")), 'info')
+    
     message = None
     if request.method == 'POST':
         form = UserRegisterForm(request.POST, request=request)
@@ -40,27 +41,29 @@ def register(request):
             if need_activation == User.ACTIVATION_NONE:
                 # No need for activation, sign in user
                 sign_user_in(request, new_user)
-                request.messages.set_flash(Message(request, 'users/activation/none', extra={'user':new_user}), 'success')
+                request.messages.set_flash(Message(_("Welcome aboard, %(username)s! Your account has been registered successfully.") % {'username': new_user.username}), 'success')
+                
             if need_activation == User.ACTIVATION_USER:
                 # Mail user activation e-mail
-                request.messages.set_flash(Message(request, 'users/registration/activation_user', extra={'user':new_user}), 'info')
+                request.messages.set_flash(Message(_("%(username)s, your account has been registered, but you will have to activate it before you will be able to sign-in. We have sent you an e-mail with activation link.") % {'username': new_user.username}), 'info')
                 new_user.email_user(
                                     request,
                                     'users/activation/user',
-                                    _("Welcome aboard, %(username)s!" % {'username': new_user.username}),
+                                    _("Welcome aboard, %(username)s!") % {'username': new_user.username},
                                     )
+                
             if need_activation == User.ACTIVATION_ADMIN:
                 # Require admin activation
-                request.messages.set_flash(Message(request, 'users/registration/activation_admin', extra={'user':new_user}), 'info')
-            new_user.email_user(
-                                request,
-                                'users/activation/admin',
-                                _("Welcome aboard, %(username)s!" % {'username': new_user.username}),
-                                {'password': form.cleaned_data['password']}
-                                )
+                request.messages.set_flash(Message(_("%(username)s, Your account has been registered, but you won't be able to sign in until board administrator accepts it. We'll notify when this happens. Thank you for your patience!") % {'username': new_user.username}), 'info')
+                new_user.email_user(
+                                    request,
+                                    'users/activation/admin',
+                                    _("Welcome aboard, %(username)s!") % {'username': new_user.username},
+                                    {'password': form.cleaned_data['password']}
+                                    )
             return redirect(reverse('index'))
         else:
-            message = Message(request, form.non_field_errors()[0])
+            message = Message(form.non_field_errors()[0], 'error')
             if request.settings['registrations_jams']:
                 SignInAttempt.objects.register_attempt(request.session.get_ip(request))
             # Have we jammed our account?

+ 51 - 45
misago/users/views/activation.py

@@ -1,5 +1,3 @@
-from django.core.urlresolvers import reverse
-from django.shortcuts import redirect
 from django.template import RequestContext
 from django.utils.translation import ugettext as _
 from misago.banning.models import check_ban
@@ -11,43 +9,7 @@ from misago.security.auth import sign_user_in
 from misago.security.decorators import *
 from misago.users.forms import *
 from misago.users.models import User
-from misago.views import error403, error404
-
-
-@block_banned
-@block_authenticated
-@block_jammed
-def activate(request, username="", user="0", token=""):
-    user = int(user)
-    try:
-        user = User.objects.get(pk=user)
-        current_activation = user.activation
-        
-        # Run checks
-        user_ban = check_ban(username=user.username, email=user.email)
-        if user_ban:
-            return error_banned(request, user, user_ban)
-        if user.activation == User.ACTIVATION_NONE:
-            return error403(request, Message(request, 'users/activation/not_required', extra={'user': user}))
-        if user.activation == User.ACTIVATION_ADMIN:
-            return error403(request, Message(request, 'users/activation/only_by_admin', extra={'user': user}))
-        if not token or not user.token or user.token != token:
-            return error403(request, Message(request, 'users/invalid_confirmation_link', extra={'user': user}))
-        
-        # Activate and sign in our member
-        user.activation = User.ACTIVATION_NONE
-        sign_user_in(request, user)
-        
-        # Update monitor
-        request.monitor['users_inactive'] = int(request.monitor['users_inactive']) - 1
-        
-        if current_activation == User.ACTIVATION_CREDENTIALS:
-            request.messages.set_flash(Message(request, 'users/activation/credentials', extra={'user':user}), 'success')
-        else:
-            request.messages.set_flash(Message(request, 'users/activation/new', extra={'user':user}), 'success')
-        return redirect(reverse('index'))
-    except User.DoesNotExist:
-        return error404(request)
+from misago.views import redirect_message, error404
 
 
 @block_banned
@@ -55,26 +17,31 @@ def activate(request, username="", user="0", token=""):
 @block_jammed
 def form(request):
     message = None
+    
     if request.method == 'POST':
         form = UserSendSpecialMailForm(request.POST, request=request)
+        
         if form.is_valid():
             user = form.found_user
             user_ban = check_ban(username=user.username, email=user.email)
+            
             if user_ban:
                 return error_banned(request, user, user_ban)
+            
             if user.activation == User.ACTIVATION_NONE:
-                return error403(request, Message(request, 'users/activation/not_required', extra={'user': user}))
+                return redirect_message(request, Message(_("%(username)s, your account is already active.") % {'username': user.username}), 'info')
+            
             if user.activation == User.ACTIVATION_ADMIN:
-                return error403(request, Message(request, 'users/activation/only_by_admin', extra={'user': user}))
-            request.messages.set_flash(Message(request, 'users/activation/resent', extra={'user':user}), 'success')
+                return redirect_message(request, Message(_("%(username)s, only board administrator can activate your account.") % {'username': user.username}), 'info')
+        
             user.email_user(
                             request,
                             'users/activation/resend',
                             _("Account Activation"),
                             )
-            return redirect(reverse('index'))
+            return redirect_message(request, Message(_("%(username)s, e-mail containing new activation link has been sent to %{emaik}s.") % {'username': user.username, 'email': user.email}), 'success')
         else:
-            message = Message(request, form.non_field_errors()[0], 'error')
+            message = Message(form.non_field_errors()[0], 'error')
     else:
         form = UserSendSpecialMailForm(request=request)
     return request.theme.render_to_response('users/resend_activation.html',
@@ -82,4 +49,43 @@ def form(request):
                                              'message': message,
                                              'form': FormLayout(form),
                                             },
-                                            context_instance=RequestContext(request));
+                                            context_instance=RequestContext(request));
+
+
+@block_banned
+@block_authenticated
+@block_jammed
+def activate(request, username="", user="0", token=""):
+    user = int(user)
+    
+    try:
+        user = User.objects.get(pk=user)
+        current_activation = user.activation
+        
+        # Run checks
+        user_ban = check_ban(username=user.username, email=user.email)
+        if user_ban:
+            return error_banned(request, user, user_ban)
+        
+        if user.activation == User.ACTIVATION_NONE:
+            return redirect_message(request, Message(_("%(username)s, your account is already active.") % {'username': user.username}), 'info')
+            
+        if user.activation == User.ACTIVATION_ADMIN:
+            return redirect_message(request, Message(_("%(username)s, only board administrator can activate your account.") % {'username': user.username}), 'info')
+        
+        if not token or not user.token or user.token != token:
+            return redirect_message(request, Message(_("%(username)s, your activation link is invalid. Try again or request new activation e-mail.") % {'username': user.username}), 'error')
+        
+        # Activate and sign in our member
+        user.activation = User.ACTIVATION_NONE
+        sign_user_in(request, user)
+        
+        # Update monitor
+        request.monitor['users_inactive'] = int(request.monitor['users_inactive']) - 1
+        
+        if current_activation == User.ACTIVATION_CREDENTIALS:
+            return redirect_message(request, Message(_("%(username)s, your account has been successfully reactivated after change of sign-in credentials.") % {'username': user.username}), 'success')
+        else:
+            return redirect_message(request, Message(_("%(username)s, your account has been successfully activated. Welcome aboard!") % {'username': user.username}), 'success')
+    except User.DoesNotExist:
+        return error404(request)

+ 19 - 11
misago/users/views/password.py

@@ -1,5 +1,3 @@
-from django.core.urlresolvers import reverse
-from django.shortcuts import redirect
 from django.template import RequestContext
 from django.utils.translation import ugettext as _
 from misago.banning.models import check_ban
@@ -11,7 +9,7 @@ from misago.security import get_random_string
 from misago.security.decorators import *
 from misago.users.forms import *
 from misago.users.models import User
-from misago.views import error403, error404
+from misago.views import redirect_message, error404
 
 
 @block_banned
@@ -19,26 +17,30 @@ from misago.views import error403, error404
 @block_jammed   
 def form(request):
     message = None
+    
     if request.method == 'POST':
         form = UserSendSpecialMailForm(request.POST, request=request)
+        
         if form.is_valid():
             user = form.found_user
             user_ban = check_ban(username=user.username, email=user.email)
+            
             if user_ban:
                 return error_banned(request, user, user_ban)
             elif user.activation != User.ACTIVATION_NONE:
-                return error403(request, Message(request, 'users/activation/required', {'user': user}))
+                return redirect_message(request, Message(_("%(username)s, your account has to be activated in order for you to be able to request new password.") % {'username': user.username}), 'info')
+            
             user.token = get_random_string(12)
             user.save(force_update=True)
-            request.messages.set_flash(Message(request, 'users/password/reset_confirm', extra={'user':user}), 'success')
             user.email_user(
                             request,
                             'users/password/confirm',
                             _("Confirm New Password Request")
                             )
-            return redirect(reverse('index'))
+            
+            return redirect_message(request, Message(_("%(username)s, new password request confirmation has been sent to %{email}s.") % {'username': user.username, 'email': user.email}), 'info')
         else:
-            message = Message(request, form.non_field_errors()[0])
+            message = Message(form.non_field_errors()[0], 'error')
     else:
         form = UserSendSpecialMailForm(request=request)
     return request.theme.render_to_response('users/forgot_password.html',
@@ -57,27 +59,33 @@ def reset(request, username="", user="0", token=""):
     try:
         user = User.objects.get(pk=user)
         user_ban = check_ban(username=user.username, email=user.email)
+        
         if user_ban:
             return error_banned(request, user, user_ban)
+        
         if user.activation != User.ACTIVATION_NONE:
-            return error403(request, Message(request, 'users/activation/required', {'user': user}))
+            return redirect_message(request, Message(_("%(username)s, your account has to be activated in order for you to be able to request new password.") % {'username': user.username}), 'info')
+        
         if not token or not user.token or user.token != token:
-            return error403(request, Message(request, 'users/invalid_confirmation_link', {'user': user}))
+            return redirect_message(request, Message(_("%(username)s, request confirmation link is invalid. Please request new confirmation link.") % {'username': user.username}), 'error')
+        
         new_password = get_random_string(6)
         user.token = None
         user.set_password(new_password)
         user.save(force_update=True)
+        
         # Logout signed in and kill remember me tokens
         Session.objects.filter(user=user).update(user=None)
         Token.objects.filter(user=user).delete()
+        
         # Set flash and mail new password
-        request.messages.set_flash(Message(request, 'users/password/reset_done', extra={'user':user}), 'success')
         user.email_user(
                         request,
                         'users/password/new',
                         _("Your New Password"),
                         {'password': new_password}
                         )
-        return redirect(reverse('sign_in'))
+        
+        return redirect_message(request, Message(_("%(username)s, your password has been changed with new one that was sent to %{email}s.") % {'username': user.username, 'email': user.email}), 'success')
     except User.DoesNotExist:
         return error404(request)

+ 2 - 2
misago/users/views/profiles.py

@@ -56,9 +56,9 @@ def list(request, rank_slug=None):
                 print username
                 users = User.objects.filter(username_slug__startswith=username).order_by('username_slug')[:10]
         elif search_form.non_field_errors()[0] == 'form_contains_errors':
-            message = Message(request, 'users/search_empty', 'error')
+            message = Message(_("To search users you have to enter username in search field."), 'error')
         else:
-            message = Message(request, search_form.non_field_errors()[0], 'error')
+            message = Message(search_form.non_field_errors()[0], 'error')
     else:
         search_form = QuickFindUserForm(request=request)
         if active_rank:

+ 16 - 8
misago/views.py

@@ -1,23 +1,31 @@
+from django.core.urlresolvers import reverse
+from django.shortcuts import redirect
 from django.template import RequestContext
 
+
 def home(request):    
     return request.theme.render_to_response('index.html',
                                             {'page_title': 'Hello World!'},
                                             context_instance=RequestContext(request));
 
-def error403(request, message=None, title=None):
-    return error_view(request, 403, message, title)
+
+def redirect_message(request, message, type='info', owner=None):
+    request.messages.set_flash(message, type, owner)
+    return redirect(reverse('index'))
+
+
+def error403(request, message=None):
+    return error_view(request, 403, message)
+
                                             
-def error404(request, message=None, title=None):
-    return error_view(request, 404, message, title)
+def error404(request, message=None):
+    return error_view(request, 404, message)
+
 
-def error_view(request, error, message, title):
-    if message:
-        message.single = True
+def error_view(request, error, message):
     response = request.theme.render_to_response(('error%s.html' % error),
                                             {
                                              'message': message,
-                                             'title': title,
                                              'hide_signin': True,
                                              'exception_response': True,
                                              },

+ 1 - 1
static/sora/css/sora.css

@@ -875,7 +875,7 @@ th.table-sort.sort-desc a:hover{border-bottom:3px solid #eca09a;padding-bottom:5
 .btn.btn-inverse{background:#555555;border:1px solid #555555;*border:0;background:#555555;border:1px solid #555555;*border:0;color:#f7f7f7;text-shadow:0px 1px 0px #484848;}.btn.btn-inverse:hover,.btn.btn-inverse:active{background:#7e7e7e;border:1px solid #7e7e7e;*border:0;}
 .btn.btn-link{background:none;border:none;}.btn.btn-link:hover,.btn.btn-link:active{color:#00aaff;text-decoration:none;}
 .alerts-global{margin-top:16px;}
-.alert-form{margin:0px;margin-bottom:16px;font-weight:bold;}
+.alert-form{margin:0px;margin-bottom:16px;}.alert-form p{font-weight:normal;}
 .alert-inline{margin:0px;padding:0px;}
 .alert-icon{float:left;}.alert-icon span{-webkit-border-radius:2px;-moz-border-radius:2px;border-radius:2px;padding:1px 2px;}
 .alert .alert-icon span{background:#f89406;}

+ 3 - 1
static/sora/css/sora/alerts.less

@@ -8,7 +8,9 @@
   margin: 0px;
   margin-bottom: 16px;
   
-  font-weight: bold;
+  p {
+    font-weight: normal;
+  }
 }
 
 .alert-inline {

+ 0 - 24
templates/_message/banned.html

@@ -1,24 +0,0 @@
-{% extends "_message/base.html" %}
-{% load i18n %}
-
-{% block content %}
-{% if message.user.is_authenticated() %}
-  <div class="alert-icon"><span><i class="icon-remove icon-white"></i></span></div>
-  {% if message.ban.reason_user %}
-  <p>{% trans username=message.user.username %}{{ username }}, your account has been banned for following reason:{% endtrans %}</p>
-  {{ message.ban.reason_user|markdown|safe }}
-  {% else %}
-  <p>{% trans username=message.user.username %}{{ username }}, your account has been banned by board administrator.{% endtrans %}</p>
-  {% endif %}
-{% else %}
-  {% if message.ban.reason_user %}
-  <p>{% trans %}Dear guest, your access to this page has been forbidden for following reason:{% endtrans %}</p>
-  {{ message.ban.reason_user|markdown|safe }}
-  {% else %}
-  <p>{% trans %}Dear guest, your access to this page has been forbidden.{% endtrans %}</p>
-  {% endif %}
-{% endif %}
-  {% if message.ban.expires %}
-  <p>{% trans %}Your ban will expire on{% endtrans %} <em>{{ message.ban.expires|date(format.DATE_FORMAT) }}</em></p>
-  {% endif %}
-{% endblock %}

+ 0 - 1
templates/_message/base.html

@@ -1 +0,0 @@
-{% block content %}{{ message.message }}{% endblock %}

+ 0 - 7
templates/_message/form_contains_errors.html

@@ -1,7 +0,0 @@
-{% extends "_message/base.html" %}
-{% load i18n %}
-
-{% block content %}
-  <div class="alert-icon"><span><i class="icon-remove icon-white"></i></span></div>
-  <p>{% trans %}Form contains errors. Please try again.{% endtrans %}</p>
-{% endblock %}

+ 0 - 7
templates/_message/invalid_request.html

@@ -1,7 +0,0 @@
-{% extends "_message/base.html" %}
-{% load i18n %}
-
-{% block content %}
-  <div class="alert-icon"><span><i class="icon-remove icon-white"></i></span></div>
-  <p>{% trans %}Request authorization is invalid. Resubmit your form.{% endtrans %}</p>
-{% endblock %}

+ 0 - 9
templates/_message/security/bad_credentials.html

@@ -1,9 +0,0 @@
-{% extends "_message/base.html" %}
-{% load i18n %}
-{% load url from future %}
-
-{% block content %}
-  <div class="alert-icon"><span><i class="icon-remove icon-white"></i></span></div>
-  <p>{% trans %}Your e-mail address or password is incorrect. Please try again.{% endtrans %}</p>
-  <p class="protip"><a href="{% url 'forgot_password' %}">{% trans %}Click here if you forgot your sign in credentials.{% endtrans %}</a></p>
-{% endblock %}

+ 0 - 6
templates/_message/security/forbidden_authenticated.html

@@ -1,6 +0,0 @@
-{% extends "_message/base.html" %}
-{% load i18n %}
-
-{% block content %}
-  <p>{% trans username=user.username %}{{ username }}, this page is not available to signed in users.{% endtrans %}</p>
-{% endblock %}

+ 0 - 7
templates/_message/security/forbidden_guest.html

@@ -1,7 +0,0 @@
-{% extends "_message/base.html" %}
-{% load i18n %}
-
-{% block content %}
-  <p>{% trans %}Dear Guest, only signed in members are allowed to access this page.{% endtrans %}</p>
-  <p>{% trans %}Please sign in or register and try again.{% endtrans %}</p>
-{% endblock %}

+ 0 - 11
templates/_message/security/forbidden_jammed.html

@@ -1,11 +0,0 @@
-{% extends "_message/base.html" %}
-{% load i18n %}
-
-{% block content %}
-  {% if settings.jams_lifetime > 0 %}
-  <p>{% trans %}You have used up allowed sign-in attempts quota and we temporarily banned you from signing in .{% endtrans %}</p>
-  <p>{% trans %}Please try again later.{% endtrans %}</p>
-  {% else %}
-  <p>{% trans %}You have used up allowed sign-in attempts quota and we banned you from signing in .{% endtrans %}</p>
-  {% endif %}
-{% endblock %}

+ 0 - 7
templates/_message/security/forbidden_request.html

@@ -1,7 +0,0 @@
-{% extends "_message/base.html" %}
-{% load i18n %}
-
-{% block content %}
-  <p>{% trans %}Request authorization is invalid.{% endtrans %}</p>
-  <p>{% trans %}Please try again.{% endtrans %}</p>
-{% endblock %}

+ 0 - 7
templates/_message/security/signed_in.html

@@ -1,7 +0,0 @@
-{% extends "_message/base.html" %}
-{% load i18n %}
-
-{% block content %}
-  <div class="alert-icon"><span><i class="icon-ok icon-white"></i></span></div>
-  <p><strong>{% trans username=message.user.username %}Welcome back, {{ username }}!{% endtrans %}</strong> {% trans %}You have signed in successfully.{% endtrans %}</p>
-{% endblock %}

+ 0 - 7
templates/_message/security/signed_out.html

@@ -1,7 +0,0 @@
-{% extends "_message/base.html" %}
-{% load i18n %}
-
-{% block content %}
-  <div class="alert-icon"><span><i class="icon-info-sign icon-white"></i></span></div>
-  <p><strong>{% trans %}You have been signed out.{% endtrans %}</strong></p>
-{% endblock %}

+ 0 - 7
templates/_message/users/activation/admin.html

@@ -1,7 +0,0 @@
-{% extends "_message/base.html" %}
-{% load i18n %}
-
-{% block content %}
-  <div class="alert-icon"><span><i class="icon-ok icon-white"></i></span></div>
-  <p>{% trans username=message.user.username %}{{ username }}, Board Administrator has not yet activated your account. Please try again later.{% endtrans %}</p>
-{% endblock %}

+ 0 - 8
templates/_message/users/activation/credentials.html

@@ -1,8 +0,0 @@
-{% extends "_message/base.html" %}
-{% load i18n %}
-
-{% block content %}
-  <div class="alert-icon"><span><i class="icon-ok icon-white"></i></span></div>
-  <p>{% trans username=message.user.username %}Welcome back, {{ username }}!{% endtrans %}</p>
-  <p class="protip">{% trans %}Your account has been successfully reactivated after change of sign-in credentials.{% endtrans %}</p>
-{% endblock %}

+ 0 - 8
templates/_message/users/activation/new.html

@@ -1,8 +0,0 @@
-{% extends "_message/base.html" %}
-{% load i18n %}
-
-{% block content %}
-  <div class="alert-icon"><span><i class="icon-ok icon-white"></i></span></div>
-  <p>{% trans username=message.user.username %}Welcome aboard, {{ username }}!{% endtrans %}</p>
-  <p class="protip">{% trans %}Your account has been successfully activated.{% endtrans %}</p>
-{% endblock %}

+ 0 - 7
templates/_message/users/activation/not_required.html

@@ -1,7 +0,0 @@
-{% extends "_message/base.html" %}
-{% load i18n %}
-
-{% block content %}
-  <div class="alert-icon"><span><i class="icon-info-sign icon-white"></i></span></div>
-  <p>{% trans username=message.user.username %}{{ username }}, your account is already active.{% endtrans %}</p>
-{% endblock %}

+ 0 - 7
templates/_message/users/activation/only_by_admin.html

@@ -1,7 +0,0 @@
-{% extends "_message/base.html" %}
-{% load i18n %}
-
-{% block content %}
-  <div class="alert-icon"><span><i class="icon-info-sign icon-white"></i></span></div>
-  <p>{% trans username=message.user.username %}{{ username }}, only administrator can activate your account.{% endtrans %}</p>
-{% endblock %}

+ 0 - 9
templates/_message/users/activation/required.html

@@ -1,9 +0,0 @@
-{% extends "_message/base.html" %}
-{% load i18n %}
-{% load url from future %}
-
-{% block content %}
-  <div class="alert-icon"><span><i class="icon-remove icon-white"></i></span></div>
-  <p><strong>{% trans username=message.user.username %}{{ username }}, your account has to be activated in order for you to be able to request new password.{% endtrans %}</strong></p>
-  <p class="protip"><a href="{% url 'send_activation' %}">{% trans %}Click here if you haven't received activation e-mail.{% endtrans %}</a></p>
-{% endblock %}

+ 0 - 8
templates/_message/users/activation/resent.html

@@ -1,8 +0,0 @@
-{% extends "_message/base.html" %}
-{% load i18n %}
-
-{% block content %}
-  <div class="alert-icon"><span><i class="icon-info-sign icon-white"></i></span></div>
-  <p><strong>{% trans %}Check your inbox!{% endtrans %}</strong></p>
-  <p>{% trans username=message.user.username, email=message.user.email %}{{ username }}, we have mailed new activation instructions to your email at {{ email }}.{% endtrans %}</p>
-{% endblock %}

+ 0 - 9
templates/_message/users/activation/user.html

@@ -1,9 +0,0 @@
-{% extends "_message/base.html" %}
-{% load i18n %}
-{% load url from future %}
-
-{% block content %}
-  <div class="alert-icon"><span><i class="icon-info-sign icon-white"></i></span></div>
-  <p><strong>{% trans username=message.user.username %}{{ username }}, you have to activate your account before you will be able to sign in.{% endtrans %}</strong></p>
-  <p class="protip"><a href="{% url 'send_activation' %}">{% trans %}Click here if you haven't received activation e-mail.{% endtrans %}</a></p>
-{% endblock %}

+ 0 - 6
templates/_message/users/invalid_confirmation_link.html

@@ -1,6 +0,0 @@
-{% extends "_message/base.html" %}
-{% load i18n %}
-
-{% block content %}
-  <p>{% trans %}Activation link is invalid. Please check your inbox and request new activation e-mail if necessary.{% endtrans %}</p>
-{% endblock %}

+ 0 - 8
templates/_message/users/password/reset_confirm.html

@@ -1,8 +0,0 @@
-{% extends "_message/base.html" %}
-{% load i18n %}
-
-{% block content %}
-  <div class="alert-icon"><span><i class="icon-info-sign icon-white"></i></span></div>
-  <p><strong>{% trans email=message.user.email %}Password reset confirmation has been sent to {{ email }}.{% endtrans %}</strong></p>
-  <p>{% trans %}You have to confirm your request for new password by clicking confirmation link in message we have sent to you.{% endtrans %}</p>
-{% endblock %}

+ 0 - 9
templates/_message/users/password/reset_done.html

@@ -1,9 +0,0 @@
-{% extends "_message/base.html" %}
-{% load i18n %}
-
-{% block content %}
-  <div class="alert-icon"><span><i class="icon-ok icon-white"></i></span></div>
-  <p><strong>{% trans email=message.user.email %}Your new password has been sent to {{ email }}!{% endtrans %}</strong></p>
-  <p>{% trans %}We have generated new password on your account and have sent it to you.{% endtrans %}</p>
-  <p>{% trans username=message.user.username %}Check your inbox, {{ username }}!{% endtrans %}</p>
-{% endblock %}

+ 0 - 10
templates/_message/users/registration/activation_admin.html

@@ -1,10 +0,0 @@
-{% extends "_message/base.html" %}
-{% load i18n %}
-
-{% block content %}
-  <div class="alert-icon"><span><i class="icon-info-sign icon-white"></i></span></div>
-  <p><strong>{% trans username=message.user.username %}Welcome aboard, {{ username }}!{% endtrans %}</strong></p>
-  <p>{% trans %}Your account has been registered, but you won't be able to sign in before Board Administrator accepts your account.{% endtrans %}</p>
-  <p>{% trans %}Usually new member accounts are activated on same day, but sometimes this may take little longer.{% endtrans %}</p>
-  <p>{% trans %}Thanks for your patience!{% endtrans %}</p>
-{% endblock %}

+ 0 - 8
templates/_message/users/registration/activation_none.html

@@ -1,8 +0,0 @@
-{% extends "_message/base.html" %}
-{% load i18n %}
-
-{% block content %}
-  <div class="alert-icon"><span><i class="icon-ok icon-white"></i></span></div>
-  <p><strong>{% trans username=message.user.username %}Welcome aboard, {{ username }}!{% endtrans %}</strong></p>
-  <p>{% trans %}Your account has been registered successfully.{% endtrans %}</p>
-{% endblock %}

+ 0 - 9
templates/_message/users/registration/activation_user.html

@@ -1,9 +0,0 @@
-{% extends "_message/base.html" %}
-{% load i18n %}
-
-{% block content %}
-  <div class="alert-icon"><span><i class="icon-info-sign icon-white"></i></span></div>
-  <p><strong>{% trans username=message.user.username %}Welcome aboard, {{ username }}!{% endtrans %}</strong></p>
-  <p>{% trans %}Your account has been registered, but you will have to activate it before you will be able to sign-in. We have sent you an e-mail with activation link.{% endtrans %}</p>
-  <p>{% trans %}Thanks for your patience!{% endtrans %}</p>
-{% endblock %}

+ 0 - 7
templates/_message/users/registration/registrations_off.html

@@ -1,7 +0,0 @@
-{% extends "_message/base.html" %}
-{% load i18n %}
-
-{% block content %}
-  <div class="alert-icon"><span><i class="icon-info-sign icon-white"></i></span></div>
-  <p><strong>{% trans %}We are sorry but new members registrations are currently not available.{% endtrans %}</strong></p>
-{% endblock %}

+ 0 - 7
templates/_message/users/search_empty.html

@@ -1,7 +0,0 @@
-{% extends "_message/base.html" %}
-{% load i18n %}
-
-{% block content %}
-  <div class="alert-icon"><span><i class="icon-remove icon-white"></i></span></div>
-  <p>{% trans %}To search users you have to enter user name in search field.{% endtrans %}</p>
-{% endblock %}

+ 0 - 2
templates/admin/admin/form.html

@@ -2,8 +2,6 @@
 {% load i18n %}
 {% load l10n %}
 {% load url from future %}
-{% from "admin/macros.html" import page_title %}
-{% import "admin/messages.html" as messages_theme %}
 {% import "_forms.html" as form_theme with context %}
 
 {% block action_body %}

+ 2 - 3
templates/admin/admin/layout.html

@@ -2,8 +2,7 @@
 {% load i18n %}
 {% load l10n %}
 {% load url from future %}
-{% from "admin/macros.html" import page_title %}
-{% import "admin/messages.html" as messages_theme %}
+{% from "admin/macros.html" import page_title, draw_message %}
 {% import "_forms.html" as form_theme with context %}
 
 {% block title %}{% if admin.actions[0].id != action.id and action.name -%}
@@ -23,7 +22,7 @@
 <h2>{% if target %}{{ target }} <small>{{ action.name }}</small>{% else %}{{ action.name }}{% if action.help %} <small>{{ action.help }}</small>{% endif %}{% endif %}</h2>
 {% endif %}
 {% if message %}
-{{ messages_theme.draw_message(message, 'alert-form') }}
+{{ draw_message(message, 'alert-form') }}
 {% endif %}
 {% block page_help %}{% endblock %}
 {% block action_body %}

+ 0 - 2
templates/admin/admin/list.html

@@ -2,8 +2,6 @@
 {% load i18n %}
 {% load l10n %}
 {% load url from future %}
-{% from "admin/macros.html" import page_title %}
-{% import "admin/messages.html" as messages_theme %}
 {% import "_forms.html" as form_theme with context %}
 
 {% block action_body %}

+ 2 - 2
templates/admin/banning/list.html

@@ -6,8 +6,8 @@
 {% block table_row scoped %}
   <td class="lead-cell">
   	<strong>{{ item.ban }}</strong> <span class="label {% if item.type == 0 -%}label-inverse">{% trans %}Username and E-mail{% endtrans %}
-  	{%- elif item.type == 1 -%}label-important">{% trans %}Username and E-mail{% endtrans %}
-  	{%- elif item.type == 2 -%}label-warning">{% trans %}Username{% endtrans %}
+  	{%- elif item.type == 1 -%}label-important">{% trans %}Username{% endtrans %}
+  	{%- elif item.type == 2 -%}label-warning">{% trans %}E-mail{% endtrans %}
   	{%- else -%}label-info">{% trans %}IP Address{% endtrans %}
   	{%- endif %}</span>
   </td>

+ 8 - 6
templates/admin/error403.html

@@ -8,13 +8,15 @@
 <div class="row">
   <div class="span6 offset3">
     <div class="page-header">
-      <h2>{% if title %}{{ title }}{% else %}{% trans %}Permission denied{% endtrans %}{% endif %} <small>403</small></h2>
+      <h2>{% trans %}Permission denied{% endtrans %} <small>{% trans %}Error 403{% endtrans %}</small></h2>
     </div>
-{% if message %}
-    {% if message.is_basic() %}<p>{{ message.message }}</p>{% else %}{% include message.tpl %}{% endif %}
-{% else %}
-    <p>{% trans %}You dont have permission to see this page.{% endtrans %}</p>
-{% endif %}
+    {% block message %}
+    {% if message %}
+    <p class="lead">{{ message }}</p>
+    {% else %}
+    <p class="lead">{% trans %}You don't have permission to see this page.{% endtrans %}</p>
+    {% endif %}
+    {% endblock %}
     <ul class="unstyled">
       <li><i class="icon-arrow-left"></i> <a href="#" class="go-back">{% trans %}Return to previous page{% endtrans %}</a></li>
     </ul>

+ 8 - 6
templates/admin/error404.html

@@ -8,13 +8,15 @@
 <div class="row">
   <div class="span6 offset3">
     <div class="page-header">
-      <h2>{% if title %}{{ title }}{% else %}{% trans %}Page not found{% endtrans %}{% endif %} <small>404</small></h2>
+      <h2>{% trans %}Page not found{% endtrans %} <small>{% trans %}Error 404{% endtrans %}</small></h2>
     </div>
-{% if message %}
-    {% if message.is_basic() %}<p>{{ message.message }}</p>{% else %}{% include message.tpl %}{% endif %}
-{% else %}
-    <p>{% trans %}The page you are looking for could not be found.{% endtrans %}</p>
-{% endif %}
+    {% block message %}
+    {% if message %}
+    <p class="lead">{{ message }}</p>
+    {% else %}
+    <p class="lead">{% trans %}The page you are looking for could not be found.{% endtrans %}</p>
+    {% endif %}
+    {% endblock %}
     <ul class="unstyled">
       <li><i class="icon-arrow-left"></i> <a href="#" class="go-back">{% trans %}Return to previous page{% endtrans %}</a></li>
     </ul>

+ 0 - 11
templates/admin/index.html

@@ -1,11 +0,0 @@
-{% extends "admin/layout.html" %}
-{% load i18n %}
-{% load url from future %}
-
-{% block title %}{% trans %}Unimplemented Admin Action!{% endtrans %}{% endblock %}
-
-{% block content %}
-<div class="page-header">
-  <h1>This action is not implemented!</h1>
-</div>
-{% endblock %}

+ 2 - 2
templates/admin/layout.html

@@ -1,7 +1,7 @@
 {% extends "admin/base.html" %}
 {% load i18n %}
 {% load url from future %}
-{% import "admin/messages.html" as messages_theme %}
+{% from "admin/macros.html" import messages_list %}
 
 {% block body %}
 <div id="page-top" class="navbar navbar-static-top navbar-sections">
@@ -34,7 +34,7 @@
   
   {% if messages %}
   <div class="alerts-global">
-  	{{ messages_theme.messages_list(messages) }}
+  	{{ messages_list(messages) }}
   </div>{% endif %}
   {% block content %}
   {% endblock %}

+ 23 - 1
templates/admin/macros.html

@@ -2,4 +2,26 @@
 
 {% macro page_title(title='', parent='', page=0) -%}
 {% if parent %}{{ parent }}: {% endif %}{% if title %}{{ title }}{% if page > 1 %} ({% trans page=page %}{{ page }} page{% endtrans %}){% endif %} - {% endif %}{% trans %}Misago Admin{% endtrans %}
-{%- endmacro %}
+{%- endmacro %}
+
+{# Messages list marco #}
+{% macro messages_list(messages) %}{% if messages %}<div class="alerts-list">{% for message in messages %}
+  {{ draw_message(message) }}
+{% endfor %}</div>{% endif %}
+{% endmacro %}
+
+{# Render single message #}
+{% macro draw_message(message, class='') %}
+  <div class="alert alert-{{ message.type }}{% if class %} {{ class }}{% endif %}">
+  	{{ draw_message_icon(message) }} <p><strong>{{ message.message }}</strong></p>
+  </div>
+{%- endmacro %}
+
+{# Render single message #}
+{% macro draw_message_icon(message) -%}
+  	<div class="alert-icon"><span><i class="icon-{% if message.type == 'error' -%}remove
+  		{%- elif message.type == 'success' -%}ok
+  		{%- elif message.type == 'info' -%}info-sign
+  		{%- else -%}warning-sign
+  		{%- endif %} icon-white"></i></span></div>
+{%- endmacro %}

+ 0 - 1
templates/admin/message/base.html

@@ -1 +0,0 @@
-{% block content %}{{ message.message }}{% endblock %}

+ 0 - 7
templates/admin/message/form_contains_errors.html

@@ -1,7 +0,0 @@
-{% extends "admin/message/base.html" %}
-{% load i18n %}
-
-{% block content %}
-  <div class="alert-icon"><span><i class="icon-remove icon-white"></i></span></div>
-  <p>{% trans %}Form contains errors. Please try again.{% endtrans %}</p>
-{% endblock %}

+ 0 - 7
templates/admin/message/invalid_request.html

@@ -1,7 +0,0 @@
-{% extends "admin/message/base.html" %}
-{% load i18n %}
-
-{% block content %}
-  <div class="alert-icon"><span><i class="icon-remove icon-white"></i></span></div>
-  <p>{% trans %}Request authorization is invalid. Resubmit your form.{% endtrans %}</p>
-{% endblock %}

+ 0 - 9
templates/admin/message/security/bad_credentials.html

@@ -1,9 +0,0 @@
-{% extends "admin/message/base.html" %}
-{% load i18n %}
-{% load url from future %}
-
-{% block content %}
-  <div class="alert-icon"><span><i class="icon-remove icon-white"></i></span></div>
-  <p>{% trans %}Your e-mail address or password is incorrect. Please try again.{% endtrans %}</p>
-  <p class="protip"><a href="{% url 'forgot_password' %}">{% trans %}Click here if you forgot your sign in credentials.{% endtrans %}</a></p>
-{% endblock %}

+ 0 - 8
templates/admin/message/security/not_admin.html

@@ -1,8 +0,0 @@
-{% extends "admin/message/base.html" %}
-{% load i18n %}
-{% load url from future %}
-
-{% block content %}
-  <div class="alert-icon"><span><i class="icon-remove icon-white"></i></span></div>
-  <p>{% trans %}You need to be administrator to access admin control panel.{% endtrans %}</p>
-{% endblock %}

+ 0 - 7
templates/admin/message/security/signed_in.html

@@ -1,7 +0,0 @@
-{% extends "admin/message/base.html" %}
-{% load i18n %}
-
-{% block content %}
-  <div class="alert-icon"><span><i class="icon-ok icon-white"></i></span></div>
-  <p><strong>{% trans username=message.user.username %}Welcome back, {{ username }}!{% endtrans %}</strong> {% trans %}You have signed in successfully.{% endtrans %}</p>
-{% endblock %}

+ 0 - 7
templates/admin/message/security/signed_out.html

@@ -1,7 +0,0 @@
-{% extends "admin/message/base.html" %}
-{% load i18n %}
-
-{% block content %}
-  <div class="alert-icon"><span><i class="icon-info-sign icon-white"></i></span></div>
-  <p>{% trans %}You have been signed out.{% endtrans %}</p>
-{% endblock %}

+ 0 - 17
templates/admin/messages.html

@@ -1,17 +0,0 @@
-{# Messages list marco #}
-{% macro messages_list(messages) %}{% if messages %}<div class="alerts-list">{% for message in messages %}
-  {{ draw_message(message) }}
-{% endfor %}</div>{% endif %}
-{% endmacro %}
-
-{# Render single message #}
-{% macro draw_message(message, class='') %}
-  <div class="alert alert-{{ message.type }}{% if class %} {{ class }}{% endif %}">{% if message.is_basic() %}
-  	<div class="alert-icon"><span><i class="icon-{% if message.type == 'error' -%}remove
-  		{%- elif message.type == 'success' -%}ok
-  		{%- elif message.type == 'info' -%}info-sign
-  		{%- else -%}warning-sign
-  		{%- endif %} icon-white"></i></span></div> <p>{{ message.message }}</p>{% else %}
-  		{% include message.tpl %}{% endif %}
-  </div>
-{%- endmacro %}

+ 2 - 2
templates/admin/settings/search_results.html

@@ -1,13 +1,13 @@
 {% extends "admin/settings/settings.html" %}
 {% load i18n %}
 {% load url from future %}
-{% from "admin/macros.html" import page_title %}
+{% from "admin/macros.html" import page_title, draw_message %}
 
 {% block title %}{{ page_title(title=_('Search Results'), parent=_('Settings')) }}{% endblock %}
 
 {% block action %}
 <h2 class="sidepanel-header">{% trans %}Search Results{% endtrans %}</h2>{% if message %}
-{{ messages_theme.draw_message(message, 'alert-form') }}{% endif %}
+{{ draw_message(message, 'alert-form') }}{% endif %}
 {% for setting in found_settings %}
 <h4>{{ _(setting.name) }} <small>{{ _(setting.group.name) }}</small></h4>
 {%- if setting.description %}<p>{{ _(setting.description) }}</p>{% endif -%}

+ 2 - 3
templates/admin/settings/settings.html

@@ -1,8 +1,7 @@
 {% extends "admin/layout.html" %}
 {% load i18n %}
 {% load url from future %}
-{% from "admin/macros.html" import page_title %}
-{% import "admin/messages.html" as messages_theme %}
+{% from "admin/macros.html" import page_title, draw_message %}
 {% import "_forms.html" as form_theme with context %}
 
 {% block title %}{{ page_title(title=_(active_group.name), parent=_('Settings')) }}{% endblock %}
@@ -26,7 +25,7 @@
   </div>
   <div class="span9">{% block action %}
   	<h2 class="sidepanel-header">{{ _(active_group.name) }}</h2>{% if message %}
-  	{{ messages_theme.draw_message(message, 'alert-form') }}
+  	{{ draw_message(message, 'alert-form') }}
   	{% endif %}{% if active_group.description %}
   	<p>{{ _(active_group.description) }}</p>{% endif %}
     <form class="form-vertical" action="{% url 'admin_settings' group_id=active_group.id, group_slug=active_group.key %}" method="post">

+ 5 - 3
templates/admin/signin.html

@@ -2,15 +2,17 @@
 {% load i18n %}
 {% load url from future %}
 {% import "_forms.html" as form_theme with context %}
-      
-{% block title %}{% trans %}Sign In{% endtrans %}{% endblock %}
+{% from "admin/macros.html" import page_title, draw_message_icon %}
+
+{% block title %}{{ page_title(title=_('Sign In')) }}{% endblock %}
 
 {% block header %}<strong>Misago</strong> {% trans %}Board Administration{% endtrans %}{% endblock %}
       
 {% block content %}
           {% if message %}
           <div class="alert alert-{{ message.type }} block-alert">
-            {% include message.tpl %}
+            {{ draw_message_icon(message) }}
+	        <p><strong>{{ message.message }}</strong></p>
           </div>
           {% endif %}
           <form class="form-vertical" action="{{ admin_index|url() }}" method="post">

+ 5 - 7
templates/sora/error403.html

@@ -8,15 +8,13 @@
 <div class="row">
   <div class="span8 offset2 side-bar">
     <div class="page-header">
-      <h1>{% if title %}{{ title }}{% else %}{% trans %}Permission denied{% endtrans %}{% endif %}</h1>
+      <h1>{% trans %}Permission denied{% endtrans %} <small>{% trans %}Error 403{% endtrans %}</small></h1>
     </div>
-{% if message %}{% set special=true %}
-    <div class="lead">
-      {% include message.tpl %}
-    </div>
-{% else %}
+    {% if message %}
+    <p class="lead">{{ message }}</p>
+    {% else %}
     <p class="lead">{% trans %}You dont have permission to see this page.{% endtrans %}</p>
-{% endif %}
+    {% endif %}
     <ul class="unstyled">
       <li><i class="icon-home"></i> <a href="{% url 'index' %}">{% trans %}Return to board index{% endtrans %}</a></li>
       <li><i class="icon-arrow-left"></i> <a href="#" class="go-back">{% trans %}Return to previous page{% endtrans %}</a></li>

+ 37 - 0
templates/sora/error403_banned.html

@@ -0,0 +1,37 @@
+{% extends "sora/layout.html" %}
+{% load i18n %}
+{% load url from future %}
+{% import "sora/macros.html" as macros with context %}
+
+{% block title %}{{ macros.page_title(title=_('You are banned')) }}{% endblock %}
+      
+{% block content %}
+<div class="row">
+  <div class="span8 offset2 side-bar">
+    <div class="page-header">
+      <h1>{% trans %}You are banned{% endtrans %}</h1>
+    </div>
+    {% if banned_user %}
+    {% if ban.reason_user %}
+    <p class="lead">{% trans username=banned_user.username %}{{ username }}, your account has been banned for following reason:{% endtrans %}</p>
+    {{ ban.reason_user|markdown|safe }}
+    {% else %}
+    <p class="lead">{% trans username=banned_user.username %}{{ username }}, your account has been banned.{% endtrans %}</p>
+    {% endif %}
+    {% else %}
+    {% if ban.reason_user %}
+    <p class="lead">{% trans %}Guest, your IP Address has been banned from accessing this page for following reason:{% endtrans %}</p>
+    {{ ban.reason_user|markdown|safe }}
+    {% else %}
+    <p class="lead">{% trans %}Guest, your IP Address has been banned from accessing this page.{% endtrans %}</p>
+    {% endif %}
+    {% endif %}
+    {% if ban.expires %}
+    <p>{% trans ban_expires=ban.expires|date(f.DATE_FORMAT) %}Your ban will expire on {{ ban_expires }}{% endtrans %}</p>
+    {% endif %}
+    <ul class="unstyled">
+      <li><i class="icon-home"></i> <a href="{% url 'index' %}">{% trans %}Return to board index{% endtrans %}</a></li>
+    </ul>
+  </div>
+</div>
+{% endblock %}

+ 5 - 7
templates/sora/error404.html

@@ -8,15 +8,13 @@
 <div class="row">
   <div class="span8 offset2 side-bar">
     <div class="page-header">
-      <h1>{% if title %}{{ title }}{% else %}{% trans %}Page not found{% endtrans %}{% endif %}</h1>
+      <h1>{% trans %}Page not found{% endtrans %} <small>{% trans %}Error 404{% endtrans %}</small></h1>
     </div>
-{% if message %}{% set special=true %}
-    <div class="lead">
-      {% include message.tpl %}
-    </div>
-{% else %}
+    {% if message %}
+    <p class="lead">{{ message }}</p>
+    {% else %}
     <p class="lead">{% trans %}The page you are looking for could not be found.{% endtrans %}</p>
-{% endif %}
+    {% endif %}
     <ul class="unstyled">
       <li><i class="icon-home"></i> <a href="{% url 'index' %}">{% trans %}Return to board index{% endtrans %}</a></li>
       <li><i class="icon-arrow-left"></i> <a href="#" class="go-back">{% trans %}Return to previous page{% endtrans %}</a></li>

+ 4 - 3
templates/sora/layout.html

@@ -1,6 +1,7 @@
 {% extends "sora/base.html" %}
 {% load i18n %}
 {% load url from future %}
+{% from "sora/macros.html" import messages_list %}
 
 {% block body %}
 {% include "sora/userbar.html" with context %}
@@ -23,9 +24,9 @@
 
 <div class="container">
   {% if messages %}
-  <div class="alerts-global">{% for message in messages %}
-  	<div class="alert alert-{{ message.type }}">{% include message.tpl %}</div>
-  {% endfor %}</div>{% endif %}
+  <div class="alerts-global">
+  	{{ messages_list(messages) }}
+  </div>{% endif %}
   
   {% block content %}
   {% endblock %}

+ 23 - 1
templates/sora/macros.html

@@ -1,5 +1,27 @@
 {% load i18n %}
 
 {% macro page_title(title='', parent='', page=0) -%}
-{% if parent %}{{ parent }}: {% endif %}{% if title %}{{ title }}{% if page > 1 %} ({% trans page=page %}{{ page }} page{% endtrans %}){% endif %} | {% endif %}{{ settings.boart_title }}
+{% if parent %}{{ parent }}: {% endif %}{% if title %}{{ title }}{% if page > 1 %} ({% trans page=page %}{{ page }} page{% endtrans %}){% endif %} | {% endif %}{{ settings.board_name }}
+{%- endmacro %}
+
+{# Messages list marco #}
+{% macro messages_list(messages) %}{% if messages %}<div class="alerts-list">{% for message in messages %}
+  {{ draw_message(message) }}
+{% endfor %}</div>{% endif %}
+{% endmacro %}
+
+{# Render single message #}
+{% macro draw_message(message, class='') %}
+  <div class="alert alert-{{ message.type }}{% if class %} {{ class }}{% endif %}">
+  	{{ draw_message_icon(message) }} <p><strong>{{ message.message }}</strong></p>
+  </div>
+{%- endmacro %}
+
+{# Render single message #}
+{% macro draw_message_icon(message) -%}
+  	<div class="alert-icon"><span><i class="icon-{% if message.type == 'error' -%}remove
+  		{%- elif message.type == 'success' -%}ok
+  		{%- elif message.type == 'info' -%}info-sign
+  		{%- else -%}warning-sign
+  		{%- endif %} icon-white"></i></span></div>
 {%- endmacro %}

+ 8 - 2
templates/sora/signin.html

@@ -2,8 +2,9 @@
 {% load i18n %}
 {% load url from future %}
 {% import "_forms.html" as form_theme with context %}
+{% import "sora/macros.html" as macros with context %}
 
-{% block title %}{% trans %}Sign In{% endtrans %} | {{ settings.board_name }}{% endblock %}
+{% block title %}{{ macros.page_title(title=_('Sign In')) }}{% endblock %}
       
 {% block content %}
 <div class="page-header">
@@ -13,7 +14,12 @@
   <div class="span6">
     <div class="well">
 	  {% if message %}<div class="alert alert-form alert-error">
-	    {% include message.tpl %}
+  	    {{ macros.draw_message_icon(message) }}
+	    <p><strong>{{ message.message }}</strong></p>{% if bad_password %}
+	    <p class="protip"><a href="{% url 'forgot_password' %}">{% trans %}Click here if you forgot your sign in credentials.{% endtrans %}</a></p>{% endif %}{% if not_active %}
+	    <p class="protip"><a href="{% url 'send_activation' %}">{% trans %}Click here if you didn't receive activation e-mail.{% endtrans %}</a></p>{% endif %}{% if banned_account.reason_user %}
+	    {{ banned_account.reason_user|markdown|safe }}{% endif %}{% if banned_account.expires %}
+        <p class="protip">{% trans ban_expires=banned_account.expires|date(f.DATE_FORMAT) %}Your ban will expire on {{ ban_expires }}{% endtrans %}</p>{% endif %}
 	  </div>{% endif %}
 	  <form class="form-horizontal" action="{% url 'sign_in' %}" method="post">
 	    <div class="form-container">

+ 3 - 4
templates/sora/users/forgot_password.html

@@ -2,8 +2,9 @@
 {% load i18n %}
 {% load url from future %}
 {% import "_forms.html" as form_theme with context %}
+{% import "sora/macros.html" as macros with context %}
 
-{% block title %}{% trans %}Request New Password{% endtrans %} | {{ settings.board_name }}{% endblock %}
+{% block title %}{{ macros.page_title(title=_('Request New Password')) }}{% endblock %}
 
 {% block content %}
 <div class="row">
@@ -11,9 +12,7 @@
     <div class="page-header">
       <h1>{% trans %}Request New Password{% endtrans %}</h1>
     </div>
-    {% if message %}<div class="alert alert-form alert-error">
-      {% include message.tpl %}
-    </div>{% endif %}
+    {% if message %}{{ macros.draw_message(message, 'alert-form') }}{% endif %}
     <form action="{% url 'forgot_password' %}" method="post">
       <div class="form-container">
         {{ form_theme.form_widget(form, width=8) }}

+ 10 - 4
templates/sora/users/list.html

@@ -2,8 +2,15 @@
 {% load i18n %}
 {% load url from future %}
 {% import "_forms.html" as form_theme with context %}
+{% import "sora/macros.html" as macros with context %}
 
-{% block title %}{% if in_search %}{% trans %}Search Users{% endtrans %} | {% elif active_rank %}{{ _(active_rank.name) }} | {% endif %}{% trans %}Users List{% endtrans %} | {{ settings.board_name }}{% endblock %}
+{% block title %}{% if in_search -%}
+{{ macros.page_title(title=_('Search Users'), parent=_('Users List')) }}
+{% elif active_rank %}
+{{ macros.page_title(title=_(active_rank.name), parent=_('Users List')) }}
+{%- else -%}
+{{ macros.page_title(title=_('Users List')) }}
+{%- endif %}{% endblock %}
 
 {% block content %}
 <div class="page-header header-tabbed">
@@ -19,9 +26,8 @@
   	</li>
   </ul>
 </div>
-<h2>{% if in_search %}{% trans %}Search Users{% endtrans %}{% elif active_rank %}{{ _(active_rank.name) }}{% endif %}</h2>{% if message %}<div class="alert alert-form alert-error">
-  {% include message.tpl %}
-</div>{% endif %}
+<h2>{% if in_search %}{% trans %}Search Users{% endtrans %}{% elif active_rank %}{{ _(active_rank.name) }}{% endif %}</h2>
+{% if message %}{{ macros.draw_message(message, 'alert-form') }}{% endif %}
 
 {% if in_search and not message and users|length > 0 %}
 <p>{% trans %}We couldn't find a member with name you entered, so we present you with some other members with names similiar to one you searched for in hopes that one of them will turn out to be member you are looking for.{% endtrans %}</p>

+ 2 - 1
templates/sora/users/profile.html

@@ -2,8 +2,9 @@
 {% load i18n %}
 {% load url from future %}
 {% import "_forms.html" as form_theme with context %}
+{% import "sora/macros.html" as macros with context %}
 
-{% block title %}{% trans username=profile.username %}Member Profile: {{ username }}{% endtrans %} | {{ settings.board_name }}{% endblock %}
+{% block title %}{{ macros.page_title(title=username, parent=_('Users')) }}{% endblock %}
 
 {% block content %}
 <div class="page-header">

+ 3 - 4
templates/sora/users/register.html

@@ -2,8 +2,9 @@
 {% load i18n %}
 {% load url from future %}
 {% import "_forms.html" as form_theme with context %}
+{% import "sora/macros.html" as macros with context %}
 
-{% block title %}{% trans %}Register new account{% endtrans %} | {{ settings.board_name }}{% endblock %}
+{% block title %}{{ macros.page_title(title=_('Register new account')) }}{% endblock %}
 
 {% block content %}
 <div class="row">
@@ -11,9 +12,7 @@
     <div class="page-header">
       <h1>{% trans %}Register new account{% endtrans %}</h1>
     </div>
-    {% if message %}<div class="alert alert-form alert-error">
-      {% include message.tpl %}
-    </div>{% endif %}
+    {% if message %}{{ macros.draw_message(message, 'alert-form') }}{% endif %}
     <form action="{% url 'register' %}" method="post">
       <div class="form-container">
         {{ form_theme.form_widget(form, width=8) }}

+ 3 - 4
templates/sora/users/resend_activation.html

@@ -2,8 +2,9 @@
 {% load i18n %}
 {% load url from future %}
 {% import "_forms.html" as form_theme with context %}
+{% import "sora/macros.html" as macros with context %}
 
-{% block title %}{% trans %}Request new Activation E-mail{% endtrans %} | {{ settings.board_name }}{% endblock %}
+{% block title %}{{ macros.page_title(title=_('Request new Activation E-mail')) }}{% endblock %}
 
 {% block content %}
 <div class="row">
@@ -11,9 +12,7 @@
     <div class="page-header">
       <h1>{% trans %}Request new Activation E-mail{% endtrans %}</h1>
     </div>
-    {% if message %}<div class="alert alert-form alert-error">
-      {% include message.tpl %}
-    </div>{% endif %}
+    {% if message %}{{ macros.draw_message(message, 'alert-form') }}{% endif %}
     <form action="{% url 'send_activation' %}" method="post">
       <div class="form-container">
         {{ form_theme.form_widget(form, width=8) }}

+ 2 - 1
templates/sora/users/usercp/avatar.html

@@ -1,8 +1,9 @@
 {% extends "sora/users/usercp/usercp.html" %}
 {% load i18n %}
 {% load url from future %}
+{% import "sora/macros.html" as macros with context %}
 
-{% block title %}{% trans %}Change your Avatar{% endtrans %} | {{ settings.board_name }}{% endblock %}
+{% block title %}{{ macros.page_title(title=_('Change your Avatar')) }}{% endblock %}
 
 {% block action %}
 <h2>{% trans %}Change your Avatar{% endtrans %}</h2>

+ 2 - 1
templates/sora/users/usercp/avatar_banned.html

@@ -1,8 +1,9 @@
 {% extends "sora/users/usercp/usercp.html" %}
 {% load i18n %}
 {% load url from future %}
+{% import "sora/macros.html" as macros with context %}
 
-{% block title %}{% trans %}Change your Avatar{% endtrans %} | {{ settings.board_name }}{% endblock %}
+{% block title %}{{ macros.page_title(title=_('Change your Avatar')) }}{% endblock %}
 
 {% block action %}
 <h2>{% trans %}Change your Avatar{% endtrans %}</h2>

+ 2 - 1
templates/sora/users/usercp/credentials.html

@@ -1,8 +1,9 @@
 {% extends "sora/users/usercp/usercp.html" %}
 {% load i18n %}
 {% load url from future %}
+{% import "sora/macros.html" as macros with context %}
 
-{% block title %}{% trans %}Change Sign-In Credentials{% endtrans %} | {{ settings.board_name }}{% endblock %}
+{% block title %}{{ macros.page_title(title=_('Change your Sign-In Credentials')) }}{% endblock %}
 
 {% block action %}
 {{ super() }}

+ 3 - 2
templates/sora/users/usercp/ignored.html

@@ -1,10 +1,11 @@
 {% extends "sora/users/usercp/usercp.html" %}
 {% load i18n %}
 {% load url from future %}
+{% import "sora/macros.html" as macros with context %}
 
-{% block title %}{% trans %}Manage Ignored Members{% endtrans %} | {{ settings.board_name }}{% endblock %}
+{% block title %}{{ macros.page_title(title=_('Ignored Members List')) }}{% endblock %}
 
 {% block action %}
 {{ super() }}
-<h2>{% trans %}Manage Ignored Members{% endtrans %}</h2>
+<h2>{% trans %}Ignored Members List{% endtrans %}</h2>
 {% endblock %}

+ 2 - 2
templates/sora/users/usercp/options.html

@@ -1,9 +1,9 @@
 {% extends "sora/users/usercp/usercp.html" %}
 {% load i18n %}
 {% load url from future %}
-{% import "_forms.html" as form_theme with context %}
+{% import "sora/macros.html" as macros with context %}
 
-{% block title %}{% trans %}Change Forum Options{% endtrans %} | {{ settings.board_name }}{% endblock %}
+{% block title %}{{ macros.page_title(title=_('Change Forum Options')) }}{% endblock %}
 
 {% block action %}
 {{ super() }}

+ 2 - 1
templates/sora/users/usercp/signature.html

@@ -1,8 +1,9 @@
 {% extends "sora/users/usercp/usercp.html" %}
 {% load i18n %}
 {% load url from future %}
+{% import "sora/macros.html" as macros with context %}
 
-{% block title %}{% trans %}Change your Signature{% endtrans %} | {{ settings.board_name }}{% endblock %}
+{% block title %}{{ macros.page_title(title=_('Edit your Signature')) }}{% endblock %}
 
 {% block action %}
 {{ super() }}

+ 3 - 2
templates/sora/users/usercp/signature_banned.html

@@ -1,12 +1,13 @@
 {% extends "sora/users/usercp/usercp.html" %}
 {% load i18n %}
 {% load url from future %}
+{% import "sora/macros.html" as macros with context %}
 
-{% block title %}{% trans %}Change your Signature{% endtrans %} | {{ settings.board_name }}{% endblock %}
+{% block title %}{{ macros.page_title(title=_('Edit your Signature')) }}{% endblock %}
 
 {% block action %}
 {{ super() }}
-<h2>{% trans %}Change your Signature{% endtrans %}</h2>
+<h2>{% trans %}Edit your Signature{% endtrans %}</h2>
 {% if user.signature_ban_reason_user %}
 <p class="lead">{% trans username=user.username %}{{ username }}, your ability to edit your signature has been removed for following reason:{% endtrans %}</p>
 {{ user.signature_ban_reason_user|markdown|safe }}

+ 1 - 3
templates/sora/users/usercp/usercp.html

@@ -2,8 +2,6 @@
 {% load i18n %}
 {% load url from future %}
 
-{% block title %}{% trans %}Options{% endtrans %} | {{ settings.board_name }}{% endblock %}
-
 {% block content %}
 <div class="page-header">
   <h1>{% trans %}Your Control Panel{% endtrans %}</h1>
@@ -18,7 +16,7 @@
         <li{% if tab == 'signature' %} class="active"{% endif %}><a href="{% url 'usercp_signature' %}"><i class="icon-align-left"></i> {% trans %}Edit Signature{% endtrans %}</a></li>
   	    <li{% if tab == 'credentials' %} class="active"{% endif %}><a href="{% url 'usercp_credentials' %}"><i class="icon-edit"></i> {% trans %}Change E-mail or Password{% endtrans %}</a></li>
   	    <li{% if tab == 'username' %} class="active"{% endif %}><a href="{% url 'usercp_username' %}"><i class="icon-user"></i> {% trans %}Change Username{% endtrans %}</a></li>
-        <li{% if tab == 'ignored' %} class="active"{% endif %}><a href="{% url 'usercp_ignored' %}"><i class="icon-eye-close"></i> {% trans %}Ignore People{% endtrans %}</a></li>
+        <li{% if tab == 'ignored' %} class="active"{% endif %}><a href="{% url 'usercp_ignored' %}"><i class="icon-eye-close"></i> {% trans %}Ignored Members List{% endtrans %}</a></li>
       </ul>
     </div>
   </div>

+ 2 - 1
templates/sora/users/usercp/username.html

@@ -1,8 +1,9 @@
 {% extends "sora/users/usercp/usercp.html" %}
 {% load i18n %}
 {% load url from future %}
+{% import "sora/macros.html" as macros with context %}
 
-{% block title %}{% trans %}Change your Username{% endtrans %} | {{ settings.board_name }}{% endblock %}
+{% block title %}{{ macros.page_title(title=_('Change your Username')) }}{% endblock %}
 
 {% block action %}
 {{ super() }}