acl.py 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. from django.utils.translation import ugettext_lazy as _
  2. from django import forms
  3. from misago.acl.builder import BaseACL
  4. from misago.acl.utils import ACLError403, ACLError404
  5. from misago.forms import YesNoSwitch
  6. def make_forum_form(request, role, form):
  7. form.base_fields['can_read_threads'] = forms.ChoiceField(choices=(
  8. ('0', _("No")),
  9. ('1', _("Yes, owned")),
  10. ('2', _("Yes, all")),
  11. ))
  12. form.base_fields['can_start_threads'] = forms.ChoiceField(choices=(
  13. ('0', _("No")),
  14. ('1', _("Yes, with moderation")),
  15. ('2', _("Yes")),
  16. ))
  17. form.base_fields['can_edit_own_threads'] = forms.BooleanField(widget=YesNoSwitch,initial=False,required=False)
  18. form.base_fields['can_soft_delete_own_threads'] = forms.BooleanField(widget=YesNoSwitch,initial=False,required=False)
  19. form.base_fields['can_write_posts'] = forms.ChoiceField(choices=(
  20. ('0', _("No")),
  21. ('1', _("Yes, with moderation")),
  22. ('2', _("Yes")),
  23. ))
  24. form.base_fields['can_edit_own_posts'] = forms.BooleanField(widget=YesNoSwitch,initial=False,required=False)
  25. form.base_fields['can_soft_delete_own_posts'] = forms.BooleanField(widget=YesNoSwitch,initial=False,required=False)
  26. form.base_fields['can_upvote_posts'] = forms.BooleanField(widget=YesNoSwitch,initial=False,required=False)
  27. form.base_fields['can_downvote_posts'] = forms.BooleanField(widget=YesNoSwitch,initial=False,required=False)
  28. form.base_fields['can_see_posts_scores'] = forms.ChoiceField(choices=(
  29. ('0', _("No")),
  30. ('1', _("Yes, final score")),
  31. ('2', _("Yes, both up and down-votes")),
  32. ))
  33. form.base_fields['can_see_votes'] = forms.BooleanField(widget=YesNoSwitch,initial=False,required=False)
  34. form.base_fields['can_make_polls'] = forms.BooleanField(widget=YesNoSwitch,initial=False,required=False)
  35. form.base_fields['can_vote_in_polls'] = forms.BooleanField(widget=YesNoSwitch,initial=False,required=False)
  36. form.base_fields['can_see_votes'] = forms.BooleanField(widget=YesNoSwitch,initial=False,required=False)
  37. form.base_fields['can_see_attachments'] = forms.BooleanField(widget=YesNoSwitch,initial=False,required=False)
  38. form.base_fields['can_upload_attachments'] = forms.BooleanField(widget=YesNoSwitch,initial=False,required=False)
  39. form.base_fields['can_download_attachments'] = forms.BooleanField(widget=YesNoSwitch,initial=False,required=False)
  40. form.base_fields['attachment_size'] = forms.IntegerField(min_value=0,initial=100)
  41. form.base_fields['attachment_limit'] = forms.IntegerField(min_value=0,initial=3)
  42. form.base_fields['can_approve'] = forms.BooleanField(widget=YesNoSwitch,initial=False,required=False)
  43. form.base_fields['can_edit_labels'] = forms.BooleanField(widget=YesNoSwitch,initial=False,required=False)
  44. form.base_fields['can_see_changelog'] = forms.BooleanField(widget=YesNoSwitch,initial=False,required=False)
  45. form.base_fields['can_make_annoucements'] = forms.BooleanField(widget=YesNoSwitch,initial=False,required=False)
  46. form.base_fields['can_pin_threads'] = forms.BooleanField(widget=YesNoSwitch,initial=False,required=False)
  47. form.base_fields['can_edit_threads_posts'] = forms.BooleanField(widget=YesNoSwitch,initial=False,required=False)
  48. form.base_fields['can_move_threads_posts'] = forms.BooleanField(widget=YesNoSwitch,initial=False,required=False)
  49. form.base_fields['can_close_threads'] = forms.BooleanField(widget=YesNoSwitch,initial=False,required=False)
  50. form.base_fields['can_protect_posts'] = forms.BooleanField(widget=YesNoSwitch,initial=False,required=False)
  51. form.base_fields['can_delete_threads'] = forms.ChoiceField(choices=(
  52. ('0', _("No")),
  53. ('1', _("Yes, soft-delete")),
  54. ('2', _("Yes, hard-delete")),
  55. ))
  56. form.base_fields['can_delete_posts'] = forms.ChoiceField(choices=(
  57. ('0', _("No")),
  58. ('1', _("Yes, soft-delete")),
  59. ('2', _("Yes, hard-delete")),
  60. ))
  61. form.base_fields['can_delete_polls'] = forms.ChoiceField(choices=(
  62. ('0', _("No")),
  63. ('1', _("Yes, soft-delete")),
  64. ('2', _("Yes, hard-delete")),
  65. ))
  66. form.base_fields['can_delete_attachments'] = forms.BooleanField(widget=YesNoSwitch,initial=False,required=False)
  67. form.layout.append((
  68. _("Threads"),
  69. (
  70. ('can_read_threads', {'label': _("Can read threads")}),
  71. ('can_start_threads', {'label': _("Can start new threads")}),
  72. ('can_edit_own_threads', {'label': _("Can edit own threads")}),
  73. ('can_soft_delete_own_threads', {'label': _("Can soft-delete own threads")}),
  74. ),
  75. ),)
  76. form.layout.append((
  77. _("Posts"),
  78. (
  79. ('can_write_posts', {'label': _("Can write posts")}),
  80. ('can_edit_own_posts', {'label': _("Can edit own posts")}),
  81. ('can_edit_own_posts', {'label': _("Can soft-delete own posts")}),
  82. ),
  83. ),)
  84. form.layout.append((
  85. _("Karma"),
  86. (
  87. ('can_upvote_posts', {'label': _("Can upvote posts")}),
  88. ('can_downvote_posts', {'label': _("Can downvote posts")}),
  89. ('can_see_posts_scores', {'label': _("Can see post score")}),
  90. ('can_see_votes', {'label': _("Can see who voted on post")}),
  91. ),
  92. ),)
  93. form.layout.append((
  94. _("Polls"),
  95. (
  96. ('can_make_polls', {'label': _("Can make polls")}),
  97. ('can_vote_in_polls', {'label': _("Can vote in polls")}),
  98. ('can_see_votes', {'label': _("Can see who voted in poll")}),
  99. ),
  100. ),)
  101. form.layout.append((
  102. _("Attachments"),
  103. (
  104. ('can_see_attachments', {'label': _("Can see attachments")}),
  105. ('can_upload_attachments', {'label': _("Can upload attachments")}),
  106. ('can_download_attachments', {'label': _("Can download attachments")}),
  107. ('attachment_size', {'label': _("Max size of single attachment (in Kb)"), 'help_text': _("Enter zero for no limit.")}),
  108. ('attachment_limit', {'label': _("Max number of attachments per post"), 'help_text': _("Enter zero for no limit.")}),
  109. ),
  110. ),)
  111. form.layout.append((
  112. _("Moderation"),
  113. (
  114. ('can_approve', {'label': _("Can accept threads and posts")}),
  115. ('can_edit_labels', {'label': _("Can edit thread labels")}),
  116. ('can_see_changelog', {'label': _("Can see edits history")}),
  117. ('can_make_annoucements', {'label': _("Can make annoucements")}),
  118. ('can_pin_threads', {'label': _("Can pin threads")}),
  119. ('can_edit_threads_posts', {'label': _("Can edit threads and posts")}),
  120. ('can_move_threads_posts', {'label': _("Can move, merge and split threads and posts")}),
  121. ('can_close_threads', {'label': _("Can close threads")}),
  122. ('can_protect_posts', {'label': _("Can protect posts"), 'help_text': _("Protected posts cannot be changed by their owners.")}),
  123. ('can_delete_threads', {'label': _("Can delete threads")}),
  124. ('can_delete_posts', {'label': _("Can delete posts")}),
  125. ('can_delete_polls', {'label': _("Can delete polls")}),
  126. ('can_delete_attachments', {'label': _("Can delete attachments")}),
  127. ),
  128. ),)
  129. class ThreadsACL(BaseACL):
  130. def allow_thread_view(self, thread):
  131. try:
  132. forum_role = self.acl[thread.forum.pk]
  133. if forum_role['can_read_threads'] == 0:
  134. raise ACLError403(_("You don't have permission to read threads in this forum."))
  135. except KeyError:
  136. raise ACLError403(_("You don't have permission to read threads in this forum."))
  137. def can_start_threads(self, forum):
  138. try:
  139. forum_role = self.acl[forum.pk]
  140. if forum_role['can_read_threads'] == 0 or forum_role['can_start_threads'] == 0:
  141. return False
  142. if forum.closed and forum_role['can_close_threads'] == 0:
  143. return False
  144. return True
  145. except KeyError:
  146. return False
  147. def allow_new_threads(self, forum):
  148. try:
  149. forum_role = self.acl[forum.pk]
  150. if forum_role['can_read_threads'] == 0 or forum_role['can_start_threads'] == 0:
  151. raise ACLError403(_("You don't have permission to start new threads in this forum."))
  152. if forum.closed and forum_role['can_close_threads'] == 0:
  153. raise ACLError403(_("This forum is closed, you can't start new threads in it."))
  154. except KeyError:
  155. raise ACLError403(_("You don't have permission to start new threads in this forum."))
  156. def can_reply(self, thread):
  157. try:
  158. forum_role = self.acl[thread.forum.pk]
  159. if forum_role['can_write_posts'] == 0:
  160. return False
  161. if thread.closed and forum_role['can_close_threads'] == 0:
  162. return False
  163. return True
  164. except KeyError:
  165. return False
  166. def allow_reply(self, thread):
  167. try:
  168. forum_role = self.acl[thread.forum.pk]
  169. if forum_role['can_write_posts'] == 0:
  170. raise ACLError403(_("You don't have permission to write replies in this forum."))
  171. if thread.closed and forum_role['can_close_threads'] == 0:
  172. raise ACLError403(_("You can't write replies in closed threads."))
  173. except KeyError:
  174. raise ACLError403(_("You don't have permission to write replies in this forum."))
  175. def build_forums(acl, perms, forums, forum_roles):
  176. acl.threads = ThreadsACL()
  177. for forum in forums:
  178. forum_role = {
  179. 'can_read_threads': 0,
  180. 'can_start_threads': 0,
  181. 'can_edit_own_threads': False,
  182. 'can_soft_delete_own_threads': False,
  183. 'can_write_posts': 0,
  184. 'can_edit_own_posts': False,
  185. 'can_soft_delete_own_posts': False,
  186. 'can_upvote_posts': False,
  187. 'can_downvote_posts': False,
  188. 'can_see_posts_scores': 0,
  189. 'can_see_votes': False,
  190. 'can_make_polls': False,
  191. 'can_vote_in_polls': False,
  192. 'can_see_votes': False,
  193. 'can_see_attachments': False,
  194. 'can_upload_attachments': False,
  195. 'can_download_attachments': False,
  196. 'attachment_size': 100,
  197. 'attachment_limit': 3,
  198. 'can_approve': False,
  199. 'can_edit_labels': False,
  200. 'can_see_changelog': False,
  201. 'can_make_annoucements': False,
  202. 'can_pin_threads': False,
  203. 'can_edit_threads_posts': False,
  204. 'can_move_threads_posts': False,
  205. 'can_close_threads': False,
  206. 'can_protect_posts': False,
  207. 'can_delete_threads': 0,
  208. 'can_delete_posts': 0,
  209. 'can_delete_polls': 0,
  210. 'can_delete_attachments': False,
  211. }
  212. for perm in perms:
  213. try:
  214. role = forum_roles[perm['forums'][forum.pk]]
  215. for p in forum_role:
  216. if p in ['attachment_size', 'attachment_limit'] and role[p] == 0:
  217. forum_role[p] = 0
  218. elif int(role[p]) > forum_role[p]:
  219. forum_role[p] = int(role[p])
  220. except KeyError:
  221. pass
  222. acl.threads.acl[forum.pk] = forum_role