bans.py 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. import re
  2. from django.conf import settings
  3. from django.db import models
  4. from django.utils import timezone
  5. from django.utils.translation import ugettext_lazy as _
  6. from misago.core.utils import time_amount
  7. __all__ = [
  8. 'BAN_USERNAME', 'BAN_EMAIL', 'BAN_IP', 'BANS_CHOICES', 'Ban', 'BanCache'
  9. ]
  10. BAN_USERNAME = 0
  11. BAN_EMAIL = 1
  12. BAN_IP = 2
  13. BANS_CHOICES = (
  14. (BAN_USERNAME, _('Username')),
  15. (BAN_EMAIL, _('E-mail address')),
  16. (BAN_IP, _('IP Address')),
  17. )
  18. class BansManager(models.Manager):
  19. def is_ip_banned(self, ip):
  20. return self.check_ban(ip=ip)
  21. def is_username_banned(self, username):
  22. return self.check_ban(username=username)
  23. def is_email_banned(self, email):
  24. return self.check_ban(email=email)
  25. def find_ban(self, username=None, email=None, ip=None):
  26. tests = []
  27. if username:
  28. username = username.lower()
  29. tests.append(BAN_USERNAME)
  30. if email:
  31. email = email.lower()
  32. tests.append(BAN_EMAIL)
  33. if ip:
  34. tests.append(BAN_IP)
  35. queryset = self.filter(is_valid=True)
  36. if len(tests) == 1:
  37. queryset = queryset.filter(test=tests[0])
  38. elif tests:
  39. queryset = queryset.filter(test__in=tests)
  40. for ban in queryset.order_by('-id').iterator():
  41. if (ban.test == BAN_USERNAME and username and
  42. ban.test_value(username)):
  43. return ban
  44. elif ban.test == BAN_EMAIL and email and ban.test_value(email):
  45. return ban
  46. elif ban.test == BAN_IP and ip and ban.test_value(ip):
  47. return ban
  48. return None
  49. class Ban(models.Model):
  50. test = models.PositiveIntegerField(default=BAN_USERNAME, db_index=True)
  51. banned_value = models.CharField(max_length=255, db_index=True)
  52. user_message = models.TextField(null=True, blank=True)
  53. staff_message = models.TextField(null=True, blank=True)
  54. valid_until = models.DateField(null=True, blank=True, db_index=True)
  55. is_valid = models.BooleanField(default=True, db_index=True)
  56. objects = BansManager()
  57. def save(self, *args, **kwargs):
  58. self.banned_value = self.banned_value.lower()
  59. self.is_valid = not self.is_expired
  60. return super(Ban, self).save(*args, **kwargs)
  61. @property
  62. def test_name(self):
  63. return BANS_CHOICES[self.test][1]
  64. @property
  65. def name(self):
  66. return self.banned_value
  67. @property
  68. def is_expired(self):
  69. if self.valid_until:
  70. return self.valid_until < timezone.now().date()
  71. else:
  72. return False
  73. def test_value(self, value):
  74. if '*' in self.banned_value:
  75. regex = re.escape(self.banned_value).replace('\*', '(.*?)')
  76. return re.search('^%s$' % regex, value) != None
  77. else:
  78. return self.banned_value == value
  79. class BanCache(models.Model):
  80. user = models.OneToOneField(settings.AUTH_USER_MODEL, primary_key=True)
  81. is_banned = models.BooleanField(default=False)
  82. bans_version = models.PositiveIntegerField(default=0)
  83. valid_until = models.DateField(null=True, blank=True)