123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138 |
- from datetime import date, timedelta
- import re
- from django.conf import settings
- from django.db import models
- from django.utils import timezone
- from django.utils.translation import ugettext_lazy as _
- from misago.core import cachebuster
- from misago.core.utils import time_amount
- __all__ = [
- 'BAN_USERNAME', 'BAN_EMAIL', 'BAN_IP', 'BANS_CHOICES', 'Ban', 'BanCache'
- ]
- BAN_CACHEBUSTER = 'misago_bans'
- BAN_USERNAME = 0
- BAN_EMAIL = 1
- BAN_IP = 2
- BANS_CHOICES = (
- (BAN_USERNAME, _('Username')),
- (BAN_EMAIL, _('E-mail address')),
- (BAN_IP, _('IP address')),
- )
- class BansManager(models.Manager):
- def is_ip_banned(self, ip):
- return self.check_ban(ip=ip)
- def is_username_banned(self, username):
- return self.check_ban(username=username)
- def is_email_banned(self, email):
- return self.check_ban(email=email)
- def invalidate_cache(self):
- cachebuster.invalidate(BAN_CACHEBUSTER)
- def find_ban(self, username=None, email=None, ip=None):
- tests = []
- if username:
- username = username.lower()
- tests.append(BAN_USERNAME)
- if email:
- email = email.lower()
- tests.append(BAN_EMAIL)
- if ip:
- tests.append(BAN_IP)
- queryset = self.filter(is_valid=True)
- if len(tests) == 1:
- queryset = queryset.filter(test=tests[0])
- elif tests:
- queryset = queryset.filter(test__in=tests)
- for ban in queryset.order_by('-id').iterator():
- if (ban.test == BAN_USERNAME and username and
- ban.test_value(username)):
- return ban
- elif ban.test == BAN_EMAIL and email and ban.test_value(email):
- return ban
- elif ban.test == BAN_IP and ip and ban.test_value(ip):
- return ban
- else:
- raise Ban.DoesNotExist('no valid ban for values has been found')
- class Ban(models.Model):
- test = models.PositiveIntegerField(default=BAN_USERNAME, db_index=True)
- banned_value = models.CharField(max_length=255, db_index=True)
- user_message = models.TextField(null=True, blank=True)
- staff_message = models.TextField(null=True, blank=True)
- valid_until = models.DateField(null=True, blank=True, db_index=True)
- is_valid = models.BooleanField(default=True, db_index=True)
- objects = BansManager()
- def save(self, *args, **kwargs):
- self.banned_value = self.banned_value.lower()
- self.is_valid = not self.is_expired
- return super(Ban, self).save(*args, **kwargs)
- @property
- def test_name(self):
- return BANS_CHOICES[self.test][1]
- @property
- def name(self):
- return self.banned_value
- @property
- def is_expired(self):
- if self.valid_until:
- return self.valid_until < timezone.now().date()
- else:
- return False
- def test_value(self, value):
- if '*' in self.banned_value:
- regex = re.escape(self.banned_value).replace('\*', '(.*?)')
- return re.search('^%s$' % regex, value) != None
- else:
- return self.banned_value == value
- def lift(self):
- self.valid_until = (timezone.now() - timedelta(days=1)).date()
- class BanCache(models.Model):
- user = models.OneToOneField(
- settings.AUTH_USER_MODEL, primary_key=True, related_name='ban_cache')
- ban = models.ForeignKey(
- Ban, null=True, blank=True, on_delete=models.SET_NULL)
- bans_version = models.PositiveIntegerField(default=0)
- user_message = models.TextField(null=True, blank=True)
- staff_message = models.TextField(null=True, blank=True)
- valid_until = models.DateField(null=True, blank=True)
- @property
- def is_banned(self):
- return bool(self.ban)
- @property
- def is_valid(self):
- version_is_valid = cachebuster.is_valid(BAN_CACHEBUSTER,
- self.bans_version)
- not_expired = not self.valid_until or self.valid_until < date.today()
- return version_is_valid and not_expired
|