Rafał Pitoń 8 лет назад
Родитель
Сommit
38a6847cb0

+ 0 - 18
misago/acl/migrations/0003_default_roles.py

@@ -111,14 +111,6 @@ def create_default_roles(apps, schema_editor):
                 'can_see_hidden_users': 1,
             },
 
-            # warnings
-            'misago.users.permissions.warnings': {
-                'can_see_other_users_warnings': 1,
-                'can_warn_users': 1,
-                'can_cancel_warnings': 1,
-                'can_be_warned': 0,
-            },
-
             # attachments
             'misago.threads.permissions.attachments': {
                 'max_attachment_size': 8 * 1024,
@@ -155,16 +147,6 @@ def create_default_roles(apps, schema_editor):
     )
 
     Role.objects.create(
-        name=_("See warnings"),
-        permissions={
-            # warnings
-            'misago.users.permissions.warnings': {
-                'can_see_other_users_warnings': 1,
-            },
-        }
-    )
-
-    Role.objects.create(
         name=_("Renaming users"),
         permissions={
             # rename users

+ 0 - 1
misago/conf/defaults.py

@@ -116,7 +116,6 @@ DEFAULT_CONTEXT_PROCESSORS = (
 MISAGO_ACL_EXTENSIONS = (
     'misago.users.permissions.account',
     'misago.users.permissions.profiles',
-    'misago.users.permissions.warnings',
     'misago.users.permissions.moderation',
     'misago.users.permissions.delete',
     'misago.categories.permissions',

+ 4 - 31
misago/users/admin.py

@@ -5,17 +5,10 @@ from django.utils.translation import ugettext_lazy as _
 from .djangoadmin import User, UserAdminModel
 from .views.admin.bans import BansList, DeleteBan, EditBan, NewBan
 from .views.admin.ranks import (
-    DefaultRank,
-    DeleteRank,
-    EditRank,
-    MoveDownRank,
-    MoveUpRank,
-    NewRank,
-    RanksList,
-    RankUsers
-)
-from .views.admin.users import DeleteAccountStep, DeletePostsStep, DeleteThreadsStep, EditUser, NewUser, UsersList
-from .views.admin.warnings import DeleteWarning, EditWarning, MoveDownWarning, MoveUpWarning, NewWarning, WarningsList
+    DefaultRank, DeleteRank, EditRank, MoveDownRank, MoveUpRank, NewRank,
+    RanksList, RankUsers)
+from .views.admin.users import (
+    DeleteAccountStep, DeletePostsStep, DeleteThreadsStep, EditUser, NewUser, UsersList)
 
 
 # register misago user model in django admin panel
@@ -62,17 +55,6 @@ class MisagoAdminExtension(object):
             url(r'^delete/(?P<pk>\d+)/$', DeleteBan.as_view(), name='delete'),
         )
 
-        # Warnings
-        urlpatterns.namespace(r'^warnings/', 'warnings', 'users')
-        urlpatterns.patterns('users:warnings',
-            url(r'^$', WarningsList.as_view(), name='index'),
-            url(r'^new/$', NewWarning.as_view(), name='new'),
-            url(r'^edit/(?P<pk>\d+)/$', EditWarning.as_view(), name='edit'),
-            url(r'^move/down/(?P<pk>\d+)/$', MoveDownWarning.as_view(), name='down'),
-            url(r'^move/up/(?P<pk>\d+)/$', MoveUpWarning.as_view(), name='up'),
-            url(r'^delete/(?P<pk>\d+)/$', DeleteWarning.as_view(), name='delete'),
-        )
-
     def register_navigation_nodes(self, site):
         site.add_node(
             name=_("Users"),
@@ -108,12 +90,3 @@ class MisagoAdminExtension(object):
             namespace='misago:admin:users:bans',
             link='misago:admin:users:bans:index',
         )
-
-        site.add_node(
-            name=_("Warning levels"),
-            icon='fa fa-exclamation-triangle',
-            parent='misago:admin:users',
-            after='misago:admin:users:bans:index',
-            namespace='misago:admin:users:warnings',
-            link='misago:admin:users:warnings:index',
-        )

+ 2 - 42
misago/users/forms/admin.py

@@ -8,13 +8,8 @@ from misago.core import forms, threadstore
 from misago.core.validators import validate_sluggable
 
 from ..models import (
-    AUTO_SUBSCRIBE_CHOICES,
-    BANS_CHOICES,
-    PRIVATE_THREAD_INVITES_LIMITS_CHOICES,
-    RESTRICTIONS_CHOICES,
-    Ban,
-    Rank,
-    WarningLevel
+    AUTO_SUBSCRIBE_CHOICES, BANS_CHOICES, PRIVATE_THREAD_INVITES_LIMITS_CHOICES,
+    Ban, Rank
 )
 from ..validators import validate_email, validate_password, validate_username
 
@@ -603,38 +598,3 @@ class SearchBansForm(forms.Form):
             queryset = queryset.filter(is_checked=False)
 
         return queryset
-
-
-"""
-Warning levels
-"""
-class WarningLevelForm(forms.ModelForm):
-    name = forms.CharField(label=_("Level name"), max_length=255)
-    length_in_minutes = forms.IntegerField(
-        label=_("Length in minutes"),
-        min_value=0,
-        help_text=_(
-            "Enter number of minutes since this warning level was "
-            "imposed on member until it's reduced, or 0 to make "
-            "this warning level permanent."
-        )
-    )
-    restricts_posting_replies = forms.TypedChoiceField(
-        label=_("Posting replies"),
-        coerce=int,
-        choices=RESTRICTIONS_CHOICES
-    )
-    restricts_posting_threads = forms.TypedChoiceField(
-        label=_("Posting threads"),
-        coerce=int,
-        choices=RESTRICTIONS_CHOICES
-    )
-
-    class Meta:
-        model = WarningLevel
-        fields = [
-            'name',
-            'length_in_minutes',
-            'restricts_posting_replies',
-            'restricts_posting_threads',
-        ]

+ 0 - 15
misago/users/forms/moderation.py

@@ -11,21 +11,6 @@ from misago.core import forms
 from ..bans import ban_user
 
 
-class WarnUserForm(forms.Form):
-    reason = forms.CharField(label=_("Warning Reason"),
-                             help_text=_("Optional message explaining why "
-                                         "this warning was given."),
-                             widget=forms.Textarea(attrs={'rows': 8}),
-                             required=False)
-
-    def clean_reason(self):
-        data = self.cleaned_data['reason']
-        if len(data) > 2000:
-            message = _("Warning reason can't be longer than 2000 characters.")
-            raise forms.ValidationError(message)
-        return data
-
-
 class ModerateAvatarForm(forms.ModelForm):
     is_avatar_locked = forms.YesNoSwitch()
     avatar_lock_user_message = forms.CharField(required=False)

+ 0 - 42
misago/users/migrations/0001_initial.py

@@ -61,11 +61,8 @@ class Migration(migrations.Migration):
                 ('is_signature_locked', models.BooleanField(default=False)),
                 ('signature_lock_user_message', models.TextField(null=True, blank=True)),
                 ('signature_lock_staff_message', models.TextField(null=True, blank=True)),
-                ('warning_level', models.PositiveIntegerField(default=0)),
-                ('warning_level_update_on', models.DateTimeField(null=True, blank=True)),
                 ('following', models.PositiveIntegerField(default=0)),
                 ('followers', models.PositiveIntegerField(default=0)),
-                ('new_notifications', models.PositiveIntegerField(default=0)),
                 ('limits_private_thread_invites_to', models.PositiveIntegerField(default=0)),
                 ('unread_private_threads', models.PositiveIntegerField(default=0)),
                 ('sync_unread_private_threads', models.BooleanField(default=False)),
@@ -213,43 +210,4 @@ class Migration(migrations.Migration):
             },
             bases=(models.Model,),
         ),
-        migrations.CreateModel(
-            name='WarningLevel',
-            fields=[
-                ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
-                ('name', models.CharField(max_length=255)),
-                ('level', models.PositiveIntegerField(default=1, db_index=True)),
-                ('length_in_minutes', models.PositiveIntegerField(default=0)),
-                ('restricts_posting_replies', models.PositiveIntegerField(default=0)),
-                ('restricts_posting_threads', models.PositiveIntegerField(default=0)),
-            ],
-            options={
-            },
-            bases=(models.Model,),
-        ),
-        migrations.CreateModel(
-            name='UserWarning',
-            fields=[
-                ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
-                ('reason', models.TextField(null=True, blank=True)),
-                ('given_on', models.DateTimeField(default=django.utils.timezone.now)),
-                ('giver_username', models.CharField(max_length=255)),
-                ('giver_slug', models.CharField(max_length=255)),
-                ('is_canceled', models.BooleanField(default=False)),
-                ('canceled_on', models.DateTimeField(null=True, blank=True)),
-                ('canceler_username', models.CharField(max_length=255)),
-                ('canceler_slug', models.CharField(max_length=255)),
-                ('canceler', models.ForeignKey(related_name='warnings_canceled', on_delete=django.db.models.deletion.SET_NULL, blank=True, to=settings.AUTH_USER_MODEL, null=True)),
-                ('giver', models.ForeignKey(related_name='warnings_given', on_delete=django.db.models.deletion.SET_NULL, blank=True, to=settings.AUTH_USER_MODEL, null=True)),
-                ('user', models.ForeignKey(related_name='warnings', to=settings.AUTH_USER_MODEL)),
-            ],
-            options={
-            },
-            bases=(models.Model,),
-        ),
-        CreatePartialIndex(
-            field='UserWarning.is_canceled',
-            index_name='misago_userwarning_is_canceled_partial',
-            condition='is_canceled = FALSE',
-        ),
     ]

+ 0 - 1
misago/users/models/__init__.py

@@ -5,4 +5,3 @@ from .activityranking import *
 from .avatar import *
 from .avatargallery import *
 from .ban import *
-from .warnings import *

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

@@ -253,9 +253,6 @@ class User(AbstractBaseUser, PermissionsMixin):
     signature_lock_user_message = models.TextField(null=True, blank=True)
     signature_lock_staff_message = models.TextField(null=True, blank=True)
 
-    warning_level = models.PositiveIntegerField(default=0)
-    warning_level_update_on = models.DateTimeField(null=True, blank=True)
-
     followers = models.PositiveIntegerField(default=0)
     following = models.PositiveIntegerField(default=0)
 
@@ -268,8 +265,6 @@ class User(AbstractBaseUser, PermissionsMixin):
         symmetrical=False,
     )
 
-    new_notifications = models.PositiveIntegerField(default=0)
-
     limits_private_thread_invites_to = models.PositiveIntegerField(
         default=LIMITS_PRIVATE_THREAD_INVITES_TO_NONE
     )

+ 0 - 148
misago/users/models/warnings.py

@@ -1,148 +0,0 @@
-from collections import OrderedDict
-from datetime import timedelta
-
-from django.conf import settings
-from django.db import models
-from django.utils import timezone
-from django.utils.encoding import python_2_unicode_compatible
-from django.utils.translation import ugettext_lazy as _
-
-from misago.core import threadstore
-from misago.core.cache import cache
-
-
-__all__ = [
-    'RESTRICT_NO', 'RESTRICT_MODERATOR_REVIEW', 'RESTRICT_DISALLOW',
-    'RESTRICTIONS_CHOICES', 'WarningLevel', 'UserWarning'
-]
-
-
-CACHE_NAME = 'misago_warning_levels'
-
-RESTRICT_NO = 0
-RESTRICT_MODERATOR_REVIEW = 1
-RESTRICT_DISALLOW = 2
-
-
-RESTRICTIONS_CHOICES = (
-    (RESTRICT_NO, _("No restrictions")),
-    (RESTRICT_MODERATOR_REVIEW, _("Review by moderator")),
-    (RESTRICT_DISALLOW, _("Disallowed")),
-)
-
-
-class WarningLevelManager(models.Manager):
-    def dict(self):
-        return self.get_levels_from_threadstore()
-
-    def get_levels_from_threadstore(self):
-        levels = threadstore.get(CACHE_NAME, 'nada')
-        if levels == 'nada':
-            levels = self.get_levels_from_cache()
-            threadstore.set(CACHE_NAME, levels)
-        return levels
-
-    def get_levels_from_cache(self):
-        levels = cache.get(CACHE_NAME, 'nada')
-        if levels == 'nada':
-            levels = self.get_levels_from_database()
-            cache.set(CACHE_NAME, levels)
-        return levels
-
-    def get_levels_from_database(self):
-        levels = [(0, None)]
-        for level, obj in enumerate(self.order_by('level')):
-            levels.append((level + 1, obj))
-        return OrderedDict(levels)
-
-
-@python_2_unicode_compatible
-class WarningLevel(models.Model):
-    name = models.CharField(max_length=255)
-    level = models.PositiveIntegerField(default=1, db_index=True)
-    length_in_minutes = models.PositiveIntegerField(default=0)
-    restricts_posting_replies = models.PositiveIntegerField(
-        default=RESTRICT_NO)
-    restricts_posting_threads = models.PositiveIntegerField(
-        default=RESTRICT_NO)
-
-    objects = WarningLevelManager()
-
-    def __str__(self):
-        return self.name
-
-    def save(self, *args, **kwargs):
-        if not self.pk:
-            self.set_level()
-
-        super(WarningLevel, self).save(*args, **kwargs)
-        cache.delete(CACHE_NAME)
-
-    def delete(self, *args, **kwargs):
-        super(WarningLevel, self).delete(*args, **kwargs)
-        cache.delete(CACHE_NAME)
-
-    @property
-    def has_restrictions(self):
-        return self.restricts_posting_replies or self.restricts_posting_threads
-
-    @property
-    def is_replying_moderated(self):
-        return self.restricts_posting_replies == RESTRICT_MODERATOR_REVIEW
-
-    @property
-    def is_replying_disallowed(self):
-        return self.restricts_posting_replies == RESTRICT_DISALLOW
-
-    @property
-    def is_starting_threads_moderated(self):
-        return self.restricts_posting_threads == RESTRICT_MODERATOR_REVIEW
-
-    @property
-    def is_starting_threads_disallowed(self):
-        return self.restricts_posting_threads == RESTRICT_DISALLOW
-
-    def set_level(self):
-        try:
-            self.level = WarningLevel.objects.latest('level').level + 1
-        except WarningLevel.DoesNotExist:
-            self.level = 1
-
-
-class UserWarning(models.Model):
-    user = models.ForeignKey(settings.AUTH_USER_MODEL,
-                             related_name="warnings")
-    reason = models.TextField(null=True, blank=True)
-    given_on = models.DateTimeField(default=timezone.now)
-    giver = models.ForeignKey(settings.AUTH_USER_MODEL,
-                              null=True, blank=True,
-                              on_delete=models.SET_NULL,
-                              related_name="warnings_given")
-    giver_username = models.CharField(max_length=255)
-    giver_slug = models.CharField(max_length=255)
-    is_canceled = models.BooleanField(default=False)
-    canceled_on = models.DateTimeField(null=True, blank=True)
-    canceler = models.ForeignKey(settings.AUTH_USER_MODEL,
-                                 null=True, blank=True,
-                                 on_delete=models.SET_NULL,
-                                 related_name="warnings_canceled")
-    canceler_username = models.CharField(max_length=255)
-    canceler_slug = models.CharField(max_length=255)
-
-    def cancel(self, canceler):
-        self.is_canceled = True
-        self.canceled_on = timezone.now()
-        self.canceler = canceler
-        self.canceler_username = canceler.username
-        self.canceler_slug = canceler.slug
-
-        self.save(update_fields=(
-            'is_canceled',
-            'canceled_on',
-            'canceler',
-            'canceler_username',
-            'canceler_slug',
-        ))
-
-    def is_expired(self, valid_for):
-        return timezone.now() > self.given_on + timedelta(minutes=valid_for)

+ 0 - 147
misago/users/permissions/warnings.py

@@ -1,147 +0,0 @@
-from django.contrib.auth import get_user_model
-from django.core.exceptions import PermissionDenied
-from django.utils.translation import ugettext_lazy as _
-
-from misago.acl import algebra
-from misago.acl.decorators import return_boolean
-from misago.acl.models import Role
-from misago.core import forms
-
-from ..models import UserWarning
-from .decorators import authenticated_only
-
-
-"""
-Admin Permissions Form
-"""
-NO_OWNED_ALL = ((0, _("No")), (1, _("Owned")), (2, _("All")))
-
-
-class LimitedPermissionsForm(forms.Form):
-    legend = _("Warnings")
-
-    can_see_other_users_warnings = forms.YesNoSwitch(label=_("Can see other users warnings"))
-
-
-class PermissionsForm(LimitedPermissionsForm):
-    can_warn_users = forms.YesNoSwitch(label=_("Can warn users"))
-    can_be_warned = forms.YesNoSwitch(label=_("Can be warned"), initial=False)
-    can_cancel_warnings = forms.TypedChoiceField(
-        label=_("Can cancel warnings"),
-        coerce=int,
-        choices=NO_OWNED_ALL,
-        initial=0
-    )
-    can_delete_warnings = forms.TypedChoiceField(
-        label=_("Can delete warnings"),
-        coerce=int,
-        choices=NO_OWNED_ALL,
-        initial=0
-    )
-
-
-def change_permissions_form(role):
-    if isinstance(role, Role):
-        if role.special_role == 'anonymous':
-            return LimitedPermissionsForm
-        else:
-            return PermissionsForm
-    else:
-        return None
-
-
-"""
-ACL Builder
-"""
-def build_acl(acl, roles, key_name):
-    new_acl = {
-        'can_see_other_users_warnings': 0,
-        'can_warn_users': 0,
-        'can_cancel_warnings': 0,
-        'can_delete_warnings': 0,
-        'can_be_warned': 1,
-    }
-    new_acl.update(acl)
-
-    return algebra.sum_acls(new_acl, roles=roles, key=key_name,
-        can_see_other_users_warnings=algebra.greater,
-        can_warn_users=algebra.greater,
-        can_cancel_warnings=algebra.greater,
-        can_delete_warnings=algebra.greater,
-        can_be_warned=algebra.lower
-    )
-
-
-"""
-ACL's for targets
-"""
-def add_acl_to_user(user, target):
-    target_acl = target.acl_
-
-    target_acl['can_see_warnings'] = can_see_warnings(user, target)
-    target_acl['can_warn'] = can_warn_user(user, target)
-    target_acl['can_cancel_warnings'] = False
-    target_acl['can_delete_warnings'] = False
-
-    if target_acl['can_warn']:
-        target_acl['can_moderate'] = True
-
-
-def add_acl_to_warning(user, target):
-    target.acl['can_cancel'] = can_cancel_warning(user, target)
-    target.acl['can_delete'] = can_delete_warning(user, target)
-
-    can_moderate = target.acl['can_cancel'] or target.acl['can_delete']
-    target.acl['can_moderate'] = can_moderate
-
-
-def register_with(registry):
-    registry.acl_annotator(get_user_model(), add_acl_to_user)
-    registry.acl_annotator(UserWarning, add_acl_to_warning)
-
-
-"""
-ACL tests
-"""
-def allow_see_warnings(user, target):
-    if user.is_authenticated() and user.pk == target.pk:
-        return None
-    if not user.acl['can_see_other_users_warnings']:
-        raise PermissionDenied(_("You can't see other users warnings."))
-can_see_warnings = return_boolean(allow_see_warnings)
-
-
-@authenticated_only
-def allow_warn_user(user, target):
-    if not user.acl['can_warn_users']:
-        raise PermissionDenied(_("You can't warn users."))
-    if not user.is_superuser and (target.is_staff or target.is_superuser):
-        raise PermissionDenied(_("You can't warn administrators."))
-    if not target.acl['can_be_warned']:
-        message = _("%(user)s can't be warned.")
-        raise PermissionDenied(message % {'user': target.username})
-can_warn_user = return_boolean(allow_warn_user)
-
-
-@authenticated_only
-def allow_cancel_warning(user, target):
-    if user.is_anonymous() or not user.acl['can_cancel_warnings']:
-        raise PermissionDenied(_("You can't cancel warnings."))
-    if user.acl['can_cancel_warnings'] == 1:
-        if target.giver_id != user.pk:
-            message = _("You can't cancel warnings issued by other users.")
-            raise PermissionDenied(message)
-    if target.is_canceled:
-        raise PermissionDenied(_("This warning is already canceled."))
-can_cancel_warning = return_boolean(allow_cancel_warning)
-
-
-@authenticated_only
-def allow_delete_warning(user, target):
-    if user.is_anonymous() or not user.acl['can_delete_warnings']:
-        raise PermissionDenied(_("You can't delete warnings."))
-    if user.acl['can_delete_warnings'] == 1:
-        if target.giver_id != user.pk:
-            message = _("You can't delete warnings issued by other users.")
-            raise PermissionDenied(message)
-can_delete_warning = return_boolean(allow_delete_warning)

+ 0 - 1
misago/users/serializers/user.py

@@ -51,7 +51,6 @@ class AuthenticatedUserSerializer(serializers.ModelSerializer):
             'short_title',
             'rank',
             'avatars',
-            'new_notifications',
             'limits_private_thread_invites_to',
             'unread_private_threads',
             'subscribe_to_started_threads',

+ 0 - 8
misago/users/signals.py

@@ -13,11 +13,3 @@ def handle_name_change(sender, **kwargs):
     sender.user_renames.update(
         changed_by_username=sender.username
     )
-    sender.warnings_given.update(
-        giver_username=sender.username,
-        giver_slug=sender.slug
-    )
-    sender.warnings_canceled.update(
-        canceler_username=sender.username,
-        canceler_slug=sender.slug
-    )

+ 0 - 170
misago/users/tests/test_warningadmin_views.py

@@ -1,170 +0,0 @@
-from django.urls import reverse
-
-from misago.admin.testutils import AdminTestCase
-
-from ..models import WarningLevel
-
-
-class WarningsAdminViewsTests(AdminTestCase):
-    def test_link_registered(self):
-        """admin nav contains warning levels link"""
-        response = self.client.get(
-            reverse('misago:admin:users:accounts:index'))
-
-        response = self.client.get(response['location'])
-        self.assertContains(response, reverse('misago:admin:users:warnings:index'))
-
-    def test_list_view(self):
-        """warning levels list view returns 200"""
-        response = self.client.get(
-            reverse('misago:admin:users:warnings:index'))
-
-        self.assertEqual(response.status_code, 200)
-        self.assertContains(response, 'No warning levels')
-
-    def test_new_view(self):
-        """new warning level view has no showstoppers"""
-        response = self.client.get(
-            reverse('misago:admin:users:warnings:new'))
-        self.assertEqual(response.status_code, 200)
-
-        response = self.client.post(
-            reverse('misago:admin:users:warnings:new'),
-            data={
-                'name': 'Test Level',
-                'length_in_minutes': 60,
-                'restricts_posting_replies': '1',
-                'restricts_posting_threads': '1',
-            })
-        self.assertEqual(response.status_code, 302)
-
-        response = self.client.get(
-            reverse('misago:admin:users:warnings:index'))
-        self.assertEqual(response.status_code, 200)
-        self.assertContains(response, 'Test Level')
-
-    def test_edit_view(self):
-        """edit warning level view has no showstoppers"""
-        self.client.post(
-            reverse('misago:admin:users:warnings:new'),
-            data={
-                'name': 'Test Level',
-                'length_in_minutes': 60,
-                'restricts_posting_replies': '1',
-                'restricts_posting_threads': '1',
-            })
-
-        test_level = WarningLevel.objects.get(level=1)
-
-        response = self.client.get(
-            reverse('misago:admin:users:warnings:edit',
-                    kwargs={'pk': test_level.pk}))
-        self.assertEqual(response.status_code, 200)
-        self.assertContains(response, test_level.name)
-
-        response = self.client.post(
-            reverse('misago:admin:users:warnings:edit',
-                    kwargs={'pk': test_level.pk}),
-            data={
-                'name': 'Edited Level',
-                'length_in_minutes': 5,
-                'restricts_posting_replies': '0',
-                'restricts_posting_threads': '0',
-            })
-        self.assertEqual(response.status_code, 302)
-
-        test_level = WarningLevel.objects.get(level=1)
-        response = self.client.get(
-            reverse('misago:admin:users:warnings:index'))
-        self.assertEqual(response.status_code, 200)
-        self.assertContains(response, test_level.name)
-        self.assertNotContains(response, 'Test Level')
-
-    def test_move_up_view(self):
-        """move warning level up view has no showstoppers"""
-        self.client.post(
-            reverse('misago:admin:users:warnings:new'),
-            data={
-                'name': 'Level 1',
-                'length_in_minutes': 5,
-                'restricts_posting_replies': '0',
-                'restricts_posting_threads': '0',
-            })
-        self.client.post(
-            reverse('misago:admin:users:warnings:new'),
-            data={
-                'name': 'Level 2',
-                'length_in_minutes': 5,
-                'restricts_posting_replies': '0',
-                'restricts_posting_threads': '0',
-            })
-
-        test_level_1 = WarningLevel.objects.get(level=1)
-        test_level_2 = WarningLevel.objects.get(level=2)
-
-        response = self.client.post(
-            reverse('misago:admin:users:warnings:up',
-                    kwargs={'pk': test_level_2.pk}))
-        self.assertEqual(response.status_code, 302)
-
-        changed_level_1 = WarningLevel.objects.get(id=test_level_1.pk)
-        changed_level_2 = WarningLevel.objects.get(id=test_level_2.pk)
-        self.assertEqual(test_level_1.level, changed_level_2.level)
-        self.assertEqual(test_level_2.level, changed_level_1.level)
-
-    def test_move_down_view(self):
-        """move warning level down view has no showstoppers"""
-        self.client.post(
-            reverse('misago:admin:users:warnings:new'),
-            data={
-                'name': 'Level 1',
-                'length_in_minutes': 5,
-                'restricts_posting_replies': '0',
-                'restricts_posting_threads': '0',
-            })
-        self.client.post(
-            reverse('misago:admin:users:warnings:new'),
-            data={
-                'name': 'Level 2',
-                'length_in_minutes': 5,
-                'restricts_posting_replies': '0',
-                'restricts_posting_threads': '0',
-            })
-
-        test_level_1 = WarningLevel.objects.get(level=1)
-        test_level_2 = WarningLevel.objects.get(level=2)
-
-        response = self.client.post(
-            reverse('misago:admin:users:warnings:down',
-                    kwargs={'pk': test_level_1.pk}))
-        self.assertEqual(response.status_code, 302)
-
-        changed_level_1 = WarningLevel.objects.get(id=test_level_1.pk)
-        changed_level_2 = WarningLevel.objects.get(id=test_level_2.pk)
-        self.assertEqual(test_level_1.level, changed_level_2.level)
-        self.assertEqual(test_level_2.level, changed_level_1.level)
-
-    def test_delete_view(self):
-        """delete warning level view has no showstoppers"""
-        self.client.post(
-            reverse('misago:admin:users:warnings:new'),
-            data={
-                'name': 'Test Level',
-                'length_in_minutes': 60,
-                'restricts_posting_replies': '1',
-                'restricts_posting_threads': '1',
-            })
-
-        test_level = WarningLevel.objects.get(level=1)
-
-        response = self.client.post(
-            reverse('misago:admin:users:warnings:delete',
-                    kwargs={'pk': test_level.pk}))
-        self.assertEqual(response.status_code, 302)
-
-        self.client.get(reverse('misago:admin:users:warnings:index'))
-        response = self.client.get(
-            reverse('misago:admin:users:warnings:index'))
-        self.assertEqual(response.status_code, 200)
-
-        self.assertNotContains(response, test_level.name)

+ 0 - 72
misago/users/tests/test_warnings.py

@@ -1,72 +0,0 @@
-from datetime import timedelta
-
-from django.contrib.auth import get_user_model
-from django.test import TestCase
-from django.utils import timezone
-
-from misago.core import threadstore
-from misago.core.cache import cache
-
-from .. import warnings
-from ..models import UserWarning, WarningLevel
-
-
-class WarningsTests(TestCase):
-    def setUp(self):
-        User = get_user_model()
-        self.test_mod = User.objects.create_user('Modo', 'mod@mod.com',
-                                                 'Pass.123')
-        self.test_user = User.objects.create_user('Bob', 'bob@bob.com',
-                                                  'Pass.123')
-
-    def test_warnings(self):
-        """user warning levels is obtained"""
-        threadstore.clear()
-        cache.clear()
-
-        self.assertTrue(warnings.is_user_warning_level_max(self.test_user))
-
-        levels = (
-            WarningLevel.objects.create(name="Level 1"),
-            WarningLevel.objects.create(name="Level 2"),
-            WarningLevel.objects.create(name="Level 3"),
-            WarningLevel.objects.create(name="Level 4"),
-            WarningLevel.objects.create(name="Level 5"),
-            WarningLevel.objects.create(name="Level 6"),
-            WarningLevel.objects.create(name="Level 7"),
-            WarningLevel.objects.create(name="Level 8")
-        )
-
-        self.assertEqual(WarningLevel.objects.count(), 8)
-
-        threadstore.clear()
-        cache.clear()
-
-        for level, warning in enumerate(levels):
-            warnings.warn_user(self.test_mod, self.test_user, "bawww")
-
-            user_level = warnings.get_user_warning_level(self.test_user)
-            user_level_obj = warnings.get_user_warning_obj(self.test_user)
-
-            self.assertEqual(user_level, level + 1)
-            self.assertEqual(user_level_obj.name, levels[level].name)
-            self.assertEqual(self.test_user.warning_level, level + 1)
-
-        self.assertTrue(warnings.is_user_warning_level_max(self.test_user))
-
-        previous_level = user_level
-        for warning in self.test_user.warnings.all():
-            warnings.cancel_warning(self.test_mod, self.test_user, warning)
-            user_level = warnings.get_user_warning_level(self.test_user)
-            self.assertEqual(user_level + 1, previous_level)
-            previous_level = user_level
-
-        self.assertEqual(0, warnings.get_user_warning_level(self.test_user))
-
-
-class WarningModelTests(TestCase):
-    def test_warning_is_expired(self):
-        """warning knows wheter or not its expired"""
-        warning = UserWarning(given_on=timezone.now() - timedelta(days=6))
-        self.assertTrue(warning.is_expired(60))
-        self.assertFalse(warning.is_expired(14 * 24 * 3600))

+ 0 - 72
misago/users/views/admin/warnings.py

@@ -1,72 +0,0 @@
-from django.contrib import messages
-from django.utils.translation import ugettext_lazy as _
-
-from misago.admin.views import generic
-
-from ...forms.admin import WarningLevelForm
-from ...models import WarningLevel
-
-
-class WarningsAdmin(generic.AdminBaseMixin):
-    root_link = 'misago:admin:users:warnings:index'
-    Model = WarningLevel
-    Form = WarningLevelForm
-    templates_dir = 'misago/admin/warnings'
-    message_404 = _("Requested warning level does not exist.")
-
-
-class WarningsList(WarningsAdmin, generic.ListView):
-    ordering = (('level', None),)
-
-
-class NewWarning(WarningsAdmin, generic.ModelFormView):
-    message_submit = _('New warning level "%(name)s" has been saved.')
-
-
-class EditWarning(WarningsAdmin, generic.ModelFormView):
-    message_submit = _('Warning level "%(name)s" has been edited.')
-
-
-class DeleteWarning(WarningsAdmin, generic.ButtonView):
-    def button_action(self, request, target):
-        target.delete()
-        message = _('Warning level "%(name)s" has been deleted.')
-        messages.success(request, message % {'name': target.name})
-
-
-class MoveDownWarning(WarningsAdmin, generic.ButtonView):
-    def button_action(self, request, target):
-        try:
-            other_target = WarningLevel.objects.filter(level__gt=target.level)
-            other_target = other_target.earliest('level')
-        except WarningLevel.DoesNotExist:
-            other_target = None
-
-        if other_target:
-            other_target.level, target.level = target.level, other_target.level
-            other_target.save(update_fields=['level'])
-            target.save(update_fields=['level'])
-
-            message = _('Warning level "%(name)s" has '
-                        'been moved below "%(other)s".')
-            targets_names = {'name': target.name, 'other': other_target.name}
-            messages.success(request, message % targets_names)
-
-
-class MoveUpWarning(WarningsAdmin, generic.ButtonView):
-    def button_action(self, request, target):
-        try:
-            other_target = WarningLevel.objects.filter(level__lt=target.level)
-            other_target = other_target.latest('level')
-        except WarningLevel.DoesNotExist:
-            other_target = None
-
-        if other_target:
-            other_target.level, target.level = target.level, other_target.level
-            other_target.save(update_fields=['level'])
-            target.save(update_fields=['level'])
-
-            message = _('Warning level "%(name)s" has '
-                        'been moved above "%(other)s".')
-            targets_names = {'name': target.name, 'other': other_target.name}
-            messages.success(request, message % targets_names)

+ 0 - 1
misago/users/views/profile.py

@@ -24,7 +24,6 @@ from ..permissions.profiles import allow_block_user, allow_follow_user
 from ..serializers import BanDetailsSerializer, UserProfileSerializer, UserSerializer
 from ..serializers.usernamechange import UsernameChangeSerializer
 from ..viewmodels import UserPosts, UserThreads
-from ..warnings import get_user_warning_level, get_user_warning_obj, get_warning_levels
 
 
 def profile_view(f):

+ 0 - 106
misago/users/warnings.py

@@ -1,106 +0,0 @@
-from datetime import timedelta
-
-from django.utils import timezone
-
-from .models import WarningLevel
-
-
-def get_warning_levels():
-    return WarningLevel.objects.dict()
-
-
-def fetch_user_valid_warnings(user):
-    levels = get_warning_levels()
-    max_level = len(levels) - 1
-
-    if not max_level:
-        return []
-
-    # build initial list of valid exceptions
-    queryset = user.warnings.exclude(is_canceled=True)
-    warnings = [w for w in queryset.order_by('-id')[:max_level]]
-
-    if not warnings:
-        return []
-
-    # expire levels
-    active_warnings = []
-    for length, level in enumerate(list(levels.values())[1:]):
-        length += 1
-        level_warnings = []
-        if level.length_in_minutes:
-            cutoff_date = timezone.now()
-            cutoff_date -= timedelta(minutes=level.length_in_minutes)
-            for warning in warnings:
-                if warning.given_on >= cutoff_date:
-                    level_warnings.append(warning)
-            if len(level_warnings) == length:
-                active_warnings = level_warnings[:length]
-            else:
-                break
-        else:
-            active_warnings = warnings[:length]
-    return active_warnings
-
-
-def update_user_warning_level(user):
-    warnings = fetch_user_valid_warnings(user)
-    user.warning_level = len(warnings)
-
-    levels = get_warning_levels()
-
-    if user.warning_level and levels[user.warning_level].length_in_minutes:
-        level_length = levels[user.warning_level].length_in_minutes
-        next_check_date = warnings[-1].given_on
-        next_check_date += timedelta(minutes=level_length)
-        user.warning_level_update_on = next_check_date
-    else:
-        user.warning_level_update_on = None
-
-    user.save(update_fields=('warning_level', 'warning_level_update_on'))
-
-
-def get_user_warning_level(user):
-    warning_level_expiration = user.warning_level_update_on
-    if warning_level_expiration and warning_level_expiration < timezone.now():
-        update_user_warning_level(user)
-    return user.warning_level
-
-
-def get_user_warning_obj(user):
-    warning_level = get_user_warning_level(user)
-    if warning_level:
-        return get_warning_levels()[warning_level]
-    else:
-        return None
-
-
-def is_user_warning_level_max(user):
-    user_level = get_user_warning_level(user)
-    levels = len(get_warning_levels())
-    return user_level == levels - 1
-
-
-def warn_user(moderator, user, reason=''):
-    warning = user.warnings.create(reason=reason,
-                                   giver=moderator,
-                                   giver_username=moderator.username,
-                                   giver_slug=moderator.slug)
-
-    user.warning_level_update_on = timezone.now()
-    update_user_warning_level(user)
-    return warning
-
-
-def cancel_warning(moderator, user, warning):
-    warning.cancel(moderator)
-
-    user.warning_level_update_on = timezone.now()
-    update_user_warning_level(user)
-
-
-def delete_warning(moderator, user, warning):
-    warning.delete()
-
-    user.warning_level_update_on = timezone.now()
-    update_user_warning_level(user)