__init__.py 4.4 KB

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