Skip to content

Commit c2f52d0

Browse files
authored
fix: Access can only be granted after OpenAPI authentication (#3599)
1 parent 2520461 commit c2f52d0

File tree

5 files changed

+55
-21
lines changed

5 files changed

+55
-21
lines changed

apps/common/init/init_doc.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,23 +18,21 @@
1818

1919
def init_app_doc(system_urlpatterns):
2020
system_urlpatterns += [
21-
path('schema/', SpectacularAPIView.as_view(), name='schema'), # schema的配置文件的路由,下面两个ui也是根据这个配置文件来生成的
21+
path('doc/schema/', SpectacularAPIView.as_view(), name='schema'), # schema的配置文件的路由,下面两个ui也是根据这个配置文件来生成的
2222
path('doc/', SpectacularSwaggerView.as_view(url_name='schema'), name='swagger-ui'), # swagger-ui的路由
23-
path('redoc/', SpectacularRedocView.as_view(url_name='schema'), name='redoc'), # redoc的路由
2423
]
2524

2625

2726
def init_chat_doc(system_urlpatterns, chat_urlpatterns):
2827
system_urlpatterns += [
29-
path('doc_chat_schema/',
28+
path('doc_chat/schema/',
3029
SpectacularAPIView.as_view(patterns=[
3130
URLPattern(pattern=f'{chat_api_prefix}{str(url.pattern)}', callback=url.callback,
3231
default_args=url.default_args,
3332
name=url.name) for url in chat_urlpatterns if
3433
['chat', 'open', 'profile'].__contains__(url.name)]),
3534
name='chat_schema'), # schema的配置文件的路由,下面两个ui也是根据这个配置文件来生成的
3635
path('doc_chat/', SpectacularSwaggerView.as_view(url_name='chat_schema'), name='swagger-ui'), # swagger-ui的路由
37-
path('redoc_chat/', SpectacularRedocView.as_view(url_name='chat_schema'), name='redoc'), # redoc的路由
3836
]
3937

4038

apps/common/middleware/doc_headers_middleware.py

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,13 @@
66
@date:2024/3/13 18:26
77
@desc:
88
"""
9+
910
from django.http import HttpResponse
1011
from django.utils.deprecation import MiddlewareMixin
1112

13+
from common.auth import TokenDetails, handles
14+
from maxkb.const import CONFIG
15+
1216
content = """
1317
<!doctype html>
1418
<html lang="en">
@@ -18,18 +22,28 @@
1822
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
1923
<title>Document</title>
2024
<script>
25+
function setCookie(name, value, days) {
26+
var expires = "";
27+
if (days) {
28+
var date = new Date();
29+
date.setTime(date.getTime() + (days*2));
30+
expires = "; expires=" + date.toUTCString();
31+
}
32+
document.cookie = name + "=" + (value || "") + expires + "; path=/";
33+
}
2134
window.onload = () => {
2235
var xhr = new XMLHttpRequest()
23-
xhr.open('GET', '/api/user', true)
36+
xhr.open('GET', '/api/user/profile', true)
2437
2538
xhr.setRequestHeader('Content-Type', 'application/json')
2639
const token = localStorage.getItem('token')
2740
const pathname = window.location.pathname
2841
if (token) {
29-
xhr.setRequestHeader('Authorization', token)
42+
xhr.setRequestHeader('Authorization', 'Bearer '+token)
3043
xhr.onreadystatechange = function () {
3144
if (xhr.readyState === 4) {
3245
if (xhr.status === 200) {
46+
setCookie("Authorization",'Bearer '+token)
3347
window.location.href = pathname
3448
}
3549
if (xhr.status === 401) {
@@ -48,15 +62,27 @@
4862
<body></body>
4963
</html>
5064
51-
"""
65+
""".replace("/api/user/profile", CONFIG.get_admin_path() + '/api/user/profile').replace('/admin/login',
66+
CONFIG.get_admin_path() + '/login')
5267

5368

5469
class DocHeadersMiddleware(MiddlewareMixin):
5570
def process_response(self, request, response):
56-
if request.path.startswith('/doc/') or request.path.startswith('/doc/chat/'):
57-
HTTP_REFERER = request.META.get('HTTP_REFERER')
58-
if HTTP_REFERER is None:
71+
if request.path.startswith('/doc/') or request.path.startswith('/doc_chat/'):
72+
auth = request.COOKIES.get('Authorization')
73+
if auth is None:
5974
return HttpResponse(content)
60-
if HTTP_REFERER == request._current_scheme_host + request.path:
61-
return response
75+
else:
76+
if not auth.startswith("Bearer "):
77+
return HttpResponse(content)
78+
try:
79+
token = auth[7:]
80+
token_details = TokenDetails(token)
81+
for handle in handles:
82+
if handle.support(request, token, token_details.get_token_details):
83+
handle.handle(request, token, token_details.get_token_details)
84+
return response
85+
return HttpResponse(content)
86+
except Exception as e:
87+
return HttpResponse(content)
6288
return response

apps/maxkb/settings/base.py

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -100,16 +100,29 @@
100100
],
101101
},
102102
},
103+
{"NAME": "DOC",
104+
'BACKEND': 'django.template.backends.django.DjangoTemplates',
105+
'DIRS': ["apps/static/drf_spectacular_sidecar"],
106+
'APP_DIRS': True,
107+
'OPTIONS': {
108+
'context_processors': [
109+
'django.template.context_processors.debug',
110+
'django.template.context_processors.request',
111+
'django.contrib.auth.context_processors.auth',
112+
'django.contrib.messages.context_processors.messages',
113+
],
114+
},
115+
},
103116
]
104117
SPECTACULAR_SETTINGS = {
105118
'TITLE': 'MaxKB API',
106119
'DESCRIPTION': _('Intelligent customer service platform'),
107120
'VERSION': 'v2',
108121
'SERVE_INCLUDE_SCHEMA': False,
109122
# OTHER SETTINGS
110-
'SWAGGER_UI_DIST': 'SIDECAR', # shorthand to use the sidecar instead
111-
'SWAGGER_UI_FAVICON_HREF': 'SIDECAR',
112-
'REDOC_DIST': 'SIDECAR',
123+
'SWAGGER_UI_DIST': '/doc/swagger-ui-dist', # shorthand to use the sidecar instead
124+
'SWAGGER_UI_FAVICON_HREF': '/doc/swagger-ui-dist/favicon-32x32.png',
125+
'REDOC_DIST': '/doc/redoc',
113126
'SECURITY_DEFINITIONS': {
114127
'Bearer': {
115128
'type': 'apiKey',

apps/maxkb/urls.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -49,15 +49,12 @@
4949
path(f'{chat_ui_prefix[1:]}/', include('oss.retrieval_urls')),
5050
]
5151
init_doc(urlpatterns, chat_urlpatterns)
52-
urlpatterns.append(
53-
re_path(r'^static/(?P<path>.*)$', static.serve, {'document_root': settings.STATIC_ROOT}, name='static'),
54-
)
5552

5653

5754
def pro():
58-
# 暴露静态主要是swagger资源
5955
urlpatterns.append(
60-
re_path(r'^static/(?P<path>.*)$', static.serve, {'document_root': settings.STATIC_ROOT}, name='static'),
56+
re_path(r'^doc/(?P<path>.*)$', static.serve,
57+
{'document_root': os.path.join(settings.STATIC_ROOT, "drf_spectacular_sidecar")}, name='doc'),
6158
)
6259
# 暴露ui静态资源
6360
urlpatterns.append(

apps/users/views/login.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ class Logout(APIView):
6161
get_operation_object=lambda r, k: {'name': r.user.username})
6262
def post(self, request: Request):
6363
version, get_key = Cache_Version.TOKEN.value
64-
cache.delete(get_key(token=request.auth), version=version)
64+
cache.delete(get_key(token=request.META.get('HTTP_AUTHORIZATION')[7:]), version=version)
6565
return result.success(True)
6666

6767

0 commit comments

Comments
 (0)