base.py 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. from django.http import Http404
  2. from django.shortcuts import render
  3. from django.views.generic import View
  4. from misago.acl import add_acl
  5. from misago.categories.models import Category
  6. from misago.categories.permissions import (allow_see_category,
  7. allow_browse_category)
  8. from misago.core.shortcuts import get_object_or_404, validate_slug
  9. from misago.threads.models import Thread, Post
  10. from misago.threads.permissions import (allow_see_thread, allow_see_post,
  11. exclude_invisible_posts)
  12. __all__ = ['CategoryMixin', 'ThreadMixin', 'PostMixin', 'ViewBase']
  13. class CategoryMixin(object):
  14. """
  15. Mixin for getting categories
  16. """
  17. def get_category(self, request, lock=False, **kwargs):
  18. category = self.fetch_category(request, lock, **kwargs)
  19. self.check_category_permissions(request, category)
  20. if kwargs.get('category_slug'):
  21. validate_slug(category, kwargs.get('category_slug'))
  22. return category
  23. def fetch_category(self, request, lock=False, **kwargs):
  24. queryset = Category.objects
  25. if lock:
  26. queryset = queryset.select_for_update()
  27. return get_object_or_404(
  28. queryset, id=kwargs.get('category_id'), role='forum')
  29. def check_category_permissions(self, request, category):
  30. if category.special_role:
  31. raise Http404()
  32. add_acl(request.user, category)
  33. allow_see_category(request.user, category)
  34. allow_browse_category(request.user, category)
  35. class ThreadMixin(object):
  36. """
  37. Mixin for getting thread
  38. """
  39. def get_thread(self, request, lock=False, **kwargs):
  40. thread = self.fetch_thread(request, lock, **kwargs)
  41. self.check_thread_permissions(request, thread)
  42. if kwargs.get('thread_slug'):
  43. validate_slug(thread, kwargs.get('thread_slug'))
  44. return thread
  45. def fetch_thread(self, request, lock=False, select_related=None,
  46. queryset=None, **kwargs):
  47. queryset = queryset or Thread.objects
  48. if lock:
  49. queryset = queryset.select_for_update()
  50. select_related = select_related or []
  51. if not 'category' in select_related:
  52. select_related.append('category')
  53. queryset = queryset.select_related(*select_related)
  54. where = {'id': kwargs.get('thread_id')}
  55. if 'category_id' in kwargs:
  56. where['category_id'] = kwargs.get('category_id')
  57. return get_object_or_404(queryset, **where)
  58. def check_thread_permissions(self, request, thread):
  59. if thread.category.special_role:
  60. raise Http404()
  61. add_acl(request.user, thread.category)
  62. add_acl(request.user, thread)
  63. allow_see_thread(request.user, thread)
  64. allow_see_category(request.user, thread.category)
  65. class PostMixin(object):
  66. def get_post(self, request, lock=False, **kwargs):
  67. post = self.fetch_post(request, lock, **kwargs)
  68. post.thread.category = post.category
  69. self.check_post_permissions(request, post)
  70. return post
  71. def fetch_post(self, request, lock=False, select_related=None,
  72. queryset=None, **kwargs):
  73. queryset = queryset or Post.objects
  74. if lock:
  75. queryset = queryset.select_for_update()
  76. select_related = select_related or []
  77. if not 'category' in select_related:
  78. select_related.append('category')
  79. if not 'thread' in select_related:
  80. select_related.append('thread')
  81. queryset = queryset.select_related(*select_related)
  82. where = {'id': kwargs.get('post_id')}
  83. if 'thread_id' in kwargs:
  84. where['thread_id'] = kwargs.get('thread_id')
  85. if 'category_id' in kwargs:
  86. where['category_id'] = kwargs.get('category_id')
  87. return get_object_or_404(queryset, **where)
  88. def check_post_permissions(self, request, post):
  89. if post.category.special_role:
  90. raise Http404()
  91. add_acl(request.user, post.category)
  92. add_acl(request.user, post.thread)
  93. add_acl(request.user, post)
  94. allow_see_post(request.user, post)
  95. allow_see_thread(request.user, post.thread)
  96. allow_see_category(request.user, post.category)
  97. def exclude_invisible_posts(self, queryset, user, category, thread):
  98. return exclude_invisible_posts(queryset, user, category)
  99. class ViewBase(CategoryMixin, ThreadMixin, PostMixin, View):
  100. def process_context(self, request, context):
  101. """
  102. Simple hook for extending and manipulating template context.
  103. """
  104. return context
  105. def render(self, request, context=None, template=None):
  106. context = self.process_context(request, context or {})
  107. template = template or self.template
  108. return render(request, template, context)