polls.py 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. from django.core.exceptions import PermissionDenied
  2. from django.utils import timezone
  3. from django.utils.translation import ugettext_lazy as _, ungettext
  4. from misago.acl import algebra
  5. from misago.acl.decorators import return_boolean
  6. from misago.acl.models import Role
  7. from misago.core import forms
  8. from ..models import Poll, Thread
  9. """
  10. Admin Permissions Forms
  11. """
  12. class RolePermissionsForm(forms.Form):
  13. legend = _("Polls")
  14. can_start_polls = forms.TypedChoiceField(
  15. label=_("Can start polls"),
  16. coerce=int,
  17. initial=0,
  18. choices=(
  19. (0, _("No")),
  20. (1, _("Own threads")),
  21. (2, _("All threads"))
  22. )
  23. )
  24. can_edit_polls = forms.TypedChoiceField(
  25. label=_("Can edit polls"),
  26. coerce=int,
  27. initial=0,
  28. choices=(
  29. (0, _("No")),
  30. (1, _("Own polls")),
  31. (2, _("All polls"))
  32. )
  33. )
  34. can_delete_polls = forms.TypedChoiceField(
  35. label=_("Can edit polls"),
  36. coerce=int,
  37. initial=0,
  38. choices=(
  39. (0, _("No")),
  40. (1, _("Own polls")),
  41. (2, _("All polls"))
  42. )
  43. )
  44. poll_edit_time = forms.IntegerField(
  45. label=_("Time limit for own polls edits, in minutes"),
  46. help_text=_("Enter 0 to don't limit time for editing own polls."),
  47. initial=0,
  48. min_value=0
  49. )
  50. can_always_see_poll_voters = forms.YesNoSwitch(
  51. label=_("Can always see polls voters"),
  52. help_text=_("Allows users to see who voted in poll even if poll votes are secret.")
  53. )
  54. def change_permissions_form(role):
  55. if isinstance(role, Role) and role.special_role != 'anonymous':
  56. return RolePermissionsForm
  57. else:
  58. return None
  59. """
  60. ACL Builder
  61. """
  62. def build_acl(acl, roles, key_name):
  63. acl.update({
  64. 'can_start_polls': 0,
  65. 'can_edit_polls': 0,
  66. 'can_delete_polls': 0,
  67. 'poll_edit_time': 0,
  68. 'can_always_see_poll_voters': 0
  69. })
  70. return algebra.sum_acls(acl, roles=roles, key=key_name,
  71. can_start_polls=algebra.greater,
  72. can_edit_polls=algebra.greater,
  73. can_delete_polls=algebra.greater,
  74. poll_edit_time=algebra.greater_or_zero,
  75. can_always_see_poll_voters=algebra.greater
  76. )
  77. """
  78. ACL's for targets
  79. """
  80. def add_acl_to_poll(user, poll):
  81. poll.acl.update({
  82. 'can_edit': can_edit_poll(user, poll),
  83. 'can_delete': can_delete_poll(user, poll),
  84. })
  85. def add_acl_to_thread(user, thread):
  86. thread.acl.update({
  87. 'can_start_poll': can_start_poll(user, thread)
  88. })
  89. def register_with(registry):
  90. registry.acl_annotator(Poll, add_acl_to_poll)
  91. registry.acl_annotator(Thread, add_acl_to_thread)
  92. """
  93. ACL tests
  94. """
  95. def allow_start_poll(user, target):
  96. if user.is_anonymous():
  97. raise PermissionDenied(_("You have to sign in to start polls."))
  98. category_acl = user.acl['categories'].get(target.category_id, {
  99. 'can_close_threads': False,
  100. })
  101. if not user.acl.get('can_start_polls'):
  102. raise PermissionDenied(_("You can't start polls."))
  103. if user.acl.get('can_start_polls') < 2 and user.pk != target.starter_id:
  104. raise PermissionDenied(_("You can't start polls in other users threads."))
  105. if not category_acl.get('can_close_threads'):
  106. if target.category.is_closed:
  107. raise PermissionDenied(_("This category is closed. You can't start polls in it."))
  108. if target.is_closed:
  109. raise PermissionDenied(_("This thread is closed. You can't start polls in it."))
  110. try:
  111. if target.poll:
  112. raise PermissionDenied(_("There's already a poll in this thread."))
  113. except Poll.DoesNotExist:
  114. pass
  115. can_start_poll = return_boolean(allow_start_poll)
  116. def allow_edit_poll(user, target):
  117. if user.is_anonymous():
  118. raise PermissionDenied(_("You have to sign in to edit polls."))
  119. category_acl = user.acl['categories'].get(target.category_id, {
  120. 'can_close_threads': False,
  121. })
  122. if not user.acl.get('can_edit_polls'):
  123. raise PermissionDenied(_("You can't edit polls."))
  124. if user.acl.get('can_edit_polls') < 2:
  125. if user.pk != target.poster_id:
  126. raise PermissionDenied(_("You can't edit other users polls in this category."))
  127. if not has_time_to_edit_poll(user, target):
  128. message = ungettext(
  129. "You can't edit polls that are older than %(minutes)s minute.",
  130. "You can't edit polls that are older than %(minutes)s minutes.",
  131. user.acl['poll_edit_time'])
  132. raise PermissionDenied(message % {'minutes': user.acl['poll_edit_time']})
  133. if target.is_over:
  134. raise PermissionDenied(_("This poll is over. You can't edit it."))
  135. if not category_acl.get('can_close_threads'):
  136. if target.category.is_closed:
  137. raise PermissionDenied(_("This category is closed. You can't edit polls in it."))
  138. if target.thread.is_closed:
  139. raise PermissionDenied(_("This thread is closed. You can't edit polls in it."))
  140. can_edit_poll = return_boolean(allow_edit_poll)
  141. def allow_delete_poll(user, target):
  142. if user.is_anonymous():
  143. raise PermissionDenied(_("You have to sign in to delete polls."))
  144. category_acl = user.acl['categories'].get(target.category_id, {
  145. 'can_close_threads': False,
  146. })
  147. if not user.acl.get('can_delete_polls'):
  148. raise PermissionDenied(_("You can't delete polls."))
  149. if user.acl.get('can_delete_polls') < 2:
  150. if user.pk != target.poster_id:
  151. raise PermissionDenied(_("You can't delete other users polls in this category."))
  152. if not has_time_to_edit_poll(user, target):
  153. message = ungettext(
  154. "You can't delete polls that are older than %(minutes)s minute.",
  155. "You can't delete polls that are older than %(minutes)s minutes.",
  156. user.acl['poll_edit_time'])
  157. raise PermissionDenied(message % {'minutes': user.acl['poll_edit_time']})
  158. if target.is_over:
  159. raise PermissionDenied(_("This poll is over. You can't delete it."))
  160. if not category_acl.get('can_close_threads'):
  161. if target.category.is_closed:
  162. raise PermissionDenied(_("This category is closed. You can't delete polls in it."))
  163. if target.thread.is_closed:
  164. raise PermissionDenied(_("This thread is closed. You can't delete polls in it."))
  165. can_delete_poll = return_boolean(allow_delete_poll)
  166. def has_time_to_edit_poll(user, target):
  167. edit_time = user.acl['poll_edit_time']
  168. if edit_time:
  169. diff = timezone.now() - target.posted_on
  170. diff_minutes = int(diff.total_seconds() / 60)
  171. return diff_minutes < edit_time
  172. else:
  173. return True