threads.py 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606
  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.exceptions 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 announcements")),
  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_pin_threads', {'label': _("Can change threads weight")}),
  123. ('can_edit_threads_posts', {'label': _("Can edit threads and posts")}),
  124. ('can_move_threads_posts', {'label': _("Can move, merge and split threads and posts")}),
  125. ('can_close_threads', {'label': _("Can close threads")}),
  126. ('can_protect_posts', {'label': _("Can protect posts"), 'help_text': _("Protected posts cannot be changed by their owners.")}),
  127. ('can_delete_threads', {'label': _("Can delete threads")}),
  128. ('can_delete_posts', {'label': _("Can delete posts")}),
  129. ('can_delete_polls', {'label': _("Can delete polls")}),
  130. ('can_delete_attachments', {'label': _("Can delete attachments")}),
  131. ),
  132. ),)
  133. class ThreadsACL(BaseACL):
  134. def get_role(self, forum):
  135. try:
  136. try:
  137. return self.acl[forum.pk]
  138. except AttributeError:
  139. return self.acl[forum]
  140. except KeyError:
  141. return {}
  142. def allow_thread_view(self, user, thread):
  143. try:
  144. forum_role = self.acl[thread.forum_id]
  145. if forum_role['can_read_threads'] == 0:
  146. raise ACLError403(_("You don't have permission to read threads in this forum."))
  147. if forum_role['can_read_threads'] == 1 and thread.weight < 2 and thread.start_poster_id != user.id:
  148. raise ACLError404()
  149. if thread.moderated and not (forum_role['can_approve'] or (user.is_authenticated() and user == thread.start_poster)):
  150. raise ACLError404()
  151. if thread.deleted and not forum_role['can_delete_threads']:
  152. raise ACLError404()
  153. except KeyError:
  154. raise ACLError403(_("You don't have permission to read threads in this forum."))
  155. def allow_post_view(self, user, thread, post):
  156. forum_role = self.acl[thread.forum_id]
  157. if post.moderated and not (forum_role['can_approve'] or (user.is_authenticated() and user == post.user)):
  158. raise ACLError404()
  159. if post.deleted and not (forum_role['can_delete_posts'] or (user.is_authenticated() and user == post.user)):
  160. raise ACLError404()
  161. def get_readable_forums(self, acl):
  162. readable = []
  163. for forum in self.acl:
  164. if acl.forums.can_browse(forum) and self.acl[forum]['can_read_threads']:
  165. readable.append(forum)
  166. return readable
  167. def filter_threads(self, request, forum, queryset):
  168. try:
  169. forum_role = self.acl[forum.pk]
  170. if not forum_role['can_approve']:
  171. if request.user.is_authenticated():
  172. queryset = queryset.filter(Q(moderated=0) | Q(start_poster=request.user))
  173. else:
  174. queryset = queryset.filter(moderated=0)
  175. if forum_role['can_read_threads'] == 1:
  176. queryset = queryset.filter(Q(weight=2) | Q(start_poster_id=request.user.id))
  177. if not forum_role['can_delete_threads']:
  178. queryset = queryset.filter(deleted=False)
  179. except KeyError:
  180. return False
  181. return queryset
  182. def filter_posts(self, request, thread, queryset):
  183. try:
  184. forum_role = self.acl[thread.forum.pk]
  185. if not forum_role['can_approve']:
  186. if request.user.is_authenticated():
  187. queryset = queryset.filter(Q(moderated=0) | Q(user=request.user))
  188. else:
  189. queryset = queryset.filter(moderated=0)
  190. except KeyError:
  191. return False
  192. return queryset
  193. def can_read_threads(self, forum):
  194. try:
  195. forum_role = self.acl[forum.pk]
  196. return forum_role['can_read_threads']
  197. except KeyError:
  198. return False
  199. def can_start_threads(self, forum):
  200. try:
  201. forum_role = self.acl[forum.pk]
  202. if forum_role['can_read_threads'] == 0 or forum_role['can_start_threads'] == 0:
  203. return False
  204. if forum.closed and forum_role['can_close_threads'] == 0:
  205. return False
  206. return True
  207. except KeyError:
  208. return False
  209. def allow_new_threads(self, forum):
  210. try:
  211. forum_role = self.acl[forum.pk]
  212. if forum_role['can_read_threads'] == 0 or forum_role['can_start_threads'] == 0:
  213. raise ACLError403(_("You don't have permission to start new threads in this forum."))
  214. if forum.closed and forum_role['can_close_threads'] == 0:
  215. raise ACLError403(_("This forum is closed, you can't start new threads in it."))
  216. except KeyError:
  217. raise ACLError403(_("You don't have permission to start new threads in this forum."))
  218. def can_edit_thread(self, user, forum, thread, post):
  219. try:
  220. forum_role = self.acl[thread.forum_id]
  221. if forum_role['can_close_threads'] == 0 and (forum.closed or thread.closed):
  222. return False
  223. if forum_role['can_edit_threads_posts']:
  224. return True
  225. if forum_role['can_edit_own_threads'] and not post.protected and post.user_id == user.pk:
  226. return True
  227. return False
  228. except KeyError:
  229. return False
  230. def allow_thread_edit(self, user, forum, thread, post):
  231. try:
  232. forum_role = self.acl[thread.forum_id]
  233. if thread.deleted or post.deleted:
  234. self.allow_deleted_post_view(forum)
  235. if not forum_role['can_close_threads']:
  236. if forum.closed:
  237. raise ACLError403(_("You can't edit threads in closed forums."))
  238. if thread.closed:
  239. raise ACLError403(_("You can't edit closed threads."))
  240. if not forum_role['can_edit_threads_posts']:
  241. if post.user_id != user.pk:
  242. raise ACLError403(_("You can't edit other members threads."))
  243. if not forum_role['can_edit_own_threads']:
  244. raise ACLError403(_("You can't edit your threads."))
  245. if post.protected:
  246. raise ACLError403(_("This thread is protected, you cannot edit it."))
  247. except KeyError:
  248. raise ACLError403(_("You don't have permission to edit threads in this forum."))
  249. def can_reply(self, forum, thread):
  250. try:
  251. forum_role = self.acl[forum.pk]
  252. if forum_role['can_write_posts'] == 0:
  253. return False
  254. if (forum.closed or thread.closed) and forum_role['can_close_threads'] == 0:
  255. return False
  256. return True
  257. except KeyError:
  258. return False
  259. def allow_reply(self, forum, thread):
  260. try:
  261. forum_role = self.acl[thread.forum.pk]
  262. if forum_role['can_write_posts'] == 0:
  263. raise ACLError403(_("You don't have permission to write replies in this forum."))
  264. if forum_role['can_close_threads'] == 0:
  265. if forum.closed:
  266. raise ACLError403(_("You can't write replies in closed forums."))
  267. if thread.closed:
  268. raise ACLError403(_("You can't write replies in closed threads."))
  269. except KeyError:
  270. raise ACLError403(_("You don't have permission to write replies in this forum."))
  271. def can_edit_reply(self, user, forum, thread, post):
  272. try:
  273. forum_role = self.acl[thread.forum_id]
  274. if forum_role['can_close_threads'] == 0 and (forum.closed or thread.closed):
  275. return False
  276. if forum_role['can_edit_threads_posts']:
  277. return True
  278. if forum_role['can_edit_own_posts'] and not post.protected and post.user_id == user.pk:
  279. return True
  280. return False
  281. except KeyError:
  282. return False
  283. def allow_reply_edit(self, user, forum, thread, post):
  284. try:
  285. forum_role = self.acl[thread.forum_id]
  286. if thread.deleted or post.deleted:
  287. self.allow_deleted_post_view(forum)
  288. if not forum_role['can_close_threads']:
  289. if forum.closed:
  290. raise ACLError403(_("You can't edit replies in closed forums."))
  291. if thread.closed:
  292. raise ACLError403(_("You can't edit replies in closed threads."))
  293. if not forum_role['can_edit_threads_posts']:
  294. if post.user_id != user.pk:
  295. raise ACLError403(_("You can't edit other members replies."))
  296. if not forum_role['can_edit_own_posts']:
  297. raise ACLError403(_("You can't edit your replies."))
  298. if post.protected:
  299. raise ACLError403(_("This reply is protected, you cannot edit it."))
  300. except KeyError:
  301. raise ACLError403(_("You don't have permission to edit replies in this forum."))
  302. def can_see_changelog(self, user, forum, post):
  303. try:
  304. forum_role = self.acl[forum.pk]
  305. return forum_role['can_see_changelog'] or user.pk == post.user_id
  306. except KeyError:
  307. return False
  308. def allow_changelog_view(self, user, forum, post):
  309. try:
  310. forum_role = self.acl[forum.pk]
  311. if post.thread.deleted or post.deleted:
  312. self.allow_deleted_post_view(forum)
  313. if not (forum_role['can_see_changelog'] or user.pk == post.user_id):
  314. raise ACLError403(_("You don't have permission to see history of changes made to this post."))
  315. except KeyError:
  316. raise ACLError403(_("You don't have permission to see history of changes made to this post."))
  317. def can_make_revert(self, forum, thread):
  318. try:
  319. forum_role = self.acl[forum.pk]
  320. if not forum_role['can_close_threads'] and (forum.closed or thread.closed):
  321. return False
  322. return forum_role['can_edit_threads_posts']
  323. except KeyError:
  324. return False
  325. def allow_revert(self, forum, thread):
  326. try:
  327. forum_role = self.acl[forum.pk]
  328. if not forum_role['can_close_threads']:
  329. if forum.closed:
  330. raise ACLError403(_("You can't make reverts in closed forums."))
  331. if thread.closed:
  332. raise ACLError403(_("You can't make reverts in closed threads."))
  333. if not forum_role['can_edit_threads_posts']:
  334. raise ACLError403(_("You don't have permission to make reverts in this forum."))
  335. except KeyError:
  336. raise ACLError403(_("You don't have permission to make reverts in this forum."))
  337. def can_mod_threads(self, forum):
  338. try:
  339. forum_role = self.acl[forum.pk]
  340. return (
  341. forum_role['can_approve']
  342. or forum_role['can_pin_threads']
  343. or forum_role['can_move_threads_posts']
  344. or forum_role['can_close_threads']
  345. or forum_role['can_delete_threads']
  346. )
  347. except KeyError:
  348. return False
  349. def can_mod_posts(self, thread):
  350. try:
  351. forum_role = self.acl[thread.forum.pk]
  352. return (
  353. forum_role['can_edit_threads_posts']
  354. or forum_role['can_move_threads_posts']
  355. or forum_role['can_close_threads']
  356. or forum_role['can_delete_threads']
  357. or forum_role['can_delete_posts']
  358. )
  359. except KeyError:
  360. return False
  361. def can_approve(self, forum):
  362. try:
  363. forum_role = self.acl[forum.pk]
  364. return forum_role['can_approve']
  365. except KeyError:
  366. return False
  367. def can_close(self, forum):
  368. try:
  369. forum_role = self.acl[forum.pk]
  370. return forum_role['can_close_threads']
  371. except KeyError:
  372. return False
  373. def can_protect(self, forum):
  374. try:
  375. forum_role = self.acl[forum.pk]
  376. return forum_role['can_protect_posts']
  377. except KeyError:
  378. return False
  379. def can_pin_threads(self, forum):
  380. try:
  381. forum_role = self.acl[forum.pk]
  382. return forum_role['can_pin_threads']
  383. except KeyError:
  384. return False
  385. def can_delete_thread(self, user, forum, thread, post):
  386. try:
  387. forum_role = self.acl[forum.pk]
  388. if not forum_role['can_close_threads'] and (forum.closed or thread.closed):
  389. return False
  390. if post.protected and not forum_role['can_protect_posts']:
  391. return False
  392. if forum_role['can_delete_threads']:
  393. return forum_role['can_delete_threads']
  394. if thread.start_poster_id == user.pk and forum_role['can_soft_delete_own_threads']:
  395. return 1
  396. return False
  397. except KeyError:
  398. return False
  399. def allow_delete_thread(self, user, forum, thread, post, delete=False):
  400. try:
  401. forum_role = self.acl[forum.pk]
  402. if not forum_role['can_close_threads']:
  403. if forum.closed:
  404. raise ACLError403(_("You don't have permission to delete threads in closed forum."))
  405. if thread.closed:
  406. raise ACLError403(_("This thread is closed, you cannot delete it."))
  407. if post.protected and not forum_role['can_protect_posts']:
  408. raise ACLError403(_("This post is protected, you cannot delete it."))
  409. if delete and forum_role['can_delete_threads'] < 2:
  410. raise ACLError403(_("You cannot hard delete this thread."))
  411. if not (forum_role['can_delete_threads'] or (thread.start_poster_id == user.pk and forum_role['can_soft_delete_own_threads'])):
  412. raise ACLError403(_("You don't have permission to delete this thread."))
  413. if thread.deleted and not delete:
  414. raise ACLError403(_("This thread is already deleted."))
  415. except KeyError:
  416. raise ACLError403(_("You don't have permission to delete this thread."))
  417. def can_delete_post(self, user, forum, thread, post):
  418. try:
  419. forum_role = self.acl[forum.pk]
  420. if not forum_role['can_close_threads'] and (forum.closed or thread.closed):
  421. return False
  422. if post.protected and not forum_role['can_protect_posts']:
  423. return False
  424. if forum_role['can_delete_posts']:
  425. return forum_role['can_delete_posts']
  426. if post.user_id == user.pk and not post.protected and forum_role['can_soft_delete_own_posts']:
  427. return 1
  428. return False
  429. except KeyError:
  430. return False
  431. def allow_delete_post(self, user, forum, thread, post, delete=False):
  432. try:
  433. forum_role = self.acl[forum.pk]
  434. if not forum_role['can_close_threads']:
  435. if forum.closed:
  436. raise ACLError403(_("You don't have permission to delete posts in closed forum."))
  437. if thread.closed:
  438. raise ACLError403(_("This thread is closed, you cannot delete its posts."))
  439. if post.protected and not forum_role['can_protect_posts']:
  440. raise ACLError403(_("This post is protected, you cannot delete it."))
  441. if delete and forum_role['can_delete_posts'] < 2:
  442. raise ACLError403(_("You cannot hard delete this post."))
  443. if not (forum_role['can_delete_posts'] or (post.user_id == user.pk and forum_role['can_soft_delete_own_posts'])):
  444. raise ACLError403(_("You don't have permission to delete this post."))
  445. if post.deleted and not delete:
  446. raise ACLError403(_("This post is already deleted."))
  447. except KeyError:
  448. raise ACLError403(_("You don't have permission to delete this post."))
  449. def can_see_deleted_threads(self, forum):
  450. try:
  451. forum_role = self.acl[forum.pk]
  452. return forum_role['can_delete_threads']
  453. except KeyError:
  454. return False
  455. def can_see_deleted_posts(self, forum):
  456. try:
  457. forum_role = self.acl[forum.pk]
  458. return forum_role['can_delete_posts']
  459. except KeyError:
  460. return False
  461. def allow_deleted_post_view(self, forum):
  462. try:
  463. forum_role = self.acl[forum.pk]
  464. if not forum_role['can_delete_posts']:
  465. raise ACLError404()
  466. except KeyError:
  467. raise ACLError404()
  468. def can_upvote_posts(self, forum):
  469. try:
  470. forum_role = self.acl[forum.pk]
  471. return forum_role['can_upvote_posts']
  472. except KeyError:
  473. return False
  474. def can_downvote_posts(self, forum):
  475. try:
  476. forum_role = self.acl[forum.pk]
  477. return forum_role['can_downvote_posts']
  478. except KeyError:
  479. return False
  480. def can_see_post_score(self, forum):
  481. try:
  482. forum_role = self.acl[forum.pk]
  483. return forum_role['can_see_posts_scores']
  484. except KeyError:
  485. return False
  486. def can_see_post_votes(self, forum):
  487. try:
  488. forum_role = self.acl[forum.pk]
  489. return forum_role['can_see_votes']
  490. except KeyError:
  491. return False
  492. def allow_post_upvote(self, forum):
  493. try:
  494. forum_role = self.acl[forum.pk]
  495. if not forum_role['can_upvote_posts']:
  496. raise ACLError403(_("You cannot upvote posts in this forum."))
  497. except KeyError:
  498. raise ACLError403(_("You cannot upvote posts in this forum."))
  499. def allow_post_downvote(self, forum):
  500. try:
  501. forum_role = self.acl[forum.pk]
  502. if not forum_role['can_downvote_posts']:
  503. raise ACLError403(_("You cannot downvote posts in this forum."))
  504. except KeyError:
  505. raise ACLError403(_("You cannot downvote posts in this forum."))
  506. def allow_post_votes_view(self, forum):
  507. try:
  508. forum_role = self.acl[forum.pk]
  509. if not forum_role['can_see_votes']:
  510. raise ACLError403(_("You don't have permission to see who voted on this post."))
  511. except KeyError:
  512. raise ACLError403(_("You don't have permission to see who voted on this post."))
  513. def build_forums(acl, perms, forums, forum_roles):
  514. acl.threads = ThreadsACL()
  515. for forum in forums:
  516. forum_role = {
  517. 'can_read_threads': 0,
  518. 'can_start_threads': 0,
  519. 'can_edit_own_threads': False,
  520. 'can_soft_delete_own_threads': False,
  521. 'can_write_posts': 0,
  522. 'can_edit_own_posts': False,
  523. 'can_soft_delete_own_posts': False,
  524. 'can_upvote_posts': False,
  525. 'can_downvote_posts': False,
  526. 'can_see_posts_scores': 0,
  527. 'can_see_votes': False,
  528. 'can_make_polls': False,
  529. 'can_vote_in_polls': False,
  530. 'can_see_poll_votes': False,
  531. 'can_see_attachments': False,
  532. 'can_upload_attachments': False,
  533. 'can_download_attachments': False,
  534. 'attachment_size': 100,
  535. 'attachment_limit': 3,
  536. 'can_approve': False,
  537. 'can_edit_labels': False,
  538. 'can_see_changelog': False,
  539. 'can_pin_threads': 0,
  540. 'can_edit_threads_posts': False,
  541. 'can_move_threads_posts': False,
  542. 'can_close_threads': False,
  543. 'can_protect_posts': False,
  544. 'can_delete_threads': 0,
  545. 'can_delete_posts': 0,
  546. 'can_delete_polls': 0,
  547. 'can_delete_attachments': False,
  548. }
  549. for perm in perms:
  550. try:
  551. role = forum_roles[perm['forums'][forum.pk]]
  552. for p in forum_role:
  553. try:
  554. if p in ['attachment_size', 'attachment_limit'] and role[p] == 0:
  555. forum_role[p] = 0
  556. elif role[p] > forum_role[p]:
  557. forum_role[p] = role[p]
  558. except KeyError:
  559. pass
  560. except KeyError:
  561. pass
  562. acl.threads.acl[forum.pk] = forum_role