123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164 |
- from rest_framework import serializers
- from django.core.exceptions import PermissionDenied
- from django.http import QueryDict
- from django.utils import timezone
- from django.utils.module_loading import import_string
- from misago.conf import settings
- class PostingInterrupt(Exception):
- def __init__(self, message):
- if not message:
- raise ValueError("You have to provide PostingInterrupt message.")
- self.message = message
- class PostingEndpoint(object):
- START = 0
- REPLY = 1
- EDIT = 2
- def __init__(self, request, mode, **kwargs):
- # we are using lock on user model to protect us from flood
- request.user.lock()
- # build kwargs dict for passing to middlewares
- self.kwargs = kwargs
- self.kwargs.update(
- {
- "mode": mode,
- "request": request,
- "settings": request.settings,
- "user": request.user,
- "user_acl": request.user_acl,
- }
- )
- self.__dict__.update(kwargs)
- # some middlewares (eg. emailnotification) may call render()
- # which will crash if this isn't set to false
- request.include_frontend_context = False
- self.datetime = timezone.now()
- self.errors = {}
- self._is_validated = False
- self.middlewares = self._load_middlewares()
- self._serializers = self._initialize_serializers()
- @property
- def is_start_endpoint(self):
- return self.mode == self.START
- @property
- def is_reply_endpoint(self):
- return self.mode == self.REPLY
- @property
- def is_edit_endpoint(self):
- return self.mode == self.EDIT
- def _load_middlewares(self):
- kwargs = self.kwargs.copy()
- kwargs.update({"datetime": self.datetime, "parsing_result": {}})
- middlewares = []
- for middleware in settings.MISAGO_POSTING_MIDDLEWARES:
- middleware_class = import_string(middleware)
- try:
- middleware_obj = middleware_class(prefix=middleware, **kwargs)
- if middleware_obj.use_this_middleware():
- middlewares.append((middleware, middleware_obj))
- except PostingInterrupt:
- raise ValueError(
- "Posting process can only be interrupted during pre_save phase"
- )
- return middlewares
- def get_serializers(self):
- """return list of serializers belonging to serializerset"""
- return self._serializers
- def _initialize_serializers(self):
- try:
- serializers = {}
- for middleware, obj in self.middlewares:
- serializer = obj.get_serializer()
- if serializer:
- serializers[middleware] = serializer
- return serializers
- except PostingInterrupt:
- raise ValueError(
- "Posting process can only be interrupted during pre_save phase"
- )
- def is_valid(self):
- """validate data against all serializers"""
- for serializer in self._serializers.values():
- if not serializer.is_valid():
- self.errors.update(serializer.errors)
- self._is_validated = True
- return not self.errors
- def save(self):
- """save new state to backend"""
- if not self._is_validated or self.errors:
- raise RuntimeError(
- "You need to validate posting data successfully before calling save"
- )
- try:
- for middleware, obj in self.middlewares:
- obj.pre_save(self._serializers.get(middleware))
- except PostingInterrupt as e:
- raise ValueError(
- "Posting process can only be interrupted from within interrupt_posting method"
- )
- try:
- for middleware, obj in self.middlewares:
- obj.interrupt_posting(self._serializers.get(middleware))
- except PostingInterrupt as e:
- raise PermissionDenied(e.message)
- try:
- for middleware, obj in self.middlewares:
- obj.save(self._serializers.get(middleware))
- for middleware, obj in self.middlewares:
- obj.post_save(self._serializers.get(middleware))
- except PostingInterrupt as e:
- raise ValueError(
- "Posting process can only be interrupted from within interrupt_posting method"
- )
- class PostingMiddleware(object):
- """abstract middleware class"""
- def __init__(self, **kwargs):
- self.kwargs = kwargs
- self.__dict__.update(kwargs)
- def use_this_middleware(self):
- return True
- def get_serializer(self):
- pass
- def pre_save(self, serializer):
- pass
- def interrupt_posting(self, serializer):
- pass
- def save(self, serializer):
- pass
- def post_save(self, serializer):
- pass
|