polls.py 7.9 KB

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