polls.py 8.3 KB

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