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

* [Update] 待续(小白)

* [Update] 修改asset user

* [Update] 计划再次更改

* [Update] 修改asset user

* [Update] 暂存与喜爱

* [Update] Add id in

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

* [Update] 修改asset user api

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

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

* [Update] dynamic user only allow 1

* [Update] 修改asset user task

* [Update] 修改node admin user task api

* [Update] remove file header license

* [Update] 添加sftp root

* [Update] 暂存

* [Update] 暂存

* [Update] 修改翻译

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

* [Update] 基本完成CAS调研

* [Update] 支持cas server

* [Update] 支持cas server

* [Update] 添加requirements

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

* [Update] 添加huaweiyun翻译

* [Update] 增加下载session 录像

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

* [Update] 暂存一下

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

* [Bugfix] 修改system user info

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

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

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

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

* Fix broken dependencies

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

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

* [Update] Remove log

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

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

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

* [Update] 修改placeholder

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

* [Update] 修改tasks

* [Update] tree service update

* [Update] 暂存

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

* [Update] Dashbaord perf

* [update] Add huawei cloud sdk requirements

* [Updte] 优化dashboard页面

* [Update] system user auth info 添加id

* [Update] 修改系统用户serializer

* [Update] 优化api

* [Update] LDAP Test Util (#3720)

* [Update] LDAPTestUtil 1

* [Update] LDAPTestUtil 2

* [Update] LDAPTestUtil 3

* [Update] LDAPTestUtil 4

* [Update] LDAPTestUtil 5

* [Update] LDAPTestUtil 6

* [Update] LDAPTestUtil 7

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

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

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

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

* [Update] 批量命令添加org_id

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

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

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

* [Update] 拆分profile view

* [Update] 修改一个翻译

* [Update] 修改aysnc api框架

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

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

* [Update] 更改登陆otp页面

* [Update] 修改command 存储redis_level

* [Update] 修改翻译

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

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

* [Update] 优化cloud task

* [Update] 统一period task

* [Update] 统一period form serializer字段

* [Update] 修改period task

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

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

* [Update] 修改翻译

* [Update] 测试可连接性

* 1.5.7 bai (#3764)

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

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

* [Bugfix] 修复backends问题

* [Update] 修改marksafe依赖版本

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

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

* [Update] 更新依赖boto3=1.12.14

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

1501 lines
47 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//jumpserver 自定义js 2015-01-29
//此函数用于checkbox的全选和反选
var checked = false;
function check_all(form) {
var checkboxes = document.getElementById(form);
if (checked === false) {
checked = true;
} else {
checked = false;
}
for (var i = 0; i < checkboxes.elements.length; i++) {
if (checkboxes.elements[i].type == "checkbox") {
checkboxes.elements[i].checked = checked;
}
}
}
function checkAll(id, name) {
var checklist = document.getElementsByName(name);
if (document.getElementById(id).checked) {
for (var i = 0; i < checklist.length; i++) {
checklist[i].checked = 1;
}
} else {
for (var j = 0; j < checklist.length; j++) {
checklist[j].checked = 0;
}
}
}
//提取指定行的数据JSON格式
function GetRowData(row) {
var rowData = {};
for (var j = 0; j < row.cells.length; j++) {
name = row.parentNode.rows[0].cells[j].getAttribute("Name");
if (name) {
var value = row.cells[j].getAttribute("Value");
if (!value) {
value = row.cells[j].innerHTML;
}
rowData[name] = value;
}
}
return rowData;
}
//此函数用于在多选提交时至少要选择一行
function GetTableDataBox() {
var tabProduct = document.getElementById("editable");
var tableData = [];
var returnData = [];
var checkboxes = document.getElementById("contents_form");
var id_list = [];
len = checkboxes.elements.length;
for (var i = 0; i < len; i++) {
if (checkboxes.elements[i].type == "checkbox" && checkboxes.elements[i].checked === true && checkboxes.elements[i].value != "checkall") {
id_list.push(i);
}
}
for (i in id_list) {
tableData.push(GetRowData(tabProduct.rows[id_list[i]]));
}
if (id_list.length === 0) {
alert('请至少选择一行!');
}
returnData.push(tableData);
returnData.push(id_list.length);
return returnData;
}
function move(from, to, from_o, to_o) {
$("#" + from + " option").each(function () {
if ($(this).prop("selected") === true) {
$("#" + to).append(this);
if (typeof from_o !== 'undefined') {
$("#" + to_o).append($("#" + from_o + " option[value='" + this.value + "']"));
}
}
});
}
function move_left(from, to, from_o, to_o) {
$("#" + from + " option").each(function () {
if ($(this).prop("selected") === true) {
$("#" + to).append(this);
if (typeof from_o !== 'undefined') {
$("#" + to_o).append($("#" + from_o + " option[value='" + this.value + "']"));
}
}
$(this).attr("selected", 'true');
});
}
function selectAll() {
// Select all check box
$('option').each(function () {
$(this).attr('selected', true);
});
}
function getCookie(name) {
var cookieValue = null;
if (document.cookie && document.cookie !== '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = jQuery.trim(cookies[i]);
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) === (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
// break;
}
}
}
return cookieValue;
}
function csrfSafeMethod(method) {
// these HTTP methods do not require CSRF protection
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
function setAjaxCSRFToken() {
var csrftoken = getCookie('csrftoken');
var sessionid = getCookie('sessionid');
$.ajaxSetup({
beforeSend: function (xhr, settings) {
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
}
});
}
function activeNav(prefix) {
var path = document.location.pathname;
if (prefix) {
path = path.replace(prefix, '');
console.log(path);
}
var urlArray = path.split("/");
var app = urlArray[1];
var resource = urlArray[2];
if (app === '') {
$('#index').addClass('active');
} else if (app === 'xpack' && resource === 'cloud') {
var item = urlArray[3];
$("#" + app).addClass('active');
$('#' + app + ' #' + resource).addClass('active');
$('#' + app + ' #' + resource + ' #' + item + ' a').css('color', '#ffffff');
} else if (app === 'settings') {
$("#" + app).addClass('active');
} else {
$("#" + app).addClass('active');
$('#' + app + ' #' + resource).addClass('active');
$('#' + app + ' #' + resource.replace(/-/g, '_')).addClass('active');
}
}
function formSubmit(props) {
/*
{
"form": $("form"),
"data": {},
"url": "",
"method": "POST",
"redirect_to": "",
"success": function(data, textStatue, jqXHR){},
"error": function(jqXHR, textStatus, errorThrown) {},
"message": "",
}
*/
props = props || {};
var data = props.data || props.form.serializeObject();
var redirectTo = props.redirect_to || props.redirectTo;
$.ajax({
url: props.url,
type: props.method || 'POST',
data: JSON.stringify(data),
contentType: props.content_type || "application/json; charset=utf-8",
dataType: props.data_type || "json"
}).done(function (data, textState, jqXHR) {
if (redirectTo) {
location.href = redirectTo;
} else if (typeof props.success === 'function') {
return props.success(data, textState, jqXHR);
}
}).fail(function (jqXHR, textStatus, errorThrown) {
if (typeof props.error === 'function') {
return props.error(jqXHR, textStatus, errorThrown)
}
if (!props.form) {
alert(jqXHR.responseText);
return
}
if (jqXHR.status === 400) {
var errors = jqXHR.responseJSON;
var noneFieldErrorRef = props.form.children('.alert-danger');
if (noneFieldErrorRef.length !== 1) {
props.form.prepend('<div class="alert alert-danger has-error" style="display: none"></div>');
noneFieldErrorRef = props.form.children('.alert-danger');
}
var noneFieldErrorMsg = "";
noneFieldErrorRef.css("display", "none");
noneFieldErrorRef.html("");
props.form.find(".help-block.error").html("");
props.form.find(".form-group.has-error").removeClass("has-error");
if (typeof errors !== "object") {
noneFieldErrorMsg = errors;
if (noneFieldErrorRef.length === 1) {
noneFieldErrorRef.css('display', 'block');
noneFieldErrorRef.html(noneFieldErrorMsg);
}
return
}
$.each(errors, function (k, v) {
var fieldRef = props.form.find('[name="' + k + '"]');
var formGroupRef = fieldRef.parents('.form-group');
var parentRef = fieldRef.parent();
var helpBlockRef = parentRef.children('.help-block.error');
if (helpBlockRef.length === 0) {
parentRef.append('<div class="help-block error"></div>');
helpBlockRef = parentRef.children('.help-block.error');
}
if (fieldRef.length === 1 && formGroupRef.length === 1) {
formGroupRef.addClass('has-error');
var help_msg = v.join("<br/>");
helpBlockRef.html(help_msg);
} else {
$.each(v, function (kk, vv) {
if (typeof vv === "object") {
$.each(vv, function (kkk, vvv) {
noneFieldErrorMsg += " " + vvv + '<br/>';
})
} else {
noneFieldErrorMsg += vv + '<br/>';
}
})
}
});
if (noneFieldErrorRef.length === 1 && noneFieldErrorMsg !== '') {
noneFieldErrorRef.css('display', 'block');
noneFieldErrorRef.html(noneFieldErrorMsg);
}
$('.has-error :visible').get(0).scrollIntoView();
}
})
}
function requestApi(props) {
// props = {url: .., body: , success: , error: , method: ,}
props = props || {};
var user_success_message = props.success_message;
var default_success_message = gettext('Update is successful!');
var user_fail_message = props.fail_message;
var default_failed_message = gettext('An unknown error occurred while updating..');
var flash_message = props.flash_message || true;
if (props.flash_message === false) {
flash_message = false;
}
var dataBody = props.body || props.data;
if (typeof(dataBody) === "object") {
dataBody = JSON.stringify(dataBody)
}
$.ajax({
url: props.url,
type: props.method || "PATCH",
data: dataBody,
contentType: props.content_type || "application/json; charset=utf-8",
dataType: props.data_type || "json"
}).done(function (data, textStatue, jqXHR) {
if (flash_message) {
var msg = "";
if (user_success_message) {
msg = user_success_message;
} else {
msg = default_success_message;
}
toastr.success(msg);
}
if (typeof props.success === 'function') {
return props.success(data);
}
}).fail(function (jqXHR, textStatus, errorThrown) {
if (flash_message) {
var msg = "";
if (user_fail_message) {
msg = user_fail_message;
} else if (jqXHR.responseJSON) {
if (jqXHR.responseJSON.error) {
msg = jqXHR.responseJSON.error
} else if (jqXHR.responseJSON.msg) {
msg = jqXHR.responseJSON.msg
} else if (jqXHR.responseJSON.detail) {
msg = jqXHR.responseJSON.detail
}
}
if (msg === "") {
msg = default_failed_message;
}
toastr.error(msg);
}
if (typeof props.error === 'function') {
return props.error(jqXHR.responseText, jqXHR.responseJSON, jqXHR.status);
}
});
// return true;
}
// Sweet Alert for Delete
function objectDelete(obj, name, url, redirectTo, title, success_message) {
function doDelete() {
var body = {};
var success = function () {
if (!redirectTo) {
$(obj).parent().parent().remove();
} else {
window.location.href = redirectTo;
}
};
var fail = function (responseText, responseJSON, status) {
var errorMsg = '';
if (responseJSON && responseJSON.error) {
errorMsg = '';
} else if (status === 404) {
errorMsg = gettext("Not found")
} else {
errorMsg = gettext("Server error")
}
swal(gettext('Error'), "[ " + name + " ] " + errorMsg);
};
requestApi({
url: url,
body: JSON.stringify(body),
method: 'DELETE',
success_message: success_message || gettext("Delete the success"),
success: success,
error: fail
});
}
swal({
title: title || gettext('Are you sure about deleting it?'),
text: " [" + name + "] ",
type: "warning",
showCancelButton: true,
cancelButtonText: gettext('Cancel'),
confirmButtonColor: "#ed5565",
confirmButtonText: gettext('Confirm'),
closeOnConfirm: true,
}, function () {
doDelete()
});
}
function orgDelete(obj, name, url, redirectTo) {
function doDelete() {
var body = {};
var success = function () {
if (!redirectTo) {
$(obj).parent().parent().remove();
} else {
window.location.href = redirectTo;
}
};
var fail = function (responseText, status) {
if (status === 400) {
swal(gettext("Error"), "[ " + name + " ] " + gettext("The organization contains undeleted information. Please try again after deleting"), "error");
} else if (status === 405) {
swal(gettext("Error"), " [ " + name + " ] " + gettext("Do not perform this operation under this organization. Try again after switching to another organization"), "error");
}
};
requestApi({
url: url,
body: JSON.stringify(body),
method: 'DELETE',
success_message: gettext("Delete the success"),
success: success,
error: fail
});
}
swal({
title: gettext("Please ensure that the following information in the organization has been deleted"),
text: gettext("User list、User group、Asset list、Domain list、Admin user、System user、Labels、Asset permission"),
type: "warning",
showCancelButton: true,
cancelButtonText: gettext('Cancel'),
confirmButtonColor: "#ed5565",
confirmButtonText: gettext('Confirm'),
closeOnConfirm: true
}, function () {
doDelete();
});
}
$.fn.serializeObject = function () {
var o = {};
var a = this.serializeArray();
$.each(a, function () {
if (o[this.name] !== undefined) {
if (!o[this.name].push) {
o[this.name] = [o[this.name]];
}
o[this.name].push(this.value || '');
} else {
o[this.name] = this.value || '';
}
});
return o;
};
function makeLabel(data) {
return "<label class='detail-key'><b>" + data[0] + ": </b></label> " + data[1] + "</br>"
}
function parseTableFilter(value) {
var cleanValues = [];
if (!value) {
return {}
}
var valuesArray = value.split(':');
for (var i=0; i<valuesArray.length; i++) {
var v = valuesArray[i].trim();
if (!v) {
continue
}
// 如果是最后一个元素直接push不需要再处理了, 因为最后一个肯定不是key
if (i === valuesArray.length -1) {
cleanValues.push(v);
continue
}
v = v.split(' ');
// 如果长度是1直接push上
// 如果长度不是1根据空格分隔后最后面的是key
if (v.length === 1) {
cleanValues.push(v[0]);
} else {
var leaveData = v.slice(0, -1).join(' ').trim();
cleanValues.push(leaveData);
cleanValues.push(v.slice(-1)[0]);
}
}
var filter = {};
var key = '';
for (i=0; i<cleanValues.length; i++) {
if (i%2 === 0) {
key = cleanValues[i]
} else {
value = cleanValues[i];
filter[key] = value
}
}
return filter;
}
var jumpserver = {};
jumpserver.checked = false;
jumpserver.selected = {};
jumpserver.language = {
processing: gettext('Loading') + '...',
search: gettext('Search'),
select: {
rows: {
_: gettext("Selected item %d"),
0: ""
}
},
lengthMenu: gettext("Per page _MENU_"),
info: gettext('Displays the results of items _START_ to _END_; A total of _TOTAL_ entries'),
infoFiltered: "",
infoEmpty: "",
zeroRecords: gettext("No match"),
emptyTable: gettext('No record'),
paginate: {
first: "«",
previous: "",
next: "",
last: "»"
}
};
function setDataTablePagerLength(num) {
$.fn.DataTable.ext.pager.numbers_length = num;
}
jumpserver.initDataTable = function (options) {
// options = {
// ele *: $('#dataTable_id'),
// ajax_url *: '{% url 'users:user-list-api' %}',
// columns *: [{data: ''}, ....],
// dom: 'fltip',
// i18n_url: '{% static "js/...../en-us.json" %}',
// order: [[1, 'asc'], [2, 'asc'], ...],
// buttons: ['excel', 'pdf', 'print'],
// columnDefs: [{target: 0, createdCell: ()=>{}}, ...],
// uc_html: '<a>header button</a>',
// op_html: 'div.btn-group?',
// paging: true
// }
setDataTablePagerLength(5);
var ele = options.ele || $('.dataTable');
var columnDefs = [
{
targets: 0,
orderable: false,
width: "20px",
createdCell: function (td, cellData) {
$(td).html('<input type="checkbox" class="text-center ipt_check" id=99991937>'.replace('99991937', cellData));
}
},
{
className: 'text-center',
render: $.fn.dataTable.render.text(),
targets: '_all'
}
];
columnDefs = options.columnDefs ? options.columnDefs.concat(columnDefs) : columnDefs;
var select = {
style: 'multi',
selector: 'td:first-child'
};
var table = ele.DataTable({
pageLength: options.pageLength || 15,
dom: options.dom || '<"#uc.pull-left"><"pull-right"<"inline"l><"#fb.inline"><"inline"f><"#fa.inline">>tr<"row m-t"<"col-md-8"<"#op.col-md-6"><"col-md-6 text-center"i>><"col-md-4"p>>',
order: options.order || [],
// select: options.select || 'multi',
searchDelay: 800,
buttons: [],
columnDefs: columnDefs,
ajax: {
url: options.ajax_url,
dataSrc: ""
},
columns: options.columns || [],
select: options.select || select,
language: jumpserver.language,
lengthMenu: [[10, 15, 25, 50, -1], [10, 15, 25, 50, "All"]]
});
table.on('select', function (e, dt, type, indexes) {
var $node = table[type](indexes).nodes().to$();
$node.find('input.ipt_check').prop('checked', true);
jumpserver.selected[$node.find('input.ipt_check').prop('id')] = true
}).on('deselect', function (e, dt, type, indexes) {
var $node = table[type](indexes).nodes().to$();
$node.find('input.ipt_check').prop('checked', false);
jumpserver.selected[$node.find('input.ipt_check').prop('id')] = false
}).on('draw', function () {
$('#op').html(options.op_html || '');
$('#uc').html(options.uc_html || '');
$('[data-toggle="popover"]').popover({
html: true,
placement: 'bottom',
trigger: 'click',
container: 'body'
}).on('click', function (e) {
$('[data-toggle="popover"]').not(this).popover('hide');
});
});
$('.ipt_check_all').on('click', function () {
if ($(this).prop("checked")) {
$(this).closest('table').find('.ipt_check').prop('checked', true);
jumpserver.checked = true;
table.rows({search: 'applied', page: 'current'}).select();
} else {
$(this).closest('table').find('.ipt_check').prop('checked', false);
jumpserver.checked = false;
table.rows({search: 'applied', page: 'current'}).deselect();
}
});
return table;
};
jumpserver.initStaticTable = function (selector) {
$(selector).DataTable({
"searching": false,
"bInfo": false,
"paging": false,
"order": [],
"language": jumpserver.language
});
};
jumpserver.initServerSideDataTable = function (options) {
// options = {
// ele *: $('#dataTable_id'),
// ajax_url *: '{% url 'users:user-list-api' %}',
// select_style: 'multi',
// columns *: [{data: ''}, ....],
// dom: 'fltip',
// i18n_url: '{% static "js/...../en-us.json" %}',
// order: [[1, 'asc'], [2, 'asc'], ...],
// buttons: ['excel', 'pdf', 'print'],
// columnDefs: [{target: 0, createdCell: ()=>{}}, ...],
// uc_html: '<a>header button</a>',
// op_html: 'div.btn-group?',
// paging: true,
// paging_numbers_length: 5;
// hideDefaultDefs: false;
// }
var pagingNumbersLength = 5;
if (options.paging_numbers_length){
pagingNumbersLength = options.paging_numbers_length;
}
setDataTablePagerLength(pagingNumbersLength);
var ele = options.ele || $('.dataTable');
var columnDefs = [
{
targets: 0,
orderable: false,
width: "20px",
createdCell: function (td, cellData) {
var data = '<input type="checkbox" class="text-center ipt_check" id=Id>'.replace('Id', cellData);
$(td).html(data);
}
},
{
targets: '_all',
className: 'text-center',
render: $.fn.dataTable.render.text()
}
];
if (options.hideDefaultDefs) {
columnDefs = [];
}
var select_style = options.select_style || 'multi';
columnDefs = options.columnDefs ? options.columnDefs.concat(columnDefs) : columnDefs;
var select = {
style: select_style,
selector: 'td:first-child'
};
var dom = '<"#uc.pull-left"> <"pull-right"<"#lb.inline"> <"inline"l> <"#fb.inline"> <"inline"f><"#fa.inline">>' +
'tr' +
'<"row m-t"<"col-md-8"<"#op.col-md-6"><"col-md-6 text-center"i>><"col-md-4"p>>';
var table = ele.DataTable({
pageLength: options.pageLength || 15,
// dom: options.dom || '<"#uc.pull-left">fltr<"row m-t"<"col-md-8"<"#op.col-md-6"><"col-md-6 text-center"i>><"col-md-4"p>>',
// dom: options.dom || '<"#uc.pull-left"><"pull-right"<"inline"l><"#fb.inline"><"inline"<"table-filter"f>><"#fa.inline">>tr<"row m-t"<"col-md-8"<"#op.col-md-6"><"col-md-6 text-center"i>><"col-md-4"p>>',
dom: options.dom || dom,
order: options.order || [],
buttons: [],
columnDefs: columnDefs,
serverSide: true,
processing: true,
searchDelay: 800,
oSearch: options.oSearch,
ajax: {
url: options.ajax_url,
error: function (jqXHR, textStatus, errorThrown) {
if (jqXHR.responseText && jqXHR.responseText.indexOf("%(value)s") !== -1 ) {
return
}
var msg = gettext("Unknown error occur");
if (jqXHR.responseJSON) {
if (jqXHR.responseJSON.error) {
msg = jqXHR.responseJSON.error
} else if (jqXHR.responseJSON.msg) {
msg = jqXHR.responseJSON.msg
}
}
alert(msg)
},
data: function (data) {
delete data.columns;
if (data.length !== null) {
data.limit = data.length;
delete data.length;
}
if (data.start !== null) {
data.offset = data.start;
delete data.start;
}
if (data.search !== null) {
var searchValue = data.search.value;
var searchFilter = parseTableFilter(searchValue);
if (Object.keys(searchFilter).length === 0) {
data.search = searchValue;
} else {
data.search = '';
$.each(searchFilter, function (k, v) {
data[k] = v
})
}
}
if (data.order !== null && data.order.length === 1) {
var col = data.order[0].column;
var order = options.columns[col].data;
if (data.order[0].dir === "desc") {
order = "-" + order;
}
data.order = order;
}
},
dataFilter: function (data) {
var json = jQuery.parseJSON(data);
json.recordsTotal = json.count;
json.recordsFiltered = json.count;
return JSON.stringify(json); // return JSON string
},
dataSrc: "results"
},
columns: options.columns || [],
select: options.select || select,
language: jumpserver.language,
lengthMenu: options.lengthMenu || [[15, 25, 50, 9999], [15, 25, 50, 'All']]
});
table.selected = [];
table.selected_rows = [];
table.on('select', function (e, dt, type, indexes) {
var $node = table[type](indexes).nodes().to$();
$node.find('input.ipt_check').prop('checked', true);
jumpserver.selected[$node.find('input.ipt_check').prop('id')] = true;
if (type === 'row') {
var rows = table.rows(indexes).data();
$.each(rows, function (id, row) {
if (row.id && $.inArray(row.id, table.selected) === -1) {
if (select.style === 'multi'){
table.selected.push(row.id);
table.selected_rows.push(row);
}
else{
table.selected = [row.id];
table.selected_rows = [row];
}
}
})
}
}).on('deselect', function (e, dt, type, indexes) {
var $node = table[type](indexes).nodes().to$();
$node.find('input.ipt_check').prop('checked', false);
jumpserver.selected[$node.find('input.ipt_check').prop('id')] = false;
if (type === 'row') {
var rows = table.rows(indexes).data();
$.each(rows, function (id, row) {
if (row.id) {
var index = table.selected.indexOf(row.id);
if (index > -1) {
table.selected.splice(index, 1);
table.selected_rows.splice(index, 1);
}
}
})
}
}).on('draw', function () {
$('[data-toggle="popover"]').popover({
html: true,
placement: 'bottom',
trigger: 'click',
container: 'body'
}).on('click', function (e) {
$('[data-toggle="popover"]').not(this).popover('hide');
});
var table_data = [];
$.each(table.rows().data(), function (id, row) {
if (row.id) {
table_data.push(row.id)
}
});
$.each(table.selected, function (id, data) {
var index = table_data.indexOf(data);
if (index > -1) {
table.rows(index).select()
}
});
}).on("init", function () {
$('#op').html(options.op_html || '');
$('#uc').html(options.uc_html || '');
$('#fb').html(options.fb_html || '');
$('#fa').html(options.fa_html || '');
$('#lb').html(options.lb_html || '');
});
var table_id = table.settings()[0].sTableId;
$('#' + table_id + ' .ipt_check_all').on('click', function () {
if (select_style !== 'multi') {
return
}
if ($(this).prop("checked")) {
$(this).closest('table').find('.ipt_check').prop('checked', true);
table.rows({search: 'applied', page: 'current'}).select();
} else {
$(this).closest('table').find('.ipt_check').prop('checked', false);
table.rows({search: 'applied', page: 'current'}).deselect();
}
});
// jumpserver.table = table;
return table;
};
/**
* 替换所有匹配exp的字符串为指定字符串
* @param exp 被替换部分的正则
* @param newStr 替换成的字符串
*/
String.prototype.replaceAll = function (exp, newStr) {
return this.replace(new RegExp(exp, "gm"), newStr);
};
/**
* 原型:字符串格式化
* @param args 格式化参数值
*/
String.prototype.format = function (args) {
var result = this;
if (arguments.length < 1) {
return result;
}
var data = arguments;
if (arguments.length == 1 && typeof (args) == "object") {
data = args;
}
for (var key in data) {
var value = data[key];
if (undefined != value) {
result = result.replaceAll("\\{" + key + "\\}", value);
}
}
return result;
};
function setCookie(key, value, time) {
var expires = new Date();
if (!time) {
time = expires.getTime() + (24 * 60 * 60 * 1000);
}
expires.setTime(time);
document.cookie = key + '=' + value + ';expires=' + expires.toUTCString() + ';path=/';
}
function delCookie(key) {
var expires = new Date();
expires.setTime(expires.getTime() - 1);
var val = getCookie(key);
if (val !== null) {
document.cookie = key + '=' + val + ";expires" + expires.toUTCString() + ';path=/';
}
}
function createPopover(dataset, title, callback) {
if (callback !== undefined) {
var new_dataset = [];
$.each(dataset, function (index, value) {
new_dataset.push(callback(value))
});
dataset = new_dataset;
}
var data_content = dataset.join("<br>");
var html = "<a data-toggle='popover' data-content='" + data_content + "'>" + dataset.length + "</a>";
return html;
}
$(function () {
(function ($) {
$.getUrlParam = function (name) {
var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)");
var r = window.location.search.substr(1).match(reg);
if (r != null) return unescape(r[2]);
return null;
}
})(jQuery);
});
function getUrlParam(name) {
var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)");
var r = window.location.search.substr(1).match(reg);
if (r != null) return unescape(r[2]);
return null;
}
function setUrlParam(url, name, value) {
var urlArray = url.split("?");
if (urlArray.length === 1) {
url += "?" + name + "=" + value;
} else {
var oriParam = urlArray[1].split("&");
var oriParamMap = {};
$.each(oriParam, function (index, value) {
var v = value.split("=");
oriParamMap[v[0]] = v[1];
});
oriParamMap[name] = value;
url = urlArray[0] + "?";
var newParam = [];
$.each(oriParamMap, function (index, value) {
newParam.push(index + "=" + value);
});
url += newParam.join("&")
}
return url
}
// Password check rules
var rules_short_map_id = {
'min': 'id_security_password_min_length',
'upper': 'id_security_password_upper_case',
'lower': 'id_security_password_lower_case',
'number': 'id_security_password_number',
'special': 'id_security_password_special_char'
};
var rules_id_map_label = {
'id_security_password_min_length': gettext('Password minimum length {N} bits'),
'id_security_password_upper_case': gettext('Must contain capital letters'),
'id_security_password_lower_case': gettext('Must contain lowercase letters'),
'id_security_password_number': gettext('Must contain numeric characters'),
'id_security_password_special_char': gettext('Must contain special characters')
};
function getRuleLabel(rule) {
var label = '';
if (rule.key === rules_short_map_id['min']) {
label = rules_id_map_label[rule.key].replace('{N}', rule.value)
} else {
label = rules_id_map_label[rule.key]
}
return label
}
// 校验密码-改变规则颜色
function checkPasswordRules(password, minLength) {
if (wordMinLength(password, minLength)) {
$('#' + rules_short_map_id['min']).css('color', 'green')
} else {
$('#' + rules_short_map_id['min']).css('color', '#908a8a')
}
if (wordUpperCase(password)) {
$('#' + rules_short_map_id['upper']).css('color', 'green')
} else {
$('#' + rules_short_map_id['upper']).css('color', '#908a8a')
}
if (wordLowerCase(password)) {
$('#' + rules_short_map_id['lower']).css('color', 'green')
} else {
$('#' + rules_short_map_id['lower']).css('color', '#908a8a')
}
if (wordNumber(password)) {
$('#' + rules_short_map_id['number']).css('color', 'green')
} else {
$('#' + rules_short_map_id['number']).css('color', '#908a8a')
}
if (wordSpecialChar(password)) {
$('#' + rules_short_map_id['special']).css('color', 'green')
} else {
$('#' + rules_short_map_id['special']).css('color', '#908a8a')
}
}
// 最小长度
function wordMinLength(word, minLength) {
//var minLength = {{ min_length }};
var re = new RegExp("^(.{" + minLength + ",})$");
return word.match(re)
}
// 大写字母
function wordUpperCase(word) {
return word.match(/([A-Z]+)/)
}
// 小写字母
function wordLowerCase(word) {
return word.match(/([a-z]+)/)
}
// 数字字符
function wordNumber(word) {
return word.match(/([\d]+)/)
}
// 特殊字符
function wordSpecialChar(word) {
return word.match(/[`,~,!,@,#,\$,%,\^,&,\*,\(,\),\-,_,=,\+,\{,\},\[,\],\|,\\,;,',:,",\,,\.,<,>,\/,\?]+/)
}
// 显示弹窗密码规则
function popoverPasswordRules(password_check_rules, $el) {
var message = "";
jQuery.each(password_check_rules, function (idx, rule) {
message += "<li id=" + rule.key + " style='list-style-type:none;'> <i class='fa fa-check-circle-o' style='margin-right:10px;' ></i>" + getRuleLabel(rule) + "</li>";
});
//$('#id_password_rules').html(message);
$el.html(message)
}
// 初始化弹窗popover
function initPopover($container, $progress, $idPassword, $el, password_check_rules, i18n_fallback) {
options = {};
// User Interface
options.ui = {
container: $container,
viewports: {
progress: $progress
//errors: $('.popover-content')
},
showProgressbar: true,
showVerdictsInsideProgressBar: true
};
options.i18n = {
fallback: i18n_fallback,
t: function (key) {
var result = '';
result = options.i18n.fallback[key];
return result === key ? '' : result;
}
};
$idPassword.pwstrength(options);
popoverPasswordRules(password_check_rules, $el);
}
function rootNodeAddDom(ztree, callback) {
var refreshIcon = "<a id='tree-refresh'><i class='fa fa-refresh'></i></a>";
var rootNode = ztree.getNodes()[0];
if (rootNode) {
var $rootNodeRef = $("#" + rootNode.tId + "_a");
$rootNodeRef.after(refreshIcon);
} else {
$rootNodeRef = $('#' + ztree.setting.treeId);
$rootNodeRef.html(refreshIcon);
}
var refreshIconRef = $('#tree-refresh');
refreshIconRef.bind('click', function () {
ztree.destroy();
callback()
})
}
function APIExportCSV(props) {
/*
{
listUrl:
objectsId:
template:
table:
params:
}
*/
var _listUrl = props.listUrl;
var _objectsId = props.objectsId;
var _template = props.template;
var _table = props.table;
var _params = props.params || {};
var tableParams = _table.ajax.params();
var exportUrl = setUrlParam(_listUrl, 'format', 'csv');
if (_template) {
exportUrl = setUrlParam(exportUrl, 'template', _template)
}
for (var k in tableParams) {
if (datatableInternalParams.includes(k)) {
continue
}
if (!tableParams[k]) {
continue
}
exportUrl = setUrlParam(exportUrl, k, tableParams[k])
}
for (var k in _params) {
exportUrl = setUrlParam(exportUrl, k, tableParams[k])
}
if (!_objectsId) {
console.log(exportUrl);
window.open(exportUrl);
return
}
requestApi({
url: '/api/v1/common/resources/cache/',
data: JSON.stringify({resources: _objectsId}),
method: "POST",
flash_message: false,
success: function (data) {
exportUrl = setUrlParam(exportUrl, 'spm', data.spm);
console.log(exportUrl);
window.open(exportUrl);
},
failed: function () {
toastr.error(gettext('Export failed'));
}
});
}
function APIExportData(props) {
props = props || {};
$.ajax({
url: '/api/common/v1/resources/cache/',
type: props.method || "POST",
data: props.body,
contentType: props.content_type || "application/json; charset=utf-8",
dataType: props.data_type || "json",
success: function (data) {
var export_url = props.success_url;
var params = props.params || {};
params['format'] = props.format;
params['spm'] = data.spm;
for (var k in params) {
export_url = setUrlParam(export_url, k, params[k])
}
window.open(export_url);
},
error: function () {
toastr.error(gettext('Export failed'));
}
})
}
function APIImportData(props) {
props = props || {};
$.ajax({
url: props.url,
type: props.method || "POST",
processData: false,
data: props.body,
contentType: props.content_type || 'text/csv',
success: function (data) {
if (props.method === 'POST') {
$('#created_failed').html('');
$('#created_failed_detail').html('');
$('#success_created').html(gettext("Import Success"));
$('#success_created_detail').html("Count" + ": " + data.length);
} else {
$('#updated_failed').html('');
$('#updated_failed_detail').html('');
$('#success_updated').html(gettext("Update Success"));
$('#success_updated_detail').html(gettext("Count") + ": " + data.length);
}
props.data_table.ajax.reload()
},
error: function (error) {
var data = error.responseJSON;
console.log(data);
if (data instanceof Array) {
var html = '';
var li = '';
var err = '';
$.each(data, function (index, item) {
err = '';
for (var prop in item) {
err += prop + ": " + item[prop][0] + " "
}
if (err) {
li = "<li>" + "Line " + (++index) + ". " + err + "</li>";
html += li
}
});
html = "<ul>" + html + "</ul>"
} else {
html = error.responseText
}
if (props.method === 'POST') {
$('#success_created').html('');
$('#success_created_detail').html('');
$('#created_failed').html(gettext("Import failed"));
$('#created_failed_detail').html(html);
} else {
$('#success_updated').html('');
$('#success_updated_detail').html('');
$('#updated_failed').html(gettext("Update failed"));
$('#updated_failed_detail').html(html);
}
}
})
}
function htmlEscape(d) {
return typeof d === 'string' ?
d.replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;') :
d;
}
function objectAttrsIsList(obj, attrs) {
attrs.forEach(function (attr) {
if (!obj[attr]) {
obj[attr] = []
} else if (obj[attr] && !(obj[attr] instanceof Array)) {
obj[attr] = [obj[attr]]
}
})
}
function objectAttrsIsDatetime(obj, attrs) {
attrs.forEach(function (attr) {
obj[attr] = toSafeDateISOStr(obj[attr]);
})
}
function objectAttrsIsBool(obj, attrs) {
attrs.forEach(function (attr) {
if (!obj[attr]) {
obj[attr] = false
} else {
obj[attr] = ['on', '1', 'true', 'True'].includes(obj[attr]);
}
})
}
function objectAttrsIsNumber(obj, attrs) {
attrs.forEach(function (attr) {
if (!obj[attr]) {
obj[attr] = null;
}
})
}
function cleanDateStr(d) {
for (var i = 0; i < 3; i++) {
if (!isNaN(Date.parse(d))) {
return d;
}
if (!isNaN(Number(d))) {
return d;
}
switch (i) {
case 0:
d = d.replaceAll('-', '/');
break;
case 1:
d = d.split('+')[0].trimRight();
break;
}
}
return null;
}
function safeDate(s) {
s = cleanDateStr(s);
return new Date(s)
}
function toSafeDateISOStr(s) {
var d = safeDate(s);
return d.toISOString();
}
function toSafeLocalDateStr(d) {
var date = safeDate(d);
var date_s = date.toLocaleString(getUserLang(), {hour12: false});
return date_s.split("/").join('-')
}
function getUrlParams(url) {
url = url.split("?");
var params = "";
if (url.length === 2) {
params = url[1];
}
return params
}
function getTimeUnits(u) {
var units = {
"d": "天",
"h": "时",
"m": "分",
"s": "秒",
};
if (getUserLang() === "zh-CN") {
return units[u]
}
return u
}
function timeOffset(a, b) {
var start = safeDate(a);
var end = safeDate(b);
var offset = (end - start) / 1000;
return readableSecond(offset)
}
function readableSecond(offset) {
var days = offset / 3600 / 24;
var hours = offset / 3600;
var minutes = offset / 60;
var seconds = offset;
if (days > 1) {
return days.toFixed(1) + " " + getTimeUnits("d");
} else if (hours > 1) {
return hours.toFixed(1) + " " + getTimeUnits("h");
} else if (minutes > 1) {
return minutes.toFixed(1) + " " + getTimeUnits("m")
} else if (seconds > 1) {
return seconds.toFixed(1) + " " + getTimeUnits("s")
}
return ""
}
function readFile(ref) {
var files = ref.prop('files');
var hasFile = files && files.length > 0;
if (hasFile) {
var reader = new FileReader();//新建一个FileReader
reader.readAsText(files[0], "UTF-8");//读取文件
reader.onload = function (evt) { //读取完文件之后会回来这里
ref.trigger("onload", evt.target.result);
};
} else {
ref.trigger("onload", null);
}
return ref
}
function select2AjaxInit(option) {
/*
{
selector:
url: ,
disabledData: ,
displayFormat,
idFormat,
}
*/
var selector = option.selector;
var url = option.url;
var disabledData = option.disabledData;
var displayFormat = option.displayFormat || function (data) {
return data.name;
};
var idFormat = option.idFormat || function (data) {
return data.id;
};
return $(selector).select2({
closeOnSelect: false,
ajax: {
url: url,
data: function (params) {
var page = params.page || 1;
var query = {
search: params.term,
offset: (page - 1) * 10,
limit: 10
};
return query
},
processResults: function (data) {
var results = $.map(data.results, function (v, i) {
var display = displayFormat(v);
var id = idFormat(v);
var d = {id: id, text: display};
if (disabledData && disabledData.indexOf(v.id) !== -1) {
d.disabled = true;
}
return d;
});
var more = !!data.next;
return {results: results, pagination: {"more": more}}
}
},
})
}
function usersSelect2Init(selector, url, disabledData) {
if (!url) {
url = '/api/v1/users/users/'
}
function displayFormat(v) {
return v.name + '(' + v.username +')';
}
var option = {
url: url,
selector: selector,
disabledData: disabledData,
displayFormat: displayFormat
};
return select2AjaxInit(option)
}
function nodesSelect2Init(selector, url, disabledData) {
if (!url) {
url = '/api/v1/assets/nodes/'
}
function displayFormat(v) {
return v.full_value;
}
var option = {
url: url,
selector: selector,
disabledData: disabledData,
displayFormat: displayFormat
};
return select2AjaxInit(option)
}
function showCeleryTaskLog(taskId) {
var url = '/ops/celery/task/taskId/log/'.replace('taskId', taskId);
window.open(url, '', 'width=900,height=600')
}
function getUserLang(){
let userLangEN = document.cookie.indexOf('django_language=en');
if (userLangEN === -1){
return 'zh-CN'
}
else{
return 'en-US'
}
}
function initDateRangePicker(selector, options) {
if (!options) {
options = {}
}
var zhLocale = {
format: 'YYYY-MM-DD HH:mm',
separator: ' ~ ',
applyLabel: "应用",
cancelLabel: "取消",
resetLabel: "重置",
daysOfWeek: ["日", "一", "二", "三", "四", "五", "六"],//汉化处理
monthNames: ["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"],
};
var enLocale = {
format: "YYYY-MM-DD HH:mm",
separator: " - ",
applyLabel: "Apply",
cancelLabel: "Cancel",
resetLabel: "Reset",
daysOfWeek: ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"],
monthNames: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
};
var defaultOption = {
singleDatePicker: true,
showDropdowns: true,
timePicker: true,
timePicker24Hour: true,
autoApply: true,
};
if (getUserLang() === 'zh-CN') {
defaultOption.locale = zhLocale;
}
else{
// en-US
defaultOption.locale = enLocale;
}
options = Object.assign(defaultOption, options);
return $(selector).daterangepicker(options);
}
function reloadPage() {
setTimeout( function () {window.location.reload();}, 300);
}
function isEmptyObject(obj) {
return Object.keys(obj).length === 0
}
function getStatusIcon(status, mapping, title) {
var navy = '<i class="fa fa-circle text-navy" title=""></i>';
var danger = '<i class="fa fa-circle text-danger" title=""></i>';
var warning = '<i class="fa fa-circle text-warning" title=""></i>';
var icons = {
navy: navy,
danger: danger,
warning: warning
};
var defaultMapping = {
true: 'navy',
false: 'danger',
1: 'navy',
0: 'danger',
default: 'navy'
};
if (!mapping) {
mapping = defaultMapping;
}
var name = mapping[status] || mapping['default'];
var icon = icons[name];
if (title) {
icon = icon.replace('title=""', 'title="' + title + '"')
}
return icon;
}