mirror of
https://github.com/jumpserver/jumpserver.git
synced 2025-09-26 15:25:55 +00:00
feat: 删掉所有view, templates, forms
This commit is contained in:
@@ -1,5 +0,0 @@
|
||||
# coding: utf-8
|
||||
#
|
||||
|
||||
from .terminal import *
|
||||
from .storage import *
|
@@ -1,165 +0,0 @@
|
||||
# coding: utf-8
|
||||
#
|
||||
|
||||
from django import forms
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from terminal.models import ReplayStorage, CommandStorage
|
||||
|
||||
|
||||
__all__ = [
|
||||
'ReplayStorageAzureForm', 'ReplayStorageOSSForm', 'ReplayStorageS3Form',
|
||||
'ReplayStorageCephForm', 'ReplayStorageSwiftForm',
|
||||
'CommandStorageTypeESForm',
|
||||
]
|
||||
|
||||
|
||||
class BaseStorageForm(forms.Form):
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(BaseStorageForm, self).__init__(*args, **kwargs)
|
||||
self.fields['type'].widget.attrs['disabled'] = True
|
||||
self.fields.move_to_end('comment')
|
||||
|
||||
|
||||
class BaseReplayStorageForm(BaseStorageForm, forms.ModelForm):
|
||||
|
||||
class Meta:
|
||||
model = ReplayStorage
|
||||
fields = ['name', 'type', 'comment']
|
||||
|
||||
|
||||
class BaseCommandStorageForm(BaseStorageForm, forms.ModelForm):
|
||||
|
||||
class Meta:
|
||||
model = CommandStorage
|
||||
fields = ['name', 'type', 'comment']
|
||||
|
||||
|
||||
class ReplayStorageAzureForm(BaseReplayStorageForm):
|
||||
azure_container_name = forms.CharField(
|
||||
max_length=128, label=_('Container name'), required=False
|
||||
)
|
||||
azure_account_name = forms.CharField(
|
||||
max_length=128, label=_('Account name'), required=False
|
||||
)
|
||||
azure_account_key = forms.CharField(
|
||||
max_length=128, label=_('Account key'), required=False,
|
||||
widget=forms.PasswordInput
|
||||
)
|
||||
azure_endpoint_suffix = forms.ChoiceField(
|
||||
choices=(
|
||||
('core.chinacloudapi.cn', 'core.chinacloudapi.cn'),
|
||||
('core.windows.net', 'core.windows.net')
|
||||
),
|
||||
label=_('Endpoint suffix'), required=False,
|
||||
)
|
||||
|
||||
|
||||
class ReplayStorageOSSForm(BaseReplayStorageForm):
|
||||
oss_bucket = forms.CharField(
|
||||
max_length=128, label=_('Bucket'), required=False
|
||||
)
|
||||
oss_access_key = forms.CharField(
|
||||
max_length=128, label=_('Access key'), required=False,
|
||||
widget=forms.PasswordInput
|
||||
)
|
||||
oss_secret_key = forms.CharField(
|
||||
max_length=128, label=_('Secret key'), required=False,
|
||||
widget=forms.PasswordInput
|
||||
)
|
||||
oss_endpoint = forms.CharField(
|
||||
max_length=128, label=_('Endpoint'), required=False,
|
||||
help_text=_(
|
||||
"""
|
||||
OSS: http://{REGION_NAME}.aliyuncs.com <br>
|
||||
Example: http://oss-cn-hangzhou.aliyuncs.com
|
||||
"""
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
class ReplayStorageS3Form(BaseReplayStorageForm):
|
||||
s3_bucket = forms.CharField(
|
||||
max_length=128, label=_('Bucket'), required=False
|
||||
)
|
||||
s3_access_key = forms.CharField(
|
||||
max_length=128, label=_('Access key'), required=False,
|
||||
widget=forms.PasswordInput
|
||||
)
|
||||
s3_secret_key = forms.CharField(
|
||||
max_length=128, label=_('Secret key'), required=False,
|
||||
widget=forms.PasswordInput
|
||||
)
|
||||
s3_endpoint = forms.CharField(
|
||||
max_length=128, label=_('Endpoint'), required=False,
|
||||
help_text=_(
|
||||
"""
|
||||
S3: http://s3.{REGION_NAME}.amazonaws.com <br>
|
||||
S3(China): http://s3.{REGION_NAME}.amazonaws.com.cn <br>
|
||||
Example: http://s3.cn-north-1.amazonaws.com.cn
|
||||
"""
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
class ReplayStorageCephForm(BaseReplayStorageForm):
|
||||
ceph_bucket = forms.CharField(
|
||||
max_length=128, label=_('Bucket'), required=False
|
||||
)
|
||||
ceph_access_key = forms.CharField(
|
||||
max_length=128, label=_('Access key'), required=False,
|
||||
widget=forms.PasswordInput
|
||||
)
|
||||
ceph_secret_key = forms.CharField(
|
||||
max_length=128, label=_('Secret key'), required=False,
|
||||
widget=forms.PasswordInput
|
||||
)
|
||||
ceph_endpoint = forms.CharField(
|
||||
max_length=128, label=_('Endpoint'), required=False,
|
||||
)
|
||||
|
||||
|
||||
class ReplayStorageSwiftForm(BaseReplayStorageForm):
|
||||
swift_bucket = forms.CharField(
|
||||
max_length=128, label=_('Bucket'), required=False
|
||||
)
|
||||
swift_access_key = forms.CharField(
|
||||
max_length=128, label=_('Access key'), required=False,
|
||||
widget=forms.PasswordInput
|
||||
)
|
||||
swift_secret_key = forms.CharField(
|
||||
max_length=128, label=_('Secret key'), required=False,
|
||||
widget=forms.PasswordInput
|
||||
)
|
||||
swift_region = forms.CharField(
|
||||
max_length=128, label=_('Region'), required=False,
|
||||
)
|
||||
swift_endpoint = forms.CharField(
|
||||
max_length=128, label=_('Endpoint'), required=False,
|
||||
)
|
||||
swift_protocol = forms.ChoiceField(
|
||||
choices=(
|
||||
('HTTP', 'http'),
|
||||
('HTTPS', 'https')
|
||||
), initial='http', label=_('Protocol'), required=True,
|
||||
)
|
||||
|
||||
|
||||
class CommandStorageTypeESForm(BaseCommandStorageForm):
|
||||
es_hosts = forms.CharField(
|
||||
max_length=128, label=_('Hosts'), required=True,
|
||||
help_text=_(
|
||||
"""
|
||||
Tips: If there are multiple hosts, separate them with a comma (,)
|
||||
<br>
|
||||
eg: http://www.jumpserver.a.com,http://www.jumpserver.b.com
|
||||
"""
|
||||
)
|
||||
)
|
||||
es_index = forms.CharField(
|
||||
max_length=128, label=_('Index'), required=True
|
||||
)
|
||||
es_doc_type = forms.CharField(
|
||||
max_length=128, label=_('Doc type'), required=True
|
||||
)
|
@@ -1,39 +0,0 @@
|
||||
# coding: utf-8
|
||||
#
|
||||
|
||||
__all__ = ['TerminalForm']
|
||||
|
||||
from django import forms
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from ..models import Terminal, ReplayStorage, CommandStorage
|
||||
|
||||
|
||||
def get_all_command_storage():
|
||||
for c in CommandStorage.objects.all():
|
||||
yield (c.name, c.name)
|
||||
|
||||
|
||||
def get_all_replay_storage():
|
||||
for r in ReplayStorage.objects.all():
|
||||
yield (r.name, r.name)
|
||||
|
||||
|
||||
class TerminalForm(forms.ModelForm):
|
||||
command_storage = forms.ChoiceField(
|
||||
choices=get_all_command_storage,
|
||||
label=_("Command storage"),
|
||||
help_text=_("Command can store in server db or ES, default to server, more see docs"),
|
||||
)
|
||||
replay_storage = forms.ChoiceField(
|
||||
choices=get_all_replay_storage,
|
||||
label=_("Replay storage"),
|
||||
help_text=_("Replay file can store in server disk, AWS S3, Aliyun OSS, default to server, more see docs"),
|
||||
)
|
||||
|
||||
class Meta:
|
||||
model = Terminal
|
||||
fields = [
|
||||
'name', 'remote_addr', 'comment',
|
||||
'command_storage', 'replay_storage',
|
||||
]
|
@@ -1,59 +0,0 @@
|
||||
{% extends '_base_create_update.html' %}
|
||||
{% load static %}
|
||||
{% load bootstrap3 %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block form %}
|
||||
<form id="StorageForm" method="post" class="form-horizontal">
|
||||
{% bootstrap_form form layout="horizontal"%}
|
||||
<div class="hr-line-dashed"></div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-4 col-sm-offset-2">
|
||||
<button class="btn btn-default" type="reset"> {% trans 'Reset' %}</button>
|
||||
<button id="submit_button" class="btn btn-primary" type="submit">{% trans 'Submit' %}</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
{% endblock %}
|
||||
|
||||
{% block custom_foot_js %}
|
||||
<script type="text/javascript">
|
||||
var storageCreateUrl, storageUpdateUrl, storageListUrl = null;
|
||||
var type_id = '#' + '{{ form.type.id_for_label }}';
|
||||
var api_action = "{{ api_action }}";
|
||||
|
||||
function getFormDataType(){
|
||||
return $(type_id+ " option:selected").val();
|
||||
}
|
||||
function getFormData(form){
|
||||
var data = form.serializeObject();
|
||||
data['type'] = getFormDataType();
|
||||
data['meta'] = constructFormDataMeta(data);
|
||||
return data
|
||||
}
|
||||
|
||||
$(document).ready(function () {
|
||||
})
|
||||
.on("submit", "form", function (evt) {
|
||||
evt.preventDefault();
|
||||
var the_url = storageCreateUrl;
|
||||
var method = "POST";
|
||||
{% if api_action == "update" %}
|
||||
the_url = storageUpdateUrl.replace('{{ DEFAULT_PK }}', '{{ object.id }}');
|
||||
method = "PUT";
|
||||
{% endif %}
|
||||
var redirect_to = storageListUrl;
|
||||
var form = $("form");
|
||||
var data = getFormData(form);
|
||||
var props = {
|
||||
url: the_url,
|
||||
data: data,
|
||||
method: method,
|
||||
form: form,
|
||||
redirect_to: redirect_to
|
||||
};
|
||||
formSubmit(props);
|
||||
})
|
||||
</script>
|
||||
{% endblock %}
|
@@ -1,129 +0,0 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load i18n static %}
|
||||
|
||||
{% block content %}
|
||||
<div class="wrapper wrapper-content animated fadeIn">
|
||||
<div class="col-lg-12">
|
||||
<div class="tabs-container">
|
||||
<ul class="nav nav-tabs">
|
||||
<li {% if is_replay %}class="active" {% endif %}><a href="{% url 'terminal:replay-storage-list' %}"> {% trans 'Replay storage' %}</a></li>
|
||||
<li {% if is_command %}class="active" {% endif %}><a href="{% url 'terminal:command-storage-list' %}" >{% trans 'Command storage' %}</a></li>
|
||||
</ul>
|
||||
<div class="tab-content">
|
||||
<div id="my-tickets" class="tab-pane active">
|
||||
<div class="panel-body">
|
||||
<div class="btn-group uc pull-left m-r-5">
|
||||
<button data-toggle="dropdown" class="btn btn-primary btn-sm dropdown-toggle">
|
||||
{% block create_storage_info %}{% endblock %}
|
||||
<span class="caret"></span></button>
|
||||
<ul class="dropdown-menu">
|
||||
{% for key, value in type_choices %}
|
||||
<li><a class="" href="{% block create_storage_url %}{% endblock %}?type={{ key }}">{{ value }}</a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
<table class="table table-striped table-bordered table-hover" id="storage_list_table" >
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="text-center">
|
||||
<input id="" type="checkbox" class="ipt_check_all">
|
||||
</th>
|
||||
<th class="text-center">{% trans 'Name' %}</th>
|
||||
<th class="text-center">{% trans 'Type' %}</th>
|
||||
<th class="text-center">{% trans 'Comment' %}</th>
|
||||
<th class="text-center" style="width: 150px">{% trans 'Action' %}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
{% block content_bottom_left %}{% endblock %}
|
||||
{% block custom_foot_js %}
|
||||
<script>
|
||||
var storage_table , storageTableAjaxUrl , storageUpdateUrl , storageDeleteUrl , storageTestConnectiveUrl = null ;
|
||||
|
||||
function initTable() {
|
||||
var options = {
|
||||
ele: $('#storage_list_table'),
|
||||
columnDefs: [
|
||||
{targets: 4, createdCell: function (td, cellData, rowData) {
|
||||
var name = htmlEscape(rowData.name);
|
||||
var del_btn, update_btn;
|
||||
if (['server', 'null'].indexOf(rowData.type) === -1){
|
||||
del_btn = '<a class="btn btn-xs btn-danger m-l-xs btn-del" data-uid="{{ DEFAULT_PK }}" mark=1 data-name="99991938">{% trans "Delete" %}</a>'
|
||||
.replace('{{ DEFAULT_PK }}', cellData)
|
||||
.replace('99991938', name);
|
||||
update_btn = '<a class="btn btn-xs m-l-xs btn-info btn-update" data-uid="{{ DEFAULT_PK }}">{% trans "Update" %}</a>'.replace('{{ DEFAULT_PK }}', cellData);
|
||||
|
||||
}
|
||||
else{
|
||||
del_btn = '<a class="btn btn-xs btn-danger disabled m-l-xs btn-del" data-uid="{{ DEFAULT_PK }}" mark=1 data-name="99991938">{% trans "Delete" %}</a>'
|
||||
.replace('{{ DEFAULT_PK }}', cellData)
|
||||
.replace('99991938', name);
|
||||
update_btn = '<a class="btn btn-xs m-l-xs disabled btn-info btn-update" data-uid="{{ DEFAULT_PK }}">{% trans "Update" %}</a>'.replace('{{ DEFAULT_PK }}', cellData);
|
||||
}
|
||||
var test_btn = '<a class="btn btn-xs btn-primary m-l-xs btn-test-connective" data-uid="{{ DEFAULT_PK }}">{% trans 'Test' %}</a>'.replace('{{ DEFAULT_PK }}', cellData);
|
||||
$(td).html(update_btn + del_btn + test_btn);
|
||||
}
|
||||
}
|
||||
],
|
||||
ajax_url: storageTableAjaxUrl,
|
||||
columns: [
|
||||
{data: "id"}, {data: "name" }, {data: "type"}, {data: "comment"},
|
||||
{data: "id", orderable: false,}
|
||||
],
|
||||
op_html: $('#actions').html()
|
||||
};
|
||||
storage_table = jumpserver.initServerSideDataTable(options);
|
||||
return storage_table
|
||||
}
|
||||
|
||||
$(document).ready(function(){
|
||||
initTable()
|
||||
})
|
||||
.on('click', '.btn-update', function (){
|
||||
var $this = $(this);
|
||||
var uid = $this.data('uid');
|
||||
window.location.href = storageUpdateUrl.replace('{{ DEFAULT_PK }}', uid);
|
||||
})
|
||||
.on('click', '.btn-del', function () {
|
||||
var $this = $(this);
|
||||
var uid = $this.data('uid');
|
||||
var name = $this.data('name');
|
||||
var the_url = storageDeleteUrl.replace('{{ DEFAULT_PK }}', uid);
|
||||
objectDelete($this, name, the_url);
|
||||
})
|
||||
.on('click', '.btn-test-connective', function () {
|
||||
var $this = $(this);
|
||||
var uid = $this.data('uid');
|
||||
var the_url = storageTestConnectiveUrl.replace('{{ DEFAULT_PK }}', uid);
|
||||
var error = function (data) {
|
||||
toastr.error(data)
|
||||
};
|
||||
var success = function(data) {
|
||||
var isValid = data.is_valid;
|
||||
if (isValid){
|
||||
toastr.success(data.msg)
|
||||
}
|
||||
else{
|
||||
toastr.error(data.msg)
|
||||
}
|
||||
};
|
||||
requestApi({
|
||||
url: the_url,
|
||||
error: error,
|
||||
method: 'GET',
|
||||
success: success,
|
||||
flash_message: false
|
||||
});
|
||||
})
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
@@ -1,237 +0,0 @@
|
||||
{% extends '_base_list.html' %}
|
||||
{% load i18n %}
|
||||
{% load static %}
|
||||
{% load common_tags %}
|
||||
{% block custom_head_css_js %}
|
||||
<link href="{% static 'css/plugins/datepicker/datepicker3.css' %}" rel="stylesheet">
|
||||
<style>
|
||||
.toggle {
|
||||
cursor: pointer;
|
||||
}
|
||||
.detail-key {
|
||||
width: 70px;
|
||||
}
|
||||
</style>
|
||||
{% endblock %}
|
||||
|
||||
{% block table_pagination %}
|
||||
{% endblock %}
|
||||
|
||||
{% block table_search %}
|
||||
{% endblock %}
|
||||
|
||||
{% block table_container %}
|
||||
<table class="table table-striped table-bordered table-hover" id="command_table" data-page="false" >
|
||||
<thead>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th>{% trans 'Command' %}</th>
|
||||
<th>{% trans 'Risk level' %}</th>
|
||||
<th>{% trans 'User' %}</th>
|
||||
<th>{% trans 'Asset' %}</th>
|
||||
<th>{% trans 'System user'%}</th>
|
||||
<th>{% trans 'Session' %}</th>
|
||||
<th>{% trans 'Datetime' %}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<div id="actions" class="hide">
|
||||
<div class="input-group">
|
||||
<select class="form-control m-b" style="width: auto" id="slct_bulk_update">
|
||||
<option value="export">{% trans 'Export command' %}</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>
|
||||
|
||||
<div class="hide" id="daterange">
|
||||
<div class="form-group p-l-5" id="date" style="padding-left: 5px">
|
||||
<div class="input-daterange input-group p-l-5" 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;" id="date_from" name="date_from" value="{{ date_from|date:'Y-m-d' }}">
|
||||
<span class="input-group-addon">to</span>
|
||||
<input type="text" class="input-sm form-control" style="width: 100px;" id="date_to" name="date_to" value="{{ date_to|date:'Y-m-d' }}">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% include '_filter_dropdown.html' %}
|
||||
{% endblock %}
|
||||
{% block content_bottom_left %}{% endblock %}
|
||||
{% block custom_foot_js %}
|
||||
<script src="{% static 'js/plugins/datepicker/bootstrap-datepicker.js' %}" charset="UTF-8"></script>
|
||||
<script src="{% static 'js/plugins/datepicker/bootstrap-datepicker.zh-CN.min.js' %}" ></script>
|
||||
<script>
|
||||
|
||||
var table;
|
||||
$(document).ready(function () {
|
||||
table = initTable().on("init", function () {
|
||||
var dateFromRef = $("#date_from");
|
||||
var dateToRef = $("#date_to");
|
||||
var options = {
|
||||
format: "yyyy-mm-dd",
|
||||
todayBtn: "linked",
|
||||
keyboardNavigation: false,
|
||||
forceParse: false,
|
||||
calendarWeeks: true,
|
||||
autoclose: true,
|
||||
language: getUserLang(),
|
||||
};
|
||||
dateFromRef.datepicker(options).on("changeDate", function () {
|
||||
var value = $(this).val() + ' 0:0:0';
|
||||
var date = safeDate(value);
|
||||
var url = table.ajax.url();
|
||||
url = setUrlParam(url, "date_from", date.getTime()/1000);
|
||||
table.ajax.url(url);
|
||||
table.ajax.reload();
|
||||
});
|
||||
dateToRef.datepicker(options).on("changeDate", function () {
|
||||
var value = $(this).val() + ' 23:59:59';
|
||||
var date = safeDate(value);
|
||||
var url = table.ajax.url();
|
||||
url = setUrlParam(url, "date_to", date.getTime()/1000);
|
||||
table.ajax.url(url);
|
||||
table.ajax.reload();
|
||||
});
|
||||
});
|
||||
|
||||
var filterMenu = [
|
||||
{title: "{% trans 'User' %}", value: "user"},
|
||||
{title: "{% trans 'Asset' %}", value: "asset"},
|
||||
{title: "{% trans 'System user' %}", value: "system_user"},
|
||||
{title: "{% trans 'Command' %}", value: "input"},
|
||||
{title: "{% trans 'Risk level' %}", value: "risk_level", submenu: [
|
||||
{title: "{% trans 'Ordinary' %}", value: "0"},
|
||||
{title: "{% trans 'Dangerous' %}", value: "5"},
|
||||
]},
|
||||
];
|
||||
initTableFilterDropdown('#command_table_filter input', filterMenu, 15, 50)
|
||||
|
||||
})
|
||||
.on('click', '#btn_bulk_update', function(){
|
||||
// var action = $('#slct_bulk_update').val();
|
||||
var params = getUrlParams(table.ajax.url());
|
||||
var searchParams = '';
|
||||
var searchValue = $('input[type=search]').val();
|
||||
var searchMap = parseTableFilter(searchValue);
|
||||
if (Object.keys(searchMap).length === 0) {
|
||||
searchParams = searchValue;
|
||||
} else {
|
||||
$.each(searchMap, function (k, v) {
|
||||
searchParams += k + '=' + v + '&'
|
||||
})
|
||||
}
|
||||
params += '&' + searchParams;
|
||||
|
||||
var exportPath = "{% url 'api-terminal:command-export' %}";
|
||||
var url = exportPath + "?" + params;
|
||||
window.open(url);
|
||||
})
|
||||
.on('click', 'body', function (e) {
|
||||
$('.dropdown-menu.search-help').hide()
|
||||
})
|
||||
.on('click', '.toggle', function (e) {
|
||||
e.preventDefault();
|
||||
var detailRows = [];
|
||||
var tr = $(this).closest('tr');
|
||||
var row = table.row(tr);
|
||||
var idx = $.inArray(tr.attr('id'), detailRows);
|
||||
|
||||
if (row.child.isShown()) {
|
||||
tr.removeClass('details');
|
||||
$(this).children('i:first-child').removeClass('fa-angle-down').addClass('fa-angle-right');
|
||||
row.child.hide();
|
||||
|
||||
// Remove from the 'open' array
|
||||
detailRows.splice(idx, 1);
|
||||
} else {
|
||||
tr.addClass('details');
|
||||
$(this).children('i:first-child').removeClass('fa-angle-right').addClass('fa-angle-down');
|
||||
row.child(format(row.data())).show();
|
||||
// Add to the 'open' array
|
||||
if (idx === -1) {
|
||||
detailRows.push(tr.attr('id'));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
function format(d) {
|
||||
var output = $("<pre style='border: none; background: none; white-space: pre-wrap'></pre>");
|
||||
|
||||
output.append('$ ', d.input);
|
||||
output.append('\r\n\r\n');
|
||||
output.append(d.output);
|
||||
return output
|
||||
}
|
||||
|
||||
var commandListUrl = '{% url "api-terminal:command-list" %}';
|
||||
var dateFrom = "{{ date_from.timestamp }}";
|
||||
var dateTo = "{{ date_to.timestamp }}";
|
||||
|
||||
function initTable() {
|
||||
commandListUrl = setUrlParam(commandListUrl, "date_from", dateFrom);
|
||||
commandListUrl = setUrlParam(commandListUrl, "date_to", dateTo);
|
||||
var options = {
|
||||
ele: $('#command_table'),
|
||||
columnDefs: [
|
||||
{targets: 0, createdCell: function (td, cellData, rowData) {
|
||||
$(td).addClass("toggle");
|
||||
$(td).html("<i class='fa fa-angle-right'></i>");
|
||||
}},
|
||||
{targets: 1, createdCell: function (td, cellData) {
|
||||
var data = htmlEscape(cellData);
|
||||
var interHtml = $("<span></span>");
|
||||
if (data.length > 40) {
|
||||
interHtml.attr('title', data);
|
||||
data = data.slice(0, 40);
|
||||
data += ' ...';
|
||||
}
|
||||
interHtml.html(data);
|
||||
$(td).html(interHtml);
|
||||
}},
|
||||
{targets: 2, createdCell: function (td, cellData){
|
||||
let risk;
|
||||
if(cellData === 5){
|
||||
risk = "{% trans 'Dangerous' %}";
|
||||
}
|
||||
else{
|
||||
risk = "{% trans 'Ordinary' %}";
|
||||
}
|
||||
$(td).html(risk)
|
||||
}},
|
||||
{targets: 6, createdCell: function (td, cellData) {
|
||||
var data = '<a href="{% url "terminal:session-detail" pk=DEFAULT_PK %}">{% trans "Goto" %}</a>'
|
||||
.replace('{{ DEFAULT_PK }}', cellData);
|
||||
$(td).html(data);
|
||||
}},
|
||||
{targets: 7, createdCell: function (td, cellData) {
|
||||
var data = toSafeLocalDateStr(cellData*1000);
|
||||
$(td).html(data);
|
||||
}},
|
||||
],
|
||||
toggle: true,
|
||||
ajax_url: commandListUrl,
|
||||
columns: [
|
||||
{data: "id"}, {data: "input", orderable: false, width: "40%"},
|
||||
{data: "risk_level", orderable: false}, {data: "user", orderable: false},
|
||||
{data: "asset", orderable: false}, {data: "system_user", orderable: false},
|
||||
{data: "session", orderable: false}, {data: "timestamp", width: "160px", orderable: false},
|
||||
],
|
||||
select: {},
|
||||
op_html: $('#actions').html(),
|
||||
fb_html: $("#daterange").html(),
|
||||
};
|
||||
table = jumpserver.initServerSideDataTable(options);
|
||||
return table
|
||||
}
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
||||
|
@@ -1,103 +0,0 @@
|
||||
{% load common_tags %}
|
||||
{% load static %}
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Command Report</title>
|
||||
<style>
|
||||
*{
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
.background {
|
||||
background-color: #535659;
|
||||
padding-top: 50px;
|
||||
padding-bottom: 50px;
|
||||
}
|
||||
|
||||
.paper {
|
||||
margin-left: 23%;
|
||||
margin-right: 24%;
|
||||
border: solid;
|
||||
padding: 50px;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-style: italic;
|
||||
text-align: center;
|
||||
}
|
||||
.info {
|
||||
width: 200px;
|
||||
margin-left: 450px;
|
||||
font-style: italic;
|
||||
text-align: left;
|
||||
padding-top: 20px;
|
||||
padding-bottom: 20px;
|
||||
}
|
||||
|
||||
.command {
|
||||
margin-left: 10px;
|
||||
}
|
||||
.command-desc {
|
||||
font-size: 12px;
|
||||
}
|
||||
.command-desc span {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.command-input {
|
||||
{#font-style: italic;#}
|
||||
font-size: 15px;
|
||||
margin-top: 10px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.command-input span {
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.hr-line-dashed {
|
||||
border-top: 1px dashed #000;
|
||||
color: #000;
|
||||
background-color: #fff;
|
||||
height: 1px;
|
||||
margin: 20px 0;
|
||||
}
|
||||
pre {
|
||||
font-size: 12px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="background">
|
||||
<div class="paper">
|
||||
<h2>Command Report</h2>
|
||||
<div class="info">
|
||||
<p>total: {{ total_count }}</p>
|
||||
<p>date: {{ now | ts_to_date }}</p>
|
||||
</div>
|
||||
|
||||
<div class="hr-line-dashed"></div>
|
||||
|
||||
<div>
|
||||
{% for command in queryset %}
|
||||
<div class="command">
|
||||
<p class="command-desc">
|
||||
[{{ command.user}} {{ command.system_user }}@{{ command.asset }} {{ command.timestamp | ts_to_date }}]
|
||||
<span>{{ forloop.counter }}</span>
|
||||
</p>
|
||||
|
||||
<p class="command-input"><span>$ </span>{{ command.input }}</p>
|
||||
|
||||
<pre>{{ command.output }}</pre>
|
||||
</div>
|
||||
|
||||
<div class="hr-line-dashed"></div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@@ -1,30 +0,0 @@
|
||||
{% extends 'terminal/base_storage_create_update.html' %}
|
||||
{% load i18n static %}
|
||||
|
||||
{% block custom_foot_js %}
|
||||
{{ block.super }}
|
||||
|
||||
<script type="text/javascript">
|
||||
|
||||
storageCreateUrl = "{% url 'api-terminal:command-storage-list' %}";
|
||||
storageUpdateUrl = "{% url 'api-terminal:command-storage-detail' pk=DEFAULT_PK %}";
|
||||
storageListUrl = "{% url "terminal:command-storage-list" %}";
|
||||
|
||||
function constructFormDataMeta(data){
|
||||
var meta = {};
|
||||
var type = data.type;
|
||||
for (var k in data){
|
||||
if (k.startsWith(type)){
|
||||
var v = data[k];
|
||||
if (k === 'es_hosts'){
|
||||
v = v.split(',');
|
||||
}
|
||||
meta[k] = v;
|
||||
delete data[k]
|
||||
}
|
||||
}
|
||||
return meta
|
||||
}
|
||||
|
||||
</script>
|
||||
{% endblock %}
|
@@ -1,15 +0,0 @@
|
||||
{% extends 'terminal/base_storage_list.html' %}
|
||||
{% load i18n static %}
|
||||
|
||||
{% block create_storage_url %}{% url "terminal:command-storage-create" %}{% endblock%}
|
||||
{% block create_storage_info %}{% trans 'Create command storage' %}{% endblock %}
|
||||
{% block custom_foot_js %}
|
||||
{{ block.super }}
|
||||
<script>
|
||||
storageTableAjaxUrl = '{% url "api-terminal:command-storage-list" %}';
|
||||
storageUpdateUrl = '{% url "terminal:command-storage-update" pk=DEFAULT_PK %}';
|
||||
storageDeleteUrl = '{% url "api-terminal:command-storage-detail" pk=DEFAULT_PK %}';
|
||||
storageTestConnectiveUrl = '{% url "api-terminal:command-storage-test-connective" pk=DEFAULT_PK %}';
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
@@ -1,25 +0,0 @@
|
||||
{% extends 'terminal/base_storage_create_update.html' %}
|
||||
{% load i18n static %}
|
||||
|
||||
{% block custom_foot_js %}
|
||||
{{ block.super }}
|
||||
|
||||
<script type="text/javascript">
|
||||
storageCreateUrl = "{% url 'api-terminal:replay-storage-list' %}";
|
||||
storageUpdateUrl = "{% url 'api-terminal:replay-storage-detail' pk=DEFAULT_PK %}";
|
||||
storageListUrl = "{% url "terminal:replay-storage-list" %}";
|
||||
|
||||
function constructFormDataMeta(data){
|
||||
var meta = {};
|
||||
var type = data.type;
|
||||
for (var k in data){
|
||||
if (k.startsWith(type)){
|
||||
meta[k] = data[k];
|
||||
delete data[k]
|
||||
}
|
||||
}
|
||||
return meta
|
||||
}
|
||||
|
||||
</script>
|
||||
{% endblock %}
|
@@ -1,14 +0,0 @@
|
||||
{% extends 'terminal/base_storage_list.html' %}
|
||||
{% load i18n static %}
|
||||
|
||||
{% block create_storage_url %}{% url "terminal:replay-storage-create" %}{% endblock%}
|
||||
{% block create_storage_info %}{% trans 'Create replay storage' %}{% endblock %}
|
||||
{% block custom_foot_js %}
|
||||
{{ block.super }}
|
||||
<script>
|
||||
storageTableAjaxUrl = '{% url "api-terminal:replay-storage-list" %}';
|
||||
storageUpdateUrl = '{% url "terminal:replay-storage-update" pk=DEFAULT_PK %}';
|
||||
storageDeleteUrl = '{% url "api-terminal:replay-storage-detail" pk=DEFAULT_PK %}';
|
||||
storageTestConnectiveUrl = '{% url "api-terminal:replay-storage-test-connective" pk=DEFAULT_PK %}';
|
||||
</script>
|
||||
{% endblock %}
|
@@ -1,96 +0,0 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load static %}
|
||||
{% load i18n %}
|
||||
{% load common_tags %}
|
||||
|
||||
{% block custom_head_css_js %}
|
||||
<link href="{% static 'css/plugins/ladda/ladda-themeless.min.css' %}" rel="stylesheet">
|
||||
<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>
|
||||
<a class="text-center" href="{% url 'terminal:session-detail' pk=object.id %}"> {% trans 'Session detail' %} </a>
|
||||
</li>
|
||||
<li class="active">
|
||||
<a class="text-center" href="{% url 'terminal:session-commands' pk=object.id %}"> {% trans 'Commands' %} </a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="tab-content">
|
||||
<div class="col-sm-10" style="padding-left: 0;">
|
||||
<div class="ibox float-e-margins">
|
||||
<div class="ibox-title">
|
||||
<span style="float: left">{% trans 'Command list' %} <b></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>{% trans 'Command' %}</th>
|
||||
<th data-hide="all"></th>
|
||||
<th style="">{% trans 'Datetime' %}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for command in object_list %}
|
||||
<tr>
|
||||
<td>{{ forloop.counter }}</td>
|
||||
<td>{{ command.input | truncatechars:40 }}</td>
|
||||
<td><pre style="border: none;background: none; white-space: pre-wrap;">
|
||||
$ {{ command.input }}
|
||||
|
||||
{{ command.output }}
|
||||
</pre></td>
|
||||
<td>{{ command.timestamp|ts_to_date}}</td>
|
||||
</tr>
|
||||
{% empty %}
|
||||
<tr>
|
||||
<td colspan="3">{% trans "There is no command about this session" %}</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 %}
|
@@ -1,211 +0,0 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load static %}
|
||||
{% load i18n %}
|
||||
{% load common_tags %}
|
||||
|
||||
{% block custom_head_css_js %}
|
||||
<link href="{% static 'css/plugins/ladda/ladda-themeless.min.css' %}" rel="stylesheet">
|
||||
<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 class="text-center" href="{% url 'terminal:session-detail' pk=object.id %}"> {% trans 'Session detail' %} </a>
|
||||
</li>
|
||||
<li>
|
||||
<a class="text-center" href="{% url 'terminal:session-commands' pk=object.id %}"> {% trans 'Commands' %} </a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="tab-content">
|
||||
<div class="col-sm-8" style="padding-left: 0;">
|
||||
<div class="ibox float-e-margins">
|
||||
<div class="ibox-title">
|
||||
<span style="float: left"> <b>{{ object.id }}</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 class="table">
|
||||
<tbody>
|
||||
<tr class="no-borders-tr">
|
||||
<td width="20%">{% trans 'User' %}:</td>
|
||||
<td><b>{{ object.user }}</b></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{% trans 'Asset' %}:</td>
|
||||
<td><b>{{ object.asset }}</b></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{% trans 'System user' %}:</td>
|
||||
<td><b>{{ object.system_user }}</b></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{% trans 'Protocol' %}:</td>
|
||||
<td><b>{{ object.protocol }}</b></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{% trans 'Login from' %}:</td>
|
||||
<td><b>{{ object.login_from_display }}</b></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{% trans 'Remote addr' %}:</td>
|
||||
<td><b>{{ object.remote_addr }}</b></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{% trans 'Date start' %}:</td>
|
||||
<td><b>{{ object.date_start }}</b></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{% trans 'Date end' %}:</td>
|
||||
<td><b>{{ object.date_end }}</b></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-4" style="padding-left: 0;padding-right: 0">
|
||||
<div class="panel panel-primary">
|
||||
<div class="panel-heading">
|
||||
<i class="fa fa-info-circle"></i> {% trans 'Quick modify' %}
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<table class="table">
|
||||
<tbody>
|
||||
{% if object.is_finished %}
|
||||
<tr class="no-borders-tr">
|
||||
<td>{% trans 'Replay session' %}:</td>
|
||||
<td>
|
||||
<span class="pull-right">
|
||||
<button type="button" onclick="window.open('/luna/replay/{{ object.id }}','luna', 'height=600, width=800, top=400, left=400, toolbar=no, menubar=no, scrollbars=no, location=no, status=no')" class="btn btn-primary btn-xs" id="btn_reset_password" style="width: 54px">{% trans 'Go' %}</button>
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{% trans 'Download replay' %}:</td>
|
||||
<td>
|
||||
<span class="pull-right">
|
||||
<button class="ladda-button btn btn-primary btn-xs btn-download" style="width: 54px" data-style="zoom-in" >{% trans 'Download' %}</button>
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
{% else %}
|
||||
<!--<tr>-->
|
||||
<!--<td class="no-borders" >{% trans 'Monitor session' %}:</td>-->
|
||||
<!--<td class="no-borders" >-->
|
||||
<!--<span class="pull-right">-->
|
||||
<!--<button type="button" class="btn btn-primary btn-xs " style="width: 54px">{% trans 'Go' %}</button>-->
|
||||
<!--</span>-->
|
||||
<!--</td>-->
|
||||
<!--</tr>-->
|
||||
<tr class="no-borders-tr">
|
||||
<td>{% trans 'Terminate session' %}:</td>
|
||||
<td>
|
||||
<span class="pull-right">
|
||||
<button type="button" class="btn btn-primary btn-xs btn-term" value="{{ object.id }}" terminal="{{ object.terminal.id }}" style="width: 54px;">{% trans 'Confirm' %}</button>
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
{% block custom_foot_js %}
|
||||
<script src="{% static "js/plugins/ladda/spin.min.js" %}"></script>
|
||||
<script src="{% static "js/plugins/ladda/ladda.min.js" %}"></script>
|
||||
<script src="{% static "js/plugins/ladda/ladda.jquery.min.js" %}"></script>
|
||||
<script>
|
||||
var downloadPageUrl = "{% url "terminal:session-replay-download" pk=object.id %}";
|
||||
var sessionReplayDetailUrl = '{% url "api-terminal:session-replay" pk=object.id %}';
|
||||
var interval = null;
|
||||
var l;
|
||||
|
||||
function terminateSession(data) {
|
||||
function success() {
|
||||
window.setTimeout(function () {
|
||||
window.location.reload()
|
||||
}, 300)
|
||||
}
|
||||
var the_url = "{% url 'api-terminal:tasks-list' %}";
|
||||
requestApi({
|
||||
url: the_url,
|
||||
method: 'POST',
|
||||
body: JSON.stringify(data),
|
||||
success: success,
|
||||
success_message: "{% trans 'Terminate success'%}"
|
||||
});
|
||||
}
|
||||
|
||||
function getReplayDetail() {
|
||||
function success(data) {
|
||||
if (data.src) {
|
||||
clearInterval(interval);
|
||||
l.ladda('stop');
|
||||
window.open(downloadPageUrl);
|
||||
return;
|
||||
}
|
||||
if (data.status === "error") {
|
||||
clearInterval(interval);
|
||||
l.ladda('stop');
|
||||
toastr.error(data.error)
|
||||
}
|
||||
}
|
||||
|
||||
requestApi({
|
||||
url: sessionReplayDetailUrl,
|
||||
method: 'GET',
|
||||
success: success,
|
||||
flash_message: false
|
||||
})
|
||||
}
|
||||
|
||||
$(document).ready(function () {
|
||||
l = $('.btn-download').ladda();
|
||||
l.click(function () {
|
||||
l.ladda('start');
|
||||
interval = setInterval(getReplayDetail, 2000)
|
||||
});
|
||||
var downloadDirect = getUrlParam('download');
|
||||
if (downloadDirect) {
|
||||
$('.btn-download').trigger('click');
|
||||
}
|
||||
}).on('click', '.btn-term', function () {
|
||||
var $this = $(this);
|
||||
var session_id = $this.attr('value');
|
||||
var terminal_id = $this.attr('terminal');
|
||||
alert(session_id);
|
||||
var data = {
|
||||
name: "kill_session",
|
||||
args: session_id,
|
||||
terminal: terminal_id
|
||||
};
|
||||
terminateSession(data)
|
||||
})
|
||||
</script>
|
||||
{% endblock %}
|
@@ -1,322 +0,0 @@
|
||||
{% extends '_base_list.html' %}
|
||||
{% load i18n %}
|
||||
{% load static %}
|
||||
{% load terminal_tags %}
|
||||
{% load common_tags %}
|
||||
{% block custom_head_css_js %}
|
||||
<link href="{% static 'css/plugins/datepicker/datepicker3.css' %}" rel="stylesheet">
|
||||
{% endblock %}
|
||||
|
||||
{% block content_left_head %}
|
||||
{% endblock %}
|
||||
|
||||
{% block table_pagination %}
|
||||
{% endblock %}
|
||||
|
||||
{% block table_search %}
|
||||
{% endblock %}
|
||||
|
||||
{% block table_container %}
|
||||
<table class="table table-striped table-bordered table-hover" id="session_table" data-page="false" >
|
||||
<thead>
|
||||
<tr>
|
||||
<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 'Remote addr' %}</th>
|
||||
<th class="text-center">{% trans 'Protocol' %}</th>
|
||||
<th class="text-center">{% trans 'Login from' %}</th>
|
||||
<th class="text-center">{% trans 'Command' %}</th>
|
||||
<th class="text-center">{% trans 'Date start' %}</th>
|
||||
<th class="text-center">{% trans 'Duration' %}</th>
|
||||
<th class="text-center">{% trans 'Action' %}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<div id="actions" class="hide">
|
||||
{% if type == "online" and request.user.can_admin_current_org %}
|
||||
<div class="input-group">
|
||||
<select class="form-control m-b" style="width: auto" id="slct_bulk_update">
|
||||
<option value="terminate">{% trans 'Terminate selected' %}</option>
|
||||
<option value="finished">{% trans 'Confirm finished' %}</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>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div class="hide" id="daterange">
|
||||
<div class="form-group p-l-5" id="date" style="padding-left: 5px">
|
||||
<div class="input-daterange input-group p-l-5" 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;" id="date_from" name="date_from" value="{{ date_from|date:'Y-m-d' }}">
|
||||
<span class="input-group-addon">to</span>
|
||||
<input type="text" class="input-sm form-control" style="width: 100px;" id="date_to" name="date_to" value="{{ date_to|date:'Y-m-d' }}">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ul class="dropdown-menu search-help">
|
||||
<li><a class="search-item" data-value="user">{% trans 'User' %}</a></li>
|
||||
<li><a class="search-item" data-value="asset">{% trans 'Asset' %}</a></li>
|
||||
<li><a class="search-item" data-value="system_user">{% trans 'System user' %}</a></li>
|
||||
<li><a class="search-item" data-value="remote_addr">{% trans 'Remote addr' %}</a></li>
|
||||
<li><a class="search-item" data-value="protocol">{% trans 'Protocol' %}</a></li>
|
||||
{# <li><a class="search-item" data-value="protocol">{% trans 'Protocol' %}</a></li>#}
|
||||
</ul>
|
||||
{% endblock %}
|
||||
|
||||
|
||||
{% block custom_foot_js %}
|
||||
<script src="{% static 'js/plugins/datepicker/bootstrap-datepicker.js' %}"></script>
|
||||
<script src="{% static 'js/plugins/datepicker/bootstrap-datepicker.zh-CN.min.js' %}" ></script>
|
||||
<script>
|
||||
|
||||
function terminateSession(data) {
|
||||
function success() {
|
||||
window.setTimeout(function () {
|
||||
window.location.reload()
|
||||
}, 1000)
|
||||
}
|
||||
var success_message = '{% trans "Terminate task send, waiting ..." %}';
|
||||
var the_url = "{% url 'api-terminal:kill-session' %}";
|
||||
requestApi({
|
||||
url: the_url,
|
||||
method: 'POST',
|
||||
body: JSON.stringify(data),
|
||||
success: success,
|
||||
success_message: success_message
|
||||
});
|
||||
}
|
||||
|
||||
var sessionListUrl = "{% url 'api-terminal:session-list' %}?is_finished={% if type == "online" %}0{% else %}1{% endif %}";
|
||||
var dateFrom = "{{ date_from.timestamp }}";
|
||||
var dateTo = "{{ date_to.timestamp }}";
|
||||
|
||||
function initTable() {
|
||||
dateFrom = toSafeDateISOStr(dateFrom * 1000);
|
||||
dateTo = toSafeDateISOStr(dateTo * 1000);
|
||||
sessionListUrl = setUrlParam(sessionListUrl, "date_from", dateFrom);
|
||||
sessionListUrl = setUrlParam(sessionListUrl, "date_to", dateTo);
|
||||
var options = {
|
||||
ele: $('#session_table'),
|
||||
ordering: false,
|
||||
columnDefs: [
|
||||
{targets: 1, createdCell: function (td, cellData, rowData, i) {
|
||||
var index = i + 1;
|
||||
var data = '<a href="{% url 'terminal:session-detail' pk=DEFAULT_PK %}">'
|
||||
+ index + "</a>";
|
||||
data = data.replace("{{ DEFAULT_PK }}", cellData);
|
||||
|
||||
$(td).html(data);
|
||||
}},
|
||||
{targets: 9, createdCell: function (td, cellData) {
|
||||
var data = toSafeLocalDateStr(cellData);
|
||||
$(td).html(data);
|
||||
}},
|
||||
{targets: 10, createdCell: function (td, cellData, rowData) {
|
||||
var data = "";
|
||||
if (cellData && rowData.date_start) {
|
||||
data = timeOffset(rowData.date_start, cellData)
|
||||
}
|
||||
$(td).html(data);
|
||||
}},
|
||||
{targets: 11, createdCell: function (td, cellData, rowData) {
|
||||
var btnGroup = "";
|
||||
var replayBtn = '<a disabled data-session="sessionID" class="btn btn-xs btn-warning btn-replay" >{% trans "Replay" %}</a>';
|
||||
replayBtn = replayBtn.replace("sessionID", rowData.id);
|
||||
var downloadBtn = ' <a disabled data-session="sessionID" class="btn btn-xs btn-info btn-download" >{% trans "Download" %}</a>';
|
||||
downloadBtn = downloadBtn.replace("sessionID", rowData.id);
|
||||
if (rowData.can_replay) {
|
||||
replayBtn = replayBtn.replace("disabled", "");
|
||||
downloadBtn = downloadBtn.replace("disabled", "");
|
||||
}
|
||||
var termBtn = '<a class="btn btn-xs btn-danger btn-term" disabled value="sessionID" terminal="terminalID" >{% trans "Terminate" %}</a>';
|
||||
if ("{{ request.user.can_admin_current_org }}" === "True") {
|
||||
termBtn = termBtn.replace("disabled", "")
|
||||
.replace("sessionID", cellData)
|
||||
.replace("terminalID", rowData.terminal)
|
||||
}
|
||||
var joinBtn = ' <a disabled data-session="sessionID" class="btn btn-xs btn-info btn-join" >{% trans "Monitoring" %}</a>';
|
||||
joinBtn = joinBtn.replace("sessionID", rowData.id);
|
||||
if (rowData.can_join){
|
||||
joinBtn = joinBtn.replace("disabled", "")
|
||||
}
|
||||
if (rowData.is_finished) {
|
||||
btnGroup += replayBtn + downloadBtn
|
||||
} else {
|
||||
btnGroup += termBtn + joinBtn;
|
||||
}
|
||||
$(td).html(btnGroup);
|
||||
}},
|
||||
],
|
||||
ajax_url: sessionListUrl,
|
||||
columns: [
|
||||
{data: "id"}, {data: "id", orderable:false}, {data: "user"},
|
||||
{data: "asset"}, {data: "system_user"},
|
||||
{data: "remote_addr"}, {data: "protocol"}, {data: "login_from_display", orderable:false},
|
||||
{data: "command_amount", orderable:false}, {data: "date_start"},
|
||||
{data: "date_end", orderable:false}, {data: "id",orderable:false},
|
||||
],
|
||||
op_html: $('#actions').html(),
|
||||
fb_html: $("#daterange").html(),
|
||||
};
|
||||
table = jumpserver.initServerSideDataTable(options);
|
||||
return table
|
||||
}
|
||||
|
||||
function finishedSession(data) {
|
||||
var the_url = "{% url 'api-terminal:session-list' %}";
|
||||
var success_message = '{% trans "Finish session success" %}';
|
||||
var success = function() {
|
||||
location.reload();
|
||||
};
|
||||
requestApi({
|
||||
url: the_url,
|
||||
method: 'PATCH',
|
||||
body: JSON.stringify(data),
|
||||
success: success,
|
||||
success_message: success_message
|
||||
});
|
||||
}
|
||||
var table;
|
||||
$(document).ready(function() {
|
||||
table = initTable("#session_table").on('init', function () {
|
||||
var dateFromRef = $("#date_from");
|
||||
var dateToRef = $("#date_to");
|
||||
var options = {
|
||||
format: "yyyy-mm-dd",
|
||||
todayBtn: "linked",
|
||||
keyboardNavigation: false,
|
||||
forceParse: false,
|
||||
calendarWeeks: true,
|
||||
autoclose: true,
|
||||
language: getUserLang(),
|
||||
};
|
||||
dateFromRef.datepicker(options).on("changeDate", function () {
|
||||
if (!$(this).val()) {
|
||||
return
|
||||
}
|
||||
var value = $(this).val() + ' 0:0:0';
|
||||
var date = toSafeDateISOStr(value);
|
||||
var url = table.ajax.url();
|
||||
url = setUrlParam(url, "date_from", date);
|
||||
table.ajax.url(url);
|
||||
table.ajax.reload();
|
||||
});
|
||||
dateToRef.datepicker(options).on("changeDate", function () {
|
||||
if (!$(this).val()) {
|
||||
return
|
||||
}
|
||||
var value = $(this).val() + ' 23:59:59';
|
||||
var date = toSafeDateISOStr(value);
|
||||
var url = table.ajax.url();
|
||||
url = setUrlParam(url, "date_to", date);
|
||||
table.ajax.url(url);
|
||||
table.ajax.reload();
|
||||
});
|
||||
});
|
||||
|
||||
}).on('click', '.btn-term', function () {
|
||||
var $this = $(this);
|
||||
var session_id = $this.attr('value');
|
||||
var data = [
|
||||
session_id
|
||||
];
|
||||
terminateSession(data)
|
||||
}).on('click', '.btn-replay', function () {
|
||||
var sessionID = $(this).data("session");
|
||||
var replayUrl = "/luna/replay/" + sessionID;
|
||||
window.open(replayUrl, "_blank", "height=600, width=800, top=400, left=400, toolbar=no, menubar=no, scrollbars=no, location=no, status=no");
|
||||
})
|
||||
.on('click', '.btn-download', function () {
|
||||
var sessionID = $(this).data("session");
|
||||
var downloadUrl = "{% url 'terminal:session-replay-download' pk=DEFAULT_PK %}"
|
||||
.replace("{{ DEFAULT_PK }}", sessionID);
|
||||
var hasConfirm = getCookie('replayConfirm');
|
||||
if (!hasConfirm) {
|
||||
var help_text = "{% trans "Visit doc for replay play offline: " %}";
|
||||
help_text += "https://github.com/jumpserver/videoplayer";
|
||||
var r = confirm(help_text);
|
||||
setCookie("replayConfirm", "1")
|
||||
}
|
||||
window.open(downloadUrl)
|
||||
})
|
||||
.on('click', '.btn-join', function () {
|
||||
var sessionID = $(this).data("session");
|
||||
var joinUrl = "/luna/join/?shareroom=" + sessionID;
|
||||
window.open(joinUrl)
|
||||
})
|
||||
.on("click", '#session_table_filter input', function (e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
var offset1 = $('#session_table_filter input').offset();
|
||||
var x = offset1.left;
|
||||
var y = offset1.top;
|
||||
var offset = $(".search-help").parent().offset();
|
||||
x -= offset.left;
|
||||
y -= offset.top;
|
||||
x += 18;
|
||||
y += 80;
|
||||
$('.search-help').css({"top":y+"px", "left":x+"px", "position": "absolute"});
|
||||
$('.dropdown-menu.search-help').show();
|
||||
})
|
||||
.on('click', '.search-item', function (e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
var keyword = $("#session_table_filter input");
|
||||
var value = $(this).data('value');
|
||||
var old_value = keyword.val();
|
||||
var new_value = old_value + ' ' + value + ':';
|
||||
keyword.val(new_value.trim());
|
||||
$('.dropdown-menu.search-help').hide();
|
||||
keyword.focus()
|
||||
})
|
||||
.on('click', 'body', function (e) {
|
||||
$('.dropdown-menu.search-help').hide()
|
||||
})
|
||||
.on('click', '#btn_bulk_update', function () {
|
||||
var action = $('#slct_bulk_update').val();
|
||||
var idList = table.selected;
|
||||
|
||||
if (idList.length === 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
function doTerminate() {
|
||||
terminateSession(idList)
|
||||
}
|
||||
|
||||
function doFinishSession() {
|
||||
var data = [];
|
||||
$.each(idList, function (i, v) {
|
||||
data.push({
|
||||
"id": v,
|
||||
"is_finished": true
|
||||
})
|
||||
});
|
||||
finishedSession(data)
|
||||
}
|
||||
switch(action) {
|
||||
case 'terminate':
|
||||
doTerminate();
|
||||
break;
|
||||
case "finished":
|
||||
doFinishSession();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
@@ -1,77 +0,0 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load static %}
|
||||
{% load i18n %}
|
||||
|
||||
{% 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"><i class="fa fa-laptop"></i> {% trans 'Terminal detail' %} </a>
|
||||
</li>
|
||||
<li class="pull-right">
|
||||
<a class="btn btn-outline btn-default" href="{% url 'terminal:terminal-update' pk=terminal.id %}"><i class="fa fa-edit"></i>{% trans 'Update' %}</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="tab-content">
|
||||
<div class="col-sm-7" style="padding-left: 0">
|
||||
<div class="ibox float-e-margins">
|
||||
<div class="ibox-title">
|
||||
<span class="label"><b>{{ terminal.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 class="table">
|
||||
<tbody>
|
||||
<tr class="no-borders-tr">
|
||||
<td width="20%">{% trans 'Name' %}:</td>
|
||||
<td><b>{{ terminal.name }}</b></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{% trans 'Remote addr' %}:</td>
|
||||
<td><b>{{ terminal.remote_addr }}</b></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{% trans 'SSH port' %}:</td>
|
||||
<td><b>{{ terminal.ssh_port }}</b></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{% trans 'Http port' %}:</td>
|
||||
<td><b>{{ terminal.http_port }}</b></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{% trans 'Date created' %}:</td>
|
||||
<td><b>{{ terminal.date_created }}</b></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{% trans 'Comment' %}:</td>
|
||||
<td><b>{{ asset.comment }}</b></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
@@ -1,144 +0,0 @@
|
||||
{% extends '_base_list.html' %}
|
||||
{% load i18n static %}
|
||||
{% block custom_head_css_js %}
|
||||
{{ block.super }}
|
||||
<style>
|
||||
div.dataTables_wrapper div.dataTables_filter,
|
||||
.dataTables_length {
|
||||
float: right !important;
|
||||
}
|
||||
div.dataTables_wrapper div.dataTables_filter {
|
||||
margin-left: 15px;
|
||||
}
|
||||
|
||||
#modal .modal-body { max-height: 200px; }
|
||||
</style>
|
||||
{% endblock %}
|
||||
|
||||
{% block table_search %}{% endblock %}
|
||||
|
||||
{% block table_container %}
|
||||
<div class="uc pull-left m-r-5"><a href="{% url "terminal:replay-storage-list" %}" class="btn btn-sm btn-primary"> {% trans "Storage configuration" %} </a></div>
|
||||
<table class="table table-striped table-bordered table-hover " id="terminal_list_table" >
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="text-center">
|
||||
<div class="checkbox checkbox-default">
|
||||
<input type="checkbox" class="ipt_check_all">
|
||||
</div>
|
||||
</th>
|
||||
<th class="text-center">{% trans 'Name' %}</th>
|
||||
<th class="text-center">{% trans 'Addr' %}</th>
|
||||
{# <th class="text-center">{% trans 'SSH port' %}</th>#}
|
||||
{# <th class="text-center">{% trans 'Http port' %}</th>#}
|
||||
<th class="text-center">{% trans 'Session' %}</th>
|
||||
<th class="text-center">{% trans 'Active' %}</th>
|
||||
<th class="text-center">{% trans 'Alive' %}</th>
|
||||
<th class="text-center">{% trans 'Action' %}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
</tbody>
|
||||
</table>
|
||||
{% include 'terminal/terminal_modal_accept.html' %}
|
||||
{% endblock %}
|
||||
{% block custom_foot_js %}
|
||||
<script src="{% static 'js/jquery.form.min.js' %}"></script>
|
||||
<script>
|
||||
function initTable() {
|
||||
var options = {
|
||||
ele: $('#terminal_list_table'),
|
||||
buttons: [],
|
||||
columnDefs: [
|
||||
{targets: 1, createdCell: function (td, cellData, rowData) {
|
||||
cellData = htmlEscape(cellData);
|
||||
var detail_btn = '<a href="{% url "terminal:terminal-detail" pk=DEFAULT_PK %}">' + cellData + '</a>';
|
||||
$(td).html(detail_btn.replace('{{ DEFAULT_PK }}', rowData.id));
|
||||
}},
|
||||
{targets: 4, createdCell: function (td, cellData) {
|
||||
if (!cellData) {
|
||||
$(td).html('<i class="fa fa-times text-danger"></i>')
|
||||
} else {
|
||||
$(td).html('<i class="fa fa-check text-navy"></i>')
|
||||
}
|
||||
}},
|
||||
{targets: 5, createdCell: function (td, cellData) {
|
||||
if (!cellData) {
|
||||
$(td).html('<i class="fa fa-circle text-danger"></i>')
|
||||
} else {
|
||||
$(td).html('<i class="fa fa-circle text-navy"></i>')
|
||||
}
|
||||
}},
|
||||
{targets: 6, createdCell: function (td, cellData, rowData) {
|
||||
var name = htmlEscape(rowData.name);
|
||||
var update_btn = '<a href="{% url "terminal:terminal-update" pk=DEFAULT_PK %}" class="btn btn-xs btn-info">{% trans "Update" %}</a>'
|
||||
.replace('{{ DEFAULT_PK }}', cellData);
|
||||
var delete_btn = '<a class="btn btn-xs btn-danger m-l-xs btn-del" data-id="{{ DEFAULT_PK }}" data-name="99991938">{% trans "Delete" %}</a>'
|
||||
.replace('{{ DEFAULT_PK }}', cellData)
|
||||
.replace('99991938', name);
|
||||
var accept_btn = '<a class="btn btn-xs btn-primary btn-accept" data-id="{{ DEFAULT_PK }}">{% trans "Accept" %}</a> '
|
||||
.replace('{{ DEFAULT_PK }}', cellData);
|
||||
var reject_btn = '<a class="btn btn-xs btn-danger m-l-xs btn-del" data-id="{{ DEFAULT_PK }}" data-name="99991938">{% trans "Reject" %}</a>'
|
||||
.replace('{{ DEFAULT_PK }}', cellData)
|
||||
.replace('99991938', name);
|
||||
if (rowData.is_accepted) {
|
||||
$(td).html(update_btn + delete_btn);
|
||||
} else {
|
||||
{% if user.is_superuser %}
|
||||
$(td).html(accept_btn + reject_btn);
|
||||
{% endif %}
|
||||
}
|
||||
}}
|
||||
],
|
||||
ajax_url: '{% url "api-terminal:terminal-list" %}',
|
||||
columns: [{data: function(){return ""}}, {data: "name" }, {data: "remote_addr" },
|
||||
{data: "session_online", orderable: false}, {data: "is_active", orderable: false}, {data: 'is_alive'}, {data: "id", orderable: false}],
|
||||
op_html: $('#actions').html()
|
||||
};
|
||||
jumpserver.initDataTable(options);
|
||||
}
|
||||
$(document).ready(function(){
|
||||
initTable();
|
||||
|
||||
}).on('click', '#btn-confirm',function () {
|
||||
var $form = $('#form_terminal_accept');
|
||||
function success(data, textStatus, jqXHR) {
|
||||
if (data.success === true) {
|
||||
window.location.reload()
|
||||
} else {
|
||||
$('#modal-error').html(data.msg).css('display', 'block');
|
||||
}
|
||||
}
|
||||
$form.ajaxSubmit({success: success});
|
||||
}).on('click', '.btn-del', function(){
|
||||
var $this = $(this);
|
||||
var id = $this.data('id');
|
||||
var name = $(this).data('name');
|
||||
var the_url = '{% url "api-terminal:terminal-detail" pk=DEFAULT_PK %}'.replace('{{ DEFAULT_PK }}', id);
|
||||
objectDelete($this, name, the_url)
|
||||
|
||||
}).on('click', '.btn-accept', function () {
|
||||
var $this = $(this);
|
||||
var terminal_id = $this.data('id');
|
||||
var the_url = "{% url 'api-terminal:terminal-detail' pk=DEFAULT_PK %}".replace('{{ DEFAULT_PK }}', terminal_id);
|
||||
var post_url = "{% url 'terminal:terminal-accept' pk=DEFAULT_PK %}".replace('{{ DEFAULT_PK }}', terminal_id);
|
||||
$.ajax({
|
||||
url: the_url,
|
||||
method: 'GET',
|
||||
success: function (data) {
|
||||
$('#id_name').val(data.name);
|
||||
$('#id_remote_addr').val(data.remote_addr);
|
||||
$('#id_url').val(data.url);
|
||||
$('#id_comment').val(data.comment);
|
||||
$('#form_terminal_accept').attr('action', post_url)
|
||||
}
|
||||
});
|
||||
$('#modal_terminal_accept').modal({
|
||||
show: true
|
||||
});
|
||||
}).on('click', '.btn-connect', function () {
|
||||
var $this = $(this);
|
||||
var id = $this.data('id');
|
||||
})
|
||||
</script>
|
||||
{% endblock %}
|
@@ -1,21 +0,0 @@
|
||||
{% extends '_modal.html' %}
|
||||
{% load i18n %}
|
||||
{% block modal_id %}modal_terminal_accept{% endblock %}
|
||||
{% block modal_class %}modal-lg{% endblock %}
|
||||
{% block modal_title%}{% trans "Accept terminal registration" %}{% endblock %}
|
||||
{% block modal_body %}
|
||||
{% load bootstrap3 %}
|
||||
<form action="" method="post" class="form-horizontal" id="form_terminal_accept" enctype="multipart/form-data">
|
||||
{% csrf_token %}
|
||||
<p class="alert alert-danger" id="modal-error" style="display: none"></p>
|
||||
{% bootstrap_field form.name layout="horizontal" %}
|
||||
{% bootstrap_field form.remote_addr layout="horizontal" %}
|
||||
{# {% bootstrap_field form.ssh_port layout="horizontal" %}#}
|
||||
{# {% bootstrap_field form.http_port layout="horizontal" %}#}
|
||||
{% bootstrap_field form.command_storage layout="horizontal" %}
|
||||
{% bootstrap_field form.replay_storage layout="horizontal" %}
|
||||
{% bootstrap_field form.comment layout="horizontal" %}
|
||||
</form>
|
||||
|
||||
{% endblock %}
|
||||
{% block modal_confirm_id %}btn-confirm{% endblock %}
|
@@ -1,5 +0,0 @@
|
||||
<form action="" method="post">
|
||||
{% csrf_token %}
|
||||
{{ form }}
|
||||
<input type="submit" value="Submit">
|
||||
</form>
|
@@ -1,70 +0,0 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load i18n %}
|
||||
{% load static %}
|
||||
{% load bootstrap3 %}
|
||||
{% block custom_head_css_js %}
|
||||
<link href="{% static "css/plugins/datepicker/datepicker3.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="ibox-title">
|
||||
<h5>{{ action }}</h5>
|
||||
<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>
|
||||
<a class="close-link">
|
||||
<i class="fa fa-times"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ibox-content">
|
||||
<form method="post" class="form-horizontal" action="" enctype="multipart/form-data">
|
||||
{% csrf_token %}
|
||||
<h3>{% trans 'Info' %}</h3>
|
||||
{% bootstrap_field form.name layout="horizontal" %}
|
||||
{% bootstrap_field form.remote_addr layout="horizontal" %}
|
||||
{% bootstrap_field form.command_storage layout="horizontal" %}
|
||||
{% bootstrap_field form.replay_storage layout="horizontal" %}
|
||||
|
||||
<div class="hr-line-dashed"></div>
|
||||
<h3>{% trans 'Other' %}</h3>
|
||||
{% bootstrap_field form.comment layout="horizontal" %}
|
||||
<div class="hr-line-dashed"></div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-4 col-sm-offset-2">
|
||||
<button class="btn btn-white" type="reset">{% trans 'Reset' %}</button>
|
||||
<button id="submit_button" class="btn btn-primary" type="submit">{% trans 'Submit' %}</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
{% block custom_foot_js %}
|
||||
<script src="{% static 'js/plugins/datepicker/bootstrap-datepicker.js' %}"></script>
|
||||
<script>
|
||||
$(document).ready(function () {
|
||||
$('.select2').select2();
|
||||
}).on('submit', 'form', function (e) {
|
||||
e.preventDefault();
|
||||
var form = $('form');
|
||||
formSubmit({
|
||||
'url': '{% url 'api-terminal-v2:terminal-detail' pk=DEFAULT_PK %}'.replace('{{ DEFAULT_PK }}', '{{ object.id }}'),
|
||||
'form': form,
|
||||
'method': 'PUT',
|
||||
'redirect_to': '{% url "terminal:terminal-list" %}'
|
||||
});
|
||||
})
|
||||
</script>
|
||||
{% endblock %}
|
@@ -1,2 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
@@ -1,14 +0,0 @@
|
||||
# ~*~ coding: utf-8 ~*~
|
||||
|
||||
from django import template
|
||||
|
||||
from ..backends import get_multi_command_storage
|
||||
|
||||
register = template.Library()
|
||||
|
||||
|
||||
@register.filter
|
||||
def get_session_command_amount(session_id):
|
||||
command_store = get_multi_command_storage()
|
||||
return command_store.count(session=session_id)
|
||||
|
@@ -1,41 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
|
||||
from django.urls import path
|
||||
|
||||
from .. import views
|
||||
|
||||
app_name = 'terminal'
|
||||
|
||||
urlpatterns = [
|
||||
# Terminal view
|
||||
path('terminal/', views.TerminalListView.as_view(), name='terminal-list'),
|
||||
path('terminal/<uuid:pk>/', views.TerminalDetailView.as_view(), name='terminal-detail'),
|
||||
path('terminal/<uuid:pk>/connect/', views.TerminalConnectView.as_view(), name='terminal-connect'),
|
||||
path('terminal/<uuid:pk>/update/', views.TerminalUpdateView.as_view(), name='terminal-update'),
|
||||
path('<uuid:pk>/accept/', views.TerminalAcceptView.as_view(), name='terminal-accept'),
|
||||
path('web-terminal/', views.WebTerminalView.as_view(), name='web-terminal'),
|
||||
path('web-sftp/', views.WebSFTPView.as_view(), name='web-sftp'),
|
||||
|
||||
# Session view
|
||||
path('session-online/', views.SessionOnlineListView.as_view(), name='session-online-list'),
|
||||
path('session-offline/', views.SessionOfflineListView.as_view(), name='session-offline-list'),
|
||||
path('session/<uuid:pk>/', views.SessionDetailView.as_view(), name='session-detail'),
|
||||
path('session/<uuid:pk>/commands/', views.SessionCommandsView.as_view(), name='session-commands'),
|
||||
path('session/<uuid:pk>/replay/download/', views.SessionReplayDownloadView.as_view(), name='session-replay-download'),
|
||||
|
||||
# Command view
|
||||
path('command/', views.CommandListView.as_view(), name='command-list'),
|
||||
|
||||
# replay-storage
|
||||
path('terminal/replay-storage/', views.ReplayStorageListView.as_view(), name='replay-storage-list'),
|
||||
path('terminal/replay-storage/create/', views.ReplayStorageCreateView.as_view(), name='replay-storage-create'),
|
||||
path('terminal/replay-storage/<uuid:pk>/update/', views.ReplayStorageUpdateView.as_view(), name='replay-storage-update'),
|
||||
|
||||
# command-storage
|
||||
path('terminal/command-storage/', views.CommandStorageListView.as_view(), name='command-storage-list'),
|
||||
path('terminal/command-storage/create/', views.CommandStorageCreateView.as_view(), name='command-storage-create'),
|
||||
path('terminal/command-storage/<uuid:pk>/update/', views.CommandStorageUpdateView.as_view(), name='command-storage-update'),
|
||||
|
||||
]
|
@@ -1,9 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
from .terminal import *
|
||||
from .session import *
|
||||
from .command import *
|
||||
from .storage import *
|
||||
|
||||
# from .replay_storage import *
|
||||
# from .command_storage import *
|
@@ -1,28 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
|
||||
from django.views.generic import TemplateView
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.utils import timezone
|
||||
|
||||
from common.permissions import PermissionsMixin, IsOrgAdmin, IsOrgAuditor
|
||||
|
||||
__all__ = ['CommandListView']
|
||||
|
||||
|
||||
class CommandListView(PermissionsMixin, TemplateView):
|
||||
template_name = "terminal/command_list.html"
|
||||
permission_classes = [IsOrgAdmin | IsOrgAuditor]
|
||||
default_days_ago = 5
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
now = timezone.now()
|
||||
context = {
|
||||
'app': _('Sessions'),
|
||||
'action': _('Command list'),
|
||||
'date_from': now - timezone.timedelta(days=self.default_days_ago),
|
||||
'date_to': now,
|
||||
}
|
||||
kwargs.update(context)
|
||||
return super().get_context_data(**kwargs)
|
||||
|
@@ -1,142 +0,0 @@
|
||||
# -*- 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
|
@@ -1,181 +0,0 @@
|
||||
# coding: utf-8
|
||||
#
|
||||
|
||||
from django.http import Http404
|
||||
from django.views.generic import TemplateView
|
||||
from django.views.generic.edit import CreateView, UpdateView
|
||||
from django.utils.translation import ugettext as _
|
||||
|
||||
from common.permissions import PermissionsMixin, IsSuperUser
|
||||
from terminal.models import ReplayStorage, CommandStorage
|
||||
from .. import forms, const
|
||||
|
||||
|
||||
__all__ = [
|
||||
'ReplayStorageListView', 'ReplayStorageCreateView',
|
||||
'ReplayStorageUpdateView', 'CommandStorageListView',
|
||||
'CommandStorageCreateView', 'CommandStorageUpdateView'
|
||||
]
|
||||
|
||||
|
||||
class ReplayStorageListView(PermissionsMixin, TemplateView):
|
||||
template_name = 'terminal/replay_storage_list.html'
|
||||
permission_classes = [IsSuperUser]
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = {
|
||||
'app': _('Terminal'),
|
||||
'action': _('Replay storage list'),
|
||||
'is_replay': True,
|
||||
'type_choices': const.REPLAY_STORAGE_TYPE_CHOICES_EXTENDS,
|
||||
}
|
||||
kwargs.update(context)
|
||||
return super().get_context_data(**kwargs)
|
||||
|
||||
|
||||
class CommandStorageListView(PermissionsMixin, TemplateView):
|
||||
template_name = 'terminal/command_storage_list.html'
|
||||
permission_classes = [IsSuperUser]
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = {
|
||||
'app': _('Terminal'),
|
||||
'action': _('Command storage list'),
|
||||
'type_choices': const.COMMAND_STORAGE_TYPE_CHOICES_EXTENDS,
|
||||
'is_command': True,
|
||||
}
|
||||
kwargs.update(context)
|
||||
return super().get_context_data(**kwargs)
|
||||
|
||||
|
||||
class BaseStorageCreateUpdateViewMixin:
|
||||
permission_classes = [IsSuperUser]
|
||||
default_type = None
|
||||
form_class = None
|
||||
form_class_choices = {}
|
||||
|
||||
def get_initial(self):
|
||||
return {'type': self.get_type()}
|
||||
|
||||
def get_type(self):
|
||||
return self.default_type
|
||||
|
||||
def get_form_class(self):
|
||||
tp = self.get_type()
|
||||
form_class = self.form_class_choices.get(tp)
|
||||
if not form_class:
|
||||
raise Http404()
|
||||
return form_class
|
||||
|
||||
|
||||
class ReplayStorageCreateUpdateViewMixin(BaseStorageCreateUpdateViewMixin):
|
||||
model = ReplayStorage
|
||||
default_type = const.REPLAY_STORAGE_TYPE_S3
|
||||
form_class = forms.ReplayStorageS3Form
|
||||
form_class_choices = {
|
||||
const.REPLAY_STORAGE_TYPE_S3: forms.ReplayStorageS3Form,
|
||||
const.REPLAY_STORAGE_TYPE_CEPH: forms.ReplayStorageCephForm,
|
||||
const.REPLAY_STORAGE_TYPE_SWIFT: forms.ReplayStorageSwiftForm,
|
||||
const.REPLAY_STORAGE_TYPE_OSS: forms.ReplayStorageOSSForm,
|
||||
const.REPLAY_STORAGE_TYPE_AZURE: forms.ReplayStorageAzureForm
|
||||
}
|
||||
|
||||
|
||||
class ReplayStorageCreateView(ReplayStorageCreateUpdateViewMixin,
|
||||
PermissionsMixin, CreateView):
|
||||
template_name = 'terminal/replay_storage_create_update.html'
|
||||
|
||||
def get_type(self):
|
||||
tp = self.request.GET.get("type")
|
||||
if tp:
|
||||
return tp.lower()
|
||||
return super().get_type()
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = {
|
||||
'app': _('Terminal'),
|
||||
'action': _('Create replay storage'),
|
||||
'api_action': 'create'
|
||||
}
|
||||
kwargs.update(context)
|
||||
return super().get_context_data(**kwargs)
|
||||
|
||||
|
||||
class ReplayStorageUpdateView(ReplayStorageCreateUpdateViewMixin,
|
||||
PermissionsMixin, UpdateView):
|
||||
template_name = 'terminal/replay_storage_create_update.html'
|
||||
|
||||
def get_initial(self):
|
||||
initial_data = super().get_initial()
|
||||
for k, v in self.object.meta.items():
|
||||
_k = "{}_{}".format(self.object.type, k.lower())
|
||||
initial_data[_k] = v
|
||||
return initial_data
|
||||
|
||||
def get_type(self):
|
||||
return self.object.type
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = {
|
||||
'app': _('Terminal'),
|
||||
'action': _('Update replay storage'),
|
||||
'api_action': 'update'
|
||||
}
|
||||
kwargs.update(context)
|
||||
return super().get_context_data(**kwargs)
|
||||
|
||||
|
||||
class CommandStorageCreateUpdateViewMixin(BaseStorageCreateUpdateViewMixin):
|
||||
model = CommandStorage
|
||||
default_type = const.COMMAND_STORAGE_TYPE_ES
|
||||
form_class = forms.CommandStorageTypeESForm
|
||||
form_class_choices = {
|
||||
const.COMMAND_STORAGE_TYPE_ES: forms.CommandStorageTypeESForm
|
||||
}
|
||||
|
||||
|
||||
class CommandStorageCreateView(CommandStorageCreateUpdateViewMixin,
|
||||
PermissionsMixin, CreateView):
|
||||
template_name = 'terminal/command_storage_create_update.html'
|
||||
|
||||
def get_type(self):
|
||||
tp = self.request.GET.get("type")
|
||||
if tp:
|
||||
return tp.lower()
|
||||
return super().get_type()
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = {
|
||||
'app': _('Terminal'),
|
||||
'action': _('Create command storage'),
|
||||
'api_action': 'create'
|
||||
}
|
||||
kwargs.update(context)
|
||||
return super().get_context_data(**kwargs)
|
||||
|
||||
|
||||
class CommandStorageUpdateView(CommandStorageCreateUpdateViewMixin,
|
||||
PermissionsMixin, UpdateView):
|
||||
template_name = 'terminal/command_storage_create_update.html'
|
||||
|
||||
def get_initial(self):
|
||||
initial_data = super().get_initial()
|
||||
for k, v in self.object.meta.items():
|
||||
_k = "{}_{}".format(self.object.type, k.lower())
|
||||
if k == 'HOSTS':
|
||||
v = ','.join(v)
|
||||
initial_data[_k] = v
|
||||
return initial_data
|
||||
|
||||
def get_type(self):
|
||||
return self.object.type
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = {
|
||||
'app': _('Terminal'),
|
||||
'action': _('Update command storage'),
|
||||
'api_action': 'update'
|
||||
}
|
||||
kwargs.update(context)
|
||||
return super().get_context_data(**kwargs)
|
||||
|
@@ -1,138 +0,0 @@
|
||||
# ~*~ coding: utf-8 ~*~
|
||||
#
|
||||
import time
|
||||
from django.views.generic import ListView, UpdateView, DeleteView, \
|
||||
DetailView, View
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.shortcuts import redirect
|
||||
from django.urls import reverse_lazy, reverse
|
||||
|
||||
from common.mixins import JSONResponseMixin
|
||||
from ..models import Terminal
|
||||
from ..forms import TerminalForm
|
||||
from common.permissions import PermissionsMixin, IsSuperUser
|
||||
|
||||
|
||||
__all__ = [
|
||||
"TerminalListView", "TerminalUpdateView", "TerminalDetailView",
|
||||
"TerminalDeleteView", "TerminalConnectView", "TerminalAcceptView",
|
||||
"WebTerminalView", 'WebSFTPView',
|
||||
]
|
||||
|
||||
|
||||
class TerminalListView(PermissionsMixin, ListView):
|
||||
model = Terminal
|
||||
template_name = 'terminal/terminal_list.html'
|
||||
form_class = TerminalForm
|
||||
permission_classes = [IsSuperUser]
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(TerminalListView, self).get_context_data(**kwargs)
|
||||
context.update({
|
||||
'app': _('Sessions'),
|
||||
'action': _('Terminal list'),
|
||||
'form': self.form_class()
|
||||
})
|
||||
return context
|
||||
|
||||
|
||||
class TerminalUpdateView(PermissionsMixin, UpdateView):
|
||||
model = Terminal
|
||||
form_class = TerminalForm
|
||||
template_name = 'terminal/terminal_update.html'
|
||||
success_url = reverse_lazy('terminal:terminal-list')
|
||||
permission_classes = [IsSuperUser]
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(TerminalUpdateView, self).get_context_data(**kwargs)
|
||||
context.update({'app': _('Sessions'), 'action': _('Update terminal')})
|
||||
return context
|
||||
|
||||
|
||||
class TerminalDetailView(PermissionsMixin, DetailView):
|
||||
model = Terminal
|
||||
template_name = 'terminal/terminal_detail.html'
|
||||
context_object_name = 'terminal'
|
||||
permission_classes = [IsSuperUser]
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(TerminalDetailView, self).get_context_data(**kwargs)
|
||||
context.update({
|
||||
'app': _('Sessions'),
|
||||
'action': _('Terminal detail')
|
||||
})
|
||||
return context
|
||||
|
||||
|
||||
class TerminalDeleteView(PermissionsMixin, DeleteView):
|
||||
model = Terminal
|
||||
template_name = 'delete_confirm.html'
|
||||
success_url = reverse_lazy('terminal:terminal-list')
|
||||
permission_classes = [IsSuperUser]
|
||||
|
||||
|
||||
class TerminalAcceptView(PermissionsMixin, JSONResponseMixin, UpdateView):
|
||||
model = Terminal
|
||||
form_class = TerminalForm
|
||||
template_name = 'terminal/terminal_modal_accept.html'
|
||||
permission_classes = [IsSuperUser]
|
||||
|
||||
def form_valid(self, form):
|
||||
terminal = form.save()
|
||||
terminal.create_app_user()
|
||||
terminal.is_accepted = True
|
||||
terminal.is_active = True
|
||||
terminal.save()
|
||||
data = {
|
||||
'success': True,
|
||||
'msg': 'success'
|
||||
}
|
||||
return self.render_json_response(data)
|
||||
|
||||
def form_invalid(self, form):
|
||||
data = {
|
||||
'success': False,
|
||||
'msg': str(form.errors),
|
||||
}
|
||||
return self.render_json_response(data)
|
||||
|
||||
|
||||
class TerminalConnectView(PermissionsMixin, DetailView):
|
||||
"""
|
||||
Abandon
|
||||
"""
|
||||
template_name = 'flash_message_standalone.html'
|
||||
model = Terminal
|
||||
permission_classes = [IsSuperUser]
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
if self.object.type == 'Web':
|
||||
context = {
|
||||
'title': _('Redirect to web terminal'),
|
||||
'messages': _('Redirect to web terminal') + self.object.url,
|
||||
'auto_redirect': True,
|
||||
'interval': 3,
|
||||
'redirect_url': self.object.url
|
||||
}
|
||||
else:
|
||||
context = {
|
||||
'title': _('Connect ssh terminal'),
|
||||
'messages': _('You should use your ssh client tools '
|
||||
'connect terminal: {} <br /> <br />'
|
||||
'{}'.format(self.object.name, self.object.url)),
|
||||
'redirect_url': reverse('terminal:terminal-list')
|
||||
}
|
||||
|
||||
kwargs.update(context)
|
||||
return super(TerminalConnectView, self).get_context_data(**kwargs)
|
||||
|
||||
|
||||
class WebTerminalView(View):
|
||||
def get(self, request, *args, **kwargs):
|
||||
redirect_url = '/luna/?_={}&'.format(int(time.time()))
|
||||
return redirect(redirect_url + request.GET.urlencode())
|
||||
|
||||
|
||||
class WebSFTPView(View):
|
||||
def get(self, request, *args, **kwargs):
|
||||
return redirect('/koko/elfinder/sftp/?' + request.GET.urlencode())
|
Reference in New Issue
Block a user