__init__.py 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. from rest_framework import serializers
  2. from django.core.exceptions import PermissionDenied
  3. from django.http import QueryDict
  4. from django.utils import timezone
  5. from django.utils.module_loading import import_string
  6. from misago.conf import settings
  7. class PostingInterrupt(Exception):
  8. def __init__(self, message):
  9. if not message:
  10. raise ValueError("You have to provide PostingInterrupt message.")
  11. self.message = message
  12. class PostingEndpoint(object):
  13. START = 0
  14. REPLY = 1
  15. EDIT = 2
  16. def __init__(self, request, mode, **kwargs):
  17. # we are using lock on user model to protect us from flood
  18. request.user.lock()
  19. # store mode
  20. self.mode = mode
  21. # build kwargs dict for passing to middlewares
  22. self.kwargs = kwargs
  23. self.kwargs.update({'mode': mode, 'request': request, 'user': request.user})
  24. # some middlewares (eg. emailnotification) may call render()
  25. # which will crash if this isn't set to false
  26. request.include_frontend_context = False
  27. self.datetime = timezone.now()
  28. self.errors = {}
  29. self._is_validated = False
  30. self.middlewares = self._load_middlewares()
  31. self._serializers = self._initialize_serializers()
  32. @property
  33. def is_start_endpoint(self):
  34. return self.mode == self.START
  35. @property
  36. def is_reply_endpoint(self):
  37. return self.mode == self.REPLY
  38. @property
  39. def is_edit_endpoint(self):
  40. return self.mode == self.EDIT
  41. def _load_middlewares(self):
  42. kwargs = self.kwargs.copy()
  43. kwargs.update({
  44. 'datetime': self.datetime,
  45. 'parsing_result': {},
  46. })
  47. middlewares = []
  48. for middleware in settings.MISAGO_POSTING_MIDDLEWARES:
  49. middleware_class = import_string(middleware)
  50. try:
  51. middleware_obj = middleware_class(prefix=middleware, **kwargs)
  52. if middleware_obj.use_this_middleware():
  53. middlewares.append((middleware, middleware_obj))
  54. except PostingInterrupt:
  55. raise ValueError("Posting process can only be interrupted during pre_save phase")
  56. return middlewares
  57. def get_serializers(self):
  58. """return list of serializers belonging to serializerset"""
  59. return self._serializers
  60. def _initialize_serializers(self):
  61. try:
  62. serializers = {}
  63. for middleware, obj in self.middlewares:
  64. serializer = obj.get_serializer()
  65. if serializer:
  66. serializers[middleware] = serializer
  67. return serializers
  68. except PostingInterrupt:
  69. raise ValueError("Posting process can only be interrupted during pre_save phase")
  70. def is_valid(self):
  71. """validate data against all serializers"""
  72. for serializer in self._serializers.values():
  73. if not serializer.is_valid():
  74. self.errors.update(serializer.errors)
  75. self._is_validated = True
  76. return not self.errors
  77. def save(self):
  78. """save new state to backend"""
  79. if not self._is_validated or self.errors:
  80. raise RuntimeError(
  81. "You need to validate posting data successfully before calling save"
  82. )
  83. try:
  84. for middleware, obj in self.middlewares:
  85. obj.pre_save(self._serializers.get(middleware))
  86. except PostingInterrupt as e:
  87. raise ValueError(
  88. "Posting process can only be interrupted from within interrupt_posting method"
  89. )
  90. try:
  91. for middleware, obj in self.middlewares:
  92. obj.interrupt_posting(self._serializers.get(middleware))
  93. except PostingInterrupt as e:
  94. raise PermissionDenied(e.message)
  95. try:
  96. for middleware, obj in self.middlewares:
  97. obj.save(self._serializers.get(middleware))
  98. for middleware, obj in self.middlewares:
  99. obj.post_save(self._serializers.get(middleware))
  100. except PostingInterrupt as e:
  101. raise ValueError(
  102. "Posting process can only be interrupted from within interrupt_posting method"
  103. )
  104. class PostingMiddleware(object):
  105. """abstract middleware class"""
  106. def __init__(self, **kwargs):
  107. self.kwargs = kwargs
  108. self.prefix = kwargs['prefix']
  109. self.mode = kwargs['mode']
  110. self.request = kwargs['request']
  111. self.user = kwargs['user']
  112. self.datetime = kwargs['datetime']
  113. self.parsing_result = kwargs['parsing_result']
  114. self.tree_name = kwargs.get('tree_name')
  115. self.thread = kwargs['thread']
  116. self.post = kwargs['post']
  117. def use_this_middleware(self):
  118. return True
  119. def get_serializer(self):
  120. pass
  121. def pre_save(self, serializer):
  122. pass
  123. def interrupt_posting(self, serializer):
  124. pass
  125. def save(self, serializer):
  126. pass
  127. def post_save(self, serializer):
  128. pass