Unverified Commit 354b728f authored by 老广's avatar 老广 Committed by GitHub

Merge pull request #1945 from jumpserver/dev_storage

[Update] 更新命令/录像存储设置
parents ce553710 4f806f11
# -*- coding: utf-8 -*-
#
import os
import json
import jms_storage
from rest_framework.views import Response, APIView
from ldap3 import Server, Connection
......@@ -8,8 +11,9 @@ from django.core.mail import get_connection, send_mail
from django.utils.translation import ugettext_lazy as _
from django.conf import settings
from .permissions import IsOrgAdmin
from .permissions import IsOrgAdmin, IsSuperUser
from .serializers import MailTestSerializer, LDAPTestSerializer
from .models import Setting
class MailTestingAPI(APIView):
......@@ -85,6 +89,79 @@ class LDAPTestingAPI(APIView):
return Response({"error": str(serializer.errors)}, status=401)
class ReplayStorageCreateAPI(APIView):
permission_classes = (IsSuperUser,)
def post(self, request):
storage_data = request.data
if storage_data.get('TYPE') == 'ceph':
port = storage_data.get('PORT')
if port.isdigit():
storage_data['PORT'] = int(storage_data.get('PORT'))
storage_name = storage_data.pop('NAME')
data = {storage_name: storage_data}
if not self.is_valid(storage_data):
return Response({"error": _("Error: Account invalid")}, status=401)
Setting.save_storage('TERMINAL_REPLAY_STORAGE', data)
return Response({"msg": _('Create succeed')}, status=200)
@staticmethod
def is_valid(storage_data):
if storage_data.get('TYPE') == 'server':
return True
storage = jms_storage.get_object_storage(storage_data)
target = 'tests.py'
src = os.path.join(settings.BASE_DIR, 'common', target)
return storage.is_valid(src, target)
class ReplayStorageDeleteAPI(APIView):
permission_classes = (IsSuperUser,)
def post(self, request):
storage_name = str(request.data.get('name'))
Setting.delete_storage('TERMINAL_REPLAY_STORAGE', storage_name)
return Response({"msg": _('Delete succeed')}, status=200)
class CommandStorageCreateAPI(APIView):
permission_classes = (IsSuperUser,)
def post(self, request):
storage_data = request.data
storage_name = storage_data.pop('NAME')
data = {storage_name: storage_data}
if not self.is_valid(storage_data):
return Response({"error": _("Error: Account invalid")}, status=401)
Setting.save_storage('TERMINAL_COMMAND_STORAGE', data)
return Response({"msg": _('Create succeed')}, status=200)
@staticmethod
def is_valid(storage_data):
if storage_data.get('TYPE') == 'server':
return True
try:
storage = jms_storage.get_log_storage(storage_data)
except Exception:
return False
return storage.ping()
class CommandStorageDeleteAPI(APIView):
permission_classes = (IsSuperUser,)
def post(self, request):
storage_name = str(request.data.get('name'))
Setting.delete_storage('TERMINAL_COMMAND_STORAGE', storage_name)
return Response({"msg": _('Delete succeed')}, status=200)
class DjangoSettingsAPI(APIView):
def get(self, request):
if not settings.DEBUG:
......
......@@ -135,32 +135,24 @@ class TerminalSettingForm(BaseForm):
('hostname', _('Hostname')),
('ip', _('IP')),
)
TERMINAL_ASSET_LIST_SORT_BY = forms.ChoiceField(
choices=SORT_BY_CHOICES, initial='hostname', label=_("List sort by")
)
TERMINAL_HEARTBEAT_INTERVAL = forms.IntegerField(
initial=5, label=_("Heartbeat interval"), help_text=_("Units: seconds")
)
TERMINAL_PASSWORD_AUTH = forms.BooleanField(
initial=True, required=False, label=_("Password auth")
)
TERMINAL_PUBLIC_KEY_AUTH = forms.BooleanField(
initial=True, required=False, label=_("Public key auth")
)
TERMINAL_COMMAND_STORAGE = FormEncryptDictField(
label=_("Command storage"), help_text=_(
"Set terminal storage setting, `default` is the using as default,"
"You can set other storage and some terminal using"
)
)
TERMINAL_REPLAY_STORAGE = FormEncryptDictField(
label=_("Replay storage"), help_text=_(
"Set replay storage setting, `default` is the using as default,"
"You can set other storage and some terminal using"
TERMINAL_HEARTBEAT_INTERVAL = forms.IntegerField(
initial=5, label=_("Heartbeat interval"), help_text=_("Units: seconds")
)
TERMINAL_ASSET_LIST_SORT_BY = forms.ChoiceField(
choices=SORT_BY_CHOICES, initial='hostname', label=_("List sort by")
)
class TerminalCommandStorage(BaseForm):
pass
class SecuritySettingForm(BaseForm):
# MFA global setting
SECURITY_MFA_AUTH = forms.BooleanField(
......
......@@ -67,6 +67,30 @@ class Setting(models.Model):
except json.JSONDecodeError as e:
raise ValueError("Json dump error: {}".format(str(e)))
@classmethod
def save_storage(cls, name, data):
obj = cls.objects.filter(name=name).first()
if not obj:
obj = cls()
obj.name = name
obj.encrypted = True
obj.cleaned_value = data
else:
value = obj.cleaned_value
value.update(data)
obj.cleaned_value = value
obj.save()
return obj
@classmethod
def delete_storage(cls, name, storage_name):
obj = cls.objects.get(name=name)
value = obj.cleaned_value
value.pop(storage_name, '')
obj.cleaned_value = value
obj.save()
return True
@classmethod
def refresh_all_settings(cls):
try:
......
......@@ -3,6 +3,7 @@ from django.conf import settings
from celery import shared_task
from .utils import get_logger
from .models import Setting
from common.models import common_settings
logger = get_logger(__file__)
......@@ -28,7 +29,7 @@ def send_mail_async(*args, **kwargs):
if len(args) == 3:
args = list(args)
args[0] = settings.EMAIL_SUBJECT_PREFIX + args[0]
args[0] = common_settings.EMAIL_SUBJECT_PREFIX + args[0]
args.insert(2, settings.EMAIL_HOST_USER)
args = tuple(args)
......
......@@ -75,32 +75,6 @@
{% block custom_foot_js %}
<script>
$(document).ready(function () {
})
.on("click", ".btn-test", function () {
var data = {};
var form = $("form").serializeArray();
$.each(form, function (i, field) {
data[field.name] = field.value;
});
var the_url = "{% url 'api-common:mail-testing' %}";
function error(message) {
toastr.error(message)
}
function success(message) {
toastr.success(message.msg)
}
APIUpdateAttr({
url: the_url,
body: JSON.stringify(data),
method: "POST",
flash_message: false,
success: success,
error: error
});
})
</script>
{% endblock %}
{#{% extends 'base.html' %}#}
{% extends '_base_create_update.html' %}
{% load static %}
{% load bootstrap3 %}
{% load i18n %}
{% load common_tags %}
{% 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 action="" method="POST" class="form-horizontal">
<div class="form-group">
<label class="col-md-2 control-label" for="id_type">{% trans "Type" %}</label>
<div class="col-md-9">
<select id="id_type" class="selector form-control">
<option value ="server" selected="selected">server</option>
<option value ="es">es (elasticsearch)</option>
</select>
</div>
</div>
<div class="form-group">
<label class="col-md-2 control-label" for="id_name">{% trans "Name" %}</label>
<div class="col-md-9">
<input id="id_name" class="form-control" type="text" name="NAME" value="">
<div class="help-block">* required</div>
<div id="id_error" style="color: red;"></div>
</div>
</div>
<div class="form-group" style="display: none;" >
<label class="col-md-2 control-label" for="id_hosts">{% trans "Hosts" %}</label>
<div class="col-md-9">
<input id="id_hosts" class="form-control" type="text" name="HOSTS" value="">
<div class="help-block">{% trans 'Tips: If there are multiple hosts, separate them with a comma (,)' %}</div>
<div class="help-block">eg: http://www.jumpserver.a.com, http://www.jumpserver.b.com</div>
</div>
</div>
{# <div class="form-group" style="display: none;" >#}
{# <label class="col-md-2 control-label" for="id_other">{% trans "Other" %}</label>#}
{# <div class="col-md-9">#}
{# <input id="id_other" class="form-control" type="text" name="OTHER" value="">#}
{# </div>#}
{# </div>#}
<div class="form-group" style="display: none;" >
<label class="col-md-2 control-label" for="id_bucket">{% trans "Index" %}</label>
<div class="col-md-9">
<input id="id_index" class="form-control" type="text" name="INDEX" value="jumpserver">
</div>
</div>
<div class="form-group" style="display: none;" >
<label class="col-md-2 control-label" for="id_doc_type">{% trans "Doc type" %}</label>
<div class="col-md-9">
<input id="id_doc_type" class="form-control" type="text" name="DOC_TYPE" value="command_store">
</div>
</div>
<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>
<a class="btn btn-primary" type="" id="id_submit_button" >{% trans 'Submit' %}</a>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
{% endblock %}
{% block custom_foot_js %}
<script>
var field_of_all, need_get_field_of_server, need_get_field_of_es;
function showField(field){
$.each(field, function(index, value){
$(value).parent('div').parent('div').css('display', '');
});
}
function hiddenField(field){
$.each(field, function(index, value){
$(value).parent('div').parent('div').css('display', 'none');
})
}
function getFieldByType(type){
if(type === 'server'){
return need_get_field_of_server
}
else if(type === 'es'){
return need_get_field_of_es
}
}
function ajaxAPI(url, data, success, error){
$.ajax({
url: url,
data: data,
method: 'POST',
contentType: 'application/json; charset=utf-8',
success: success,
error: error
})
}
$(document).ready(function() {
var name_id = '#id_name';
var hosts_id = '#id_hosts';
{#var other_id = '#id_other';#}
var index_id = '#id_index';
var doc_type_id = '#id_doc_type';
field_of_all = [name_id, hosts_id, index_id, doc_type_id];
need_get_field_of_server = [name_id];
need_get_field_of_es = [name_id, hosts_id, index_id, doc_type_id];
})
.on('change', '.selector', function(){
var type = $('.selector').val();
console.log(type);
hiddenField(field_of_all);
var field = getFieldByType(type);
showField(field)
})
.on('click', '#id_submit_button', function(){
var type = $('.selector').val();
var field = getFieldByType(type);
var data = {'TYPE': type};
$.each(field, function(index, id_field){
var name = $(id_field).attr('name');
var value = $(id_field).val();
if(name === 'HOSTS'){
data[name] = value.split(',');
}
else{
data[name] = value
}
});
var url = "{% url 'api-common:command-storage-create' %}";
var success = function(data, textStatus) {
console.log(data, textStatus);
location = "{% url 'common:terminal-setting' %}";
};
var error = function(data, textStatus) {
var error_msg = data.responseJSON.error;
$('#id_error').html(error_msg)
};
ajaxAPI(url, JSON.stringify(data), success, error)
})
</script>
{% endblock %}
{#{% extends 'base.html' %}#}
{% extends '_base_create_update.html' %}
{% load static %}
{% load bootstrap3 %}
{% load i18n %}
{% load common_tags %}
{% 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 action="" method="POST" class="form-horizontal">
<div class="form-group">
<label class="col-md-2 control-label" for="id_type">{% trans "Type" %}</label>
<div class="col-md-9">
<select id="id_type" class="selector form-control">
<option value ="server" selected="selected">server</option>
<option value ="s3">s3</option>
<option value="oss">oss</option>
<option value ="azure">azure</option>
<option value="ceph">ceph</option>
</select>
</div>
</div>
<div class="form-group">
<label class="col-md-2 control-label" for="id_name">{% trans "Name" %}</label>
<div class="col-md-9">
<input id="id_name" class="form-control" type="text" name="NAME" value="">
<div class="help-block">* required</div>
<div id="id_error" style="color: red;"></div>
</div>
</div>
<div class="form-group" style="display: none;" >
<label class="col-md-2 control-label" for="id_host">{% trans "Host" %}</label>
<div class="col-md-9">
<input id="id_host" class="form-control" type="text" name="HOSTNAME" value="" placeholder="Host">
</div>
</div>
<div class="form-group" style="display: none;" >
<label class="col-md-2 control-label" for="id_port">{% trans "Port" %}</label>
<div class="col-md-9">
<input id="id_port" class="form-control" type="text" name="PORT" value="" placeholder="7480">
</div>
</div>
<div class="form-group" style="display: none;" >
<label class="col-md-2 control-label" for="id_bucket">{% trans "Bucket" %}</label>
<div class="col-md-9">
<input id="id_bucket" class="form-control" type="text" name="BUCKET" value="" placeholder="Bucket">
</div>
</div>
<div class="form-group" style="display: none;" >
<label class="col-md-2 control-label" for="id_access_key">{% trans "Access key" %}</label>
<div class="col-md-9">
<input id="id_access_key" class="form-control" type="text" name="ACCESS_KEY" value="" placeholder="Access key">
</div>
</div>
<div class="form-group" style="display: none;" >
<label class="col-md-2 control-label" for="id_secret_key">{% trans "Secret key" %}</label>
<div class="col-md-9">
<input id="id_secret_key" class="form-control" type="text" name="SECRET_KEY" value="", placeholder="Secret key">
</div>
</div>
<div class="form-group" style="display: none;" >
<label class="col-md-2 control-label" for="id_container_name">{% trans "Container name" %}</label>
<div class="col-md-9">
<input id="id_container_name" class="form-control" type="text" name="CONTAINER_NAME" value="" placeholder="Container">
</div>
</div>
<div class="form-group" style="display: none;" >
<label class="col-md-2 control-label" for="id_account_name">{% trans "Account name" %}</label>
<div class="col-md-9">
<input id="id_account_name" class="form-control" type="text" name="ACCOUNT_NAME" value="" placeholder="Account name">
</div>
</div>
<div class="form-group" style="display: none;" >
<label class="col-md-2 control-label" for="id_account_key">{% trans "Account key" %}</label>
<div class="col-md-9">
<input id="id_account_key" class="form-control" type="text" name="ACCOUNT_KEY" value="" placeholder="Account key">
</div>
</div>
<div class="form-group" style="display: none;" >
<label class="col-md-2 control-label" for="id_endpoint">{% trans "Endpoint" %}</label>
<div class="col-md-9">
<input id="id_endpoint" class="form-control" type="text" name="ENDPOINT" value="" placeholder="Endpoint">
</div>
</div>
<div class="form-group" style="display: none;" >
<label class="col-md-2 control-label" for="id_endpoint_suffix">{% trans "Endpoint suffix" %}</label>
{# <div class="col-md-9">#}
{# <input id="id_endpoint_suffix" class="form-control" type="text" name="ENDPOINT_SUFFIX" value="">#}
{# <div class="help-block">{% trans '' %}</div>#}
{# </div>#}
<div class="col-md-9">
<select id="id_endpoint_suffix" name="ENDPOINT_SUFFIX" class="endpoint-suffix-selector form-control">
<option value="core.chinacloudapi.cn" selected="selected">core.chinacloudapi.cn</option>
<option value="core.windows.net">core.windows.net</option>
</select>
</div>
</div>
<div class="form-group" style="display: none;" >
<label class="col-md-2 control-label" for="id_region">{% trans "Region" %}</label>
<div class="col-md-9">
<input id="id_region" class="form-control" type="text" name="REGION" value="" placeholder="">
</div>
</div>
<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>
<a class="btn btn-primary" type="" id="id_submit_button" >{% trans 'Submit' %}</a>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
{% endblock %}
{% block custom_foot_js %}
<script>
var field_of_all, need_get_field_of_server, need_get_field_of_s3,
need_get_field_of_oss, need_get_field_of_azure, need_get_field_of_ceph;
function showField(field){
$.each(field, function(index, value){
$(value).parent('div').parent('div').css('display', '');
});
}
function hiddenField(field){
$.each(field, function(index, value){
$(value).parent('div').parent('div').css('display', 'none');
})
}
function getFieldByType(type){
if(type === 'server'){
return need_get_field_of_server
}
else if(type === 's3'){
return need_get_field_of_s3
}
else if(type === 'oss'){
return need_get_field_of_oss
}
else if(type === 'azure'){
return need_get_field_of_azure
}
else if(type === 'ceph'){
return need_get_field_of_ceph
}
}
function ajaxAPI(url, data, success, error){
$.ajax({
url: url,
data: data,
method: 'POST',
contentType: 'application/json; charset=utf-8',
success: success,
error: error
})
}
$(document).ready(function() {
var name_id = '#id_name';
var host_id = '#id_host';
var port_id = '#id_port';
var bucket_id = '#id_bucket';
var access_key_id = '#id_access_key';
var secret_key_id = '#id_secret_key';
var container_name_id = '#id_container_name';
var account_name_id = '#id_account_name';
var account_key_id = '#id_account_key';
var endpoint_id = '#id_endpoint';
var endpoint_suffix_id = '#id_endpoint_suffix';
var region_id = '#id_region';
field_of_all = [name_id, host_id, port_id, bucket_id, access_key_id, secret_key_id, container_name_id, account_name_id, account_key_id, endpoint_id, endpoint_suffix_id, region_id];
need_get_field_of_server = [name_id];
need_get_field_of_s3 = [name_id, bucket_id, access_key_id, secret_key_id, region_id];
need_get_field_of_oss = [name_id, access_key_id, secret_key_id, endpoint_id];
need_get_field_of_azure = [name_id, container_name_id, account_name_id, account_key_id, endpoint_suffix_id];
need_get_field_of_ceph = [name_id, host_id, port_id, bucket_id, access_key_id, secret_key_id, region_id];
})
.on('change', '.selector', function(){
var type = $('.selector').val();
console.log(type);
hiddenField(field_of_all);
var field = getFieldByType(type);
showField(field)
})
.on('click', '#id_submit_button', function(){
var type = $('.selector').val();
var field = getFieldByType(type);
var data = {'TYPE': type};
$.each(field, function(index, id_field){
var name = $(id_field).attr('name');
data[name] = $(id_field).val();
});
var url = "{% url 'api-common:replay-storage-create' %}";
var success = function(data, textStatus) {
location = "{% url 'common:terminal-setting' %}";
};
var error = function(data, textStatus) {
var error_msg = data.responseJSON.error;
$('#id_error').html(error_msg)
};
ajaxAPI(url, JSON.stringify(data), success, error)
})
</script>
{% endblock %}
......@@ -63,6 +63,14 @@
{% endif %}
{% endfor %}
<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>
<div class="hr-line-dashed"></div>
<h3>{% trans "Command storage" %}</h3>
......@@ -71,6 +79,7 @@
<tr>
<th>{% trans 'Name' %}</th>
<th>{% trans 'Type' %}</th>
<th>{% trans 'Action' %}</th>
</tr>
</thead>
<tbody>
......@@ -78,10 +87,13 @@
<tr>
<td>{{ name }}</td>
<td>{{ setting.TYPE }}</td>
<td><a class="btn btn-xs btn-danger m-l-xs btn-del-command" data-name="{{ name }}">{% trans 'Delete' %}</a></td>
</tr>
{% endfor %}
</tbody>
</table>
<a href="{% url 'common:command-storage-create' %}" class="btn btn-primary">{% trans 'Add' %}</a>
<div class="hr-line-dashed"></div>
<h3>{% trans "Replay storage" %}</h3>
<table class="table table-hover " id="task-history-list-table">
......@@ -89,6 +101,7 @@
<tr>
<th>{% trans 'Name' %}</th>
<th>{% trans 'Type' %}</th>
<th>{% trans 'Action' %}</th>
</tr>
</thead>
<tbody>
......@@ -96,18 +109,14 @@
<tr>
<td>{{ name }}</td>
<td>{{ setting.TYPE }}</td>
<td><a class="btn btn-xs btn-danger m-l-xs btn-del-replay" data-name="{{ name }}">{% trans 'Delete' %}</a></td>
</tr>
{% endfor %}
</tbody>
</table>
<a href="{% url 'common:replay-storage-create' %}" class="btn btn-primary">{% trans 'Add' %}</a>
<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>
</div>
</div>
......@@ -116,40 +125,63 @@
</div>
</div>
</div>
</div>
{% endblock %}
{% block custom_foot_js %}
<script>
$(document).ready(function () {
})
.on("click", ".btn-test", function () {
var data = {};
var form = $("form").serializeArray();
$.each(form, function (i, field) {
data[field.name] = field.value;
});
<script>
var the_url = "{% url 'api-common:ldap-testing' %}";
function ajaxAPI(url, data, success, error, method){
$.ajax({
url: url,
data: data,
method: method,
contentType: 'application/json; charset=utf-8',
success: success,
error: error
})
}
function error(message) {
toastr.error(message)
function deleteStorage($this, the_url){
var name = $this.data('name');
function doDelete(){
console.log('delete storage');
var data = {"name": name};
var method = 'POST';
var success = function(){
$this.parent().parent().remove();
toastr.success("{% trans 'Delete succeed' %}");
};
var error = function(){
toastr.error("{% trans 'Delete failed' %}}");
};
ajaxAPI(the_url, JSON.stringify(data), success, error, method);
}
swal({
title: "{% trans 'Are you sure about deleting it?' %}",
text: " [" + name + "] ",
type: "warning",
showCancelButton: true,
cancelButtonText: "{% trans 'Cancel' %}",
confirmButtonColor: "#ed5565",
confirmButtonText: "{% trans 'Confirm' %}",
closeOnConfirm: true
}, function () {
doDelete()
});
}
function success(message) {
toastr.success(message.msg)
}
$(document).ready(function () {
APIUpdateAttr({
url: the_url,
body: JSON.stringify(data),
method: "POST",
flash_message: false,
success: success,
error: error
});
})
.on('click', '', function () {
})
.on('click', '.btn-del-replay', function(){
var $this = $(this);
var the_url = "{% url 'api-common:replay-storage-delete' %}";
deleteStorage($this, the_url);
})
.on('click', '.btn-del-command', function() {
var $this = $(this);
var the_url = "{% url 'api-common:command-storage-delete' %}";
deleteStorage($this, the_url)
});
})
</script>
</script>
{% endblock %}
......@@ -9,5 +9,9 @@ app_name = 'common'
urlpatterns = [
path('mail/testing/', api.MailTestingAPI.as_view(), name='mail-testing'),
path('ldap/testing/', api.LDAPTestingAPI.as_view(), name='ldap-testing'),
path('terminal/replay-storage/create/', api.ReplayStorageCreateAPI.as_view(), name='replay-storage-create'),
path('terminal/replay-storage/delete/', api.ReplayStorageDeleteAPI.as_view(), name='replay-storage-delete'),
path('terminal/command-storage/create/', api.CommandStorageCreateAPI.as_view(), name='command-storage-create'),
path('terminal/command-storage/delete/', api.CommandStorageDeleteAPI.as_view(), name='command-storage-delete'),
# path('django-settings/', api.DjangoSettingsAPI.as_view(), name='django-settings'),
]
......@@ -11,5 +11,7 @@ urlpatterns = [
url(r'^email/$', views.EmailSettingView.as_view(), name='email-setting'),
url(r'^ldap/$', views.LDAPSettingView.as_view(), name='ldap-setting'),
url(r'^terminal/$', views.TerminalSettingView.as_view(), name='terminal-setting'),
url(r'^terminal/replay-storage/create$', views.ReplayStorageCreateView.as_view(), name='replay-storage-create'),
url(r'^terminal/command-storage/create$', views.CommandStorageCreateView.as_view(), name='command-storage-create'),
url(r'^security/$', views.SecuritySettingView.as_view(), name='security-setting'),
]
......@@ -37,7 +37,8 @@ def reverse(view_name, urlconf=None, args=None, kwargs=None,
kwargs=kwargs, current_app=current_app)
if external:
url = settings.SITE_URL.strip('/') + url
from common.models import common_settings
url = common_settings.SITE_URL.strip('/') + url
return url
......@@ -387,6 +388,49 @@ def get_request_ip(request):
return login_ip
def get_command_storage_or_create_default_storage():
from common.models import common_settings, Setting
name = 'TERMINAL_COMMAND_STORAGE'
default = {'default': {'TYPE': 'server'}}
command_storage = common_settings.TERMINAL_COMMAND_STORAGE
if command_storage is None:
obj = Setting()
obj.name = name
obj.encrypted = True
obj.cleaned_value = default
obj.save()
if isinstance(command_storage, dict) and not command_storage:
obj = Setting.objects.get(name=name)
value = obj.cleaned_value
value.update(default)
obj.cleaned_value = value
obj.save()
command_storage = common_settings.TERMINAL_COMMAND_STORAGE
return command_storage
def get_replay_storage_or_create_default_storage():
from common.models import common_settings, Setting
name = 'TERMINAL_REPLAY_STORAGE'
default = {'default': {'TYPE': 'server'}}
replay_storage = common_settings.TERMINAL_REPLAY_STORAGE
if replay_storage is None:
obj = Setting()
obj.name = name
obj.encrypted = True
obj.cleaned_value = default
obj.save()
replay_storage = common_settings.TERMINAL_REPLAY_STORAGE
if isinstance(replay_storage, dict) and not replay_storage:
obj = Setting.objects.get(name=name)
value = obj.cleaned_value
value.update(default)
obj.cleaned_value = value
obj.save()
replay_storage = common_settings.TERMINAL_REPLAY_STORAGE
return replay_storage
class TeeObj:
origin_stdout = sys.stdout
......
......@@ -4,10 +4,12 @@ from django.contrib import messages
from django.utils.translation import ugettext as _
from django.conf import settings
from common.models import common_settings
from .forms import EmailSettingForm, LDAPSettingForm, BasicSettingForm, \
TerminalSettingForm, SecuritySettingForm
from common.permissions import SuperUserRequiredMixin
from .signals import ldap_auth_enable
from . import utils
class BasicSettingView(SuperUserRequiredMixin, TemplateView):
......@@ -95,14 +97,15 @@ class TerminalSettingView(SuperUserRequiredMixin, TemplateView):
template_name = "common/terminal_setting.html"
def get_context_data(self, **kwargs):
command_storage = settings.TERMINAL_COMMAND_STORAGE
replay_storage = settings.TERMINAL_REPLAY_STORAGE
command_storage = utils.get_command_storage_or_create_default_storage()
replay_storage = utils.get_replay_storage_or_create_default_storage()
context = {
'app': _('Settings'),
'action': _('Terminal setting'),
'form': self.form_class(),
'replay_storage': replay_storage,
'command_storage': command_storage,
'command_storage': command_storage
}
kwargs.update(context)
return super().get_context_data(**kwargs)
......@@ -120,6 +123,30 @@ class TerminalSettingView(SuperUserRequiredMixin, TemplateView):
return render(request, self.template_name, context)
class ReplayStorageCreateView(SuperUserRequiredMixin, TemplateView):
template_name = 'common/replay_storage_create.html'
def get_context_data(self, **kwargs):
context = {
'app': _('Settings'),
'action': _('Create replay storage')
}
kwargs.update(context)
return super().get_context_data(**kwargs)
class CommandStorageCreateView(SuperUserRequiredMixin, TemplateView):
template_name = 'common/command_storage_create.html'
def get_context_data(self, **kwargs):
context = {
'app': _('Settings'),
'action': _('Create command storage')
}
kwargs.update(context)
return super().get_context_data(**kwargs)
class SecuritySettingView(SuperUserRequiredMixin, TemplateView):
form_class = SecuritySettingForm
template_name = "common/security_setting.html"
......
......@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Jumpserver 0.3.3\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2018-10-16 16:03+0800\n"
"POT-Creation-Date: 2018-10-24 11:03+0800\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: ibuler <ibuler@qq.com>\n"
"Language-Team: Jumpserver team<ibuler@qq.com>\n"
......@@ -34,8 +34,8 @@ msgid "Test if the assets under the node are connectable: {}"
msgstr "测试节点下资产是否可连接: {}"
#: assets/forms/asset.py:27 assets/models/asset.py:83 assets/models/user.py:113
#: assets/templates/assets/asset_detail.html:183
#: assets/templates/assets/asset_detail.html:191
#: assets/templates/assets/asset_detail.html:187
#: assets/templates/assets/asset_detail.html:195
#: assets/templates/assets/system_user_asset.html:95 perms/models.py:32
msgid "Nodes"
msgstr "节点管理"
......@@ -43,7 +43,7 @@ msgstr "节点管理"
#: assets/forms/asset.py:30 assets/forms/asset.py:69 assets/forms/asset.py:112
#: assets/forms/asset.py:116 assets/models/asset.py:88
#: assets/models/cluster.py:19 assets/models/user.py:73
#: assets/templates/assets/asset_detail.html:73 templates/_nav.html:24
#: assets/templates/assets/asset_detail.html:77 templates/_nav.html:24
#: xpack/plugins/cloud/models.py:137
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:67
#: xpack/plugins/orgs/templates/orgs/org_list.html:18
......@@ -110,6 +110,7 @@ msgstr "选择资产"
#: assets/templates/assets/domain_gateway_list.html:58
#: assets/templates/assets/system_user_asset.html:52
#: assets/templates/assets/user_asset_list.html:163
#: common/templates/common/replay_storage_create.html:60
msgid "Port"
msgstr "端口"
......@@ -154,8 +155,10 @@ msgstr "不能包含特殊字符"
#: assets/templates/assets/label_list.html:14
#: assets/templates/assets/system_user_detail.html:58
#: assets/templates/assets/system_user_list.html:29 common/models.py:30
#: common/templates/common/terminal_setting.html:72
#: common/templates/common/terminal_setting.html:90 ops/models/adhoc.py:37
#: common/templates/common/command_storage_create.html:41
#: common/templates/common/replay_storage_create.html:44
#: common/templates/common/terminal_setting.html:80
#: common/templates/common/terminal_setting.html:102 ops/models/adhoc.py:37
#: ops/templates/ops/task_detail.html:59 ops/templates/ops/task_list.html:35
#: orgs/models.py:12 perms/models.py:28
#: perms/templates/perms/asset_permission_detail.html:62
......@@ -243,7 +246,9 @@ msgstr "自动推送系统用户到资产"
msgid ""
"1-100, High level will be using login asset as default, if user was granted "
"more than 2 system user"
msgstr "1-100, 1最低优先级,100最高优先级。授权多个用户时,高优先级的系统用户将会作为默认登录用户"
msgstr ""
"1-100, 1最低优先级,100最高优先级。授权多个用户时,高优先级的系统用户将会作为"
"默认登录用户"
#: assets/forms/user.py:155
msgid ""
......@@ -281,7 +286,7 @@ msgid "Hostname"
msgstr "主机名"
#: assets/models/asset.py:75 assets/models/domain.py:49
#: assets/models/user.py:117
#: assets/models/user.py:117 assets/templates/assets/asset_detail.html:73
#: assets/templates/assets/domain_gateway_list.html:59
#: assets/templates/assets/system_user_detail.html:70
#: assets/templates/assets/system_user_list.html:31
......@@ -290,14 +295,14 @@ msgstr "主机名"
msgid "Protocol"
msgstr "协议"
#: assets/models/asset.py:77 assets/templates/assets/asset_detail.html:97
#: assets/models/asset.py:77 assets/templates/assets/asset_detail.html:101
#: assets/templates/assets/user_asset_list.html:165
msgid "Platform"
msgstr "系统平台"
#: assets/models/asset.py:84 assets/models/cmd_filter.py:20
#: assets/models/domain.py:52 assets/models/label.py:21
#: assets/templates/assets/asset_detail.html:105
#: assets/templates/assets/asset_detail.html:109
#: assets/templates/assets/user_asset_list.html:169
msgid "Is active"
msgstr "激活"
......@@ -306,19 +311,19 @@ msgstr "激活"
msgid "Public IP"
msgstr "公网IP"
#: assets/models/asset.py:92 assets/templates/assets/asset_detail.html:113
#: assets/models/asset.py:92 assets/templates/assets/asset_detail.html:117
msgid "Asset number"
msgstr "资产编号"
#: assets/models/asset.py:96 assets/templates/assets/asset_detail.html:77
#: assets/models/asset.py:96 assets/templates/assets/asset_detail.html:81
msgid "Vendor"
msgstr "制造商"
#: assets/models/asset.py:98 assets/templates/assets/asset_detail.html:81
#: assets/models/asset.py:98 assets/templates/assets/asset_detail.html:85
msgid "Model"
msgstr "型号"
#: assets/models/asset.py:100 assets/templates/assets/asset_detail.html:109
#: assets/models/asset.py:100 assets/templates/assets/asset_detail.html:113
msgid "Serial number"
msgstr "序列号"
......@@ -338,7 +343,7 @@ msgstr "CPU核数"
msgid "CPU vcpus"
msgstr "CPU总数"
#: assets/models/asset.py:108 assets/templates/assets/asset_detail.html:89
#: assets/models/asset.py:108 assets/templates/assets/asset_detail.html:93
msgid "Memory"
msgstr "内存"
......@@ -350,7 +355,7 @@ msgstr "硬盘大小"
msgid "Disk info"
msgstr "硬盘信息"
#: assets/models/asset.py:115 assets/templates/assets/asset_detail.html:101
#: assets/models/asset.py:115 assets/templates/assets/asset_detail.html:105
#: assets/templates/assets/user_asset_list.html:166
msgid "OS"
msgstr "操作系统"
......@@ -368,7 +373,7 @@ msgid "Hostname raw"
msgstr "主机名原始"
#: assets/models/asset.py:125 assets/templates/assets/asset_create.html:34
#: assets/templates/assets/asset_detail.html:220
#: assets/templates/assets/asset_detail.html:224
#: assets/templates/assets/asset_update.html:39 templates/_nav.html:26
msgid "Labels"
msgstr "标签管理"
......@@ -377,7 +382,7 @@ msgstr "标签管理"
#: assets/models/cluster.py:28 assets/models/cmd_filter.py:24
#: assets/models/cmd_filter.py:54 assets/models/group.py:21
#: assets/templates/assets/admin_user_detail.html:68
#: assets/templates/assets/asset_detail.html:117
#: assets/templates/assets/asset_detail.html:121
#: assets/templates/assets/cmd_filter_detail.html:77
#: assets/templates/assets/domain_detail.html:72
#: assets/templates/assets/system_user_detail.html:100
......@@ -412,7 +417,7 @@ msgstr "创建日期"
#: assets/models/domain.py:51 assets/models/group.py:23
#: assets/models/label.py:22 assets/templates/assets/admin_user_detail.html:72
#: assets/templates/assets/admin_user_list.html:32
#: assets/templates/assets/asset_detail.html:125
#: assets/templates/assets/asset_detail.html:129
#: assets/templates/assets/cmd_filter_detail.html:65
#: assets/templates/assets/cmd_filter_list.html:27
#: assets/templates/assets/cmd_filter_rule_list.html:62
......@@ -533,8 +538,10 @@ msgstr "过滤器"
#: assets/models/cmd_filter.py:46
#: assets/templates/assets/cmd_filter_rule_list.html:58
#: audits/templates/audits/login_log_list.html:50
#: common/templates/common/terminal_setting.html:73
#: common/templates/common/terminal_setting.html:91
#: common/templates/common/command_storage_create.html:31
#: common/templates/common/replay_storage_create.html:31
#: common/templates/common/terminal_setting.html:81
#: common/templates/common/terminal_setting.html:103
msgid "Type"
msgstr "类型"
......@@ -568,6 +575,8 @@ msgstr "每行一个命令"
#: assets/templates/assets/system_user_list.html:38 audits/models.py:37
#: audits/templates/audits/operate_log_list.html:41
#: audits/templates/audits/operate_log_list.html:67
#: common/templates/common/terminal_setting.html:82
#: common/templates/common/terminal_setting.html:104
#: ops/templates/ops/adhoc_history.html:59 ops/templates/ops/task_adhoc.html:64
#: ops/templates/ops/task_history.html:65 ops/templates/ops/task_list.html:42
#: perms/templates/perms/asset_permission_list.html:60
......@@ -843,10 +852,12 @@ msgstr "其它"
#: assets/templates/assets/gateway_create_update.html:58
#: assets/templates/assets/label_create_update.html:18
#: common/templates/common/basic_setting.html:61
#: common/templates/common/command_storage_create.html:80
#: common/templates/common/email_setting.html:62
#: common/templates/common/ldap_setting.html:62
#: common/templates/common/replay_storage_create.html:139
#: common/templates/common/security_setting.html:70
#: common/templates/common/terminal_setting.html:106
#: common/templates/common/terminal_setting.html:68
#: perms/templates/perms/asset_permission_create_update.html:69
#: terminal/templates/terminal/terminal_update.html:47
#: users/templates/users/_user.html:46
......@@ -874,10 +885,12 @@ msgstr "重置"
#: assets/templates/assets/gateway_create_update.html:59
#: assets/templates/assets/label_create_update.html:19
#: common/templates/common/basic_setting.html:62
#: common/templates/common/command_storage_create.html:81
#: common/templates/common/email_setting.html:63
#: common/templates/common/ldap_setting.html:63
#: common/templates/common/replay_storage_create.html:140
#: common/templates/common/security_setting.html:71
#: common/templates/common/terminal_setting.html:108
#: common/templates/common/terminal_setting.html:70
#: perms/templates/perms/asset_permission_create_update.html:70
#: terminal/templates/terminal/command_list.html:103
#: terminal/templates/terminal/session_list.html:127
......@@ -945,12 +958,12 @@ msgid "Quick update"
msgstr "快速更新"
#: assets/templates/assets/admin_user_assets.html:72
#: assets/templates/assets/asset_detail.html:168
#: assets/templates/assets/asset_detail.html:172
msgid "Test connective"
msgstr "测试可连接性"
#: assets/templates/assets/admin_user_assets.html:75
#: assets/templates/assets/asset_detail.html:171
#: assets/templates/assets/asset_detail.html:175
#: assets/templates/assets/system_user_asset.html:75
#: assets/templates/assets/system_user_asset.html:161
#: assets/templates/assets/system_user_detail.html:151
......@@ -1003,6 +1016,8 @@ msgstr "更新"
#: assets/templates/assets/label_list.html:39
#: assets/templates/assets/system_user_detail.html:30
#: assets/templates/assets/system_user_list.html:93 audits/models.py:33
#: common/templates/common/terminal_setting.html:90
#: common/templates/common/terminal_setting.html:112
#: ops/templates/ops/task_list.html:72
#: perms/templates/perms/asset_permission_detail.html:34
#: perms/templates/perms/asset_permission_list.html:201
......@@ -1031,12 +1046,13 @@ msgid "Select nodes"
msgstr "选择节点"
#: assets/templates/assets/admin_user_detail.html:100
#: assets/templates/assets/asset_detail.html:200
#: assets/templates/assets/asset_detail.html:204
#: assets/templates/assets/asset_list.html:633
#: assets/templates/assets/cmd_filter_detail.html:106
#: assets/templates/assets/system_user_asset.html:112
#: assets/templates/assets/system_user_detail.html:182
#: assets/templates/assets/system_user_list.html:143 templates/_modal.html:22
#: assets/templates/assets/system_user_list.html:143
#: common/templates/common/terminal_setting.html:165 templates/_modal.html:22
#: terminal/templates/terminal/session_detail.html:108
#: users/templates/users/user_detail.html:382
#: users/templates/users/user_detail.html:408
......@@ -1096,28 +1112,28 @@ msgstr "选择需要修改属性"
msgid "Select all"
msgstr "全选"
#: assets/templates/assets/asset_detail.html:85
#: assets/templates/assets/asset_detail.html:89
msgid "CPU"
msgstr "CPU"
#: assets/templates/assets/asset_detail.html:93
#: assets/templates/assets/asset_detail.html:97
msgid "Disk"
msgstr "硬盘"
#: assets/templates/assets/asset_detail.html:121
#: assets/templates/assets/asset_detail.html:125
#: users/templates/users/user_detail.html:115
#: users/templates/users/user_profile.html:104
msgid "Date joined"
msgstr "创建日期"
#: assets/templates/assets/asset_detail.html:137
#: assets/templates/assets/asset_detail.html:141
#: terminal/templates/terminal/session_detail.html:81
#: users/templates/users/user_detail.html:134
#: users/templates/users/user_profile.html:142
msgid "Quick modify"
msgstr "快速修改"
#: assets/templates/assets/asset_detail.html:143
#: assets/templates/assets/asset_detail.html:147
#: assets/templates/assets/asset_list.html:95
#: assets/templates/assets/user_asset_list.html:47 perms/models.py:34
#: perms/models.py:82
......@@ -1134,15 +1150,15 @@ msgstr "快速修改"
msgid "Active"
msgstr "激活中"
#: assets/templates/assets/asset_detail.html:160
#: assets/templates/assets/asset_detail.html:164
msgid "Refresh hardware"
msgstr "更新硬件信息"
#: assets/templates/assets/asset_detail.html:163
#: assets/templates/assets/asset_detail.html:167
msgid "Refresh"
msgstr "刷新"
#: assets/templates/assets/asset_detail.html:300
#: assets/templates/assets/asset_detail.html:304
#: users/templates/users/user_detail.html:301
#: users/templates/users/user_detail.html:328
msgid "Update successfully!"
......@@ -1271,6 +1287,7 @@ msgstr "删除选择资产"
#: assets/templates/assets/asset_list.html:631
#: assets/templates/assets/system_user_list.html:141
#: common/templates/common/terminal_setting.html:163
#: users/templates/users/user_detail.html:380
#: users/templates/users/user_detail.html:406
#: users/templates/users/user_detail.html:474
......@@ -1737,7 +1754,7 @@ msgstr "改密日志"
#: audits/views.py:183 templates/_nav.html:10 users/views/group.py:28
#: users/views/group.py:44 users/views/group.py:60 users/views/group.py:76
#: users/views/group.py:92 users/views/login.py:327 users/views/user.py:68
#: users/views/group.py:92 users/views/login.py:328 users/views/user.py:68
#: users/views/user.py:83 users/views/user.py:111 users/views/user.py:193
#: users/views/user.py:354 users/views/user.py:404 users/views/user.py:439
msgid "Users"
......@@ -1747,22 +1764,35 @@ msgstr "用户管理"
msgid "Login log"
msgstr "登录日志"
#: common/api.py:18
#: common/api.py:22
msgid "Test mail sent to {}, please check"
msgstr "邮件已经发送{}, 请检查"
#: common/api.py:42
#: common/api.py:46
msgid "Test ldap success"
msgstr "连接LDAP成功"
#: common/api.py:72
#: common/api.py:76
msgid "Search no entry matched in ou {}"
msgstr "在ou:{}中没有匹配条目"
#: common/api.py:81
#: common/api.py:85
msgid "Match {} s users"
msgstr "匹配 {} 个用户"
#: common/api.py:107 common/api.py:138
msgid "Error: Account invalid"
msgstr ""
#: common/api.py:110 common/api.py:141
msgid "Create succeed"
msgstr "创建成功"
#: common/api.py:127 common/api.py:161
#: common/templates/common/terminal_setting.html:151
msgid "Delete succeed"
msgstr "删除成功"
#: common/const.py:6
#, python-format
msgid "<b>%(name)s</b> was created successfully"
......@@ -1879,120 +1909,98 @@ msgid "Enable LDAP auth"
msgstr "启用LDAP认证"
#: common/forms.py:139
msgid "List sort by"
msgstr "资产列表排序"
msgid "Password auth"
msgstr "密码认证"
#: common/forms.py:142
msgid "Public key auth"
msgstr "密钥认证"
#: common/forms.py:145
msgid "Heartbeat interval"
msgstr "心跳间隔"
#: common/forms.py:142 ops/models/adhoc.py:38
#: common/forms.py:145 ops/models/adhoc.py:38
msgid "Units: seconds"
msgstr "单位: 秒"
#: common/forms.py:145
msgid "Password auth"
msgstr "密码认证"
#: common/forms.py:148
msgid "Public key auth"
msgstr "密钥认证"
#: common/forms.py:151 common/templates/common/terminal_setting.html:68
#: terminal/forms.py:30 terminal/models.py:22
msgid "Command storage"
msgstr "命令存储"
#: common/forms.py:152
msgid ""
"Set terminal storage setting, `default` is the using as default,You can set "
"other storage and some terminal using"
msgstr "设置终端命令存储,default是默认用的存储方式"
#: common/forms.py:157 common/templates/common/terminal_setting.html:86
#: terminal/forms.py:35 terminal/models.py:23
msgid "Replay storage"
msgstr "录像存储"
#: common/forms.py:158
msgid ""
"Set replay storage setting, `default` is the using as default,You can set "
"other storage and some terminal using"
msgstr "设置终端录像存储,default是默认用的存储方式"
msgid "List sort by"
msgstr "资产列表排序"
#: common/forms.py:168
#: common/forms.py:160
msgid "MFA Secondary certification"
msgstr "MFA 二次认证"
#: common/forms.py:170
#: common/forms.py:162
msgid ""
"After opening, the user login must use MFA secondary authentication (valid "
"for all users, including administrators)"
msgstr "开启后,用户登录必须使用MFA二次认证(对所有用户有效,包括管理员)"
#: common/forms.py:177
#: common/forms.py:169
msgid "Limit the number of login failures"
msgstr "限制登录失败次数"
#: common/forms.py:182
#: common/forms.py:174
msgid "No logon interval"
msgstr "禁止登录时间间隔"
#: common/forms.py:184
#: common/forms.py:176
msgid ""
"Tip :(unit/minute) if the user has failed to log in for a limited number of "
"times, no login is allowed during this time interval."
msgstr ""
"提示: (单位: 分钟) 当用户登录失败次数达到限制后,那么在此时间间隔内禁止登录."
#: common/forms.py:190
#: common/forms.py:182
msgid "Connection max idle time"
msgstr "SSH最大空闲时间"
#: common/forms.py:192
#: common/forms.py:184
msgid ""
"If idle time more than it, disconnect connection(only ssh now) Unit: minute"
msgstr "提示: (单位: 分钟) 如果超过该配置没有操作,连接会被断开(仅ssh) "
#: common/forms.py:198
#: common/forms.py:190
msgid "Password minimum length"
msgstr "密码最小长度 "
#: common/forms.py:204
#: common/forms.py:196
msgid "Must contain capital letters"
msgstr "必须包含大写字母"
#: common/forms.py:206
#: common/forms.py:198
msgid ""
"After opening, the user password changes and resets must contain uppercase "
"letters"
msgstr "开启后,用户密码修改、重置必须包含大写字母"
#: common/forms.py:212
#: common/forms.py:204
msgid "Must contain lowercase letters"
msgstr "必须包含小写字母"
#: common/forms.py:213
#: common/forms.py:205
msgid ""
"After opening, the user password changes and resets must contain lowercase "
"letters"
msgstr "开启后,用户密码修改、重置必须包含小写字母"
#: common/forms.py:219
#: common/forms.py:211
msgid "Must contain numeric characters"
msgstr "必须包含数字字符"
#: common/forms.py:220
#: common/forms.py:212
msgid ""
"After opening, the user password changes and resets must contain numeric "
"characters"
msgstr "开启后,用户密码修改、重置必须包含数字字符"
#: common/forms.py:226
#: common/forms.py:218
msgid "Must contain special characters"
msgstr "必须包含特殊字符"
#: common/forms.py:227
#: common/forms.py:219
msgid ""
"After opening, the user password changes and resets must contain special "
"characters"
......@@ -2016,7 +2024,7 @@ msgstr "启用"
#: common/templates/common/ldap_setting.html:15
#: common/templates/common/security_setting.html:15
#: common/templates/common/terminal_setting.html:16
#: common/templates/common/terminal_setting.html:46 common/views.py:20
#: common/templates/common/terminal_setting.html:46 common/views.py:22
msgid "Basic setting"
msgstr "基本设置"
......@@ -2024,7 +2032,7 @@ msgstr "基本设置"
#: common/templates/common/email_setting.html:18
#: common/templates/common/ldap_setting.html:18
#: common/templates/common/security_setting.html:18
#: common/templates/common/terminal_setting.html:20 common/views.py:46
#: common/templates/common/terminal_setting.html:20 common/views.py:48
msgid "Email setting"
msgstr "邮件设置"
......@@ -2032,7 +2040,7 @@ msgstr "邮件设置"
#: common/templates/common/email_setting.html:21
#: common/templates/common/ldap_setting.html:21
#: common/templates/common/security_setting.html:21
#: common/templates/common/terminal_setting.html:24 common/views.py:72
#: common/templates/common/terminal_setting.html:24 common/views.py:74
msgid "LDAP setting"
msgstr "LDAP设置"
......@@ -2040,7 +2048,7 @@ msgstr "LDAP设置"
#: common/templates/common/email_setting.html:24
#: common/templates/common/ldap_setting.html:24
#: common/templates/common/security_setting.html:24
#: common/templates/common/terminal_setting.html:28 common/views.py:102
#: common/templates/common/terminal_setting.html:28 common/views.py:105
msgid "Terminal setting"
msgstr "终端设置"
......@@ -2048,10 +2056,72 @@ msgstr "终端设置"
#: common/templates/common/email_setting.html:27
#: common/templates/common/ldap_setting.html:27
#: common/templates/common/security_setting.html:27
#: common/templates/common/terminal_setting.html:31 common/views.py:130
#: common/templates/common/terminal_setting.html:31 common/views.py:157
msgid "Security setting"
msgstr "安全设置"
#: common/templates/common/command_storage_create.html:50
#: ops/models/adhoc.py:159 ops/templates/ops/adhoc_detail.html:53
#: ops/templates/ops/task_adhoc.html:59 ops/templates/ops/task_list.html:38
msgid "Hosts"
msgstr "主机"
#: common/templates/common/command_storage_create.html:53
msgid "Tips: If there are multiple hosts, separate them with a comma (,)"
msgstr "提示: 如果有多台主机,请使用逗号 ( , ) 进行分割"
#: common/templates/common/command_storage_create.html:64
msgid "Index"
msgstr "索引"
#: common/templates/common/command_storage_create.html:71
msgid "Doc type"
msgstr "文档类型"
#: common/templates/common/replay_storage_create.html:53
#: templates/index.html:91
msgid "Host"
msgstr "主机"
#: common/templates/common/replay_storage_create.html:67
msgid "Bucket"
msgstr "桶名称"
#: common/templates/common/replay_storage_create.html:74
msgid "Access key"
msgstr ""
#: common/templates/common/replay_storage_create.html:81
msgid "Secret key"
msgstr ""
#: common/templates/common/replay_storage_create.html:88
msgid "Container name"
msgstr "容器名称"
#: common/templates/common/replay_storage_create.html:95
msgid "Account name"
msgstr "账户名称"
#: common/templates/common/replay_storage_create.html:102
msgid "Account key"
msgstr "账户密钥"
#: common/templates/common/replay_storage_create.html:109
msgid "Endpoint"
msgstr "端点"
#: common/templates/common/replay_storage_create.html:116
msgid "Endpoint suffix"
msgstr "端点后缀"
#: common/templates/common/replay_storage_create.html:130
#: xpack/plugins/cloud/models.py:206
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:83
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_instance.html:64
msgid "Region"
msgstr "地域"
#: common/templates/common/security_setting.html:42
msgid "User login settings"
msgstr "用户登录设置"
......@@ -2060,20 +2130,59 @@ msgstr "用户登录设置"
msgid "Password check rule"
msgstr "密码校验规则"
#: common/templates/common/terminal_setting.html:76 terminal/forms.py:27
#: terminal/models.py:22
msgid "Command storage"
msgstr "命令存储"
#: common/templates/common/terminal_setting.html:95
#: common/templates/common/terminal_setting.html:117
#: perms/templates/perms/asset_permission_asset.html:97
#: perms/templates/perms/asset_permission_detail.html:157
#: perms/templates/perms/asset_permission_user.html:97
#: perms/templates/perms/asset_permission_user.html:125
#: users/templates/users/user_group_detail.html:95
#: xpack/plugins/orgs/templates/orgs/org_detail.html:93
#: xpack/plugins/orgs/templates/orgs/org_detail.html:130
msgid "Add"
msgstr "添加"
#: common/templates/common/terminal_setting.html:98 terminal/forms.py:32
#: terminal/models.py:23
msgid "Replay storage"
msgstr "录像存储"
#: common/templates/common/terminal_setting.html:154
msgid "Delete failed"
msgstr "删除失败"
#: common/templates/common/terminal_setting.html:159
msgid "Are you sure about deleting it?"
msgstr "您确定删除吗?"
#: common/validators.py:7
msgid "Special char not allowed"
msgstr "不能包含特殊字符"
#: common/views.py:19 common/views.py:45 common/views.py:71 common/views.py:101
#: common/views.py:129 templates/_nav.html:116
#: common/views.py:21 common/views.py:47 common/views.py:73 common/views.py:104
#: common/views.py:131 common/views.py:143 common/views.py:156
#: templates/_nav.html:116
msgid "Settings"
msgstr "系统设置"
#: common/views.py:30 common/views.py:56 common/views.py:84 common/views.py:114
#: common/views.py:140
#: common/views.py:32 common/views.py:58 common/views.py:86 common/views.py:117
#: common/views.py:167
msgid "Update setting successfully, please restart program"
msgstr "更新设置成功, 请手动重启程序"
#: common/views.py:132
msgid "Create replay storage"
msgstr "创建录像存储"
#: common/views.py:144
msgid "Create command storage"
msgstr "创建命令存储"
#: jumpserver/views.py:180
msgid ""
"<div>Luna is a separately deployed program, you need to deploy Luna, coco, "
......@@ -2117,11 +2226,6 @@ msgstr "模式"
msgid "Options"
msgstr "选项"
#: ops/models/adhoc.py:159 ops/templates/ops/adhoc_detail.html:53
#: ops/templates/ops/task_adhoc.html:59 ops/templates/ops/task_list.html:38
msgid "Hosts"
msgstr "主机"
#: ops/models/adhoc.py:160
msgid "Run as admin"
msgstr "再次执行"
......@@ -2380,16 +2484,6 @@ msgstr "资产或资产组"
msgid "Add asset to this permission"
msgstr "添加资产"
#: perms/templates/perms/asset_permission_asset.html:97
#: perms/templates/perms/asset_permission_detail.html:157
#: perms/templates/perms/asset_permission_user.html:97
#: perms/templates/perms/asset_permission_user.html:125
#: users/templates/users/user_group_detail.html:95
#: xpack/plugins/orgs/templates/orgs/org_detail.html:93
#: xpack/plugins/orgs/templates/orgs/org_detail.html:130
msgid "Add"
msgstr "添加"
#: perms/templates/perms/asset_permission_asset.html:108
msgid "Add node to this permission"
msgstr "添加节点"
......@@ -2665,10 +2759,6 @@ msgid ""
"assets per user host per month, respectively."
msgstr "以下图形分别描述一个月活跃用户和资产占所有用户主机的百分比"
#: templates/index.html:91
msgid "Host"
msgstr "主机"
#: templates/index.html:106 templates/index.html:121
msgid "Top 10 assets in a week"
msgstr "一周Top10资产"
......@@ -2787,12 +2877,12 @@ msgstr "输入"
msgid "Session"
msgstr "会话"
#: terminal/forms.py:31
#: terminal/forms.py:28
msgid "Command can store in server db or ES, default to server, more see docs"
msgstr ""
"命令支持存储到服务器端数据库、ES中,默认存储的服务器端数据库,更多查看文档"
#: terminal/forms.py:36
#: terminal/forms.py:33
msgid ""
"Replay file can store in server disk, AWS S3, Aliyun OSS, default to server, "
"more see docs"
......@@ -3925,56 +4015,56 @@ msgstr "更新用户组"
msgid "User group granted asset"
msgstr "用户组授权资产"
#: users/views/login.py:69
#: users/views/login.py:70
msgid "Please enable cookies and try again."
msgstr "设置你的浏览器支持cookie"
#: users/views/login.py:175 users/views/user.py:526 users/views/user.py:551
#: users/views/login.py:176 users/views/user.py:526 users/views/user.py:551
msgid "MFA code invalid, or ntp sync server time"
msgstr "MFA验证码不正确,或者服务器端时间不对"
#: users/views/login.py:204
#: users/views/login.py:205
msgid "Logout success"
msgstr "退出登录成功"
#: users/views/login.py:205
#: users/views/login.py:206
msgid "Logout success, return login page"
msgstr "退出登录成功,返回到登录页面"
#: users/views/login.py:221
#: users/views/login.py:222
msgid "Email address invalid, please input again"
msgstr "邮箱地址错误,重新输入"
#: users/views/login.py:234
#: users/views/login.py:235
msgid "Send reset password message"
msgstr "发送重置密码邮件"
#: users/views/login.py:235
#: users/views/login.py:236
msgid "Send reset password mail success, login your mail box and follow it "
msgstr ""
"发送重置邮件成功, 请登录邮箱查看, 按照提示操作 (如果没收到,请等待3-5分钟)"
#: users/views/login.py:248
#: users/views/login.py:249
msgid "Reset password success"
msgstr "重置密码成功"
#: users/views/login.py:249
#: users/views/login.py:250
msgid "Reset password success, return to login page"
msgstr "重置密码成功,返回到登录页面"
#: users/views/login.py:270 users/views/login.py:283
#: users/views/login.py:271 users/views/login.py:284
msgid "Token invalid or expired"
msgstr "Token错误或失效"
#: users/views/login.py:279
#: users/views/login.py:280
msgid "Password not same"
msgstr "密码不一致"
#: users/views/login.py:289 users/views/user.py:127 users/views/user.py:422
#: users/views/login.py:290 users/views/user.py:127 users/views/user.py:422
msgid "* Your password does not meet the requirements"
msgstr "* 您的密码不符合要求"
#: users/views/login.py:327
#: users/views/login.py:328
msgid "First login"
msgstr "首次登陆"
......@@ -4160,12 +4250,6 @@ msgstr "同步实例任务历史"
msgid "Instance"
msgstr "实例"
#: xpack/plugins/cloud/models.py:206
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:83
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_instance.html:64
msgid "Region"
msgstr "地域"
#: xpack/plugins/cloud/providers/base.py:73
msgid "任务执行开始: {}"
msgstr ""
......@@ -4339,6 +4423,21 @@ msgstr "创建组织"
msgid "Update org"
msgstr "更新组织"
#, fuzzy
#~| msgid "Delete succeed"
#~ msgid "Delete success"
#~ msgstr "删除成功"
#~ msgid ""
#~ "Set terminal storage setting, `default` is the using as default,You can "
#~ "set other storage and some terminal using"
#~ msgstr "设置终端命令存储,default是默认用的存储方式"
#~ msgid ""
#~ "Set replay storage setting, `default` is the using as default,You can set "
#~ "other storage and some terminal using"
#~ msgstr "设置终端录像存储,default是默认用的存储方式"
#~ msgid "Sync instance task detail"
#~ msgstr "同步实例任务详情"
......
......@@ -152,6 +152,9 @@ function activeNav() {
$('#' + 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');
......
......@@ -2,6 +2,9 @@ from importlib import import_module
from django.conf import settings
from .command.serializers import SessionCommandSerializer
from common import utils
from common.models import common_settings, Setting
TYPE_ENGINE_MAPPING = {
'elasticsearch': 'terminal.backends.command.es',
}
......@@ -16,7 +19,9 @@ def get_command_storage():
def get_terminal_command_storages():
storage_list = {}
for name, params in settings.TERMINAL_COMMAND_STORAGE.items():
command_storage = utils.get_command_storage_or_create_default_storage()
for name, params in command_storage.items():
tp = params['TYPE']
if tp == 'server':
storage = get_command_storage()
......
......@@ -2,36 +2,33 @@
#
from django import forms
from django.conf import settings
from django.utils.translation import ugettext_lazy as _
from .models import Terminal
def get_all_command_storage():
# storage_choices = []
from common.models import Setting
Setting.refresh_all_settings()
for k, v in settings.TERMINAL_COMMAND_STORAGE.items():
from common import utils
command_storage = utils.get_command_storage_or_create_default_storage()
for k, v in command_storage.items():
yield (k, k)
def get_all_replay_storage():
# storage_choices = []
from common.models import Setting
Setting.refresh_all_settings()
for k, v in settings.TERMINAL_REPLAY_STORAGE.items():
from common import utils
replay_storage = utils.get_replay_storage_or_create_default_storage()
for k, v in replay_storage.items():
yield (k, k)
class TerminalForm(forms.ModelForm):
command_storage = forms.ChoiceField(
choices=get_all_command_storage(),
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(),
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"),
)
......
......@@ -21,6 +21,7 @@ from formtools.wizard.views import SessionWizardView
from django.conf import settings
from common.utils import get_object_or_none, get_request_ip
from common.models import common_settings
from ..models import User, LoginLog
from ..utils import send_reset_password_mail, check_otp_code, \
redirect_user_first_login_or_index, get_user_or_tmp_user, \
......@@ -318,7 +319,7 @@ class UserFirstLoginView(LoginRequiredMixin, SessionWizardView):
user.is_public_key_valid = True
user.save()
context = {
'user_guide_url': settings.USER_GUIDE_URL
'user_guide_url': common_settings.USER_GUIDE_URL
}
return render(self.request, 'users/first_login_done.html', context)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment