forked from marcgibbons/django-rest-swagger
-
Notifications
You must be signed in to change notification settings - Fork 0
/
views.py
161 lines (131 loc) · 5.69 KB
/
views.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
import json
from django.utils import six
from django.views.generic import View
from django.utils.safestring import mark_safe
from django.utils.encoding import smart_text
from django.shortcuts import render_to_response, RequestContext
from django.core.exceptions import PermissionDenied
from .compat import import_string
from rest_framework.views import Response
from rest_framework.settings import api_settings
from rest_framework.utils import formatting
from rest_framework_swagger.urlparser import UrlParser
from rest_framework_swagger.apidocview import APIDocView
from rest_framework_swagger.docgenerator import DocumentationGenerator
import rest_framework_swagger as rfs
try:
JSONRenderer = list(filter(
lambda item: item.format == 'json',
api_settings.DEFAULT_RENDERER_CLASSES,
))[0]
except IndexError:
from rest_framework.renderers import JSONRenderer
def get_restructuredtext(view_cls, html=False):
from docutils import core
description = view_cls.__doc__ or ''
description = formatting.dedent(smart_text(description))
if html:
parts = core.publish_parts(source=description, writer_name='html')
html = parts['body_pre_docinfo'] + parts['fragment']
return mark_safe(html)
return description
def get_full_base_path(request):
try:
base_path = rfs.SWAGGER_SETTINGS['base_path']
except KeyError:
return request.build_absolute_uri(request.path).rstrip('/')
else:
protocol = 'https' if request.is_secure() else 'http'
return '{0}://{1}'.format(protocol, base_path.rstrip('/'))
class SwaggerUIView(View):
def get(self, request, *args, **kwargs):
if not self.has_permission(request):
return self.handle_permission_denied(request)
template_name = rfs.SWAGGER_SETTINGS.get('template_path')
data = {
'swagger_settings': {
'discovery_url': "%s/api-docs/" % get_full_base_path(request),
'api_key': rfs.SWAGGER_SETTINGS.get('api_key', ''),
'token_type': rfs.SWAGGER_SETTINGS.get('token_type'),
'enabled_methods': mark_safe(
json.dumps(rfs.SWAGGER_SETTINGS.get('enabled_methods'))),
'doc_expansion': rfs.SWAGGER_SETTINGS.get('doc_expansion', ''),
}
}
response = render_to_response(
template_name, RequestContext(request, data))
return response
def has_permission(self, request):
if rfs.SWAGGER_SETTINGS.get('is_superuser') and \
not request.user.is_superuser:
return False
if rfs.SWAGGER_SETTINGS.get('is_authenticated') and \
not request.user.is_authenticated():
return False
return True
def handle_permission_denied(self, request):
permission_denied_handler = rfs.SWAGGER_SETTINGS.get(
'permission_denied_handler')
if isinstance(permission_denied_handler, six.string_types):
permission_denied_handler = import_string(
permission_denied_handler)
if permission_denied_handler:
return permission_denied_handler(request)
else:
raise PermissionDenied()
class SwaggerResourcesView(APIDocView):
renderer_classes = (JSONRenderer, )
def get(self, request):
apis = [{'path': '/' + path} for path in self.get_resources()]
return Response({
'apiVersion': rfs.SWAGGER_SETTINGS.get('api_version', ''),
'swaggerVersion': '1.2',
'basePath': self.get_base_path(),
'apis': apis,
'info': rfs.SWAGGER_SETTINGS.get('info', {
'contact': '',
'description': '',
'license': '',
'licenseUrl': '',
'termsOfServiceUrl': '',
'title': '',
}),
})
def get_base_path(self):
try:
base_path = rfs.SWAGGER_SETTINGS['base_path']
except KeyError:
return self.request.build_absolute_uri(
self.request.path).rstrip('/')
else:
protocol = 'https' if self.request.is_secure() else 'http'
return '{0}://{1}/{2}'.format(protocol, base_path, 'api-docs')
def get_resources(self):
urlparser = UrlParser()
urlconf = getattr(self.request, "urlconf", None)
exclude_namespaces = rfs.SWAGGER_SETTINGS.get('exclude_namespaces')
apis = urlparser.get_apis(urlconf=urlconf, exclude_namespaces=exclude_namespaces)
authorized_apis = filter(lambda a: self.handle_resource_access(self.request, a['pattern']), apis)
authorized_apis_list = list(authorized_apis)
resources = urlparser.get_top_level_apis(authorized_apis_list)
return resources
class SwaggerApiView(APIDocView):
renderer_classes = (JSONRenderer, )
def get(self, request, path):
apis = self.get_apis_for_resource(path)
generator = DocumentationGenerator(for_user=request.user)
return Response({
'apiVersion': rfs.SWAGGER_SETTINGS.get('api_version', ''),
'swaggerVersion': '1.2',
'basePath': self.api_full_uri.rstrip('/'),
'resourcePath': '/' + path,
'apis': generator.generate(apis),
'models': generator.get_models(apis),
})
def get_apis_for_resource(self, filter_path):
urlparser = UrlParser()
urlconf = getattr(self.request, "urlconf", None)
apis = urlparser.get_apis(urlconf=urlconf, filter_path=filter_path)
authorized_apis = filter(lambda a: self.handle_resource_access(self.request, a['pattern']), apis)
authorized_apis_list = list(authorized_apis)
return authorized_apis_list