threads.py 49 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485
  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(
  1050. user_acl, categories, queryset
  1051. ): # pylint: disable=too-many-branches
  1052. show_all = []
  1053. show_accepted_visible = []
  1054. show_accepted = []
  1055. show_visible = []
  1056. show_owned = []
  1057. show_owned_visible = []
  1058. for category in categories:
  1059. add_acl_to_obj(user_acl, category)
  1060. if not (category.acl["can_see"] and category.acl["can_browse"]):
  1061. continue
  1062. can_hide = category.acl["can_hide_threads"]
  1063. if category.acl["can_see_all_threads"]:
  1064. can_mod = category.acl["can_approve_content"]
  1065. if can_mod and can_hide:
  1066. show_all.append(category)
  1067. elif user_acl["is_authenticated"]:
  1068. if not can_mod and not can_hide:
  1069. show_accepted_visible.append(category)
  1070. elif not can_mod:
  1071. show_accepted.append(category)
  1072. elif not can_hide:
  1073. show_visible.append(category)
  1074. else:
  1075. show_accepted_visible.append(category)
  1076. elif user_acl["is_authenticated"]:
  1077. if can_hide:
  1078. show_owned.append(category)
  1079. else:
  1080. show_owned_visible.append(category)
  1081. conditions = None
  1082. if show_all:
  1083. conditions = Q(category__in=show_all)
  1084. if show_accepted_visible:
  1085. if user_acl["is_authenticated"]:
  1086. condition = Q(
  1087. Q(starter_id=user_acl["user_id"]) | Q(is_unapproved=False),
  1088. category__in=show_accepted_visible,
  1089. is_hidden=False,
  1090. )
  1091. else:
  1092. condition = Q(
  1093. category__in=show_accepted_visible, is_hidden=False, is_unapproved=False
  1094. )
  1095. if conditions:
  1096. conditions = conditions | condition
  1097. else:
  1098. conditions = condition
  1099. if show_accepted:
  1100. condition = Q(
  1101. Q(starter_id=user_acl["user_id"]) | Q(is_unapproved=False),
  1102. category__in=show_accepted,
  1103. )
  1104. if conditions:
  1105. conditions = conditions | condition
  1106. else:
  1107. conditions = condition
  1108. if show_visible:
  1109. condition = Q(category__in=show_visible, is_hidden=False)
  1110. if conditions:
  1111. conditions = conditions | condition
  1112. else:
  1113. conditions = condition
  1114. if show_owned:
  1115. condition = Q(category__in=show_owned, starter_id=user_acl["user_id"])
  1116. if conditions:
  1117. conditions = conditions | condition
  1118. else:
  1119. conditions = condition
  1120. if show_owned_visible:
  1121. condition = Q(
  1122. category__in=show_owned_visible,
  1123. starter_id=user_acl["user_id"],
  1124. is_hidden=False,
  1125. )
  1126. if conditions:
  1127. conditions = conditions | condition
  1128. else:
  1129. conditions = condition
  1130. if not conditions:
  1131. return Thread.objects.none()
  1132. return queryset.filter(conditions)
  1133. def exclude_invisible_posts(user_acl, categories, queryset):
  1134. if hasattr(categories, "__iter__"):
  1135. return exclude_invisible_posts_in_categories(user_acl, categories, queryset)
  1136. return exclude_invisible_posts_in_category(user_acl, categories, queryset)
  1137. def exclude_invisible_posts_in_categories(
  1138. user_acl, categories, queryset
  1139. ): # pylint: disable=too-many-branches
  1140. show_all = []
  1141. show_approved = []
  1142. show_approved_owned = []
  1143. hide_invisible_events = []
  1144. for category in categories:
  1145. add_acl_to_obj(user_acl, category)
  1146. if category.acl["can_approve_content"]:
  1147. show_all.append(category.pk)
  1148. else:
  1149. if user_acl["is_authenticated"]:
  1150. show_approved_owned.append(category.pk)
  1151. else:
  1152. show_approved.append(category.pk)
  1153. if not category.acl["can_hide_events"]:
  1154. hide_invisible_events.append(category.pk)
  1155. conditions = None
  1156. if show_all:
  1157. conditions = Q(category__in=show_all)
  1158. if show_approved:
  1159. condition = Q(category__in=show_approved, is_unapproved=False)
  1160. if conditions:
  1161. conditions = conditions | condition
  1162. else:
  1163. conditions = condition
  1164. if show_approved_owned:
  1165. condition = Q(
  1166. Q(poster_id=user_acl["user_id"]) | Q(is_unapproved=False),
  1167. category__in=show_approved_owned,
  1168. )
  1169. if conditions:
  1170. conditions = conditions | condition
  1171. else:
  1172. conditions = condition
  1173. if hide_invisible_events:
  1174. queryset = queryset.exclude(
  1175. category__in=hide_invisible_events, is_event=True, is_hidden=True
  1176. )
  1177. if not conditions:
  1178. return Post.objects.none()
  1179. return queryset.filter(conditions)
  1180. def exclude_invisible_posts_in_category(user_acl, category, queryset):
  1181. add_acl_to_obj(user_acl, category)
  1182. if not category.acl["can_approve_content"]:
  1183. if user_acl["is_authenticated"]:
  1184. queryset = queryset.filter(
  1185. Q(is_unapproved=False) | Q(poster_id=user_acl["user_id"])
  1186. )
  1187. else:
  1188. queryset = queryset.exclude(is_unapproved=True)
  1189. if not category.acl["can_hide_events"]:
  1190. queryset = queryset.exclude(is_event=True, is_hidden=True)
  1191. return queryset