mirror of https://github.com/jumpserver/jumpserver
[Update] 修改session
parent
94462bddb3
commit
bf8fa95597
|
@ -41,7 +41,7 @@
|
||||||
</a>
|
</a>
|
||||||
<ul class="nav nav-second-level">
|
<ul class="nav nav-second-level">
|
||||||
<li id="terminal"><a href="{% url 'terminal:terminal-list' %}">{% trans 'Terminal' %}</a></li>
|
<li id="terminal"><a href="{% url 'terminal:terminal-list' %}">{% trans 'Terminal' %}</a></li>
|
||||||
<li id="session"><a href="">{% trans 'Session' %}</a></li>
|
<li id="session"><a href="{% url 'terminal:session-online-list' %}">{% trans 'Session' %}</a></li>
|
||||||
<li id="command"><a href="">{% trans 'Command' %}</a></li>
|
<li id="command"><a href="">{% trans 'Command' %}</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
|
|
|
@ -78,19 +78,20 @@ class TerminalStatusViewSet(viewsets.ModelViewSet):
|
||||||
sessions_active = []
|
sessions_active = []
|
||||||
for session_data in self.request.data.get("sessions", []):
|
for session_data in self.request.data.get("sessions", []):
|
||||||
session_data["terminal"] = self.request.user.terminal.id
|
session_data["terminal"] = self.request.user.terminal.id
|
||||||
_id = session_data["id"]
|
_uuid = session_data["uuid"]
|
||||||
session = get_object_or_none(Session, id=_id)
|
session = get_object_or_none(Session, uuid=_uuid)
|
||||||
if session:
|
if session:
|
||||||
serializer = TerminalSessionSerializer(data=session_data,
|
serializer = TerminalSessionSerializer(
|
||||||
instance=session)
|
data=session_data, instance=session
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
serializer = TerminalSessionSerializer(data=session_data)
|
serializer = TerminalSessionSerializer(data=session_data)
|
||||||
|
|
||||||
if serializer.is_valid():
|
if serializer.is_valid():
|
||||||
serializer.save()
|
serializer.save()
|
||||||
else:
|
else:
|
||||||
logger.error("session serializer is not valid {}".format(
|
msg = "session data is not valid {}".format(serializer.errors)
|
||||||
serializer.errors))
|
logger.error(msg)
|
||||||
|
|
||||||
if not session_data["is_finished"]:
|
if not session_data["is_finished"]:
|
||||||
sessions_active.append(session_data["id"])
|
sessions_active.append(session_data["id"])
|
||||||
|
|
|
@ -74,6 +74,10 @@ class Status(models.Model):
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
db_table = 'terminal_status'
|
db_table = 'terminal_status'
|
||||||
|
get_latest_by = 'date_created'
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.date_created.strftime("%Y-%m-%d %H:%M:%S")
|
||||||
|
|
||||||
|
|
||||||
class Session(models.Model):
|
class Session(models.Model):
|
||||||
|
@ -82,7 +86,7 @@ class Session(models.Model):
|
||||||
('WT', 'Web Terminal'),
|
('WT', 'Web Terminal'),
|
||||||
)
|
)
|
||||||
|
|
||||||
id = models.UUIDField(default=uuid.uuid4, primary_key=True)
|
uuid = models.UUIDField(default=uuid.uuid4, db_index=True)
|
||||||
user = models.CharField(max_length=128, verbose_name=_("User"))
|
user = models.CharField(max_length=128, verbose_name=_("User"))
|
||||||
asset = models.CharField(max_length=1024, verbose_name=_("Asset"))
|
asset = models.CharField(max_length=1024, verbose_name=_("Asset"))
|
||||||
system_user = models.CharField(max_length=128, verbose_name=_("System User"))
|
system_user = models.CharField(max_length=128, verbose_name=_("System User"))
|
||||||
|
|
|
@ -23,8 +23,13 @@ class TerminalSerializer(serializers.ModelSerializer):
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_is_alive(obj):
|
def get_is_alive(obj):
|
||||||
log = obj.status_set.last()
|
status = obj.status_set.latest()
|
||||||
if log and timezone.now() - log.date_created < timezone.timedelta(seconds=600):
|
|
||||||
|
if not status:
|
||||||
|
return False
|
||||||
|
|
||||||
|
delta = timezone.now() - status.date_created
|
||||||
|
if delta < timezone.timedelta(seconds=600):
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
|
|
@ -0,0 +1,109 @@
|
||||||
|
{% extends '_base_list.html' %}
|
||||||
|
{% load i18n %}
|
||||||
|
{% load static %}
|
||||||
|
{% load common_tags %}
|
||||||
|
{% block content_left_head %}
|
||||||
|
<link href="{% static "css/plugins/footable/footable.core.css" %}" rel="stylesheet">
|
||||||
|
<link href="{% static 'css/plugins/datepicker/datepicker3.css' %}" rel="stylesheet">
|
||||||
|
<style>
|
||||||
|
#search_btn {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block table_search %}
|
||||||
|
<form id="search_form" method="get" action="" class="pull-right form-inline">
|
||||||
|
<div class="form-group" id="date">
|
||||||
|
<div class="input-daterange input-group" id="datepicker">
|
||||||
|
<span class="input-group-addon"><i class="fa fa-calendar"></i></span>
|
||||||
|
<input type="text" class="input-sm form-control" style="width: 100px;" name="date_from" value="{{ date_from }}">
|
||||||
|
<span class="input-group-addon">to</span>
|
||||||
|
<input type="text" class="input-sm form-control" style="width: 100px;" name="date_to" value="{{ date_to }}">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="input-group">
|
||||||
|
<select class="select2 form-control" name="username">
|
||||||
|
<option value="">{% trans 'User' %}</option>
|
||||||
|
{% for u in user_list %}
|
||||||
|
<option value="{{ u.username }}" {% if username == u.username %} selected {% endif %}>{{ u.username }}</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="input-group">
|
||||||
|
<select class="select2 form-control" name="ip">
|
||||||
|
<option value="">{% trans 'Asset' %}</option>
|
||||||
|
{% for a in asset_list %}
|
||||||
|
<option value="{{ a.ip }}" {% if ip == a.ip %} selected {% endif %}>{{ a.ip }}</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="input-group">
|
||||||
|
<select class="select2 form-control" name="system_user">
|
||||||
|
<option value="">{% trans 'System user' %}</option>
|
||||||
|
{% for s in system_user_list %}
|
||||||
|
<option value="{{ s.username }}" {% if s.username == system_user %} selected {% endif %}>{{ s.username }}</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="input-group">
|
||||||
|
<input type="text" class="form-control input-sm" name="command" placeholder="Command" value="{{ command }}">
|
||||||
|
</div>
|
||||||
|
<div class="input-group">
|
||||||
|
<div class="input-group-btn">
|
||||||
|
<button id='search_btn' type="submit" class="btn btn-sm btn-primary">
|
||||||
|
搜索
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
{% endblock %}
|
||||||
|
{% block table_container %}
|
||||||
|
<table class="footable table table-stripped toggle-arrow-tiny" data-page="false">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th data-toggle="true">ID</th>
|
||||||
|
<th>Command</th>
|
||||||
|
<th>Username</th>
|
||||||
|
<th>IP</th>
|
||||||
|
<th>System user</th>
|
||||||
|
<th>Proxy log</th>
|
||||||
|
<th>Datetime</th>
|
||||||
|
<th data-hide="all">Output</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for command in command_list %}
|
||||||
|
<tr>
|
||||||
|
<td>{{ command.id }}</td>
|
||||||
|
<td>{{ command.command }}</td>
|
||||||
|
<td>{{ command.user }}</td>
|
||||||
|
<td>{{ command.asset }}</td>
|
||||||
|
<td>{{ command.system_user }}</td>
|
||||||
|
<td><a href="{% url 'audits:proxy-log-detail' pk=command.proxy_log_id %}">{{ command.proxy_log_id}}</a></td>
|
||||||
|
<td>{{ command.timestamp|ts_to_date }}</td>
|
||||||
|
<td><pre style="border: none; background: none">{{ command.output|to_html|safe }}</pre></td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block custom_foot_js %}
|
||||||
|
<script src="{% static "js/plugins/footable/footable.all.min.js" %}"></script>
|
||||||
|
<script src="{% static 'js/plugins/datepicker/bootstrap-datepicker.js' %}"></script>
|
||||||
|
<script>
|
||||||
|
$(document).ready(function () {
|
||||||
|
$('.footable').footable();
|
||||||
|
$('.select2').select2();
|
||||||
|
$('#date .input-daterange').datepicker({
|
||||||
|
dateFormat: 'mm/dd/yy',
|
||||||
|
keyboardNavigation: false,
|
||||||
|
forceParse: false,
|
||||||
|
autoclose: true
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,58 @@
|
||||||
|
{% load static %}
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<meta name="renderer" content="webkit">
|
||||||
|
{% include '_head_css_js.html' %}
|
||||||
|
<link href="{% static 'css/bootstrap.min.css' %}" rel="stylesheet">
|
||||||
|
<link href="{% static "css/plugins/footable/footable.core.css" %}" rel="stylesheet">
|
||||||
|
<script src="{% static 'js/jquery-2.1.1.js' %}"></script>
|
||||||
|
<script src="{% static 'js/plugins/sweetalert/sweetalert.min.js' %}"></script>
|
||||||
|
<script src="{% static 'js/bootstrap.min.js' %}"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="wrapper wrapper-content animated fadeInRight">
|
||||||
|
<div class="tab-content">
|
||||||
|
<div class="ibox-content">
|
||||||
|
<input type="text" class="form-control input-sm m-b-xs" id="filter"
|
||||||
|
placeholder="Search in table">
|
||||||
|
<table class="footable table table-stripped toggle-arrow-tiny" data-page-size="10" data-filter=#filter>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th data-toggle="true">ID</th>
|
||||||
|
<th>Command</th>
|
||||||
|
<th data-hide="all">Output</th>
|
||||||
|
<th>Datetime</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody class="table_body">
|
||||||
|
{% for command in object_list %}
|
||||||
|
<tr>
|
||||||
|
<td>{{ command.command_no }}</td>
|
||||||
|
<td>{{ command.command }}</td>
|
||||||
|
<td>{{ command.output_decode |safe }}</td>
|
||||||
|
<td>{{ command.datetime }}</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
<tfoot>
|
||||||
|
<tr>
|
||||||
|
<td colspan="5">
|
||||||
|
<ul class="pagination pull-right"></ul>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tfoot>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
<script src="{% static "js/plugins/footable/footable.all.min.js" %}"></script>
|
||||||
|
<script>
|
||||||
|
$(document).ready(function () {
|
||||||
|
$('.footable').footable();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</html>
|
|
@ -0,0 +1,85 @@
|
||||||
|
{% extends 'base.html' %}
|
||||||
|
{% load static %}
|
||||||
|
{% load i18n %}
|
||||||
|
{% load common_tags %}
|
||||||
|
|
||||||
|
{% block custom_head_css_js %}
|
||||||
|
<link href="{% static "css/plugins/footable/footable.core.css" %}" rel="stylesheet">
|
||||||
|
{% endblock %}
|
||||||
|
{% block content %}
|
||||||
|
<div class="wrapper wrapper-content animated fadeInRight">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-12">
|
||||||
|
<div class="ibox float-e-margins">
|
||||||
|
<div class="panel-options">
|
||||||
|
<ul class="nav nav-tabs">
|
||||||
|
<li class="active">
|
||||||
|
<a href="#" class="text-center"> {% trans 'Proxy log detail' %} </a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div class="tab-content">
|
||||||
|
<div class="col-sm-11" style="padding-left: 0;">
|
||||||
|
<div class="ibox float-e-margins">
|
||||||
|
<div class="ibox-title">
|
||||||
|
<span style="float: left">{% trans 'Command log list' %} <b>{{ user_object.name }}</b></span>
|
||||||
|
<div class="ibox-tools">
|
||||||
|
<a class="collapse-link">
|
||||||
|
<i class="fa fa-chevron-up"></i>
|
||||||
|
</a>
|
||||||
|
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
|
||||||
|
<i class="fa fa-wrench"></i>
|
||||||
|
</a>
|
||||||
|
<ul class="dropdown-menu dropdown-user">
|
||||||
|
</ul>
|
||||||
|
<a class="close-link">
|
||||||
|
<i class="fa fa-times"></i>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="ibox-content">
|
||||||
|
<table id="command-log" class="footable table table-stripped toggle-arrow-tiny" data-page-size="10">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th data-toggle="true">ID</th>
|
||||||
|
<th>Command</th>
|
||||||
|
<th data-hide="all">Output</th>
|
||||||
|
<th>Datetime</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for command in object_list %}
|
||||||
|
<tr>
|
||||||
|
<td>{{ command.command_no }}</td>
|
||||||
|
<td>{{ command.command }}</td>
|
||||||
|
<td><pre style="border: none;background: none">{{ command.output|to_html|safe}}</pre></td>
|
||||||
|
<td>{{ command.timestamp|ts_to_date}}</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
<tfoot>
|
||||||
|
<tr>
|
||||||
|
<td colspan="5">
|
||||||
|
<ul class="pagination pull-right"></ul>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tfoot>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
|
{% block custom_foot_js %}
|
||||||
|
<script src="{% static "js/plugins/footable/footable.all.min.js" %}"></script>
|
||||||
|
<script>
|
||||||
|
$(document).ready(function () {
|
||||||
|
$('.footable').footable();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
{% endblock %}
|
|
@ -0,0 +1,159 @@
|
||||||
|
{% extends '_base_list.html' %}
|
||||||
|
{% load i18n %}
|
||||||
|
{% load static %}
|
||||||
|
{% block content_left_head %}
|
||||||
|
<link href="{% static 'css/plugins/datepicker/datepicker3.css' %}" rel="stylesheet">
|
||||||
|
<style>
|
||||||
|
#search_btn {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
|
||||||
|
{% block table_search %}
|
||||||
|
<form id="search_form" method="get" action="" class="pull-right form-inline">
|
||||||
|
<div class="form-group" id="date">
|
||||||
|
<div class="input-daterange input-group" id="datepicker">
|
||||||
|
<span class="input-group-addon"><i class="fa fa-calendar"></i></span>
|
||||||
|
<input type="text" class="input-sm form-control" style="width: 100px;" name="date_from" value="{{ date_from }}">
|
||||||
|
<span class="input-group-addon">to</span>
|
||||||
|
<input type="text" class="input-sm form-control" style="width: 100px;" name="date_to" value="{{ date_to }}">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="input-group">
|
||||||
|
<select class="select2 form-control" name="username">
|
||||||
|
<option value="">{% trans 'User' %}</option>
|
||||||
|
{% for u in user_list %}
|
||||||
|
<option value="{{ u }}" {% if u == username %} selected {% endif %}>{{ u }}</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="input-group">
|
||||||
|
<select class="select2 form-control" name="ip">
|
||||||
|
<option value="">{% trans 'Asset' %}</option>
|
||||||
|
{% for a in asset_list %}
|
||||||
|
<option value="{{ a }}" {% if a == ip %} selected {% endif %}>{{ a }}</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="input-group">
|
||||||
|
<select class="select2 form-control" name="system_user">
|
||||||
|
<option value="">{% trans 'System user' %}</option>
|
||||||
|
{% for su in system_user_list %}
|
||||||
|
<option value="{{ su }}" {% if su == system_user %} selected {% endif %}>{{ su }}</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="input-group">
|
||||||
|
<input type="text" class="form-control input-sm" name="keyword" placeholder="Keyword" value="{{ keyword }}">
|
||||||
|
</div>
|
||||||
|
<div class="input-group">
|
||||||
|
<div class="input-group-btn">
|
||||||
|
<button id='search_btn' type="submit" class="btn btn-sm btn-primary">
|
||||||
|
搜索
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block table_head %}
|
||||||
|
<th class="text-center"></th>
|
||||||
|
<th class="text-center">{% trans 'ID' %}</th>
|
||||||
|
<th class="text-center">{% trans 'User' %}</th>
|
||||||
|
<th class="text-center">{% trans 'Asset' %}</th>
|
||||||
|
<th class="text-center">{% trans 'System user' %}</th>
|
||||||
|
<th class="text-center">{% trans 'Terminal' %}</th>
|
||||||
|
<th class="text-center">{% trans 'Command' %}</th>
|
||||||
|
<th class="text-center">{% trans 'Success' %}</th>
|
||||||
|
<th class="text-center">{% trans 'Finished' %}</th>
|
||||||
|
<th class="text-center">{% trans 'Play' %}</th>
|
||||||
|
<th class="text-center">{% trans 'Date start' %}</th>
|
||||||
|
<th class="text-center">{% trans 'Time' %}</th>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block table_body %}
|
||||||
|
{% for proxy_log in proxy_log_list %}
|
||||||
|
<tr class="gradeX">
|
||||||
|
<td class="text-center"><input type="checkbox" class="cbx-term" value="{{ proxy_log.id }}"></td>
|
||||||
|
<td class="text-center">
|
||||||
|
<a href="{% url 'audits:proxy-log-detail' pk=proxy_log.id %}">{{ proxy_log.id }}</a>
|
||||||
|
</td>
|
||||||
|
<td class="text-center">{{ proxy_log.user }}</td>
|
||||||
|
<td class="text-center">{{ proxy_log.asset }}</td>
|
||||||
|
<td class="text-center">{{ proxy_log.system_user }}</td>
|
||||||
|
<td class="text-center">{{ proxy_log.terminal }}</td>
|
||||||
|
<td class="text-center">{{ proxy_log.commands.all|length}}</td>
|
||||||
|
<td class="text-center">
|
||||||
|
{% if proxy_log.is_failed %}
|
||||||
|
<i class="fa fa-times text-danger"></i>
|
||||||
|
{% else %}
|
||||||
|
<i class="fa fa-check text-navy"></i>
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
{% if proxy_log.is_finished %}
|
||||||
|
<td class="text-center">
|
||||||
|
<i class="fa fa-check text-navy"></i>
|
||||||
|
</td>
|
||||||
|
<td class="text-center">
|
||||||
|
<a><span class="text-navy"><i class="fa fa-play-circle"></i></span></a>
|
||||||
|
</td>
|
||||||
|
{% else %}
|
||||||
|
<td class="text-center">
|
||||||
|
<a class="btn-term" value="{{ proxy_log.id }}"><i class="fa fa-times text-danger"></i></a>
|
||||||
|
</td>
|
||||||
|
<td class="text-center">
|
||||||
|
<a><span class="text-danger"><i class="fa fa-eye"></i></span></a>
|
||||||
|
</td>
|
||||||
|
{% endif %}
|
||||||
|
<td class="text-center">{{ proxy_log.date_start }}</td>
|
||||||
|
<td class="text-center">{{ proxy_log.date_finished|timeuntil:proxy_log.date_start }}</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
|
||||||
|
{% block custom_foot_js %}
|
||||||
|
<script src="{% static 'js/plugins/datepicker/bootstrap-datepicker.js' %}"></script>
|
||||||
|
<script>
|
||||||
|
function terminateConnection(data) {
|
||||||
|
function success() {
|
||||||
|
window.setTimeout(function () {
|
||||||
|
window.location.reload()
|
||||||
|
}, 300)
|
||||||
|
}
|
||||||
|
var the_url = "";
|
||||||
|
APIUpdateAttr({url: the_url, method: 'POST', body: JSON.stringify(data), success: success, success_message: 'Terminate success'});
|
||||||
|
}
|
||||||
|
$(document).ready(function() {
|
||||||
|
$('table').DataTable({
|
||||||
|
"searching": false,
|
||||||
|
"paging": false,
|
||||||
|
"bInfo" : false,
|
||||||
|
"order": []
|
||||||
|
});
|
||||||
|
$('.select2').select2();
|
||||||
|
$('#date .input-daterange').datepicker({
|
||||||
|
dateFormat: 'mm/dd/yy',
|
||||||
|
keyboardNavigation: false,
|
||||||
|
forceParse: false,
|
||||||
|
autoclose: true
|
||||||
|
});
|
||||||
|
}).on('click', '.btn-term', function () {
|
||||||
|
var $this = $(this);
|
||||||
|
var proxy_log_id = $this.attr('value');
|
||||||
|
var data = {
|
||||||
|
proxy_log_id: proxy_log_id
|
||||||
|
};
|
||||||
|
terminateConnection(data)
|
||||||
|
}).on('click', '#btn_bulk_update', function () {
|
||||||
|
var data = [];
|
||||||
|
$('.cbx-term:checked').each(function () {
|
||||||
|
data.push({proxy_log_id: $(this).attr('value')})
|
||||||
|
});
|
||||||
|
terminateConnection(data)
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
{% endblock %}
|
||||||
|
|
|
@ -0,0 +1,173 @@
|
||||||
|
{% extends '_base_list.html' %}
|
||||||
|
{% load i18n %}
|
||||||
|
{% load static %}
|
||||||
|
{% block content_left_head %}
|
||||||
|
<link href="{% static 'css/plugins/datepicker/datepicker3.css' %}" rel="stylesheet">
|
||||||
|
<style>
|
||||||
|
#search_btn {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
|
||||||
|
{% block table_search %}
|
||||||
|
<form id="search_form" method="get" action="" class="pull-right form-inline">
|
||||||
|
<div class="form-group" id="date">
|
||||||
|
<div class="input-daterange input-group" id="datepicker">
|
||||||
|
<span class="input-group-addon"><i class="fa fa-calendar"></i></span>
|
||||||
|
<input type="text" class="input-sm form-control" style="width: 100px;" name="date_from" value="{{ date_from }}">
|
||||||
|
<span class="input-group-addon">to</span>
|
||||||
|
<input type="text" class="input-sm form-control" style="width: 100px;" name="date_to" value="{{ date_to }}">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="input-group">
|
||||||
|
<select class="select2 form-control" name="username">
|
||||||
|
<option value="">{% trans 'User' %}</option>
|
||||||
|
{% for u in user_list %}
|
||||||
|
<option value="{{ u }}" {% if u == username %} selected {% endif %}>{{ u }}</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="input-group">
|
||||||
|
<select class="select2 form-control" name="ip">
|
||||||
|
<option value="">{% trans 'Asset' %}</option>
|
||||||
|
{% for a in asset_list %}
|
||||||
|
<option value="{{ a }}" {% if a == ip %} selected {% endif %}>{{ a }}</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="input-group">
|
||||||
|
<select class="select2 form-control" name="system_user">
|
||||||
|
<option value="">{% trans 'System user' %}</option>
|
||||||
|
{% for su in system_user_list %}
|
||||||
|
<option value="{{ su }}" {% if su == system_user %} selected {% endif %}>{{ su }}</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="input-group">
|
||||||
|
<input type="text" class="form-control input-sm" name="keyword" placeholder="Keyword" value="{{ keyword }}">
|
||||||
|
</div>
|
||||||
|
<div class="input-group">
|
||||||
|
<div class="input-group-btn">
|
||||||
|
<button id='search_btn' type="submit" class="btn btn-sm btn-primary">
|
||||||
|
搜索
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block table_head %}
|
||||||
|
<th class="text-center"></th>
|
||||||
|
<th class="text-center">{% trans 'ID' %}</th>
|
||||||
|
<th class="text-center">{% trans 'User' %}</th>
|
||||||
|
<th class="text-center">{% trans 'Asset' %}</th>
|
||||||
|
<th class="text-center">{% trans 'System user' %}</th>
|
||||||
|
<th class="text-center">{% trans 'Terminal' %}</th>
|
||||||
|
<th class="text-center">{% trans 'Command' %}</th>
|
||||||
|
<th class="text-center">{% trans 'Success' %}</th>
|
||||||
|
<th class="text-center">{% trans 'Finished' %}</th>
|
||||||
|
<th class="text-center">{% trans 'Monitor' %}</th>
|
||||||
|
<th class="text-center">{% trans 'Date start' %}</th>
|
||||||
|
<th class="text-center">{% trans 'Time' %}</th>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block table_body %}
|
||||||
|
{% for session in session_list %}
|
||||||
|
<tr class="gradeX">
|
||||||
|
<td class="text-center"><input type="checkbox" class="cbx-term" value="{{ session.id }}"></td>
|
||||||
|
<td class="text-center">
|
||||||
|
<a href="">{{ session.id }}</a>
|
||||||
|
</td>
|
||||||
|
<td class="text-center">{{ session.user }}</td>
|
||||||
|
<td class="text-center">{{ session.asset }}</td>
|
||||||
|
<td class="text-center">{{ session.system_user }}</td>
|
||||||
|
<td class="text-center">{{ session.terminal.name }}</td>
|
||||||
|
<td class="text-center">{{ session.commands.all|length}}</td>
|
||||||
|
<td class="text-center">
|
||||||
|
{% if session.is_failed %}
|
||||||
|
<i class="fa fa-times text-danger"></i>
|
||||||
|
{% else %}
|
||||||
|
<i class="fa fa-check text-navy"></i>
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
{% if session.is_finished %}
|
||||||
|
<td class="text-center">
|
||||||
|
<i class="fa fa-check text-navy"></i>
|
||||||
|
</td>
|
||||||
|
<td class="text-center">
|
||||||
|
<a><span class="text-navy"><i class="fa fa-play-circle"></i></span></a>
|
||||||
|
</td>
|
||||||
|
{% else %}
|
||||||
|
<td class="text-center">
|
||||||
|
<a class="btn-term" value="{{ session.id }}"><i class="fa fa-times text-danger"></i></a>
|
||||||
|
</td>
|
||||||
|
<td class="text-center">
|
||||||
|
<a><span class="text-danger"><i class="fa fa-eye"></i></span></a>
|
||||||
|
</td>
|
||||||
|
{% endif %}
|
||||||
|
<td class="text-center">{{ session.date_start }}</td>
|
||||||
|
<td class="text-center">{{ session.date_finished|timeuntil:session.date_start }}</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block content_bottom_left %}
|
||||||
|
<div id="actions">
|
||||||
|
<div class="input-group">
|
||||||
|
<select class="form-control m-b" style="width: auto" id="slct_bulk_update">
|
||||||
|
<option value="terminate">{% trans 'Terminate selected' %}</option>
|
||||||
|
</select>
|
||||||
|
<div class="input-group-btn pull-left" style="padding-left: 5px;">
|
||||||
|
<button id='btn_bulk_update' style="height: 32px;" class="btn btn-sm btn-primary">
|
||||||
|
{% trans 'Submit' %}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block custom_foot_js %}
|
||||||
|
<script src="{% static 'js/plugins/datepicker/bootstrap-datepicker.js' %}"></script>
|
||||||
|
<script>
|
||||||
|
function terminateConnection(data) {
|
||||||
|
function success() {
|
||||||
|
window.setTimeout(function () {
|
||||||
|
window.location.reload()
|
||||||
|
}, 300)
|
||||||
|
}
|
||||||
|
var the_url = "";
|
||||||
|
APIUpdateAttr({url: the_url, method: 'POST', body: JSON.stringify(data), success: success, success_message: 'Terminate success'});
|
||||||
|
}
|
||||||
|
$(document).ready(function() {
|
||||||
|
$('table').DataTable({
|
||||||
|
"searching": false,
|
||||||
|
"paging": false,
|
||||||
|
"bInfo" : false,
|
||||||
|
"order": []
|
||||||
|
});
|
||||||
|
$('.select2').select2();
|
||||||
|
$('#date .input-daterange').datepicker({
|
||||||
|
dateFormat: 'mm/dd/yy',
|
||||||
|
keyboardNavigation: false,
|
||||||
|
forceParse: false,
|
||||||
|
autoclose: true
|
||||||
|
});
|
||||||
|
}).on('click', '.btn-term', function () {
|
||||||
|
var $this = $(this);
|
||||||
|
var proxy_log_id = $this.attr('value');
|
||||||
|
var data = {
|
||||||
|
proxy_log_id: proxy_log_id
|
||||||
|
};
|
||||||
|
terminateConnection(data)
|
||||||
|
}).on('click', '#btn_bulk_update', function () {
|
||||||
|
var data = [];
|
||||||
|
$('.cbx-term:checked').each(function () {
|
||||||
|
data.push({proxy_log_id: $(this).attr('value')})
|
||||||
|
});
|
||||||
|
terminateConnection(data)
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
{% endblock %}
|
||||||
|
|
|
@ -9,13 +9,14 @@ from .. import views
|
||||||
app_name = 'terminal'
|
app_name = 'terminal'
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
|
# Terminal view
|
||||||
url(r'^terminal/$', views.TerminalListView.as_view(), name='terminal-list'),
|
url(r'^terminal/$', views.TerminalListView.as_view(), name='terminal-list'),
|
||||||
url(r'^terminal/(?P<pk>[0-9a-zA-Z\-]+)/$', views.TerminalDetailView.as_view(),
|
url(r'^terminal/(?P<pk>[0-9a-zA-Z\-]+)/$', views.TerminalDetailView.as_view(), name='terminal-detail'),
|
||||||
name='terminal-detail'),
|
url(r'^terminal/(?P<pk>[0-9a-zA-Z\-]+)/connect/$', views.TerminalConnectView.as_view(), name='terminal-connect'),
|
||||||
url(r'^terminal/(?P<pk>[0-9a-zA-Z\-]+)/connect/$', views.TerminalConnectView.as_view(),
|
url(r'^terminal/(?P<pk>[0-9a-zA-Z\-]+)/update/$', views.TerminalUpdateView.as_view(), name='terminal-update'),
|
||||||
name='terminal-connect'),
|
url(r'^(?P<pk>[0-9a-zA-Z\-]+)/accept/$', views.TerminalAcceptView.as_view(), name='terminal-accept'),
|
||||||
url(r'^terminal/(?P<pk>[0-9a-zA-Z\-]+)/update/$', views.TerminalUpdateView.as_view(),
|
|
||||||
name='terminal-update'),
|
# Session view
|
||||||
url(r'^(?P<pk>[0-9a-zA-Z\-]+)/accept/$', views.TerminalAccept.as_view(),
|
url(r'^session/online/$', views.SessionOnlineListView.as_view(), name='session-online-list'),
|
||||||
name='terminal-accept'),
|
url(r'^session/offline$', views.SessionOfflineListView.as_view(), name='session-offline-list'),
|
||||||
]
|
]
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
from .terminal import *
|
||||||
|
from .session import *
|
|
@ -0,0 +1,126 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
|
||||||
|
import time
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
from django.views.generic import ListView, UpdateView, DeleteView, DetailView, TemplateView
|
||||||
|
from django.views.generic.edit import SingleObjectMixin
|
||||||
|
from django.utils.translation import ugettext as _
|
||||||
|
from django.utils import timezone
|
||||||
|
from django.utils.module_loading import import_string
|
||||||
|
from django.urls import reverse_lazy
|
||||||
|
from django.http import HttpResponse
|
||||||
|
from django.conf import settings
|
||||||
|
from django.db.models import Q
|
||||||
|
|
||||||
|
from users.utils import AdminUserRequiredMixin
|
||||||
|
from ..models import Session, Command, Terminal
|
||||||
|
from ..backends import get_command_store
|
||||||
|
|
||||||
|
|
||||||
|
__all__ = [
|
||||||
|
'SessionOnlineListView', 'SessionOfflineListView',
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
class SessionListView(AdminUserRequiredMixin, ListView):
|
||||||
|
model = Session
|
||||||
|
template_name = 'terminal/session_online.html'
|
||||||
|
context_object_name = 'session_list'
|
||||||
|
paginate_by = settings.CONFIG.DISPLAY_PER_PAGE
|
||||||
|
keyword = username = hostname = system_user = date_from_s = date_to_s = ''
|
||||||
|
ordering = ['is_finished', '-id']
|
||||||
|
date_format = '%m/%d/%Y'
|
||||||
|
|
||||||
|
def get_queryset(self):
|
||||||
|
date_now = timezone.localtime(timezone.now())
|
||||||
|
date_to_default = date_now.strftime(self.date_format)
|
||||||
|
date_from_default = (date_now-timezone.timedelta(7)).strftime(self.date_format)
|
||||||
|
|
||||||
|
self.queryset = super().get_queryset()
|
||||||
|
self.keyword = self.request.GET.get('keyword', '')
|
||||||
|
self.username = self.request.GET.get('username')
|
||||||
|
self.ip = self.request.GET.get('ip')
|
||||||
|
self.system_user = self.request.GET.get('system_user')
|
||||||
|
self.date_from_s = self.request.GET.get('date_from', date_from_default)
|
||||||
|
self.date_to_s = self.request.GET.get('date_to', date_to_default)
|
||||||
|
|
||||||
|
filter_kwargs = {}
|
||||||
|
if self.date_from_s:
|
||||||
|
date_from = datetime.strptime(self.date_from_s, self.date_format)
|
||||||
|
date_from = date_from.replace(tzinfo=timezone.get_current_timezone())
|
||||||
|
filter_kwargs['date_start__gt'] = date_from
|
||||||
|
if self.date_to_s:
|
||||||
|
date_to = timezone.datetime.strptime(
|
||||||
|
self.date_to_s + ' 23:59:59', '%m/%d/%Y %H:%M:%S')
|
||||||
|
date_to = date_to.replace(tzinfo=timezone.get_current_timezone())
|
||||||
|
filter_kwargs['date_start__lt'] = date_to
|
||||||
|
if self.username:
|
||||||
|
filter_kwargs['user'] = self.username
|
||||||
|
if self.ip:
|
||||||
|
filter_kwargs['asset'] = self.ip
|
||||||
|
if self.system_user:
|
||||||
|
filter_kwargs['system_user'] = self.system_user
|
||||||
|
if self.keyword:
|
||||||
|
self.queryset = self.queryset.filter(
|
||||||
|
Q(user__icontains=self.keyword) |
|
||||||
|
Q(asset__icontains=self.keyword) |
|
||||||
|
Q(system_user__icontains=self.keyword)).distinct()
|
||||||
|
if filter_kwargs:
|
||||||
|
self.queryset = self.queryset.filter(**filter_kwargs)
|
||||||
|
return self.queryset
|
||||||
|
|
||||||
|
def get_context_data(self, **kwargs):
|
||||||
|
context = {
|
||||||
|
'app': _('Audits'),
|
||||||
|
'action': _('Proxy log list'),
|
||||||
|
'user_list': set(
|
||||||
|
list(Session.objects.values_list('user', flat=True))),
|
||||||
|
'asset_list': set(
|
||||||
|
list(Session.objects.values_list('asset', flat=True))),
|
||||||
|
'system_user_list': set(
|
||||||
|
list(Session.objects.values_list('system_user', flat=True))),
|
||||||
|
'keyword': self.keyword,
|
||||||
|
'date_from': self.date_from_s,
|
||||||
|
'date_to': self.date_to_s,
|
||||||
|
'username': self.username,
|
||||||
|
'ip': self.ip,
|
||||||
|
'system_user': self.system_user,
|
||||||
|
}
|
||||||
|
kwargs.update(context)
|
||||||
|
return super().get_context_data(**kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
class SessionOnlineListView(SessionListView):
|
||||||
|
template_name = 'terminal/session_online.html'
|
||||||
|
|
||||||
|
def get_queryset(self):
|
||||||
|
queryset = super().get_queryset().filter(is_finished=False)
|
||||||
|
return queryset
|
||||||
|
|
||||||
|
def get_context_data(self, **kwargs):
|
||||||
|
context = {
|
||||||
|
'action': _('Session online list'),
|
||||||
|
}
|
||||||
|
kwargs.update(context)
|
||||||
|
return super().get_context_data(**kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
class SessionOfflineListView(SessionListView):
|
||||||
|
template_name = 'terminal/session_offline.html'
|
||||||
|
|
||||||
|
def get_queryset(self):
|
||||||
|
queryset = super().get_queryset()
|
||||||
|
queryset = queryset.filter(is_finished=True)
|
||||||
|
return queryset
|
||||||
|
|
||||||
|
def get_context_data(self, **kwargs):
|
||||||
|
context = {
|
||||||
|
'action': _('Session offline list'),
|
||||||
|
}
|
||||||
|
kwargs.update(context)
|
||||||
|
return super().get_context_data(**kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -8,9 +8,15 @@ from django.utils.translation import ugettext as _
|
||||||
from django.urls import reverse_lazy, reverse
|
from django.urls import reverse_lazy, reverse
|
||||||
|
|
||||||
from common.mixins import JSONResponseMixin
|
from common.mixins import JSONResponseMixin
|
||||||
from .models import Terminal
|
from ..models import Terminal
|
||||||
from .forms import TerminalForm
|
from ..forms import TerminalForm
|
||||||
from .hands import AdminUserRequiredMixin
|
from ..hands import AdminUserRequiredMixin
|
||||||
|
|
||||||
|
|
||||||
|
__all__ = [
|
||||||
|
"TerminalListView", "TerminalUpdateView", "TerminalDetailView",
|
||||||
|
"TerminalDeleteView", "TerminalConnectView", "TerminalAcceptView",
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
class TerminalListView(LoginRequiredMixin, ListView):
|
class TerminalListView(LoginRequiredMixin, ListView):
|
||||||
|
@ -60,7 +66,7 @@ class TerminalDeleteView(AdminUserRequiredMixin, DeleteView):
|
||||||
success_url = reverse_lazy('terminal:terminal-list')
|
success_url = reverse_lazy('terminal:terminal-list')
|
||||||
|
|
||||||
|
|
||||||
class TerminalAccept(AdminUserRequiredMixin, JSONResponseMixin, UpdateView):
|
class TerminalAcceptView(AdminUserRequiredMixin, JSONResponseMixin, UpdateView):
|
||||||
model = Terminal
|
model = Terminal
|
||||||
form_class = TerminalForm
|
form_class = TerminalForm
|
||||||
template_name = 'Terminal/terminal_modal_test.html'
|
template_name = 'Terminal/terminal_modal_test.html'
|
Loading…
Reference in New Issue