bans.py 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. """
  2. API for testing values for bans
  3. Calling this instead of Ban.objects.find_ban is preffered, if you don't want
  4. to use validate_X_banned validators
  5. """
  6. from datetime import date, datetime
  7. from misago.core import cachebuster
  8. from misago.users.models import Ban, BanCache
  9. BAN_CACHE_SESSION_KEY = 'misago_ip_check'
  10. BAN_VERSION_KEY = 'misago_bans'
  11. def get_username_ban(username):
  12. try:
  13. return Ban.objects.find_ban(username=username)
  14. except Ban.DoesNotExist:
  15. return None
  16. def get_email_ban(email):
  17. try:
  18. return Ban.objects.find_ban(email=email)
  19. except Ban.DoesNotExist:
  20. return None
  21. def get_ip_ban(ip):
  22. try:
  23. return Ban.objects.find_ban(ip=ip)
  24. except Ban.DoesNotExist:
  25. return None
  26. def get_user_ban(user):
  27. """
  28. This function checks if user is banned
  29. When user model is available, this is preffered to calling
  30. get_email_ban(user.email) and get_username_ban(user.username)
  31. because it sets ban cache on user model
  32. """
  33. try:
  34. ban_cache = user.ban_cache
  35. if not ban_cache.is_valid:
  36. _set_user_ban_cache(user)
  37. except BanCache.DoesNotExist:
  38. user.ban_cache = BanCache(user=user)
  39. ban_cache = _set_user_ban_cache(user)
  40. if ban_cache.is_banned:
  41. return ban_cache
  42. else:
  43. return None
  44. def _set_user_ban_cache(user):
  45. ban_cache = user.ban_cache
  46. ban_cache.bans_version = cachebuster.get_version(BAN_VERSION_KEY)
  47. try:
  48. user_ban = Ban.objects.find_ban(username=user.username,
  49. email=user.email)
  50. ban_cache.is_banned = True
  51. ban_cache.valid_until = user_ban.valid_until
  52. ban_cache.user_message = user_ban.user_message
  53. ban_cache.staff_message = user_ban.staff_message
  54. except Ban.DoesNotExist:
  55. ban_cache.is_banned = False
  56. ban_cache.valid_until = None
  57. ban_cache.user_message = None
  58. ban_cache.staff_message = None
  59. ban_cache.save()
  60. return ban_cache
  61. """
  62. Utility for checking if request came from banned IP
  63. This check may be performed frequently, which is why there is extra
  64. boilerplate that caches ban check result in session
  65. """
  66. def get_request_ip_ban(request):
  67. session_ban_cache = _get_session_bancache(request)
  68. if session_ban_cache:
  69. if session_ban_cache['is_banned']:
  70. return session_ban_cache
  71. else:
  72. return False
  73. found_ban = get_ip_ban(request._misago_real_ip)
  74. ban_cache = request.session[BAN_CACHE_SESSION_KEY] = {
  75. 'version': cachebuster.get_version(BAN_VERSION_KEY),
  76. 'ip': request._misago_real_ip,
  77. }
  78. if found_ban:
  79. if found_ban.valid_until:
  80. valid_until_as_string = found_ban.valid_until.strftime('%Y-%m-%d')
  81. ban_cache['valid_until'] = valid_until_as_string
  82. else:
  83. ban_cache['valid_until'] = None
  84. ban_cache.update({
  85. 'is_banned': True,
  86. 'message': found_ban.user_message
  87. })
  88. request.session[BAN_CACHE_SESSION_KEY] = ban_cache
  89. return _hydrate_session_cache(request.session[BAN_CACHE_SESSION_KEY])
  90. else:
  91. ban_cache['is_banned'] = False
  92. request.session[BAN_CACHE_SESSION_KEY] = ban_cache
  93. return None
  94. def _get_session_bancache(request):
  95. try:
  96. ban_cache = request.session[BAN_CACHE_SESSION_KEY]
  97. ban_cache = _hydrate_session_cache(ban_cache)
  98. if ban_cache['ip'] != request._misago_real_ip:
  99. return None
  100. if not cachebuster.is_valid(BAN_VERSION_KEY, ban_cache['version']):
  101. return None
  102. if ban_cache.get('valid_until'):
  103. """
  104. Make two timezone unaware dates and compare them
  105. """
  106. if ban_cache.get('valid_until') < date.today():
  107. return None
  108. return ban_cache
  109. except KeyError:
  110. return None
  111. def _hydrate_session_cache(ban_cache):
  112. hydrated = ban_cache.copy()
  113. if hydrated.get('valid_until'):
  114. expiration_datetime = datetime.strptime(ban_cache.get('valid_until'),
  115. '%Y-%m-%d')
  116. hydrated['valid_until'] = expiration_datetime.date()
  117. return hydrated