threads.py 34 KB

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