bans.py 3.7 KB

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