threads.py 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782
  1. from datetime import timedelta
  2. from django.db import models
  3. from django.db.models import Q
  4. from django.utils import timezone
  5. from django.utils.translation import ugettext_lazy as _
  6. import floppyforms as forms
  7. from misago.acl.builder import BaseACL
  8. from misago.acl.exceptions import ACLError403, ACLError404
  9. from misago.forms import YesNoSwitch
  10. def make_forum_form(request, role, form):
  11. form.base_fields['can_read_threads'] = forms.TypedChoiceField(label=_("Can read threads"),
  12. choices=(
  13. (0, _("No")),
  14. (1, _("Yes, owned")),
  15. (2, _("Yes, all")),
  16. ), coerce=int)
  17. form.base_fields['can_start_threads'] = forms.TypedChoiceField(label=_("Can start new threads"),
  18. choices=(
  19. (0, _("No")),
  20. (1, _("Yes, with moderation")),
  21. (2, _("Yes")),
  22. ), coerce=int)
  23. form.base_fields['can_edit_own_threads'] = forms.BooleanField(label=_("Can edit own threads"),
  24. widget=YesNoSwitch, initial=False, required=False)
  25. form.base_fields['can_soft_delete_own_threads'] = forms.BooleanField(label=_("Can soft-delete own threads"),
  26. widget=YesNoSwitch, initial=False, required=False)
  27. form.base_fields['can_write_posts'] = forms.TypedChoiceField(label=_("Can write posts"),
  28. choices=(
  29. (0, _("No")),
  30. (1, _("Yes, with moderation")),
  31. (2, _("Yes")),
  32. ), coerce=int)
  33. form.base_fields['can_edit_own_posts'] = forms.BooleanField(label=_("Can edit own posts"),
  34. widget=YesNoSwitch, initial=False, required=False)
  35. form.base_fields['can_soft_delete_own_posts'] = forms.BooleanField(label=_("Can soft-delete own posts"),
  36. widget=YesNoSwitch, initial=False, required=False)
  37. form.base_fields['can_upvote_posts'] = forms.BooleanField(label=_("Can upvote posts"),
  38. widget=YesNoSwitch, initial=False, required=False)
  39. form.base_fields['can_downvote_posts'] = forms.BooleanField(label=_("Can downvote posts"),
  40. widget=YesNoSwitch, initial=False, required=False)
  41. form.base_fields['can_see_posts_scores'] = forms.TypedChoiceField(label=_("Can see post score"),
  42. choices=(
  43. (0, _("No")),
  44. (1, _("Yes, final score")),
  45. (2, _("Yes, both up and down-votes")),
  46. ), coerce=int)
  47. form.base_fields['can_see_votes'] = forms.BooleanField(label=_("Can see who voted on post"),
  48. widget=YesNoSwitch, initial=False, required=False)
  49. form.base_fields['can_make_polls'] = forms.BooleanField(label=_("Can make polls"),
  50. widget=YesNoSwitch, initial=False, required=False)
  51. form.base_fields['can_vote_in_polls'] = forms.BooleanField(label=_("Can vote in polls"),
  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_change_prefixes'] = forms.BooleanField(label=_("Can change threads prefixes"),
  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_see_poll_votes'] = forms.BooleanField(label=_("Can always see who voted in poll"),
  99. widget=YesNoSwitch, initial=False, required=False)
  100. form.base_fields['can_edit_polls'] = forms.IntegerField(label=_("Time for poll edition"), min_value=0, initial=15,
  101. help_text=_("Enter number of minutes after poll has been started for which member (or moderator) will be able to edit poll or 0 to always allow edition of unfinished polls. If you enter zero, users will always be able to change (and possibly maniputale) unfinished polls. This permission has also effect on user's permission to delete poll."))
  102. form.base_fields['can_delete_polls'] = forms.TypedChoiceField(label=_("Can delete polls"),
  103. choices=(
  104. (0, _("No")),
  105. (1, _("Yes, within allowed time")),
  106. (2, _("Yes, always")),
  107. ), coerce=int)
  108. form.base_fields['can_delete_attachments'] = forms.BooleanField(label=_("Can delete attachments"),
  109. widget=YesNoSwitch, initial=False, required=False)
  110. form.base_fields['can_delete_checkpoints'] = forms.TypedChoiceField(label=_("Can delete checkpoints"),
  111. choices=(
  112. (0, _("No")),
  113. (1, _("Yes, soft-delete")),
  114. (2, _("Yes, hard-delete")),
  115. ), coerce=int)
  116. form.base_fields['can_see_deleted_checkpoints'] = forms.BooleanField(label=_("Can see deleted checkpoints"),
  117. widget=YesNoSwitch, initial=False, required=False)
  118. form.fieldsets.append((
  119. _("Threads"),
  120. ('can_read_threads', 'can_start_threads', 'can_edit_own_threads', 'can_soft_delete_own_threads')
  121. ))
  122. form.fieldsets.append((
  123. _("Posts"),
  124. ('can_write_posts', 'can_edit_own_posts', 'can_soft_delete_own_posts')
  125. ))
  126. form.fieldsets.append((
  127. _("Karma"),
  128. ('can_upvote_posts', 'can_downvote_posts', 'can_see_posts_scores', 'can_see_votes')
  129. ))
  130. form.fieldsets.append((
  131. _("Polls"),
  132. ('can_make_polls', 'can_vote_in_polls', 'can_see_poll_votes', 'can_edit_polls', 'can_delete_polls')
  133. ))
  134. form.fieldsets.append((
  135. _("Attachments"),
  136. ('can_see_attachments', 'can_upload_attachments',
  137. 'can_download_attachments', 'attachment_size', 'attachment_limit')
  138. ))
  139. form.fieldsets.append((
  140. _("Moderation"),
  141. ('can_approve', 'can_change_prefixes', 'can_see_changelog', 'can_pin_threads', 'can_edit_threads_posts',
  142. 'can_move_threads_posts', 'can_close_threads', 'can_protect_posts', 'can_delete_threads',
  143. 'can_delete_posts', 'can_delete_attachments', 'can_delete_checkpoints', 'can_see_deleted_checkpoints')
  144. ))
  145. class ThreadsACL(BaseACL):
  146. def get_role(self, forum):
  147. try:
  148. try:
  149. return self.acl[forum.pk]
  150. except AttributeError:
  151. return self.acl[forum]
  152. except KeyError:
  153. return {}
  154. def allow_thread_view(self, user, thread):
  155. try:
  156. forum_role = self.acl[thread.forum_id]
  157. if forum_role['can_read_threads'] == 0:
  158. raise ACLError403(_("You don't have permission to read threads in this forum."))
  159. if forum_role['can_read_threads'] == 1 and thread.weight < 2 and (not user.is_authenticated() or thread.start_poster_id != user.id):
  160. raise ACLError404()
  161. if thread.moderated and not (forum_role['can_approve'] or (user.is_authenticated() and user == thread.start_poster)):
  162. raise ACLError404()
  163. if thread.deleted and not forum_role['can_delete_threads']:
  164. raise ACLError404()
  165. except KeyError:
  166. raise ACLError403(_("You don't have permission to read threads in this forum."))
  167. def allow_post_view(self, user, thread, post):
  168. forum_role = self.acl[thread.forum_id]
  169. if post.moderated and not (forum_role['can_approve'] or (user.is_authenticated() and user == post.user)):
  170. raise ACLError404()
  171. if post.deleted and not (forum_role['can_delete_posts'] or (user.is_authenticated() and user == post.user)):
  172. raise ACLError404()
  173. def filter_threads(self, request, forum, queryset):
  174. try:
  175. forum_role = self.get_role(forum)
  176. if not forum_role['can_approve']:
  177. if request.user.is_authenticated():
  178. queryset = queryset.filter(Q(moderated=False) | Q(start_poster=request.user))
  179. else:
  180. queryset = queryset.filter(moderated=False)
  181. if forum_role['can_read_threads'] == 1:
  182. if request.user.is_authenticated():
  183. queryset = queryset.filter(Q(weight=2) | Q(start_poster_id=request.user.id))
  184. else:
  185. queryset = queryset.filter(weight=2)
  186. if not forum_role['can_delete_threads']:
  187. queryset = queryset.filter(deleted=False)
  188. except KeyError:
  189. return False
  190. return queryset
  191. def filter_posts(self, request, thread, queryset):
  192. try:
  193. forum_role = self.acl[thread.forum.pk]
  194. if not forum_role['can_approve']:
  195. if request.user.is_authenticated():
  196. queryset = queryset.filter(Q(moderated=0) | Q(user=request.user))
  197. else:
  198. queryset = queryset.filter(moderated=0)
  199. except KeyError:
  200. return False
  201. return queryset
  202. def can_read_threads(self, forum):
  203. try:
  204. forum_role = self.get_role(forum)
  205. return forum_role['can_read_threads']
  206. except KeyError:
  207. return False
  208. def can_start_threads(self, forum):
  209. try:
  210. forum_role = self.get_role(forum)
  211. if forum_role['can_read_threads'] == 0 or forum_role['can_start_threads'] == 0:
  212. return False
  213. if forum.closed and forum_role['can_close_threads'] == 0:
  214. return False
  215. return True
  216. except KeyError:
  217. return False
  218. def allow_new_threads(self, forum):
  219. try:
  220. forum_role = self.get_role(forum)
  221. if forum_role['can_read_threads'] == 0 or forum_role['can_start_threads'] == 0:
  222. raise ACLError403(_("You don't have permission to start new threads in this forum."))
  223. if forum.closed and forum_role['can_close_threads'] == 0:
  224. raise ACLError403(_("This forum is closed, you can't start new threads in it."))
  225. except KeyError:
  226. raise ACLError403(_("You don't have permission to start new threads in this forum."))
  227. def can_edit_thread(self, user, forum, thread, post):
  228. try:
  229. forum_role = self.get_role(forum)
  230. if forum_role['can_close_threads'] == 0 and (forum.closed or thread.closed):
  231. return False
  232. if forum_role['can_edit_threads_posts']:
  233. return True
  234. if forum_role['can_edit_own_threads'] and not post.protected and post.user_id == user.pk:
  235. return True
  236. return False
  237. except KeyError:
  238. return False
  239. def allow_thread_edit(self, user, forum, thread, post):
  240. try:
  241. forum_role = self.get_role(forum)
  242. if thread.deleted or post.deleted:
  243. self.allow_deleted_post_view(forum)
  244. if not forum_role['can_close_threads']:
  245. if forum.closed:
  246. raise ACLError403(_("You can't edit threads in closed forums."))
  247. if thread.closed:
  248. raise ACLError403(_("You can't edit closed threads."))
  249. if not forum_role['can_edit_threads_posts']:
  250. if post.user_id != user.pk:
  251. raise ACLError403(_("You can't edit other members threads."))
  252. if not forum_role['can_edit_own_threads']:
  253. raise ACLError403(_("You can't edit your threads."))
  254. if post.protected:
  255. raise ACLError403(_("This thread is protected, you cannot edit it."))
  256. except KeyError:
  257. raise ACLError403(_("You don't have permission to edit threads in this forum."))
  258. def can_reply(self, forum, thread):
  259. try:
  260. forum_role = self.get_role(forum)
  261. if forum_role['can_write_posts'] == 0:
  262. return False
  263. if (forum.closed or thread.closed) and forum_role['can_close_threads'] == 0:
  264. return False
  265. return True
  266. except KeyError:
  267. return False
  268. def allow_reply(self, forum, thread):
  269. try:
  270. forum_role = self.get_role(forum)
  271. if forum_role['can_write_posts'] == 0:
  272. raise ACLError403(_("You don't have permission to write replies in this forum."))
  273. if forum_role['can_close_threads'] == 0:
  274. if forum.closed:
  275. raise ACLError403(_("You can't write replies in closed forums."))
  276. if thread.closed:
  277. raise ACLError403(_("You can't write replies in closed threads."))
  278. except KeyError:
  279. raise ACLError403(_("You don't have permission to write replies in this forum."))
  280. def can_edit_reply(self, user, forum, thread, post):
  281. try:
  282. forum_role = self.get_role(forum)
  283. if forum_role['can_close_threads'] == 0 and (forum.closed or thread.closed):
  284. return False
  285. if forum_role['can_edit_threads_posts']:
  286. return True
  287. if forum_role['can_edit_own_posts'] and not post.protected and post.user_id == user.pk:
  288. return True
  289. return False
  290. except KeyError:
  291. return False
  292. def allow_reply_edit(self, user, forum, thread, post):
  293. try:
  294. forum_role = self.get_role(forum)
  295. if thread.deleted or post.deleted:
  296. self.allow_deleted_post_view(forum)
  297. if not forum_role['can_close_threads']:
  298. if forum.closed:
  299. raise ACLError403(_("You can't edit replies in closed forums."))
  300. if thread.closed:
  301. raise ACLError403(_("You can't edit replies in closed threads."))
  302. if not forum_role['can_edit_threads_posts']:
  303. if post.user_id != user.pk:
  304. raise ACLError403(_("You can't edit other members replies."))
  305. if not forum_role['can_edit_own_posts']:
  306. raise ACLError403(_("You can't edit your replies."))
  307. if post.protected:
  308. raise ACLError403(_("This reply is protected, you cannot edit it."))
  309. except KeyError:
  310. raise ACLError403(_("You don't have permission to edit replies in this forum."))
  311. def can_change_prefix(self, forum):
  312. try:
  313. forum_role = self.get_role(forum)
  314. return forum_role['can_change_prefixes']
  315. except KeyError:
  316. return False
  317. def can_see_changelog(self, user, forum, post):
  318. try:
  319. forum_role = self.get_role(forum)
  320. return forum_role['can_see_changelog'] or user.pk == post.user_id
  321. except KeyError:
  322. return False
  323. def allow_changelog_view(self, user, forum, post):
  324. try:
  325. forum_role = self.get_role(forum)
  326. if post.thread.deleted or post.deleted:
  327. self.allow_deleted_post_view(forum)
  328. if not (forum_role['can_see_changelog'] or user.pk == post.user_id):
  329. raise ACLError403(_("You don't have permission to see history of changes made to this post."))
  330. except KeyError:
  331. raise ACLError403(_("You don't have permission to see history of changes made to this post."))
  332. def can_make_revert(self, forum, thread):
  333. try:
  334. forum_role = self.get_role(forum)
  335. if not forum_role['can_close_threads'] and (forum.closed or thread.closed):
  336. return False
  337. return forum_role['can_edit_threads_posts']
  338. except KeyError:
  339. return False
  340. def allow_revert(self, forum, thread):
  341. try:
  342. forum_role = self.get_role(forum)
  343. if not forum_role['can_close_threads']:
  344. if forum.closed:
  345. raise ACLError403(_("You can't make reverts in closed forums."))
  346. if thread.closed:
  347. raise ACLError403(_("You can't make reverts in closed threads."))
  348. if not forum_role['can_edit_threads_posts']:
  349. raise ACLError403(_("You don't have permission to make reverts in this forum."))
  350. except KeyError:
  351. raise ACLError403(_("You don't have permission to make reverts in this forum."))
  352. def can_mod_threads(self, forum):
  353. try:
  354. forum_role = self.get_role(forum)
  355. return (
  356. forum_role['can_approve']
  357. or forum_role['can_pin_threads']
  358. or forum_role['can_move_threads_posts']
  359. or forum_role['can_close_threads']
  360. or forum_role['can_delete_threads']
  361. )
  362. except KeyError:
  363. return False
  364. def can_mod_posts(self, forum):
  365. try:
  366. forum_role = self.get_role(forum)
  367. return (
  368. forum_role['can_edit_threads_posts']
  369. or forum_role['can_move_threads_posts']
  370. or forum_role['can_close_threads']
  371. or forum_role['can_delete_threads']
  372. or forum_role['can_delete_posts']
  373. )
  374. except KeyError:
  375. return False
  376. def can_approve(self, forum):
  377. try:
  378. forum_role = self.get_role(forum)
  379. return forum_role['can_approve']
  380. except KeyError:
  381. return False
  382. def can_close(self, forum):
  383. try:
  384. forum_role = self.get_role(forum)
  385. return forum_role['can_close_threads']
  386. except KeyError:
  387. return False
  388. def can_protect(self, forum):
  389. try:
  390. forum_role = self.get_role(forum)
  391. return forum_role['can_protect_posts']
  392. except KeyError:
  393. return False
  394. def can_pin_threads(self, forum):
  395. try:
  396. forum_role = self.get_role(forum)
  397. return forum_role['can_pin_threads']
  398. except KeyError:
  399. return False
  400. def can_delete_thread(self, user, forum, thread, post):
  401. try:
  402. forum_role = self.get_role(forum)
  403. if post.pk != thread.start_post_id:
  404. return False
  405. if not forum_role['can_close_threads'] and (forum.closed or thread.closed):
  406. return False
  407. if post.protected and not forum_role['can_protect_posts'] and not forum_role['can_delete_threads']:
  408. return False
  409. if forum_role['can_delete_threads']:
  410. return forum_role['can_delete_threads']
  411. if thread.start_poster_id == user.pk and forum_role['can_soft_delete_own_threads']:
  412. return 1
  413. return False
  414. except KeyError:
  415. return False
  416. def allow_delete_thread(self, user, forum, thread, post, delete=False):
  417. try:
  418. forum_role = self.get_role(forum)
  419. if not forum_role['can_close_threads']:
  420. if forum.closed:
  421. raise ACLError403(_("You don't have permission to delete threads in closed forum."))
  422. if thread.closed:
  423. raise ACLError403(_("This thread is closed, you cannot delete it."))
  424. if post.protected and not forum_role['can_protect_posts'] and not forum_role['can_delete_threads']:
  425. raise ACLError403(_("This post is protected, you cannot delete it."))
  426. if not (forum_role['can_delete_threads'] == 2 or
  427. (not delete and (forum_role['can_delete_threads'] == 1 or
  428. (thread.start_poster_id == user.pk and forum_role['can_soft_delete_own_threads'])))):
  429. raise ACLError403(_("You don't have permission to delete this thread."))
  430. if thread.deleted and not delete:
  431. raise ACLError403(_("This thread is already deleted."))
  432. except KeyError:
  433. raise ACLError403(_("You don't have permission to delete this thread."))
  434. def can_delete_post(self, user, forum, thread, post):
  435. try:
  436. forum_role = self.get_role(forum)
  437. if post.pk == thread.start_post_id:
  438. return False
  439. if not forum_role['can_close_threads'] and (forum.closed or thread.closed):
  440. return False
  441. if post.protected and not forum_role['can_protect_posts'] and not forum_role['can_delete_posts']:
  442. return False
  443. if forum_role['can_delete_posts']:
  444. return forum_role['can_delete_posts']
  445. if post.user_id == user.pk and not post.protected and forum_role['can_soft_delete_own_posts']:
  446. return 1
  447. return False
  448. except KeyError:
  449. return False
  450. def allow_delete_post(self, user, forum, thread, post, delete=False):
  451. try:
  452. forum_role = self.get_role(forum)
  453. if not forum_role['can_close_threads']:
  454. if forum.closed:
  455. raise ACLError403(_("You don't have permission to delete posts in closed forum."))
  456. if thread.closed:
  457. raise ACLError403(_("This thread is closed, you cannot delete its posts."))
  458. if post.protected and not forum_role['can_protect_posts'] and not forum_role['can_delete_posts']:
  459. raise ACLError403(_("This post is protected, you cannot delete it."))
  460. if not (forum_role['can_delete_posts'] == 2 or
  461. (not delete and (forum_role['can_delete_posts'] == 1 or
  462. (post.user_id == user.pk and forum_role['can_soft_delete_own_posts'])))):
  463. raise ACLError403(_("You don't have permission to delete this post."))
  464. if post.deleted and not delete:
  465. raise ACLError403(_("This post is already deleted."))
  466. except KeyError:
  467. raise ACLError403(_("You don't have permission to delete this post."))
  468. def can_see_deleted_threads(self, forum):
  469. try:
  470. forum_role = self.get_role(forum)
  471. return forum_role['can_delete_threads']
  472. except KeyError:
  473. return False
  474. def can_see_deleted_posts(self, forum):
  475. try:
  476. forum_role = self.get_role(forum)
  477. return forum_role['can_delete_posts']
  478. except KeyError:
  479. return False
  480. def allow_deleted_post_view(self, forum):
  481. try:
  482. forum_role = self.get_role(forum)
  483. if not forum_role['can_delete_posts']:
  484. raise ACLError404()
  485. except KeyError:
  486. raise ACLError404()
  487. def can_upvote_posts(self, forum):
  488. try:
  489. forum_role = self.get_role(forum)
  490. return forum_role['can_upvote_posts']
  491. except KeyError:
  492. return False
  493. def can_downvote_posts(self, forum):
  494. try:
  495. forum_role = self.get_role(forum)
  496. return forum_role['can_downvote_posts']
  497. except KeyError:
  498. return False
  499. def can_see_post_score(self, forum):
  500. try:
  501. forum_role = self.get_role(forum)
  502. return forum_role['can_see_posts_scores']
  503. except KeyError:
  504. return False
  505. def can_see_post_votes(self, forum):
  506. try:
  507. forum_role = self.get_role(forum)
  508. return forum_role['can_see_votes']
  509. except KeyError:
  510. return False
  511. def allow_post_upvote(self, forum):
  512. try:
  513. forum_role = self.get_role(forum)
  514. if not forum_role['can_upvote_posts']:
  515. raise ACLError403(_("You cannot upvote posts in this forum."))
  516. except KeyError:
  517. raise ACLError403(_("You cannot upvote posts in this forum."))
  518. def allow_post_downvote(self, forum):
  519. try:
  520. forum_role = self.get_role(forum)
  521. if not forum_role['can_downvote_posts']:
  522. raise ACLError403(_("You cannot downvote posts in this forum."))
  523. except KeyError:
  524. raise ACLError403(_("You cannot downvote posts in this forum."))
  525. def allow_post_votes_view(self, forum):
  526. try:
  527. forum_role = self.get_role(forum)
  528. if not forum_role['can_see_votes']:
  529. raise ACLError403(_("You don't have permission to see who voted on this post."))
  530. except KeyError:
  531. raise ACLError403(_("You don't have permission to see who voted on this post."))
  532. def can_make_polls(self, forum):
  533. try:
  534. forum_role = self.get_role(forum)
  535. return forum_role['can_make_polls']
  536. except KeyError:
  537. return False
  538. def can_vote_in_polls(self, forum, thread, poll):
  539. try:
  540. forum_role = self.get_role(forum)
  541. return (forum_role['can_vote_in_polls']
  542. and not forum.closed
  543. and not thread.closed
  544. and not thread.deleted
  545. and not poll.over
  546. and (poll.vote_changing or not poll.user_votes))
  547. except KeyError:
  548. return False
  549. def allow_vote_in_polls(self, forum, thread, poll):
  550. try:
  551. forum_role = self.get_role(forum)
  552. if not forum_role['can_vote_in_polls']:
  553. raise ACLError403(_("You don't have permission to vote polls."))
  554. if poll.over:
  555. raise ACLError403(_("This poll has ended."))
  556. if forum.closed or thread.closed:
  557. raise ACLError403(_("This poll has been closed."))
  558. if thread.deleted:
  559. raise ACLError403(_("This poll's thread has been deleted."))
  560. if poll.user_votes and not poll.vote_changing:
  561. raise ACLError403(_("You have already voted in this poll."))
  562. except KeyError:
  563. raise ACLError403(_("You don't have permission to vote in this poll."))
  564. def can_see_poll_votes(self, forum, poll):
  565. try:
  566. forum_role = self.get_role(forum)
  567. return forum_role['can_see_poll_votes'] or poll.public
  568. except KeyError:
  569. return False
  570. def allow_see_poll_votes(self, forum, poll):
  571. try:
  572. forum_role = self.get_role(forum)
  573. if not forum_role['can_see_poll_votes'] and not poll.public:
  574. raise ACLError403(_("You don't have permission to see votes in this poll."))
  575. except KeyError:
  576. raise ACLError403(_("You don't have permission to see votes in this poll."))
  577. def can_edit_poll(self, forum, poll):
  578. try:
  579. if poll.over:
  580. return False
  581. forum_role = self.get_role(forum)
  582. if forum_role['can_edit_polls'] == 0:
  583. return True
  584. edition_expires = poll.start_date + timedelta(minutes=forum_role['can_edit_polls'])
  585. return timezone.now() <= edition_expires
  586. except KeyError:
  587. return False
  588. def can_delete_poll(self, forum, poll):
  589. try:
  590. forum_role = self.get_role(forum)
  591. if not forum_role['can_delete_polls']:
  592. return False
  593. if forum_role['can_edit_threads_posts']:
  594. return True
  595. if poll.over:
  596. return False
  597. if forum_role['can_delete_polls'] == 1:
  598. edition_expires = poll.start_date + timedelta(minutes=forum_role['can_edit_polls'])
  599. return timezone.now() <= edition_expires
  600. return True
  601. except KeyError:
  602. return False
  603. def can_upload_attachments(self, forum):
  604. try:
  605. forum_role = self.get_role(forum)
  606. return forum_role['can_upload_attachments']
  607. except KeyError:
  608. return False
  609. def allow_upload_attachments(self, forum):
  610. if not self.can_upload_attachments(forum):
  611. raise ACLError403(_("You don't have permission to upload files in this forum."))
  612. def attachment_size_limit(self, forum):
  613. try:
  614. forum_role = self.get_role(forum)
  615. return forum_role['attachment_size']
  616. except KeyError:
  617. return -1
  618. def attachments_limit(self, forum):
  619. try:
  620. forum_role = self.get_role(forum)
  621. return forum_role['attachment_limit']
  622. except KeyError:
  623. return -1
  624. def can_see_all_checkpoints(self, forum):
  625. try:
  626. forum_role = self.get_role(forum)
  627. return forum_role['can_see_deleted_checkpoints']
  628. except KeyError:
  629. return False
  630. def can_delete_checkpoint(self, forum):
  631. try:
  632. forum_role = self.get_role(forum)
  633. return forum_role['can_delete_checkpoints']
  634. except KeyError:
  635. return False
  636. def allow_checkpoint_view(self, forum, checkpoint):
  637. if checkpoint.deleted:
  638. try:
  639. forum_role = self.get_role(forum)
  640. if not forum_role['can_see_deleted_checkpoints']:
  641. raise ACLError403(_("Selected checkpoint could not be found."))
  642. except KeyError:
  643. raise ACLError403(_("Selected checkpoint could not be found."))
  644. def allow_checkpoint_hide(self, forum):
  645. try:
  646. forum_role = self.get_role(forum)
  647. if not forum_role['can_delete_checkpoints']:
  648. raise ACLError403(_("You cannot hide checkpoints!"))
  649. except KeyError:
  650. raise ACLError403(_("You cannot hide checkpoints!"))
  651. def allow_checkpoint_delete(self, forum):
  652. try:
  653. forum_role = self.get_role(forum)
  654. if forum_role['can_delete_checkpoints'] != 2:
  655. raise ACLError403(_("You cannot delete checkpoints!"))
  656. except KeyError:
  657. raise ACLError403(_("You cannot delete checkpoints!"))
  658. def allow_checkpoint_show(self, forum):
  659. try:
  660. forum_role = self.get_role(forum)
  661. if not forum_role['can_delete_checkpoints']:
  662. raise ACLError403(_("You cannot show checkpoints!"))
  663. except KeyError:
  664. raise ACLError403(_("You cannot show checkpoints!"))
  665. def build_forums(acl, perms, forums, forum_roles):
  666. acl.threads = ThreadsACL()
  667. for forum in forums:
  668. forum_role = {
  669. 'can_read_threads': 0,
  670. 'can_start_threads': 0,
  671. 'can_edit_own_threads': False,
  672. 'can_soft_delete_own_threads': False,
  673. 'can_write_posts': 0,
  674. 'can_edit_own_posts': False,
  675. 'can_soft_delete_own_posts': False,
  676. 'can_upvote_posts': False,
  677. 'can_downvote_posts': False,
  678. 'can_see_posts_scores': 0,
  679. 'can_see_votes': False,
  680. 'can_make_polls': False,
  681. 'can_vote_in_polls': False,
  682. 'can_see_attachments': False,
  683. 'can_upload_attachments': False,
  684. 'can_download_attachments': False,
  685. 'attachment_size': 100,
  686. 'attachment_limit': 3,
  687. 'can_approve': False,
  688. 'can_change_prefixes': False,
  689. 'can_see_changelog': False,
  690. 'can_pin_threads': 0,
  691. 'can_edit_threads_posts': False,
  692. 'can_move_threads_posts': False,
  693. 'can_close_threads': False,
  694. 'can_protect_posts': False,
  695. 'can_delete_threads': 0,
  696. 'can_delete_posts': 0,
  697. 'can_see_poll_votes': False,
  698. 'can_edit_polls': 15,
  699. 'can_delete_polls': 0,
  700. 'can_delete_attachments': False,
  701. 'can_see_deleted_checkpoints': False,
  702. 'can_delete_checkpoints': 0,
  703. }
  704. for perm in perms:
  705. try:
  706. role = forum_roles[perm['forums'][forum.pk]]
  707. for p in forum_role:
  708. try:
  709. if p == 'can_edit_polls':
  710. if role[p] < forum_role[p]:
  711. forum_role[p] = role[p]
  712. elif p in ['attachment_size', 'attachment_limit'] and role[p] == 0:
  713. forum_role[p] = 0
  714. elif role[p] > forum_role[p]:
  715. forum_role[p] = role[p]
  716. except KeyError:
  717. pass
  718. except KeyError:
  719. pass
  720. acl.threads.acl[forum.pk] = forum_role