threads.py 49 KB

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