jumpserver/apps/terminal/views/session.py
老广 1fd2e782f8
1.5.7 Merge to dev (#3766)
* [Update] 暂存,优化解决不了问题

* [Update] 待续(小白)

* [Update] 修改asset user

* [Update] 计划再次更改

* [Update] 修改asset user

* [Update] 暂存与喜爱

* [Update] Add id in

* [Update] 阶段性完成ops task该做

* [Update] 修改asset user api

* [Update] 修改asset user 任务,查看认证等

* [Update] 基本完成asset user改造

* [Update] dynamic user only allow 1

* [Update] 修改asset user task

* [Update] 修改node admin user task api

* [Update] remove file header license

* [Update] 添加sftp root

* [Update] 暂存

* [Update] 暂存

* [Update] 修改翻译

* [Update] 修改系统用户改为同名后,用户名改为空

* [Update] 基本完成CAS调研

* [Update] 支持cas server

* [Update] 支持cas server

* [Update] 添加requirements

* [Update] 为方便调试添加mysql ipython到包中

* [Update] 添加huaweiyun翻译

* [Update] 增加下载session 录像

* [Update] 只有第一次通知replay离线的使用方法

* [Update] 暂存一下

* [Bugfix] 获取系统用户信息报错

* [Bugfix] 修改system user info

* [Update] 改成清理10天git status

* [Update] 修改celery日志保留时间

* [Update]修复部分pip包依赖的版本不兼容问题 (#3672)

* [Update] 修复用户更新页面会清空用户public_key的问题

* Fix broken dependencies

Co-authored-by: BaiJiangJie <32935519+BaiJiangJie@users.noreply.github.com>

* [Update] 修改获取系统用户auth info

* [Update] Remove log

* [Bugfix] 修复sftp home设置的bug

* [Update] 授权的系统用户添加sftp root

* [Update] 修改系统用户关联的用户

* [Update] 修改placeholder

* [Update] 优化获取授权的系统用户

* [Update] 修改tasks

* [Update] tree service update

* [Update] 暂存

* [Update] 基本完成用户授权树和资产树改造

* [Update] Dashbaord perf

* [update] Add huawei cloud sdk requirements

* [Updte] 优化dashboard页面

* [Update] system user auth info 添加id

* [Update] 修改系统用户serializer

* [Update] 优化api

* [Update] LDAP Test Util (#3720)

* [Update] LDAPTestUtil 1

* [Update] LDAPTestUtil 2

* [Update] LDAPTestUtil 3

* [Update] LDAPTestUtil 4

* [Update] LDAPTestUtil 5

* [Update] LDAPTestUtil 6

* [Update] LDAPTestUtil 7

* [Update] session 已添加is success,并且添加display serializer

* [Bugfix] 修复无法删除空节点的bug

* [Update] 命令记录分组织显示

* [Update] Session is_success 添加迁移文件

* [Update] 批量命令添加org_id

* [Update] 修复一些文案,修改不绑定MFA,不能ssh登录

* [Update] 修改replay api, 返回session信息

* [Update] 解决无效es导致访问命令记录页面失败的问题

* [Update] 拆分profile view

* [Update] 修改一个翻译

* [Update] 修改aysnc api框架

* [Update] 命令列表添加risk level

* [Update] 完成录像打包下载

* [Update] 更改登陆otp页面

* [Update] 修改command 存储redis_level

* [Update] 修改翻译

* [Update] 修改系统用户的用户列表字段

* [Update] 使用新logo和统一Jumpserver为JumpServer

* [Update] 优化cloud task

* [Update] 统一period task

* [Update] 统一period form serializer字段

* [Update] 修改period task

* [Update] 修改资产网关信息

* [Update] 用户授权资产树资产信息添加domain

* [Update] 修改翻译

* [Update] 测试可连接性

* 1.5.7 bai (#3764)

* [Update] 修复index页面Bug;修复测试资产用户可连接性问题;

* [Update] 修改测试资产用户可连接

* [Bugfix] 修复backends问题

* [Update] 修改marksafe依赖版本

* [Update] 修改测试资产用户可连接性

* [Update] 修改检测服务器性能时获取percent值

* [Update] 更新依赖boto3=1.12.14

Co-authored-by: Yanzhe Lee <lee.yanzhe@yanzhe.org>
Co-authored-by: BaiJiangJie <32935519+BaiJiangJie@users.noreply.github.com>
Co-authored-by: Bai <bugatti_it@163.com>
2020-03-12 16:24:38 +08:00

143 lines
4.7 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# -*- coding: utf-8 -*-
#
import os
import tarfile
from django.views.generic import ListView, TemplateView, DetailView
from django.views.generic.edit import SingleObjectMixin
from django.utils.translation import ugettext as _
from django.utils import timezone
from django.utils.encoding import escape_uri_path
from django.http import FileResponse, HttpResponse
from django.core.files.storage import default_storage
from common.permissions import PermissionsMixin, IsOrgAdmin, IsOrgAuditor
from common.utils import model_to_json
from ..models import Session
from ..backends import get_multi_command_storage
from .. import utils
__all__ = [
'SessionOnlineListView', 'SessionOfflineListView',
'SessionDetailView', 'SessionReplayDownloadView',
'SessionCommandsView',
]
class SessionListView(PermissionsMixin, TemplateView):
model = Session
template_name = 'terminal/session_list.html'
date_from = date_to = None
permission_classes = [IsOrgAdmin | IsOrgAuditor]
default_days_ago = 5
def get_context_data(self, **kwargs):
now = timezone.now()
context = {
'date_from': now - timezone.timedelta(days=self.default_days_ago),
'date_to': now,
}
kwargs.update(context)
return super().get_context_data(**kwargs)
class SessionOnlineListView(SessionListView):
def get_context_data(self, **kwargs):
context = {
'app': _('Sessions'),
'action': _('Session online list'),
'type': 'online',
}
kwargs.update(context)
return super().get_context_data(**kwargs)
class SessionOfflineListView(SessionListView):
def get_context_data(self, **kwargs):
context = {
'app': _('Sessions'),
'action': _('Session offline'),
'type': 'offline',
}
kwargs.update(context)
return super().get_context_data(**kwargs)
class SessionDetailView(PermissionsMixin, DetailView):
template_name = 'terminal/session_detail.html'
model = Session
permission_classes = [IsOrgAdmin | IsOrgAuditor]
def get_context_data(self, **kwargs):
context = {
'app': _('Sessions'),
'action': _('Session detail'),
}
kwargs.update(context)
return super().get_context_data(**kwargs)
class SessionCommandsView(SingleObjectMixin, PermissionsMixin, ListView):
template_name = 'terminal/session_commands.html'
model = Session
object = None
permission_classes = [IsOrgAdmin | IsOrgAuditor]
def get(self, request, *args, **kwargs):
self.object = self.get_object(queryset=self.model.objects.all())
return super().get(request, *args, **kwargs)
def get_queryset(self):
command_store = get_multi_command_storage()
return command_store.filter(session=self.object.id)
def get_context_data(self, **kwargs):
context = {
'app': _('Sessions'),
'action': _('Session detail'),
}
kwargs.update(context)
return super().get_context_data(**kwargs)
class SessionReplayDownloadView(PermissionsMixin, DetailView):
permission_classes = [IsOrgAdmin | IsOrgAuditor]
model = Session
@staticmethod
def prepare_offline_file(session, local_path):
replay_path = default_storage.path(local_path)
current_dir = os.getcwd()
dir_path = os.path.dirname(replay_path)
replay_filename = os.path.basename(replay_path)
meta_filename = '{}.json'.format(session.id)
offline_filename = '{}.tar'.format(session.id)
os.chdir(dir_path)
with open(meta_filename, 'wt') as f:
f.write(model_to_json(session))
with tarfile.open(offline_filename, 'w') as f:
f.add(replay_filename)
f.add(meta_filename)
file = open(offline_filename, 'rb')
os.chdir(current_dir)
return file
def get(self, request, *args, **kwargs):
session = self.get_object()
local_path, url = utils.get_session_replay_url(session)
if local_path is None:
error = url
return HttpResponse(error)
file = self.prepare_offline_file(session, local_path)
response = FileResponse(file)
response['Content-Type'] = 'application/octet-stream'
# 这里要注意哦网上查到的方法都是response['Content-Disposition']='attachment;filename="filename.py"',
# 但是如果文件名是英文名没问题如果文件名包含中文下载下来的文件名会被改为url中的path。
filename = escape_uri_path('{}.tar'.format(session.id))
disposition = "attachment; filename*=UTF-8''{}".format(filename)
response["Content-Disposition"] = disposition
return response