acl.py 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587
  1. from django import forms
  2. from django.db import models
  3. from django.db.models import Q
  4. from django.utils.translation import ugettext_lazy as _
  5. from misago.acl.builder import BaseACL
  6. from misago.acl.utils import ACLError403, ACLError404
  7. from misago.forms import YesNoSwitch
  8. def make_forum_form(request, role, form):
  9. form.base_fields['can_read_threads'] = forms.TypedChoiceField(choices=(
  10. (0, _("No")),
  11. (1, _("Yes, owned")),
  12. (2, _("Yes, all")),
  13. ), coerce=int)
  14. form.base_fields['can_start_threads'] = forms.TypedChoiceField(choices=(
  15. (0, _("No")),
  16. (1, _("Yes, with moderation")),
  17. (2, _("Yes")),
  18. ), coerce=int)
  19. form.base_fields['can_edit_own_threads'] = forms.BooleanField(widget=YesNoSwitch, initial=False, required=False)
  20. form.base_fields['can_soft_delete_own_threads'] = forms.BooleanField(widget=YesNoSwitch, initial=False, required=False)
  21. form.base_fields['can_write_posts'] = forms.TypedChoiceField(choices=(
  22. (0, _("No")),
  23. (1, _("Yes, with moderation")),
  24. (2, _("Yes")),
  25. ), coerce=int)
  26. form.base_fields['can_edit_own_posts'] = forms.BooleanField(widget=YesNoSwitch, initial=False, required=False)
  27. form.base_fields['can_soft_delete_own_posts'] = forms.BooleanField(widget=YesNoSwitch, initial=False, required=False)
  28. form.base_fields['can_upvote_posts'] = forms.BooleanField(widget=YesNoSwitch, initial=False, required=False)
  29. form.base_fields['can_downvote_posts'] = forms.BooleanField(widget=YesNoSwitch, initial=False, required=False)
  30. form.base_fields['can_see_posts_scores'] = forms.TypedChoiceField(choices=(
  31. (0, _("No")),
  32. (1, _("Yes, final score")),
  33. (2, _("Yes, both up and down-votes")),
  34. ), coerce=int)
  35. form.base_fields['can_see_votes'] = forms.BooleanField(widget=YesNoSwitch, initial=False, required=False)
  36. form.base_fields['can_make_polls'] = forms.BooleanField(widget=YesNoSwitch, initial=False, required=False)
  37. form.base_fields['can_vote_in_polls'] = forms.BooleanField(widget=YesNoSwitch, initial=False, required=False)
  38. form.base_fields['can_see_poll_votes'] = forms.BooleanField(widget=YesNoSwitch, initial=False, required=False)
  39. form.base_fields['can_see_attachments'] = forms.BooleanField(widget=YesNoSwitch, initial=False, required=False)
  40. form.base_fields['can_upload_attachments'] = forms.BooleanField(widget=YesNoSwitch, initial=False, required=False)
  41. form.base_fields['can_download_attachments'] = forms.BooleanField(widget=YesNoSwitch, initial=False, required=False)
  42. form.base_fields['attachment_size'] = forms.IntegerField(min_value=0, initial=100)
  43. form.base_fields['attachment_limit'] = forms.IntegerField(min_value=0, initial=3)
  44. form.base_fields['can_approve'] = forms.BooleanField(widget=YesNoSwitch, initial=False, required=False)
  45. form.base_fields['can_edit_labels'] = forms.BooleanField(widget=YesNoSwitch, initial=False, required=False)
  46. form.base_fields['can_see_changelog'] = forms.BooleanField(widget=YesNoSwitch, initial=False, required=False)
  47. form.base_fields['can_pin_threads'] = forms.TypedChoiceField(choices=(
  48. (0, _("No")),
  49. (1, _("Yes, to stickies")),
  50. (2, _("Yes, to annoucements")),
  51. ), coerce=int)
  52. form.base_fields['can_edit_threads_posts'] = forms.BooleanField(widget=YesNoSwitch, initial=False, required=False)
  53. form.base_fields['can_move_threads_posts'] = forms.BooleanField(widget=YesNoSwitch, initial=False, required=False)
  54. form.base_fields['can_close_threads'] = forms.BooleanField(widget=YesNoSwitch, initial=False, required=False)
  55. form.base_fields['can_protect_posts'] = forms.BooleanField(widget=YesNoSwitch, initial=False, required=False)
  56. form.base_fields['can_delete_threads'] = forms.TypedChoiceField(choices=(
  57. (0, _("No")),
  58. (1, _("Yes, soft-delete")),
  59. (2, _("Yes, hard-delete")),
  60. ), coerce=int)
  61. form.base_fields['can_delete_posts'] = forms.TypedChoiceField(choices=(
  62. (0, _("No")),
  63. (1, _("Yes, soft-delete")),
  64. (2, _("Yes, hard-delete")),
  65. ), coerce=int)
  66. form.base_fields['can_delete_polls'] = forms.TypedChoiceField(choices=(
  67. (0, _("No")),
  68. (1, _("Yes, soft-delete")),
  69. (2, _("Yes, hard-delete")),
  70. ), coerce=int)
  71. form.base_fields['can_delete_attachments'] = forms.BooleanField(widget=YesNoSwitch, initial=False, required=False)
  72. form.layout.append((
  73. _("Threads"),
  74. (
  75. ('can_read_threads', {'label': _("Can read threads")}),
  76. ('can_start_threads', {'label': _("Can start new threads")}),
  77. ('can_edit_own_threads', {'label': _("Can edit own threads")}),
  78. ('can_soft_delete_own_threads', {'label': _("Can soft-delete own threads")}),
  79. ),
  80. ),)
  81. form.layout.append((
  82. _("Posts"),
  83. (
  84. ('can_write_posts', {'label': _("Can write posts")}),
  85. ('can_edit_own_posts', {'label': _("Can edit own posts")}),
  86. ('can_soft_delete_own_posts', {'label': _("Can soft-delete own posts")}),
  87. ),
  88. ),)
  89. form.layout.append((
  90. _("Karma"),
  91. (
  92. ('can_upvote_posts', {'label': _("Can upvote posts")}),
  93. ('can_downvote_posts', {'label': _("Can downvote posts")}),
  94. ('can_see_posts_scores', {'label': _("Can see post score")}),
  95. ('can_see_votes', {'label': _("Can see who voted on post")}),
  96. ),
  97. ),)
  98. form.layout.append((
  99. _("Polls"),
  100. (
  101. ('can_make_polls', {'label': _("Can make polls")}),
  102. ('can_vote_in_polls', {'label': _("Can vote in polls")}),
  103. ('can_see_poll_votes', {'label': _("Can see who voted in poll")}),
  104. ),
  105. ),)
  106. form.layout.append((
  107. _("Attachments"),
  108. (
  109. ('can_see_attachments', {'label': _("Can see attachments")}),
  110. ('can_upload_attachments', {'label': _("Can upload attachments")}),
  111. ('can_download_attachments', {'label': _("Can download attachments")}),
  112. ('attachment_size', {'label': _("Max size of single attachment (in Kb)"), 'help_text': _("Enter zero for no limit.")}),
  113. ('attachment_limit', {'label': _("Max number of attachments per post"), 'help_text': _("Enter zero for no limit.")}),
  114. ),
  115. ),)
  116. form.layout.append((
  117. _("Moderation"),
  118. (
  119. ('can_approve', {'label': _("Can accept threads and posts")}),
  120. ('can_edit_labels', {'label': _("Can edit thread labels")}),
  121. ('can_see_changelog', {'label': _("Can see edits history")}),
  122. ('can_make_annoucements', {'label': _("Can make annoucements")}),
  123. ('can_pin_threads', {'label': _("Can change threads weight")}),
  124. ('can_edit_threads_posts', {'label': _("Can edit threads and posts")}),
  125. ('can_move_threads_posts', {'label': _("Can move, merge and split threads and posts")}),
  126. ('can_close_threads', {'label': _("Can close threads")}),
  127. ('can_protect_posts', {'label': _("Can protect posts"), 'help_text': _("Protected posts cannot be changed by their owners.")}),
  128. ('can_delete_threads', {'label': _("Can delete threads")}),
  129. ('can_delete_posts', {'label': _("Can delete posts")}),
  130. ('can_delete_polls', {'label': _("Can delete polls")}),
  131. ('can_delete_attachments', {'label': _("Can delete attachments")}),
  132. ),
  133. ),)
  134. class ThreadsACL(BaseACL):
  135. def get_role(self, forum):
  136. try:
  137. try:
  138. return self.acl[forum.pk]
  139. except AttributeError:
  140. return self.acl[forum]
  141. except KeyError:
  142. return {}
  143. def allow_thread_view(self, user, thread):
  144. try:
  145. forum_role = self.acl[thread.forum_id]
  146. if forum_role['can_read_threads'] == 0:
  147. raise ACLError403(_("You don't have permission to read threads in this forum."))
  148. if forum_role['can_read_threads'] == 1 and thread.weight < 2 and thread.start_poster_id != user.id:
  149. raise ACLError404()
  150. if thread.moderated and not (forum_role['can_approve'] or (user.is_authenticated() and user == thread.start_poster)):
  151. raise ACLError404()
  152. if thread.deleted and not forum_role['can_delete_threads']:
  153. raise ACLError404()
  154. except KeyError:
  155. raise ACLError403(_("You don't have permission to read threads in this forum."))
  156. def allow_post_view(self, user, thread, post):
  157. forum_role = self.acl[thread.forum_id]
  158. if post.moderated and not (forum_role['can_approve'] or (user.is_authenticated() and user == post.user)):
  159. raise ACLError404()
  160. if post.deleted and not (forum_role['can_delete_posts'] or (user.is_authenticated() and user == post.user)):
  161. raise ACLError404()
  162. def get_readable_forums(self, acl):
  163. readable = []
  164. for forum in self.acl:
  165. if acl.forums.can_browse(forum) and self.acl[forum]['can_read_threads']:
  166. readable.append(forum)
  167. return readable
  168. def filter_threads(self, request, forum, queryset):
  169. try:
  170. forum_role = self.acl[forum.pk]
  171. if not forum_role['can_approve']:
  172. if request.user.is_authenticated():
  173. queryset = queryset.filter(Q(moderated=0) | Q(start_poster=request.user))
  174. else:
  175. queryset = queryset.filter(moderated=0)
  176. if forum_role['can_read_threads'] == 1:
  177. queryset = queryset.filter(Q(weight=2) | Q(start_poster_id=request.user.id))
  178. if not forum_role['can_delete_threads']:
  179. queryset = queryset.filter(deleted=False)
  180. except KeyError:
  181. return False
  182. return queryset
  183. def filter_posts(self, request, thread, queryset):
  184. try:
  185. forum_role = self.acl[thread.forum.pk]
  186. if not forum_role['can_approve']:
  187. if request.user.is_authenticated():
  188. queryset = queryset.filter(Q(moderated=0) | Q(user=request.user))
  189. else:
  190. queryset = queryset.filter(moderated=0)
  191. except KeyError:
  192. return False
  193. return queryset
  194. def can_start_threads(self, forum):
  195. try:
  196. forum_role = self.acl[forum.pk]
  197. if forum_role['can_read_threads'] == 0 or forum_role['can_start_threads'] == 0:
  198. return False
  199. if forum.closed and forum_role['can_close_threads'] == 0:
  200. return False
  201. return True
  202. except KeyError:
  203. return False
  204. def allow_new_threads(self, forum):
  205. try:
  206. forum_role = self.acl[forum.pk]
  207. if forum_role['can_read_threads'] == 0 or forum_role['can_start_threads'] == 0:
  208. raise ACLError403(_("You don't have permission to start new threads in this forum."))
  209. if forum.closed and forum_role['can_close_threads'] == 0:
  210. raise ACLError403(_("This forum is closed, you can't start new threads in it."))
  211. except KeyError:
  212. raise ACLError403(_("You don't have permission to start new threads in this forum."))
  213. def can_edit_thread(self, user, forum, thread, post):
  214. try:
  215. forum_role = self.acl[thread.forum_id]
  216. if forum_role['can_close_threads'] == 0 and (forum.closed or thread.closed):
  217. return False
  218. if forum_role['can_edit_threads_posts']:
  219. return True
  220. if forum_role['can_edit_own_threads'] and not post.protected and post.user_id == user.pk:
  221. return True
  222. return False
  223. except KeyError:
  224. return False
  225. def allow_thread_edit(self, user, forum, thread, post):
  226. try:
  227. forum_role = self.acl[thread.forum_id]
  228. if thread.deleted or post.deleted:
  229. self.allow_deleted_post_view(forum)
  230. if not forum_role['can_close_threads']:
  231. if forum.closed:
  232. raise ACLError403(_("You can't edit threads in closed forums."))
  233. if thread.closed:
  234. raise ACLError403(_("You can't edit closed threads."))
  235. if not forum_role['can_edit_threads_posts']:
  236. if post.user_id != user.pk:
  237. raise ACLError403(_("You can't edit other members threads."))
  238. if not forum_role['can_edit_own_threads']:
  239. raise ACLError403(_("You can't edit your threads."))
  240. if post.protected:
  241. raise ACLError403(_("This thread is protected, you cannot edit it."))
  242. except KeyError:
  243. raise ACLError403(_("You don't have permission to edit threads in this forum."))
  244. def can_reply(self, forum, thread):
  245. try:
  246. forum_role = self.acl[forum.pk]
  247. if forum_role['can_write_posts'] == 0:
  248. return False
  249. if (forum.closed or thread.closed) and forum_role['can_close_threads'] == 0:
  250. return False
  251. return True
  252. except KeyError:
  253. return False
  254. def allow_reply(self, forum, thread):
  255. try:
  256. forum_role = self.acl[thread.forum.pk]
  257. if forum_role['can_write_posts'] == 0:
  258. raise ACLError403(_("You don't have permission to write replies in this forum."))
  259. if forum_role['can_close_threads'] == 0:
  260. if forum.closed:
  261. raise ACLError403(_("You can't write replies in closed forums."))
  262. if thread.closed:
  263. raise ACLError403(_("You can't write replies in closed threads."))
  264. except KeyError:
  265. raise ACLError403(_("You don't have permission to write replies in this forum."))
  266. def can_edit_reply(self, user, forum, thread, post):
  267. try:
  268. forum_role = self.acl[thread.forum_id]
  269. if forum_role['can_close_threads'] == 0 and (forum.closed or thread.closed):
  270. return False
  271. if forum_role['can_edit_threads_posts']:
  272. return True
  273. if forum_role['can_edit_own_posts'] and not post.protected and post.user_id == user.pk:
  274. return True
  275. return False
  276. except KeyError:
  277. return False
  278. def allow_reply_edit(self, user, forum, thread, post):
  279. try:
  280. forum_role = self.acl[thread.forum_id]
  281. if thread.deleted or post.deleted:
  282. self.allow_deleted_post_view(forum)
  283. if not forum_role['can_close_threads']:
  284. if forum.closed:
  285. raise ACLError403(_("You can't edit replies in closed forums."))
  286. if thread.closed:
  287. raise ACLError403(_("You can't edit replies in closed threads."))
  288. if not forum_role['can_edit_threads_posts']:
  289. if post.user_id != user.pk:
  290. raise ACLError403(_("You can't edit other members replies."))
  291. if not forum_role['can_edit_own_posts']:
  292. raise ACLError403(_("You can't edit your replies."))
  293. if post.protected:
  294. raise ACLError403(_("This reply is protected, you cannot edit it."))
  295. except KeyError:
  296. raise ACLError403(_("You don't have permission to edit replies in this forum."))
  297. def can_see_changelog(self, user, forum, post):
  298. try:
  299. forum_role = self.acl[forum.pk]
  300. return forum_role['can_see_changelog'] or user.pk == post.user_id
  301. except KeyError:
  302. return False
  303. def allow_changelog_view(self, user, forum, post):
  304. try:
  305. forum_role = self.acl[forum.pk]
  306. if post.thread.deleted or post.deleted:
  307. self.allow_deleted_post_view(forum)
  308. if not (forum_role['can_see_changelog'] or user.pk == post.user_id):
  309. raise ACLError403(_("You don't have permission to see history of changes made to this post."))
  310. except KeyError:
  311. raise ACLError403(_("You don't have permission to see history of changes made to this post."))
  312. def can_make_revert(self, forum, thread):
  313. try:
  314. forum_role = self.acl[forum.pk]
  315. if not forum_role['can_close_threads'] and (forum.closed or thread.closed):
  316. return False
  317. return forum_role['can_edit_threads_posts']
  318. except KeyError:
  319. return False
  320. def allow_revert(self, forum, thread):
  321. try:
  322. forum_role = self.acl[forum.pk]
  323. if not forum_role['can_close_threads']:
  324. if forum.closed:
  325. raise ACLError403(_("You can't make reverts in closed forums."))
  326. if thread.closed:
  327. raise ACLError403(_("You can't make reverts in closed threads."))
  328. if not forum_role['can_edit_threads_posts']:
  329. raise ACLError403(_("You don't have permission to make reverts in this forum."))
  330. except KeyError:
  331. raise ACLError403(_("You don't have permission to make reverts in this forum."))
  332. def can_mod_threads(self, forum):
  333. try:
  334. forum_role = self.acl[forum.pk]
  335. return (
  336. forum_role['can_approve']
  337. or forum_role['can_pin_threads']
  338. or forum_role['can_move_threads_posts']
  339. or forum_role['can_close_threads']
  340. or forum_role['can_delete_threads']
  341. )
  342. except KeyError:
  343. return False
  344. def can_mod_posts(self, thread):
  345. try:
  346. forum_role = self.acl[thread.forum.pk]
  347. return (
  348. forum_role['can_edit_threads_posts']
  349. or forum_role['can_move_threads_posts']
  350. or forum_role['can_close_threads']
  351. or forum_role['can_delete_threads']
  352. or forum_role['can_delete_posts']
  353. )
  354. except KeyError:
  355. return False
  356. def can_approve(self, forum):
  357. try:
  358. forum_role = self.acl[forum.pk]
  359. return forum_role['can_approve']
  360. except KeyError:
  361. return False
  362. def can_protect(self, forum):
  363. try:
  364. forum_role = self.acl[forum.pk]
  365. return forum_role['can_protect_posts']
  366. except KeyError:
  367. return False
  368. def can_delete_thread(self, user, forum, thread, post):
  369. try:
  370. forum_role = self.acl[forum.pk]
  371. if not forum_role['can_close_threads'] and (forum.closed or thread.closed):
  372. return False
  373. if post.protected and not forum_role['can_protect_posts']:
  374. return False
  375. if forum_role['can_delete_threads']:
  376. return forum_role['can_delete_threads']
  377. if thread.start_poster_id == user.pk and forum_role['can_soft_delete_own_threads']:
  378. return 1
  379. return False
  380. except KeyError:
  381. return False
  382. def allow_delete_thread(self, user, forum, thread, post, delete=False):
  383. try:
  384. forum_role = self.acl[forum.pk]
  385. if not forum_role['can_close_threads']:
  386. if forum.closed:
  387. raise ACLError403(_("You don't have permission to delete threads in closed forum."))
  388. if thread.closed:
  389. raise ACLError403(_("This thread is closed, you cannot delete it."))
  390. if post.protected and not forum_role['can_protect_posts']:
  391. raise ACLError403(_("This post is protected, you cannot delete it."))
  392. if delete and forum_role['can_delete_threads'] < 2:
  393. raise ACLError403(_("You cannot hard delete this thread."))
  394. if not (forum_role['can_delete_threads'] or (thread.start_poster_id == user.pk and forum_role['can_soft_delete_own_threads'])):
  395. raise ACLError403(_("You don't have permission to delete this thread."))
  396. if thread.deleted and not delete:
  397. raise ACLError403(_("This thread is already deleted."))
  398. except KeyError:
  399. raise ACLError403(_("You don't have permission to delete this thread."))
  400. def can_delete_post(self, user, forum, thread, post):
  401. try:
  402. forum_role = self.acl[forum.pk]
  403. if not forum_role['can_close_threads'] and (forum.closed or thread.closed):
  404. return False
  405. if post.protected and not forum_role['can_protect_posts']:
  406. return False
  407. if forum_role['can_delete_posts']:
  408. return forum_role['can_delete_posts']
  409. if post.user_id == user.pk and not post.protected and forum_role['can_soft_delete_own_posts']:
  410. return 1
  411. return False
  412. except KeyError:
  413. return False
  414. def allow_delete_post(self, user, forum, thread, post, delete=False):
  415. try:
  416. forum_role = self.acl[forum.pk]
  417. if not forum_role['can_close_threads']:
  418. if forum.closed:
  419. raise ACLError403(_("You don't have permission to delete posts in closed forum."))
  420. if thread.closed:
  421. raise ACLError403(_("This thread is closed, you cannot delete its posts."))
  422. if post.protected and not forum_role['can_protect_posts']:
  423. raise ACLError403(_("This post is protected, you cannot delete it."))
  424. if delete and forum_role['can_delete_posts'] < 2:
  425. raise ACLError403(_("You cannot hard delete this post."))
  426. if not (forum_role['can_delete_posts'] or (post.user_id == user.pk and forum_role['can_soft_delete_own_posts'])):
  427. raise ACLError403(_("You don't have permission to delete this post."))
  428. if post.deleted and not delete:
  429. raise ACLError403(_("This post is already deleted."))
  430. except KeyError:
  431. raise ACLError403(_("You don't have permission to delete this post."))
  432. def can_see_deleted_threads(self, forum):
  433. try:
  434. forum_role = self.acl[forum.pk]
  435. return forum_role['can_delete_threads']
  436. except KeyError:
  437. return False
  438. def can_see_deleted_posts(self, forum):
  439. try:
  440. forum_role = self.acl[forum.pk]
  441. return forum_role['can_delete_posts']
  442. except KeyError:
  443. return False
  444. def allow_deleted_post_view(self, forum):
  445. try:
  446. forum_role = self.acl[forum.pk]
  447. if not forum_role['can_delete_posts']:
  448. raise ACLError404()
  449. except KeyError:
  450. raise ACLError404()
  451. def can_upvote_posts(self, forum):
  452. try:
  453. forum_role = self.acl[forum.pk]
  454. return forum_role['can_upvote_posts']
  455. except KeyError:
  456. return False
  457. def can_downvote_posts(self, forum):
  458. try:
  459. forum_role = self.acl[forum.pk]
  460. return forum_role['can_downvote_posts']
  461. except KeyError:
  462. return False
  463. def can_see_post_score(self, forum):
  464. try:
  465. forum_role = self.acl[forum.pk]
  466. return forum_role['can_see_posts_scores']
  467. except KeyError:
  468. return False
  469. def can_see_post_votes(self, forum):
  470. try:
  471. forum_role = self.acl[forum.pk]
  472. return forum_role['can_see_votes']
  473. except KeyError:
  474. return False
  475. def allow_post_upvote(self, forum):
  476. try:
  477. forum_role = self.acl[forum.pk]
  478. if not forum_role['can_upvote_posts']:
  479. raise ACLError403(_("You cannot upvote posts in this forum."))
  480. except KeyError:
  481. raise ACLError403(_("You cannot upvote posts in this forum."))
  482. def allow_post_downvote(self, forum):
  483. try:
  484. forum_role = self.acl[forum.pk]
  485. if not forum_role['can_downvote_posts']:
  486. raise ACLError403(_("You cannot downvote posts in this forum."))
  487. except KeyError:
  488. raise ACLError403(_("You cannot downvote posts in this forum."))
  489. def allow_post_votes_view(self, forum):
  490. try:
  491. forum_role = self.acl[forum.pk]
  492. if not forum_role['can_see_votes']:
  493. raise ACLError403(_("You don't have permission to see who voted on this post."))
  494. except KeyError:
  495. raise ACLError403(_("You don't have permission to see who voted on this post."))
  496. def build_forums(acl, perms, forums, forum_roles):
  497. acl.threads = ThreadsACL()
  498. for forum in forums:
  499. forum_role = {
  500. 'can_read_threads': 0,
  501. 'can_start_threads': 0,
  502. 'can_edit_own_threads': False,
  503. 'can_soft_delete_own_threads': False,
  504. 'can_write_posts': 0,
  505. 'can_edit_own_posts': False,
  506. 'can_soft_delete_own_posts': False,
  507. 'can_upvote_posts': False,
  508. 'can_downvote_posts': False,
  509. 'can_see_posts_scores': 0,
  510. 'can_see_votes': False,
  511. 'can_make_polls': False,
  512. 'can_vote_in_polls': False,
  513. 'can_see_poll_votes': False,
  514. 'can_see_attachments': False,
  515. 'can_upload_attachments': False,
  516. 'can_download_attachments': False,
  517. 'attachment_size': 100,
  518. 'attachment_limit': 3,
  519. 'can_approve': False,
  520. 'can_edit_labels': False,
  521. 'can_see_changelog': False,
  522. 'can_make_annoucements': False,
  523. 'can_pin_threads': 0,
  524. 'can_edit_threads_posts': False,
  525. 'can_move_threads_posts': False,
  526. 'can_close_threads': False,
  527. 'can_protect_posts': False,
  528. 'can_delete_threads': 0,
  529. 'can_delete_posts': 0,
  530. 'can_delete_polls': 0,
  531. 'can_delete_attachments': False,
  532. }
  533. for perm in perms:
  534. try:
  535. role = forum_roles[perm['forums'][forum.pk]]
  536. for p in forum_role:
  537. try:
  538. if p in ['attachment_size', 'attachment_limit'] and role[p] == 0:
  539. forum_role[p] = 0
  540. elif role[p] > forum_role[p]:
  541. forum_role[p] = role[p]
  542. except KeyError:
  543. pass
  544. except KeyError:
  545. pass
  546. acl.threads.acl[forum.pk] = forum_role