threads.py 49 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481
  1. from django import forms
  2. from django.core.exceptions import PermissionDenied
  3. from django.db.models import Q
  4. from django.http import Http404
  5. from django.utils import timezone
  6. from django.utils.translation import gettext_lazy as _
  7. from django.utils.translation import ngettext
  8. from ...acl import algebra
  9. from ...acl.decorators import return_boolean
  10. from ...acl.models import Role
  11. from ...acl.objectacl import add_acl_to_obj
  12. from ...admin.forms import YesNoSwitch
  13. from ...categories.models import Category, CategoryRole
  14. from ...categories.permissions import get_categories_roles
  15. from ..models import Post, Thread
  16. __all__ = [
  17. "allow_see_thread",
  18. "can_see_thread",
  19. "allow_start_thread",
  20. "can_start_thread",
  21. "allow_reply_thread",
  22. "can_reply_thread",
  23. "allow_edit_thread",
  24. "can_edit_thread",
  25. "allow_pin_thread",
  26. "can_pin_thread",
  27. "allow_unhide_thread",
  28. "can_unhide_thread",
  29. "allow_hide_thread",
  30. "can_hide_thread",
  31. "allow_delete_thread",
  32. "can_delete_thread",
  33. "allow_move_thread",
  34. "can_move_thread",
  35. "allow_merge_thread",
  36. "can_merge_thread",
  37. "allow_approve_thread",
  38. "can_approve_thread",
  39. "allow_see_post",
  40. "can_see_post",
  41. "allow_edit_post",
  42. "can_edit_post",
  43. "allow_unhide_post",
  44. "can_unhide_post",
  45. "allow_hide_post",
  46. "can_hide_post",
  47. "allow_delete_post",
  48. "can_delete_post",
  49. "allow_protect_post",
  50. "can_protect_post",
  51. "allow_approve_post",
  52. "can_approve_post",
  53. "allow_move_post",
  54. "can_move_post",
  55. "allow_merge_post",
  56. "can_merge_post",
  57. "allow_unhide_event",
  58. "can_unhide_event",
  59. "allow_split_post",
  60. "can_split_post",
  61. "allow_hide_event",
  62. "can_hide_event",
  63. "allow_delete_event",
  64. "can_delete_event",
  65. "exclude_invisible_threads",
  66. "exclude_invisible_posts",
  67. ]
  68. class RolePermissionsForm(forms.Form):
  69. legend = _("Threads")
  70. can_see_unapproved_content_lists = YesNoSwitch(
  71. label=_("Can see unapproved content list"),
  72. help_text=_(
  73. 'Allows access to "unapproved" tab on threads lists for '
  74. "easy listing of threads that are unapproved or contain "
  75. "unapproved posts. Despite the tab being available on all "
  76. "threads lists, it will only display threads belonging to "
  77. "categories in which the user has permission to approve "
  78. "content."
  79. ),
  80. )
  81. can_see_reported_content_lists = YesNoSwitch(
  82. label=_("Can see reported content list"),
  83. help_text=_(
  84. 'Allows access to "reported" tab on threads lists for '
  85. "easy listing of threads that contain reported posts. "
  86. "Despite the tab being available on all categories "
  87. "threads lists, it will only display threads belonging to "
  88. "categories in which the user has permission to see posts "
  89. "reports."
  90. ),
  91. )
  92. can_omit_flood_protection = YesNoSwitch(
  93. label=_("Can omit flood protection"),
  94. help_text=_("Allows posting more frequently than flood protection would."),
  95. )
  96. class CategoryPermissionsForm(forms.Form):
  97. legend = _("Threads")
  98. can_see_all_threads = forms.TypedChoiceField(
  99. label=_("Can see threads"),
  100. coerce=int,
  101. initial=0,
  102. choices=[(0, _("Started threads")), (1, _("All threads"))],
  103. )
  104. can_start_threads = YesNoSwitch(label=_("Can start threads"))
  105. can_reply_threads = YesNoSwitch(label=_("Can reply to threads"))
  106. can_edit_threads = forms.TypedChoiceField(
  107. label=_("Can edit threads"),
  108. coerce=int,
  109. initial=0,
  110. choices=[(0, _("No")), (1, _("Own threads")), (2, _("All threads"))],
  111. )
  112. can_hide_own_threads = forms.TypedChoiceField(
  113. label=_("Can hide own threads"),
  114. help_text=_(
  115. "Only threads started within time limit and "
  116. "with no replies can be hidden."
  117. ),
  118. coerce=int,
  119. initial=0,
  120. choices=[(0, _("No")), (1, _("Hide threads")), (2, _("Delete threads"))],
  121. )
  122. thread_edit_time = forms.IntegerField(
  123. label=_("Time limit for own threads edits, in minutes"),
  124. help_text=_("Enter 0 to don't limit time for editing own threads."),
  125. initial=0,
  126. min_value=0,
  127. )
  128. can_hide_threads = forms.TypedChoiceField(
  129. label=_("Can hide all threads"),
  130. coerce=int,
  131. initial=0,
  132. choices=[(0, _("No")), (1, _("Hide threads")), (2, _("Delete threads"))],
  133. )
  134. can_pin_threads = forms.TypedChoiceField(
  135. label=_("Can pin threads"),
  136. coerce=int,
  137. initial=0,
  138. choices=[(0, _("No")), (1, _("Locally")), (2, _("Globally"))],
  139. )
  140. can_close_threads = YesNoSwitch(label=_("Can close threads"))
  141. can_move_threads = YesNoSwitch(label=_("Can move threads"))
  142. can_merge_threads = YesNoSwitch(label=_("Can merge threads"))
  143. can_edit_posts = forms.TypedChoiceField(
  144. label=_("Can edit posts"),
  145. coerce=int,
  146. initial=0,
  147. choices=[(0, _("No")), (1, _("Own posts")), (2, _("All posts"))],
  148. )
  149. can_hide_own_posts = forms.TypedChoiceField(
  150. label=_("Can hide own posts"),
  151. help_text=_(
  152. "Only last posts to thread made within edit time limit can be hidden."
  153. ),
  154. coerce=int,
  155. initial=0,
  156. choices=[(0, _("No")), (1, _("Hide posts")), (2, _("Delete posts"))],
  157. )
  158. post_edit_time = forms.IntegerField(
  159. label=_("Time limit for own post edits, in minutes"),
  160. help_text=_("Enter 0 to don't limit time for editing own posts."),
  161. initial=0,
  162. min_value=0,
  163. )
  164. can_hide_posts = forms.TypedChoiceField(
  165. label=_("Can hide all posts"),
  166. coerce=int,
  167. initial=0,
  168. choices=[(0, _("No")), (1, _("Hide posts")), (2, _("Delete posts"))],
  169. )
  170. can_see_posts_likes = forms.TypedChoiceField(
  171. label=_("Can see posts likes"),
  172. coerce=int,
  173. initial=0,
  174. choices=[
  175. (0, _("No")),
  176. (1, _("Number only")),
  177. (2, _("Number and list of likers")),
  178. ],
  179. )
  180. can_like_posts = YesNoSwitch(
  181. label=_("Can like posts"),
  182. help_text=_("Only users with this permission to see likes can like posts."),
  183. )
  184. can_protect_posts = YesNoSwitch(
  185. label=_("Can protect posts"),
  186. help_text=_("Only users with this permission can edit protected posts."),
  187. )
  188. can_move_posts = YesNoSwitch(
  189. label=_("Can move posts"),
  190. help_text=_("Will be able to move posts to other threads."),
  191. )
  192. can_merge_posts = YesNoSwitch(label=_("Can merge posts"))
  193. can_approve_content = YesNoSwitch(
  194. label=_("Can approve content"),
  195. help_text=_("Will be able to see and approve unapproved content."),
  196. )
  197. can_report_content = YesNoSwitch(label=_("Can report posts"))
  198. can_see_reports = YesNoSwitch(label=_("Can see reports"))
  199. can_hide_events = forms.TypedChoiceField(
  200. label=_("Can hide events"),
  201. coerce=int,
  202. initial=0,
  203. choices=[(0, _("No")), (1, _("Hide events")), (2, _("Delete events"))],
  204. )
  205. require_threads_approval = YesNoSwitch(label=_("Require threads approval"))
  206. require_replies_approval = YesNoSwitch(label=_("Require replies approval"))
  207. require_edits_approval = YesNoSwitch(label=_("Require edits approval"))
  208. def change_permissions_form(role):
  209. if isinstance(role, Role) and role.special_role != "anonymous":
  210. return RolePermissionsForm
  211. if isinstance(role, CategoryRole):
  212. return CategoryPermissionsForm
  213. def build_acl(acl, roles, key_name):
  214. acl.update(
  215. {
  216. "can_see_unapproved_content_lists": False,
  217. "can_see_reported_content_lists": False,
  218. "can_omit_flood_protection": False,
  219. "can_approve_content": [],
  220. "can_see_reports": [],
  221. }
  222. )
  223. acl = algebra.sum_acls(
  224. acl,
  225. roles=roles,
  226. key=key_name,
  227. can_see_unapproved_content_lists=algebra.greater,
  228. can_see_reported_content_lists=algebra.greater,
  229. can_omit_flood_protection=algebra.greater,
  230. )
  231. categories_roles = get_categories_roles(roles)
  232. categories = list(Category.objects.all_categories(include_root=True))
  233. for category in categories:
  234. category_acl = acl["categories"].get(category.pk, {"can_browse": 0})
  235. if category_acl["can_browse"]:
  236. category_acl = acl["categories"][category.pk] = build_category_acl(
  237. category_acl, category, categories_roles, key_name
  238. )
  239. if category_acl.get("can_approve_content"):
  240. acl["can_approve_content"].append(category.pk)
  241. if category_acl.get("can_see_reports"):
  242. acl["can_see_reports"].append(category.pk)
  243. return acl
  244. def build_category_acl(acl, category, categories_roles, key_name):
  245. category_roles = categories_roles.get(category.pk, [])
  246. final_acl = {
  247. "can_see_all_threads": 0,
  248. "can_start_threads": 0,
  249. "can_reply_threads": 0,
  250. "can_edit_threads": 0,
  251. "can_edit_posts": 0,
  252. "can_hide_own_threads": 0,
  253. "can_hide_own_posts": 0,
  254. "thread_edit_time": 0,
  255. "post_edit_time": 0,
  256. "can_hide_threads": 0,
  257. "can_hide_posts": 0,
  258. "can_protect_posts": 0,
  259. "can_move_posts": 0,
  260. "can_merge_posts": 0,
  261. "can_pin_threads": 0,
  262. "can_close_threads": 0,
  263. "can_move_threads": 0,
  264. "can_merge_threads": 0,
  265. "can_report_content": 0,
  266. "can_see_reports": 0,
  267. "can_see_posts_likes": 0,
  268. "can_like_posts": 0,
  269. "can_approve_content": 0,
  270. "require_threads_approval": 0,
  271. "require_replies_approval": 0,
  272. "require_edits_approval": 0,
  273. "can_hide_events": 0,
  274. }
  275. final_acl.update(acl)
  276. algebra.sum_acls(
  277. final_acl,
  278. roles=category_roles,
  279. key=key_name,
  280. can_see_all_threads=algebra.greater,
  281. can_start_threads=algebra.greater,
  282. can_reply_threads=algebra.greater,
  283. can_edit_threads=algebra.greater,
  284. can_edit_posts=algebra.greater,
  285. can_hide_threads=algebra.greater,
  286. can_hide_posts=algebra.greater,
  287. can_hide_own_threads=algebra.greater,
  288. can_hide_own_posts=algebra.greater,
  289. thread_edit_time=algebra.greater_or_zero,
  290. post_edit_time=algebra.greater_or_zero,
  291. can_protect_posts=algebra.greater,
  292. can_move_posts=algebra.greater,
  293. can_merge_posts=algebra.greater,
  294. can_pin_threads=algebra.greater,
  295. can_close_threads=algebra.greater,
  296. can_move_threads=algebra.greater,
  297. can_merge_threads=algebra.greater,
  298. can_report_content=algebra.greater,
  299. can_see_reports=algebra.greater,
  300. can_see_posts_likes=algebra.greater,
  301. can_like_posts=algebra.greater,
  302. can_approve_content=algebra.greater,
  303. require_threads_approval=algebra.greater,
  304. require_replies_approval=algebra.greater,
  305. require_edits_approval=algebra.greater,
  306. can_hide_events=algebra.greater,
  307. )
  308. return final_acl
  309. def add_acl_to_category(user_acl, category):
  310. category_acl = user_acl["categories"].get(category.pk, {})
  311. category.acl.update(
  312. {
  313. "can_see_all_threads": 0,
  314. "can_see_own_threads": 0,
  315. "can_start_threads": 0,
  316. "can_reply_threads": 0,
  317. "can_edit_threads": 0,
  318. "can_edit_posts": 0,
  319. "can_hide_own_threads": 0,
  320. "can_hide_own_posts": 0,
  321. "thread_edit_time": 0,
  322. "post_edit_time": 0,
  323. "can_hide_threads": 0,
  324. "can_hide_posts": 0,
  325. "can_protect_posts": 0,
  326. "can_move_posts": 0,
  327. "can_merge_posts": 0,
  328. "can_pin_threads": 0,
  329. "can_close_threads": 0,
  330. "can_move_threads": 0,
  331. "can_merge_threads": 0,
  332. "can_report_content": 0,
  333. "can_see_reports": 0,
  334. "can_see_posts_likes": 0,
  335. "can_like_posts": 0,
  336. "can_approve_content": 0,
  337. "require_threads_approval": category.require_threads_approval,
  338. "require_replies_approval": category.require_replies_approval,
  339. "require_edits_approval": category.require_edits_approval,
  340. "can_hide_events": 0,
  341. }
  342. )
  343. algebra.sum_acls(
  344. category.acl,
  345. acls=[category_acl],
  346. can_see_all_threads=algebra.greater,
  347. can_see_posts_likes=algebra.greater,
  348. )
  349. if user_acl["is_authenticated"]:
  350. algebra.sum_acls(
  351. category.acl,
  352. acls=[category_acl],
  353. can_start_threads=algebra.greater,
  354. can_reply_threads=algebra.greater,
  355. can_edit_threads=algebra.greater,
  356. can_edit_posts=algebra.greater,
  357. can_hide_threads=algebra.greater,
  358. can_hide_posts=algebra.greater,
  359. can_hide_own_threads=algebra.greater,
  360. can_hide_own_posts=algebra.greater,
  361. thread_edit_time=algebra.greater_or_zero,
  362. post_edit_time=algebra.greater_or_zero,
  363. can_protect_posts=algebra.greater,
  364. can_move_posts=algebra.greater,
  365. can_merge_posts=algebra.greater,
  366. can_pin_threads=algebra.greater,
  367. can_close_threads=algebra.greater,
  368. can_move_threads=algebra.greater,
  369. can_merge_threads=algebra.greater,
  370. can_report_content=algebra.greater,
  371. can_see_reports=algebra.greater,
  372. can_like_posts=algebra.greater,
  373. can_approve_content=algebra.greater,
  374. require_threads_approval=algebra.greater,
  375. require_replies_approval=algebra.greater,
  376. require_edits_approval=algebra.greater,
  377. can_hide_events=algebra.greater,
  378. )
  379. if user_acl["can_approve_content"]:
  380. category.acl.update(
  381. {
  382. "require_threads_approval": 0,
  383. "require_replies_approval": 0,
  384. "require_edits_approval": 0,
  385. }
  386. )
  387. category.acl["can_see_own_threads"] = not category.acl["can_see_all_threads"]
  388. def add_acl_to_thread(user_acl, thread):
  389. category_acl = user_acl["categories"].get(thread.category_id, {})
  390. thread.acl.update(
  391. {
  392. "can_reply": can_reply_thread(user_acl, thread),
  393. "can_edit": can_edit_thread(user_acl, thread),
  394. "can_pin": can_pin_thread(user_acl, thread),
  395. "can_pin_globally": False,
  396. "can_hide": can_hide_thread(user_acl, thread),
  397. "can_unhide": can_unhide_thread(user_acl, thread),
  398. "can_delete": can_delete_thread(user_acl, thread),
  399. "can_close": category_acl.get("can_close_threads", False),
  400. "can_move": can_move_thread(user_acl, thread),
  401. "can_merge": can_merge_thread(user_acl, thread),
  402. "can_move_posts": category_acl.get("can_move_posts", False),
  403. "can_merge_posts": category_acl.get("can_merge_posts", False),
  404. "can_approve": can_approve_thread(user_acl, thread),
  405. "can_see_reports": category_acl.get("can_see_reports", False),
  406. }
  407. )
  408. if thread.acl["can_pin"] and category_acl.get("can_pin_threads") == 2:
  409. thread.acl["can_pin_globally"] = True
  410. def add_acl_to_post(user_acl, post):
  411. if post.is_event:
  412. add_acl_to_event(user_acl, post)
  413. else:
  414. add_acl_to_reply(user_acl, post)
  415. def add_acl_to_event(user_acl, event):
  416. can_hide_events = 0
  417. if user_acl["is_authenticated"]:
  418. category_acl = user_acl["categories"].get(
  419. event.category_id, {"can_hide_events": 0}
  420. )
  421. can_hide_events = category_acl["can_hide_events"]
  422. event.acl.update(
  423. {
  424. "can_see_hidden": can_hide_events > 0,
  425. "can_hide": can_hide_event(user_acl, event),
  426. "can_delete": can_delete_event(user_acl, event),
  427. }
  428. )
  429. def add_acl_to_reply(user_acl, post):
  430. category_acl = user_acl["categories"].get(post.category_id, {})
  431. post.acl.update(
  432. {
  433. "can_reply": can_reply_thread(user_acl, post.thread),
  434. "can_edit": can_edit_post(user_acl, post),
  435. "can_see_hidden": post.is_first_post or category_acl.get("can_hide_posts"),
  436. "can_unhide": can_unhide_post(user_acl, post),
  437. "can_hide": can_hide_post(user_acl, post),
  438. "can_delete": can_delete_post(user_acl, post),
  439. "can_protect": can_protect_post(user_acl, post),
  440. "can_approve": can_approve_post(user_acl, post),
  441. "can_move": can_move_post(user_acl, post),
  442. "can_merge": can_merge_post(user_acl, post),
  443. "can_report": category_acl.get("can_report_content", False),
  444. "can_see_reports": category_acl.get("can_see_reports", False),
  445. "can_see_likes": category_acl.get("can_see_posts_likes", 0),
  446. "can_like": False,
  447. }
  448. )
  449. if not post.acl["can_see_hidden"]:
  450. post.acl["can_see_hidden"] = post.id == post.thread.first_post_id
  451. if user_acl["is_authenticated"] and post.acl["can_see_likes"]:
  452. post.acl["can_like"] = category_acl.get("can_like_posts", False)
  453. def register_with(registry):
  454. registry.acl_annotator(Category, add_acl_to_category)
  455. registry.acl_annotator(Thread, add_acl_to_thread)
  456. registry.acl_annotator(Post, add_acl_to_post)
  457. def allow_see_thread(user_acl, target):
  458. category_acl = user_acl["categories"].get(
  459. target.category_id, {"can_see": False, "can_browse": False}
  460. )
  461. if not (category_acl["can_see"] and category_acl["can_browse"]):
  462. raise Http404()
  463. if target.is_hidden and (
  464. user_acl["is_anonymous"] or not category_acl["can_hide_threads"]
  465. ):
  466. raise Http404()
  467. if user_acl["is_anonymous"] or user_acl["user_id"] != target.starter_id:
  468. if not category_acl["can_see_all_threads"]:
  469. raise Http404()
  470. if target.is_unapproved and not category_acl["can_approve_content"]:
  471. raise Http404()
  472. can_see_thread = return_boolean(allow_see_thread)
  473. def allow_start_thread(user_acl, target):
  474. if user_acl["is_anonymous"]:
  475. raise PermissionDenied(_("You have to sign in to start threads."))
  476. category_acl = user_acl["categories"].get(target.pk, {"can_start_threads": False})
  477. if not category_acl["can_start_threads"]:
  478. raise PermissionDenied(
  479. _("You don't have permission to start new threads in this category.")
  480. )
  481. if target.is_closed and not category_acl["can_close_threads"]:
  482. raise PermissionDenied(
  483. _("This category is closed. You can't start new threads in it.")
  484. )
  485. can_start_thread = return_boolean(allow_start_thread)
  486. def allow_reply_thread(user_acl, target):
  487. if user_acl["is_anonymous"]:
  488. raise PermissionDenied(_("You have to sign in to reply threads."))
  489. category_acl = user_acl["categories"].get(
  490. target.category_id, {"can_reply_threads": False}
  491. )
  492. if not category_acl["can_reply_threads"]:
  493. raise PermissionDenied(_("You can't reply to threads in this category."))
  494. if not category_acl["can_close_threads"]:
  495. if target.category.is_closed:
  496. raise PermissionDenied(
  497. _("This category is closed. You can't reply to threads in it.")
  498. )
  499. if target.is_closed:
  500. raise PermissionDenied(
  501. _("You can't reply to closed threads in this category.")
  502. )
  503. can_reply_thread = return_boolean(allow_reply_thread)
  504. def allow_edit_thread(user_acl, target):
  505. if user_acl["is_anonymous"]:
  506. raise PermissionDenied(_("You have to sign in to edit threads."))
  507. category_acl = user_acl["categories"].get(
  508. target.category_id, {"can_edit_threads": False}
  509. )
  510. if not category_acl["can_edit_threads"]:
  511. raise PermissionDenied(_("You can't edit threads in this category."))
  512. if category_acl["can_edit_threads"] == 1:
  513. if user_acl["user_id"] != target.starter_id:
  514. raise PermissionDenied(
  515. _("You can't edit other users threads in this category.")
  516. )
  517. if not has_time_to_edit_thread(user_acl, target):
  518. message = ngettext(
  519. "You can't edit threads that are older than %(minutes)s minute.",
  520. "You can't edit threads that are older than %(minutes)s minutes.",
  521. category_acl["thread_edit_time"],
  522. )
  523. raise PermissionDenied(
  524. message % {"minutes": category_acl["thread_edit_time"]}
  525. )
  526. if not category_acl["can_close_threads"]:
  527. if target.category.is_closed:
  528. raise PermissionDenied(
  529. _("This category is closed. You can't edit threads in it.")
  530. )
  531. if target.is_closed:
  532. raise PermissionDenied(_("This thread is closed. You can't edit it."))
  533. can_edit_thread = return_boolean(allow_edit_thread)
  534. def allow_pin_thread(user_acl, target):
  535. if user_acl["is_anonymous"]:
  536. raise PermissionDenied(_("You have to sign in to change threads weights."))
  537. category_acl = user_acl["categories"].get(
  538. target.category_id, {"can_pin_threads": 0}
  539. )
  540. if not category_acl["can_pin_threads"]:
  541. raise PermissionDenied(_("You can't change threads weights in this category."))
  542. if not category_acl["can_close_threads"]:
  543. if target.category.is_closed:
  544. raise PermissionDenied(
  545. _("This category is closed. You can't change threads weights in it.")
  546. )
  547. if target.is_closed:
  548. raise PermissionDenied(
  549. _("This thread is closed. You can't change its weight.")
  550. )
  551. can_pin_thread = return_boolean(allow_pin_thread)
  552. def allow_unhide_thread(user_acl, target):
  553. if user_acl["is_anonymous"]:
  554. raise PermissionDenied(_("You have to sign in to hide threads."))
  555. category_acl = user_acl["categories"].get(
  556. target.category_id, {"can_close_threads": False}
  557. )
  558. if not category_acl["can_close_threads"]:
  559. if target.category.is_closed:
  560. raise PermissionDenied(
  561. _("This category is closed. You can't reveal threads in it.")
  562. )
  563. if target.is_closed:
  564. raise PermissionDenied(_("This thread is closed. You can't reveal it."))
  565. can_unhide_thread = return_boolean(allow_unhide_thread)
  566. def allow_hide_thread(user_acl, target):
  567. if user_acl["is_anonymous"]:
  568. raise PermissionDenied(_("You have to sign in to hide threads."))
  569. category_acl = user_acl["categories"].get(
  570. target.category_id, {"can_hide_threads": 0, "can_hide_own_threads": 0}
  571. )
  572. if (
  573. not category_acl["can_hide_threads"]
  574. and not category_acl["can_hide_own_threads"]
  575. ):
  576. raise PermissionDenied(_("You can't hide threads in this category."))
  577. if not category_acl["can_hide_threads"] and category_acl["can_hide_own_threads"]:
  578. if user_acl["user_id"] != target.starter_id:
  579. raise PermissionDenied(
  580. _("You can't hide other users theads in this category.")
  581. )
  582. if not has_time_to_edit_thread(user_acl, target):
  583. message = ngettext(
  584. "You can't hide threads that are older than %(minutes)s minute.",
  585. "You can't hide threads that are older than %(minutes)s minutes.",
  586. category_acl["thread_edit_time"],
  587. )
  588. raise PermissionDenied(
  589. message % {"minutes": category_acl["thread_edit_time"]}
  590. )
  591. if not category_acl["can_close_threads"]:
  592. if target.category.is_closed:
  593. raise PermissionDenied(
  594. _("This category is closed. You can't hide threads in it.")
  595. )
  596. if target.is_closed:
  597. raise PermissionDenied(_("This thread is closed. You can't hide it."))
  598. can_hide_thread = return_boolean(allow_hide_thread)
  599. def allow_delete_thread(user_acl, target):
  600. if user_acl["is_anonymous"]:
  601. raise PermissionDenied(_("You have to sign in to delete threads."))
  602. category_acl = user_acl["categories"].get(
  603. target.category_id, {"can_hide_threads": 0, "can_hide_own_threads": 0}
  604. )
  605. if (
  606. category_acl["can_hide_threads"] != 2
  607. and category_acl["can_hide_own_threads"] != 2
  608. ):
  609. raise PermissionDenied(_("You can't delete threads in this category."))
  610. if (
  611. category_acl["can_hide_threads"] != 2
  612. and category_acl["can_hide_own_threads"] == 2
  613. ):
  614. if user_acl["user_id"] != target.starter_id:
  615. raise PermissionDenied(
  616. _("You can't delete other users theads in this category.")
  617. )
  618. if not has_time_to_edit_thread(user_acl, target):
  619. message = ngettext(
  620. "You can't delete threads that are older than %(minutes)s minute.",
  621. "You can't delete threads that are older than %(minutes)s minutes.",
  622. category_acl["thread_edit_time"],
  623. )
  624. raise PermissionDenied(
  625. message % {"minutes": category_acl["thread_edit_time"]}
  626. )
  627. if not category_acl["can_close_threads"]:
  628. if target.category.is_closed:
  629. raise PermissionDenied(
  630. _("This category is closed. You can't delete threads in it.")
  631. )
  632. if target.is_closed:
  633. raise PermissionDenied(_("This thread is closed. You can't delete it."))
  634. can_delete_thread = return_boolean(allow_delete_thread)
  635. def allow_move_thread(user_acl, target):
  636. if user_acl["is_anonymous"]:
  637. raise PermissionDenied(_("You have to sign in to move threads."))
  638. category_acl = user_acl["categories"].get(
  639. target.category_id, {"can_move_threads": 0}
  640. )
  641. if not category_acl["can_move_threads"]:
  642. raise PermissionDenied(_("You can't move threads in this category."))
  643. if not category_acl["can_close_threads"]:
  644. if target.category.is_closed:
  645. raise PermissionDenied(
  646. _("This category is closed. You can't move it's threads.")
  647. )
  648. if target.is_closed:
  649. raise PermissionDenied(_("This thread is closed. You can't move it."))
  650. can_move_thread = return_boolean(allow_move_thread)
  651. def allow_merge_thread(user_acl, target, otherthread=False):
  652. if user_acl["is_anonymous"]:
  653. raise PermissionDenied(_("You have to sign in to merge threads."))
  654. category_acl = user_acl["categories"].get(
  655. target.category_id, {"can_merge_threads": 0}
  656. )
  657. if not category_acl["can_merge_threads"]:
  658. if otherthread:
  659. raise PermissionDenied(_("Other thread can't be merged with."))
  660. raise PermissionDenied(_("You can't merge threads in this category."))
  661. if not category_acl["can_close_threads"]:
  662. if target.category.is_closed:
  663. if otherthread:
  664. raise PermissionDenied(
  665. _("Other thread's category is closed. You can't merge with it.")
  666. )
  667. raise PermissionDenied(
  668. _("This category is closed. You can't merge it's threads.")
  669. )
  670. if target.is_closed:
  671. if otherthread:
  672. raise PermissionDenied(
  673. _("Other thread is closed and can't be merged with.")
  674. )
  675. raise PermissionDenied(
  676. _("This thread is closed. You can't merge it with other threads.")
  677. )
  678. can_merge_thread = return_boolean(allow_merge_thread)
  679. def allow_approve_thread(user_acl, target):
  680. if user_acl["is_anonymous"]:
  681. raise PermissionDenied(_("You have to sign in to approve threads."))
  682. category_acl = user_acl["categories"].get(
  683. target.category_id, {"can_approve_content": 0}
  684. )
  685. if not category_acl["can_approve_content"]:
  686. raise PermissionDenied(_("You can't approve threads in this category."))
  687. if not category_acl["can_close_threads"]:
  688. if target.category.is_closed:
  689. raise PermissionDenied(
  690. _("This category is closed. You can't approve threads in it.")
  691. )
  692. if target.is_closed:
  693. raise PermissionDenied(_("This thread is closed. You can't approve it."))
  694. can_approve_thread = return_boolean(allow_approve_thread)
  695. def allow_see_post(user_acl, target):
  696. category_acl = user_acl["categories"].get(
  697. target.category_id, {"can_approve_content": False, "can_hide_events": False}
  698. )
  699. if not target.is_event and target.is_unapproved:
  700. if user_acl["is_anonymous"]:
  701. raise Http404()
  702. if (
  703. not category_acl["can_approve_content"]
  704. and user_acl["user_id"] != target.poster_id
  705. ):
  706. raise Http404()
  707. if target.is_event and target.is_hidden and not category_acl["can_hide_events"]:
  708. raise Http404()
  709. can_see_post = return_boolean(allow_see_post)
  710. def allow_edit_post(user_acl, target):
  711. if user_acl["is_anonymous"]:
  712. raise PermissionDenied(_("You have to sign in to edit posts."))
  713. if target.is_event:
  714. raise PermissionDenied(_("Events can't be edited."))
  715. category_acl = user_acl["categories"].get(
  716. target.category_id, {"can_edit_posts": False}
  717. )
  718. if not category_acl["can_edit_posts"]:
  719. raise PermissionDenied(_("You can't edit posts in this category."))
  720. if (
  721. target.is_hidden
  722. and not target.is_first_post
  723. and not category_acl["can_hide_posts"]
  724. ):
  725. raise PermissionDenied(_("This post is hidden, you can't edit it."))
  726. if category_acl["can_edit_posts"] == 1:
  727. if target.poster_id != user_acl["user_id"]:
  728. raise PermissionDenied(
  729. _("You can't edit other users posts in this category.")
  730. )
  731. if target.is_protected and not category_acl["can_protect_posts"]:
  732. raise PermissionDenied(_("This post is protected. You can't edit it."))
  733. if not has_time_to_edit_post(user_acl, target):
  734. message = ngettext(
  735. "You can't edit posts that are older than %(minutes)s minute.",
  736. "You can't edit posts that are older than %(minutes)s minutes.",
  737. category_acl["post_edit_time"],
  738. )
  739. raise PermissionDenied(
  740. message % {"minutes": category_acl["post_edit_time"]}
  741. )
  742. if not category_acl["can_close_threads"]:
  743. if target.category.is_closed:
  744. raise PermissionDenied(
  745. _("This category is closed. You can't edit posts in it.")
  746. )
  747. if target.thread.is_closed:
  748. raise PermissionDenied(
  749. _("This thread is closed. You can't edit posts in it.")
  750. )
  751. can_edit_post = return_boolean(allow_edit_post)
  752. def allow_unhide_post(user_acl, target):
  753. if user_acl["is_anonymous"]:
  754. raise PermissionDenied(_("You have to sign in to reveal posts."))
  755. category_acl = user_acl["categories"].get(
  756. target.category_id, {"can_hide_posts": 0, "can_hide_own_posts": 0}
  757. )
  758. if not category_acl["can_hide_posts"]:
  759. if not category_acl["can_hide_own_posts"]:
  760. raise PermissionDenied(_("You can't reveal posts in this category."))
  761. if user_acl["user_id"] != target.poster_id:
  762. raise PermissionDenied(
  763. _("You can't reveal other users posts in this category.")
  764. )
  765. if target.is_protected and not category_acl["can_protect_posts"]:
  766. raise PermissionDenied(_("This post is protected. You can't reveal it."))
  767. if not has_time_to_edit_post(user_acl, target):
  768. message = ngettext(
  769. "You can't reveal posts that are older than %(minutes)s minute.",
  770. "You can't reveal posts that are older than %(minutes)s minutes.",
  771. category_acl["post_edit_time"],
  772. )
  773. raise PermissionDenied(
  774. message % {"minutes": category_acl["post_edit_time"]}
  775. )
  776. if target.is_first_post:
  777. raise PermissionDenied(_("You can't reveal thread's first post."))
  778. if not category_acl["can_close_threads"]:
  779. if target.category.is_closed:
  780. raise PermissionDenied(
  781. _("This category is closed. You can't reveal posts in it.")
  782. )
  783. if target.thread.is_closed:
  784. raise PermissionDenied(
  785. _("This thread is closed. You can't reveal posts in it.")
  786. )
  787. can_unhide_post = return_boolean(allow_unhide_post)
  788. def allow_hide_post(user_acl, target):
  789. if user_acl["is_anonymous"]:
  790. raise PermissionDenied(_("You have to sign in to hide posts."))
  791. category_acl = user_acl["categories"].get(
  792. target.category_id, {"can_hide_posts": 0, "can_hide_own_posts": 0}
  793. )
  794. if not category_acl["can_hide_posts"]:
  795. if not category_acl["can_hide_own_posts"]:
  796. raise PermissionDenied(_("You can't hide posts in this category."))
  797. if user_acl["user_id"] != target.poster_id:
  798. raise PermissionDenied(
  799. _("You can't hide other users posts in this category.")
  800. )
  801. if target.is_protected and not category_acl["can_protect_posts"]:
  802. raise PermissionDenied(_("This post is protected. You can't hide it."))
  803. if not has_time_to_edit_post(user_acl, target):
  804. message = ngettext(
  805. "You can't hide posts that are older than %(minutes)s minute.",
  806. "You can't hide posts that are older than %(minutes)s minutes.",
  807. category_acl["post_edit_time"],
  808. )
  809. raise PermissionDenied(
  810. message % {"minutes": category_acl["post_edit_time"]}
  811. )
  812. if target.is_first_post:
  813. raise PermissionDenied(_("You can't hide thread's first post."))
  814. if not category_acl["can_close_threads"]:
  815. if target.category.is_closed:
  816. raise PermissionDenied(
  817. _("This category is closed. You can't hide posts in it.")
  818. )
  819. if target.thread.is_closed:
  820. raise PermissionDenied(
  821. _("This thread is closed. You can't hide posts in it.")
  822. )
  823. can_hide_post = return_boolean(allow_hide_post)
  824. def allow_delete_post(user_acl, target):
  825. if user_acl["is_anonymous"]:
  826. raise PermissionDenied(_("You have to sign in to delete posts."))
  827. category_acl = user_acl["categories"].get(
  828. target.category_id, {"can_hide_posts": 0, "can_hide_own_posts": 0}
  829. )
  830. if category_acl["can_hide_posts"] != 2:
  831. if category_acl["can_hide_own_posts"] != 2:
  832. raise PermissionDenied(_("You can't delete posts in this category."))
  833. if user_acl["user_id"] != target.poster_id:
  834. raise PermissionDenied(
  835. _("You can't delete other users posts in this category.")
  836. )
  837. if target.is_protected and not category_acl["can_protect_posts"]:
  838. raise PermissionDenied(_("This post is protected. You can't delete it."))
  839. if not has_time_to_edit_post(user_acl, target):
  840. message = ngettext(
  841. "You can't delete posts that are older than %(minutes)s minute.",
  842. "You can't delete posts that are older than %(minutes)s minutes.",
  843. category_acl["post_edit_time"],
  844. )
  845. raise PermissionDenied(
  846. message % {"minutes": category_acl["post_edit_time"]}
  847. )
  848. if target.is_first_post:
  849. raise PermissionDenied(_("You can't delete thread's first post."))
  850. if not category_acl["can_close_threads"]:
  851. if target.category.is_closed:
  852. raise PermissionDenied(
  853. _("This category is closed. You can't delete posts in it.")
  854. )
  855. if target.thread.is_closed:
  856. raise PermissionDenied(
  857. _("This thread is closed. You can't delete posts in it.")
  858. )
  859. can_delete_post = return_boolean(allow_delete_post)
  860. def allow_protect_post(user_acl, target):
  861. if user_acl["is_anonymous"]:
  862. raise PermissionDenied(_("You have to sign in to protect posts."))
  863. category_acl = user_acl["categories"].get(
  864. target.category_id, {"can_protect_posts": False}
  865. )
  866. if not category_acl["can_protect_posts"]:
  867. raise PermissionDenied(_("You can't protect posts in this category."))
  868. if not can_edit_post(user_acl, target):
  869. raise PermissionDenied(_("You can't protect posts you can't edit."))
  870. can_protect_post = return_boolean(allow_protect_post)
  871. def allow_approve_post(user_acl, target):
  872. if user_acl["is_anonymous"]:
  873. raise PermissionDenied(_("You have to sign in to approve posts."))
  874. category_acl = user_acl["categories"].get(
  875. target.category_id, {"can_approve_content": False}
  876. )
  877. if not category_acl["can_approve_content"]:
  878. raise PermissionDenied(_("You can't approve posts in this category."))
  879. if target.is_first_post:
  880. raise PermissionDenied(_("You can't approve thread's first post."))
  881. if (
  882. not target.is_first_post
  883. and not category_acl["can_hide_posts"]
  884. and target.is_hidden
  885. ):
  886. raise PermissionDenied(_("You can't approve posts the content you can't see."))
  887. if not category_acl["can_close_threads"]:
  888. if target.category.is_closed:
  889. raise PermissionDenied(
  890. _("This category is closed. You can't approve posts in it.")
  891. )
  892. if target.thread.is_closed:
  893. raise PermissionDenied(
  894. _("This thread is closed. You can't approve posts in it.")
  895. )
  896. can_approve_post = return_boolean(allow_approve_post)
  897. def allow_move_post(user_acl, target):
  898. if user_acl["is_anonymous"]:
  899. raise PermissionDenied(_("You have to sign in to move posts."))
  900. category_acl = user_acl["categories"].get(
  901. target.category_id, {"can_move_posts": False}
  902. )
  903. if not category_acl["can_move_posts"]:
  904. raise PermissionDenied(_("You can't move posts in this category."))
  905. if target.is_event:
  906. raise PermissionDenied(_("Events can't be moved."))
  907. if target.is_first_post:
  908. raise PermissionDenied(_("You can't move thread's first post."))
  909. if not category_acl["can_hide_posts"] and target.is_hidden:
  910. raise PermissionDenied(_("You can't move posts the content you can't see."))
  911. if not category_acl["can_close_threads"]:
  912. if target.category.is_closed:
  913. raise PermissionDenied(
  914. _("This category is closed. You can't move posts in it.")
  915. )
  916. if target.thread.is_closed:
  917. raise PermissionDenied(
  918. _("This thread is closed. You can't move posts in it.")
  919. )
  920. can_move_post = return_boolean(allow_move_post)
  921. def allow_merge_post(user_acl, target):
  922. if user_acl["is_anonymous"]:
  923. raise PermissionDenied(_("You have to sign in to merge posts."))
  924. category_acl = user_acl["categories"].get(
  925. target.category_id, {"can_merge_posts": False}
  926. )
  927. if not category_acl["can_merge_posts"]:
  928. raise PermissionDenied(_("You can't merge posts in this category."))
  929. if target.is_event:
  930. raise PermissionDenied(_("Events can't be merged."))
  931. if (
  932. target.is_hidden
  933. and not category_acl["can_hide_posts"]
  934. and not target.is_first_post
  935. ):
  936. raise PermissionDenied(_("You can't merge posts the content you can't see."))
  937. if not category_acl["can_close_threads"]:
  938. if target.category.is_closed:
  939. raise PermissionDenied(
  940. _("This category is closed. You can't merge posts in it.")
  941. )
  942. if target.thread.is_closed:
  943. raise PermissionDenied(
  944. _("This thread is closed. You can't merge posts in it.")
  945. )
  946. can_merge_post = return_boolean(allow_merge_post)
  947. def allow_split_post(user_acl, target):
  948. if user_acl["is_anonymous"]:
  949. raise PermissionDenied(_("You have to sign in to split posts."))
  950. category_acl = user_acl["categories"].get(
  951. target.category_id, {"can_move_posts": False}
  952. )
  953. if not category_acl["can_move_posts"]:
  954. raise PermissionDenied(_("You can't split posts in this category."))
  955. if target.is_event:
  956. raise PermissionDenied(_("Events can't be split."))
  957. if target.is_first_post:
  958. raise PermissionDenied(_("You can't split thread's first post."))
  959. if not category_acl["can_hide_posts"] and target.is_hidden:
  960. raise PermissionDenied(_("You can't split posts the content you can't see."))
  961. if not category_acl["can_close_threads"]:
  962. if target.category.is_closed:
  963. raise PermissionDenied(
  964. _("This category is closed. You can't split posts in it.")
  965. )
  966. if target.thread.is_closed:
  967. raise PermissionDenied(
  968. _("This thread is closed. You can't split posts in it.")
  969. )
  970. can_split_post = return_boolean(allow_split_post)
  971. def allow_unhide_event(user_acl, target):
  972. if user_acl["is_anonymous"]:
  973. raise PermissionDenied(_("You have to sign in to reveal events."))
  974. category_acl = user_acl["categories"].get(
  975. target.category_id, {"can_hide_events": 0}
  976. )
  977. if not category_acl["can_hide_events"]:
  978. raise PermissionDenied(_("You can't reveal events in this category."))
  979. if not category_acl["can_close_threads"]:
  980. if target.category.is_closed:
  981. raise PermissionDenied(
  982. _("This category is closed. You can't reveal events in it.")
  983. )
  984. if target.thread.is_closed:
  985. raise PermissionDenied(
  986. _("This thread is closed. You can't reveal events in it.")
  987. )
  988. can_unhide_event = return_boolean(allow_unhide_event)
  989. def allow_hide_event(user_acl, target):
  990. if user_acl["is_anonymous"]:
  991. raise PermissionDenied(_("You have to sign in to hide events."))
  992. category_acl = user_acl["categories"].get(
  993. target.category_id, {"can_hide_events": 0}
  994. )
  995. if not category_acl["can_hide_events"]:
  996. raise PermissionDenied(_("You can't hide events in this category."))
  997. if not category_acl["can_close_threads"]:
  998. if target.category.is_closed:
  999. raise PermissionDenied(
  1000. _("This category is closed. You can't hide events in it.")
  1001. )
  1002. if target.thread.is_closed:
  1003. raise PermissionDenied(
  1004. _("This thread is closed. You can't hide events in it.")
  1005. )
  1006. can_hide_event = return_boolean(allow_hide_event)
  1007. def allow_delete_event(user_acl, target):
  1008. if user_acl["is_anonymous"]:
  1009. raise PermissionDenied(_("You have to sign in to delete events."))
  1010. category_acl = user_acl["categories"].get(
  1011. target.category_id, {"can_hide_events": 0}
  1012. )
  1013. if category_acl["can_hide_events"] != 2:
  1014. raise PermissionDenied(_("You can't delete events in this category."))
  1015. if not category_acl["can_close_threads"]:
  1016. if target.category.is_closed:
  1017. raise PermissionDenied(
  1018. _("This category is closed. You can't delete events in it.")
  1019. )
  1020. if target.thread.is_closed:
  1021. raise PermissionDenied(
  1022. _("This thread is closed. You can't delete events in it.")
  1023. )
  1024. can_delete_event = return_boolean(allow_delete_event)
  1025. def can_change_owned_thread(user_acl, target):
  1026. if user_acl["is_anonymous"] or user_acl["user_id"] != target.starter_id:
  1027. return False
  1028. if target.category.is_closed or target.is_closed:
  1029. return False
  1030. return has_time_to_edit_thread(user_acl, target)
  1031. def has_time_to_edit_thread(user_acl, target):
  1032. edit_time = (
  1033. user_acl["categories"].get(target.category_id, {}).get("thread_edit_time", 0)
  1034. )
  1035. if edit_time:
  1036. diff = timezone.now() - target.started_on
  1037. diff_minutes = int(diff.total_seconds() / 60)
  1038. return diff_minutes < edit_time
  1039. return True
  1040. def has_time_to_edit_post(user_acl, target):
  1041. edit_time = (
  1042. user_acl["categories"].get(target.category_id, {}).get("post_edit_time", 0)
  1043. )
  1044. if edit_time:
  1045. diff = timezone.now() - target.posted_on
  1046. diff_minutes = int(diff.total_seconds() / 60)
  1047. return diff_minutes < edit_time
  1048. return True
  1049. def exclude_invisible_threads(user_acl, categories, queryset):
  1050. show_all = []
  1051. show_accepted_visible = []
  1052. show_accepted = []
  1053. show_visible = []
  1054. show_owned = []
  1055. show_owned_visible = []
  1056. for category in categories:
  1057. add_acl_to_obj(user_acl, category)
  1058. if not (category.acl["can_see"] and category.acl["can_browse"]):
  1059. continue
  1060. can_hide = category.acl["can_hide_threads"]
  1061. if category.acl["can_see_all_threads"]:
  1062. can_mod = category.acl["can_approve_content"]
  1063. if can_mod and can_hide:
  1064. show_all.append(category)
  1065. elif user_acl["is_authenticated"]:
  1066. if not can_mod and not can_hide:
  1067. show_accepted_visible.append(category)
  1068. elif not can_mod:
  1069. show_accepted.append(category)
  1070. elif not can_hide:
  1071. show_visible.append(category)
  1072. else:
  1073. show_accepted_visible.append(category)
  1074. elif user_acl["is_authenticated"]:
  1075. if can_hide:
  1076. show_owned.append(category)
  1077. else:
  1078. show_owned_visible.append(category)
  1079. conditions = None
  1080. if show_all:
  1081. conditions = Q(category__in=show_all)
  1082. if show_accepted_visible:
  1083. if user_acl["is_authenticated"]:
  1084. condition = Q(
  1085. Q(starter_id=user_acl["user_id"]) | Q(is_unapproved=False),
  1086. category__in=show_accepted_visible,
  1087. is_hidden=False,
  1088. )
  1089. else:
  1090. condition = Q(
  1091. category__in=show_accepted_visible, is_hidden=False, is_unapproved=False
  1092. )
  1093. if conditions:
  1094. conditions = conditions | condition
  1095. else:
  1096. conditions = condition
  1097. if show_accepted:
  1098. condition = Q(
  1099. Q(starter_id=user_acl["user_id"]) | Q(is_unapproved=False),
  1100. category__in=show_accepted,
  1101. )
  1102. if conditions:
  1103. conditions = conditions | condition
  1104. else:
  1105. conditions = condition
  1106. if show_visible:
  1107. condition = Q(category__in=show_visible, is_hidden=False)
  1108. if conditions:
  1109. conditions = conditions | condition
  1110. else:
  1111. conditions = condition
  1112. if show_owned:
  1113. condition = Q(category__in=show_owned, starter_id=user_acl["user_id"])
  1114. if conditions:
  1115. conditions = conditions | condition
  1116. else:
  1117. conditions = condition
  1118. if show_owned_visible:
  1119. condition = Q(
  1120. category__in=show_owned_visible,
  1121. starter_id=user_acl["user_id"],
  1122. is_hidden=False,
  1123. )
  1124. if conditions:
  1125. conditions = conditions | condition
  1126. else:
  1127. conditions = condition
  1128. if not conditions:
  1129. return Thread.objects.none()
  1130. return queryset.filter(conditions)
  1131. def exclude_invisible_posts(user_acl, categories, queryset):
  1132. if hasattr(categories, "__iter__"):
  1133. return exclude_invisible_posts_in_categories(user_acl, categories, queryset)
  1134. return exclude_invisible_posts_in_category(user_acl, categories, queryset)
  1135. def exclude_invisible_posts_in_categories(user_acl, categories, queryset):
  1136. show_all = []
  1137. show_approved = []
  1138. show_approved_owned = []
  1139. hide_invisible_events = []
  1140. for category in categories:
  1141. add_acl_to_obj(user_acl, category)
  1142. if category.acl["can_approve_content"]:
  1143. show_all.append(category.pk)
  1144. else:
  1145. if user_acl["is_authenticated"]:
  1146. show_approved_owned.append(category.pk)
  1147. else:
  1148. show_approved.append(category.pk)
  1149. if not category.acl["can_hide_events"]:
  1150. hide_invisible_events.append(category.pk)
  1151. conditions = None
  1152. if show_all:
  1153. conditions = Q(category__in=show_all)
  1154. if show_approved:
  1155. condition = Q(category__in=show_approved, is_unapproved=False)
  1156. if conditions:
  1157. conditions = conditions | condition
  1158. else:
  1159. conditions = condition
  1160. if show_approved_owned:
  1161. condition = Q(
  1162. Q(poster_id=user_acl["user_id"]) | Q(is_unapproved=False),
  1163. category__in=show_approved_owned,
  1164. )
  1165. if conditions:
  1166. conditions = conditions | condition
  1167. else:
  1168. conditions = condition
  1169. if hide_invisible_events:
  1170. queryset = queryset.exclude(
  1171. category__in=hide_invisible_events, is_event=True, is_hidden=True
  1172. )
  1173. if not conditions:
  1174. return Post.objects.none()
  1175. return queryset.filter(conditions)
  1176. def exclude_invisible_posts_in_category(user_acl, category, queryset):
  1177. add_acl_to_obj(user_acl, category)
  1178. if not category.acl["can_approve_content"]:
  1179. if user_acl["is_authenticated"]:
  1180. queryset = queryset.filter(
  1181. Q(is_unapproved=False) | Q(poster_id=user_acl["user_id"])
  1182. )
  1183. else:
  1184. queryset = queryset.exclude(is_unapproved=True)
  1185. if not category.acl["can_hide_events"]:
  1186. queryset = queryset.exclude(is_event=True, is_hidden=True)
  1187. return queryset