import importlib from django.apps import apps from drf_spectacular.utils import ( extend_schema, extend_schema_view, OpenApiParameter, OpenApiResponse, PolymorphicProxySerializer ) from rest_framework.reverse import reverse from api.viewsets.common import SubModelViewSet from core.models.ticket_base import TicketBase def spectacular_request_serializers( serializer_type = 'Model'): serializers: dict = {} for model in apps.get_models(): if issubclass(model, TicketBase): serializer_name = 'ticket' if model._meta.sub_model_type != 'ticket': serializer_name += '_' + model._meta.sub_model_type serializer_module = importlib.import_module( model._meta.app_label + '.serializers.' + str( serializer_name ) ) serializers.update({ str(model._meta.verbose_name).lower().replace(' ', '_'): getattr(serializer_module, serializer_type + 'Serializer') }) return serializers @extend_schema_view( create=extend_schema( summary = 'Create a Ticket', description='.', parameters = [ OpenApiParameter( name = 'ticket_type', description = 'Enter the Ticket type. This is the name of the Ticket sub-model.', location = OpenApiParameter.PATH, type = str, required = False, allow_blank = True, ), ], request = PolymorphicProxySerializer( component_name = 'Tickets', serializers = spectacular_request_serializers(), resource_type_field_name = None, many = False, ), responses = { 200: OpenApiResponse( description='Already exists', response = PolymorphicProxySerializer( component_name = 'Tickets (View)', serializers = spectacular_request_serializers( 'View' ), resource_type_field_name = None, many = False, ) ), 201: OpenApiResponse( description = 'Created', response = PolymorphicProxySerializer( component_name = 'Tickets (View)', serializers = spectacular_request_serializers( 'View' ), resource_type_field_name = None, many = False, ) ), 403: OpenApiResponse(description='User is missing add permissions'), } ), destroy = extend_schema( summary = 'Delete a Ticket', description = '.', parameters =[ OpenApiParameter( name = 'ticket_type', description = 'Enter the ticket type. This is the name of the Ticket sub-model.', location = OpenApiParameter.PATH, type = str, required = False, allow_blank = True, ), ], request = PolymorphicProxySerializer( component_name = 'Tickets', serializers = spectacular_request_serializers(), resource_type_field_name = None, many = False, ), responses = { 204: OpenApiResponse(description='Object deleted'), 403: OpenApiResponse(description='User is missing delete permissions'), } ), list = extend_schema( summary = 'Fetch all Tickets', description='.', parameters = [ OpenApiParameter( name = 'ticket_type', description = 'Enter the ticket type. This is the name of the Ticket sub-model.', location = OpenApiParameter.PATH, type = str, required = False, allow_blank = True, ), ], request = PolymorphicProxySerializer( component_name = 'Tickets', serializers = spectacular_request_serializers(), resource_type_field_name = None, many = False, ), responses = { 200: OpenApiResponse( description='', response = PolymorphicProxySerializer( component_name = 'Tickets (View)', serializers = spectacular_request_serializers( 'View' ), resource_type_field_name = None, many = False, ) ), 403: OpenApiResponse(description='User is missing view permissions'), } ), retrieve = extend_schema( summary = 'Fetch a single ticket', description='.', parameters = [ OpenApiParameter( name = 'ticket_type', description = 'Enter the ticket type. This is the name of the Ticket sub-model.', location = OpenApiParameter.PATH, type = str, required = False, allow_blank = True, ), ], request = PolymorphicProxySerializer( component_name = 'Tickets', serializers = spectacular_request_serializers(), resource_type_field_name = None, many = False, ), responses = { 200: OpenApiResponse( description='', response = PolymorphicProxySerializer( component_name = 'Tickets (View)', serializers = spectacular_request_serializers( 'View' ), resource_type_field_name = None, many = False, ) ), 403: OpenApiResponse(description='User is missing view permissions'), } ), update = extend_schema(exclude = True), partial_update = extend_schema( summary = 'Update a Ticket', description = '.', parameters = [ OpenApiParameter( name = 'tickets_type', description = 'Enter the ticket type. This is the name of the Ticket sub-model.', location = OpenApiParameter.PATH, type = str, required = False, allow_blank = True, ), ], request = PolymorphicProxySerializer( component_name = 'Tickets', serializers = spectacular_request_serializers(), resource_type_field_name = None, many = False, ), responses = { 200: OpenApiResponse( description='', response = PolymorphicProxySerializer( component_name = 'Tickets (View)', serializers = spectacular_request_serializers( 'View' ), resource_type_field_name = None, many = False, ) ), 403: OpenApiResponse(description='User is missing change permissions'), } ), ) class ViewSet( SubModelViewSet ): _has_import: bool = False """User Permission get_permission_required() sets this to `True` when user has import permission. """ _has_purge: bool = False """User Permission get_permission_required() sets this to `True` when user has purge permission. """ _has_triage: bool = False """User Permission get_permission_required() sets this to `True` when user has triage permission. """ base_model = TicketBase filterset_fields = [ 'organization', 'is_deleted' ] model_kwarg = 'ticket_type' search_fields = [ 'title', 'description' ] view_description = 'All Tickets' def get_back_url(self) -> str: if( self.back_url is None and self.kwargs.get(self.model_kwarg, None) is not None ): self.back_url = reverse( viewname = '_api_ticketbase_sub-list', request = self.request, kwargs = { 'ticket_type': self.kwargs[self.model_kwarg], } ) return self.back_url def get_permission_required(self): import_permission = self.model._meta.app_label + '.import_' + self.model._meta.model_name if(import_permission in self.request.tenancy._user_permissions): self._has_import = True purge_permission = self.model._meta.app_label + '.purge_' + self.model._meta.model_name if(purge_permission in self.request.tenancy._user_permissions): self._has_purge = True triage_permission = self.model._meta.app_label + '.triage_' + self.model._meta.model_name if(triage_permission in self.request.tenancy._user_permissions): self._has_triage = True return super().get_permission_required() @extend_schema_view( # prevent duplicate documentation of both /core/ticket endpoints create = extend_schema(exclude = True), destroy = extend_schema(exclude = True), list = extend_schema(exclude = True), retrieve = extend_schema(exclude = True), update = extend_schema(exclude = True), partial_update = extend_schema(exclude = True), ) class NoDocsViewSet( ViewSet ): pass