mirror of https://github.com/jumpserver/jumpserver
perf: 优化 Playbook 文件创建逻辑
parent
74cc174d7a
commit
f3ca45aa74
|
@ -3,6 +3,7 @@ import shutil
|
|||
import zipfile
|
||||
|
||||
from django.conf import settings
|
||||
from django.core.exceptions import SuspiciousFileOperation
|
||||
from django.shortcuts import get_object_or_404
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from rest_framework import status
|
||||
|
@ -18,6 +19,7 @@ __all__ = ["PlaybookViewSet", "PlaybookFileBrowserAPIView"]
|
|||
|
||||
from rest_framework.views import APIView
|
||||
from rest_framework.response import Response
|
||||
from django.utils._os import safe_join
|
||||
|
||||
|
||||
def unzip_playbook(src, dist):
|
||||
|
@ -37,7 +39,7 @@ class PlaybookViewSet(OrgBulkModelViewSet):
|
|||
raise JMSException(code='playbook_has_job', detail={"msg": _("Currently playbook is being used in a job")})
|
||||
instance_id = instance.id
|
||||
super().perform_destroy(instance)
|
||||
dest_path = os.path.join(settings.DATA_DIR, "ops", "playbook", instance_id.__str__())
|
||||
dest_path = safe_join(settings.DATA_DIR, "ops", "playbook", instance_id.__str__())
|
||||
shutil.rmtree(dest_path)
|
||||
|
||||
def get_queryset(self):
|
||||
|
@ -48,8 +50,8 @@ class PlaybookViewSet(OrgBulkModelViewSet):
|
|||
def perform_create(self, serializer):
|
||||
instance = serializer.save()
|
||||
if 'multipart/form-data' in self.request.headers['Content-Type']:
|
||||
src_path = os.path.join(settings.MEDIA_ROOT, instance.path.name)
|
||||
dest_path = os.path.join(settings.DATA_DIR, "ops", "playbook", instance.id.__str__())
|
||||
src_path = safe_join(settings.MEDIA_ROOT, instance.path.name)
|
||||
dest_path = safe_join(settings.DATA_DIR, "ops", "playbook", instance.id.__str__())
|
||||
try:
|
||||
unzip_playbook(src_path, dest_path)
|
||||
except RuntimeError as e:
|
||||
|
@ -60,9 +62,9 @@ class PlaybookViewSet(OrgBulkModelViewSet):
|
|||
|
||||
else:
|
||||
if instance.create_method == 'blank':
|
||||
dest_path = os.path.join(settings.DATA_DIR, "ops", "playbook", instance.id.__str__())
|
||||
dest_path = safe_join(settings.DATA_DIR, "ops", "playbook", instance.id.__str__())
|
||||
os.makedirs(dest_path)
|
||||
with open(os.path.join(dest_path, 'main.yml'), 'w') as f:
|
||||
with open(safe_join(dest_path, 'main.yml'), 'w') as f:
|
||||
f.write('## write your playbook here')
|
||||
|
||||
|
||||
|
@ -83,13 +85,15 @@ class PlaybookFileBrowserAPIView(APIView):
|
|||
work_path = playbook.work_dir
|
||||
file_key = request.query_params.get('key', '')
|
||||
if file_key:
|
||||
file_path = os.path.join(work_path, file_key)
|
||||
with open(file_path, 'r') as f:
|
||||
try:
|
||||
try:
|
||||
file_path = safe_join(work_path, file_key)
|
||||
with open(file_path, 'r') as f:
|
||||
content = f.read()
|
||||
except UnicodeDecodeError:
|
||||
content = _('Unsupported file content')
|
||||
return Response({'content': content})
|
||||
except UnicodeDecodeError:
|
||||
content = _('Unsupported file content')
|
||||
except SuspiciousFileOperation:
|
||||
raise JMSException(code='invalid_file_path', detail={"msg": _("Invalid file path")})
|
||||
return Response({'content': content})
|
||||
else:
|
||||
expand_key = request.query_params.get('expand', '')
|
||||
nodes = self.generate_tree(playbook, work_path, expand_key)
|
||||
|
@ -105,7 +109,8 @@ class PlaybookFileBrowserAPIView(APIView):
|
|||
parent_key = ''
|
||||
if os.path.dirname(parent_key) == 'root':
|
||||
parent_key = os.path.basename(parent_key)
|
||||
full_path = os.path.join(work_path, parent_key)
|
||||
|
||||
full_path = safe_join(work_path, parent_key)
|
||||
|
||||
is_directory = request.data.get('is_directory', False)
|
||||
content = request.data.get('content', '')
|
||||
|
@ -117,27 +122,30 @@ class PlaybookFileBrowserAPIView(APIView):
|
|||
p = 'new_file.yml'
|
||||
else:
|
||||
p = 'new_dir'
|
||||
np = os.path.join(full_path, p)
|
||||
np = safe_join(full_path, p)
|
||||
n = 0
|
||||
while os.path.exists(np):
|
||||
n += 1
|
||||
np = os.path.join(full_path, '{}({})'.format(p, n))
|
||||
np = safe_join(full_path, '{}({})'.format(p, n))
|
||||
return np
|
||||
|
||||
if is_directory:
|
||||
new_file_path = find_new_name(name)
|
||||
os.makedirs(new_file_path)
|
||||
else:
|
||||
new_file_path = find_new_name(name, True)
|
||||
with open(new_file_path, 'w') as f:
|
||||
f.write(content)
|
||||
try:
|
||||
if is_directory:
|
||||
new_file_path = find_new_name(name)
|
||||
os.makedirs(new_file_path)
|
||||
else:
|
||||
new_file_path = find_new_name(name, True)
|
||||
with open(new_file_path, 'w') as f:
|
||||
f.write(content)
|
||||
except SuspiciousFileOperation:
|
||||
raise JMSException(code='invalid_file_path', detail={"msg": _("Invalid file path")})
|
||||
|
||||
relative_path = os.path.relpath(os.path.dirname(new_file_path), work_path)
|
||||
new_node = {
|
||||
"name": os.path.basename(new_file_path),
|
||||
"title": os.path.basename(new_file_path),
|
||||
"id": os.path.join(relative_path, os.path.basename(new_file_path))
|
||||
if not os.path.join(relative_path, os.path.basename(new_file_path)).startswith('.')
|
||||
"id": safe_join(relative_path, os.path.basename(new_file_path))
|
||||
if not safe_join(relative_path, os.path.basename(new_file_path)).startswith('.')
|
||||
else os.path.basename(new_file_path),
|
||||
"isParent": is_directory,
|
||||
"pId": relative_path if not relative_path.startswith('.') else 'root',
|
||||
|
@ -156,7 +164,7 @@ class PlaybookFileBrowserAPIView(APIView):
|
|||
new_name = request.data.get('new_name', '')
|
||||
|
||||
if file_key in self.protected_files and new_name:
|
||||
return Response({'msg': '{} can not be rename'.format(file_key)}, status=status.HTTP_400_BAD_REQUEST)
|
||||
raise JMSException(code='this_file_can_not_be_rename', detail={"msg": _("This file can not be rename")})
|
||||
|
||||
if os.path.dirname(file_key) == 'root':
|
||||
file_key = os.path.basename(file_key)
|
||||
|
@ -166,16 +174,20 @@ class PlaybookFileBrowserAPIView(APIView):
|
|||
|
||||
if not file_key or file_key == 'root':
|
||||
return Response(status=status.HTTP_400_BAD_REQUEST)
|
||||
file_path = os.path.join(work_path, file_key)
|
||||
file_path = safe_join(work_path, file_key)
|
||||
|
||||
# rename
|
||||
if new_name:
|
||||
new_file_path = os.path.join(os.path.dirname(file_path), new_name)
|
||||
if new_file_path == file_path:
|
||||
return Response(status=status.HTTP_200_OK)
|
||||
if os.path.exists(new_file_path):
|
||||
return Response({'msg': '{} already exists'.format(new_name)}, status=status.HTTP_400_BAD_REQUEST)
|
||||
os.rename(file_path, new_file_path)
|
||||
try:
|
||||
new_file_path = safe_join(os.path.dirname(file_path), new_name)
|
||||
if new_file_path == file_path:
|
||||
return Response(status=status.HTTP_200_OK)
|
||||
if os.path.exists(new_file_path):
|
||||
raise JMSException(code='file_already exists', detail={"msg": _("File already exists")})
|
||||
os.rename(file_path, new_file_path)
|
||||
except SuspiciousFileOperation:
|
||||
raise JMSException(code='invalid_file_path', detail={"msg": _("Invalid file path")})
|
||||
|
||||
# edit content
|
||||
else:
|
||||
if not is_directory:
|
||||
|
@ -189,10 +201,11 @@ class PlaybookFileBrowserAPIView(APIView):
|
|||
work_path = playbook.work_dir
|
||||
file_key = request.query_params.get('key', '')
|
||||
if not file_key:
|
||||
return Response({'msg': 'key is required'}, status=status.HTTP_400_BAD_REQUEST)
|
||||
raise JMSException(code='file_key_is_required', detail={"msg": _("File key is required")})
|
||||
|
||||
if file_key in self.protected_files:
|
||||
return Response({'msg': ' {} can not be delete'.format(file_key)}, status=status.HTTP_400_BAD_REQUEST)
|
||||
file_path = os.path.join(work_path, file_key)
|
||||
raise JMSException(code='This file can not be delete', detail={"msg": _("This file can not be delete")})
|
||||
file_path = safe_join(work_path, file_key)
|
||||
if os.path.isdir(file_path):
|
||||
shutil.rmtree(file_path)
|
||||
else:
|
||||
|
@ -216,11 +229,12 @@ class PlaybookFileBrowserAPIView(APIView):
|
|||
|
||||
relative_path = os.path.relpath(path, root_path)
|
||||
for d in dirs:
|
||||
dir_id = os.path.relpath(safe_join(path, d), root_path)
|
||||
|
||||
node = {
|
||||
"name": d,
|
||||
"title": d,
|
||||
"id": os.path.join(relative_path, d) if not os.path.join(relative_path, d).startswith(
|
||||
'.') else d,
|
||||
"id": dir_id,
|
||||
"isParent": True,
|
||||
"open": True,
|
||||
"pId": relative_path if not relative_path.startswith('.') else 'root',
|
||||
|
@ -230,12 +244,12 @@ class PlaybookFileBrowserAPIView(APIView):
|
|||
node['open'] = True
|
||||
nodes.append(node)
|
||||
for f in files:
|
||||
file_id = os.path.relpath(safe_join(path, f), root_path)
|
||||
node = {
|
||||
"name": f,
|
||||
"title": f,
|
||||
"iconSkin": 'file',
|
||||
"id": os.path.join(relative_path, f) if not os.path.join(relative_path, f).startswith(
|
||||
'.') else f,
|
||||
"id": file_id,
|
||||
"isParent": False,
|
||||
"open": False,
|
||||
"pId": relative_path if not relative_path.startswith('.') else 'root',
|
||||
|
|
Loading…
Reference in New Issue