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 -*- # -*- coding: utf-8 -*-
# #
import os
import json import json
import jms_storage
from rest_framework.views import Response, APIView from rest_framework.views import Response, APIView
from ldap3 import Server, Connection from ldap3 import Server, Connection
...@@ -8,8 +11,9 @@ from django.core.mail import get_connection, send_mail ...@@ -8,8 +11,9 @@ from django.core.mail import get_connection, send_mail
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from django.conf import settings from django.conf import settings
from .permissions import IsOrgAdmin from .permissions import IsOrgAdmin, IsSuperUser
from .serializers import MailTestSerializer, LDAPTestSerializer from .serializers import MailTestSerializer, LDAPTestSerializer
from .models import Setting
class MailTestingAPI(APIView): class MailTestingAPI(APIView):
...@@ -85,6 +89,79 @@ class LDAPTestingAPI(APIView): ...@@ -85,6 +89,79 @@ class LDAPTestingAPI(APIView):
return Response({"error": str(serializer.errors)}, status=401) 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): class DjangoSettingsAPI(APIView):
def get(self, request): def get(self, request):
if not settings.DEBUG: if not settings.DEBUG:
......
...@@ -135,32 +135,24 @@ class TerminalSettingForm(BaseForm): ...@@ -135,32 +135,24 @@ class TerminalSettingForm(BaseForm):
('hostname', _('Hostname')), ('hostname', _('Hostname')),
('ip', _('IP')), ('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( TERMINAL_PASSWORD_AUTH = forms.BooleanField(
initial=True, required=False, label=_("Password auth") initial=True, required=False, label=_("Password auth")
) )
TERMINAL_PUBLIC_KEY_AUTH = forms.BooleanField( TERMINAL_PUBLIC_KEY_AUTH = forms.BooleanField(
initial=True, required=False, label=_("Public key auth") initial=True, required=False, label=_("Public key auth")
) )
TERMINAL_COMMAND_STORAGE = FormEncryptDictField( TERMINAL_HEARTBEAT_INTERVAL = forms.IntegerField(
label=_("Command storage"), help_text=_( initial=5, label=_("Heartbeat interval"), help_text=_("Units: seconds")
"Set terminal storage setting, `default` is the using as default,"
"You can set other storage and some terminal using"
)
) )
TERMINAL_REPLAY_STORAGE = FormEncryptDictField( TERMINAL_ASSET_LIST_SORT_BY = forms.ChoiceField(
label=_("Replay storage"), help_text=_( choices=SORT_BY_CHOICES, initial='hostname', label=_("List sort by")
"Set replay storage setting, `default` is the using as default,"
"You can set other storage and some terminal using"
)
) )
class TerminalCommandStorage(BaseForm):
pass
class SecuritySettingForm(BaseForm): class SecuritySettingForm(BaseForm):
# MFA global setting # MFA global setting
SECURITY_MFA_AUTH = forms.BooleanField( SECURITY_MFA_AUTH = forms.BooleanField(
......
...@@ -67,6 +67,30 @@ class Setting(models.Model): ...@@ -67,6 +67,30 @@ class Setting(models.Model):
except json.JSONDecodeError as e: except json.JSONDecodeError as e:
raise ValueError("Json dump error: {}".format(str(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 @classmethod
def refresh_all_settings(cls): def refresh_all_settings(cls):
try: try:
......
...@@ -3,6 +3,7 @@ from django.conf import settings ...@@ -3,6 +3,7 @@ from django.conf import settings
from celery import shared_task from celery import shared_task
from .utils import get_logger from .utils import get_logger
from .models import Setting from .models import Setting
from common.models import common_settings
logger = get_logger(__file__) logger = get_logger(__file__)
...@@ -28,7 +29,7 @@ def send_mail_async(*args, **kwargs): ...@@ -28,7 +29,7 @@ def send_mail_async(*args, **kwargs):
if len(args) == 3: if len(args) == 3:
args = list(args) 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.insert(2, settings.EMAIL_HOST_USER)
args = tuple(args) args = tuple(args)
......
...@@ -75,32 +75,6 @@ ...@@ -75,32 +75,6 @@
{% block custom_foot_js %} {% block custom_foot_js %}
<script> <script>
$(document).ready(function () { $(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> </script>
{% endblock %} {% 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 %}
This diff is collapsed.
...@@ -63,6 +63,14 @@ ...@@ -63,6 +63,14 @@
{% endif %} {% endif %}
{% endfor %} {% 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> <div class="hr-line-dashed"></div>
<h3>{% trans "Command storage" %}</h3> <h3>{% trans "Command storage" %}</h3>
...@@ -71,6 +79,7 @@ ...@@ -71,6 +79,7 @@
<tr> <tr>
<th>{% trans 'Name' %}</th> <th>{% trans 'Name' %}</th>
<th>{% trans 'Type' %}</th> <th>{% trans 'Type' %}</th>
<th>{% trans 'Action' %}</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
...@@ -78,10 +87,13 @@ ...@@ -78,10 +87,13 @@
<tr> <tr>
<td>{{ name }}</td> <td>{{ name }}</td>
<td>{{ setting.TYPE }}</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> </tr>
{% endfor %} {% endfor %}
</tbody> </tbody>
</table> </table>
<a href="{% url 'common:command-storage-create' %}" class="btn btn-primary">{% trans 'Add' %}</a>
<div class="hr-line-dashed"></div> <div class="hr-line-dashed"></div>
<h3>{% trans "Replay storage" %}</h3> <h3>{% trans "Replay storage" %}</h3>
<table class="table table-hover " id="task-history-list-table"> <table class="table table-hover " id="task-history-list-table">
...@@ -89,6 +101,7 @@ ...@@ -89,6 +101,7 @@
<tr> <tr>
<th>{% trans 'Name' %}</th> <th>{% trans 'Name' %}</th>
<th>{% trans 'Type' %}</th> <th>{% trans 'Type' %}</th>
<th>{% trans 'Action' %}</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
...@@ -96,18 +109,14 @@ ...@@ -96,18 +109,14 @@
<tr> <tr>
<td>{{ name }}</td> <td>{{ name }}</td>
<td>{{ setting.TYPE }}</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> </tr>
{% endfor %} {% endfor %}
</tbody> </tbody>
</table> </table>
<a href="{% url 'common:replay-storage-create' %}" class="btn btn-primary">{% trans 'Add' %}</a>
<div class="hr-line-dashed"></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>
<button id="submit_button" class="btn btn-primary"
type="submit">{% trans 'Submit' %}</button>
</div>
</div>
</form> </form>
</div> </div>
</div> </div>
...@@ -116,40 +125,63 @@ ...@@ -116,40 +125,63 @@
</div> </div>
</div> </div>
</div> </div>
</div>
{% endblock %} {% endblock %}
{% block custom_foot_js %} {% block custom_foot_js %}
<script> <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: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) { function deleteStorage($this, the_url){
toastr.error(message) 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) { $(document).ready(function () {
toastr.success(message.msg)
}
APIUpdateAttr({ })
url: the_url, .on('click', '.btn-del-replay', function(){
body: JSON.stringify(data), var $this = $(this);
method: "POST", var the_url = "{% url 'api-common:replay-storage-delete' %}";
flash_message: false, deleteStorage($this, the_url);
success: success, })
error: error .on('click', '.btn-del-command', function() {
}); var $this = $(this);
}) var the_url = "{% url 'api-common:command-storage-delete' %}";
.on('click', '', function () { deleteStorage($this, the_url)
});
}) </script>
</script>
{% endblock %} {% endblock %}
...@@ -9,5 +9,9 @@ app_name = 'common' ...@@ -9,5 +9,9 @@ app_name = 'common'
urlpatterns = [ urlpatterns = [
path('mail/testing/', api.MailTestingAPI.as_view(), name='mail-testing'), path('mail/testing/', api.MailTestingAPI.as_view(), name='mail-testing'),
path('ldap/testing/', api.LDAPTestingAPI.as_view(), name='ldap-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'), # path('django-settings/', api.DjangoSettingsAPI.as_view(), name='django-settings'),
] ]
...@@ -11,5 +11,7 @@ urlpatterns = [ ...@@ -11,5 +11,7 @@ urlpatterns = [
url(r'^email/$', views.EmailSettingView.as_view(), name='email-setting'), url(r'^email/$', views.EmailSettingView.as_view(), name='email-setting'),
url(r'^ldap/$', views.LDAPSettingView.as_view(), name='ldap-setting'), url(r'^ldap/$', views.LDAPSettingView.as_view(), name='ldap-setting'),
url(r'^terminal/$', views.TerminalSettingView.as_view(), name='terminal-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'), url(r'^security/$', views.SecuritySettingView.as_view(), name='security-setting'),
] ]
...@@ -37,7 +37,8 @@ def reverse(view_name, urlconf=None, args=None, kwargs=None, ...@@ -37,7 +37,8 @@ def reverse(view_name, urlconf=None, args=None, kwargs=None,
kwargs=kwargs, current_app=current_app) kwargs=kwargs, current_app=current_app)
if external: if external:
url = settings.SITE_URL.strip('/') + url from common.models import common_settings
url = common_settings.SITE_URL.strip('/') + url
return url return url
...@@ -387,6 +388,49 @@ def get_request_ip(request): ...@@ -387,6 +388,49 @@ def get_request_ip(request):
return login_ip 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: class TeeObj:
origin_stdout = sys.stdout origin_stdout = sys.stdout
......
...@@ -4,10 +4,12 @@ from django.contrib import messages ...@@ -4,10 +4,12 @@ from django.contrib import messages
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
from django.conf import settings from django.conf import settings
from common.models import common_settings
from .forms import EmailSettingForm, LDAPSettingForm, BasicSettingForm, \ from .forms import EmailSettingForm, LDAPSettingForm, BasicSettingForm, \
TerminalSettingForm, SecuritySettingForm TerminalSettingForm, SecuritySettingForm
from common.permissions import SuperUserRequiredMixin from common.permissions import SuperUserRequiredMixin
from .signals import ldap_auth_enable from .signals import ldap_auth_enable
from . import utils
class BasicSettingView(SuperUserRequiredMixin, TemplateView): class BasicSettingView(SuperUserRequiredMixin, TemplateView):
...@@ -95,14 +97,15 @@ class TerminalSettingView(SuperUserRequiredMixin, TemplateView): ...@@ -95,14 +97,15 @@ class TerminalSettingView(SuperUserRequiredMixin, TemplateView):
template_name = "common/terminal_setting.html" template_name = "common/terminal_setting.html"
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
command_storage = settings.TERMINAL_COMMAND_STORAGE command_storage = utils.get_command_storage_or_create_default_storage()
replay_storage = settings.TERMINAL_REPLAY_STORAGE replay_storage = utils.get_replay_storage_or_create_default_storage()
context = { context = {
'app': _('Settings'), 'app': _('Settings'),
'action': _('Terminal setting'), 'action': _('Terminal setting'),
'form': self.form_class(), 'form': self.form_class(),
'replay_storage': replay_storage, 'replay_storage': replay_storage,
'command_storage': command_storage, 'command_storage': command_storage
} }
kwargs.update(context) kwargs.update(context)
return super().get_context_data(**kwargs) return super().get_context_data(**kwargs)
...@@ -120,6 +123,30 @@ class TerminalSettingView(SuperUserRequiredMixin, TemplateView): ...@@ -120,6 +123,30 @@ class TerminalSettingView(SuperUserRequiredMixin, TemplateView):
return render(request, self.template_name, context) 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): class SecuritySettingView(SuperUserRequiredMixin, TemplateView):
form_class = SecuritySettingForm form_class = SecuritySettingForm
template_name = "common/security_setting.html" template_name = "common/security_setting.html"
......
This diff is collapsed.
...@@ -152,6 +152,9 @@ function activeNav() { ...@@ -152,6 +152,9 @@ function activeNav() {
$('#' + app + ' #' + resource).addClass('active'); $('#' + app + ' #' + resource).addClass('active');
$('#' + app + ' #' + resource + ' #' + item + ' a').css('color', '#ffffff'); $('#' + app + ' #' + resource + ' #' + item + ' a').css('color', '#ffffff');
} }
else if (app === 'settings'){
$("#" + app).addClass('active');
}
else { else {
$("#" + app).addClass('active'); $("#" + app).addClass('active');
$('#' + app + ' #' + resource).addClass('active'); $('#' + app + ' #' + resource).addClass('active');
......
...@@ -31,8 +31,8 @@ ...@@ -31,8 +31,8 @@
<div class="ibox-content"> <div class="ibox-content">
{% if form.errors.all %} {% if form.errors.all %}
<div class="alert alert-danger" style="margin: 20px auto 0px"> <div class="alert alert-danger" style="margin: 20px auto 0px">
{{ form.errors.all }} {{ form.errors.all }}
</div> </div>
{% endif %} {% endif %}
{% block form %} {% block form %}
{% endblock %} {% endblock %}
......
...@@ -2,6 +2,9 @@ from importlib import import_module ...@@ -2,6 +2,9 @@ from importlib import import_module
from django.conf import settings from django.conf import settings
from .command.serializers import SessionCommandSerializer from .command.serializers import SessionCommandSerializer
from common import utils
from common.models import common_settings, Setting
TYPE_ENGINE_MAPPING = { TYPE_ENGINE_MAPPING = {
'elasticsearch': 'terminal.backends.command.es', 'elasticsearch': 'terminal.backends.command.es',
} }
...@@ -16,7 +19,9 @@ def get_command_storage(): ...@@ -16,7 +19,9 @@ def get_command_storage():
def get_terminal_command_storages(): def get_terminal_command_storages():
storage_list = {} 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'] tp = params['TYPE']
if tp == 'server': if tp == 'server':
storage = get_command_storage() storage = get_command_storage()
......
...@@ -2,36 +2,33 @@ ...@@ -2,36 +2,33 @@
# #
from django import forms from django import forms
from django.conf import settings
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from .models import Terminal from .models import Terminal
def get_all_command_storage(): def get_all_command_storage():
# storage_choices = [] from common import utils
from common.models import Setting command_storage = utils.get_command_storage_or_create_default_storage()
Setting.refresh_all_settings() for k, v in command_storage.items():
for k, v in settings.TERMINAL_COMMAND_STORAGE.items():
yield (k, k) yield (k, k)
def get_all_replay_storage(): def get_all_replay_storage():
# storage_choices = [] from common import utils
from common.models import Setting replay_storage = utils.get_replay_storage_or_create_default_storage()
Setting.refresh_all_settings() for k, v in replay_storage.items():
for k, v in settings.TERMINAL_REPLAY_STORAGE.items():
yield (k, k) yield (k, k)
class TerminalForm(forms.ModelForm): class TerminalForm(forms.ModelForm):
command_storage = forms.ChoiceField( command_storage = forms.ChoiceField(
choices=get_all_command_storage(), choices=get_all_command_storage,
label=_("Command storage"), label=_("Command storage"),
help_text=_("Command can store in server db or ES, default to server, more see docs"), help_text=_("Command can store in server db or ES, default to server, more see docs"),
) )
replay_storage = forms.ChoiceField( replay_storage = forms.ChoiceField(
choices=get_all_replay_storage(), choices=get_all_replay_storage,
label=_("Replay storage"), label=_("Replay storage"),
help_text=_("Replay file can store in server disk, AWS S3, Aliyun OSS, default to server, more see docs"), 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 ...@@ -21,6 +21,7 @@ from formtools.wizard.views import SessionWizardView
from django.conf import settings from django.conf import settings
from common.utils import get_object_or_none, get_request_ip from common.utils import get_object_or_none, get_request_ip
from common.models import common_settings
from ..models import User, LoginLog from ..models import User, LoginLog
from ..utils import send_reset_password_mail, check_otp_code, \ from ..utils import send_reset_password_mail, check_otp_code, \
redirect_user_first_login_or_index, get_user_or_tmp_user, \ redirect_user_first_login_or_index, get_user_or_tmp_user, \
...@@ -318,7 +319,7 @@ class UserFirstLoginView(LoginRequiredMixin, SessionWizardView): ...@@ -318,7 +319,7 @@ class UserFirstLoginView(LoginRequiredMixin, SessionWizardView):
user.is_public_key_valid = True user.is_public_key_valid = True
user.save() user.save()
context = { 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) 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