__init__.py 4.6 KB

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