mirror of
https://github.com/jumpserver/jumpserver.git
synced 2025-07-04 18:46:39 +00:00
Merge branch 'dev' of github.com:jumpserver/jumpserver into github_dev
This commit is contained in:
commit
2eda58eadd
@ -258,10 +258,35 @@ class SessionReplayViewSet(viewsets.ViewSet):
|
|||||||
serializer_class = ReplaySerializer
|
serializer_class = ReplaySerializer
|
||||||
permission_classes = (IsSuperUserOrAppUser,)
|
permission_classes = (IsSuperUserOrAppUser,)
|
||||||
session = None
|
session = None
|
||||||
|
upload_to = 'replay' # 仅添加到本地存储中
|
||||||
|
|
||||||
def gen_session_path(self):
|
def get_session_path(self, version=2):
|
||||||
|
"""
|
||||||
|
获取session日志的文件路径
|
||||||
|
:param version: 原来后缀是 .gz,为了统一新版本改为 .replay.gz
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
suffix = '.replay.gz'
|
||||||
|
if version == 1:
|
||||||
|
suffix = '.gz'
|
||||||
date = self.session.date_start.strftime('%Y-%m-%d')
|
date = self.session.date_start.strftime('%Y-%m-%d')
|
||||||
return os.path.join(date, str(self.session.id) + '.gz')
|
return os.path.join(date, str(self.session.id) + suffix)
|
||||||
|
|
||||||
|
def get_local_path(self, version=2):
|
||||||
|
session_path = self.get_session_path(version=version)
|
||||||
|
if version == 2:
|
||||||
|
local_path = os.path.join(self.upload_to, session_path)
|
||||||
|
else:
|
||||||
|
local_path = session_path
|
||||||
|
return local_path
|
||||||
|
|
||||||
|
def save_to_storage(self, f):
|
||||||
|
local_path = self.get_local_path()
|
||||||
|
try:
|
||||||
|
name = default_storage.save(local_path, f)
|
||||||
|
return name, None
|
||||||
|
except OSError as e:
|
||||||
|
return None, e
|
||||||
|
|
||||||
def create(self, request, *args, **kwargs):
|
def create(self, request, *args, **kwargs):
|
||||||
session_id = kwargs.get('pk')
|
session_id = kwargs.get('pk')
|
||||||
@ -270,42 +295,48 @@ class SessionReplayViewSet(viewsets.ViewSet):
|
|||||||
|
|
||||||
if serializer.is_valid():
|
if serializer.is_valid():
|
||||||
file = serializer.validated_data['file']
|
file = serializer.validated_data['file']
|
||||||
file_path = self.gen_session_path()
|
name, err = self.save_to_storage(file)
|
||||||
try:
|
if not name:
|
||||||
default_storage.save(file_path, file)
|
msg = "Failed save replay `{}`: {}".format(session_id, err)
|
||||||
return Response({'url': default_storage.url(file_path)},
|
logger.error(msg)
|
||||||
status=201)
|
return Response({'msg': str(err)}, status=400)
|
||||||
except IOError:
|
url = default_storage.url(name)
|
||||||
return Response("Save error", status=500)
|
return Response({'url': url}, status=201)
|
||||||
else:
|
else:
|
||||||
logger.error(
|
msg = 'Upload data invalid: {}'.format(serializer.errors)
|
||||||
'Update load data invalid: {}'.format(serializer.errors))
|
logger.error(msg)
|
||||||
return Response({'msg': serializer.errors}, status=401)
|
return Response({'msg': serializer.errors}, status=401)
|
||||||
|
|
||||||
def retrieve(self, request, *args, **kwargs):
|
def retrieve(self, request, *args, **kwargs):
|
||||||
session_id = kwargs.get('pk')
|
session_id = kwargs.get('pk')
|
||||||
self.session = get_object_or_404(Session, id=session_id)
|
self.session = get_object_or_404(Session, id=session_id)
|
||||||
path = self.gen_session_path()
|
# 新版本和老版本的文件后缀不同
|
||||||
|
session_path = self.get_session_path() # 存在外部存储上的路径
|
||||||
|
local_path = self.get_local_path()
|
||||||
|
local_path_v1 = self.get_local_path(version=1)
|
||||||
|
|
||||||
if default_storage.exists(path):
|
# 去default storage中查找
|
||||||
url = default_storage.url(path)
|
for _local_path in (local_path, local_path_v1, session_path):
|
||||||
return redirect(url)
|
if default_storage.exists(_local_path):
|
||||||
else:
|
url = default_storage.url(_local_path)
|
||||||
configs = settings.TERMINAL_REPLAY_STORAGE
|
return redirect(url)
|
||||||
configs = [cfg for cfg in configs if cfg['TYPE'] != 'server']
|
|
||||||
if not configs:
|
|
||||||
return HttpResponseNotFound()
|
|
||||||
|
|
||||||
date = self.session.date_start.strftime('%Y-%m-%d')
|
# 去定义的外部storage查找
|
||||||
file_path = os.path.join(date, str(self.session.id) + '.replay.gz')
|
configs = settings.TERMINAL_REPLAY_STORAGE
|
||||||
target_path = default_storage.base_location + '/' + path
|
configs = {k: v for k, v in configs.items() if v['TYPE'] != 'server'}
|
||||||
storage = jms_storage.get_multi_object_storage(configs)
|
if not configs:
|
||||||
ok, err = storage.download(file_path, target_path)
|
return HttpResponseNotFound()
|
||||||
if ok:
|
|
||||||
return redirect(default_storage.url(path))
|
target_path = os.path.join(default_storage.base_location, local_path) # 保存到storage的路径
|
||||||
else:
|
target_dir = os.path.dirname(target_path)
|
||||||
logger.error("Failed download replay file: {}".format(err))
|
if not os.path.isdir(target_dir):
|
||||||
return HttpResponseNotFound()
|
os.makedirs(target_dir, exist_ok=True)
|
||||||
|
storage = jms_storage.get_multi_object_storage(configs)
|
||||||
|
ok, err = storage.download(session_path, target_path)
|
||||||
|
if not ok:
|
||||||
|
logger.error("Failed download replay file: {}".format(err))
|
||||||
|
return HttpResponseNotFound()
|
||||||
|
return redirect(default_storage.url(local_path))
|
||||||
|
|
||||||
|
|
||||||
class SessionReplayV2ViewSet(SessionReplayViewSet):
|
class SessionReplayV2ViewSet(SessionReplayViewSet):
|
||||||
|
@ -128,16 +128,12 @@ class UserToken(APIView):
|
|||||||
return Response({'error': msg}, status=406)
|
return Response({'error': msg}, status=406)
|
||||||
|
|
||||||
|
|
||||||
class UserProfile(APIView):
|
class UserProfile(generics.RetrieveAPIView):
|
||||||
permission_classes = (IsValidUser,)
|
permission_classes = (IsAuthenticated,)
|
||||||
serializer_class = UserSerializer
|
serializer_class = UserSerializer
|
||||||
|
|
||||||
def get(self, request):
|
def get_object(self):
|
||||||
# return Response(request.user.to_json())
|
return self.request.user
|
||||||
return Response(self.serializer_class(request.user).data)
|
|
||||||
|
|
||||||
def post(self, request):
|
|
||||||
return Response(self.serializer_class(request.user).data)
|
|
||||||
|
|
||||||
|
|
||||||
class UserOtpAuthApi(APIView):
|
class UserOtpAuthApi(APIView):
|
||||||
|
@ -421,8 +421,8 @@ $(document).ready(function() {
|
|||||||
APIUpdateAttr({ url: the_url, body: JSON.stringify(body), success: success, error: fail});
|
APIUpdateAttr({ url: the_url, body: JSON.stringify(body), success: success, error: fail});
|
||||||
}).on('click', '.btn-delete-user', function () {
|
}).on('click', '.btn-delete-user', function () {
|
||||||
var $this = $(this);
|
var $this = $(this);
|
||||||
var name = "{{ user.name }}";
|
var name = "{{ user_object.name }}";
|
||||||
var uid = "{{ user.id }}";
|
var uid = "{{ user_object.id }}";
|
||||||
var the_url = '{% url "api-users:user-detail" pk=DEFAULT_PK %}'.replace('{{ DEFAULT_PK }}', uid);
|
var the_url = '{% url "api-users:user-detail" pk=DEFAULT_PK %}'.replace('{{ DEFAULT_PK }}', uid);
|
||||||
var redirect_url = "{% url 'users:user-list' %}";
|
var redirect_url = "{% url 'users:user-list' %}";
|
||||||
objectDelete($this, name, the_url, redirect_url);
|
objectDelete($this, name, the_url, redirect_url);
|
||||||
|
@ -61,7 +61,7 @@ pytz==2018.3
|
|||||||
PyYAML==3.12
|
PyYAML==3.12
|
||||||
redis==2.10.6
|
redis==2.10.6
|
||||||
requests==2.18.4
|
requests==2.18.4
|
||||||
jms-storage==0.0.17
|
jms-storage==0.0.18
|
||||||
s3transfer==0.1.13
|
s3transfer==0.1.13
|
||||||
simplejson==3.13.2
|
simplejson==3.13.2
|
||||||
six==1.11.0
|
six==1.11.0
|
||||||
|
Loading…
Reference in New Issue
Block a user