moderation.py 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. from datetime import timedelta
  2. from django import forms
  3. from django.contrib.auth import get_user_model
  4. from django.core.exceptions import PermissionDenied
  5. from django.template.defaultfilters import date as format_date
  6. from django.utils import timezone
  7. from django.utils.translation import gettext_lazy as _
  8. from misago.acl import algebra
  9. from misago.acl.decorators import return_boolean
  10. from misago.acl.models import Role
  11. from misago.admin.forms import YesNoSwitch
  12. from misago.users.bans import get_user_ban
  13. __all__ = [
  14. "allow_rename_user",
  15. "can_rename_user",
  16. "allow_moderate_avatar",
  17. "can_moderate_avatar",
  18. "allow_moderate_signature",
  19. "can_moderate_signature",
  20. "allow_edit_profile_details",
  21. "can_edit_profile_details",
  22. "allow_ban_user",
  23. "can_ban_user",
  24. "allow_lift_ban",
  25. "can_lift_ban",
  26. ]
  27. class PermissionsForm(forms.Form):
  28. legend = _("Users moderation")
  29. can_rename_users = YesNoSwitch(label=_("Can rename users"))
  30. can_moderate_avatars = YesNoSwitch(label=_("Can moderate avatars"))
  31. can_moderate_signatures = YesNoSwitch(label=_("Can moderate signatures"))
  32. can_moderate_profile_details = YesNoSwitch(label=_("Can moderate profile details"))
  33. can_ban_users = YesNoSwitch(label=_("Can ban users"))
  34. max_ban_length = forms.IntegerField(
  35. label=_("Max length, in days, of imposed ban"),
  36. help_text=_("Enter zero to let moderators impose permanent bans."),
  37. min_value=0,
  38. initial=0,
  39. )
  40. can_lift_bans = YesNoSwitch(label=_("Can lift bans"))
  41. max_lifted_ban_length = forms.IntegerField(
  42. label=_("Max length, in days, of lifted ban"),
  43. help_text=_("Enter zero to let moderators lift permanent bans."),
  44. min_value=0,
  45. initial=0,
  46. )
  47. def change_permissions_form(role):
  48. if isinstance(role, Role) and role.special_role != "anonymous":
  49. return PermissionsForm
  50. else:
  51. return None
  52. def build_acl(acl, roles, key_name):
  53. new_acl = {
  54. "can_rename_users": 0,
  55. "can_moderate_avatars": 0,
  56. "can_moderate_signatures": 0,
  57. "can_moderate_profile_details": 0,
  58. "can_ban_users": 0,
  59. "max_ban_length": 2,
  60. "can_lift_bans": 0,
  61. "max_lifted_ban_length": 2,
  62. }
  63. new_acl.update(acl)
  64. return algebra.sum_acls(
  65. new_acl,
  66. roles=roles,
  67. key=key_name,
  68. can_rename_users=algebra.greater,
  69. can_moderate_avatars=algebra.greater,
  70. can_moderate_signatures=algebra.greater,
  71. can_moderate_profile_details=algebra.greater,
  72. can_ban_users=algebra.greater,
  73. max_ban_length=algebra.greater_or_zero,
  74. can_lift_bans=algebra.greater,
  75. max_lifted_ban_length=algebra.greater_or_zero,
  76. )
  77. def add_acl_to_user(user_acl, target):
  78. target.acl["can_rename"] = can_rename_user(user_acl, target)
  79. target.acl["can_moderate_avatar"] = can_moderate_avatar(user_acl, target)
  80. target.acl["can_moderate_signature"] = can_moderate_signature(user_acl, target)
  81. target.acl["can_edit_profile_details"] = can_edit_profile_details(user_acl, target)
  82. target.acl["can_ban"] = can_ban_user(user_acl, target)
  83. target.acl["max_ban_length"] = user_acl["max_ban_length"]
  84. target.acl["can_lift_ban"] = can_lift_ban(user_acl, target)
  85. mod_permissions = ["can_rename", "can_moderate_avatar", "can_moderate_signature"]
  86. for permission in mod_permissions:
  87. if target.acl[permission]:
  88. target.acl["can_moderate"] = True
  89. break
  90. def register_with(registry):
  91. registry.acl_annotator(get_user_model(), add_acl_to_user)
  92. def allow_rename_user(user_acl, target):
  93. if not user_acl["can_rename_users"]:
  94. raise PermissionDenied(_("You can't rename users."))
  95. if not user_acl["is_superuser"] and (target.is_staff or target.is_superuser):
  96. raise PermissionDenied(_("You can't rename administrators."))
  97. can_rename_user = return_boolean(allow_rename_user)
  98. def allow_moderate_avatar(user_acl, target):
  99. if not user_acl["can_moderate_avatars"]:
  100. raise PermissionDenied(_("You can't moderate avatars."))
  101. if not user_acl["is_superuser"] and (target.is_staff or target.is_superuser):
  102. raise PermissionDenied(_("You can't moderate administrators avatars."))
  103. can_moderate_avatar = return_boolean(allow_moderate_avatar)
  104. def allow_moderate_signature(user_acl, target):
  105. if not user_acl["can_moderate_signatures"]:
  106. raise PermissionDenied(_("You can't moderate signatures."))
  107. if not user_acl["is_superuser"] and (target.is_staff or target.is_superuser):
  108. message = _("You can't moderate administrators signatures.")
  109. raise PermissionDenied(message)
  110. can_moderate_signature = return_boolean(allow_moderate_signature)
  111. def allow_edit_profile_details(user_acl, target):
  112. if user_acl["is_anonymous"]:
  113. raise PermissionDenied(_("You have to sign in to edit profile details."))
  114. if (
  115. user_acl["user_id"] != target.id
  116. and not user_acl["can_moderate_profile_details"]
  117. ):
  118. raise PermissionDenied(_("You can't edit other users details."))
  119. if not user_acl["is_superuser"] and (target.is_staff or target.is_superuser):
  120. message = _("You can't edit administrators details.")
  121. raise PermissionDenied(message)
  122. can_edit_profile_details = return_boolean(allow_edit_profile_details)
  123. def allow_ban_user(user_acl, target):
  124. if not user_acl["can_ban_users"]:
  125. raise PermissionDenied(_("You can't ban users."))
  126. if target.is_staff or target.is_superuser:
  127. raise PermissionDenied(_("You can't ban administrators."))
  128. can_ban_user = return_boolean(allow_ban_user)
  129. def allow_lift_ban(user_acl, target):
  130. if not user_acl["can_lift_bans"]:
  131. raise PermissionDenied(_("You can't lift bans."))
  132. ban = get_user_ban(target, user_acl["cache_versions"])
  133. if not ban:
  134. raise PermissionDenied(_("This user is not banned."))
  135. if user_acl["max_lifted_ban_length"]:
  136. expiration_limit = timedelta(days=user_acl["max_lifted_ban_length"])
  137. lift_cutoff = (timezone.now() + expiration_limit).date()
  138. if not ban.valid_until:
  139. raise PermissionDenied(_("You can't lift permanent bans."))
  140. elif ban.valid_until > lift_cutoff:
  141. message = _("You can't lift bans that expire after %(expiration)s.")
  142. raise PermissionDenied(message % {"expiration": format_date(lift_cutoff)})
  143. can_lift_ban = return_boolean(allow_lift_ban)